297 lines
11 KiB
C#
297 lines
11 KiB
C#
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;
|
||
}
|
||
}
|
||
}
|
||
} |