diff --git a/Entity/Character/Character.cs b/Entity/Character/Character.cs
index ab07f1b..ffd098d 100644
--- a/Entity/Character/Character.cs
+++ b/Entity/Character/Character.cs
@@ -749,11 +749,17 @@ namespace Milimoe.FunGame.Core.Entity
public double ExCDR { get; set; } = 0;
///
- /// 攻击距离 [ 与技能和物品相关 ] [ 单位:格 ]
+ /// 攻击距离 [ 与技能和物品相关 ] [ 单位:格(半径) ]
///
[InitOptional]
- public double ATR { get; set; } = 1;
-
+ public int ATR { get; set; } = 1;
+
+ ///
+ /// 行动力/可移动距离 [ 与技能和物品相关 ] [ 单位:格(半径) ]
+ ///
+ [InitOptional]
+ public int MOV { get; set; } = 5;
+
///
/// 暴击率(%) = [ 与敏捷相关 ] + 额外暴击率(%)
///
@@ -2017,6 +2023,7 @@ namespace Milimoe.FunGame.Core.Entity
c.Lifesteal = Lifesteal;
c.Shield = Shield.Copy();
c.ATR = ATR;
+ c.MOV = MOV;
c.MagicType = MagicType;
c.ImmuneType = ImmuneType;
}
@@ -2126,6 +2133,7 @@ namespace Milimoe.FunGame.Core.Entity
ExAccelerationCoefficient = c.ExAccelerationCoefficient;
ExCDR = c.ExCDR;
ATR = c.ATR;
+ MOV = c.MOV;
ExCritRate = c.ExCritRate;
ExCritDMG = c.ExCritDMG;
ExEvadeRate = c.ExEvadeRate;
diff --git a/Entity/Skill/Effect.cs b/Entity/Skill/Effect.cs
index f5ba582..514f097 100644
--- a/Entity/Skill/Effect.cs
+++ b/Entity/Skill/Effect.cs
@@ -2,6 +2,7 @@
using Milimoe.FunGame.Core.Api.Utility;
using Milimoe.FunGame.Core.Interface.Base;
using Milimoe.FunGame.Core.Interface.Entity;
+using Milimoe.FunGame.Core.Library.Common.Addon;
using Milimoe.FunGame.Core.Library.Constant;
namespace Milimoe.FunGame.Core.Entity
@@ -387,6 +388,16 @@ namespace Milimoe.FunGame.Core.Entity
}
+ ///
+ /// 时间流逝时 [ 地图用 ]
+ ///
+ ///
+ ///
+ public virtual void OnTimeElapsed(Grid grid, double elapsed)
+ {
+
+ }
+
///
/// 在完成伤害结算后
///
@@ -542,6 +553,18 @@ namespace Milimoe.FunGame.Core.Entity
}
+ ///
+ /// 开始选择移动目标前
+ ///
+ ///
+ ///
+ ///
+ ///
+ public virtual void BeforeSelectTargetGrid(Character character, List enemys, List teammates, GameMap map)
+ {
+
+ }
+
///
/// 开始选择目标前,修改可选择的 , 列表
/// 有两种,使用时注意判断是 还是
diff --git a/Entity/Skill/Skill.cs b/Entity/Skill/Skill.cs
index f4bfe72..f43a527 100644
--- a/Entity/Skill/Skill.cs
+++ b/Entity/Skill/Skill.cs
@@ -90,6 +90,11 @@ namespace Milimoe.FunGame.Core.Entity
///
public bool IsMagic => SkillType == SkillType.Magic;
+ ///
+ /// 是否无视施法距离(全图施法),魔法默认为 true,战技默认为 false
+ ///
+ public bool CastAnyWhere { get; set; } = false;
+
///
/// 施法距离 [ 单位:格 ]
///
@@ -254,6 +259,7 @@ namespace Milimoe.FunGame.Core.Entity
protected Skill(SkillType type, Character? character = null)
{
SkillType = type;
+ CastAnyWhere = SkillType == SkillType.Magic;
Character = character;
}
diff --git a/Interface/Base/IGamingQueue.cs b/Interface/Base/IGamingQueue.cs
index 3c6d468..695bf54 100644
--- a/Interface/Base/IGamingQueue.cs
+++ b/Interface/Base/IGamingQueue.cs
@@ -154,6 +154,16 @@ namespace Milimoe.FunGame.Core.Interface.Base
///
public Task UseItemAsync(Item item, Character caster, List enemys, List teammates);
+ ///
+ /// 选取移动目标
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public Task SelectTargetGridAsync(Character character, List enemys, List teammates, GameMap map);
+
///
/// 选取技能目标
///
diff --git a/Library/Common/Addon/Example/ExampleGameModule.cs b/Library/Common/Addon/Example/ExampleGameModule.cs
index 992634c..0ad8370 100644
--- a/Library/Common/Addon/Example/ExampleGameModule.cs
+++ b/Library/Common/Addon/Example/ExampleGameModule.cs
@@ -319,13 +319,36 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon.Example
public override string Author => "FunGamer";
- public override float Length => 12.0f;
+ public override int Length => 12;
- public override float Width => 12.0f;
+ public override int Width => 12;
- public override float Height => 6.0f;
+ public override int Height => 6;
public override float Size => 4.0f;
+
+ public override GameMap InitGamingQueue(IGamingQueue queue)
+ {
+ // 因为模组在模组管理器中都是单例的,所以每次游戏都需要返回一个新的地图对象给队列
+ GameMap map = new ExampleGameMap();
+
+ // 做一些绑定,以便介入游戏队列
+ /// 但是,传入的 queue 可能不是 ,要做类型检查
+ // 不使用框架的实现时,需要地图作者与游戏队列的作者做好适配
+ if (queue is GamingQueue gq)
+ {
+ gq.SelectTargetGrid += Gq_SelectTargetGrid;
+ }
+
+ return map;
+ }
+
+ private async Task Gq_SelectTargetGrid(GamingQueue queue, Character character, List enemys, List teammates, GameMap map)
+ {
+ // 介入选择,假设这里更新界面,让玩家选择目的地
+ await Task.CompletedTask;
+ return Grid.Empty;
+ }
}
///
diff --git a/Library/Common/Addon/GameMap.cs b/Library/Common/Addon/GameMap.cs
index 84bf570..e9cccee 100644
--- a/Library/Common/Addon/GameMap.cs
+++ b/Library/Common/Addon/GameMap.cs
@@ -1,5 +1,7 @@
using Milimoe.FunGame.Core.Api.Utility;
+using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Interface.Addons;
+using Milimoe.FunGame.Core.Interface.Base;
namespace Milimoe.FunGame.Core.Library.Common.Addon
{
@@ -28,17 +30,17 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon
///
/// 长度
///
- public abstract float Length { get; }
+ public abstract int Length { get; }
///
/// 宽度
///
- public abstract float Width { get; }
+ public abstract int Width { get; }
///
/// 高度
///
- public abstract float Height { get; }
+ public abstract int Height { get; }
///
/// 格子大小
@@ -49,6 +51,16 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon
/// 格子集
///
public Dictionary Grids { get; } = [];
+
+ ///
+ /// 格子集(基于坐标)
+ ///
+ public Dictionary<(int x, int y, int z), Grid> GridsByCoordinate { get; } = [];
+
+ ///
+ /// 角色集
+ ///
+ public Dictionary Characters { get; } = [];
///
/// 使用坐标获取格子,0号格子的坐标是(0, 0),如果你还有高度的话,则是(0, 0, 0)
@@ -57,14 +69,34 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon
///
///
///
- public Grid this[float x, float y, float z = 0] => Grids.Values.Where(g => g.X == x && g.Y == y && g.Z == z).FirstOrDefault();
+ public Grid? this[int x, int y, int z = 0]
+ {
+ get
+ {
+ if (GridsByCoordinate.TryGetValue((x, y, z), out Grid? grid))
+ {
+ return grid;
+ }
+ return null;
+ }
+ }
///
- /// 使用坐标获取格子,从0号开始
+ /// 使用编号获取格子,从0号开始
///
///
///
- public Grid this[int id] => Grids[id];
+ public Grid? this[long id]
+ {
+ get
+ {
+ if (Grids.TryGetValue(id, out Grid? grid))
+ {
+ return grid;
+ }
+ return null;
+ }
+ }
///
/// 加载标记
@@ -88,13 +120,15 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon
// 地图加载后,不允许再次加载此地图
IsLoaded = true;
// 生成格子
- for (float x = 0; x < Length; x++)
+ for (int x = 0; x < Length; x++)
{
- for (float y = 0; y < Width; y++)
+ for (int y = 0; y < Width; y++)
{
- for (float z = 0; z < Height; z++)
+ for (int z = 0; z < Height; z++)
{
- Grids.Add(Grids.Count, new(Grids.Count, x, y, z));
+ Grid grid = new(Grids.Count, x, y, z);
+ Grids.Add(Grids.Count, grid);
+ GridsByCoordinate.Add((x, y, z), grid);
}
}
}
@@ -118,5 +152,221 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon
{
return true;
}
+
+ ///
+ /// 获取角色当前所在的格子
+ ///
+ ///
+ ///
+ public Grid? GetCharacterCurrentGrid(Character character)
+ {
+ if (Characters.TryGetValue(character, out Grid? current))
+ {
+ return current;
+ }
+ return null;
+ }
+
+ ///
+ /// 强制设置角色当前所在的格子
+ ///
+ ///
+ ///
+ ///
+ public bool SetCharacterCurrentGrid(Character character, Grid target)
+ {
+ Grid? current = GetCharacterCurrentGrid(character);
+ current?.Characters.Remove(character);
+ if (Grids.ContainsValue(target))
+ {
+ target.Characters.Add(character);
+ Characters[character] = target;
+ return true;
+ }
+ return false;
+ }
+
+ ///
+ /// 将角色从地图中移除
+ ///
+ ///
+ ///
+ public void RemoveCharacter(Character character)
+ {
+ Grid? current = GetCharacterCurrentGrid(character);
+ current?.Characters.Remove(character);
+ Characters[character] = Grid.Empty;
+ }
+
+ ///
+ /// 获取以某个格子为中心,一定范围内的格子(曼哈顿距离),只考虑同一平面的格子,不包含中心格子。
+ ///
+ ///
+ ///
+ ///
+ public virtual List GetGridsByRange(Grid grid, int range)
+ {
+ List grids = [];
+
+ for (int dx = -range; dx <= range; ++dx)
+ {
+ for (int dy = -range; dy <= range; ++dy)
+ {
+ //限制在中心点周围范围内
+ if (Math.Abs(dx) + Math.Abs(dy) <= range)
+ {
+ //检查是否在棋盘范围内
+ int x = grid.X;
+ int y = grid.Y;
+ int z = grid.Z;
+ if (GridsByCoordinate.TryGetValue((x, y, z), out Grid? select) && select != null)
+ {
+ grids.Add(select);
+ }
+ }
+ }
+ }
+ grids.RemoveAll(g => g.Id == grid.Id);
+
+ return grids;
+ }
+
+ ///
+ /// 设置角色移动
+ ///
+ ///
+ ///
+ ///
+ /// 移动的步数,只算平面移动步数
+ public virtual int CharacterMove(Character character, Grid? current, Grid target)
+ {
+ if (current is null || current.Id < 0 || target.Id < 0 || !Grids.ContainsValue(target))
+ {
+ return -1;
+ }
+
+ Grid? realGrid = GetCharacterCurrentGrid(character);
+
+ if (current.Id == target.Id)
+ {
+ return 0;
+ }
+
+ // 记录走到某个格子时的步数
+ Queue<(Grid grid, int steps)> queue = new();
+ // 记录已访问的格子
+ HashSet visited = [];
+
+ // 将起始格子加入队列,步数为0,并标记为已访问
+ queue.Enqueue((current, 0));
+ visited.Add(current.Id);
+
+ while (queue.Count > 0)
+ {
+ var (currentGrid, currentSteps) = queue.Dequeue();
+
+ // 如果当前格子就是目标格子,则找到了最短路径
+ if (currentGrid.Id == target.Id)
+ {
+ realGrid?.Characters.Remove(character);
+ current.Characters.Remove(character);
+ target.Characters.Add(character);
+ Characters[character] = target;
+ return currentSteps;
+ }
+
+ // 定义平面移动的四个方向
+ (int dx, int dy)[] directions = [
+ (0, 1), // 上
+ (0, -1), // 下
+ (1, 0), // 右
+ (-1, 0) // 左
+ ];
+
+ foreach (var (dx, dy) in directions)
+ {
+ int nextX = currentGrid.X + dx;
+ int nextY = currentGrid.Y + dy;
+ int nextZ = currentGrid.Z;
+
+ // 尝试获取相邻格子
+ Grid? neighborGrid = this[nextX, nextY, nextZ];
+
+ // 如果相邻格子存在且未被访问过
+ if (neighborGrid != null && !visited.Contains(neighborGrid.Id))
+ {
+ visited.Add(neighborGrid.Id);
+ queue.Enqueue((neighborGrid, currentSteps + 1));
+ }
+ }
+ }
+
+ return -1;
+ }
+
+ ///
+ /// 初始化游戏队列
+ ///
+ ///
+ public virtual GameMap InitGamingQueue(IGamingQueue queue)
+ {
+ return this;
+ }
+
+ ///
+ /// 在事件流逝前处理
+ ///
+ ///
+ protected virtual void BeforeTimeElapsed(ref double timeToReduce)
+ {
+
+ }
+
+ ///
+ /// 在事件流逝后处理
+ ///
+ ///
+ protected virtual void AfterTimeElapsed(ref double timeToReduce)
+ {
+
+ }
+
+ ///
+ /// 时间流逝时,处理格子上的特效
+ ///
+ ///
+ public void OnTimeElapsed(double timeToReduce)
+ {
+ BeforeTimeElapsed(ref timeToReduce);
+
+ foreach (Grid grid in Grids.Values)
+ {
+ List effects = [.. grid.Effects];
+ foreach (Effect effect in effects)
+ {
+ if (effect.Durative)
+ {
+ if (effect.RemainDuration < timeToReduce)
+ {
+ // 移除特效前也完成剩余时间内的效果
+ effect.OnTimeElapsed(grid, effect.RemainDuration);
+ effect.RemainDuration = 0;
+ grid.Effects.Remove(effect);
+ }
+ else
+ {
+ effect.RemainDuration -= timeToReduce;
+ effect.OnTimeElapsed(grid, timeToReduce);
+ }
+ }
+ else
+ {
+ effect.OnTimeElapsed(grid, timeToReduce);
+ }
+ }
+ }
+
+ AfterTimeElapsed(ref timeToReduce);
+ }
}
}
diff --git a/Library/Common/Addon/Grid.cs b/Library/Common/Addon/Grid.cs
index 96c771a..2640717 100644
--- a/Library/Common/Addon/Grid.cs
+++ b/Library/Common/Addon/Grid.cs
@@ -3,8 +3,13 @@ using Milimoe.FunGame.Core.Entity;
namespace Milimoe.FunGame.Core.Library.Common.Addon
{
- public struct Grid(int id, float x, float y, float z)
+ public class Grid(int id, int x, int y, int z)
{
+ ///
+ /// 空格子
+ ///
+ public static Grid Empty { get; } = new Grid(-1, 0, 0, 0);
+
///
/// 格子编号
///
@@ -13,17 +18,17 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon
///
/// 格子在地图中的x坐标
///
- public float X { get; } = x;
+ public int X { get; } = x;
///
/// 格子在地图中的y坐标
///
- public float Y { get; } = y;
+ public int Y { get; } = y;
///
/// 格子在地图中的z坐标
///
- public float Z { get; } = z;
+ public int Z { get; } = z;
///
/// 是谁站在这格子上?
diff --git a/Library/Common/JsonConverter/CharacterConverter.cs b/Library/Common/JsonConverter/CharacterConverter.cs
index bb33128..abca358 100644
--- a/Library/Common/JsonConverter/CharacterConverter.cs
+++ b/Library/Common/JsonConverter/CharacterConverter.cs
@@ -198,7 +198,10 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
result.ExCDR = reader.GetDouble();
break;
case nameof(Character.ATR):
- result.ATR = reader.GetDouble();
+ result.ATR = reader.GetInt32();
+ break;
+ case nameof(Character.MOV):
+ result.MOV = reader.GetInt32();
break;
case nameof(Character.ExCritRate):
result.ExCritRate = reader.GetDouble();
@@ -309,6 +312,7 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
writer.WriteNumber(nameof(Character.ExAccelerationCoefficient), value.ExAccelerationCoefficient);
writer.WriteNumber(nameof(Character.ExCDR), value.ExCDR);
writer.WriteNumber(nameof(Character.ATR), value.ATR);
+ writer.WriteNumber(nameof(Character.MOV), value.MOV);
writer.WriteNumber(nameof(Character.ExCritRate), value.ExCritRate);
writer.WriteNumber(nameof(Character.ExCritDMG), value.ExCritDMG);
writer.WriteNumber(nameof(Character.ExEvadeRate), value.ExEvadeRate);
diff --git a/Library/Common/JsonConverter/SkillConverter.cs b/Library/Common/JsonConverter/SkillConverter.cs
index d7b3d26..1b88430 100644
--- a/Library/Common/JsonConverter/SkillConverter.cs
+++ b/Library/Common/JsonConverter/SkillConverter.cs
@@ -41,6 +41,9 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
case nameof(Skill.Level):
result.Level = reader.GetInt32();
break;
+ case nameof(Skill.CastAnyWhere):
+ result.CastAnyWhere = reader.GetBoolean();
+ break;
case nameof(Skill.CastRange):
result.CastRange = reader.GetInt32();
break;
@@ -128,6 +131,7 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
if (value.GeneralDescription.Length > 0) writer.WriteString(nameof(Skill.GeneralDescription), value.GeneralDescription);
if (value.Slogan.Length > 0) writer.WriteString(nameof(Skill.Slogan), value.Slogan);
if (value.Level > 0) writer.WriteNumber(nameof(Skill.Level), value.Level);
+ writer.WriteBoolean(nameof(Skill.CastAnyWhere), value.CastAnyWhere);
writer.WriteNumber(nameof(Skill.CastRange), value.CastRange);
if (value.CanSelectSelf) writer.WriteBoolean(nameof(Skill.CanSelectSelf), value.CanSelectSelf);
if (!value.CanSelectEnemy) writer.WriteBoolean(nameof(Skill.CanSelectEnemy), value.CanSelectEnemy);
diff --git a/Model/GamingQueue.cs b/Model/GamingQueue.cs
index bee9a44..2d058af 100644
--- a/Model/GamingQueue.cs
+++ b/Model/GamingQueue.cs
@@ -296,7 +296,7 @@ namespace Milimoe.FunGame.Core.Model
#endregion
- #region 战棋地图(#TODO)
+ #region 战棋地图
///
/// 加载地图
@@ -304,7 +304,7 @@ namespace Milimoe.FunGame.Core.Model
///
public void LoadGameMap(GameMap map)
{
- _map = map;
+ _map = map.InitGamingQueue(this);
}
#endregion
@@ -665,6 +665,9 @@ namespace Milimoe.FunGame.Core.Model
}
}
+ // 处理地图上的特效
+ _map?.OnTimeElapsed(timeToReduce);
+
// 移除到时间的特效
List effects = [.. character.Effects];
foreach (Effect effect in effects)
@@ -782,7 +785,7 @@ namespace Milimoe.FunGame.Core.Model
List rewards = GetRoundRewards(TotalRound, character);
// 基础硬直时间
- double baseTime = 10;
+ double baseTime = 0;
bool isCheckProtected = true;
// 队友列表
@@ -824,6 +827,14 @@ namespace Milimoe.FunGame.Core.Model
bool decided = false;
// 最大取消次数
int cancelTimes = 3;
+ // 此变量控制角色移动后可以继续选择其他的行动
+ bool moved = false;
+
+ Grid? currentGrid = null;
+ if (_map != null)
+ {
+ currentGrid = _map.GetCharacterCurrentGrid(character);
+ }
// 行动开始前,可以修改可选取的角色列表
Dictionary continuousKillingTemp = new(_continuousKilling);
@@ -847,7 +858,8 @@ namespace Milimoe.FunGame.Core.Model
bool isAI = CharactersInAI.Contains(character);
while (!decided && (!isAI || cancelTimes > 0))
{
- cancelTimes--;
+ if (moved) moved = false;
+ else cancelTimes--;
type = CharacterActionType.None;
// 是否能使用物品和释放技能
@@ -1008,7 +1020,7 @@ namespace Milimoe.FunGame.Core.Model
await OnCharacterNormalAttackAsync(character, targets);
character.NormalAttack.Attack(this, character, targets);
- baseTime = character.NormalAttack.RealHardnessTime;
+ baseTime += character.NormalAttack.RealHardnessTime;
effects = [.. character.Effects.Where(e => e.IsInEffect)];
foreach (Effect effect in effects)
{
@@ -1055,7 +1067,7 @@ namespace Milimoe.FunGame.Core.Model
await OnCharacterPreCastSkillAsync(character, skillTarget);
_castingSkills[character] = skillTarget;
- baseTime = skill.RealCastTime;
+ baseTime += skill.RealCastTime;
skill.OnSkillCasting(this, character, targets);
}
}
@@ -1083,7 +1095,7 @@ namespace Milimoe.FunGame.Core.Model
skill.BeforeSkillCasted();
character.EP -= cost;
- baseTime = skill.RealHardnessTime;
+ baseTime += skill.RealHardnessTime;
skill.CurrentCD = skill.RealCD;
skill.Enable = false;
LastRound.SkillCost = $"{-cost:0.##} EP";
@@ -1131,7 +1143,7 @@ namespace Milimoe.FunGame.Core.Model
skill.BeforeSkillCasted();
character.MP -= cost;
- baseTime = skill.RealHardnessTime;
+ baseTime += skill.RealHardnessTime;
skill.CurrentCD = skill.RealCD;
skill.Enable = false;
LastRound.SkillCost = $"{-cost:0.##} MP";
@@ -1146,7 +1158,7 @@ namespace Milimoe.FunGame.Core.Model
{
WriteLine($"[ {character} ] 放弃释放技能!");
// 放弃释放技能会获得3的硬直时间
- baseTime = 3;
+ if (baseTime == 0) baseTime = 3;
}
effects = [.. character.Effects.Where(e => e.IsInEffect)];
@@ -1184,7 +1196,7 @@ namespace Milimoe.FunGame.Core.Model
skill.BeforeSkillCasted();
character.EP -= cost;
- baseTime = skill.RealHardnessTime;
+ baseTime += skill.RealHardnessTime;
skill.CurrentCD = skill.RealCD;
skill.Enable = false;
LastRound.SkillCost = $"{-cost:0.##} EP";
@@ -1199,7 +1211,7 @@ namespace Milimoe.FunGame.Core.Model
{
WriteLine($"[ {character} ] 因能量不足放弃释放爆发技!");
// 放弃释放技能会获得3的硬直时间
- baseTime = 3;
+ if (baseTime == 0) baseTime = 3;
}
effects = [.. character.Effects.Where(e => e.IsInEffect)];
@@ -1224,7 +1236,7 @@ namespace Milimoe.FunGame.Core.Model
{
decided = true;
LastRound.Item = item;
- baseTime = skill.RealHardnessTime > 0 ? skill.RealHardnessTime : 5;
+ baseTime += skill.RealHardnessTime > 0 ? skill.RealHardnessTime : 5;
effects = [.. character.Effects.Where(e => e.IsInEffect)];
foreach (Effect effect in effects)
{
@@ -1235,7 +1247,7 @@ namespace Milimoe.FunGame.Core.Model
}
else if (type == CharacterActionType.EndTurn)
{
- baseTime = 3;
+ baseTime += 3;
if (character.CharacterState == CharacterState.NotActionable ||
character.CharacterState == CharacterState.ActionRestricted ||
character.CharacterState == CharacterState.BattleRestricted)
@@ -1249,13 +1261,23 @@ namespace Milimoe.FunGame.Core.Model
}
else if (type == CharacterActionType.Move)
{
- baseTime = 3;
- decided = true;
- WriteLine($"[ {character} ] 进行了移动,并结束了回合!");
- await OnCharacterMoveAsync(character);
+ if (_map != null)
+ {
+ baseTime += 4;
+ Grid target = await SelectTargetGridAsync(character, enemys, teammates, _map);
+ if (target.Id != -1)
+ {
+ int steps = _map.CharacterMove(character, currentGrid, target);
+ if (steps > 4) baseTime += 0.7 * steps;
+ moved = true;
+ WriteLine($"[ {character} ] 移动了 {steps} 步!");
+ await OnCharacterMoveAsync(character, target);
+ }
+ }
}
else
{
+ if (baseTime == 0) baseTime += 10;
decided = true;
WriteLine($"[ {character} ] 完全行动不能!");
}
@@ -2278,6 +2300,37 @@ namespace Milimoe.FunGame.Core.Model
return CharacterActionType.EndTurn;
}
+ ///
+ /// 选取移动目标
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task SelectTargetGridAsync(Character character, List enemys, List teammates, GameMap map)
+ {
+ List effects = [.. character.Effects.Where(e => e.IsInEffect)];
+ foreach (Effect effect in effects)
+ {
+ effect.BeforeSelectTargetGrid(character, enemys, teammates, map);
+ }
+ Grid target = await OnSelectTargetGridAsync(character, enemys, teammates, map);
+ if (target.Id != -1)
+ {
+ return target;
+ }
+ if (map.Characters.TryGetValue(character, out Grid? current) && current != null)
+ {
+ List grids = map.GetGridsByRange(current, character.MOV);
+ if (grids.Count > 0)
+ {
+ return grids[Random.Shared.Next(grids.Count)];
+ }
+ }
+ return Grid.Empty;
+ }
+
///
/// 选取技能目标
///
@@ -3269,6 +3322,24 @@ namespace Milimoe.FunGame.Core.Model
return await (SelectItem?.Invoke(this, character, items) ?? Task.FromResult- (null));
}
+ public delegate Task SelectTargetGridEventHandler(GamingQueue queue, Character character, List enemys, List teammates, GameMap map);
+ ///
+ /// 选取移动目标事件
+ ///
+ public event SelectTargetGridEventHandler? SelectTargetGrid;
+ ///
+ /// 选取移动目标事件
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ protected async Task OnSelectTargetGridAsync(Character character, List enemys, List teammates, GameMap map)
+ {
+ return await (SelectTargetGrid?.Invoke(this, character, enemys, teammates, map) ?? Task.FromResult(Grid.Empty));
+ }
+
public delegate Task
> SelectSkillTargetsEventHandler(GamingQueue queue, Character caster, Skill skill, List enemys, List teammates);
///
/// 选取技能目标事件
@@ -3543,7 +3614,7 @@ namespace Milimoe.FunGame.Core.Model
await (CharacterGiveUp?.Invoke(this, actor) ?? Task.CompletedTask);
}
- public delegate Task CharacterMoveEventHandler(GamingQueue queue, Character actor);
+ public delegate Task CharacterMoveEventHandler(GamingQueue queue, Character actor, Grid grid);
///
/// 角色移动事件
///
@@ -3552,10 +3623,11 @@ namespace Milimoe.FunGame.Core.Model
/// 角色移动事件
///
///
+ ///
///
- protected async Task OnCharacterMoveAsync(Character actor)
+ protected async Task OnCharacterMoveAsync(Character actor, Grid grid)
{
- await (CharacterMove?.Invoke(this, actor) ?? Task.CompletedTask);
+ await (CharacterMove?.Invoke(this, actor, grid) ?? Task.CompletedTask);
}
public delegate Task GameEndEventHandler(GamingQueue queue, Character winner);