添加任务计划;添加复制物品、技能新增复制选项 (#102)

* 添加任务计划

* 复制物品、技能新增复制选项;修改游戏平衡常数

* 更新游戏平衡常数

---------

Co-authored-by: yeziuku <53083103+yeziuku@users.noreply.github.com>
This commit is contained in:
milimoe 2024-12-15 16:37:57 +08:00 committed by GitHub
parent a485e8d588
commit a6d8b71829
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 280 additions and 63 deletions

View File

@ -0,0 +1,129 @@
using Milimoe.FunGame.Core.Model;
namespace Milimoe.FunGame.Core.Api.Utility
{
public class TaskScheduler
{
/// <summary>
/// 任务计划管理器实例,可以直接使用
/// </summary>
public static TaskScheduler Shared { get; } = new();
private readonly List<ScheduledTask> _tasks = [];
private readonly List<RecurringTask> _recurringTasks = [];
private readonly Timer _timer;
private readonly Lock _lock = new();
/// <summary>
/// 创建一个轻量级的任务计划管理器
/// </summary>
public TaskScheduler()
{
_timer = new Timer(CheckAndRunTasks, null, TimeSpan.Zero, TimeSpan.FromSeconds(1));
_timer.Change(TimeSpan.Zero, TimeSpan.FromSeconds(1));
}
/// <summary>
/// 添加一个任务计划
/// </summary>
/// <param name="name"></param>
/// <param name="timeOfDay"></param>
/// <param name="action"></param>
public void AddTask(string name, TimeSpan timeOfDay, Action action)
{
lock (_lock)
{
_tasks.Add(new ScheduledTask(name, timeOfDay, action));
}
}
/// <summary>
/// 添加一个循环任务
/// </summary>
/// <param name="name"></param>
/// <param name="interval"></param>
/// <param name="action"></param>
/// <param name="startNow"></param>
public void AddRecurringTask(string name, TimeSpan interval, Action action, bool startNow = false)
{
lock (_lock)
{
DateTime now = DateTime.Now;
now = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, 0);
DateTime nextRun = startNow ? now : now.Add(interval);
RecurringTask recurringTask = new(name, interval, action)
{
NextRun = nextRun
};
_recurringTasks.Add(recurringTask);
}
}
/// <summary>
/// 移除任务计划
/// </summary>
/// <param name="name"></param>
public void RemoveTask(string name)
{
lock (_lock)
{
int removeTasks = _tasks.RemoveAll(t => t.Name == name);
int removeRecurringTasks = _recurringTasks.RemoveAll(t => t.Name == name);
}
}
/// <summary>
/// 执行任务
/// </summary>
/// <param name="state"></param>
private void CheckAndRunTasks(object? state)
{
lock (_lock)
{
DateTime now = DateTime.Now;
foreach (ScheduledTask task in _tasks)
{
if (!task.IsTodayRun)
{
if (now.TimeOfDay >= task.TimeOfDay && now.TimeOfDay < task.TimeOfDay.Add(TimeSpan.FromSeconds(10)))
{
task.LastRun = now;
ThreadPool.QueueUserWorkItem(_ =>
{
try
{
task.Action();
}
catch (Exception ex)
{
task.Error = ex;
}
});
}
}
}
foreach (RecurringTask recurringTask in _recurringTasks)
{
if (now >= recurringTask.NextRun)
{
recurringTask.LastRun = now;
recurringTask.NextRun = recurringTask.NextRun.Add(recurringTask.Interval);
ThreadPool.QueueUserWorkItem(_ =>
{
try
{
recurringTask.Action();
}
catch (Exception ex)
{
recurringTask.Error = ex;
}
});
}
}
}
}
}
}

View File

