2026-02-03 01:38:51 +08:00

488 lines
19 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Godot;
using Milimoe.FunGame.Core.Api.Utility;
using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Library.Common.Addon;
using Milimoe.FunGame.Core.Library.Constant;
using Milimoe.FunGame.Core.Model;
using Oshima.Core.Constant;
using Oshima.FunGame.OshimaModules.Effects.OpenEffects;
using Oshima.FunGame.OshimaModules.Models;
using Oshima.FunGame.OshimaServers.Service;
namespace Milimoe.GodotGame;
public partial class Fighting : Control
{
[Export]
public TileMapLayer TileMapLayer { get; set; }
[Export]
public Camera2D CameraFight { get; set; }
public Character Character { get; set; }
public Node ParentUI { get; set; }
public Node NovelUI { get; set; }
public RichTextLabel FightLog { get; set; }
public Vector2I StartCell { get; set; }
public EnemyBody Enemy { get; set; }
public GamingQueue GamingQueue => _gamingQueue;
public Dictionary<Character, CharacterStatistics> CharacterStatistics { get; } = [];
public static Dictionary<Character, CharacterStatistics> TeamCharacterStatistics { get; } = [];
public PluginConfig StatsConfig { get; } = new(nameof(Fighting), nameof(CharacterStatistics));
public PluginConfig TeamStatsConfig { get; } = new(nameof(Fighting), nameof(TeamCharacterStatistics));
public bool IsWeb { get; set; } = false;
public bool TeamMode { get; set; } = false;
public string Msg { get; set; } = "";
private GamingQueue _gamingQueue = null;
private bool _fastMode = false;
public override void _Ready()
{
InitCharacter();
}
public async Task<List<string>> StartGame(bool isWeb = false, bool isTeam = false)
{
IsWeb = isWeb;
TeamMode = isTeam;
try
{
List<string> result = [];
Msg = "";
List<Character> allCharactersInGame = [.. FunGameConstant.Characters.OrderBy(o => Random.Shared.Next()).Take(3)];
TeamGamingQueue tgq = null;
MixGamingQueue mgq = null;
int clevel = 60;
int slevel = 6;
int mlevel = 8;
// 升级和赋能
List<Character> characters = [];
for (int index = 0; index < allCharactersInGame.Count; index++)
{
Character c = allCharactersInGame[index];
c.Level = clevel;
c.NormalAttack.Level = mlevel;
FunGameService.AddCharacterSkills(c, 1, slevel, slevel);
foreach (Skill skillLoop in FunGameConstant.Skills)
{
Skill skill = skillLoop.Copy();
skill.Character = c;
skill.Level = slevel;
c.Skills.Add(skill);
}
foreach (Skill skillLoop in FunGameConstant.CommonPassiveSkills)
{
Skill passive = skillLoop.Copy();
passive.Character = c;
passive.Level = 1;
c.Skills.Add(passive);
}
c.EP = 100;
characters.Add(c);
}
Character.NormalAttack.Level = mlevel;
foreach (Skill skillLoop in FunGameConstant.Skills)
{
Skill skill = skillLoop.Copy();
skill.Character = Character;
skill.Level = slevel;
Character.Skills.Add(skill);
}
foreach (Skill skillLoop in FunGameConstant.CommonPassiveSkills)
{
Skill passive = skillLoop.Copy();
passive.Character = Character;
passive.Level = 1;
Character.Skills.Add(passive);
}
Character.EP = 100;
characters.Add(Character);
// 询问玩家需要选择哪个角色 (通过UI界面选择)
Character player = Character ?? throw new Exception("没有选择角色,游戏结束。");
// 创建顺序表并排序
Team team1 = null, team2 = null;
if (isTeam)
{
tgq = new(WriteLine)
{
GameplayEquilibriumConstant = OshimaGameModuleConstant.GameplayEquilibriumConstant
};
_gamingQueue = tgq;
WriteLine("=== 团队模式随机分组 ===");
// 打乱角色列表
List<Character> shuffledCharacters = [.. characters.OrderBy(c => Random.Shared.Next())];
// 创建两个团队
List<Character> group1 = [];
List<Character> group2 = [];
// 将角色交替分配到两个团队中
for (int cid = 0; cid < shuffledCharacters.Count; cid++)
{
Character thisCharacter = shuffledCharacters[cid];
if (cid % 2 == 0)
{
group1.Add(thisCharacter);
}
else
{
group2.Add(thisCharacter);
}
}
// 添加到团队字典,第一个为队长
tgq.AddTeam($"{group1.First().NickName}的小队", group1);
tgq.AddTeam($"{group2.First().NickName}的小队", group2);
foreach (Team team in tgq.Teams.Values)
{
WriteLine($"团队【{team.Name}】的成员:\r\n{string.Join("\r\n", team.Members)}\r\n");
if (team.IsOnThisTeam(player))
{
foreach (Character c in team.Members.Except([player]))
{
c.Promotion = 300;
}
team1 = team;
}
else
{
team.Members.ForEach(c => c.Promotion = 400);
team2 = team;
}
}
// 初始化角色
_gamingQueue.InitCharacters(characters);
}
else
{
mgq = new MixGamingQueue(characters, WriteLine)
{
GameplayEquilibriumConstant = OshimaGameModuleConstant.GameplayEquilibriumConstant
};
_gamingQueue = mgq;
}
// 启用调试模式
//_gamingQueue.IsDebug = true;
// 加载地图和绑定事件
_gamingQueue.LoadGameMap(new GodotMap(TileMapLayer));
_gamingQueue.UseQueueProtected = false;
if (_gamingQueue.Map != null)
{
GodotMap map = (GodotMap)_gamingQueue.Map;
HashSet<Grid> allocated = [];
List<Grid> allGrids = [.. map.Grids.Values];
if (isTeam && tgq != null && team1 != null && team2 != null)
{
// 团队模式放置角色
Grid currentGrid = map.GetGridByVector2I(StartCell);
List<Grid> grids = map.GetGridsByRange(currentGrid, 10);
foreach (Character character in characters)
{
Grid grid = grids.OrderBy(o => Random.Shared.Next()).FirstOrDefault(g => g.Characters.Count == 0);
map.SetCharacterCurrentGrid(character, grid);
}
map.SetCharacterCurrentGrid(Character, currentGrid);
}
else
{
// 非团队模式,随机放置角色
foreach (Character character in characters)
{
character.NormalAttack.GamingQueue = _gamingQueue;
Grid grid = Grid.Empty;
do
{
grid = allGrids[Random.Shared.Next(allGrids.Count)];
}
while (allocated.Contains(grid));
allocated.Add(grid);
map.SetCharacterCurrentGrid(character, grid);
}
}
}
// 绑定事件
//await Controller.SetQueue(_gamingQueue.HardnessTime);
//await Controller.SetCharacterStatistics(_gamingQueue.CharacterStatistics);
//_gamingQueue.TurnStartEvent += GamingQueue_TurnStart;
//_gamingQueue.DecideActionEvent += GamingQueue_DecideAction;
//_gamingQueue.SelectNormalAttackTargetsEvent += GamingQueue_SelectNormalAttackTargets;
//_gamingQueue.SelectSkillEvent += GamingQueue_SelectSkill;
//_gamingQueue.SelectSkillTargetsEvent += GamingQueue_SelectSkillTargets;
//_gamingQueue.SelectNonDirectionalSkillTargetsEvent += GamingQueue_SelectNonDirectionalSkillTargets;
//_gamingQueue.SelectItemEvent += GamingQueue_SelectItem;
//_gamingQueue.QueueUpdatedEvent += GamingQueue_QueueUpdated;
//_gamingQueue.TurnEndEvent += GamingQueue_TurnEnd;
//_gamingQueue.CharacterInquiryEvent += GamingQueue_CharacterInquiryEvent;
//_gamingQueue.CharacterActionTakenEvent += GamingQueue_CharacterActionTakenEvent
//_gamingQueue.SelectTargetGridEvent += GamingQueue_SelectTargetGrid;
//_gamingQueue.CharacterMoveEvent += GamingQueue_CharacterMove;
// 总游戏时长
double totalTime = 0;
// 开始空投
Msg = "";
int qMagicCardPack = 5;
int qWeapon = 5;
int qArmor = 5;
int qShoes = 5;
int qAccessory = 5;
DropItems(_gamingQueue, qMagicCardPack, qWeapon, qArmor, qShoes, qAccessory);
double nextDropItemTime = 40;
if (qMagicCardPack < 5) qMagicCardPack++;
if (qWeapon < 5) qWeapon++;
if (qArmor < 5) qArmor++;
if (qShoes < 5) qShoes++;
if (qAccessory < 5) qAccessory++;
// 初始化队列,准备开始游戏
_gamingQueue.InitActionQueue();
_gamingQueue.SetCharactersToAIControl(false, characters);
_gamingQueue.SetCharactersToAIControl(false, player);
_gamingQueue.CustomData.Add("player", player);
// 显示初始顺序表
_gamingQueue.DisplayQueue();
WriteLine($"你的角色是 [ {player} ],详细信息:{player.GetInfo()}");
// 总回合数
int maxRound = isTeam ? 9999 : 999;
// 随机回合奖励
Dictionary<long, bool> effects = [];
foreach (EffectID id in FunGameConstant.RoundRewards.Keys)
{
long effectID = (long)id;
bool isActive = false;
if (effectID > (long)EffectID.Active_Start)
{
isActive = true;
}
effects.Add(effectID, isActive);
}
_gamingQueue.InitRoundRewards(maxRound, 1, effects, id => FunGameConstant.RoundRewards[(EffectID)id]);
int i = 1;
while (i < maxRound)
{
Msg = "";
if (i == maxRound - 1)
{
if (isTeam)
{
WriteLine("两队打到天昏地暗,流局了!!");
break;
}
else
{
WriteLine($"=== 终局审判 ===");
Dictionary<Character, double> hpPercentage = [];
foreach (Character c in characters)
{
hpPercentage.TryAdd(c, c.HP / c.MaxHP);
}
double max = hpPercentage.Values.Max();
Character winner = hpPercentage.Keys.Where(c => hpPercentage[c] == max).First();
WriteLine("[ " + winner + " ] 成为了天选之人!!");
foreach (Character c in characters.Where(c => c != winner && c.HP > 0))
{
WriteLine("[ " + winner + " ] 对 [ " + c + " ] 造成了 99999999999 点真实伤害。");
_gamingQueue.DeathCalculation(winner, c);
}
mgq?.EndGameInfo(winner);
}
result.Add(Msg);
break;
}
// 检查是否有角色可以行动
Character characterToAct = _gamingQueue.NextCharacter();
// 处理回合
if (characterToAct != null)
{
// 获取该角色当前位置
if (_gamingQueue.Map != null)
{
Grid currentGrid = _gamingQueue.Map.GetCharacterCurrentGrid(characterToAct);
if (currentGrid != null) _gamingQueue.CustomData["currentGrid"] = currentGrid;
}
bool isGameEnd = false;
try
{
isGameEnd = _gamingQueue.ProcessTurn(characterToAct);
}
catch (Exception e)
{
WriteLine(e.ToString());
}
if (isGameEnd)
{
result.Add(Msg);
break;
}
if (isWeb) _gamingQueue.DisplayQueue();
}
string roundMsg = "";
if (_gamingQueue.LastRound.HasKill)
{
roundMsg = Msg;
Msg = "";
}
// 模拟时间流逝
double timeLapse = _gamingQueue.TimeLapse();
totalTime += timeLapse;
nextDropItemTime -= timeLapse;
if (roundMsg != "")
{
if (isWeb)
{
roundMsg += "\r\n" + Msg;
}
result.Add(roundMsg);
}
if (nextDropItemTime <= 0)
{
// 空投
Msg = "";
DropItems(_gamingQueue, qMagicCardPack, qWeapon, qArmor, qShoes, qAccessory);
WriteLine("");
nextDropItemTime = 40;
if (qMagicCardPack < 5) qMagicCardPack++;
if (qWeapon < 5) qWeapon++;
if (qArmor < 5) qArmor++;
if (qShoes < 5) qShoes++;
if (qAccessory < 5) qAccessory++;
}
await Task.Delay(1);
}
WriteLine("--- 游戏结束 ---");
WriteLine($"总游戏时长:{totalTime:0.##} {_gamingQueue.GameplayEquilibriumConstant.InGameTime}");
// 赛后统计
FunGameService.GetCharacterRating(_gamingQueue.CharacterStatistics, isTeam, tgq != null ? tgq.EliminatedTeams : []);
if ((isTeam && tgq != null && tgq.EliminatedTeams.Any(t => t.IsOnThisTeam(Character) && t.IsWinner)) || _gamingQueue.Eliminated.Last() == Character)
{
Enemy.Dead = true;
}
result.Add(Msg);
return result;
}
catch (Exception ex)
{
WriteLine(ex.ToString());
return [ex.ToString()];
}
}
public void WriteLine(string str = "")
{
Msg += str + "\r\n";
FightLog.AppendText(str.Trim() + "\r\n");
FightLog.ScrollToLine(FightLog.GetLineCount());
}
public void InitCharacter()
{
foreach (Character c in FunGameConstant.Characters)
{
CharacterStatistics.Add(c, new());
TeamCharacterStatistics.Add(c, new());
}
StatsConfig.LoadConfig();
TeamStatsConfig.LoadConfig();
foreach (Character character in CharacterStatistics.Keys)
{
if (StatsConfig.ContainsKey(character.ToStringWithOutUser()))
{
CharacterStatistics[character] = StatsConfig.Get<CharacterStatistics>(character.ToStringWithOutUser()) ?? CharacterStatistics[character];
}
}
foreach (Character character in TeamCharacterStatistics.Keys)
{
if (TeamStatsConfig.ContainsKey(character.ToStringWithOutUser()))
{
TeamCharacterStatistics[character] = TeamStatsConfig.Get<CharacterStatistics>(character.ToStringWithOutUser()) ?? TeamCharacterStatistics[character];
}
}
}
public static void DropItems(GamingQueue queue, int mQuality, int wQuality, int aQuality, int sQuality, int acQuality)
{
Item[] weapons = [.. FunGameConstant.Equipment.Where(i => i.Id.ToString().StartsWith("11") && (int)i.QualityType == wQuality)];
Item[] armors = [.. FunGameConstant.Equipment.Where(i => i.Id.ToString().StartsWith("12") && (int)i.QualityType == aQuality)];
Item[] shoes = [.. FunGameConstant.Equipment.Where(i => i.Id.ToString().StartsWith("13") && (int)i.QualityType == sQuality)];
Item[] accessorys = [.. FunGameConstant.Equipment.Where(i => i.Id.ToString().StartsWith("14") && (int)i.QualityType == acQuality)];
Item[] consumables = [.. FunGameConstant.AllItems.Where(i => i.ItemType == ItemType.Consumable && i.IsInGameItem)];
foreach (Character character in queue.AllCharacters)
{
Item a = null, b = null, c = null, d = null;
if (weapons.Length > 0) a = weapons[Random.Shared.Next(weapons.Length)];
if (armors.Length > 0) b = armors[Random.Shared.Next(armors.Length)];
if (shoes.Length > 0) c = shoes[Random.Shared.Next(shoes.Length)];
if (accessorys.Length > 0) d = accessorys[Random.Shared.Next(accessorys.Length)];
List<Item> drops = [];
if (a != null) drops.Add(a);
if (b != null) drops.Add(b);
if (c != null) drops.Add(c);
if (d != null) drops.Add(d);
mQuality = 2;
Item magicCardPack = FunGameService.GenerateMagicCardPack(8, (QualityType)mQuality);
if (magicCardPack != null)
{
foreach (Skill magic in magicCardPack.Skills.Magics)
{
magic.Level = 8;
}
magicCardPack.SetGamingQueue(queue);
queue.Equip(character, magicCardPack);
}
foreach (Item item in drops)
{
Item realItem = item.Copy();
realItem.SetGamingQueue(queue);
queue.Equip(character, realItem);
}
if (consumables.Length > 0 && character.Items.Count < 5)
{
for (int i = 0; i < 2; i++)
{
Item consumable = consumables[Random.Shared.Next(consumables.Length)].Copy();
consumable.Character = character;
character.Items.Add(consumable);
}
}
}
}
}