210 lines
7.9 KiB
C#
210 lines
7.9 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Continentis.MainGame.Card;
|
|
using Sirenix.OdinInspector;
|
|
using UnityEngine;
|
|
|
|
namespace Continentis.MainGame.Character
|
|
{
|
|
public enum Fraction
|
|
{
|
|
Player,
|
|
Ally,
|
|
Enemy,
|
|
Neutral
|
|
}
|
|
|
|
public interface ICardOwner
|
|
{
|
|
DeckSubmodule deckSubmodule { get; }
|
|
}
|
|
|
|
public partial class CharacterBase : ICardOwner
|
|
{
|
|
public CharacterData data;
|
|
|
|
public Fraction fraction;
|
|
|
|
[ShowInInspector]
|
|
public AttributeSubmodule attributeSubmodule { get; private set; }
|
|
|
|
[ShowInInspector]
|
|
public EventSubmodule eventSubmodule { get; private set; }
|
|
|
|
[ShowInInspector]
|
|
public EquipmentSubmodule equipmentSubmodule { get; private set; }
|
|
|
|
[ShowInInspector]
|
|
public DeckSubmodule deckSubmodule { get; private set; }
|
|
|
|
[ShowInInspector]
|
|
public IntentionSubmodule intentionSubmodule { get; private set; }
|
|
|
|
[ShowInInspector]
|
|
public StatusSubmodule statusSubmodule { get; private set; }
|
|
|
|
[ShowInInspector]
|
|
public CombatBuffSubmodule combatBuffSubmodule { get; private set; }
|
|
|
|
public void Initialize(Fraction fraction)
|
|
{
|
|
this.fraction = fraction;
|
|
|
|
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.attributeSubmodule.GetRoundCurrentAttribute("StaminaCost") <= stamina &&
|
|
card.cardLogic.attributeSubmodule.GetRoundCurrentAttribute("ManaCost") <= mana;
|
|
}
|
|
|
|
bool CheckAvailabilityAndSetTargets(CardInstance card, out List<CharacterBase> targets)
|
|
{
|
|
card.cardLogic.SetTargets(out List<CharacterBase> valid, out _, out _);
|
|
if (valid.Count == 0 || !card.cardLogic.CheckBeforePlay())
|
|
{
|
|
targets = null;
|
|
return false; // 无有效目标或无法使用则跳过
|
|
}
|
|
|
|
targets = new List<CharacterBase>();
|
|
int maximumTargets = card.cardLogic.attributeSubmodule.targetCount;
|
|
if (maximumTargets == -1 || maximumTargets >= valid.Count)
|
|
{
|
|
targets.AddRange(valid);
|
|
}
|
|
else
|
|
{
|
|
while (targets.Count < maximumTargets && valid.Count > 0)
|
|
{
|
|
CharacterBase target = valid[Random.Range(0, valid.Count)];
|
|
valid.Remove(target);
|
|
targets.Add(target);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
IntentionBase currentIntention = intentionSubmodule.currentIntention;
|
|
List<CardInstance> availableCards = deckSubmodule.PoolPile;
|
|
List<IntendedCard> intended = new List<IntendedCard>();
|
|
int currentStamina = attributeSubmodule.GetRoundCurrentGeneralAttribute("Stamina");
|
|
int remainingStamina = currentStamina - currentIntention.guaranteedStamina;
|
|
int currentMana = attributeSubmodule.GetRoundCurrentGeneralAttribute("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.attributeSubmodule.GetRoundCurrentAttribute("StaminaCost");
|
|
remainingMana -= card.cardLogic.attributeSubmodule.GetRoundCurrentAttribute("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.attributeSubmodule.GetRoundCurrentAttribute("StaminaCost");
|
|
remainingMana -= chosen.cardLogic.attributeSubmodule.GetRoundCurrentAttribute("ManaCost");
|
|
}
|
|
}
|
|
|
|
intentionSubmodule.intendedCards.AddRange(intended);
|
|
}
|
|
}
|
|
|
|
public partial class CharacterBase
|
|
{
|
|
public CombatCharacterViewBase GenerateCharacterView(Vector3 position)
|
|
{
|
|
GameObject prefab = MainGameManager.Instance.basePrefabs.combatCharacterView;
|
|
CombatCharacterViewBase characterView = Object.Instantiate(prefab, position, Quaternion.identity).GetComponent<CombatCharacterViewBase>();
|
|
characterView.character = this;
|
|
this.characterView = characterView;
|
|
return characterView;
|
|
}
|
|
}
|
|
} |