222 lines
8.0 KiB
C#
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;
|
|
}
|
|
}
|
|
} |