From 5a4c8fe1961b359bcb70710856530de54985d47a Mon Sep 17 00:00:00 2001 From: milimoe Date: Fri, 7 Feb 2025 01:27:54 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=B4=BB=E5=8A=A8=E5=92=8C?= =?UTF-8?q?=E6=B4=BB=E5=8A=A8=E4=B8=AD=E5=BF=83=EF=BC=8C=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=8D=95=E4=BD=8D=EF=BC=8C=E4=BF=AE=E6=94=B9=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Entity/Character/Character.cs | 1 - Entity/Character/Unit.cs | 481 ++++++++++++++++++ Entity/System/Activity.cs | 122 +++++ Entity/System/Quest.cs | 51 +- Library/Common/Event/SendTalkEventArgs.cs | 9 +- Library/Common/Event/UserActivityEventArgs.cs | 13 +- Library/Constant/ConstantSet.cs | 12 + Library/Constant/StateEnum.cs | 3 +- Model/EventCenter.cs | 134 +++++ 9 files changed, 783 insertions(+), 43 deletions(-) create mode 100644 Entity/Character/Unit.cs create mode 100644 Entity/System/Activity.cs create mode 100644 Model/EventCenter.cs diff --git a/Entity/Character/Character.cs b/Entity/Character/Character.cs index b61706b..82c8dcc 100644 --- a/Entity/Character/Character.cs +++ b/Entity/Character/Character.cs @@ -8,7 +8,6 @@ namespace Milimoe.FunGame.Core.Entity /// /// 角色需要使用 Factory.Get 的方式来构造,并赋值 标记的属性 /// 在使用时仅需要调用 方法即可获得相同对象 - /// 不建议继承 /// public class Character : BaseEntity { diff --git a/Entity/Character/Unit.cs b/Entity/Character/Unit.cs new file mode 100644 index 0000000..d4f72c5 --- /dev/null +++ b/Entity/Character/Unit.cs @@ -0,0 +1,481 @@ +using System.Text; +using Milimoe.FunGame.Core.Api.Utility; +using Milimoe.FunGame.Core.Library.Constant; + +namespace Milimoe.FunGame.Core.Entity +{ + /// + /// 是一个用于描述生物的单元对象(单位),而 是一种高级单位(单位单位/英雄单位) + /// 和单位一样,使用 标记的需要初始赋值的属性 + /// + public class Unit : Character + { + /// + /// 单位名称 + /// + public override string Name { get; set; } = ""; + + /// + /// 获取单位名称以及所属玩家 + /// + /// + public override string ToString() + { + string str = Name; + if (User != null && User.Username != "") + { + str += "(" + User.Username + ")"; + } + return str; + } + + /// + /// 获取单位名称以及所属玩家,包含等级 + /// + /// + public new string ToStringWithLevel() + { + string str = Name + " - 等级 " + Level; + if (User != null && User.Username != "") + { + str += "(" + User.Username + ")"; + } + return str; + } + + /// + /// 获取单位的详细信息 + /// + /// + public new string GetInfo(bool showUser = true, bool showGrowth = true, bool showEXP = false) + { + StringBuilder builder = new(); + + builder.AppendLine(showUser ? ToStringWithLevel() : ToStringWithLevelWithOutUser()); + builder.AppendLine($"等级:{Level} / {General.GameplayEquilibriumConstant.MaxLevel}"); + double exHP = ExHP + ExHP2 + ExHP3; + builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "")); + double exMP = ExMP + ExMP2 + ExMP3; + builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); + double exATK = ExATK + ExATK2 + ExATK3; + builder.AppendLine($"攻击力:{ATK:0.##}" + (exATK != 0 ? $" [{BaseATK:0.##} {(exATK >= 0 ? "+" : "-")} {Math.Abs(exATK):0.##}]" : "")); + double exDEF = ExDEF + ExDEF2 + ExDEF3; + builder.AppendLine($"物理护甲:{DEF:0.##}" + (exDEF != 0 ? $" [{BaseDEF:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exDEF):0.##}]" : "") + $" ({PDR * 100:0.##}%)"); + double mdf = Calculation.Round4Digits((MDF.None + MDF.Starmark + MDF.PurityNatural + MDF.PurityContemporary + + MDF.Bright + MDF.Shadow + MDF.Element + MDF.Fleabane + MDF.Particle) / 9) * 100; + if (Calculation.IsApproximatelyZero(mdf)) mdf = 0; + builder.AppendLine($"魔法抗性:{mdf:0.##}%(平均)"); + double exSPD = AGI * General.GameplayEquilibriumConstant.AGItoSPDMultiplier + ExSPD; + builder.AppendLine($"行动速度:{SPD:0.##}" + (exSPD != 0 ? $" [{InitialSPD:0.##} {(exSPD >= 0 ? "+" : "-")} {Math.Abs(exSPD):0.##}]" : "") + $" ({ActionCoefficient * 100:0.##}%)"); + builder.AppendLine($"生命回复:{HR:0.##}" + (ExHR != 0 ? $" [{InitialHR + STR * General.GameplayEquilibriumConstant.STRtoHRFactor:0.##} {(ExHR >= 0 ? "+" : "-")} {Math.Abs(ExHR):0.##}]" : "")); + builder.AppendLine($"魔法回复:{MR:0.##}" + (ExMR != 0 ? $" [{InitialMR + INT * General.GameplayEquilibriumConstant.INTtoMRFactor:0.##} {(ExMR >= 0 ? "+" : "-")} {Math.Abs(ExMR):0.##}]" : "")); + builder.AppendLine($"暴击率:{CritRate * 100:0.##}%"); + builder.AppendLine($"暴击伤害:{CritDMG * 100:0.##}%"); + builder.AppendLine($"闪避率:{EvadeRate * 100:0.##}%"); + builder.AppendLine($"冷却缩减:{CDR * 100:0.##}%"); + builder.AppendLine($"加速系数:{AccelerationCoefficient * 100:0.##}%"); + builder.AppendLine($"物理穿透:{PhysicalPenetration * 100:0.##}%"); + builder.AppendLine($"魔法穿透:{MagicalPenetration * 100:0.##}%"); + + if (CharacterState != CharacterState.Actionable) + { + builder.AppendLine(CharacterSet.GetCharacterState(CharacterState)); + } + + if (IsNeutral) + { + builder.AppendLine("单位是无敌的"); + } + + if (IsUnselectable) + { + builder.AppendLine("单位是不可选中的"); + } + + builder.AppendLine("== 普通攻击 =="); + builder.Append(NormalAttack.ToString()); + + if (Skills.Count > 0) + { + builder.AppendLine("== 单位技能 =="); + foreach (Skill skill in Skills) + { + builder.Append(skill.ToString()); + } + } + + if (EquipSlot.Any()) + { + builder.AppendLine("== 装备栏 =="); + if (EquipSlot.MagicCardPack != null) + { + builder.AppendLine($"[{ItemSet.GetQualityTypeName(EquipSlot.MagicCardPack.QualityType)}]" + ItemSet.GetEquipSlotTypeName(EquipSlotType.MagicCardPack) + ":" + EquipSlot.MagicCardPack.Name); + builder.AppendLine(EquipSlot.MagicCardPack.Description); + } + if (EquipSlot.Weapon != null) + { + builder.AppendLine($"[{ItemSet.GetQualityTypeName(EquipSlot.Weapon.QualityType)}]" + ItemSet.GetEquipSlotTypeName(EquipSlotType.Weapon) + ":" + EquipSlot.Weapon.Name); + builder.AppendLine(EquipSlot.Weapon.Description); + } + if (EquipSlot.Armor != null) + { + builder.AppendLine($"[{ItemSet.GetQualityTypeName(EquipSlot.Armor.QualityType)}]" + ItemSet.GetEquipSlotTypeName(EquipSlotType.Armor) + ":" + EquipSlot.Armor.Name); + builder.AppendLine(EquipSlot.Armor.Description); + } + if (EquipSlot.Shoes != null) + { + builder.AppendLine($"[{ItemSet.GetQualityTypeName(EquipSlot.Shoes.QualityType)}]" + ItemSet.GetEquipSlotTypeName(EquipSlotType.Shoes) + ":" + EquipSlot.Shoes.Name); + builder.AppendLine(EquipSlot.Shoes.Description); + } + if (EquipSlot.Accessory1 != null) + { + builder.AppendLine($"[{ItemSet.GetQualityTypeName(EquipSlot.Accessory1.QualityType)}]" + ItemSet.GetEquipSlotTypeName(EquipSlotType.Accessory1) + ":" + EquipSlot.Accessory1.Name); + builder.AppendLine(EquipSlot.Accessory1.Description); + } + if (EquipSlot.Accessory2 != null) + { + builder.AppendLine($"[{ItemSet.GetQualityTypeName(EquipSlot.Accessory2.QualityType)}]" + ItemSet.GetEquipSlotTypeName(EquipSlotType.Accessory2) + ":" + EquipSlot.Accessory2.Name); + builder.AppendLine(EquipSlot.Accessory2.Description); + } + } + + if (Items.Count > 0) + { + builder.AppendLine("== 单位背包 =="); + foreach (Item item in Items) + { + builder.Append(item.ToString()); + } + } + + if (Effects.Where(e => e.EffectType != EffectType.Item).Any()) + { + builder.AppendLine("== 状态栏 =="); + foreach (Effect effect in Effects.Where(e => e.EffectType != EffectType.Item)) + { + builder.Append(effect.ToString()); + } + } + + /** + * 意义不明(✖)的代码 + */ + if (showGrowth == showEXP) + { + showGrowth.ToString(); + } + + return builder.ToString(); + } + + /// + /// 获取单位的简略信息 + /// + /// + public new string GetSimpleInfo(bool showUser = true, bool showGrowth = true, bool showEXP = false, bool showBasicOnly = false) + { + StringBuilder builder = new(); + + builder.AppendLine(showUser ? ToStringWithLevel() : ToStringWithLevelWithOutUser()); + builder.AppendLine($"等级:{Level} / {General.GameplayEquilibriumConstant.MaxLevel}"); + double exHP = ExHP + ExHP2 + ExHP3; + builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "")); + double exMP = ExMP + ExMP2 + ExMP3; + builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); + double exATK = ExATK + ExATK2 + ExATK3; + builder.AppendLine($"攻击力:{ATK:0.##}" + (exATK != 0 ? $" [{BaseATK:0.##} {(exATK >= 0 ? "+" : "-")} {Math.Abs(exATK):0.##}]" : "")); + double exDEF = ExDEF + ExDEF2 + ExDEF3; + builder.AppendLine($"物理护甲:{DEF:0.##}" + (exDEF != 0 ? $" [{BaseDEF:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exDEF):0.##}]" : "") + $" ({PDR * 100:0.##}%)"); + double mdf = Calculation.Round4Digits((MDF.None + MDF.Starmark + MDF.PurityNatural + MDF.PurityContemporary + + MDF.Bright + MDF.Shadow + MDF.Element + MDF.Fleabane + MDF.Particle) / 9) * 100; + if (Calculation.IsApproximatelyZero(mdf)) mdf = 0; + builder.AppendLine($"魔法抗性:{mdf:0.##}%(平均)"); + double exSPD = AGI * General.GameplayEquilibriumConstant.AGItoSPDMultiplier + ExSPD; + builder.AppendLine($"行动速度:{SPD:0.##}" + (exSPD != 0 ? $" [{InitialSPD:0.##} {(exSPD >= 0 ? "+" : "-")} {Math.Abs(exSPD):0.##}]" : "") + $" ({ActionCoefficient * 100:0.##}%)"); + builder.AppendLine($"生命回复:{HR:0.##}" + (ExHR != 0 ? $" [{InitialHR + STR * General.GameplayEquilibriumConstant.STRtoHRFactor:0.##} {(ExHR >= 0 ? "+" : "-")} {Math.Abs(ExHR):0.##}]" : "")); + builder.AppendLine($"魔法回复:{MR:0.##}" + (ExMR != 0 ? $" [{InitialMR + INT * General.GameplayEquilibriumConstant.INTtoMRFactor:0.##} {(ExMR >= 0 ? "+" : "-")} {Math.Abs(ExMR):0.##}]" : "")); + + if (!showBasicOnly) + { + if (CharacterState != CharacterState.Actionable) + { + builder.AppendLine(CharacterSet.GetCharacterState(CharacterState)); + } + + if (IsNeutral) + { + builder.AppendLine("单位是无敌的"); + } + + if (IsUnselectable) + { + builder.AppendLine("单位是不可选中的"); + } + + if (Skills.Count > 0) + { + builder.AppendLine("== 单位技能 =="); + builder.AppendLine(string.Join(",", Skills.Select(s => s.Name))); + } + + if (EquipSlot.Any()) + { + builder.AppendLine("== 已装备槽位 =="); + List types = []; + if (EquipSlot.MagicCardPack != null) + { + types.Add(EquipSlotType.MagicCardPack); + } + if (EquipSlot.Weapon != null) + { + types.Add(EquipSlotType.Weapon); + } + if (EquipSlot.Armor != null) + { + types.Add(EquipSlotType.Armor); + } + if (EquipSlot.Shoes != null) + { + types.Add(EquipSlotType.Shoes); + } + if (EquipSlot.Accessory1 != null) + { + types.Add(EquipSlotType.Accessory1); + } + if (EquipSlot.Accessory2 != null) + { + types.Add(EquipSlotType.Accessory2); + } + builder.AppendLine(string.Join(",", types.Select(ItemSet.GetEquipSlotTypeName))); + } + + if (Effects.Where(e => e.EffectType != EffectType.Item).Any()) + { + builder.AppendLine("== 状态栏 =="); + builder.Append(string.Join(",", Effects.Where(e => e.EffectType != EffectType.Item).Select(e => e.Name))); + } + } + + /** + * 意义不明(✖)的代码 + */ + if (showGrowth == showEXP) + { + showGrowth.ToString(); + } + + return builder.ToString(); + } + + /// + /// 获取战斗状态的信息 + /// + /// + /// + public new string GetInBattleInfo(double hardnessTimes) + { + StringBuilder builder = new(); + + builder.AppendLine(ToStringWithLevel()); + double exHP = ExHP + ExHP2 + ExHP3; + builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "")); + double exMP = ExMP + ExMP2 + ExMP3; + builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); + double exATK = ExATK + ExATK2 + ExATK3; + builder.AppendLine($"攻击力:{ATK:0.##}" + (exATK != 0 ? $" [{BaseATK:0.##} {(exATK >= 0 ? "+" : "-")} {Math.Abs(exATK):0.##}]" : "")); + + if (CharacterState != CharacterState.Actionable) + { + builder.AppendLine(CharacterSet.GetCharacterState(CharacterState)); + } + + if (IsNeutral) + { + builder.AppendLine("单位是中立单位,处于无敌状态"); + } + + if (IsUnselectable) + { + builder.AppendLine("单位是不可选中的"); + } + + builder.AppendLine($"硬直时间:{hardnessTimes:0.##}"); + + if (Effects.Where(e => e.EffectType != EffectType.Item).Any()) + { + builder.AppendLine("== 状态栏 =="); + foreach (Effect effect in Effects.Where(e => e.EffectType != EffectType.Item)) + { + builder.Append(effect.ToString()); + } + } + + return builder.ToString(); + } + + /// + /// 获取战斗状态的信息(简略版) + /// + /// + /// + public new string GetSimpleInBattleInfo(double hardnessTimes) + { + StringBuilder builder = new(); + + builder.AppendLine(ToStringWithLevel()); + double exHP = ExHP + ExHP2 + ExHP3; + builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "")); + double exMP = ExMP + ExMP2 + ExMP3; + builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); + double exATK = ExATK + ExATK2 + ExATK3; + builder.AppendLine($"攻击力:{ATK:0.##}" + (exATK != 0 ? $" [{BaseATK:0.##} {(exATK >= 0 ? "+" : "-")} {Math.Abs(exATK):0.##}]" : "")); + builder.AppendLine($"硬直时间:{hardnessTimes:0.##}"); + + if (Effects.Where(e => e.EffectType != EffectType.Item).Any()) + { + builder.AppendLine("== 状态栏 =="); + builder.Append(string.Join(",", Effects.Where(e => e.EffectType != EffectType.Item).Select(e => e.Name))); + } + + return builder.ToString(); + } + + /// + /// 获取单位的技能信息 + /// + /// + public new string GetSkillInfo(bool showUser = true) + { + StringBuilder builder = new(); + + builder.AppendLine(showUser ? ToStringWithLevel() : ToStringWithLevelWithOutUser()); + + if (CharacterState != CharacterState.Actionable) + { + builder.AppendLine(CharacterSet.GetCharacterState(CharacterState)); + } + + if (IsNeutral) + { + builder.AppendLine("单位是无敌的"); + } + + if (IsUnselectable) + { + builder.AppendLine("单位是不可选中的"); + } + + builder.AppendLine("== 普通攻击 =="); + builder.Append(NormalAttack.ToString()); + + if (Skills.Count > 0) + { + builder.AppendLine("== 单位技能 =="); + foreach (Skill skill in Skills) + { + builder.Append(skill.ToString()); + } + } + + if (Effects.Where(e => e.EffectType != EffectType.Item).Any()) + { + builder.AppendLine("== 状态栏 =="); + foreach (Effect effect in Effects.Where(e => e.EffectType != EffectType.Item)) + { + builder.Append(effect.ToString()); + } + } + + return builder.ToString(); + } + + /// + /// 获取单位的物品信息 + /// + /// + public new string GetItemInfo(bool showUser = true, bool showGrowth = true, bool showEXP = false) + { + StringBuilder builder = new(); + + builder.AppendLine(showUser ? ToStringWithLevel() : ToStringWithLevelWithOutUser()); + builder.AppendLine($"等级:{Level} / {General.GameplayEquilibriumConstant.MaxLevel}"); + double exHP = ExHP + ExHP2 + ExHP3; + builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "")); + double exMP = ExMP + ExMP2 + ExMP3; + builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); + double exATK = ExATK + ExATK2 + ExATK3; + builder.AppendLine($"攻击力:{ATK:0.##}" + (exATK != 0 ? $" [{BaseATK:0.##} {(exATK >= 0 ? "+" : "-")} {Math.Abs(exATK):0.##}]" : "")); + double exDEF = ExDEF + ExDEF2 + ExDEF3; + builder.AppendLine($"物理护甲:{DEF:0.##}" + (exDEF != 0 ? $" [{BaseDEF:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exDEF):0.##}]" : "") + $" ({PDR * 100:0.##}%)"); + double mdf = Calculation.Round4Digits((MDF.None + MDF.Starmark + MDF.PurityNatural + MDF.PurityContemporary + + MDF.Bright + MDF.Shadow + MDF.Element + MDF.Fleabane + MDF.Particle) / 9) * 100; + if (Calculation.IsApproximatelyZero(mdf)) mdf = 0; + builder.AppendLine($"魔法抗性:{mdf:0.##}%(平均)"); + double exSPD = AGI * General.GameplayEquilibriumConstant.AGItoSPDMultiplier + ExSPD; + builder.AppendLine($"行动速度:{SPD:0.##}" + (exSPD != 0 ? $" [{InitialSPD:0.##} {(exSPD >= 0 ? "+" : "-")} {Math.Abs(exSPD):0.##}]" : "") + $" ({ActionCoefficient * 100:0.##}%)"); + builder.AppendLine($"生命回复:{HR:0.##}" + (ExHR != 0 ? $" [{InitialHR + STR * General.GameplayEquilibriumConstant.STRtoHRFactor:0.##} {(ExHR >= 0 ? "+" : "-")} {Math.Abs(ExHR):0.##}]" : "")); + builder.AppendLine($"魔法回复:{MR:0.##}" + (ExMR != 0 ? $" [{InitialMR + INT * General.GameplayEquilibriumConstant.INTtoMRFactor:0.##} {(ExMR >= 0 ? "+" : "-")} {Math.Abs(ExMR):0.##}]" : "")); + builder.AppendLine($"暴击率:{CritRate * 100:0.##}%"); + builder.AppendLine($"暴击伤害:{CritDMG * 100:0.##}%"); + builder.AppendLine($"闪避率:{EvadeRate * 100:0.##}%"); + builder.AppendLine($"冷却缩减:{CDR * 100:0.##}%"); + builder.AppendLine($"加速系数:{AccelerationCoefficient * 100:0.##}%"); + builder.AppendLine($"物理穿透:{PhysicalPenetration * 100:0.##}%"); + builder.AppendLine($"魔法穿透:{MagicalPenetration * 100:0.##}%"); + + if (EquipSlot.Any()) + { + builder.AppendLine("== 装备栏 =="); + if (EquipSlot.MagicCardPack != null) + { + builder.AppendLine($"[{ItemSet.GetQualityTypeName(EquipSlot.MagicCardPack.QualityType)}]" + ItemSet.GetEquipSlotTypeName(EquipSlotType.MagicCardPack) + ":" + EquipSlot.MagicCardPack.Name); + builder.AppendLine(EquipSlot.MagicCardPack.Description); + } + if (EquipSlot.Weapon != null) + { + builder.AppendLine($"[{ItemSet.GetQualityTypeName(EquipSlot.Weapon.QualityType)}]" + ItemSet.GetEquipSlotTypeName(EquipSlotType.Weapon) + ":" + EquipSlot.Weapon.Name); + builder.AppendLine(EquipSlot.Weapon.Description); + } + if (EquipSlot.Armor != null) + { + builder.AppendLine($"[{ItemSet.GetQualityTypeName(EquipSlot.Armor.QualityType)}]" + ItemSet.GetEquipSlotTypeName(EquipSlotType.Armor) + ":" + EquipSlot.Armor.Name); + builder.AppendLine(EquipSlot.Armor.Description); + } + if (EquipSlot.Shoes != null) + { + builder.AppendLine($"[{ItemSet.GetQualityTypeName(EquipSlot.Shoes.QualityType)}]" + ItemSet.GetEquipSlotTypeName(EquipSlotType.Shoes) + ":" + EquipSlot.Shoes.Name); + builder.AppendLine(EquipSlot.Shoes.Description); + } + if (EquipSlot.Accessory1 != null) + { + builder.AppendLine($"[{ItemSet.GetQualityTypeName(EquipSlot.Accessory1.QualityType)}]" + ItemSet.GetEquipSlotTypeName(EquipSlotType.Accessory1) + ":" + EquipSlot.Accessory1.Name); + builder.AppendLine(EquipSlot.Accessory1.Description); + } + if (EquipSlot.Accessory2 != null) + { + builder.AppendLine($"[{ItemSet.GetQualityTypeName(EquipSlot.Accessory2.QualityType)}]" + ItemSet.GetEquipSlotTypeName(EquipSlotType.Accessory2) + ":" + EquipSlot.Accessory2.Name); + builder.AppendLine(EquipSlot.Accessory2.Description); + } + } + + if (Items.Count > 0) + { + builder.AppendLine("== 单位背包 =="); + foreach (Item item in Items) + { + builder.Append(item.ToString()); + } + } + + /** + * 意义不明(✖)的代码 + */ + if (showGrowth == showEXP) + { + showGrowth.ToString(); + } + + return builder.ToString(); + } + } +} diff --git a/Entity/System/Activity.cs b/Entity/System/Activity.cs new file mode 100644 index 0000000..e471d17 --- /dev/null +++ b/Entity/System/Activity.cs @@ -0,0 +1,122 @@ +using System.Text; +using Milimoe.FunGame.Core.Library.Common.Event; +using Milimoe.FunGame.Core.Library.Constant; + +namespace Milimoe.FunGame.Core.Entity +{ + public class Activity(long id, string name, DateTime startTime, DateTime endTime) + { + public long Id { get; set; } = id; + public string Name { get; set; } = name; + public DateTime StartTime { get; set; } = startTime; + public DateTime EndTime { get; set; } = endTime; + public ActivityState Status { get; private set; } = ActivityState.Future; + public HashSet Quests { get; set; } = []; + + // 事件 + public event Action? UserAccess; + public event Action? UserGetActivityInfo; + + public void UnRegisterUserAccess() + { + UserAccess = null; + } + + public void UnRegisterUserGetActivityInfo() + { + UserGetActivityInfo = null; + } + + public void UpdateState() + { + ActivityState newState; + DateTime now = DateTime.Now; + DateTime upComingTime = StartTime.AddHours(-6); + + if (now < upComingTime) + { + newState = ActivityState.Future; + } + else if (now >= upComingTime && now < StartTime) + { + newState = ActivityState.Upcoming; + } + else if (now >= StartTime && now < EndTime) + { + newState = ActivityState.InProgress; + } + else + { + newState = ActivityState.Ended; + } + + if (Status != newState) + { + Status = newState; + foreach (Quest quest in Quests) + { + if (newState == ActivityState.InProgress) + { + if (quest.Status == QuestState.NotStarted && quest.QuestType == QuestType.Progressive) + { + quest.Status = QuestState.InProgress; + } + } + else if (newState == ActivityState.Ended) + { + if (quest.Status == QuestState.NotStarted || quest.Status == QuestState.InProgress) + { + quest.Status = QuestState.Missed; + } + } + } + } + } + + public bool AllowUserAccess(long userId, long questId = 0) + { + UpdateState(); + ActivityEventArgs args = new(userId, questId, this); + UserAccess?.Invoke(args); + return args.AllowAccess; + } + + public void GetActivityInfo(long userId, long questId = 0) + { + UpdateState(); + ActivityEventArgs args = new(userId, questId, this); + UserGetActivityInfo?.Invoke(args); + } + + public string ToString(bool showQuests) + { + UpdateState(); + StringBuilder builder = new(); + + builder.AppendLine($"☆--- [{Name}] ---☆"); + string status = Status switch + { + ActivityState.Future => "预告中", + ActivityState.Upcoming => "即将开始", + ActivityState.InProgress => "进行中", + _ => "已结束" + }; + builder.AppendLine($"活动状态:{status}"); + builder.AppendLine($"开始时间:{StartTime.ToString(General.GeneralDateTimeFormatChinese)}"); + builder.AppendLine($"结束时间:{EndTime.ToString(General.GeneralDateTimeFormatChinese)}"); + + if (showQuests && Quests.Count > 0) + { + builder.AppendLine("=== 任务列表 ==="); + builder.AppendLine(string.Join("\r\n", Quests)); + } + + return builder.ToString().Trim(); + } + + public override string ToString() + { + return ToString(true); + } + } +} diff --git a/Entity/System/Quest.cs b/Entity/System/Quest.cs index b754f56..1d225ac 100644 --- a/Entity/System/Quest.cs +++ b/Entity/System/Quest.cs @@ -13,7 +13,26 @@ namespace Milimoe.FunGame.Core.Entity public double MaterialsAward { get; set; } = 0; public HashSet Awards { get; set; } = []; public Dictionary AwardsCount { get; set; } = []; - public string AwardsString { get; set; } = ""; + public string AwardsString + { + get + { + List awards = []; + if (CreditsAward > 0) + { + awards.Add($"{General.GameplayEquilibriumConstant.InGameCurrency} * {CreditsAward}"); + } + if (MaterialsAward > 0) + { + awards.Add($"{General.GameplayEquilibriumConstant.InGameMaterial} * {MaterialsAward}"); + } + foreach (Item item in Awards) + { + awards.Add($"[{ItemSet.GetQualityTypeName(item.QualityType)}|{ItemSet.GetItemTypeName(item.ItemType)}] {item.Name} * {AwardsCount[item.Name]}"); + } + return string.Join(",", awards); + } + } public DateTime? StartTime { get; set; } = null; public DateTime? SettleTime { get; set; } = null; public QuestType QuestType { get; set; } = QuestType.Continuous; @@ -29,21 +48,6 @@ namespace Milimoe.FunGame.Core.Entity progressString = $"\r\n当前进度:{Progress}/{MaxProgress}"; } - List awards = []; - if (CreditsAward > 0) - { - awards.Add($"{General.GameplayEquilibriumConstant.InGameCurrency} * {CreditsAward}"); - } - if (MaterialsAward > 0) - { - awards.Add($"{General.GameplayEquilibriumConstant.InGameMaterial} * {MaterialsAward}"); - } - foreach (Item item in Awards) - { - awards.Add($"[{ItemSet.GetQualityTypeName(item.QualityType)}|{ItemSet.GetItemTypeName(item.ItemType)}] {item.Name} * {AwardsCount[item.Name]}"); - } - AwardsString = string.Join(",", awards); - return $"{Id}. {Name}\r\n" + $"{Description}\r\n" + (QuestType == QuestType.Continuous ? $"需要时间:{EstimatedMinutes} 分钟\r\n" : "") + @@ -53,24 +57,13 @@ namespace Milimoe.FunGame.Core.Entity + "\r\n" : "") + $"完成奖励:{AwardsString}\r\n" + - $"任务状态:{GetStatus()}" + progressString + + $"任务状态:{CommonSet.GetQuestStatus(Status)}" + progressString + (SettleTime.HasValue ? $"\r\n结算时间:{SettleTime.Value.ToString(General.GeneralDateTimeFormatChinese)}" : ""); } - private string GetStatus() - { - return Status switch - { - QuestState.InProgress => "进行中", - QuestState.Completed => "已完成", - QuestState.Settled => "已结算", - _ => "未开始" - }; - } - public override bool Equals(IBaseEntity? other) { - return other is Quest && other.Id == Id; + return other is Quest && other.GetIdName() == GetIdName(); } } } diff --git a/Library/Common/Event/SendTalkEventArgs.cs b/Library/Common/Event/SendTalkEventArgs.cs index 2aef9c0..7388751 100644 --- a/Library/Common/Event/SendTalkEventArgs.cs +++ b/Library/Common/Event/SendTalkEventArgs.cs @@ -1,12 +1,7 @@ namespace Milimoe.FunGame.Core.Library.Common.Event { - public class SendTalkEventArgs : GeneralEventArgs + public class SendTalkEventArgs(string message = "") : GeneralEventArgs { - public string Message { get; set; } = ""; - - public SendTalkEventArgs(string message = "") - { - this.Message = message; - } + public string Message { get; set; } = message; } } diff --git a/Library/Common/Event/UserActivityEventArgs.cs b/Library/Common/Event/UserActivityEventArgs.cs index d8786a5..7f12986 100644 --- a/Library/Common/Event/UserActivityEventArgs.cs +++ b/Library/Common/Event/UserActivityEventArgs.cs @@ -1,13 +1,16 @@ -using Milimoe.FunGame.Core.Library.Constant; +using Milimoe.FunGame.Core.Entity; +using Milimoe.FunGame.Core.Library.Constant; namespace Milimoe.FunGame.Core.Library.Common.Event { - public class UserActivityEventArgs(long userId, ActivityState activityState, DateTime startTime, DateTime endTime) : GeneralEventArgs + public class ActivityEventArgs(long userId, long questId, Activity activity) : EventArgs { public long UserId { get; } = userId; - public ActivityState ActivityState { get; } = activityState; - public DateTime StartTime { get; } = startTime; - public DateTime EndTime { get; } = endTime; + public long QuestId { get; } = questId; + public Activity Activity { get; } = activity; + public ActivityState ActivityState { get; } = activity.Status; + public DateTime StartTime { get; } = activity.StartTime; + public DateTime EndTime { get; } = activity.EndTime; public bool AllowAccess { get; set; } = false; } } diff --git a/Library/Constant/ConstantSet.cs b/Library/Constant/ConstantSet.cs index 1e6dcb0..9c53918 100644 --- a/Library/Constant/ConstantSet.cs +++ b/Library/Constant/ConstantSet.cs @@ -18,6 +18,18 @@ namespace Milimoe.FunGame.Core.Library.Constant _ => "I/" }; } + + public static string GetQuestStatus(QuestState status) + { + return status switch + { + QuestState.InProgress => "进行中", + QuestState.Completed => "已完成", + QuestState.Settled => "已结算", + QuestState.Missed => "未完成", + _ => "未开始" + }; + } } /// diff --git a/Library/Constant/StateEnum.cs b/Library/Constant/StateEnum.cs index db67c8e..49094ad 100644 --- a/Library/Constant/StateEnum.cs +++ b/Library/Constant/StateEnum.cs @@ -92,7 +92,8 @@ namespace Milimoe.FunGame.Core.Library.Constant NotStarted, InProgress, Completed, - Settled + Settled, + Missed } public enum ActivityState diff --git a/Model/EventCenter.cs b/Model/EventCenter.cs new file mode 100644 index 0000000..b463ead --- /dev/null +++ b/Model/EventCenter.cs @@ -0,0 +1,134 @@ +using Milimoe.FunGame.Core.Entity; +using Milimoe.FunGame.Core.Library.Common.Event; + +namespace Milimoe.FunGame.Core.Model +{ + public class EventCenter + { + public static EventCenter Instance { get; } = new(); + + public Dictionary> Events { get; } = []; + + public Dictionary Stores { get; set; } = []; + + public HashSet this[string name] + { + get + { + if (Events.TryGetValue(name, out HashSet? activities) && activities != null) + { + return activities; + } + return []; + } + set + { + AddOrUpdateEvent(name, value); + } + } + + public Activity? GetActivity(string eventName, string activityName) + { + if (Events.TryGetValue(eventName, out HashSet? activities) && activities != null && activities.FirstOrDefault(a => a.Name == activityName) is Activity activity) + { + return activity; + } + return null; + } + + public void AddOrUpdateEvent(string name, IEnumerable activities) + { + Events[name] = new(activities); + } + + public bool RemoveEvent(string name) + { + return Events.Remove(name); + } + + public Store? GetStore(string name) + { + if (Stores.TryGetValue(name, out Store? store)) + { + return store; + } + return null; + } + + public void AddOrUpdateStore(string name, Store store) + { + Stores[name] = store; + } + + public bool RemoveStore(string name) + { + return Stores.Remove(name); + } + + public bool AddActivity(string eventName, Activity activity) + { + if (Events.TryGetValue(eventName, out HashSet? activities) && activities != null) + { + return activities.Add(activity); + } + else + { + Events[eventName] = [activity]; + } + return false; + } + + public bool RemoveActivity(string eventName, Activity activity) + { + if (Events.TryGetValue(eventName, out HashSet? activities) && activities != null) + { + return activities.Remove(activity); + } + return false; + } + + public void RegisterUserAccessEventHandler(string eventName, Action handler) + { + if (Events.TryGetValue(eventName, out HashSet? activities) && activities != null) + { + foreach (Activity activity in activities) + { + activity.UserAccess += handler; + } + } + } + + public void RegisterUserGetActivityInfoEventHandler(string eventName, Action handler) + { + if (Events.TryGetValue(eventName, out HashSet? activities) && activities != null) + { + foreach (Activity activity in activities) + { + activity.UserGetActivityInfo += handler; + } + } + } + + public void UnRegisterUserAccess(string eventName) + { + if (Events.TryGetValue(eventName, out HashSet? activities) && activities != null) + { + foreach (Activity activity in activities) + { + activity.UnRegisterUserAccess(); + } + } + } + + public void UnRegisterUserGetActivityInfo(string eventName) + { + if (Events.TryGetValue(eventName, out HashSet? activities) && activities != null) + { + foreach (Activity activity in activities) + { + activity.UnRegisterUserGetActivityInfo(); + } + } + } + } +}