Files
Continentis/Assets/Scripts/MainGame/Combat/CombatCharacterController.cs
SoulliesOfficial c3b1561375 更新
2026-04-01 12:23:27 -04:00

297 lines
11 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Linq;
using Continentis.MainGame.Character;
using DG.Tweening;
using Lean.Pool;
using SLSFramework.General;
using SLSFramework.UModAssistance;
using UnityEngine;
using Object = UnityEngine.Object;
namespace Continentis.MainGame.Combat
{
[Serializable]
public partial class CombatCharacterController
{
[Header("References")]
public List<CharacterBase> characters;
public Dictionary<Fraction, List<CombatNPC>> npcs;
public CombatTeam playerTeam;
public List<PlayerHero> playerHeroes;
public List<CombatNPC> allies => npcs[Fraction.Ally];
public CombatTeam enemyTeam;
public List<CombatNPC> enemies => npcs[Fraction.Enemy];
public List<CombatNPC> neutrals => npcs[Fraction.Neutral];
public List<CharacterBase> actionOrderList;
public List<CombatCharacterViewBase> combatCharacterViews;
}
public partial class CombatCharacterController
{
public void Initialize(List<CharacterData> playerHeroDataList, List<CharacterData> enemyDataList)
{
characters = new List<CharacterBase>();
npcs = new Dictionary<Fraction, List<CombatNPC>>
{
{ Fraction.Ally, new List<CombatNPC>() },
{ Fraction.Enemy, new List<CombatNPC>() },
{ Fraction.Neutral, new List<CombatNPC>() }
};
playerTeam = new CombatTeam();
playerHeroes = new List<PlayerHero>();
enemyTeam = new CombatTeam();
actionOrderList = new List<CharacterBase>();
combatCharacterViews = new List<CombatCharacterViewBase>();
foreach (var data in playerHeroDataList)
{
PlayerHero hero = new PlayerHero(data, Fraction.Player);
CombatCharacterViewBase view = hero.GenerateCharacterView(new Vector3(-4.5f, -2, 0));
playerHeroes.Add(hero);
characters.Add(hero);
combatCharacterViews.Add(view);
}
foreach (var data in enemyDataList)
{
CombatNPC enemy = new CombatNPC(data, Fraction.Enemy);
CombatCharacterViewBase view = enemy.GenerateCharacterView(new Vector3(4.5f, -2, 0));
view.mainView.transform.localEulerAngles = new Vector3(0, 180, 0);
enemies.Add(enemy);
characters.Add(enemy);
combatCharacterViews.Add(view);
}
SetViewPositions(0);
//ModManager.CreateInstance<CharacterCombatBuffBase>("Basic.Buffs.Weak", 2).Apply(enemies[0]);
}
public void AddCombatNPC(params (CharacterData, Fraction)[] dataList)
{
foreach ((CharacterData, Fraction) npcData in dataList)
{
CharacterData data = npcData.Item1;
Fraction fraction = npcData.Item2;
if (fraction == Fraction.Player)
{
Debug.LogError("Cannot add Player fraction as CombatNPC.");
return;
}
CombatNPC npc = new CombatNPC(data, fraction);
npc.InitializeCards();
Vector3 eulerAngles = fraction == Fraction.Enemy ? new Vector3(0, 180, 0) : Vector3.zero;
CombatCharacterViewBase view = npc.GenerateCharacterView(new Vector3(0, -1, 0));
view.mainView.transform.localEulerAngles = eulerAngles;
npcs[fraction].Add(npc);
characters.Add(npc);
combatCharacterViews.Add(view);
CombatMainManager.Instance.eventCollection.onCharacterJoin.Invoke(npc);
}
SetViewPositions();
}
public void SetViewPositions(float transitionDuration = 0.25f)
{
float playerSideLeftBound = -7.5f;
float playerSideRightBound = -1.5f;
float playerBaseInterval = 2f;
if (playerHeroes.Count > 4)
{
playerBaseInterval = (playerSideRightBound - playerSideLeftBound) / (playerHeroes.Count - 1);
}
playerHeroes.Sort((x, y) => x.data.combatPositionOrder.CompareTo(y.data.combatPositionOrder));
for (int index = 0; index < playerHeroes.Count; index++)
{
float xPos = playerSideLeftBound + index * playerBaseInterval;
Vector3 position = new Vector3(xPos, -1, 0);
if (transitionDuration > 0f)
{
playerHeroes[index].characterView.transform.DOMove(position, transitionDuration)
.SetEase(Ease.InOutSine)
.OnComplete(SetViewHUDs)
.Play();
}
else
{
playerHeroes[index].characterView.transform.position = position;
SetViewHUDs();
}
}
float enemySideLeftBound = 1.5f;
float enemySideRightBound = 7.5f;
float enemyBaseInterval = 2f;
if (enemies.Count > 4)
{
enemyBaseInterval = (enemySideRightBound - enemySideLeftBound) / (enemies.Count - 1);
}
enemies.Sort((x, y) => y.data.combatPositionOrder.CompareTo(x.data.combatPositionOrder));
for (int index = 0; index < enemies.Count; index++)
{
float xPos = enemySideLeftBound + index * enemyBaseInterval;
Vector3 position = new Vector3(xPos, -1, 0);
if (transitionDuration > 0f)
{
enemies[index].characterView.transform.DOMove(position, transitionDuration)
.SetEase(Ease.InOutSine)
.OnComplete(SetViewHUDs)
.Play();
}
else
{
enemies[index].characterView.transform.position = position;
SetViewHUDs();
}
}
Debug.Log($"Enemy are sorted: {string.Join(", ", enemies.Select(e => e.data.displayName))}");
}
public void SetViewHUDs()
{
CombatUIManager.Instance.hudPage.Initialize(characters);
foreach (CharacterBase character in characters)
{
character.characterView.hudContainer.EnableHUD("MainAttributesBar");
character.characterView.hudContainer.EnableHUD("CharacterBuffCollection");
if (character is CombatNPC)
{
character.characterView.hudContainer.EnableHUD("Intention");
}
}
}
}
public partial class CombatCharacterController
{
public void SetActionOrder()
{
Dictionary<int, float> speeds = new Dictionary<int, float>();
for (var index = 0; index < characters.Count; index++)
{
CharacterBase character = characters[index];
float speed = character.GetAttribute("Speed");
if (character.fraction is Fraction.Player)
{
speed += 0.01f; // 玩家角色微增速度,确保同速度时玩家角色优先
}
speeds.Add(index, speed);
}
actionOrderList.Clear();
foreach (var pair in speeds.OrderByDescending(pair => pair.Value))
{
actionOrderList.Add(characters[pair.Key]);
}
}
}
public partial class CombatCharacterController
{
public void RemoveCharacter(CharacterBase character)
{
characters.Remove(character);
actionOrderList.Remove(character);
combatCharacterViews.Remove(character.characterView);
if (character is PlayerHero playerHero)
{
playerHeroes.Remove(playerHero);
}
else if (character is CombatNPC npc)
{
npcs[character.fraction].Remove(npc);
}
Object.Destroy(character.characterView.hudContainer.gameObject);
Object.Destroy(character.characterView.gameObject);
SetViewPositions();
CheckCombatEnd();
}
/// <summary>
/// 检查战斗胜负条件:敌方全灭→胜利,玩家方全灭→失败。
/// </summary>
private void CheckCombatEnd()
{
if (enemies.Count == 0)
{
CombatMainManager.Instance.EndCombat(isVictory: true);
}
else if (playerHeroes.Count == 0)
{
CombatMainManager.Instance.EndCombat(isVictory: false);
}
}
}
public partial class CombatCharacterController
{
public List<CharacterBase> GetAllAllies(CharacterBase character, bool includeSelf = false)
{
if (character.fraction is Fraction.Player or Fraction.Ally)
{
List<CharacterBase> alliesList = new List<CharacterBase>(playerHeroes);
alliesList.AddRange(npcs[Fraction.Ally]);
if (!includeSelf)
{
alliesList.Remove(character);
}
return alliesList;
}
else
{
return npcs[character.fraction].Cast<CharacterBase>().ToList();
}
}
public List<CharacterBase> GetAllEnemies(CharacterBase character)
{
if (character.fraction is Fraction.Player or Fraction.Ally)
{
return npcs[Fraction.Enemy].Cast<CharacterBase>().ToList();
}
else if (character.fraction is Fraction.Enemy)
{
List<CharacterBase> enemiesList = new List<CharacterBase>(playerHeroes);
enemiesList.AddRange(npcs[Fraction.Ally]);
return enemiesList;
}
else // Neutral中立单位视所有非中立方为敌人
{
List<CharacterBase> enemiesList = new List<CharacterBase>(playerHeroes);
enemiesList.AddRange(npcs[Fraction.Ally]);
enemiesList.AddRange(npcs[Fraction.Enemy]);
return enemiesList;
}
}
}
}