1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-22 22:13:35 +02:00
vcmi/lib/networkPacks/PacksForClientBattle.h
Ivan Savenko 0c07384293 Refactoring of serialization versioning handling
- Removed 'version' field from serialize() method
- Handler classes - Binary(De)Serializer now have 'version' field
- Serialization versioning now uses named enum

Save compatibility with 1.4.X saves should be intact
2024-01-20 20:34:51 +02:00

558 lines
12 KiB
C++

/*
* PacksForClientBattle.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
#include "NetPacksBase.h"
#include "BattleChanges.h"
#include "../MetaString.h"
#include "../battle/BattleAction.h"
class CClient;
VCMI_LIB_NAMESPACE_BEGIN
class CGHeroInstance;
class CArmedInstance;
class IBattleState;
class BattleInfo;
struct DLL_LINKAGE BattleStart : public CPackForClient
{
void applyGs(CGameState * gs) const;
BattleID battleID = BattleID::NONE;
BattleInfo * info = nullptr;
void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler & h)
{
h & battleID;
h & info;
assert(battleID != BattleID::NONE);
}
};
struct DLL_LINKAGE BattleNextRound : public CPackForClient
{
void applyGs(CGameState * gs) const;
BattleID battleID = BattleID::NONE;
void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler & h)
{
h & battleID;
assert(battleID != BattleID::NONE);
}
};
struct DLL_LINKAGE BattleSetActiveStack : public CPackForClient
{
void applyGs(CGameState * gs) const;
BattleID battleID = BattleID::NONE;
ui32 stack = 0;
ui8 askPlayerInterface = true;
void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler & h)
{
h & battleID;
h & stack;
h & askPlayerInterface;
assert(battleID != BattleID::NONE);
}
};
struct DLL_LINKAGE BattleCancelled: public CPackForClient
{
void applyGs(CGameState * gs) const;
BattleID battleID = BattleID::NONE;
template <typename Handler> void serialize(Handler & h)
{
h & battleID;
assert(battleID != BattleID::NONE);
}
};
struct DLL_LINKAGE BattleResultAccepted : public CPackForClient
{
void applyGs(CGameState * gs) const;
struct HeroBattleResults
{
HeroBattleResults()
: hero(nullptr), army(nullptr), exp(0) {}
CGHeroInstance * hero;
CArmedInstance * army;
TExpType exp;
template <typename Handler> void serialize(Handler & h)
{
h & hero;
h & army;
h & exp;
}
};
BattleID battleID = BattleID::NONE;
std::array<HeroBattleResults, 2> heroResult;
ui8 winnerSide;
template <typename Handler> void serialize(Handler & h)
{
h & battleID;
h & heroResult;
h & winnerSide;
assert(battleID != BattleID::NONE);
}
};
struct DLL_LINKAGE BattleResult : public Query
{
void applyFirstCl(CClient * cl);
BattleID battleID = BattleID::NONE;
EBattleResult result = EBattleResult::NORMAL;
ui8 winner = 2; //0 - attacker, 1 - defender, [2 - draw (should be possible?)]
std::map<CreatureID, si32> casualties[2]; //first => casualties of attackers - map crid => number
TExpType exp[2] = {0, 0}; //exp for attacker and defender
std::set<ArtifactInstanceID> artifacts; //artifacts taken from loser to winner - currently unused
void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler & h)
{
h & battleID;
h & queryID;
h & result;
h & winner;
h & casualties[0];
h & casualties[1];
h & exp;
h & artifacts;
assert(battleID != BattleID::NONE);
}
};
struct DLL_LINKAGE BattleLogMessage : public CPackForClient
{
BattleID battleID = BattleID::NONE;
std::vector<MetaString> lines;
void applyGs(CGameState * gs);
void applyBattle(IBattleState * battleState);
void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler & h)
{
h & battleID;
h & lines;
assert(battleID != BattleID::NONE);
}
};
struct DLL_LINKAGE BattleStackMoved : public CPackForClient
{
BattleID battleID = BattleID::NONE;
ui32 stack = 0;
std::vector<BattleHex> tilesToMove;
int distance = 0;
bool teleporting = false;
void applyGs(CGameState * gs);
void applyBattle(IBattleState * battleState);
void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler & h)
{
h & battleID;
h & stack;
h & tilesToMove;
h & distance;
h & teleporting;
assert(battleID != BattleID::NONE);
}
};
struct DLL_LINKAGE BattleUnitsChanged : public CPackForClient
{
void applyGs(CGameState * gs);
void applyBattle(IBattleState * battleState);
BattleID battleID = BattleID::NONE;
std::vector<UnitChanges> changedStacks;
void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler & h)
{
h & battleID;
h & changedStacks;
assert(battleID != BattleID::NONE);
}
};
struct BattleStackAttacked
{
DLL_LINKAGE void applyGs(CGameState * gs);
DLL_LINKAGE void applyBattle(IBattleState * battleState);
BattleID battleID = BattleID::NONE;
ui32 stackAttacked = 0, attackerID = 0;
ui32 killedAmount = 0;
int64_t damageAmount = 0;
UnitChanges newState;
enum EFlags { KILLED = 1, SECONDARY = 2, REBIRTH = 4, CLONE_KILLED = 8, SPELL_EFFECT = 16, FIRE_SHIELD = 32, };
ui32 flags = 0; //uses EFlags (above)
SpellID spellID = SpellID::NONE; //only if flag SPELL_EFFECT is set
bool killed() const//if target stack was killed
{
return flags & KILLED || flags & CLONE_KILLED;
}
bool cloneKilled() const
{
return flags & CLONE_KILLED;
}
bool isSecondary() const//if stack was not a primary target (receives no spell effects)
{
return flags & SECONDARY;
}
///Attacked with spell (SPELL_LIKE_ATTACK)
bool isSpell() const
{
return flags & SPELL_EFFECT;
}
bool willRebirth() const//resurrection, e.g. Phoenix
{
return flags & REBIRTH;
}
bool fireShield() const
{
return flags & FIRE_SHIELD;
}
template <typename Handler> void serialize(Handler & h)
{
h & battleID;
h & stackAttacked;
h & attackerID;
h & newState;
h & flags;
h & killedAmount;
h & damageAmount;
h & spellID;
assert(battleID != BattleID::NONE);
}
bool operator<(const BattleStackAttacked & b) const
{
return stackAttacked < b.stackAttacked;
}
};
struct DLL_LINKAGE BattleAttack : public CPackForClient
{
void applyGs(CGameState * gs);
BattleUnitsChanged attackerChanges;
BattleID battleID = BattleID::NONE;
std::vector<BattleStackAttacked> bsa;
ui32 stackAttacking = 0;
ui32 flags = 0; //uses Eflags (below)
enum EFlags { SHOT = 1, COUNTER = 2, LUCKY = 4, UNLUCKY = 8, BALLISTA_DOUBLE_DMG = 16, DEATH_BLOW = 32, SPELL_LIKE = 64, LIFE_DRAIN = 128 };
BattleHex tile;
SpellID spellID = SpellID::NONE; //for SPELL_LIKE
bool shot() const//distance attack - decrease number of shots
{
return flags & SHOT;
}
bool counter() const//is it counterattack?
{
return flags & COUNTER;
}
bool lucky() const
{
return flags & LUCKY;
}
bool unlucky() const
{
return flags & UNLUCKY;
}
bool ballistaDoubleDmg() const //if it's ballista attack and does double dmg
{
return flags & BALLISTA_DOUBLE_DMG;
}
bool deathBlow() const
{
return flags & DEATH_BLOW;
}
bool spellLike() const
{
return flags & SPELL_LIKE;
}
bool lifeDrain() const
{
return flags & LIFE_DRAIN;
}
void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler & h)
{
h & battleID;
h & bsa;
h & stackAttacking;
h & flags;
h & tile;
h & spellID;
h & attackerChanges;
assert(battleID != BattleID::NONE);
}
};
struct DLL_LINKAGE StartAction : public CPackForClient
{
StartAction() = default;
explicit StartAction(BattleAction act)
: ba(std::move(act))
{
}
void applyFirstCl(CClient * cl);
void applyGs(CGameState * gs);
BattleID battleID = BattleID::NONE;
BattleAction ba;
void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler & h)
{
h & battleID;
h & ba;
assert(battleID != BattleID::NONE);
}
};
struct DLL_LINKAGE EndAction : public CPackForClient
{
void visitTyped(ICPackVisitor & visitor) override;
BattleID battleID = BattleID::NONE;
template <typename Handler> void serialize(Handler & h)
{
h & battleID;
}
};
struct DLL_LINKAGE BattleSpellCast : public CPackForClient
{
void applyGs(CGameState * gs) const;
BattleID battleID = BattleID::NONE;
bool activeCast = true;
ui8 side = 0; //which hero did cast spell: 0 - attacker, 1 - defender
SpellID spellID; //id of spell
ui8 manaGained = 0; //mana channeling ability
BattleHex tile; //destination tile (may not be set in some global/mass spells
std::set<ui32> affectedCres; //ids of creatures affected by this spell, generally used if spell does not set any effect (like dispel or cure)
std::set<ui32> resistedCres; // creatures that resisted the spell (e.g. Dwarves)
std::set<ui32> reflectedCres; // creatures that reflected the spell (e.g. Magic Mirror spell)
si32 casterStack = -1; // -1 if not cated by creature, >=0 caster stack ID
bool castByHero = true; //if true - spell has been cast by hero, otherwise by a creature
void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler & h)
{
h & battleID;
h & side;
h & spellID;
h & manaGained;
h & tile;
h & affectedCres;
h & resistedCres;
h & reflectedCres;
h & casterStack;
h & castByHero;
h & activeCast;
assert(battleID != BattleID::NONE);
}
};
struct DLL_LINKAGE StacksInjured : public CPackForClient
{
void applyGs(CGameState * gs);
void applyBattle(IBattleState * battleState);
BattleID battleID = BattleID::NONE;
std::vector<BattleStackAttacked> stacks;
void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler & h)
{
h & battleID;
h & stacks;
assert(battleID != BattleID::NONE);
}
};
struct DLL_LINKAGE BattleResultsApplied : public CPackForClient
{
BattleID battleID = BattleID::NONE;
PlayerColor player1, player2;
void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler & h)
{
h & battleID;
h & player1;
h & player2;
assert(battleID != BattleID::NONE);
}
};
struct DLL_LINKAGE BattleObstaclesChanged : public CPackForClient
{
void applyGs(CGameState * gs);
void applyBattle(IBattleState * battleState);
BattleID battleID = BattleID::NONE;
std::vector<ObstacleChanges> changes;
void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler & h)
{
h & battleID;
h & changes;
assert(battleID != BattleID::NONE);
}
};
struct DLL_LINKAGE CatapultAttack : public CPackForClient
{
struct AttackInfo
{
si16 destinationTile;
EWallPart attackedPart;
ui8 damageDealt;
template <typename Handler> void serialize(Handler & h)
{
h & destinationTile;
h & attackedPart;
h & damageDealt;
}
};
CatapultAttack();
~CatapultAttack() override;
void applyGs(CGameState * gs);
void applyBattle(IBattleState * battleState);
BattleID battleID = BattleID::NONE;
std::vector< AttackInfo > attackedParts;
int attacker = -1; //if -1, then a spell caused this
void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler & h)
{
h & battleID;
h & attackedParts;
h & attacker;
assert(battleID != BattleID::NONE);
}
};
struct DLL_LINKAGE BattleSetStackProperty : public CPackForClient
{
enum BattleStackProperty { CASTS, ENCHANTER_COUNTER, UNBIND, CLONED, HAS_CLONE };
void applyGs(CGameState * gs) const;
BattleID battleID = BattleID::NONE;
int stackID = 0;
BattleStackProperty which = CASTS;
int val = 0;
int absolute = 0;
template <typename Handler> void serialize(Handler & h)
{
h & battleID;
h & stackID;
h & which;
h & val;
h & absolute;
assert(battleID != BattleID::NONE);
}
protected:
void visitTyped(ICPackVisitor & visitor) override;
};
///activated at the beginning of turn
struct DLL_LINKAGE BattleTriggerEffect : public CPackForClient
{
void applyGs(CGameState * gs) const; //effect
BattleID battleID = BattleID::NONE;
int stackID = 0;
int effect = 0; //use corresponding Bonus type
int val = 0;
int additionalInfo = 0;
template <typename Handler> void serialize(Handler & h)
{
h & battleID;
h & stackID;
h & effect;
h & val;
h & additionalInfo;
assert(battleID != BattleID::NONE);
}
protected:
void visitTyped(ICPackVisitor & visitor) override;
};
struct DLL_LINKAGE BattleUpdateGateState : public CPackForClient
{
void applyGs(CGameState * gs) const;
BattleID battleID = BattleID::NONE;
EGateState state = EGateState::NONE;
template <typename Handler> void serialize(Handler & h)
{
h & battleID;
h & state;
assert(battleID != BattleID::NONE);
}
protected:
void visitTyped(ICPackVisitor & visitor) override;
};
VCMI_LIB_NAMESPACE_END