/* * @Author: 白哉 * @Description: 技能类 * @Date: 2025年04月22日 星期二 17:04:44 * @Modify: */ using System; using MemoryPack; using RuntimeData; using UnityEngine; namespace Logic.Skill { public enum SkillDamageEvent { ActiveAttackBeforeStarted, ActiveAttackFinished, } public interface ISkill { public SkillType GetSkillType(); // 事件触发生命周期 (事件已发生) public void OnMove(UnitData self, GridData grid, MapData mapData, MoveType moveType); // 伤害结算前 public void BeforeDamaged(MapData mapData, SettlementInfo info); // 对他人伤害结算前 public void BeforeDamageOther(MapData mapData, SettlementInfo info); // 伤害结算时 public void OnDamaged(MapData mapData, SettlementInfo info); // 对他人伤害结算时 public void OnDamageOther(MapData mapData, SettlementInfo info); // 主动攻击之前 public void BeforeActiveAttackOther(MapData mapData, UnitData origin, UnitData target,out int addDmg); // 主动攻击之后 public void AfterActiveAttackOther(MapData mapData, UnitData origin, UnitData target); public void AfterActiveAttacked(MapData mapData, UnitData origin, UnitData target); // 事件触发生命周期 (时刻) public void OnTurnStart(UnitData self, MapData mapData); public void OnTurnStart(CityData city, MapData mapData); public void OnTurnStart(PlayerData self, MapData mapData); public void OnTurnStart(GridData self, MapData mapData); public void OnTurnEnd(UnitData self, MapData mapData); public void OnTurnEnd(CityData city, MapData mapData); public void OnTurnEnd(PlayerData self, MapData mapData); public void OnTurnEnd(GridData self, MapData mapData); public void OnFinished(IdentifierBase self, MapData mapData); // 属性变化 // 是否能攻击所有人 public bool CanAttackAll(UnitData self, MapData mapData); // 是否限制自身移动 public bool IsLimitSelfMove(UnitData self, MapData mapData); // 是否限制自身攻击 public bool IsLimitSelfAttack(UnitData self, MapData mapData); // 是否限制敌方反击 public bool IsLimitTargetCounterAttack(UnitData self, MapData mapData); // 是否限制自身反击 public bool IsLimitSelfCounterAttack(UnitData self, MapData mapData); // 是否无视敌人控制区 public bool IsIgnoreControlArea(UnitData self, MapData mapData); // 是否限制自身经验增长 public bool IsLimitSelfExp(UnitData self, MapData mapData); // 是否无视树林和山脉 public bool IsIgnoreWoodAndMountains(UnitData self, MapData mapData); // 是否能在指定海陆层移动 public bool IsCanMoveOnTerrain(UnitData self, MapData mapData, TerrainType terrainType); // 是否能在指定地形层移动 public bool IsCanMoveOnFeature(UnitData self, MapData mapData, TerrainFeature featureType); // 是否无视地形层移动减损 public bool IsIgnoreMoveLoss(UnitData self, MapData mapData, TerrainFeature terrainType); // 是否无视植被层移动减损 public bool IsIgnoreMoveLoss(UnitData self, MapData mapData, Vegetation terrainType); // 是否具备同类数量限制 public bool IsLimitCount(UnitData self, MapData mapData, out int count); // 是否能移动到我方的无人城市 public bool IsCanMoveToNoUnitSelfCity(UnitData self, MapData mapData); // 是否能移动到我方的英雄附近 public bool IsCanMoveGiantNearbyGrid(UnitData self, MapData mapData); // 是否能移动到 // 能否被杀死 public bool IsCanBeKill(UnitData self, MapData mapData); // 能否被伤害 public bool IsCanBeDamaged(UnitData self, MapData mapData, int dmg); // 能否制造矿山 public bool IsCanBuildMine(UnitData self, MapData mapData); // 是否隐身 public bool IsInvisible(UnitData self, MapData mapData); // 值变化 // 获取额外视野(视野增加) public int GetExtraSight(UnitData self, MapData mapData); // 获取暴击率 public float GetCriticalHitRate(UnitData self, MapData mapData); public float GetAttackAdditionParam(MapData mapData, UnitData self, UnitData target = null); public float GetAttackMultiplicationParam(MapData mapData, UnitData self, UnitData target = null); public float GetDefenseAdditionParam(MapData mapData, UnitData self, UnitData target = null); public float GetDefenseMultiplicationParam(MapData mapData, UnitData self, UnitData target = null); // 获得额外移动范围 public int GetExtraMoveRange(UnitData self); // 获得额外攻击范围 public int GetExtraAttackRange(UnitData self); // 获取特定技能加成 public int GetSpecialSkillBonus(MapData mapData, UnitData self, SkillType skillType); // 全局技能 // 当有单位受伤结算时 public void OnUnitDamaged(IdentifierBase identifier, MapData mapData, SettlementInfo info); // 当有单位移动时 public void OnAnyUnitMove(MapData map, UnitData self, UnitData moveUnit, GridData target, MoveType moveType); // 当有单位死亡时 public void OnAnyUnitDie(MapData map, UnitData self); // 当有单位创建时 public void OnAnyUnitCreate(MapData map, UnitData self, UnitData newUnit); } [MemoryPackable] public abstract partial class SkillBase : ISkill { [MemoryPackInclude] protected bool IsPermanent; //是否叠层 [MemoryPackInclude] protected bool IsLevelSkill; //如果是叠层且0层的时候仍然有该状态 [MemoryPackInclude] protected bool ZeroLevelStay; [MemoryPackInclude] protected uint Turns; [MemoryPackInclude] protected uint TurnsLimit; [MemoryPackInclude] protected float Score; [MemoryPackInclude] protected int _level; [MemoryPackInclude] protected int _levelLimit; [MemoryPackInclude] protected bool _autoDisappear; public virtual int Level => _level; public bool HasTimeLimit => !IsPermanent; public int LastTime => (int)TurnsLimit - (int)Turns; public bool NoShow => _autoDisappear && _level == 0; public bool ShowSkillLevel => IsLevelSkill && !NoShow; public bool ShowSkill => !IsLevelSkill || ShowSkillLevel; [MemoryPackConstructor] public SkillBase() { IsLevelSkill = false; Turns = 0; _level = 0; _autoDisappear = true; } public abstract SkillType GetSkillType(); public virtual float GetScore() { return Score; } public virtual bool IsFinished() { Turns++; return (!IsPermanent && TurnsLimit < Turns) || (IsLevelSkill && _autoDisappear && _level == 0); } public virtual bool IsActive() { return true; } public SkillBase GetCopySkill() { var skill = SkillFactory.GetSkillBySkillType(GetSkillType()); GetSkillCopy(skill); return skill; } public virtual void SetTurnsLimit(uint time) { IsPermanent = false; TurnsLimit = time; } public virtual void AddTurnLimit(uint time) { TurnsLimit += time; } public virtual void AddLevel(MapData map, UnitData origin, UnitData self, int add) { _level += add; if (_level > _levelLimit) _level = _levelLimit; if (!map.GetPlayerDataByUnitId(origin.Id, out var player)) return; origin.HeroTask(map)?.OnAddSkillLevels(map, GetSkillType(), (uint)add); } public virtual void ReduceLevel(MapData map, UnitData origin, int reduce) { _level -= reduce; } public virtual void SetLevel(int level) { _level = level; } public virtual void GetSkillCopy(SkillBase skill) { skill.IsPermanent = IsPermanent; skill.Turns = Turns; skill.TurnsLimit = TurnsLimit; skill.Score = Score; } public virtual void DeepCopy(SkillBase copySkill) { IsPermanent = copySkill.IsPermanent; Turns = copySkill.Turns; TurnsLimit = copySkill.TurnsLimit; } public virtual void OnSkillAdd(UnitData self, MapData mapData) { } public virtual void OnMove(UnitData self, GridData grid, MapData mapData,MoveType moveType) { } public virtual void BeforeDamaged(MapData mapData, SettlementInfo info) { } public virtual void BeforeDamageOther(MapData mapData, SettlementInfo info) { } public virtual void OnDamaged(MapData mapData, SettlementInfo info) { } public virtual void OnTransformRemoved(UnitData self, MapData mapData) { } public virtual void OnTransformAdded(UnitData self, MapData mapData) { } public virtual void OnDamageOther(MapData mapData, SettlementInfo info) { } public virtual void BeforeActiveAttackOther(MapData mapData, UnitData origin, UnitData target,out int addDmg) { addDmg = 0; } public virtual void AfterActiveAttackOther(MapData mapData, UnitData origin, UnitData target) { } public virtual void AfterActiveAttacked(MapData mapData, UnitData origin, UnitData target) { } public virtual void OnTurnStart(UnitData self, MapData mapData) { } public virtual void OnTurnStart(GridData self, MapData mapData) { } public virtual void OnTurnStart(CityData city, MapData mapData) { } public virtual void OnTurnStart(PlayerData self, MapData mapData) { } public virtual void OnTurnEnd(UnitData self, MapData mapData) { } public virtual void OnTurnEnd(CityData city, MapData mapData) { } public virtual void OnTurnEnd(PlayerData self, MapData mapData) { } public virtual void OnTurnEnd(GridData self, MapData mapData) { } public virtual void OnFinished(IdentifierBase self, MapData mapData) { } public virtual bool CanAttackAll(UnitData self, MapData mapData) { return false; } public virtual bool IsLimitSelfMove(UnitData self, MapData mapData) { return false; } public virtual bool IsLimitSelfAttack(UnitData self, MapData mapData) { return false; } public virtual bool IsLimitTargetCounterAttack(UnitData self, MapData mapData) { return false; } public virtual bool IsLimitSelfCounterAttack(UnitData self, MapData mapData) { return false; } public virtual bool IsIgnoreControlArea(UnitData self, MapData mapData) { return false; } public virtual bool IsLimitSelfExp(UnitData self, MapData mapData) { return false; } public virtual bool IsIgnoreWoodAndMountains(UnitData self, MapData mapData) { return false; } public virtual bool IsCanMoveOnTerrain(UnitData self, MapData mapData, TerrainType terrainType) { return false; } public virtual bool IsCanMoveOnFeature(UnitData self, MapData mapData, TerrainFeature terrainType) { return false; } public virtual bool IsIgnoreMoveLoss(UnitData self, MapData mapData, TerrainFeature terrainType) { return false; } public virtual bool IsIgnoreMoveLoss(UnitData self, MapData mapData, Vegetation terrainType) { return false; } public virtual bool IsLimitCount(UnitData self, MapData mapData, out int count) { count = -1; return false; } public virtual bool IsCanMoveToNoUnitSelfCity(UnitData self, MapData mapData) { return false; } public virtual bool IsCanMoveGiantNearbyGrid(UnitData self, MapData mapData) { return false; } public virtual bool IsCanBeKill(UnitData self, MapData mapData) { return true; } public virtual bool IsCanBeDamaged(UnitData self, MapData mapData, int dmg) { return true; } public virtual bool IsCanBuildMine(UnitData self, MapData mapData) { return false; } public virtual bool IsInvisible(UnitData self, MapData mapData) { return false; } public virtual int GetExtraSight(UnitData self, MapData mapData) { return 0; } public virtual float GetCriticalHitRate(UnitData self, MapData mapData) { return 0; } public virtual float GetAttackAdditionParam(MapData mapData, UnitData self, UnitData target = null) { return 0; } public virtual float GetDefenseAdditionParam(MapData mapData, UnitData self, UnitData target = null) { return 0; } public virtual float GetAttackMultiplicationParam(MapData mapData, UnitData self, UnitData target = null) { return 1; } public virtual float GetDefenseMultiplicationParam(MapData mapData, UnitData self, UnitData target = null) { return 1; } public virtual int GetExtraMoveRange(UnitData self) { return 0; } public virtual int GetExtraAttackRange(UnitData self) { return 0; } public virtual int GetSpecialSkillBonus(MapData mapData, UnitData self, SkillType skillType) { return 1; } public virtual void OnUnitDamaged(IdentifierBase identifier, MapData mapData, SettlementInfo info) { } public virtual void OnAnyUnitMove(MapData map, UnitData self, UnitData moveUnit, GridData target, MoveType moveType) { } public virtual void OnAnyUnitDie(MapData map, UnitData self) { } public virtual void OnAnyUnitCreate(MapData map, UnitData self, UnitData newUnit) { } } }