添加活动和活动中心,添加单位,修改任务系统

This commit is contained in:
milimoe 2025-02-07 01:27:54 +08:00
parent 765c89dde6
commit 5a4c8fe196
Signed by: milimoe
GPG Key ID: 05D280912DA6C69E
9 changed files with 783 additions and 43 deletions

View File

@ -8,7 +8,6 @@ namespace Milimoe.FunGame.Core.Entity
/// <summary> /// <summary>
/// 角色需要使用 Factory.Get 的方式来构造,并赋值 <see cref="InitRequired"/> 标记的属性<para /> /// 角色需要使用 Factory.Get 的方式来构造,并赋值 <see cref="InitRequired"/> 标记的属性<para />
/// 在使用时仅需要调用 <see cref="Copy"/> 方法即可获得相同对象<para /> /// 在使用时仅需要调用 <see cref="Copy"/> 方法即可获得相同对象<para />
/// 不建议继承
/// </summary> /// </summary>
public class Character : BaseEntity public class Character : BaseEntity
{ {

481
Entity/Character/Unit.cs Normal file
View File

@ -0,0 +1,481 @@
using System.Text;
using Milimoe.FunGame.Core.Api.Utility;
using Milimoe.FunGame.Core.Library.Constant;
namespace Milimoe.FunGame.Core.Entity
{
/// <summary>
/// <see cref="Unit"/> 是一个用于描述生物的单元对象(单位),而 <see cref="Character"/> 是一种高级单位(单位单位/英雄单位)<para />
/// 和单位一样,使用 <see cref="InitRequired"/> 标记的需要初始赋值的属性<para />
/// </summary>
public class Unit : Character
{
/// <summary>
/// 单位名称
/// </summary>
public override string Name { get; set; } = "";
/// <summary>
/// 获取单位名称以及所属玩家
/// </summary>
/// <returns></returns>
public override string ToString()
{
string str = Name;
if (User != null && User.Username != "")
{
str += "(" + User.Username + ")";
}
return str;
}
/// <summary>
/// 获取单位名称以及所属玩家,包含等级
/// </summary>
/// <returns></returns>
public new string ToStringWithLevel()
{
string str = Name + " - 等级 " + Level;
if (User != null && User.Username != "")
{
str += "" + User.Username + "";
}
return str;
}
/// <summary>
/// 获取单位的详细信息
/// </summary>
/// <returns></returns>
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();
}
/// <summary>
/// 获取单位的简略信息
/// </summary>
/// <returns></returns>
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<EquipSlotType> 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();
}
/// <summary>
/// 获取战斗状态的信息
/// </summary>
/// <param name="hardnessTimes"></param>
/// <returns></returns>
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();
}
/// <summary>
/// 获取战斗状态的信息(简略版)
/// </summary>
/// <param name="hardnessTimes"></param>
/// <returns></returns>
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();
}
/// <summary>
/// 获取单位的技能信息
/// </summary>
/// <returns></returns>
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();
}
/// <summary>
/// 获取单位的物品信息
/// </summary>
/// <returns></returns>
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();
}
}
}

122
Entity/System/Activity.cs Normal file
View File

@ -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<Quest> Quests { get; set; } = [];
// 事件
public event Action<ActivityEventArgs>? UserAccess;
public event Action<ActivityEventArgs>? 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);
}
}
}

View File

@ -13,7 +13,26 @@ namespace Milimoe.FunGame.Core.Entity
public double MaterialsAward { get; set; } = 0; public double MaterialsAward { get; set; } = 0;
public HashSet<Item> Awards { get; set; } = []; public HashSet<Item> Awards { get; set; } = [];
public Dictionary<string, int> AwardsCount { get; set; } = []; public Dictionary<string, int> AwardsCount { get; set; } = [];
public string AwardsString { get; set; } = ""; public string AwardsString
{
get
{
List<string> 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? StartTime { get; set; } = null;
public DateTime? SettleTime { get; set; } = null; public DateTime? SettleTime { get; set; } = null;
public QuestType QuestType { get; set; } = QuestType.Continuous; public QuestType QuestType { get; set; } = QuestType.Continuous;
@ -29,21 +48,6 @@ namespace Milimoe.FunGame.Core.Entity
progressString = $"\r\n当前进度{Progress}/{MaxProgress}"; progressString = $"\r\n当前进度{Progress}/{MaxProgress}";
} }
List<string> 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" + return $"{Id}. {Name}\r\n" +
$"{Description}\r\n" + $"{Description}\r\n" +
(QuestType == QuestType.Continuous ? $"需要时间:{EstimatedMinutes} 分钟\r\n" : "") + (QuestType == QuestType.Continuous ? $"需要时间:{EstimatedMinutes} 分钟\r\n" : "") +
@ -53,24 +57,13 @@ namespace Milimoe.FunGame.Core.Entity
+ "\r\n" + "\r\n"
: "") + : "") +
$"完成奖励:{AwardsString}\r\n" + $"完成奖励:{AwardsString}\r\n" +
$"任务状态:{GetStatus()}" + progressString + $"任务状态:{CommonSet.GetQuestStatus(Status)}" + progressString +
(SettleTime.HasValue ? $"\r\n结算时间{SettleTime.Value.ToString(General.GeneralDateTimeFormatChinese)}" : ""); (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) public override bool Equals(IBaseEntity? other)
{ {
return other is Quest && other.Id == Id; return other is Quest && other.GetIdName() == GetIdName();
} }
} }
} }

