diff --git a/Service/Application.Domain.Entity/game/user/unit_user_map.cs b/Service/Application.Domain.Entity/game/user/unit_user_map.cs
new file mode 100644
index 0000000..5958593
--- /dev/null
+++ b/Service/Application.Domain.Entity/game/user/unit_user_map.cs
@@ -0,0 +1,28 @@
+using SqlSugar;
+using System;
+
+namespace Application.Domain.Entity
+{
+ [Tenant("Kg.SeaTime.Game")]
+ public class unit_user_map
+ {
+ ///
+ /// umId
+ ///
+ [SugarColumn(IsPrimaryKey = true, Length = 50)]
+ public string umId { get; set; }
+
+ ///
+ /// userId
+ ///
+ [SugarColumn(Length = 50, IsNullable = true)]
+ public string? userId { get; set; }
+
+ ///
+ /// cityId
+ ///
+ [SugarColumn(IsNullable = true)]
+ public int? cityId { get; set; }
+
+ }
+}
\ No newline at end of file
diff --git a/Service/Application.Domain.Entity/model/MapTemp.cs b/Service/Application.Domain.Entity/model/MapTemp.cs
new file mode 100644
index 0000000..e5d3550
--- /dev/null
+++ b/Service/Application.Domain.Entity/model/MapTemp.cs
@@ -0,0 +1,9 @@
+namespace Application.Domain.Entity;
+
+public class MapTemp
+{
+ public int cityId { get; set; }
+ public string cityName { get; set; }
+ public int copper { get; set; }
+ public int distance { get; set; }
+}
\ No newline at end of file
diff --git a/Service/Application.Domain/Config/GameConfig.cs b/Service/Application.Domain/Config/GameConfig.cs
index 12de65c..afc29d8 100644
--- a/Service/Application.Domain/Config/GameConfig.cs
+++ b/Service/Application.Domain/Config/GameConfig.cs
@@ -15,4 +15,5 @@ public static class GameConfig
public const int GameUserFriendMaxCount = 50;//好友最大上限人数
public const int GameAutoBagGoodsId = 10001;//百宝箱物品ID
public const int GameAutoDrugGoodsId = 10001;//急救箱物品ID
+ public const int GameToMapNeedCopper = 5;//传送每海里费用
}
\ No newline at end of file
diff --git a/Service/Application.Domain/Enum/GameEnum.cs b/Service/Application.Domain/Enum/GameEnum.cs
index c11bcbf..454aec9 100644
--- a/Service/Application.Domain/Enum/GameEnum.cs
+++ b/Service/Application.Domain/Enum/GameEnum.cs
@@ -50,5 +50,6 @@ public static class GameEnum
RetBlood,
RetMorale,
RetVigour,
+ MapTo,
}
}
\ No newline at end of file
diff --git a/Service/Application.Domain/Services/Interface/Map/IGameMapService.cs b/Service/Application.Domain/Services/Interface/Map/IGameMapService.cs
index 6b14d94..0dba7d9 100644
--- a/Service/Application.Domain/Services/Interface/Map/IGameMapService.cs
+++ b/Service/Application.Domain/Services/Interface/Map/IGameMapService.cs
@@ -23,6 +23,8 @@ public interface IGameMapService
Task GetUserOnMapInfo(string userId);
Task SetUserMapDefult(string userId);
Task GetToMapInfo(string userId, string toMap, bool isUpUserMap = true, bool isChangeCity = false);
+ Task> GetUserCityMapData(string userId);
+ Task AddUserCityMap(string userId, int cityId);
#endregion
#region 其他相关
diff --git a/Service/Application.Domain/Services/Service/Map/GameMapService.cs b/Service/Application.Domain/Services/Service/Map/GameMapService.cs
index 692f6d0..d824e64 100644
--- a/Service/Application.Domain/Services/Service/Map/GameMapService.cs
+++ b/Service/Application.Domain/Services/Service/Map/GameMapService.cs
@@ -290,6 +290,42 @@ public class GameMapService(ISqlSugarClient DbClient, IRedisCache redis) : IGame
}
}
+ public async Task> GetUserCityMapData(string userId)
+ {
+ string key = string.Format(UserCache.BaseCacheKey, "UserCityMap");
+ if (await redis.HExistsHashAsync(key, userId))
+ {
+ return await redis.GetHashAsync>(key, userId);
+ }
+
+ var db = DbClient.AsTenant().GetConnectionWithAttr();
+ var data = await db.Queryable().Where(it => it.userId == userId).ToListAsync();
+ await redis.AddHashAsync(key, userId, data);
+ return data;
+ }
+
+ private async Task ClearUserCityMapCache(string userId)
+ {
+ string key = string.Format(UserCache.BaseCacheKey, "UserCityMap");
+ await redis.DelHashAsync(key, userId);
+ }
+
+ public async Task AddUserCityMap(string userId, int cityId)
+ {
+ unit_user_map map = new unit_user_map();
+ map.umId = $"{userId}_{cityId}";
+ map.userId = userId;
+ map.cityId = cityId;
+ var db = DbClient.AsTenant().GetConnectionWithAttr();
+ bool result = await db.Storageable(map).ExecuteCommandAsync() > 0;
+ if (result)
+ {
+ await ClearUserCityMapCache(userId);
+ }
+
+ return result;
+ }
+
#endregion
#region 其他相关
diff --git a/Service/Application.Domain/Tool/Base/GameTool.cs b/Service/Application.Domain/Tool/Base/GameTool.cs
index 4730921..7d0b368 100644
--- a/Service/Application.Domain/Tool/Base/GameTool.cs
+++ b/Service/Application.Domain/Tool/Base/GameTool.cs
@@ -1,4 +1,6 @@
-namespace Application.Domain;
+using System.Drawing;
+
+namespace Application.Domain;
public class GameTool
{
@@ -87,4 +89,39 @@ public class GameTool
return weight;
}
+ #region 距离计算
+
+ ///
+ /// 计算海里
+ ///
+ ///
+ ///
+ ///
+ public static int ComputeMile(string onMap, string toMap)
+ {
+ string[] _OnMap = onMap.Split('_');
+ int sx = Convert.ToInt32(_OnMap[0]);
+ int sy = Convert.ToInt32(_OnMap[1]);
+ string[] _ToMap = toMap.Split('_');
+ int ex = Convert.ToInt32(_ToMap[0]);
+ int ey = Convert.ToInt32(_ToMap[1]);
+ return GetDistanceByLocation(sx, sy, ex, ey) * 10;
+ }
+
+ private static int GetDistance(PointF start, PointF end)
+ {
+ double value = Math.Sqrt(Math.Abs(start.X - end.X) * Math.Abs(start.X - end.X) + Math.Abs(start.Y - end.Y) * Math.Abs(start.Y - end.Y));
+
+ return Convert.ToInt32(value);
+ }
+
+ private static int GetDistanceByLocation(int onX, int onY, int toX, int toY)
+ {
+ PointF start = new PointF(onX, onY);
+ PointF end = new PointF(toX, toY);
+ return GetDistance(start, end);
+ }
+
+ #endregion 距离计算
+
}
\ No newline at end of file
diff --git a/Service/Application.Web/Controllers/Map/MapController.cs b/Service/Application.Web/Controllers/Map/MapController.cs
index 8bae3a3..5a5cbf1 100644
--- a/Service/Application.Web/Controllers/Map/MapController.cs
+++ b/Service/Application.Web/Controllers/Map/MapController.cs
@@ -16,17 +16,24 @@ public class MapController : ControllerBase
private readonly IGameChatService _chatService;
private readonly IUnitUserAttrService _attrService;
private readonly IMessageService _messageService;
+ private readonly IUnitUserWeight _weightService;
+ private readonly IUnitUserAccService _accService;
public MapController(IUnitUserService userService, IGameMapService mapService, IGameChatService chatService,
- IUnitUserAttrService attrService, IMessageService messageService)
+ IUnitUserAttrService attrService, IMessageService messageService, IUnitUserWeight weightService,
+ IUnitUserAccService accService)
{
_userService = userService;
_mapService = mapService;
_chatService = chatService;
_attrService = attrService;
_messageService = messageService;
+ _weightService = weightService;
+ _accService = accService;
}
+ #region 地图相关
+
///
/// 获取地图主页信息
///
@@ -167,6 +174,179 @@ public class MapController : ControllerBase
}
}
+
+ ///
+ /// 获取传送/航海城市列表
+ ///
+ ///
+ ///
+ ///
+ [HttpGet]
+ public async Task GetCityData(int npcId, int cityId)
+ {
+ string userId = StateHelper.userId;
+
+ #region NPC验证
+
+ var npcInfo = await _mapService.GetNpcInfo(npcId);
+ if (npcInfo == null)
+ {
+ return PoAction.Message("Npc不存在!");
+ }
+
+ if (npcInfo.status != 1)
+ {
+ return PoAction.Message("Npc不存在!");
+ }
+
+ if (!npcInfo.bus.Any(it => it.code == nameof(GameEnum.NpcBusCode.MapTo)))
+ {
+ return PoAction.Message("业务不可用!");
+ }
+
+ var onMap = await _mapService.GetUserOnMapId(userId);
+ if (npcInfo.mapId != onMap)
+ {
+ return PoAction.Message("Npc不存在!");
+ }
+
+ #endregion
+
+ var cityData = await _mapService.GetCityData();
+ cityData = cityData.FindAll(it => it.type == "DEF_MAP");
+
+ List area = cityData.FindAll(it => it.parent == 0);
+ if (cityId == 0)
+ {
+ cityId = area[0].cityId;
+ }
+
+ var onCityData = cityData.FindAll(it => it.parent == cityId);
+ var userCity = await _mapService.GetUserCityMapData(userId);
+ var AtCity = await _mapService.GetMapCityByMapId(onMap);
+
+ List city = new List();
+ onCityData.ForEach(item =>
+ {
+ if (userCity.Any(it => it.cityId == item.cityId) && item.cityId != AtCity)
+ {
+ MapTemp temp = new MapTemp();
+ temp.cityId = item.cityId;
+ temp.cityName = item.cityName;
+ temp.distance = GameTool.ComputeMile(onMap, item.toMap);
+ temp.copper = temp.distance * GameConfig.GameToMapNeedCopper;
+ city.Add(temp);
+ }
+ });
+ string tips = $"*传送消耗:{GameConfig.GameToMapNeedCopper}铜贝/海里
*等级低于80级不需要传送费!";
+ return PoAction.Ok(new { area, city, cityId, tips });
+ }
+
+ ///
+ /// 用户传送到地图
+ ///
+ ///
+ ///
+ ///
+ [HttpGet]
+ public async Task UserToMap(int npcId, int cityId)
+ {
+ string userId = StateHelper.userId;
+
+ #region NPC验证
+
+ var npcInfo = await _mapService.GetNpcInfo(npcId);
+ if (npcInfo == null)
+ {
+ return PoAction.Message("Npc不存在!");
+ }
+
+ if (npcInfo.status != 1)
+ {
+ return PoAction.Message("Npc不存在!");
+ }
+
+ if (!npcInfo.bus.Any(it => it.code == nameof(GameEnum.NpcBusCode.MapTo)))
+ {
+ return PoAction.Message("业务不可用!");
+ }
+
+ var onMap = await _mapService.GetUserOnMap(userId);
+ if (npcInfo.mapId != onMap.mapId)
+ {
+ return PoAction.Message("Npc不存在!");
+ }
+
+ #endregion
+
+ var cityInfo = await _mapService.GetCityInfo(cityId);
+ if (cityInfo == null)
+ {
+ return PoAction.Message("城市不存在!");
+ }
+
+ var userWeight = await _weightService.GetUserWeightInfo(userId);
+ if (userWeight.shipOnWeight > 0)
+ {
+ return PoAction.Message("背包中存在货物,不可传送,你可以进行航行!");
+ }
+
+ var onMapInfo = await _mapService.GetMapInfo(onMap.mapId);
+ if (onMapInfo.cityId == cityId)
+ {
+ return PoAction.Message("您已在当前城市,无需传送!");
+ }
+
+ var MySeaMap = await _mapService.GetUserCityMapData(userId);
+ if (MySeaMap.Any(it => it.cityId == cityId)==false)
+ {
+ return PoAction.Message("您暂未获取该城市海图!");
+ }
+
+ bool isCanTo = false;
+ var MyLev = await _attrService.GetUserLev(userId);
+ if (MyLev < 80)
+ {
+ isCanTo = true;
+ }
+
+ int need = 0;
+ if (isCanTo == false) //判断费用
+ {
+ var myAcc = await _accService.GetUserAccInfo(userId, nameof(AccEnum.AccType.copper));
+ need = GameTool.ComputeMile(onMap.mapId, cityInfo.toMap) * GameConfig.GameToMapNeedCopper;
+ if (myAcc < need)
+ {
+ return PoAction.Message("铜贝不足!");
+ }
+
+ isCanTo = true;
+ }
+
+ if (isCanTo)
+ {
+ if (await _mapService.UpdateUserOnMap(onMap, cityInfo.toMap))
+ {
+ if (need > 0)
+ {
+ await _accService.UpdateUserCopper(userId, 0, need, $"传送到【{cityInfo.cityName}】费用");
+ }
+
+ return PoAction.Ok(true);
+ }
+ else
+ {
+ return PoAction.Message("传送失败,请稍后尝试!");
+ }
+ }
+ else
+ {
+ return PoAction.Message("传送失败,请稍后尝试!");
+ }
+ }
+
+ #endregion
+
#region npc相关
///
diff --git a/Web/src/pages/map/run.vue b/Web/src/pages/map/run.vue
new file mode 100644
index 0000000..41a40c8
--- /dev/null
+++ b/Web/src/pages/map/run.vue
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/Web/src/pages/map/to.vue b/Web/src/pages/map/to.vue
new file mode 100644
index 0000000..c053286
--- /dev/null
+++ b/Web/src/pages/map/to.vue
@@ -0,0 +1,79 @@
+
+
+ 请选择城市:
+
+ {{ index + 1 }}.
{{ item.cityName }}({{ GameTool.FormatCopper(item.copper) }})
+
+
+ 暂无海图.
+
+
+
+ 【
+
+
+ {{ item.cityName }}
+
+ 】
+
+
+
+
\ No newline at end of file
diff --git a/Web/src/services/map/MapService.ts b/Web/src/services/map/MapService.ts
index 7d8cd81..137c4c4 100644
--- a/Web/src/services/map/MapService.ts
+++ b/Web/src/services/map/MapService.ts
@@ -31,6 +31,22 @@ export class MapService {
return await ApiService.Request("get", "/Map/Map/GetAutoMapPath", { toMap });
}
+ /**
+ * 获取传送/航海城市列表
+ * GET /Map/Map/GetCityData
+ */
+ static async GetCityData(npcId: number, cityId: number) {
+ return await ApiService.Request("get", "/Map/Map/GetCityData", { npcId, cityId });
+ }
+
+ /**
+ * 用户传送到地图
+ * GET /Map/Map/UserToMap
+ */
+ static async UserToMap(npcId: number, cityId: number) {
+ return await ApiService.Request("get", "/Map/Map/UserToMap", { npcId, cityId });
+ }
+
/**
* 获取NPC相关信息
* GET /Map/Map/GetNpcInfo