Files
Continentis/Assets/Scripts/MainGame/Character/CharacterBase.cs
2025-10-25 07:49:39 -04:00

222 lines
8.0 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using Continentis.MainGame.Card;
using Continentis.MainGame.Combat;
using NaughtyAttributes;
using UnityEngine;
using Object = UnityEngine.Object;
using Random = UnityEngine.Random;
namespace Continentis.MainGame.Character
{
public enum Fraction
{
Player,
Ally,
Enemy,
Neutral
}
public interface ICardOwner
{
DeckSubmodule deckSubmodule { get; }
}
public partial class CharacterBase : ICardOwner, IGameElement
{
public Guid elementID { get; set; }
public CharacterData data;
public Fraction fraction;
public CombatTeam team;
public int actionCountThisRound;
[ShowNativeProperty]
public AttributeSubmodule attributeSubmodule { get; private set; }
[ShowNativeProperty]
public EventSubmodule eventSubmodule { get; private set; }
[ShowNativeProperty]
public EquipmentSubmodule equipmentSubmodule { get; private set; }
[ShowNativeProperty]
public DeckSubmodule deckSubmodule { get; private set; }
[ShowNativeProperty]
public IntentionSubmodule intentionSubmodule { get; private set; }
[ShowNativeProperty]
public StatusSubmodule statusSubmodule { get; private set; }
[ShowNativeProperty]
public CombatBuffSubmodule combatBuffSubmodule { get; private set; }
public void Initialize(Fraction fraction)
{
(this as IGameElement).Initialize();
this.fraction = fraction;
switch (fraction)
{
case Fraction.Player:
this.team = CombatMainManager.Instance.characterController.playerTeam;
break;
case Fraction.Enemy:
this.team = CombatMainManager.Instance.characterController.enemyTeam;
break;
default:
this.team = null;
break;
}
attributeSubmodule = new AttributeSubmodule(this);
equipmentSubmodule = new EquipmentSubmodule(this);
eventSubmodule = new EventSubmodule(this);
deckSubmodule = new DeckSubmodule(this);
intentionSubmodule = new IntentionSubmodule(this);
statusSubmodule = new StatusSubmodule(this);
combatBuffSubmodule = new CombatBuffSubmodule(this);
}
}
public partial class CharacterBase
{
public CombatCharacterViewBase characterView;
}
public partial class CharacterBase
{
public virtual void GetIntendedCards()
{
bool CanAfford(CardInstance card, int stamina, int mana)
{
return card.cardLogic.GetAttribute("StaminaCost") <= stamina &&
card.cardLogic.GetAttribute("ManaCost") <= mana;
}
bool CheckAvailabilityAndSetTargets(CardInstance card, out List<CharacterBase> targets)
{
card.cardLogic.DetectTargetsValidity(out List<CharacterBase> valid, out _, out _);
if (valid.Count == 0 || !card.cardLogic.CheckBeforePlay())
{
targets = null;
return false; // 无有效目标或无法使用则跳过
}
targets = card.cardLogic.SetRandomTargets(valid);
return true;
}
IntentionBase currentIntention = intentionSubmodule.currentIntention;
List<CardInstance> availableCards = deckSubmodule.PoolPile;
List<IntendedCard> intended = new List<IntendedCard>();
int currentStamina = GetAttribute("Stamina");
int remainingStamina = currentStamina - currentIntention.guaranteedStamina;
int currentMana = GetAttribute("Mana");
int remainingMana = currentMana - currentIntention.guaranteedMana;
List<CardInstance> forced = new List<CardInstance>();
List<CardInstance> normal = new List<CardInstance>();
foreach (CardInstance card in availableCards)
{
if (card.cardLogic.weightSubmodule.forceUse)
{
forced.Add(card);
}
else
{
normal.Add(card);
}
}
intentionSubmodule.intendedCards.Clear();
//(characterView.hudContainer.enablingHUDs["Intention"] as Intention)?.Clear();
// 1. 优先处理强制选择卡牌
foreach (CardInstance card in forced)
{
if (currentIntention.maxCardCount > 0 && intended.Count >= currentIntention.maxCardCount)
{
break; // 已达数量上限
}
if (CanAfford(card, remainingStamina, remainingMana))
{
if(!CheckAvailabilityAndSetTargets(card, out List<CharacterBase> targets))
{
continue; // 无有效目标或无法使用则跳过
}
intended.Add(new IntendedCard(card, targets));
remainingStamina -= card.cardLogic.GetAttribute("StaminaCost");
remainingMana -= card.cardLogic.GetAttribute("ManaCost");
}
// 行动力不足则跳过该卡
}
// 2. 在剩余普通卡牌中基于权重随机选取
while (intended.Count < currentIntention.maxCardCount)
{
// 筛选出当前资源下还能出的牌
List<CardInstance> affordableCards = normal.FindAll(card => CanAfford(card, remainingStamina, remainingMana));
if (affordableCards.Count == 0)
{
break;
}
float totalWeight = affordableCards.Sum(card => card.cardLogic.weightSubmodule.currentWeight);
if (totalWeight <= 0f) break;
float r = Random.value * totalWeight;
float accum = 0f;
CardInstance chosen = null;
foreach (CardInstance card in affordableCards)
{
accum += card.cardLogic.weightSubmodule.currentWeight;
if (r <= accum)
{
chosen = card;
break;
}
}
if (chosen != null)
{
if (!CheckAvailabilityAndSetTargets(chosen, out List<CharacterBase> targets))
{
normal.Remove(chosen);
continue; // 无有效目标或无法使用则跳过
}
intended.Add(new IntendedCard(chosen, targets));
normal.Remove(chosen);
remainingStamina -= chosen.cardLogic.GetAttribute("StaminaCost");
remainingMana -= chosen.cardLogic.GetAttribute("ManaCost");
}
}
intentionSubmodule.intendedCards.AddRange(intended);
}
}
public partial class CharacterBase
{
public CombatCharacterViewBase GenerateCharacterView(Vector3 position)
{
GameObject prefab = data.combatCharacterView;
CombatCharacterViewBase characterView = Object.Instantiate(prefab, position, Quaternion.identity).GetComponent<CombatCharacterViewBase>();
characterView.InitializeAnimations();
characterView.character = this;
this.characterView = characterView;
return characterView;
}
}
}