CTT/Server/Hotfix/Game/System/Map/PvpMapSystem.cs

511 lines
19 KiB
C#
Executable File
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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 == 23)
{
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;
}
}
}