309 lines
11 KiB
C#
309 lines
11 KiB
C#
/*
|
||
* @Author: 白哉
|
||
* @Description:
|
||
* @Date: 2025年04月03日 星期四 11:04:31
|
||
* @Modify:
|
||
*/
|
||
|
||
|
||
using System.Collections.Generic;
|
||
using Logic.Skill;
|
||
using MemoryPack;
|
||
|
||
|
||
namespace RuntimeData
|
||
{
|
||
[MemoryPackable]
|
||
[MemoryPackUnion(1, typeof(PlayerData))]
|
||
[MemoryPackUnion(2, typeof(UnitData))]
|
||
[MemoryPackUnion(3, typeof(CityData))]
|
||
[MemoryPackUnion(4, typeof(GridData))]
|
||
public abstract partial class IdentifierBase
|
||
{
|
||
// 唯一 ID
|
||
public uint Id;
|
||
|
||
// 技能信息
|
||
public List<SkillBase> Skills = new List<SkillBase>();
|
||
private Dictionary<SkillType, SkillBase> _skillDict;
|
||
|
||
// Mark 信息
|
||
/*[MemoryPackInclude]
|
||
protected bool _renderMark;
|
||
|
||
public bool RenderMark
|
||
{
|
||
get => _renderMark;
|
||
set => _renderMark = value;
|
||
}*/
|
||
|
||
public bool GetSkill(SkillType skillType, out SkillBase skill)
|
||
{
|
||
RefreshSkillDict();
|
||
return _skillDict.TryGetValue(skillType, out skill);
|
||
}
|
||
|
||
// 添加技能的常规方法 (这里默认了添加和覆盖都走统一接口)
|
||
public virtual void AddOrOverrideSkill(SkillType skillType, MapData mapData, uint originId)
|
||
{
|
||
RefreshSkillDict();
|
||
if (_skillDict.ContainsKey(skillType))
|
||
{
|
||
_skillDict[skillType].OnSkillOverride(mapData, originId, Id);
|
||
}
|
||
else
|
||
{
|
||
var skill = SkillFactory.GetSkillBySkillType(skillType);
|
||
if (skill == null) return;
|
||
Skills.Add(skill);
|
||
_skillDict[skillType] = skill;
|
||
skill.OnSkillAdd(mapData, originId);
|
||
// 首次添加技能时,OnSkillAdd不会调用AddLevel,OnAddSkillLevels不会触发
|
||
// 在此统一通知HeroTask,避免各技能手动处理遗漏
|
||
if (mapData.UnitMap.GetUnitDataByUnitId(originId, out var origin))
|
||
{
|
||
origin.HeroTask(mapData)?.OnAddSkillLevels(mapData, skillType, 1);
|
||
}
|
||
}
|
||
|
||
// 同步状态图标显示(ShowOnUnitMono 配置的技能)
|
||
if (this is UnitData unitDataForStatus)
|
||
{
|
||
unitDataForStatus.Renderer(mapData)?.SyncStatusWithUnitSkills();
|
||
}
|
||
}
|
||
|
||
public virtual void AddOrOverrideSkill(SkillBase skill, MapData mapData, uint originId)
|
||
{
|
||
if (_skillDict.ContainsKey(skill.GetSkillType())) return;
|
||
|
||
Skills.Add(skill);
|
||
_skillDict[skill.GetSkillType()] = skill;
|
||
skill.OnSkillAdd(mapData, originId);
|
||
if (mapData.UnitMap.GetUnitDataByUnitId(originId, out var origin))
|
||
{
|
||
origin.HeroTask(mapData)?.OnAddSkillLevels(mapData, skill.GetSkillType(), 1);
|
||
}
|
||
|
||
// 同步状态图标显示(ShowOnUnitMono 配置的技能)
|
||
if (this is UnitData unitDataForStatus)
|
||
{
|
||
unitDataForStatus.Renderer(mapData)?.SyncStatusWithUnitSkills();
|
||
}
|
||
}
|
||
|
||
// 添加技能的特殊方法 (这里默认了添加和覆盖都走统一接口)
|
||
public virtual void SpecialAddOrOverrideSkill(SkillType skillType, MapData mapData, uint originId, SkillOverrideInfo overrideInfo)
|
||
{
|
||
|
||
}
|
||
|
||
//TODO Legacy 这是一个耦合方法,会被拆解
|
||
public virtual void AddSkill_Legacy(SkillType skillType, MapData mapData, bool IsPermanent, int turnLimit,
|
||
bool IsLevel, int level, bool autoDisappear, SpecialAddSkillType addType, uint originId)
|
||
{
|
||
RefreshSkillDict();
|
||
//如果技能已经存在
|
||
if (_skillDict.ContainsKey(skillType))
|
||
{
|
||
if (addType == SpecialAddSkillType.Normal) return;
|
||
if (addType == SpecialAddSkillType.AddTurnLimit)
|
||
{
|
||
var skill = _skillDict[skillType];
|
||
//如果对方本来就是永久,直接return
|
||
if (!skill.HasTimeLimit) return;
|
||
//否则让对方的limit增加
|
||
if (!IsPermanent)
|
||
skill.AddTurnLimit((uint)turnLimit + 1);
|
||
return;
|
||
}
|
||
|
||
if (addType == SpecialAddSkillType.Force)
|
||
{
|
||
var skill = _skillDict[skillType];
|
||
skill.SetPermanent(IsPermanent);
|
||
if (!IsPermanent)
|
||
skill.SetTurnsLimit((uint)turnLimit);
|
||
skill.SetIsLevel(IsLevel);
|
||
skill.SetAutoDisappear(autoDisappear);
|
||
if (skill.HasLevel)
|
||
{
|
||
skill.SetLevel(0);
|
||
mapData.UnitMap.GetUnitDataByUnitId(originId, out var unitData);
|
||
skill.AddLevel(mapData, unitData, this as UnitData, level);
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
if (addType == SpecialAddSkillType.AddLevel)
|
||
{
|
||
var skill = _skillDict[skillType];
|
||
//如果对方不是叠层技能,直接return
|
||
if (!skill.HasLevel) return;
|
||
mapData.UnitMap.GetUnitDataByUnitId(originId, out var unitData);
|
||
skill.AddLevel(mapData, unitData, this as UnitData, level);
|
||
return;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
var skill = SkillFactory.GetSkillBySkillType(skillType);
|
||
if (skill == null) return;
|
||
|
||
Skills.Add(skill);
|
||
_skillDict[skillType] = skill;
|
||
if (!IsPermanent) skill.SetTurnsLimit((uint)turnLimit);
|
||
if (IsLevel && mapData.UnitMap.GetUnitDataByUnitId(originId, out var unitData))
|
||
{
|
||
//首次添加时,0层消失的叠层技能应当把传入层数视为目标值而非增量
|
||
//(构造函数/OnSkillAdd 可能已经保底到 1 层,不应再被叠加)
|
||
if (skill.HasLevel && skill.AutoDisappear)
|
||
skill.SetLevel(0);
|
||
skill.AddLevel(mapData, unitData, this as UnitData, level);
|
||
}
|
||
|
||
skill.OnSkillAdd(mapData, originId);
|
||
|
||
// 同步状态图标显示(ShowOnUnitMono 配置的技能)
|
||
if (this is UnitData unitDataForStatus)
|
||
{
|
||
unitDataForStatus.Renderer(mapData)?.SyncStatusWithUnitSkills();
|
||
}
|
||
}
|
||
}
|
||
|
||
//初始一个小兵,填加初始技能/国家科技标准的时候,使用这个
|
||
public virtual void AddInitSkill(SkillType skillType, MapData mapData)
|
||
{
|
||
RefreshSkillDict();
|
||
//如果技能已经存在,删除,重置
|
||
if (_skillDict.ContainsKey(skillType))
|
||
RemoveSkill(skillType,mapData);
|
||
var skill = SkillFactory.GetSkillBySkillType(skillType);
|
||
if (skill == null) return;
|
||
Skills.Add(skill);
|
||
_skillDict[skillType] = skill;
|
||
}
|
||
|
||
/*public virtual void AddSkill(SkillType skillType, MapData mapData, uint originId = 0)
|
||
{
|
||
RefreshSkillDict();
|
||
if (_skillDict.ContainsKey(skillType)) return;
|
||
var skill = SkillFactory.GetSkillBySkillType(skillType);
|
||
if (skill != null)
|
||
{
|
||
Skills.Add(skill);
|
||
_skillDict[skillType] = skill;
|
||
skill.OnSkillAdd(mapData, originId);
|
||
}
|
||
}
|
||
|
||
public virtual void AddSkill(SkillType skillType, uint turnLimit, MapData mapData, uint originId = 0)
|
||
{
|
||
RefreshSkillDict();
|
||
//如果已经有这个技能了
|
||
if (_skillDict.ContainsKey(skillType))
|
||
{
|
||
var skill = _skillDict[skillType];
|
||
//如果对方本来就是永久,直接return
|
||
if(!skill.HasTimeLimit) return;
|
||
//否则让对方的limit增加
|
||
skill.AddTurnLimit(turnLimit + 1);
|
||
}
|
||
//如果还没有这个技能
|
||
else
|
||
{
|
||
var skill = SkillFactory.GetSkillBySkillType(skillType);
|
||
if (skill != null)
|
||
{
|
||
Skills.Add(skill);
|
||
_skillDict[skillType] = skill;
|
||
skill.SetTurnsLimit(turnLimit);
|
||
skill.OnSkillAdd(mapData, originId);
|
||
}
|
||
}
|
||
}*/
|
||
|
||
public void RemoveSkill(SkillType skillType, MapData map)
|
||
{
|
||
RefreshSkillDict();
|
||
if (!_skillDict.TryGetValue(skillType, out var value)) return;
|
||
Skills.Remove(value);
|
||
_skillDict.Remove(skillType);
|
||
|
||
|
||
// 如果是HideState技能被移除,触发渲染更新
|
||
if (skillType == SkillType.HideState && this is UnitData unitData)
|
||
{
|
||
unitData.Renderer(map)?.InstantUpdateUnit(true);
|
||
}
|
||
|
||
// 同步状态图标显示(ShowOnUnitMono 配置的技能)
|
||
if (this is UnitData unitDataForStatus)
|
||
{
|
||
unitDataForStatus.Renderer(map)?.SyncStatusWithUnitSkills();
|
||
}
|
||
}
|
||
|
||
private void RefreshSkillDict()
|
||
{
|
||
_skillDict ??= new Dictionary<SkillType, SkillBase>();
|
||
if (_skillDict.Count != Skills.Count)
|
||
{
|
||
_skillDict.Clear();
|
||
foreach (var skill in Skills) _skillDict[skill.GetSkillType()] = skill;
|
||
}
|
||
}
|
||
|
||
// MemoryPack 反序列化之后的后处理
|
||
[MemoryPackOnDeserialized]
|
||
public void OnAfterMemoryPackDeserialize()
|
||
{
|
||
_skillDict ??= new Dictionary<SkillType, SkillBase>();
|
||
_skillDict.Clear();
|
||
foreach (var skill in Skills) _skillDict[skill.GetSkillType()] = skill;
|
||
}
|
||
|
||
// 共享的技能迭代缓冲区,避免每次OnSkillsTurnStart/End都new List
|
||
[MemoryPackIgnore]
|
||
private List<SkillBase> _skillIterBuffer;
|
||
|
||
protected virtual void OnSkillsTurnStart(MapData map)
|
||
{
|
||
_skillIterBuffer ??= new List<SkillBase>();
|
||
_skillIterBuffer.Clear();
|
||
_skillIterBuffer.AddRange(Skills);
|
||
foreach (var skill in _skillIterBuffer)
|
||
{
|
||
skill.BeforeTurnStart();
|
||
if (skill.IsFinished())
|
||
{
|
||
skill.OnFinished(this, map);
|
||
Skills.Remove(skill);
|
||
continue;
|
||
}
|
||
skill.OnTurnStart(this, map);
|
||
}
|
||
}
|
||
|
||
protected virtual void OnSkillsAfterTurnStart(MapData map)
|
||
{
|
||
_skillIterBuffer ??= new List<SkillBase>();
|
||
_skillIterBuffer.Clear();
|
||
_skillIterBuffer.AddRange(Skills);
|
||
foreach (var skill in _skillIterBuffer)
|
||
{
|
||
skill.OnAfterTurnStart(this, map);
|
||
}
|
||
}
|
||
|
||
protected virtual void OnSkillsTurnEnd(MapData map)
|
||
{
|
||
_skillIterBuffer ??= new List<SkillBase>();
|
||
_skillIterBuffer.Clear();
|
||
_skillIterBuffer.AddRange(Skills);
|
||
foreach (var skill in _skillIterBuffer) skill.OnTurnEnd(this, map);
|
||
}
|
||
}
|
||
} |