mirror of
https://github.com/project-redbud/FunGame-Core.git
synced 2025-04-22 03:59:35 +08:00
动态工厂可以构造主动技能了;完善技能底层选取逻辑;团队模式完善;优化回合日志 (#99)
* 修复诸多复活角色的问题;添加了更多回合记录 * 完善了底层技能选取目标方法;添加筛选条件列表,使技能能够灵活的选取角色 * 优化死亡结算的逻辑;优化回合记录日志 * 现在动态工厂可以构造主动技能了
This commit is contained in:
parent
3db586cab2
commit
75d1337ce1
@ -675,7 +675,7 @@ namespace Milimoe.FunGame.Core.Api.Utility
|
|||||||
/// 此方法检查一个 百分比(%) 数值是否存在于 [0,1] 区间
|
/// 此方法检查一个 百分比(%) 数值是否存在于 [0,1] 区间
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="value"></param>
|
/// <param name="value"></param>
|
||||||
/// <returns>如果超过0,则返回0;超过1则返回1。</returns>
|
/// <returns>如果低于0,则返回0;超过1则返回1。</returns>
|
||||||
public static double PercentageCheck(double value)
|
public static double PercentageCheck(double value)
|
||||||
{
|
{
|
||||||
return Math.Max(0, Math.Min(value, 1));
|
return Math.Max(0, Math.Min(value, 1));
|
||||||
|
@ -1307,7 +1307,6 @@ namespace Milimoe.FunGame.Core.Entity
|
|||||||
PrimaryAttribute = PrimaryAttribute,
|
PrimaryAttribute = PrimaryAttribute,
|
||||||
Level = Level,
|
Level = Level,
|
||||||
EXP = EXP,
|
EXP = EXP,
|
||||||
CharacterState = CharacterState,
|
|
||||||
InitialHP = InitialHP,
|
InitialHP = InitialHP,
|
||||||
ExHP2 = ExHP2,
|
ExHP2 = ExHP2,
|
||||||
InitialMP = InitialMP,
|
InitialMP = InitialMP,
|
||||||
@ -1363,8 +1362,9 @@ namespace Milimoe.FunGame.Core.Entity
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 复活此角色,回复出厂状态
|
/// 复活此角色,回复出厂状态
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="original">需要一个原始的角色用于还原状态</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public void Respawn()
|
public void Respawn(Character original)
|
||||||
{
|
{
|
||||||
Item? mcp = UnEquip(EquipSlotType.MagicCardPack);
|
Item? mcp = UnEquip(EquipSlotType.MagicCardPack);
|
||||||
Item? w = UnEquip(EquipSlotType.Weapon);
|
Item? w = UnEquip(EquipSlotType.Weapon);
|
||||||
@ -1374,11 +1374,17 @@ namespace Milimoe.FunGame.Core.Entity
|
|||||||
Item? ac2 = UnEquip(EquipSlotType.Accessory2);
|
Item? ac2 = UnEquip(EquipSlotType.Accessory2);
|
||||||
List<Skill> skills = new(Skills);
|
List<Skill> skills = new(Skills);
|
||||||
List<Item> items = new(Items);
|
List<Item> items = new(Items);
|
||||||
Character c = Copy();
|
Character c = original.Copy();
|
||||||
|
List<Effect> effects = [.. Effects];
|
||||||
|
foreach (Effect e in effects)
|
||||||
|
{
|
||||||
|
e.OnEffectLost(this);
|
||||||
|
}
|
||||||
Effects.Clear();
|
Effects.Clear();
|
||||||
Skills.Clear();
|
Skills.Clear();
|
||||||
Items.Clear();
|
Items.Clear();
|
||||||
Id = c.Id;
|
Id = c.Id;
|
||||||
|
Guid = original.Guid;
|
||||||
Name = c.Name;
|
Name = c.Name;
|
||||||
FirstName = c.FirstName;
|
FirstName = c.FirstName;
|
||||||
NickName = c.NickName;
|
NickName = c.NickName;
|
||||||
@ -1392,6 +1398,10 @@ namespace Milimoe.FunGame.Core.Entity
|
|||||||
Level = c.Level;
|
Level = c.Level;
|
||||||
EXP = c.EXP;
|
EXP = c.EXP;
|
||||||
CharacterState = c.CharacterState;
|
CharacterState = c.CharacterState;
|
||||||
|
CharacterEffectStates.Clear();
|
||||||
|
CharacterEffectTypes.Clear();
|
||||||
|
IsUnselectable = false;
|
||||||
|
UpdateCharacterState();
|
||||||
InitialHP = c.InitialHP;
|
InitialHP = c.InitialHP;
|
||||||
ExHP2 = c.ExHP2;
|
ExHP2 = c.ExHP2;
|
||||||
InitialMP = c.InitialMP;
|
InitialMP = c.InitialMP;
|
||||||
@ -1432,6 +1442,7 @@ namespace Milimoe.FunGame.Core.Entity
|
|||||||
Skill newskill = skill.Copy();
|
Skill newskill = skill.Copy();
|
||||||
newskill.Character = this;
|
newskill.Character = this;
|
||||||
newskill.Level = skill.Level;
|
newskill.Level = skill.Level;
|
||||||
|
newskill.CurrentCD = 0;
|
||||||
Skills.Add(newskill);
|
Skills.Add(newskill);
|
||||||
}
|
}
|
||||||
foreach (Item item in items)
|
foreach (Item item in items)
|
||||||
|
@ -22,21 +22,6 @@ namespace Milimoe.FunGame.Core.Entity
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual EffectType EffectType { get; set; } = EffectType.None;
|
public virtual EffectType EffectType { get; set; } = EffectType.None;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 作用于自身
|
|
||||||
/// </summary>
|
|
||||||
public virtual bool TargetSelf { get; set; } = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 作用目标数量
|
|
||||||
/// </summary>
|
|
||||||
public virtual int TargetCount { get; set; } = 0;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 作用范围
|
|
||||||
/// </summary>
|
|
||||||
public virtual double TargetRange { get; set; } = 0;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 持续性的<para/>
|
/// 持续性的<para/>
|
||||||
/// 配合 <see cref="Duration"/> 使用,而不是 <see cref="DurationTurn"/>。
|
/// 配合 <see cref="Duration"/> 使用,而不是 <see cref="DurationTurn"/>。
|
||||||
@ -232,7 +217,8 @@ namespace Milimoe.FunGame.Core.Entity
|
|||||||
/// 技能开始吟唱时 [ 爆发技插队可触发此项 ]
|
/// 技能开始吟唱时 [ 爆发技插队可触发此项 ]
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="caster"></param>
|
/// <param name="caster"></param>
|
||||||
public virtual void OnSkillCasting(Character caster)
|
/// <param name="targets"></param>
|
||||||
|
public virtual void OnSkillCasting(Character caster, List<Character> targets)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -436,6 +422,18 @@ namespace Milimoe.FunGame.Core.Entity
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 治疗一个目标 [ 强烈建议使用此方法而不是自行调用 <see cref="IGamingQueue.HealToTarget"/> ]
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="actor"></param>
|
||||||
|
/// <param name="target"></param>
|
||||||
|
/// <param name="heal"></param>
|
||||||
|
/// <param name="canRespawn"></param>
|
||||||
|
public void HealToTarget(Character actor, Character target, double heal, bool canRespawn = false)
|
||||||
|
{
|
||||||
|
GamingQueue?.HealToTarget(actor, target, heal, canRespawn);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 打断施法 [ 尽可能的调用此方法而不是直接调用 <see cref="IGamingQueue.InterruptCasting"/>,以防止中断性变更 ]
|
/// 打断施法 [ 尽可能的调用此方法而不是直接调用 <see cref="IGamingQueue.InterruptCasting"/>,以防止中断性变更 ]
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -484,9 +482,6 @@ namespace Milimoe.FunGame.Core.Entity
|
|||||||
copy.Name = Name;
|
copy.Name = Name;
|
||||||
copy.Description = Description;
|
copy.Description = Description;
|
||||||
copy.EffectType = EffectType;
|
copy.EffectType = EffectType;
|
||||||
copy.TargetSelf = TargetSelf;
|
|
||||||
copy.TargetCount = TargetCount;
|
|
||||||
copy.TargetRange = TargetRange;
|
|
||||||
copy.Durative = Durative;
|
copy.Durative = Durative;
|
||||||
copy.Duration = Duration;
|
copy.Duration = Duration;
|
||||||
copy.DurationTurn = DurationTurn;
|
copy.DurationTurn = DurationTurn;
|
||||||
|
@ -15,7 +15,7 @@ namespace Milimoe.FunGame.Core.Entity
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 普通攻击说明
|
/// 普通攻击说明
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Description => $"对目标敌人造成 {(1.0 + 0.05 * (Level - 1)) * 100:0.##}% [ {Damage:0.##} ] 点{(IsMagic ? CharacterSet.GetMagicDamageName(MagicType) : "物理伤害")}。";
|
public string Description => $"对目标敌人造成 {(1.0 + 0.05 * (Level - 1)) * 100:0.##}% 攻击力 [ {Damage:0.##} ] 点{(IsMagic ? CharacterSet.GetMagicDamageName(MagicType) : "物理伤害")}。";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 所属的角色
|
/// 所属的角色
|
||||||
@ -66,6 +66,8 @@ namespace Milimoe.FunGame.Core.Entity
|
|||||||
public void Attack(IGamingQueue queue, Character attacker, params Character[] enemys)
|
public void Attack(IGamingQueue queue, Character attacker, params Character[] enemys)
|
||||||
{
|
{
|
||||||
foreach (Character enemy in enemys)
|
foreach (Character enemy in enemys)
|
||||||
|
{
|
||||||
|
if (enemy.HP > 0)
|
||||||
{
|
{
|
||||||
queue.WriteLine("[ " + Character + $" ] 对 [ {enemy} ] 发起了普通攻击!");
|
queue.WriteLine("[ " + Character + $" ] 对 [ {enemy} ] 发起了普通攻击!");
|
||||||
double expected = Damage;
|
double expected = Damage;
|
||||||
@ -73,6 +75,7 @@ namespace Milimoe.FunGame.Core.Entity
|
|||||||
queue.DamageToEnemy(attacker, enemy, damage, true, IsMagic, MagicType, result);
|
queue.DamageToEnemy(attacker, enemy, damage, true, IsMagic, MagicType, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 修改伤害类型
|
/// 修改伤害类型
|
||||||
@ -95,7 +98,7 @@ namespace Milimoe.FunGame.Core.Entity
|
|||||||
StringBuilder builder = new();
|
StringBuilder builder = new();
|
||||||
|
|
||||||
builder.AppendLine(Name + " - 等级 " + Level);
|
builder.AppendLine(Name + " - 等级 " + Level);
|
||||||
builder.AppendLine("技能描述:" + Description);
|
builder.AppendLine("描述:" + Description);
|
||||||
builder.AppendLine("硬直时间:" + HardnessTime);
|
builder.AppendLine("硬直时间:" + HardnessTime);
|
||||||
|
|
||||||
return builder.ToString();
|
return builder.ToString();
|
||||||
|
@ -18,8 +18,92 @@ namespace Milimoe.FunGame.Core.Entity
|
|||||||
foreach (string str in args.Keys)
|
foreach (string str in args.Keys)
|
||||||
{
|
{
|
||||||
Values[str] = args[str];
|
Values[str] = args[str];
|
||||||
switch (str)
|
switch (str.ToLower())
|
||||||
{
|
{
|
||||||
|
case "active":
|
||||||
|
if (bool.TryParse(args[str].ToString(), out bool isActive) && isActive)
|
||||||
|
{
|
||||||
|
SkillType = SkillType.Item;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "debuff":
|
||||||
|
if (bool.TryParse(args[str].ToString(), out bool isDebuff) && isDebuff)
|
||||||
|
{
|
||||||
|
IsDebuff = isDebuff;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "self":
|
||||||
|
if (bool.TryParse(args[str].ToString(), out bool self))
|
||||||
|
{
|
||||||
|
CanSelectSelf = self;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "enemy":
|
||||||
|
if (bool.TryParse(args[str].ToString(), out bool enemy))
|
||||||
|
{
|
||||||
|
CanSelectEnemy = enemy;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "teammate":
|
||||||
|
if (bool.TryParse(args[str].ToString(), out bool teammate))
|
||||||
|
{
|
||||||
|
CanSelectTeammate = teammate;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "count":
|
||||||
|
if (int.TryParse(args[str].ToString(), out int count) && count > 0)
|
||||||
|
{
|
||||||
|
CanSelectTargetCount = count;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "range":
|
||||||
|
if (int.TryParse(args[str].ToString(), out int range) && range > 0)
|
||||||
|
{
|
||||||
|
CanSelectTargetRange = range;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "mpcost":
|
||||||
|
if (double.TryParse(args[str].ToString(), out double mpcost) && mpcost > 0)
|
||||||
|
{
|
||||||
|
MPCost = mpcost;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "epcost":
|
||||||
|
if (double.TryParse(args[str].ToString(), out double epcost) && epcost > 0)
|
||||||
|
{
|
||||||
|
EPCost = epcost;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "costall":
|
||||||
|
if (bool.TryParse(args[str].ToString(), out bool costall) && costall)
|
||||||
|
{
|
||||||
|
CostAllEP = costall;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "mincost":
|
||||||
|
if (double.TryParse(args[str].ToString(), out double mincost) && mincost > 0)
|
||||||
|
{
|
||||||
|
MinCostEP = mincost;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "cd":
|
||||||
|
if (double.TryParse(args[str].ToString(), out double cd) && cd > 0)
|
||||||
|
{
|
||||||
|
CD = cd;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "cast":
|
||||||
|
if (double.TryParse(args[str].ToString(), out double cast) && cast > 0)
|
||||||
|
{
|
||||||
|
CastTime = cast;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "ht":
|
||||||
|
if (double.TryParse(args[str].ToString(), out double ht) && ht > 0)
|
||||||
|
{
|
||||||
|
HardnessTime = ht;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -82,11 +82,26 @@ namespace Milimoe.FunGame.Core.Entity
|
|||||||
[InitRequired]
|
[InitRequired]
|
||||||
public bool IsMagic => SkillType == SkillType.Magic;
|
public bool IsMagic => SkillType == SkillType.Magic;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否属于 Debuff
|
||||||
|
/// </summary>
|
||||||
|
public bool IsDebuff { get; set; } = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 可选取自身
|
/// 可选取自身
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual bool CanSelectSelf { get; set; } = false;
|
public virtual bool CanSelectSelf { get; set; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 可选取敌对角色
|
||||||
|
/// </summary>
|
||||||
|
public virtual bool CanSelectEnemy { get; set; } = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 可选取友方角色
|
||||||
|
/// </summary>
|
||||||
|
public virtual bool CanSelectTeammate { get; set; } = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 可选取的作用目标数量
|
/// 可选取的作用目标数量
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -97,10 +112,15 @@ namespace Milimoe.FunGame.Core.Entity
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual double CanSelectTargetRange { get; set; } = 0;
|
public virtual double CanSelectTargetRange { get; set; } = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 选取角色的条件
|
||||||
|
/// </summary>
|
||||||
|
public List<Func<Character, bool>> SelectTargetPredicates { get; } = [];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 实际魔法消耗 [ 魔法 ]
|
/// 实际魔法消耗 [ 魔法 ]
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public double RealMPCost => Math.Max(0, MPCost * (1 - Calculation.PercentageCheck((Character?.INT ?? 0) * 0.00125)));
|
public double RealMPCost => Math.Max(0, MPCost * (1 - Calculation.PercentageCheck((Character?.INT ?? 0) * General.GameplayEquilibriumConstant.INTtoCastMPReduce)));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 魔法消耗 [ 魔法 ]
|
/// 魔法消耗 [ 魔法 ]
|
||||||
@ -122,7 +142,7 @@ namespace Milimoe.FunGame.Core.Entity
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 实际能量消耗 [ 战技 ]
|
/// 实际能量消耗 [ 战技 ]
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public double RealEPCost => CostAllEP ? Math.Max(MinCostEP, Character?.EP ?? MinCostEP) : (IsSuperSkill ? EPCost : Math.Max(0, EPCost * (1 - Calculation.PercentageCheck((Character?.INT ?? 0) * 0.00075))));
|
public double RealEPCost => CostAllEP ? Math.Max(MinCostEP, Character?.EP ?? MinCostEP) : (IsSuperSkill ? EPCost : Math.Max(0, EPCost * (1 - Calculation.PercentageCheck((Character?.INT ?? 0) * General.GameplayEquilibriumConstant.INTtoCastEPReduce))));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 能量消耗 [ 战技 ]
|
/// 能量消耗 [ 战技 ]
|
||||||
@ -140,10 +160,20 @@ namespace Milimoe.FunGame.Core.Entity
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual double MinCostEP { get; set; } = 100;
|
public virtual double MinCostEP { get; set; } = 100;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上一次释放此技能消耗的魔法 [ 魔法 ]
|
||||||
|
/// </summary>
|
||||||
|
public double LastCostMP { get; set; } = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上一次释放此技能消耗的能量 [ 战技 ]
|
||||||
|
/// </summary>
|
||||||
|
public double LastCostEP { get; set; } = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 实际冷却时间
|
/// 实际冷却时间
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public double RealCD => Math.Max(0, CD * (1 - Character?.CDR ?? 0));
|
public double RealCD => Math.Max(0, CD * (1 - (Character?.CDR ?? 0)));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 冷却时间
|
/// 冷却时间
|
||||||
@ -247,21 +277,37 @@ namespace Milimoe.FunGame.Core.Entity
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual List<Character> SelectTargets(Character caster, List<Character> enemys, List<Character> teammates)
|
public virtual List<Character> SelectTargets(Character caster, List<Character> enemys, List<Character> teammates)
|
||||||
{
|
{
|
||||||
|
List<Character> tobeSelected = [];
|
||||||
|
|
||||||
if (CanSelectSelf)
|
if (CanSelectSelf)
|
||||||
{
|
{
|
||||||
return [caster];
|
tobeSelected.Add(caster);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CanSelectEnemy)
|
||||||
|
{
|
||||||
|
tobeSelected.AddRange(enemys);
|
||||||
|
}
|
||||||
|
if (CanSelectTeammate)
|
||||||
|
{
|
||||||
|
tobeSelected.AddRange(teammates);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 筛选出符合条件的角色
|
||||||
|
tobeSelected = [.. tobeSelected.Where(c => SelectTargetPredicates.All(f => f(c)))];
|
||||||
|
|
||||||
|
List<Character> targets = [];
|
||||||
|
|
||||||
|
if (tobeSelected.Count <= CanSelectTargetCount)
|
||||||
|
{
|
||||||
|
targets.AddRange(tobeSelected);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
List<Character> targets = [];
|
targets.AddRange(tobeSelected.OrderBy(x => Random.Shared.Next()).Take(CanSelectTargetCount));
|
||||||
|
|
||||||
if (enemys.Count <= CanSelectTargetCount)
|
|
||||||
{
|
|
||||||
return [.. enemys];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return enemys.OrderBy(x => Random.Shared.Next()).Take(CanSelectTargetCount).ToList();
|
return [.. targets.Distinct()];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -269,16 +315,26 @@ namespace Milimoe.FunGame.Core.Entity
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="queue"></param>
|
/// <param name="queue"></param>
|
||||||
/// <param name="caster"></param>
|
/// <param name="caster"></param>
|
||||||
public void OnSkillCasting(IGamingQueue queue, Character caster)
|
/// <param name="targets"></param>
|
||||||
|
public void OnSkillCasting(IGamingQueue queue, Character caster, List<Character> targets)
|
||||||
{
|
{
|
||||||
GamingQueue = queue;
|
GamingQueue = queue;
|
||||||
foreach (Effect e in Effects)
|
foreach (Effect e in Effects)
|
||||||
{
|
{
|
||||||
e.GamingQueue = GamingQueue;
|
e.GamingQueue = GamingQueue;
|
||||||
e.OnSkillCasting(caster);
|
e.OnSkillCasting(caster, targets);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 技能效果触发前
|
||||||
|
/// </summary>
|
||||||
|
public void BeforeSkillCasted()
|
||||||
|
{
|
||||||
|
LastCostMP = RealMPCost;
|
||||||
|
LastCostEP = RealEPCost;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 触发技能效果
|
/// 触发技能效果
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -43,5 +43,6 @@
|
|||||||
public int LastRank { get; set; } = 0;
|
public int LastRank { get; set; } = 0;
|
||||||
public double AvgRank { get; set; } = 0;
|
public double AvgRank { get; set; } = 0;
|
||||||
public double Rating { get; set; } = 0;
|
public double Rating { get; set; } = 0;
|
||||||
|
public int MVPs { get; set; } = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,129 @@
|
|||||||
using Milimoe.FunGame.Core.Library.Constant;
|
using System.Text;
|
||||||
|
using Milimoe.FunGame.Core.Api.Utility;
|
||||||
|
using Milimoe.FunGame.Core.Library.Constant;
|
||||||
|
|
||||||
namespace Milimoe.FunGame.Core.Entity.System
|
namespace Milimoe.FunGame.Core.Entity
|
||||||
{
|
{
|
||||||
public class RoundRecord(int round, Character actor)
|
public class RoundRecord(int round)
|
||||||
{
|
{
|
||||||
public int Round { get; set; } = round;
|
public int Round { get; set; } = round;
|
||||||
public Character Actor { get; set; } = actor;
|
public Character Actor { get; set; } = Factory.GetCharacter();
|
||||||
public CharacterActionType ActionType { get; set; } = CharacterActionType.None;
|
public CharacterActionType ActionType { get; set; } = CharacterActionType.None;
|
||||||
public List<Character> Targets { get; set; } = [];
|
public List<Character> Targets { get; set; } = [];
|
||||||
public Skill? Skill { get; set; } = null;
|
public Skill? Skill { get; set; } = null;
|
||||||
|
public string SkillCost { get; set; } = "";
|
||||||
public Item? Item { get; set; } = null;
|
public Item? Item { get; set; } = null;
|
||||||
|
public bool HasKill { get; set; } = false;
|
||||||
|
public Dictionary<Character, double> Damages { get; set; } = [];
|
||||||
|
public Dictionary<Character, bool> IsCritical { get; set; } = [];
|
||||||
|
public Dictionary<Character, double> Heals { get; set; } = [];
|
||||||
|
public Dictionary<Character, EffectType> Effects { get; set; } = [];
|
||||||
|
public List<string> ActorContinuousKilling { get; set; } = [];
|
||||||
|
public List<string> DeathContinuousKilling { get; set; } = [];
|
||||||
|
public double CastTime { get; set; } = 0;
|
||||||
|
public double HardnessTime { get; set; } = 0;
|
||||||
|
public Dictionary<Character, double> RespawnCountdowns { get; set; } = [];
|
||||||
|
public List<Character> Respawns { get; set; } = [];
|
||||||
|
public List<Skill> RoundRewards { get; set; } = [];
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
StringBuilder builder = new();
|
||||||
|
|
||||||
|
builder.AppendLine($"=== Round {Round} ===");
|
||||||
|
if (RoundRewards.Count > 0)
|
||||||
|
{
|
||||||
|
builder.AppendLine($"[ {Actor} ] 回合奖励 -> {string.Join(" / ", RoundRewards.Select(s => s.Description)).Trim()}");
|
||||||
|
}
|
||||||
|
if (ActionType == CharacterActionType.NormalAttack || ActionType == CharacterActionType.CastSkill || ActionType == CharacterActionType.CastSuperSkill)
|
||||||
|
{
|
||||||
|
if (ActionType == CharacterActionType.NormalAttack)
|
||||||
|
{
|
||||||
|
builder.Append($"[ {Actor} ] {Actor.NormalAttack.Name} -> ");
|
||||||
|
}
|
||||||
|
else if (ActionType == CharacterActionType.CastSkill || ActionType == CharacterActionType.CastSuperSkill)
|
||||||
|
{
|
||||||
|
if (Skill != null)
|
||||||
|
{
|
||||||
|
builder.Append($"[ {Actor} ] {Skill.Name}({SkillCost})-> ");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
builder.Append($"释放魔法 -> ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
builder.AppendLine(string.Join(" / ", GetTargetsState()));
|
||||||
|
if (DeathContinuousKilling.Count > 0) builder.AppendLine($"{string.Join("\r\n", DeathContinuousKilling)}");
|
||||||
|
if (ActorContinuousKilling.Count > 0) builder.AppendLine($"{string.Join("\r\n", ActorContinuousKilling)}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ActionType == CharacterActionType.PreCastSkill && Skill != null)
|
||||||
|
{
|
||||||
|
if (Skill.IsMagic)
|
||||||
|
{
|
||||||
|
builder.AppendLine($"[ {Actor} ] 吟唱 [ {Skill.Name} ],持续时间:{CastTime:0.##}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
builder.AppendLine($"[ {Actor} ]:{Skill.Name}({SkillCost})-> ");
|
||||||
|
builder.AppendLine(string.Join(" / ", GetTargetsState()));
|
||||||
|
builder.AppendLine($"[ {Actor} ] 回合结束,硬直时间:{HardnessTime:0.##}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
builder.AppendLine($"[ {Actor} ] 回合结束,硬直时间:{HardnessTime:0.##}");
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Character character in RespawnCountdowns.Keys)
|
||||||
|
{
|
||||||
|
builder.AppendLine($"[ {character} ] 进入复活倒计时:{RespawnCountdowns[character]:0.##}");
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Character character in Respawns)
|
||||||
|
{
|
||||||
|
builder.AppendLine($"[ {character} ] 复活了");
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<string> GetTargetsState()
|
||||||
|
{
|
||||||
|
List<string> strings = [];
|
||||||
|
foreach (Character target in Targets.Distinct())
|
||||||
|
{
|
||||||
|
string hasDamage = "";
|
||||||
|
string hasHeal = "";
|
||||||
|
string hasEffect = "";
|
||||||
|
if (Damages.TryGetValue(target, out double damage))
|
||||||
|
{
|
||||||
|
hasDamage = $"伤害:{damage:0.##}";
|
||||||
|
if (IsCritical.TryGetValue(target, out bool isCritical) && isCritical)
|
||||||
|
{
|
||||||
|
hasDamage = "暴击," + hasDamage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Heals.TryGetValue(target, out double heals))
|
||||||
|
{
|
||||||
|
hasHeal = $"治疗:{heals:0.##}";
|
||||||
|
}
|
||||||
|
if (Effects.TryGetValue(target, out EffectType effectType))
|
||||||
|
{
|
||||||
|
hasEffect = $"施加:{SkillSet.GetEffectTypeName(effectType)}";
|
||||||
|
}
|
||||||
|
if (ActionType == CharacterActionType.NormalAttack && hasDamage == "")
|
||||||
|
{
|
||||||
|
hasDamage = "完美闪避";
|
||||||
|
}
|
||||||
|
if ((ActionType == CharacterActionType.PreCastSkill || ActionType == CharacterActionType.PreCastSkill || ActionType == CharacterActionType.CastSkill) && hasDamage == "" && target != Actor)
|
||||||
|
{
|
||||||
|
hasDamage = "免疫";
|
||||||
|
}
|
||||||
|
string[] strs = [hasDamage, hasHeal, hasEffect];
|
||||||
|
strings.Add($"[ {target}({string.Join(" / ", strs.Where(s => s != ""))})])");
|
||||||
|
}
|
||||||
|
return strings;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
namespace Milimoe.FunGame.Core.Entity.System
|
namespace Milimoe.FunGame.Core.Entity
|
||||||
{
|
{
|
||||||
public class Season(long id, string name, string description)
|
public class Season(long id, string name, string description)
|
||||||
{
|
{
|
||||||
|
@ -13,11 +13,26 @@ namespace Milimoe.FunGame.Core.Interface.Base
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Action<string> WriteLine { get; }
|
public Action<string> WriteLine { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 原始的角色字典
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<Guid, Character> Original { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 当前的行动顺序
|
/// 当前的行动顺序
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<Character> Queue { get; }
|
public List<Character> Queue { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上回合记录
|
||||||
|
/// </summary>
|
||||||
|
public RoundRecord LastRound { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 所有回合的记录
|
||||||
|
/// </summary>
|
||||||
|
public List<RoundRecord> Rounds { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 当前已死亡的角色顺序(第一个是最早死的)
|
/// 当前已死亡的角色顺序(第一个是最早死的)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -63,6 +78,15 @@ namespace Milimoe.FunGame.Core.Interface.Base
|
|||||||
/// <param name="damageResult"></param>
|
/// <param name="damageResult"></param>
|
||||||
public void DamageToEnemy(Character actor, Character enemy, double damage, bool isNormalAttack, bool isMagicDamage = false, MagicType magicType = MagicType.None, DamageResult damageResult = DamageResult.Normal);
|
public void DamageToEnemy(Character actor, Character enemy, double damage, bool isNormalAttack, bool isMagicDamage = false, MagicType magicType = MagicType.None, DamageResult damageResult = DamageResult.Normal);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 治疗一个目标
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="actor"></param>
|
||||||
|
/// <param name="target"></param>
|
||||||
|
/// <param name="heal"></param>
|
||||||
|
/// <param name="canRespawn"></param>
|
||||||
|
public void HealToTarget(Character actor, Character target, double heal, bool canRespawn = false);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 计算物理伤害
|
/// 计算物理伤害
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -41,6 +41,12 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
|
|||||||
case nameof(Skill.CanSelectSelf):
|
case nameof(Skill.CanSelectSelf):
|
||||||
result.CanSelectSelf = reader.GetBoolean();
|
result.CanSelectSelf = reader.GetBoolean();
|
||||||
break;
|
break;
|
||||||
|
case nameof(Skill.CanSelectEnemy):
|
||||||
|
result.CanSelectEnemy = reader.GetBoolean();
|
||||||
|
break;
|
||||||
|
case nameof(Skill.CanSelectTeammate):
|
||||||
|
result.CanSelectTeammate = reader.GetBoolean();
|
||||||
|
break;
|
||||||
case nameof(Skill.CanSelectTargetCount):
|
case nameof(Skill.CanSelectTargetCount):
|
||||||
result.CanSelectTargetCount = reader.GetInt32();
|
result.CanSelectTargetCount = reader.GetInt32();
|
||||||
break;
|
break;
|
||||||
@ -59,6 +65,12 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
|
|||||||
case nameof(Skill.EPCost):
|
case nameof(Skill.EPCost):
|
||||||
result.EPCost = reader.GetDouble();
|
result.EPCost = reader.GetDouble();
|
||||||
break;
|
break;
|
||||||
|
case nameof(Skill.CostAllEP):
|
||||||
|
result.CostAllEP = reader.GetBoolean();
|
||||||
|
break;
|
||||||
|
case nameof(Skill.MinCostEP):
|
||||||
|
result.MinCostEP = reader.GetDouble();
|
||||||
|
break;
|
||||||
case nameof(Skill.CastTime):
|
case nameof(Skill.CastTime):
|
||||||
result.CastTime = reader.GetDouble();
|
result.CastTime = reader.GetDouble();
|
||||||
break;
|
break;
|
||||||
@ -100,12 +112,16 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
|
|||||||
if (value.Level > 0) writer.WriteNumber(nameof(Skill.Level), value.Level);
|
if (value.Level > 0) writer.WriteNumber(nameof(Skill.Level), value.Level);
|
||||||
writer.WriteNumber(nameof(Skill.SkillType), (int)value.SkillType);
|
writer.WriteNumber(nameof(Skill.SkillType), (int)value.SkillType);
|
||||||
if (value.CanSelectSelf) writer.WriteBoolean(nameof(Skill.CanSelectSelf), value.CanSelectSelf);
|
if (value.CanSelectSelf) writer.WriteBoolean(nameof(Skill.CanSelectSelf), value.CanSelectSelf);
|
||||||
|
if (!value.CanSelectEnemy) writer.WriteBoolean(nameof(Skill.CanSelectEnemy), value.CanSelectEnemy);
|
||||||
|
if (value.CanSelectTeammate) writer.WriteBoolean(nameof(Skill.CanSelectTeammate), value.CanSelectTeammate);
|
||||||
if (value.CanSelectTargetCount != 0) writer.WriteNumber(nameof(Skill.CanSelectTargetCount), value.CanSelectTargetCount);
|
if (value.CanSelectTargetCount != 0) writer.WriteNumber(nameof(Skill.CanSelectTargetCount), value.CanSelectTargetCount);
|
||||||
if (value.CanSelectTargetRange != 0) writer.WriteNumber(nameof(Skill.CanSelectTargetRange), value.CanSelectTargetRange);
|
if (value.CanSelectTargetRange != 0) writer.WriteNumber(nameof(Skill.CanSelectTargetRange), value.CanSelectTargetRange);
|
||||||
if (!value.Enable) writer.WriteBoolean(nameof(Skill.Enable), value.Enable);
|
if (!value.Enable) writer.WriteBoolean(nameof(Skill.Enable), value.Enable);
|
||||||
if (value.IsInEffect) writer.WriteBoolean(nameof(Skill.IsInEffect), value.IsInEffect);
|
if (value.IsInEffect) writer.WriteBoolean(nameof(Skill.IsInEffect), value.IsInEffect);
|
||||||
if (value.MPCost > 0) writer.WriteNumber(nameof(Skill.MPCost), value.MPCost);
|
if (value.MPCost > 0) writer.WriteNumber(nameof(Skill.MPCost), value.MPCost);
|
||||||
if (value.EPCost > 0) writer.WriteNumber(nameof(Skill.EPCost), value.EPCost);
|
if (value.EPCost > 0) writer.WriteNumber(nameof(Skill.EPCost), value.EPCost);
|
||||||
|
if (value.CostAllEP) writer.WriteBoolean(nameof(Skill.CostAllEP), value.CostAllEP);
|
||||||
|
if (value.MinCostEP > 0) writer.WriteNumber(nameof(Skill.MinCostEP), value.MinCostEP);
|
||||||
if (value.CastTime > 0) writer.WriteNumber(nameof(Skill.CastTime), value.CastTime);
|
if (value.CastTime > 0) writer.WriteNumber(nameof(Skill.CastTime), value.CastTime);
|
||||||
if (value.CD > 0) writer.WriteNumber(nameof(Skill.CD), value.CD);
|
if (value.CD > 0) writer.WriteNumber(nameof(Skill.CD), value.CD);
|
||||||
if (value.CurrentCD > 0) writer.WriteNumber(nameof(Skill.CurrentCD), value.CurrentCD);
|
if (value.CurrentCD > 0) writer.WriteNumber(nameof(Skill.CurrentCD), value.CurrentCD);
|
||||||
|
@ -521,5 +521,53 @@ namespace Milimoe.FunGame.Core.Library.Constant
|
|||||||
_ => General.GameplayEquilibriumConstant.MaxPassiveSkillLevel
|
_ => General.GameplayEquilibriumConstant.MaxPassiveSkillLevel
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string GetEffectTypeName(EffectType type)
|
||||||
|
{
|
||||||
|
return type switch
|
||||||
|
{
|
||||||
|
EffectType.None => "无特殊效果",
|
||||||
|
EffectType.Item => "装备特效",
|
||||||
|
EffectType.Mark => "标记",
|
||||||
|
EffectType.Stun => "眩晕",
|
||||||
|
EffectType.Freeze => "冰冻",
|
||||||
|
EffectType.Silence => "沉默",
|
||||||
|
EffectType.Root => "定身",
|
||||||
|
EffectType.Fear => "恐惧",
|
||||||
|
EffectType.Sleep => "睡眠",
|
||||||
|
EffectType.Knockback => "击退",
|
||||||
|
EffectType.Knockdown => "击倒",
|
||||||
|
EffectType.Taunt => "嘲讽",
|
||||||
|
EffectType.Slow => "减速",
|
||||||
|
EffectType.Weaken => "衰弱",
|
||||||
|
EffectType.Poison => "中毒",
|
||||||
|
EffectType.Burn => "燃烧",
|
||||||
|
EffectType.Bleed => "流血",
|
||||||
|
EffectType.Blind => "致盲",
|
||||||
|
EffectType.Cripple => "致残",
|
||||||
|
EffectType.Shield => "护盾",
|
||||||
|
EffectType.HealOverTime => "持续治疗",
|
||||||
|
EffectType.Haste => "加速",
|
||||||
|
EffectType.Invulnerable => "无敌",
|
||||||
|
EffectType.Unselectable => "不可选中",
|
||||||
|
EffectType.DamageBoost => "伤害提升",
|
||||||
|
EffectType.DefenseBoost => "防御提升",
|
||||||
|
EffectType.CritBoost => "暴击提升",
|
||||||
|
EffectType.ManaRegen => "魔法恢复",
|
||||||
|
EffectType.ArmorBreak => "破甲",
|
||||||
|
EffectType.MagicResistBreak => "降低魔抗",
|
||||||
|
EffectType.Curse => "诅咒",
|
||||||
|
EffectType.Exhaustion => "疲劳",
|
||||||
|
EffectType.ManaBurn => "魔力燃烧",
|
||||||
|
EffectType.Charm => "魅惑",
|
||||||
|
EffectType.Disarm => "缴械",
|
||||||
|
EffectType.Confusion => "混乱",
|
||||||
|
EffectType.Petrify => "石化",
|
||||||
|
EffectType.SilenceMagic => "法术沉默",
|
||||||
|
EffectType.Banish => "放逐",
|
||||||
|
EffectType.Doom => "毁灭",
|
||||||
|
_ => "未知效果"
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
using Milimoe.FunGame.Core.Api.Utility;
|
using Milimoe.FunGame.Core.Api.Utility;
|
||||||
using Milimoe.FunGame.Core.Entity;
|
using Milimoe.FunGame.Core.Entity;
|
||||||
using Milimoe.FunGame.Core.Entity.System;
|
|
||||||
using Milimoe.FunGame.Core.Interface.Base;
|
using Milimoe.FunGame.Core.Interface.Base;
|
||||||
using Milimoe.FunGame.Core.Library.Constant;
|
using Milimoe.FunGame.Core.Library.Constant;
|
||||||
|
|
||||||
@ -16,6 +15,11 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Action<string> WriteLine { get; }
|
public Action<string> WriteLine { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 原始的角色字典
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<Guid, Character> Original => _original;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 当前的行动顺序
|
/// 当前的行动顺序
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -82,7 +86,17 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 上回合记录
|
/// 上回合记录
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public RoundRecord LastRound { get; set; } = new(0, Factory.GetCharacter());
|
public RoundRecord LastRound { get; set; } = new(0);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 所有回合的记录
|
||||||
|
/// </summary>
|
||||||
|
public List<RoundRecord> Rounds { get; } = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 原始的角色字典
|
||||||
|
/// </summary>
|
||||||
|
protected readonly Dictionary<Guid, Character> _original = [];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 当前的行动顺序
|
/// 当前的行动顺序
|
||||||
@ -119,6 +133,11 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
protected readonly Dictionary<Character, int> _earnedMoney = [];
|
protected readonly Dictionary<Character, int> _earnedMoney = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 角色最高连杀数
|
||||||
|
/// </summary>
|
||||||
|
protected readonly Dictionary<Character, int> _maxContinuousKilling = [];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 角色目前的连杀数
|
/// 角色目前的连杀数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -154,6 +173,11 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
protected readonly Dictionary<Character, double> _respawnCountdown = [];
|
protected readonly Dictionary<Character, double> _respawnCountdown = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当前回合死亡角色
|
||||||
|
/// </summary>
|
||||||
|
protected readonly List<Character> _roundDeaths = [];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否是团队模式
|
/// 是否是团队模式
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -202,6 +226,15 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
/// <param name="characters"></param>
|
/// <param name="characters"></param>
|
||||||
public void InitCharacterQueue(List<Character> characters)
|
public void InitCharacterQueue(List<Character> characters)
|
||||||
{
|
{
|
||||||
|
// 保存原始的角色信息。用于复活时还原状态
|
||||||
|
foreach (Character character in characters)
|
||||||
|
{
|
||||||
|
Character original = character.Copy();
|
||||||
|
original.Guid = Guid.NewGuid();
|
||||||
|
character.Guid = original.Guid;
|
||||||
|
_original.Add(original.Guid, original);
|
||||||
|
}
|
||||||
|
|
||||||
// 初始排序:按速度排序
|
// 初始排序:按速度排序
|
||||||
List<IGrouping<double, Character>> groupedBySpeed = [.. characters
|
List<IGrouping<double, Character>> groupedBySpeed = [.. characters
|
||||||
.GroupBy(c => c.SPD)
|
.GroupBy(c => c.SPD)
|
||||||
@ -291,6 +324,7 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
public void ClearQueue()
|
public void ClearQueue()
|
||||||
{
|
{
|
||||||
FirstKiller = null;
|
FirstKiller = null;
|
||||||
|
_original.Clear();
|
||||||
_queue.Clear();
|
_queue.Clear();
|
||||||
_hardnessTimes.Clear();
|
_hardnessTimes.Clear();
|
||||||
_assistDamage.Clear();
|
_assistDamage.Clear();
|
||||||
@ -298,6 +332,7 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
_cutCount.Clear();
|
_cutCount.Clear();
|
||||||
_castingSkills.Clear();
|
_castingSkills.Clear();
|
||||||
_castingSuperSkills.Clear();
|
_castingSuperSkills.Clear();
|
||||||
|
_maxContinuousKilling.Clear();
|
||||||
_continuousKilling.Clear();
|
_continuousKilling.Clear();
|
||||||
_earnedMoney.Clear();
|
_earnedMoney.Clear();
|
||||||
_eliminated.Clear();
|
_eliminated.Clear();
|
||||||
@ -491,8 +526,8 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
/// <returns>是否结束游戏</returns>
|
/// <returns>是否结束游戏</returns>
|
||||||
public bool ProcessTurn(Character character)
|
public bool ProcessTurn(Character character)
|
||||||
{
|
{
|
||||||
TotalRound++;
|
LastRound.Actor = character;
|
||||||
LastRound = new(TotalRound, character);
|
_roundDeaths.Clear();
|
||||||
|
|
||||||
if (!BeforeTurn(character))
|
if (!BeforeTurn(character))
|
||||||
{
|
{
|
||||||
@ -696,7 +731,7 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
character.CharacterState = CharacterState.Casting;
|
character.CharacterState = CharacterState.Casting;
|
||||||
_castingSkills.Add(character, new(skill, targets));
|
_castingSkills.Add(character, new(skill, targets));
|
||||||
baseTime = skill.CastTime;
|
baseTime = skill.CastTime;
|
||||||
skill.OnSkillCasting(this, character);
|
skill.OnSkillCasting(this, character, targets);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -708,12 +743,14 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
if (!cancel)
|
if (!cancel)
|
||||||
{
|
{
|
||||||
decided = true;
|
decided = true;
|
||||||
skill.OnSkillCasting(this, character);
|
skill.OnSkillCasting(this, character, targets);
|
||||||
|
skill.BeforeSkillCasted();
|
||||||
|
|
||||||
character.EP -= cost;
|
character.EP -= cost;
|
||||||
baseTime = skill.HardnessTime;
|
baseTime = skill.HardnessTime;
|
||||||
skill.CurrentCD = skill.RealCD;
|
skill.CurrentCD = skill.RealCD;
|
||||||
skill.Enable = false;
|
skill.Enable = false;
|
||||||
|
LastRound.SkillCost = $"{-cost:0.##} EP";
|
||||||
|
|
||||||
WriteLine("[ " + character + $" ] 消耗了 {cost:0.##} 点能量,释放了{(skill.IsSuperSkill ? "爆发技" : "战技")} [ {skill.Name} ]!{(skill.Slogan != "" ? skill.Slogan : "")}");
|
WriteLine("[ " + character + $" ] 消耗了 {cost:0.##} 点能量,释放了{(skill.IsSuperSkill ? "爆发技" : "战技")} [ {skill.Name} ]!{(skill.Slogan != "" ? skill.Slogan : "")}");
|
||||||
skill.OnSkillCasted(this, character, targets);
|
skill.OnSkillCasted(this, character, targets);
|
||||||
@ -742,10 +779,13 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
// 判断是否能够释放技能
|
// 判断是否能够释放技能
|
||||||
if (CheckCanCast(character, skill, out double cost))
|
if (CheckCanCast(character, skill, out double cost))
|
||||||
{
|
{
|
||||||
|
skill.BeforeSkillCasted();
|
||||||
|
|
||||||
character.MP -= cost;
|
character.MP -= cost;
|
||||||
baseTime = skill.HardnessTime;
|
baseTime = skill.HardnessTime;
|
||||||
skill.CurrentCD = skill.RealCD;
|
skill.CurrentCD = skill.RealCD;
|
||||||
skill.Enable = false;
|
skill.Enable = false;
|
||||||
|
LastRound.SkillCost = $"{-cost:0.##} MP";
|
||||||
|
|
||||||
WriteLine("[ " + character + $" ] 消耗了 {cost:0.##} 点魔法值,释放了魔法 [ {skill.Name} ]!{(skill.Slogan != "" ? skill.Slogan : "")}");
|
WriteLine("[ " + character + $" ] 消耗了 {cost:0.##} 点魔法值,释放了魔法 [ {skill.Name} ]!{(skill.Slogan != "" ? skill.Slogan : "")}");
|
||||||
skill.OnSkillCasted(this, character, targets);
|
skill.OnSkillCasted(this, character, targets);
|
||||||
@ -779,10 +819,13 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
List<Character> targets = SelectTargets(character, skill, enemys, teammates, out _);
|
List<Character> targets = SelectTargets(character, skill, enemys, teammates, out _);
|
||||||
LastRound.Targets = [.. targets];
|
LastRound.Targets = [.. targets];
|
||||||
|
|
||||||
|
skill.BeforeSkillCasted();
|
||||||
|
|
||||||
character.EP -= cost;
|
character.EP -= cost;
|
||||||
baseTime = skill.HardnessTime;
|
baseTime = skill.HardnessTime;
|
||||||
skill.CurrentCD = skill.RealCD;
|
skill.CurrentCD = skill.RealCD;
|
||||||
skill.Enable = false;
|
skill.Enable = false;
|
||||||
|
LastRound.SkillCost = $"{-cost:0.##} EP";
|
||||||
|
|
||||||
WriteLine("[ " + character + $" ] 消耗了 {cost:0.##} 点能量值,释放了爆发技 [ {skill.Name} ]!{(skill.Slogan != "" ? skill.Slogan : "")}");
|
WriteLine("[ " + character + $" ] 消耗了 {cost:0.##} 点能量值,释放了爆发技 [ {skill.Name} ]!{(skill.Slogan != "" ? skill.Slogan : "")}");
|
||||||
skill.OnSkillCasted(this, character, targets);
|
skill.OnSkillCasted(this, character, targets);
|
||||||
@ -811,13 +854,16 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
WriteLine("[ " + character + $" ] 放弃了行动!");
|
WriteLine("[ " + character + $" ] 放弃了行动!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LastRound.ActionType = type;
|
||||||
|
|
||||||
|
// 统一在回合结束时处理角色的死亡
|
||||||
|
ProcessCharacterDeath(character);
|
||||||
|
|
||||||
if (_isGameEnd)
|
if (_isGameEnd)
|
||||||
{
|
{
|
||||||
return _isGameEnd;
|
return _isGameEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
LastRound.ActionType = type;
|
|
||||||
|
|
||||||
// 减少硬直时间
|
// 减少硬直时间
|
||||||
double newHardnessTime = baseTime;
|
double newHardnessTime = baseTime;
|
||||||
if (character.CharacterState != CharacterState.Casting)
|
if (character.CharacterState != CharacterState.Casting)
|
||||||
@ -829,8 +875,10 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
{
|
{
|
||||||
newHardnessTime = Math.Max(0, Calculation.Round2Digits(baseTime * (1 - character.AccelerationCoefficient)));
|
newHardnessTime = Math.Max(0, Calculation.Round2Digits(baseTime * (1 - character.AccelerationCoefficient)));
|
||||||
WriteLine("[ " + character + " ] 进行吟唱,持续时间: " + newHardnessTime);
|
WriteLine("[ " + character + " ] 进行吟唱,持续时间: " + newHardnessTime);
|
||||||
|
LastRound.CastTime = newHardnessTime;
|
||||||
}
|
}
|
||||||
AddCharacter(character, newHardnessTime, isCheckProtected);
|
AddCharacter(character, newHardnessTime, isCheckProtected);
|
||||||
|
LastRound.HardnessTime = newHardnessTime;
|
||||||
|
|
||||||
// 有人想要插队吗?
|
// 有人想要插队吗?
|
||||||
WillPreCastSuperSkill(character);
|
WillPreCastSuperSkill(character);
|
||||||
@ -885,10 +933,38 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
|
|
||||||
// 获取第一个角色的硬直时间
|
// 获取第一个角色的硬直时间
|
||||||
double timeToReduce = _hardnessTimes[_queue[0]];
|
double timeToReduce = _hardnessTimes[_queue[0]];
|
||||||
TotalTime = Calculation.Round2Digits(TotalTime + timeToReduce);
|
// 如果复活时间更快,应该先流逝复活时间
|
||||||
|
if (_respawnCountdown.Count != 0)
|
||||||
|
{
|
||||||
|
double timeToRespawn = _respawnCountdown.Values.Min();
|
||||||
|
if (timeToRespawn < timeToReduce)
|
||||||
|
{
|
||||||
|
timeToReduce = Calculation.Round2Digits(timeToRespawn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TotalTime = Calculation.Round2Digits(TotalTime + timeToReduce);
|
||||||
WriteLine("时间流逝:" + timeToReduce);
|
WriteLine("时间流逝:" + timeToReduce);
|
||||||
|
|
||||||
|
// 减少复活倒计时
|
||||||
|
foreach (Character character in _respawnCountdown.Keys)
|
||||||
|
{
|
||||||
|
_respawnCountdown[character] = Calculation.Round2Digits(_respawnCountdown[character] - timeToReduce);
|
||||||
|
if (_respawnCountdown[character] <= 0)
|
||||||
|
{
|
||||||
|
double hardnessTime = 5;
|
||||||
|
character.Respawn(_original[character.Guid]);
|
||||||
|
WriteLine($"[ {character} ] 已复活!获得 {hardnessTime} 硬直时间。");
|
||||||
|
AddCharacter(character, hardnessTime, false);
|
||||||
|
LastRound.Respawns.Add(character);
|
||||||
|
_respawnCountdown.Remove(character);
|
||||||
|
if (!_respawnTimes.TryAdd(character, 1))
|
||||||
|
{
|
||||||
|
_respawnTimes[character] += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (Character character in _queue)
|
foreach (Character character in _queue)
|
||||||
{
|
{
|
||||||
// 减少所有角色的硬直时间
|
// 减少所有角色的硬直时间
|
||||||
@ -970,25 +1046,13 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 减少复活倒计时
|
|
||||||
foreach (Character character in _respawnCountdown.Keys)
|
|
||||||
{
|
|
||||||
_respawnCountdown[character] -= timeToReduce;
|
|
||||||
if (_respawnCountdown[character] <= 0)
|
|
||||||
{
|
|
||||||
double hardnessTime = 5;
|
|
||||||
character.Respawn();
|
|
||||||
WriteLine($"[ {character} ] 已复活!获得 {hardnessTime} 硬直时间。");
|
|
||||||
AddCharacter(character, hardnessTime, false);
|
|
||||||
_respawnCountdown.Remove(character);
|
|
||||||
if (!_respawnTimes.TryAdd(character, 1))
|
|
||||||
{
|
|
||||||
_respawnTimes[character] += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
WriteLine("\r\n");
|
WriteLine("\r\n");
|
||||||
|
|
||||||
|
// 在时间流逝后,进入下一回合
|
||||||
|
TotalRound++;
|
||||||
|
LastRound = new(TotalRound);
|
||||||
|
Rounds.Add(LastRound);
|
||||||
|
|
||||||
return timeToReduce;
|
return timeToReduce;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1010,6 +1074,10 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!LastRound.IsCritical.TryAdd(enemy, damageResult == DamageResult.Critical) && damageResult == DamageResult.Critical)
|
||||||
|
{
|
||||||
|
LastRound.IsCritical[enemy] = true;
|
||||||
|
}
|
||||||
bool isEvaded = damageResult == DamageResult.Evaded;
|
bool isEvaded = damageResult == DamageResult.Evaded;
|
||||||
List<Effect> effects = actor.Effects.Union(enemy.Effects).Where(e => e.Level > 0).ToList();
|
List<Effect> effects = actor.Effects.Union(enemy.Effects).Where(e => e.Level > 0).ToList();
|
||||||
foreach (Effect effect in effects)
|
foreach (Effect effect in effects)
|
||||||
@ -1062,71 +1130,54 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
effect.AfterDamageCalculation(actor, enemy, damage, isNormalAttack, isMagicDamage, magicType, damageResult);
|
effect.AfterDamageCalculation(actor, enemy, damage, isNormalAttack, isMagicDamage, magicType, damageResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enemy.HP <= 0 && !_eliminated.Contains(enemy))
|
if (enemy.HP <= 0 && !_eliminated.Contains(enemy) && !_respawnCountdown.ContainsKey(enemy))
|
||||||
{
|
{
|
||||||
|
LastRound.HasKill = true;
|
||||||
|
_roundDeaths.Add(enemy);
|
||||||
DeathCalculation(actor, enemy);
|
DeathCalculation(actor, enemy);
|
||||||
// 给所有角色的特效广播角色死亡结算
|
|
||||||
effects = _queue.SelectMany(c => c.Effects.Where(e => e.Level > 0)).ToList();
|
|
||||||
foreach (Effect effect in effects)
|
|
||||||
{
|
|
||||||
effect.AfterDeathCalculation(enemy, actor, _continuousKilling, _earnedMoney);
|
|
||||||
}
|
|
||||||
// 将死者移出队列
|
|
||||||
_queue.Remove(enemy);
|
|
||||||
if (_isTeamMode)
|
|
||||||
{
|
|
||||||
Team? killTeam = GetTeam(actor);
|
|
||||||
Team? deathTeam = GetTeam(enemy);
|
|
||||||
if (deathTeam != null)
|
|
||||||
{
|
|
||||||
if (deathTeam.GetActiveCharacters(this).Count == 0)
|
|
||||||
{
|
|
||||||
// 团灭了
|
|
||||||
_eliminatedTeams.Add(deathTeam);
|
|
||||||
_teams.Remove(deathTeam.Name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
List<Character> remain = deathTeam.GetActiveTeammates(this, enemy);
|
|
||||||
int remainCount = remain.Count;
|
|
||||||
if (remainCount > 0) WriteLine($"[ {deathTeam} ] 剩余成员:[ {string.Join(" ] / [ ", remain)} ]({remainCount} 人)");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (killTeam != null)
|
/// <summary>
|
||||||
|
/// 治疗一个目标
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="actor"></param>
|
||||||
|
/// <param name="target"></param>
|
||||||
|
/// <param name="heal"></param>
|
||||||
|
/// <param name="canRespawn"></param>
|
||||||
|
public void HealToTarget(Character actor, Character target, double heal, bool canRespawn = false)
|
||||||
{
|
{
|
||||||
if (MaxScoreToWin > 0 && killTeam.Score >= MaxScoreToWin)
|
if (target.HP == target.MaxHP)
|
||||||
{
|
{
|
||||||
List<Team> combinedTeams = [.. _eliminatedTeams, .. _teams.Values];
|
|
||||||
combinedTeams.Remove(killTeam);
|
|
||||||
_eliminatedTeams.Clear();
|
|
||||||
_eliminatedTeams.AddRange(combinedTeams.OrderByDescending(t => t.Score));
|
|
||||||
EndGameInfo(killTeam);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!_teams.Keys.Where(str => str != killTeam.Name).Any())
|
|
||||||
|
bool isDead = target.HP <= 0;
|
||||||
|
|
||||||
|
if (heal < 0) heal = 0;
|
||||||
|
if (target.HP > 0 || (isDead && canRespawn))
|
||||||
{
|
{
|
||||||
// 没有其他的团队了,游戏结束
|
target.HP += heal;
|
||||||
EndGameInfo(killTeam);
|
if (!LastRound.Heals.TryAdd(target, heal))
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (killTeam != null)
|
|
||||||
{
|
{
|
||||||
List<Character> actives = killTeam.GetActiveCharacters(this);
|
LastRound.Heals[target] += heal;
|
||||||
actives.Add(actor);
|
|
||||||
int remainCount = actives.Count;
|
|
||||||
if (remainCount > 0) WriteLine($"[ {killTeam} ] 剩余成员:[ {string.Join(" ] / [ ", actives)} ]({remainCount} 人)");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isDead && canRespawn)
|
||||||
|
{
|
||||||
|
if (target != actor)
|
||||||
|
{
|
||||||
|
WriteLine($"[ {target} ] 被 [ {actor} ] 复苏了,并回复了 {heal:0.##} 点生命值!!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WriteLine($"[ {target} ] 复苏了,并回复了 {heal:0.##} 点生命值!!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!_queue.Where(c => c != actor).Any())
|
WriteLine($"[ {target} ] 回复了 {heal:0.##} 点生命值!");
|
||||||
{
|
|
||||||
// 没有其他的角色了,游戏结束
|
|
||||||
EndGameInfo(actor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1211,10 +1262,10 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
double penetratedDEF = (1 - actor.PhysicalPenetration) * enemy.DEF;
|
double penetratedDEF = (1 - actor.PhysicalPenetration) * enemy.DEF;
|
||||||
|
|
||||||
// 物理伤害减免
|
// 物理伤害减免
|
||||||
double physicalDamageReduction = penetratedDEF / (penetratedDEF + 120);
|
double physicalDamageReduction = penetratedDEF / (penetratedDEF + General.GameplayEquilibriumConstant.DEFReductionFactor);
|
||||||
|
|
||||||
// 最终的物理伤害
|
// 最终的物理伤害
|
||||||
finalDamage = expectedDamage * (1 - physicalDamageReduction);
|
finalDamage = expectedDamage * (1 - Calculation.PercentageCheck(physicalDamageReduction + enemy.ExPDR));
|
||||||
|
|
||||||
// 暴击判定
|
// 暴击判定
|
||||||
effects = actor.Effects.Where(e => e.Level > 0).ToList();
|
effects = actor.Effects.Where(e => e.Level > 0).ToList();
|
||||||
@ -1355,6 +1406,79 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
return DamageResult.Normal;
|
return DamageResult.Normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ProcessCharacterDeath(Character character)
|
||||||
|
{
|
||||||
|
foreach (Character enemy in _roundDeaths)
|
||||||
|
{
|
||||||
|
// 给所有角色的特效广播角色死亡结算
|
||||||
|
List<Effect> effects = _queue.SelectMany(c => c.Effects.Where(e => e.Level > 0)).ToList();
|
||||||
|
foreach (Effect effect in effects)
|
||||||
|
{
|
||||||
|
effect.AfterDeathCalculation(enemy, character, _continuousKilling, _earnedMoney);
|
||||||
|
}
|
||||||
|
// 将死者移出队列
|
||||||
|
_queue.Remove(enemy);
|
||||||
|
if (_isTeamMode)
|
||||||
|
{
|
||||||
|
Team? killTeam = GetTeam(character);
|
||||||
|
Team? deathTeam = GetTeam(enemy);
|
||||||
|
|
||||||
|
if (MaxRespawnTimes != 0)
|
||||||
|
{
|
||||||
|
WriteLine($"\r\n=== 当前死亡竞赛比分 ===\r\n{string.Join("\r\n", Teams.OrderByDescending(kv => kv.Value.Score).Select(kv => kv.Key + ":" + kv.Value.Score + "(剩余存活人数:" + kv.Value.GetActiveCharacters(this).Count + ")"))}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deathTeam != null)
|
||||||
|
{
|
||||||
|
List<Character> remain = deathTeam.GetActiveCharacters(this);
|
||||||
|
int remainCount = remain.Count;
|
||||||
|
if (remainCount == 0)
|
||||||
|
{
|
||||||
|
// 团灭了
|
||||||
|
_eliminatedTeams.Add(deathTeam);
|
||||||
|
_teams.Remove(deathTeam.Name);
|
||||||
|
}
|
||||||
|
else if (MaxRespawnTimes == 0)
|
||||||
|
{
|
||||||
|
WriteLine($"[ {deathTeam} ] 剩余成员:[ {string.Join(" ] / [ ", remain)} ]({remainCount} 人)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (killTeam != null)
|
||||||
|
{
|
||||||
|
List<Character> actives = killTeam.GetActiveCharacters(this);
|
||||||
|
actives.Add(character);
|
||||||
|
int remainCount = actives.Count;
|
||||||
|
if (remainCount > 0 && MaxRespawnTimes == 0)
|
||||||
|
{
|
||||||
|
WriteLine($"[ {killTeam} ] 剩余成员:[ {string.Join(" ] / [ ", actives)} ]({remainCount} 人)");
|
||||||
|
}
|
||||||
|
if (!_teams.Keys.Where(str => str != killTeam.Name).Any())
|
||||||
|
{
|
||||||
|
// 没有其他的团队了,游戏结束
|
||||||
|
EndGameInfo(killTeam);
|
||||||
|
}
|
||||||
|
if (MaxScoreToWin > 0 && killTeam.Score >= MaxScoreToWin)
|
||||||
|
{
|
||||||
|
List<Team> combinedTeams = [.. _eliminatedTeams, .. _teams.Values];
|
||||||
|
combinedTeams.Remove(killTeam);
|
||||||
|
_eliminatedTeams.Clear();
|
||||||
|
_eliminatedTeams.AddRange(combinedTeams.OrderByDescending(t => t.Score));
|
||||||
|
EndGameInfo(killTeam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!_queue.Where(c => c != character).Any())
|
||||||
|
{
|
||||||
|
// 没有其他的角色了,游戏结束
|
||||||
|
EndGameInfo(character);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 死亡结算
|
/// 死亡结算
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -1363,6 +1487,10 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
public void DeathCalculation(Character killer, Character death)
|
public void DeathCalculation(Character killer, Character death)
|
||||||
{
|
{
|
||||||
if (!_continuousKilling.TryAdd(killer, 1)) _continuousKilling[killer] += 1;
|
if (!_continuousKilling.TryAdd(killer, 1)) _continuousKilling[killer] += 1;
|
||||||
|
if (!_maxContinuousKilling.TryAdd(killer, 1) && _continuousKilling[killer] > _maxContinuousKilling[killer])
|
||||||
|
{
|
||||||
|
_maxContinuousKilling[killer] = _continuousKilling[killer];
|
||||||
|
}
|
||||||
_stats[killer].Kills += 1;
|
_stats[killer].Kills += 1;
|
||||||
_stats[death].Deaths += 1;
|
_stats[death].Deaths += 1;
|
||||||
int money = Random.Shared.Next(250, 350);
|
int money = Random.Shared.Next(250, 350);
|
||||||
@ -1392,6 +1520,7 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
money += (coefficient + 1) * Random.Shared.Next(50, 100);
|
money += (coefficient + 1) * Random.Shared.Next(50, 100);
|
||||||
string termination = CharacterSet.GetContinuousKilling(coefficient);
|
string termination = CharacterSet.GetContinuousKilling(coefficient);
|
||||||
string msg = $"[ {killer} ] 终结了 [ {death} ]{(termination != "" ? " 的" + termination : "")},获得 {money} {General.GameplayEquilibriumConstant.InGameCurrency}!";
|
string msg = $"[ {killer} ] 终结了 [ {death} ]{(termination != "" ? " 的" + termination : "")},获得 {money} {General.GameplayEquilibriumConstant.InGameCurrency}!";
|
||||||
|
LastRound.DeathContinuousKilling.Add(msg);
|
||||||
if (assists.Length > 1)
|
if (assists.Length > 1)
|
||||||
{
|
{
|
||||||
msg += "助攻:[ " + string.Join(" ] / [ ", assists.Where(c => c != killer)) + " ]";
|
msg += "助攻:[ " + string.Join(" ] / [ ", assists.Where(c => c != killer)) + " ]";
|
||||||
@ -1401,6 +1530,7 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
string msg = $"[ {killer} ] 杀死了 [ {death} ],获得 {money} {General.GameplayEquilibriumConstant.InGameCurrency}!";
|
string msg = $"[ {killer} ] 杀死了 [ {death} ],获得 {money} {General.GameplayEquilibriumConstant.InGameCurrency}!";
|
||||||
|
LastRound.DeathContinuousKilling.Add(msg);
|
||||||
if (assists.Length > 1)
|
if (assists.Length > 1)
|
||||||
{
|
{
|
||||||
msg += "助攻:[ " + string.Join(" ] / [ ", assists.Where(c => c != killer)) + " ]";
|
msg += "助攻:[ " + string.Join(" ] / [ ", assists.Where(c => c != killer)) + " ]";
|
||||||
@ -1419,21 +1549,27 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
|
|
||||||
int kills = _continuousKilling[killer];
|
int kills = _continuousKilling[killer];
|
||||||
string continuousKilling = CharacterSet.GetContinuousKilling(kills);
|
string continuousKilling = CharacterSet.GetContinuousKilling(kills);
|
||||||
|
string actorContinuousKilling = "";
|
||||||
if (kills == 2 || kills == 3)
|
if (kills == 2 || kills == 3)
|
||||||
{
|
{
|
||||||
WriteLine("[ " + killer + " ] 完成了" + continuousKilling + "!");
|
actorContinuousKilling = "[ " + killer + " ] 完成了一次" + continuousKilling + "!";
|
||||||
}
|
}
|
||||||
else if (kills == 4)
|
else if (kills == 4)
|
||||||
{
|
{
|
||||||
WriteLine("[ " + killer + " ] 正在" + continuousKilling + "!");
|
actorContinuousKilling = "[ " + killer + " ] 正在" + continuousKilling + "!";
|
||||||
}
|
}
|
||||||
else if (kills > 4 && kills < 10)
|
else if (kills > 4 && kills < 10)
|
||||||
{
|
{
|
||||||
WriteLine("[ " + killer + " ] 已经" + continuousKilling + "!");
|
actorContinuousKilling = "[ " + killer + " ] 已经" + continuousKilling + "!";
|
||||||
}
|
}
|
||||||
else if (kills >= 10)
|
else if (kills >= 10)
|
||||||
{
|
{
|
||||||
WriteLine("[ " + killer + " ] 已经" + continuousKilling + "!拜托谁去杀了他吧!!!");
|
actorContinuousKilling = "[ " + killer + " ] 已经" + continuousKilling + "!拜托谁去杀了他吧!!!";
|
||||||
|
}
|
||||||
|
if (actorContinuousKilling != "")
|
||||||
|
{
|
||||||
|
LastRound.ActorContinuousKilling.Add(actorContinuousKilling);
|
||||||
|
WriteLine(actorContinuousKilling);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_earnedMoney.TryAdd(killer, money)) _earnedMoney[killer] += money;
|
if (!_earnedMoney.TryAdd(killer, money)) _earnedMoney[killer] += money;
|
||||||
@ -1467,8 +1603,34 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 进入复活倒计时
|
// 进入复活倒计时
|
||||||
double respawnTime = Math.Min(90, death.Level * 0.36 + times * 2.77);
|
double respawnTime = Calculation.Round2Digits(Math.Min(90, death.Level * 0.36 + times * 2.77 + kills * Random.Shared.Next(0, 3)));
|
||||||
_respawnCountdown.TryAdd(death, respawnTime);
|
_respawnCountdown.TryAdd(death, respawnTime);
|
||||||
|
LastRound.RespawnCountdowns.TryAdd(death, respawnTime);
|
||||||
|
WriteLine($"[ {death} ] 进入复活倒计时:{respawnTime:0.##} 时间!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除死者的施法
|
||||||
|
_castingSkills.Remove(death);
|
||||||
|
_castingSuperSkills.Remove(death);
|
||||||
|
|
||||||
|
// 因丢失目标而中断施法
|
||||||
|
List<Character> castingSkills = [.. _castingSkills.Keys];
|
||||||
|
foreach (Character caster in castingSkills)
|
||||||
|
{
|
||||||
|
SkillTarget st = _castingSkills[caster];
|
||||||
|
if (st.Targets.Remove(death) && st.Targets.Count == 0)
|
||||||
|
{
|
||||||
|
_castingSkills.Remove(caster);
|
||||||
|
if (caster.CharacterState == CharacterState.Casting)
|
||||||
|
{
|
||||||
|
caster.CharacterState = CharacterState.Actionable;
|
||||||
|
}
|
||||||
|
WriteLine($"[ {caster} ] 终止了 [ {st.Skill.Name} ] 的施法" + (_hardnessTimes[caster] > 3 ? ",并获得了 3 硬直时间的补偿。" : "。"));
|
||||||
|
if (_hardnessTimes[caster] > 3)
|
||||||
|
{
|
||||||
|
_hardnessTimes[caster] = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1489,7 +1651,7 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
CharacterStatistics statistics = CharacterStatistics[ec];
|
CharacterStatistics statistics = CharacterStatistics[ec];
|
||||||
string topCharacter = ec.ToString() +
|
string topCharacter = ec.ToString() +
|
||||||
(statistics.FirstKills > 0 ? " [ 第一滴血 ]" : "") +
|
(statistics.FirstKills > 0 ? " [ 第一滴血 ]" : "") +
|
||||||
(_continuousKilling.TryGetValue(ec, out int kills) && kills > 1 ? $" [ {CharacterSet.GetContinuousKilling(kills)} ]" : "") +
|
(_maxContinuousKilling.TryGetValue(ec, out int kills) && kills > 1 ? $" [ {CharacterSet.GetContinuousKilling(kills)} ]" : "") +
|
||||||
(_earnedMoney.TryGetValue(ec, out int earned) ? $" [ 已赚取 {earned} {General.GameplayEquilibriumConstant.InGameCurrency} ]" : "");
|
(_earnedMoney.TryGetValue(ec, out int earned) ? $" [ 已赚取 {earned} {General.GameplayEquilibriumConstant.InGameCurrency} ]" : "");
|
||||||
if (top == 1)
|
if (top == 1)
|
||||||
{
|
{
|
||||||
@ -1571,7 +1733,7 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
|
|
||||||
string topCharacter = respawning + ec.ToString() +
|
string topCharacter = respawning + ec.ToString() +
|
||||||
(statistics.FirstKills > 0 ? " [ 第一滴血 ]" : "") +
|
(statistics.FirstKills > 0 ? " [ 第一滴血 ]" : "") +
|
||||||
(_continuousKilling.TryGetValue(ec, out int kills) && kills > 1 ? $" [ {CharacterSet.GetContinuousKilling(kills)} ]" : "") +
|
(_maxContinuousKilling.TryGetValue(ec, out int kills) && kills > 1 ? $" [ {CharacterSet.GetContinuousKilling(kills)} ]" : "") +
|
||||||
(_earnedMoney.TryGetValue(ec, out int earned) ? $" [ 已赚取 {earned} {General.GameplayEquilibriumConstant.InGameCurrency} ]" : "") +
|
(_earnedMoney.TryGetValue(ec, out int earned) ? $" [ 已赚取 {earned} {General.GameplayEquilibriumConstant.InGameCurrency} ]" : "") +
|
||||||
$"({statistics.Kills} / {statistics.Assists}{(MaxRespawnTimes != 0 ? " / " + statistics.Deaths : "")})";
|
$"({statistics.Kills} / {statistics.Assists}{(MaxRespawnTimes != 0 ? " / " + statistics.Deaths : "")})";
|
||||||
topTeam += topCharacter + "\r\n";
|
topTeam += topCharacter + "\r\n";
|
||||||
@ -1671,7 +1833,7 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
_hardnessTimes[c] = Calculation.Round2Digits(_hardnessTimes[c] + 0.01);
|
_hardnessTimes[c] = Calculation.Round2Digits(_hardnessTimes[c] + 0.01);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
skill.OnSkillCasting(this, other);
|
skill.OnSkillCasting(this, other, []);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1779,6 +1941,14 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
}
|
}
|
||||||
statsTaken.TotalTakenDamage = Calculation.Round2Digits(statsTaken.TotalTakenDamage + damage);
|
statsTaken.TotalTakenDamage = Calculation.Round2Digits(statsTaken.TotalTakenDamage + damage);
|
||||||
}
|
}
|
||||||
|
if (LastRound.Damages.TryGetValue(characterTaken, out double damageTotal))
|
||||||
|
{
|
||||||
|
LastRound.Damages[characterTaken] = damageTotal + damage;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LastRound.Damages[characterTaken] = damage;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -1837,6 +2007,10 @@ namespace Milimoe.FunGame.Core.Model
|
|||||||
cancel = false;
|
cancel = false;
|
||||||
if (skill.SkillType == SkillType.SuperSkill) cancel = false;
|
if (skill.SkillType == SkillType.SuperSkill) cancel = false;
|
||||||
List<Character> targets = skill.SelectTargets(caster, enemys, teammates);
|
List<Character> targets = skill.SelectTargets(caster, enemys, teammates);
|
||||||
|
if (targets.Count == 0)
|
||||||
|
{
|
||||||
|
cancel = true;
|
||||||
|
}
|
||||||
return targets;
|
return targets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,6 +225,16 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public double INTtoMRFactor { get; set; } = 0.1;
|
public double INTtoMRFactor { get; set; } = 0.1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 每 1 点智力减少魔法消耗
|
||||||
|
/// </summary>
|
||||||
|
public double INTtoCastMPReduce { get; set; } = 0.00125;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 每 1 点智力减少能量消耗
|
||||||
|
/// </summary>
|
||||||
|
public double INTtoCastEPReduce { get; set; } = 0.00075;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 每 1 点敏捷增加行动速度
|
/// 每 1 点敏捷增加行动速度
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user