View File

@ -1,12 +1,7 @@
namespace Milimoe.FunGame.Core.Library.Common.Event namespace Milimoe.FunGame.Core.Library.Common.Event
{ {
public class SendTalkEventArgs : GeneralEventArgs public class SendTalkEventArgs(string message = "") : GeneralEventArgs
{ {
public string Message { get; set; } = ""; public string Message { get; set; } = message;
public SendTalkEventArgs(string message = "")
{
this.Message = message;
}
} }
} }

View File

@ -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 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 long UserId { get; } = userId;
public ActivityState ActivityState { get; } = activityState; public long QuestId { get; } = questId;
public DateTime StartTime { get; } = startTime; public Activity Activity { get; } = activity;
public DateTime EndTime { get; } = endTime; public ActivityState ActivityState { get; } = activity.Status;
public DateTime StartTime { get; } = activity.StartTime;
public DateTime EndTime { get; } = activity.EndTime;
public bool AllowAccess { get; set; } = false; public bool AllowAccess { get; set; } = false;
} }
} }

View File

@ -18,6 +18,18 @@ namespace Milimoe.FunGame.Core.Library.Constant
_ => "I/" _ => "I/"
}; };
} }
public static string GetQuestStatus(QuestState status)
{
return status switch
{
QuestState.InProgress => "进行中",
QuestState.Completed => "已完成",
QuestState.Settled => "已结算",
QuestState.Missed => "未完成",
_ => "未开始"
};
}
} }
/// <summary> /// <summary>

View File

@ -92,7 +92,8 @@ namespace Milimoe.FunGame.Core.Library.Constant
NotStarted, NotStarted,
InProgress, InProgress,
Completed, Completed,
Settled Settled,
Missed
} }
public enum ActivityState public enum ActivityState

134
Model/EventCenter.cs Normal file
View File

@ -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<string, HashSet<Activity>> Events { get; } = [];
public Dictionary<string, Store> Stores { get; set; } = [];
public HashSet<Activity> this[string name]
{
get
{
if (Events.TryGetValue(name, out HashSet<Activity>? activities) && activities != null)
{
return activities;
}
return [];
}
set
{
AddOrUpdateEvent(name, value);
}
}
public Activity? GetActivity(string eventName, string activityName)
{
if (Events.TryGetValue(eventName, out HashSet<Activity>? activities) && activities != null && activities.FirstOrDefault(a => a.Name == activityName) is Activity activity)
{
return activity;
}
return null;
}
public void AddOrUpdateEvent(string name, IEnumerable<Activity> 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<Activity>? 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<Activity>? activities) && activities != null)
{
return activities.Remove(activity);
}
return false;
}
public void RegisterUserAccessEventHandler(string eventName, Action<ActivityEventArgs> handler)
{
if (Events.TryGetValue(eventName, out HashSet<Activity>? activities) && activities != null)
{
foreach (Activity activity in activities)
{
activity.UserAccess += handler;
}
}
}
public void RegisterUserGetActivityInfoEventHandler(string eventName, Action<ActivityEventArgs> handler)
{
if (Events.TryGetValue(eventName, out HashSet<Activity>? activities) && activities != null)
{
foreach (Activity activity in activities)
{
activity.UserGetActivityInfo += handler;
}
}
}
public void UnRegisterUserAccess(string eventName)
{
if (Events.TryGetValue(eventName, out HashSet<Activity>? activities) && activities != null)
{
foreach (Activity activity in activities)
{
activity.UnRegisterUserAccess();
}
}
}
public void UnRegisterUserGetActivityInfo(string eventName)
{
if (Events.TryGetValue(eventName, out HashSet<Activity>? activities) && activities != null)
{
foreach (Activity activity in activities)
{
activity.UnRegisterUserGetActivityInfo();
}
}
}
}
}