@ -1239,8 +1239,8 @@ namespace Milimoe.FunGame.Core.Entity
builder.AppendLine($"力量:{STR:0.##}" + (ExSTR != 0 ? $" [{BaseSTR:0.##} {(ExSTR >= 0 ? "+" : "-")} {Math.Abs(ExSTR):0.##}]" : "") + (showGrowth ? $"{(STRGrowth >= 0 ? "+" : "-")}{Math.Abs(STRGrowth)}/Lv" : "")); builder.AppendLine($"力量:{STR:0.##}" + (ExSTR != 0 ? $" [{BaseSTR:0.##} {(ExSTR >= 0 ? "+" : "-")} {Math.Abs(ExSTR):0.##}]" : "") + (showGrowth ? $"{(STRGrowth >= 0 ? "+" : "-")}{Math.Abs(STRGrowth)}/Lv" : ""));
builder.AppendLine($"敏捷:{AGI:0.##}" + (ExAGI != 0 ? $" [{BaseAGI:0.##} {(ExAGI >= 0 ? "+" : "-")} {Math.Abs(ExAGI):0.##}]" : "") + (showGrowth ? $"{(AGIGrowth >= 0 ? "+" : "-")}{Math.Abs(AGIGrowth)}/Lv" : "")); builder.AppendLine($"敏捷:{AGI:0.##}" + (ExAGI != 0 ? $" [{BaseAGI:0.##} {(ExAGI >= 0 ? "+" : "-")} {Math.Abs(ExAGI):0.##}]" : "") + (showGrowth ? $"{(AGIGrowth >= 0 ? "+" : "-")}{Math.Abs(AGIGrowth)}/Lv" : ""));
builder.AppendLine($"智力:{INT:0.##}" + (ExINT != 0 ? $" [{BaseINT:0.##} {(ExINT >= 0 ? "+" : "-")} {Math.Abs(ExINT):0.##}]" : "") + (showGrowth ? $"{(INTGrowth >= 0 ? "+" : "-")}{Math.Abs(INTGrowth)}/Lv" : "")); builder.AppendLine($"智力:{INT:0.##}" + (ExINT != 0 ? $" [{BaseINT:0.##} {(ExINT >= 0 ? "+" : "-")} {Math.Abs(ExINT):0.##}]" : "") + (showGrowth ? $"{(INTGrowth >= 0 ? "+" : "-")}{Math.Abs(INTGrowth)}/Lv" : ""));
builder.AppendLine($"生命回复:{HR:0.##}" + (ExHR != 0 ? $" [{InitialHR + STR * 0.25:0.##} {(ExHR >= 0 ? "+" : "-")} {Math.Abs(ExHR):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 * 0.1:0.##} {(ExMR >= 0 ? "+" : "-")} {Math.Abs(ExMR):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($"暴击率:{CritRate * 100:0.##}%");
builder.AppendLine($"暴击伤害:{CritDMG * 100:0.##}%"); builder.AppendLine($"暴击伤害:{CritDMG * 100:0.##}%");
builder.AppendLine($"闪避率:{EvadeRate * 100:0.##}%"); builder.AppendLine($"闪避率:{EvadeRate * 100:0.##}%");
@ -1362,8 +1362,8 @@ namespace Milimoe.FunGame.Core.Entity
builder.AppendLine($"力量:{STR:0.##}" + (ExSTR != 0 ? $" [{BaseSTR:0.##} {(ExSTR >= 0 ? "+" : "-")} {Math.Abs(ExSTR):0.##}]" : "") + (showGrowth ? $"{(STRGrowth >= 0 ? "+" : "-")}{Math.Abs(STRGrowth)}/Lv" : "")); builder.AppendLine($"力量:{STR:0.##}" + (ExSTR != 0 ? $" [{BaseSTR:0.##} {(ExSTR >= 0 ? "+" : "-")} {Math.Abs(ExSTR):0.##}]" : "") + (showGrowth ? $"{(STRGrowth >= 0 ? "+" : "-")}{Math.Abs(STRGrowth)}/Lv" : ""));
builder.AppendLine($"敏捷:{AGI:0.##}" + (ExAGI != 0 ? $" [{BaseAGI:0.##} {(ExAGI >= 0 ? "+" : "-")} {Math.Abs(ExAGI):0.##}]" : "") + (showGrowth ? $"{(AGIGrowth >= 0 ? "+" : "-")}{Math.Abs(AGIGrowth)}/Lv" : "")); builder.AppendLine($"敏捷:{AGI:0.##}" + (ExAGI != 0 ? $" [{BaseAGI:0.##} {(ExAGI >= 0 ? "+" : "-")} {Math.Abs(ExAGI):0.##}]" : "") + (showGrowth ? $"{(AGIGrowth >= 0 ? "+" : "-")}{Math.Abs(AGIGrowth)}/Lv" : ""));
builder.AppendLine($"智力:{INT:0.##}" + (ExINT != 0 ? $" [{BaseINT:0.##} {(ExINT >= 0 ? "+" : "-")} {Math.Abs(ExINT):0.##}]" : "") + (showGrowth ? $"{(INTGrowth >= 0 ? "+" : "-")}{Math.Abs(INTGrowth)}/Lv" : "")); builder.AppendLine($"智力:{INT:0.##}" + (ExINT != 0 ? $" [{BaseINT:0.##} {(ExINT >= 0 ? "+" : "-")} {Math.Abs(ExINT):0.##}]" : "") + (showGrowth ? $"{(INTGrowth >= 0 ? "+" : "-")}{Math.Abs(INTGrowth)}/Lv" : ""));
builder.AppendLine($"生命回复:{HR:0.##}" + (ExHR != 0 ? $" [{InitialHR + STR * 0.25:0.##} {(ExHR >= 0 ? "+" : "-")} {Math.Abs(ExHR):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 * 0.1:0.##} {(ExMR >= 0 ? "+" : "-")} {Math.Abs(ExMR):0.##}]" : "")); builder.AppendLine($"魔法回复:{MR:0.##}" + (ExMR != 0 ? $" [{InitialMR + INT * General.GameplayEquilibriumConstant.INTtoMRFactor:0.##} {(ExMR >= 0 ? "+" : "-")} {Math.Abs(ExMR):0.##}]" : ""));
if (CharacterState != CharacterState.Actionable) if (CharacterState != CharacterState.Actionable)
{ {

View File

@ -102,8 +102,10 @@ namespace Milimoe.FunGame.Core.Entity
/// <param name="items"></param> /// <param name="items"></param>
/// <param name="newItemGuid"></param> /// <param name="newItemGuid"></param>
/// <param name="equips"></param> /// <param name="equips"></param>
/// <param name="itemsDefined"></param>
/// <param name="skillsDefined"></param>
/// <returns>构建的新角色</returns> /// <returns>构建的新角色</returns>
public Character Build(int level, IEnumerable<Skill> skills, IEnumerable<Item> items, bool newItemGuid = true, EquipSlot? equips = null) public Character Build(int level, IEnumerable<Skill> skills, IEnumerable<Item> items, bool newItemGuid = true, EquipSlot? equips = null, IEnumerable<Item>? itemsDefined = null, IEnumerable<Skill>? skillsDefined = null)
{ {
Character character = Factory.GetCharacter(); Character character = Factory.GetCharacter();
character.Id = Id; character.Id = Id;
@ -133,7 +135,7 @@ namespace Milimoe.FunGame.Core.Entity
// 主动技能的Guid表示与其关联的物品 // 主动技能的Guid表示与其关联的物品
if (skill.Guid == Guid.Empty) if (skill.Guid == Guid.Empty)
{ {
Skill newskill = skill.Copy(); Skill newskill = skill.Copy(true, skillsDefined);
newskill.Character = character; newskill.Character = character;
newskill.Level = skill.Level; newskill.Level = skill.Level;
if (skill.CurrentCD > 0 && !skill.Enable) if (skill.CurrentCD > 0 && !skill.Enable)
@ -146,7 +148,16 @@ namespace Milimoe.FunGame.Core.Entity
} }
foreach (Item item in items) foreach (Item item in items)
{ {
Item newitem = item.Copy(true, !newItemGuid); Item newitem;
if (itemsDefined != null && itemsDefined.FirstOrDefault(i => i.GetIdName() == item.GetIdName()) is Item itemDefined)
{
newitem = itemDefined.Copy(true, !newItemGuid, true, itemsDefined, skillsDefined);
item.SetPropertyToItemModuleNew(newitem);
}
else
{
newitem = item.Copy(true, !newItemGuid, true, itemsDefined, skillsDefined);
}
newitem.Character = character; newitem.Character = character;
character.Items.Add(newitem); character.Items.Add(newitem);
} }
@ -160,32 +171,32 @@ namespace Milimoe.FunGame.Core.Entity
Item? ac2 = equips.Accessory2; Item? ac2 = equips.Accessory2;
if (mcp != null) if (mcp != null)
{ {
mcp = mcp.Copy(true, !newItemGuid); mcp = mcp.Copy(true, !newItemGuid, true, itemsDefined, skillsDefined);
character.Equip(mcp); character.Equip(mcp);
} }
if (w != null) if (w != null)
{ {
w = w.Copy(true, !newItemGuid); w = w.Copy(true, !newItemGuid, true, itemsDefined, skillsDefined);
character.Equip(w); character.Equip(w);
} }
if (a != null) if (a != null)
{ {
a = a.Copy(true, !newItemGuid); a = a.Copy(true, !newItemGuid, true, itemsDefined, skillsDefined);
character.Equip(a); character.Equip(a);
} }
if (s != null) if (s != null)
{ {
s = s.Copy(true, !newItemGuid); s = s.Copy(true, !newItemGuid, true, itemsDefined, skillsDefined);
character.Equip(s); character.Equip(s);
} }
if (ac1 != null) if (ac1 != null)
{ {
ac1 = ac1.Copy(true, !newItemGuid); ac1 = ac1.Copy(true, !newItemGuid, true, itemsDefined, skillsDefined);
character.Equip(ac1); character.Equip(ac1);
} }
if (ac2 != null) if (ac2 != null)
{ {
ac2 = ac2.Copy(true, !newItemGuid); ac2 = ac2.Copy(true, !newItemGuid, true, itemsDefined, skillsDefined);
character.Equip(ac2); character.Equip(ac2);
} }
} }
@ -199,10 +210,12 @@ namespace Milimoe.FunGame.Core.Entity
/// </summary> /// </summary>
/// <param name="reference"></param> /// <param name="reference"></param>
/// <param name="newItemGuid"></param> /// <param name="newItemGuid"></param>
/// <param name="itemsDefined">对于动态扩展的物品而言,传入已定义的物品表,不使用被复制物品的数据</param>
/// <param name="skillsDefined">对于动态扩展的技能而言,传入已定义的技能表,不使用被复制技能的数据</param>
/// <returns>构建的新角色</returns> /// <returns>构建的新角色</returns>
public static Character Build(Character reference, bool newItemGuid = true) public static Character Build(Character reference, bool newItemGuid = true, IEnumerable<Item>? itemsDefined = null, IEnumerable<Skill>? skillsDefined = null)
{ {
Character character = new CharacterBuilder(reference).Build(reference.Level, reference.Skills, reference.Items, newItemGuid, reference.EquipSlot); Character character = new CharacterBuilder(reference).Build(reference.Level, reference.Skills, reference.Items, newItemGuid, reference.EquipSlot, itemsDefined, skillsDefined);
character.NormalAttack.Level = reference.Level; character.NormalAttack.Level = reference.Level;
character.NormalAttack.SetMagicType(reference.NormalAttack.IsMagic, reference.NormalAttack.MagicType); character.NormalAttack.SetMagicType(reference.NormalAttack.IsMagic, reference.NormalAttack.MagicType);
return character; return character;

View File

@ -549,48 +549,46 @@ namespace Milimoe.FunGame.Core.Entity
newbyFactory.WeaponType = WeaponType; newbyFactory.WeaponType = WeaponType;
newbyFactory.EquipSlotType = EquipSlotType; newbyFactory.EquipSlotType = EquipSlotType;
newbyFactory.Equipable = Equipable; newbyFactory.Equipable = Equipable;
newbyFactory.Unequipable = Unequipable;
newbyFactory.IsPurchasable = IsPurchasable; newbyFactory.IsPurchasable = IsPurchasable;
newbyFactory.Price = Price; newbyFactory.Price = Price;
newbyFactory.IsSellable = IsSellable; newbyFactory.IsSellable = IsSellable;
newbyFactory.NextSellableTime = NextSellableTime; newbyFactory.NextSellableTime = NextSellableTime;
newbyFactory.IsTradable = IsTradable; newbyFactory.IsTradable = IsTradable;
newbyFactory.NextTradableTime = NextTradableTime; newbyFactory.NextTradableTime = NextTradableTime;
newbyFactory.RemainUseTimes = RemainUseTimes;
} }
/// <summary> /// <summary>
/// 复制一个物品 /// 复制一个物品
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public Item Copy(bool copyLevel = false, bool copyGuid = false) public Item Copy(bool copyLevel = false, bool copyGuid = false, bool copyProperty = true, IEnumerable<Item>? itemsDefined = null, IEnumerable<Skill>? skillsDefined = null)
{ {
Item item = Factory.OpenFactory.GetInstance<Item>(Id, Name, []); Item item = Factory.OpenFactory.GetInstance<Item>(Id, Name, []);
SetPropertyToItemModuleNew(item); Item? itemDefined = null;
item.Id = Id; if (itemsDefined != null && itemsDefined.FirstOrDefault(i => i.GetIdName() == item.GetIdName()) is Item temp)
item.Name = Name; {
itemDefined = temp;
}
if (copyProperty) SetPropertyToItemModuleNew(item);
if (copyGuid) item.Guid = Guid; if (copyGuid) item.Guid = Guid;
item.Description = Description; itemDefined ??= this;
item.GeneralDescription = GeneralDescription; item.Id = itemDefined.Id;
item.BackgroundStory = BackgroundStory; item.Name = itemDefined.Name;
item.ItemType = ItemType; item.Description = itemDefined.Description;
item.Equipable = Equipable; item.GeneralDescription = itemDefined.GeneralDescription;
item.Unequipable = Unequipable; item.BackgroundStory = itemDefined.BackgroundStory;
item.WeaponType = WeaponType; item.ItemType = itemDefined.ItemType;
item.QualityType = QualityType; item.QualityType = itemDefined.QualityType;
item.RarityType = RarityType; item.RarityType = itemDefined.RarityType;
item.RankType = RankType; item.RankType = itemDefined.RankType;
item.Key = Key; item.Key = itemDefined.Key;
item.Enable = Enable; item.Enable = itemDefined.Enable;
item.IsInGameItem = IsInGameItem; item.IsInGameItem = itemDefined.IsInGameItem;
item.IsPurchasable = IsPurchasable;
item.Price = Price;
item.IsSellable = IsSellable;
item.NextSellableTime = NextSellableTime;
item.IsTradable = IsTradable;
item.NextTradableTime = NextTradableTime;
item.RemainUseTimes = RemainUseTimes;
if (item is OpenItem) if (item is OpenItem)
{ {
item.Skills.Active = Skills.Active?.Copy(); item.Skills.Active = Skills.Active?.Copy(true, skillsDefined);
if (item.Skills.Active != null) if (item.Skills.Active != null)
{ {
item.Skills.Active.Level = copyLevel ? (Skills.Active?.Level ?? 1) : 1; item.Skills.Active.Level = copyLevel ? (Skills.Active?.Level ?? 1) : 1;
@ -598,7 +596,7 @@ namespace Milimoe.FunGame.Core.Entity
} }
foreach (Skill skill in Skills.Passives) foreach (Skill skill in Skills.Passives)
{ {
Skill newskill = skill.Copy(); Skill newskill = skill.Copy(true, skillsDefined);
newskill.Item = item; newskill.Item = item;
newskill.Level = copyLevel ? skill.Level : 1; newskill.Level = copyLevel ? skill.Level : 1;
newskill.Guid = item.Guid; newskill.Guid = item.Guid;
@ -606,7 +604,7 @@ namespace Milimoe.FunGame.Core.Entity
} }
foreach (Skill skill in Skills.Magics) foreach (Skill skill in Skills.Magics)
{ {
Skill newskill = skill.Copy(); Skill newskill = skill.Copy(true, skillsDefined);
newskill.Item = item; newskill.Item = item;
newskill.Level = copyLevel ? skill.Level : 1; newskill.Level = copyLevel ? skill.Level : 1;
newskill.Guid = item.Guid; newskill.Guid = item.Guid;
@ -638,10 +636,6 @@ namespace Milimoe.FunGame.Core.Entity
/// <param name="level"></param> /// <param name="level"></param>
public void SetMagicsLevel(int level) public void SetMagicsLevel(int level)
{ {
if (Skills.Active != null)
{
Skills.Active.Level = level;
}
foreach (Skill skill in Skills.Magics) foreach (Skill skill in Skills.Magics)
{ {
skill.Level = level; skill.Level = level;

View File

@ -240,6 +240,7 @@ namespace Milimoe.FunGame.Core.Entity
/// <param name="newbyFactory"></param> /// <param name="newbyFactory"></param>
public void SetPropertyToItemModuleNew(Skill newbyFactory) public void SetPropertyToItemModuleNew(Skill newbyFactory)
{ {
newbyFactory.GamingQueue = GamingQueue;
newbyFactory.Enable = Enable; newbyFactory.Enable = Enable;
newbyFactory.IsInEffect = IsInEffect; newbyFactory.IsInEffect = IsInEffect;
newbyFactory.CurrentCD = CurrentCD; newbyFactory.CurrentCD = CurrentCD;
@ -452,26 +453,35 @@ namespace Milimoe.FunGame.Core.Entity
/// 复制一个技能 /// 复制一个技能
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public Skill Copy() public Skill Copy(bool copyProperty = true, IEnumerable<Skill>? skillsDefined = null)
{ {
Dictionary<string, object> args = new() Dictionary<string, object> args = new()
{ {
{ "values", Values } { "values", Values }
}; };
Skill? skillDefined = null;
if (skillsDefined != null && skillsDefined.FirstOrDefault(i => i.GetIdName() == GetIdName()) is Skill temp)
{
skillDefined = temp;
}
if (skillDefined != null)
{
args["values"] = skillDefined.Values;
}
Skill skill = Factory.OpenFactory.GetInstance<Skill>(Id, Name, args); Skill skill = Factory.OpenFactory.GetInstance<Skill>(Id, Name, args);
SetPropertyToItemModuleNew(skill); skillDefined ??= skill;
skill.Id = Id; if (copyProperty) SetPropertyToItemModuleNew(skill);
skill.Name = Name; skill.Id = skillDefined.Id;
skill.Description = Description; skill.Name = skillDefined.Name;
skill.GeneralDescription = GeneralDescription; skill.Description = skillDefined.Description;
skill.SkillType = SkillType; skill.GeneralDescription = skillDefined.GeneralDescription;
skill.MPCost = MPCost; skill.SkillType = skillDefined.SkillType;
skill.CastTime = CastTime; skill.MPCost = skillDefined.MPCost;
skill.EPCost = EPCost; skill.CastTime = skillDefined.CastTime;
skill.CD = CD; skill.EPCost = skillDefined.EPCost;
skill.CurrentCD = CurrentCD; skill.CD = skillDefined.CD;
skill.HardnessTime = HardnessTime; skill.HardnessTime = skillDefined.HardnessTime;
skill.GamingQueue = GamingQueue; skill.GamingQueue = skillDefined.GamingQueue;
if (skill is OpenSkill) if (skill is OpenSkill)
{ {
foreach (Effect e in Effects) foreach (Effect e in Effects)

View File

@ -684,6 +684,7 @@ namespace Milimoe.FunGame.Core.Model
} }
else else
{ {
decided = true;
WriteLine("[ " + character + $" ] 完全行动不能!"); WriteLine("[ " + character + $" ] 完全行动不能!");
type = CharacterActionType.None; type = CharacterActionType.None;
} }
@ -1639,7 +1640,7 @@ namespace Milimoe.FunGame.Core.Model
foreach (Character caster in castingSkills) foreach (Character caster in castingSkills)
{ {
SkillTarget st = _castingSkills[caster]; SkillTarget st = _castingSkills[caster];
if (st.Targets.Remove(death) && st.Targets.Count == 0) if (st.Targets.Remove(death))
{ {
_castingSkills.Remove(caster); _castingSkills.Remove(caster);
if (caster.CharacterState == CharacterState.Casting) if (caster.CharacterState == CharacterState.Casting)

View File

@ -203,7 +203,7 @@
/// <summary> /// <summary>
/// 每 1 点力量增加生命回复力 /// 每 1 点力量增加生命回复力
/// </summary> /// </summary>
public double STRtoHRFactor { get; set; } = 0.25; public double STRtoHRFactor { get; set; } = 0.025;
/// <summary> /// <summary>
/// 每 1 点力量增加物理护甲 /// 每 1 点力量增加物理护甲
@ -228,7 +228,7 @@
/// <summary> /// <summary>
/// 每 1 点智力增加魔法回复力 /// 每 1 点智力增加魔法回复力
/// </summary> /// </summary>
public double INTtoMRFactor { get; set; } = 0.1; public double INTtoMRFactor { get; set; } = 0.01;
/// <summary> /// <summary>
/// 每 1 点智力减少魔法消耗 /// 每 1 点智力减少魔法消耗

35
Model/RecurringTask.cs Normal file
View File

@ -0,0 +1,35 @@
namespace Milimoe.FunGame.Core.Model
{
public class RecurringTask(string name, TimeSpan interval, Action action)
{
/// <summary>
/// 任务名称
/// </summary>
public string Name { get; set; } = name;
/// <summary>
/// 循环执行间隔
/// </summary>
public TimeSpan Interval { get; set; } = interval;
/// <summary>
/// 任务执行逻辑
/// </summary>
public Action Action { get; set; } = action;
/// <summary>
/// 记录上一次运行时间
/// </summary>
public DateTime? LastRun { get; set; } = null;
/// <summary>
/// 记录下一次运行时间
/// </summary>
public DateTime NextRun { get; set; } = DateTime.MaxValue;
/// <summary>
/// 最后一次运行时发生的错误
/// </summary>
public Exception? Error { get; set; }
}
}

35
Model/ScheduledTask.cs Normal file
View File

@ -0,0 +1,35 @@
namespace Milimoe.FunGame.Core.Model
{
public class ScheduledTask(string name, TimeSpan timeSpan, Action action)
{
/// <summary>
/// 任务名称
/// </summary>
public string Name { get; set; } = name;
/// <summary>
/// 每天的目标时间
/// </summary>
public TimeSpan TimeOfDay { get; set; } = timeSpan;
/// <summary>
/// 任务执行逻辑
/// </summary>
public Action Action { get; set; } = action;
/// <summary>
/// 记录上一次运行时间
/// </summary>
public DateTime? LastRun { get; set; } = null;
/// <summary>
/// 当天是否已经运行
/// </summary>
public bool IsTodayRun => LastRun.HasValue && LastRun.Value.Date == DateTime.Today;
/// <summary>
/// 最后一次运行时发生的错误
/// </summary>
public Exception? Error { get; set; }
}
}