511 lines
19 KiB
C#
Executable File
511 lines
19 KiB
C#
Executable File
using Cal.DataTable;
|
||
using ET.EventType;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
|
||
namespace ET
|
||
{
|
||
public class PvpMapAwakeSystem: AwakeSystem<PvpMap>
|
||
{
|
||
public override void Awake(PvpMap self)
|
||
{
|
||
PvpMap.inatance = self;
|
||
self.timerId = TimerComponent.Instance.NewRepeatedTimer(30 * 1000, self.UpdatePer30);
|
||
}
|
||
}
|
||
|
||
public class PvpMapDestroySystem: DestroySystem<PvpMap>
|
||
{
|
||
public override void Destroy(PvpMap self)
|
||
{
|
||
TimerComponent.Instance.Remove(ref self.timerId);
|
||
}
|
||
}
|
||
|
||
public static class PvpMapSystem
|
||
{
|
||
class SendReword: AEvent<ET.EventType.UpdatePer1HourOfDay>
|
||
{
|
||
public override async ETTask Run(UpdatePer1HourOfDay args)
|
||
{
|
||
DateTime dateTime = DateTime.Now;
|
||
if (dateTime.DayOfWeek != System.DayOfWeek.Wednesday && dateTime.DayOfWeek != System.DayOfWeek.Friday)
|
||
{
|
||
return;
|
||
}
|
||
|
||
DateTime now = Game.TimeInfo.ToDateTime(args.now).ToLocalTime();
|
||
if (now.Hour == 22)
|
||
{
|
||
await PvpMap.inatance.SettlePvp();
|
||
}
|
||
|
||
await ETTask.CompletedTask;
|
||
}
|
||
}
|
||
|
||
public static void UpdatePer30(this PvpMap self)
|
||
{
|
||
if (PvpMap.inatance.CanPvp() != null) return;
|
||
ClearNotInSceneUnit(PersonalPvpType.Cupper, PvpMap.inatance.matchCupperList);
|
||
ClearNotInSceneUnit(PersonalPvpType.Sliver, PvpMap.inatance.matchSliverList);
|
||
ClearNotInSceneUnit(PersonalPvpType.Gold, PvpMap.inatance.matchGoldList);
|
||
PvpMap.inatance.MatchBattle(PvpMap.inatance.matchGoldList);
|
||
PvpMap.inatance.MatchBattle(PvpMap.inatance.matchSliverList);
|
||
PvpMap.inatance.MatchBattle(PvpMap.inatance.matchCupperList);
|
||
}
|
||
|
||
private static void ClearNotInSceneUnit(PersonalPvpType type, List<Unit> list)
|
||
{
|
||
try
|
||
{
|
||
MapScene mapScene = null;
|
||
switch (type)
|
||
{
|
||
case PersonalPvpType.Cupper:
|
||
mapScene = MapSceneComponent.Instance.GetMap(Sys_SceneId.Scene_PersonalPvp1 * 100 + 1);
|
||
break;
|
||
case PersonalPvpType.Sliver:
|
||
mapScene = MapSceneComponent.Instance.GetMap(Sys_SceneId.Scene_PersonalPvp2 * 100 + 1);
|
||
break;
|
||
case PersonalPvpType.Gold:
|
||
mapScene = MapSceneComponent.Instance.GetMap(Sys_SceneId.Scene_PersonalPvp3 * 100 + 1);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
if (mapScene == null) return;
|
||
using ListComponent<Unit> listComponent = ListComponent<Unit>.Create();
|
||
listComponent.List.AddRange(mapScene.GetAll());
|
||
for (int i = list.Count - 1; i >= 0; i--)
|
||
{
|
||
Unit unit = list[i];
|
||
if (!listComponent.List.Contains(unit))
|
||
{
|
||
list.RemoveAt(i);
|
||
}
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Log.Error(e);
|
||
}
|
||
}
|
||
|
||
public static async ETTask SettlePvp(this PvpMap self)
|
||
{
|
||
self.rankList.Clear();
|
||
List<PlayerData> list = await DBComponent.Instance.QueryJson<PlayerData>("{}");
|
||
using ListComponent<(long, int, int)> listComponent = ListComponent<(long, int, int)>.Create();
|
||
foreach (PlayerData data in list)
|
||
{
|
||
try
|
||
{
|
||
if (data.personalPvpCount > 0)
|
||
listComponent.List.Add((data.Id, data.personalScord, data.personalPvpCount));
|
||
data.personalPvpCount = 0;
|
||
data.personalScord = 0;
|
||
Unit _unit = MapUnitComponent.Instance.Get(data.Id);
|
||
if (_unit)
|
||
{
|
||
_unit.RemoveComponent<PlayerData>();
|
||
_unit.AddComponent(data);
|
||
}
|
||
|
||
UnitHelper.SaveComponenet(data);
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Log.Error(e);
|
||
}
|
||
}
|
||
|
||
listComponent.List.Sort((a, b) => -a.Item2.CompareTo(b.Item2));
|
||
try
|
||
{
|
||
Log.Info($"1 : {listComponent.List?[0].Item1} {listComponent.List?[0].Item2}");
|
||
Log.Info($"2 : {listComponent.List?[1].Item1} {listComponent.List?[1].Item2}");
|
||
Log.Info($"3 : {listComponent.List?[2].Item1} {listComponent.List?[2].Item2}");
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Log.Error(e);
|
||
}
|
||
|
||
int goldRank = 0, sliverRank = 0, cupperRank = 0;
|
||
for (int i = 0; i < listComponent.List.Count; i++)
|
||
{
|
||
(long id, int pvpScord, int pvpCount) = listComponent.List[i];
|
||
|
||
try
|
||
{
|
||
if (pvpScord >= 100)
|
||
{
|
||
int voucher = 500 - (10 * goldRank);
|
||
goldRank++;
|
||
if (voucher < 300) voucher = 300;
|
||
await MailHelper.AddItem(id, BagHelper.VoucherId, voucher, true, "", "竞技场奖励", "黄金段位的奖励", "系统");
|
||
continue;
|
||
}
|
||
|
||
if (pvpScord >= 50)
|
||
{
|
||
int voucher = 300 - (5 * sliverRank);
|
||
sliverRank++;
|
||
if (voucher < 50) voucher = 50;
|
||
await MailHelper.AddItem(id, BagHelper.VoucherId, voucher, true, "", "竞技场奖励", "白银段位的奖励", "系统");
|
||
}
|
||
else
|
||
{
|
||
if (pvpCount >= 20)
|
||
{
|
||
int voucher = 50 - (2 * cupperRank);
|
||
cupperRank++;
|
||
if (voucher > 0)
|
||
await MailHelper.AddItem(id, BagHelper.VoucherId, voucher, true, "", "竞技场奖励", $"青铜段位的奖励,你战斗了{pvpCount}次", "系统");
|
||
}
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Log.Error(e);
|
||
}
|
||
}
|
||
}
|
||
|
||
public static string CanPvp(this PvpMap self)
|
||
{
|
||
DateTime dateTime = DateTime.Now;
|
||
if (AppConfig.inst.isTest)
|
||
return null;
|
||
if (dateTime.DayOfWeek != System.DayOfWeek.Wednesday && dateTime.DayOfWeek != System.DayOfWeek.Friday)
|
||
{
|
||
return $"周三、周五 开启!";
|
||
}
|
||
|
||
DateTime start = new(dateTime.Year, dateTime.Month, dateTime.Day, 19, 00, 0, DateTimeKind.Local);
|
||
DateTime end = start.AddHours(2);
|
||
if (dateTime < start || dateTime > end)
|
||
{
|
||
return $"周三、周五 {start:HH:mm}~{end:HH:mm}开启!";
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
private static PersonalPvpType GetTypeBySceneId(int sceneId)
|
||
{
|
||
PersonalPvpType pvpType = sceneId switch
|
||
{
|
||
Sys_SceneId.Scene_PersonalPvp1 => PersonalPvpType.Cupper,
|
||
Sys_SceneId.Scene_PersonalPvp2 => PersonalPvpType.Sliver,
|
||
Sys_SceneId.Scene_PersonalPvp3 => PersonalPvpType.Gold,
|
||
_ => throw new Exception($"scene is wrong => {sceneId}")
|
||
};
|
||
return pvpType;
|
||
}
|
||
public static bool CanEnterPvpMap(this PvpMap self, PlayerData data, int mapId)
|
||
{
|
||
try
|
||
{
|
||
int sceneId = mapId / 100;
|
||
PersonalPvpType pvpType = GetTypeBySceneId(sceneId);
|
||
PersonalPvpType canEnterLevel = GetLevelType(self, data.personalScord);
|
||
if (canEnterLevel == pvpType)
|
||
return true;
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Log.Error(e);
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
public static async ETTask SettleBattle(this PvpMap self, Team win, Team fail)
|
||
{
|
||
try
|
||
{
|
||
Unit winner = MapUnitComponent.Instance.Get(win.LeaderId);
|
||
Unit failer = MapUnitComponent.Instance.Get(fail.LeaderId);
|
||
await SettleBattle(self, winner, failer);
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Log.Error(e);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 结算积分
|
||
/// </summary>
|
||
/// <param name="self"></param>
|
||
/// <param name="winner"></param>
|
||
/// <param name="failer"></param>
|
||
public static async ETTask SettleBattle(this PvpMap self, Unit winner, Unit failer)
|
||
{
|
||
try
|
||
{
|
||
PlayerData winData, failData;
|
||
if (!winner)
|
||
winData = await DBComponent.Instance.Query<PlayerData>(winner.Id);
|
||
else
|
||
winData = winner.GetComponent<PlayerData>();
|
||
if (!failer)
|
||
failData = await DBComponent.Instance.Query<PlayerData>(failer.Id);
|
||
else
|
||
failData = failer.GetComponent<PlayerData>();
|
||
winData.personalPvpCount++;
|
||
failData.personalPvpCount++;
|
||
NumericComponent num = winner.GetComponent<NumericComponent>();
|
||
NumericComponent failNum = failer.GetComponent<NumericComponent>();
|
||
switch (GetLevelType(self, winData.personalScord))
|
||
{
|
||
case PersonalPvpType.Cupper:
|
||
winData.personalScord += 4;
|
||
num.AddSet(NumericType.PvpMoney, 5);
|
||
failNum.AddSet(NumericType.PvpMoney, 3);
|
||
break;
|
||
case PersonalPvpType.Sliver:
|
||
winData.personalScord += 2;
|
||
failData.personalScord -= 1;
|
||
num.AddSet(NumericType.PvpMoney, 8);
|
||
failNum.AddSet(NumericType.PvpMoney, 5);
|
||
break;
|
||
case PersonalPvpType.Gold:
|
||
winData.personalScord += 1;
|
||
failData.personalScord -= 1;
|
||
num.AddSet(NumericType.PvpMoney, 12);
|
||
failNum.AddSet(NumericType.PvpMoney, 8);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
UnitHelper.SaveComponenet(num);
|
||
UnitHelper.SaveComponenet(failNum);
|
||
UnitHelper.SaveComponenet(winData);
|
||
UnitHelper.SaveComponenet(failData);
|
||
ModifyData(self, winData);
|
||
ModifyData(self, failData);
|
||
if (failData.personalScord < 0) failData.personalScord = 0;
|
||
SetPvpMap(self, winner, winData);
|
||
SetPvpMap(self, failer, failData);
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Log.Error(e);
|
||
}
|
||
}
|
||
|
||
private static void ModifyData(PvpMap self, PlayerData data)
|
||
{
|
||
for (LinkedListNode<(long, int)>? item = self.rankList.First; item != null; item = item.Next)
|
||
{
|
||
if (item.Value.Item1 == data.Id)
|
||
{
|
||
self.rankList.Remove(item);
|
||
break;
|
||
}
|
||
}
|
||
|
||
LinkedListHelper.InsertToLinkedListAndSort(self.rankList, (data.Id, data.personalScord), (a, b) => a.Item2 > b.Item2);
|
||
}
|
||
|
||
private static void SetPvpMap(this PvpMap self, Unit unit, PlayerData data)
|
||
{
|
||
try
|
||
{
|
||
if (data.personalPvpCount > ConstDefine.PersonalMaxBattleCount)
|
||
{
|
||
Game.EventSystem.Publish(new ET.EventType.BackMainCity { unit = unit, }).Coroutine();
|
||
return;
|
||
}
|
||
|
||
int sceneId = GetLevelType(self, data.personalScord) switch
|
||
{
|
||
PersonalPvpType.Cupper => Sys_SceneId.Scene_PersonalPvp1,
|
||
PersonalPvpType.Sliver => Sys_SceneId.Scene_PersonalPvp2,
|
||
PersonalPvpType.Gold => Sys_SceneId.Scene_PersonalPvp3,
|
||
_ => throw new Exception($"{GetLevelType(self, data.personalScord)} scord = {data.personalScord}"),
|
||
};
|
||
UnitScene unitScene = unit.GetComponent<UnitScene>();
|
||
if (unitScene.MapId / 100 == sceneId)
|
||
return;
|
||
Game.EventSystem.Publish(new ET.EventType.ChangeMap { unit = unit, mapId = sceneId * 100 + 1 }).Coroutine();
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Log.Error(e);
|
||
}
|
||
}
|
||
|
||
public static PersonalPvpType GetLevelType(this PvpMap self, int scord)
|
||
{
|
||
int index = (int) PersonalPvpType.Gold;
|
||
for (int i = 0; i < ConstDefine.PersonalPvpScordArr.Length; i++)
|
||
{
|
||
if (ConstDefine.PersonalPvpScordArr[i] > scord)
|
||
{
|
||
index = i - 1;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (index < 0) index = 0;
|
||
return (PersonalPvpType) index;
|
||
}
|
||
|
||
public static string RequestMatch(this PvpMap self, Unit unit, int unitSceneMapId)
|
||
{
|
||
PlayerData data = unit.GetComponent<PlayerData>();
|
||
if (data == null)
|
||
{
|
||
Log.Error($"【{UserComponent.Instance.Get(unit.Id)?.NickName}({unit.Id})】无 data");
|
||
return "系统错误";
|
||
}
|
||
|
||
if (data.personalPvpCount > ConstDefine.PersonalMaxBattleCount)
|
||
{
|
||
return "战斗次数达到上限";
|
||
}
|
||
|
||
PersonalPvpType type = GetLevelType(self, data.personalScord);
|
||
int sceneId = unitSceneMapId / 100;
|
||
PersonalPvpType pvpType = GetTypeBySceneId(sceneId);
|
||
if (type != pvpType)
|
||
{
|
||
Game.EventSystem.Publish(new ET.EventType.BackMainCity { unit = unit, }).Coroutine();
|
||
return "上次已结算";
|
||
}
|
||
|
||
UnitScene unitScene = unit.GetComponent<UnitScene>();
|
||
UnitSceneType unitSceneType = MapHelper.GetMapType(unitScene.MapId / 100);
|
||
if (unitSceneType != UnitSceneType.PersonalPvp)
|
||
{
|
||
return "只能在竞技场匹配";
|
||
}
|
||
|
||
if (unit.teamState == TeamState.Fight)
|
||
{
|
||
return "战斗中...";
|
||
}
|
||
|
||
return Mathch(self, unit, type);
|
||
}
|
||
|
||
private static string Mathch(PvpMap self, Unit unit, PersonalPvpType type)
|
||
{
|
||
List<Unit> list = null;
|
||
switch (type)
|
||
{
|
||
case PersonalPvpType.Cupper:
|
||
list = self.matchCupperList;
|
||
break;
|
||
case PersonalPvpType.Sliver:
|
||
list = self.matchSliverList;
|
||
break;
|
||
case PersonalPvpType.Gold:
|
||
list = self.matchGoldList;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
if (list == null)
|
||
{
|
||
Log.Error($"list = null");
|
||
return "系统错误";
|
||
}
|
||
|
||
if (list.Contains(unit))
|
||
{
|
||
return "正在匹配中";
|
||
}
|
||
|
||
list.Add(unit);
|
||
return "正在匹配...";
|
||
}
|
||
|
||
static void MatchBattle(this PvpMap self, List<Unit> list)
|
||
{
|
||
if (list.Count < 2) return;
|
||
using ListComponent<Unit> listComponent = ListComponent<Unit>.Create();
|
||
listComponent.List.AddRange(list.FindAll(t =>
|
||
t &&
|
||
t.teamState != TeamState.Fight &&
|
||
t.GetComponent<PlayerData>().personalPvpCount < ConstDefine.PersonalMaxBattleCount
|
||
));
|
||
listComponent.List.Sort((a, b) =>
|
||
{
|
||
try
|
||
{
|
||
if (!a)
|
||
return -1;
|
||
if (!b)
|
||
return 1;
|
||
PlayerData dataA = a.GetComponent<PlayerData>();
|
||
PlayerData dataB = b.GetComponent<PlayerData>();
|
||
if (dataA.personalScord != dataB.personalScord)
|
||
{
|
||
return -dataA.personalScord.CompareTo(dataB.personalScord);
|
||
}
|
||
|
||
NumericComponent numA = a.GetComponent<NumericComponent>();
|
||
NumericComponent numB = b.GetComponent<NumericComponent>();
|
||
int levelA = numA.GetAsInt(NumericType.Level);
|
||
int levelB = numB.GetAsInt(NumericType.Level);
|
||
return -levelA.CompareTo(levelB);
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Log.Error(e);
|
||
}
|
||
|
||
return -1;
|
||
});
|
||
for (int i = 1; i < listComponent.List.Count; i += 2)
|
||
{
|
||
Unit unitA = listComponent.List[i - 1];
|
||
Unit unitB = listComponent.List[i];
|
||
StartBattle(unitA, unitB).Coroutine();
|
||
}
|
||
}
|
||
|
||
private static async ETTask StartBattle(Unit unit, Unit target)
|
||
{
|
||
await TimerComponent.Instance.WaitFrameAsync();
|
||
Team team = TeamComponent.Instance.Get(unit.TeamLeaderId);
|
||
Team targetTeam = TeamComponent.Instance.Get(target.TeamLeaderId);
|
||
CopyBattle battle = BattleMgrCompnent.Instance.CreateBattle(team);
|
||
battle.Init(team, targetTeam, CopyConfigId.PersonalPvpBattle, 0);
|
||
}
|
||
|
||
public static void Remove(this PvpMap self, Unit unit)
|
||
{
|
||
if (self.CanPvp() != null) return;
|
||
self.matchCupperList.Remove(unit);
|
||
self.matchSliverList.Remove(unit);
|
||
self.matchGoldList.Remove(unit);
|
||
}
|
||
|
||
public static async ETTask<string> GetRankList(this PvpMap self, List<PvpRankInfo> list)
|
||
{
|
||
for (LinkedListNode<(long, int)>? item = self.rankList.First; item != null; item = item.Next)
|
||
{
|
||
try
|
||
{
|
||
User user = await UserComponent.Instance.Query(item.Value.Item1);
|
||
list.Add(new PvpRankInfo { name = user.NickName, jobIs = user.JobId, level = user.Level, scord = item.Value.Item2 });
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Log.Error(e);
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
}
|
||
} |