复制牌,保护buff显示调整

This commit is contained in:
SoulliesOfficial
2025-10-30 12:07:59 -04:00
parent b68eeda9af
commit 8b72c75128
33 changed files with 433 additions and 104 deletions

Binary file not shown.

View File

@@ -50,7 +50,10 @@ MonoBehaviour:
- CardData_Basic_Dazed
- CardData_Basic_Faint
- CardData_Basic_Oblivion
- CardData_Basic_BattlefieldExperience
- CardData_Basic_BodyAsShield
- CardData_Basic_Cover
- CardData_Basic_EchoOfHonor
- CardData_Basic_GuardianAura
- CardData_Basic_KightDefense
- CardData_Basic_KnightStrike

View File

@@ -0,0 +1,58 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 9a4129cdd7011ca46b83d8c17d9f3623, type: 3}
m_Name: CardData_Basic_BattlefieldExperience
m_EditorClassIdentifier: Assembly-CSharp::Continentis.MainGame.Card.CardData
modName: Basic
className: BattlefieldExperience
displayName: Card_Basic_BattlefieldExperience_DisplayName
cardRarity: 20
cardType: 10
keywords:
- TargetSelf
cardSprite: {fileID: 21300000, guid: f7aa890753b65ec48a3195d42c6a1f97, type: 3}
cardLayoutTags: []
functionText: Card_Basic_BattlefieldExperience_FunctionText
cardDescription:
baseWeight: 1
variableAttributes:
dictionaryList:
- Key: TargetCount
Value: 0
index: 0
isKeyDuplicated: 0
- Key: StaminaCost
Value: 1
index: 1
isKeyDuplicated: 0
- Key: ManaCost
Value: 0
index: 2
isKeyDuplicated: 0
dividerPosProp: 0.5
originalAttributes:
dictionaryList: []
dividerPosProp: 0.5
runtimeCurrentAttributes:
dictionaryList: []
dividerPosProp: 0.5
upgradeNode:
sourceCard: {fileID: 0}
isTerminalNode: 0
isInfiniteUpgrade: 0
maxUpgradeLevel: 0
upgradeCards: []
customDescriptions: []
prefabRefs: []
derivativeCardDataRefs:
- CardData_Basic_Strike
derivativeCharacterDataRefs: []

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f9d9239ddc8a8ca439bd10ba30e2c0ab
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,62 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 9a4129cdd7011ca46b83d8c17d9f3623, type: 3}
m_Name: CardData_Basic_BodyAsShield
m_EditorClassIdentifier:
modName: Basic
className: BodyAsShield
displayName: Card_Basic_BodyAsShield_DisplayName
cardRarity: 10
cardType: 10
keywords:
- Reuse
- TargetAllies
cardSprite: {fileID: 21300000, guid: 08151241767bc164da8ba328a76a9ced, type: 3}
cardLayoutTags: []
functionText: Card_Basic_BodyAsShield_FunctionText
cardDescription:
baseWeight: 1
variableAttributes:
dictionaryList:
- Key: StaminaCost
Value: 1
index: 0
isKeyDuplicated: 0
- Key: ManaCost
Value: 0
index: 1
isKeyDuplicated: 0
- Key: TargetCount
Value: 1
index: 2
isKeyDuplicated: 0
- Key: BuffCount_Protecting
Value: 1
index: 3
isKeyDuplicated: 0
dividerPosProp: 0.5
originalAttributes:
dictionaryList: []
dividerPosProp: 0.5
runtimeCurrentAttributes:
dictionaryList: []
dividerPosProp: 0.5
upgradeNode:
sourceCard: {fileID: 0}
isTerminalNode: 0
isInfiniteUpgrade: 0
maxUpgradeLevel: 0
upgradeCards: []
customDescriptions: []
prefabRefs: []
derivativeCardDataRefs: []
derivativeCharacterDataRefs: []

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 16ef46bc1b3e48b44a8415a273e3e4b1
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,58 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 9a4129cdd7011ca46b83d8c17d9f3623, type: 3}
m_Name: CardData_Basic_EchoOfHonor
m_EditorClassIdentifier: Assembly-CSharp::Continentis.MainGame.Card.CardData
modName: Basic
className: EchoOfHonor
displayName: Card_Basic_EchoOfHonor_DisplayName
cardRarity: 40
cardType: 10
keywords:
- TargetSelf
cardSprite: {fileID: 21300000, guid: 714816a67caa6d94e90b6f20b334a474, type: 3}
cardLayoutTags: []
functionText: Card_Basic_EchoOfHonor_FunctionText
cardDescription:
baseWeight: 1
variableAttributes:
dictionaryList:
- Key: TargetCount
Value: 0
index: 0
isKeyDuplicated: 0
- Key: StaminaCost
Value: 2
index: 1
isKeyDuplicated: 0
- Key: ManaCost
Value: 2
index: 2
isKeyDuplicated: 0
dividerPosProp: 0.5
originalAttributes:
dictionaryList: []
dividerPosProp: 0.5
runtimeCurrentAttributes:
dictionaryList: []
dividerPosProp: 0.5
upgradeNode:
sourceCard: {fileID: 0}
isTerminalNode: 0
isInfiniteUpgrade: 0
maxUpgradeLevel: 0
upgradeCards: []
customDescriptions: []
prefabRefs: []
derivativeCardDataRefs:
- CardData_Basic_Strike
derivativeCharacterDataRefs: []

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 11ed4b7bf1ead254abe97724fb3688fc
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -9,7 +9,7 @@ namespace Continentis.Mods.Basic.Cards
{
public void GenerateProtection(CharacterBase protector, CharacterBase target, int roundCount)
{
Protected protectedBuff = card.CreateCharacterBuff<Protected>(protector);
Protected protectedBuff = card.CreateCharacterBuff<Protected>();
protectedBuff.Apply(target, user, card);
Protecting protectingBuff = card.CreateCharacterBuff<Protecting>(target, roundCount, protectedBuff);
protectingBuff.Apply(protector, user, card);

View File

@@ -0,0 +1,30 @@
using System.Collections.Generic;
using Continentis.MainGame.Card;
using Continentis.MainGame.Character;
using Continentis.MainGame.Commands;
using SLSFramework.General;
using UnityEngine;
namespace Continentis.Mods.Basic.Cards
{
public class BattlefieldExperience : CardLogicBase
{
protected override void SetUpLogicComponents()
{
AddLogicComponent<CardLogicComponent_GenerateCards>();
}
protected override CommandBase PlayEffect(List<CharacterBase> targetList)
{
CommandGroup mainGroup = new CommandGroup(ExecutionMode.Sequential);
mainGroup.AddCommand(new Cmd_PlayAnimation(user.characterView, "Skill"));
mainGroup.AddCommand(new Cmd_Function(() =>
{
CardData holyWaterCardData = GetDerivativeCardData(0);
CardInstance.GenerateCardInstance(holyWaterCardData, user.team, "Hand");
}));
return mainGroup;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 2d882784f82e4404991185dbd3ea2ca0

View File

@@ -0,0 +1,28 @@
using System.Collections.Generic;
using Continentis.MainGame.Card;
using Continentis.MainGame.Character;
using Continentis.MainGame.Commands;
using Continentis.Mods.Basic.Buffs;
using SLSFramework.General;
using UnityEngine;
namespace Continentis.Mods.Basic.Cards
{
public class BodyAsShield : CardLogicBase
{
protected override void SetUpLogicComponents()
{
AddLogicComponent<CardLogicComponent_Protect>();
}
protected override CommandBase PlayEffect(List<CharacterBase> targetList)
{
CommandGroup mainGroup = TargetListCommandGroup(targetList,
new Cmd_PlayAnimation(user.characterView, "Skill"),
new Cmd_ParamFunction<CharacterBase>((target) =>
LogicComponent<CardLogicComponent_Protect>().GenerateProtection(user, target, GetAttribute("BuffCount_Protecting"))));
return mainGroup;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: a591880f990d0a945a6b76cce22e2234

View File

@@ -0,0 +1,37 @@
using System.Collections.Generic;
using Continentis.MainGame.Card;
using Continentis.MainGame.Character;
using Continentis.MainGame.Commands;
using SLSFramework.General;
using UnityEngine;
namespace Continentis.Mods.Basic.Cards
{
public class EchoOfHonor : CardLogicBase
{
protected override void SetUpLogicComponents()
{
AddLogicComponent<CardLogicComponent_GenerateCards>();
}
protected override CommandBase PlayEffect(List<CharacterBase> targetList)
{
CommandGroup mainGroup = new CommandGroup(ExecutionMode.Sequential);
mainGroup.AddCommand(new Cmd_PlayAnimation(user.characterView, "Skill"));
mainGroup.AddCommand(new Cmd_Function(() =>
{
if (user.deckSubmodule.HandPile.Exclude(this.cardInstance).TryGetRandom(out CardInstance randomHandCard))
{
CardInstance newCard = CardInstance.GenerateCardInstance(randomHandCard.cardLogic, user, "Hand");
newCard.cardLogic.SetAttribute("StaminaCost", 0);
newCard.GenerateHandCardView("Hand");
}
else
{
Debug.LogWarning("EchoOfHonor: No other cards in hand to copy.");
}
}));
return mainGroup;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 282b6253d383eac43817c8c9bd79aafe

View File

@@ -0,0 +1,16 @@
using UnityEngine;
public class IronWall : MonoBehaviour
{
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 62b78a6b24f5eac43a9ec432f9ad7f3e

View File

@@ -16,7 +16,7 @@ namespace Continentis.Mods.Basic.Cards
new Cmd_PlayAnimation(user.characterView, "Skill"),
new Cmd_ParamFunction<CharacterBase>((target) =>
{
Protected protectedBuff = CreateCharacterBuff<Protected>(user);
Protected protectedBuff = CreateCharacterBuff<Protected>();
protectedBuff.Apply(target, user, this);
Protecting protectingBuff = CreateCharacterBuff<Protecting>(target, GetAttribute("BuffCount_Protecting"), protectedBuff);
protectingBuff.Apply(user, user, this);

View File

@@ -1,3 +1,4 @@
using System.Collections.Generic;
using Continentis.MainGame;
using Continentis.MainGame.Character;
using Continentis.MainGame.Combat;
@@ -8,30 +9,28 @@ namespace Continentis.Mods.Basic.Buffs
{
public class Protected : CharacterCombatBuffBase
{
public CharacterBase protector;
public Protecting protectingBuff;
public List<Protecting> protectingSources;
public Protected(CharacterBase protector)
public Protected()
{
Initialize(BuffType.Neutral, BuffDispelLevel.DeathOnly, 100);
SetIdentification(protector.elementID.ToString());
this.protector = protector;
this.contentSubmodule = new ContentSubmodule(this)
.AddParameterGetter("Protector", () => protector.data.displayName);//TODO: 以后增加角色的ContentSubmodule
this.contentSubmodule = new ContentSubmodule(this);//TODO: 以后增加角色的ContentSubmodule
this.iconSubmodule = new IconSubmodule(this).SetTextFunctions();
this.eventSubmodule = new EventSubmodule(this);
this.eventSubmodule.onOpponentDecideAction.Add("Protected",
/*
this.eventSubmodule.onOpponentDecideAction.Add("Protected",
new EventUnit<CharacterBase, IntendedCard, CharacterBase>((opponent, intendedCard, originalTarget) =>
{
if (opponent is CombatNPC npc)
{
intendedCard.targets.Remove(originalTarget);
intendedCard.targets.Add(protector); //TODO: 后续用设计专门的函数决定目标改变
//intendedCard.targets.Add(protector); //TODO: 后续用设计专门的函数决定目标改变
}
}));
*/
}
public override bool OnBuffApply(out CharacterCombatBuffBase existingBuff)
@@ -40,7 +39,7 @@ namespace Continentis.Mods.Basic.Buffs
if (FindExistingSameBuff(out existingBuff))
{
return true; //独立处理直接返回true
return false;
}
return true;

View File

@@ -33,22 +33,37 @@ namespace Continentis.Mods.Basic.Buffs
public override bool OnBuffApply(out CharacterCombatBuffBase existingBuff)
{
this.protectedBuff ??= target.combatBuffSubmodule.GetBuff<Protected>(attachedCharacter.elementID.ToString());
this.protectedBuff.protectingBuff = this;
MainGameManager.Instance.basePrefabs.GenerateInfoText(contentSubmodule.displayName, attachedCharacter.characterView);
if (FindExistingSameBuff(out existingBuff))
{
Debug.Log("Existing same buff found.");
Protecting existProtecting = existingBuff as Protecting;
Debug.Log(existProtecting == null ? "Existing buff is not of type Protecting!" : "Existing Protecting buff found.");
if (existProtecting.target == this.target)
{
existProtecting.roundCountSubmodule.AddCount(this.roundCountSubmodule.remainingCount);
return false;
}
this.protectedBuff ??= target.combatBuffSubmodule.GetBuff<Protected>();
this.protectedBuff.protectingSources.Add(this);
return true; //独立处理直接返回true
}
Debug.Log("No existing same buff found.");
return true;
}
public override void OnBuffRemove()
{
base.OnBuffRemove();
protectedBuff?.OnBuffRemove();
protectedBuff.protectingSources.Remove(this);
if (protectedBuff.protectingSources.Count == 0)
{
protectedBuff.Remove();
}
}
}
}

View File

@@ -206,5 +206,8 @@ MonoBehaviour:
- CardData_Basic_Tactic
- CardData_Basic_Cover
- CardData_Basic_OathOfCourage
- CardData_Basic_BattlefieldExperience
- CardData_Basic_BodyAsShield
- CardData_Basic_EchoOfHonor
hudDataRefs:
- HUDData_Basic_Default

View File

@@ -40,6 +40,6 @@ Buff_Basic_SoulAbsorption_FunctionText,"Amplify the lifesteal effect by $Paramet
Buff_Basic_Heavy_DisplayName,Heavy,沉重,,,,,
Buff_Basic_Heavy_FunctionText,You can not draw cards.,你不能抽牌。,,,,,
Buff_Basic_Protected_DisplayName,Protected,被保护,,,,,
Buff_Basic_Protected_FunctionText,"You are protected by $ParameterString(""Protector"").","你正在被$ParameterString(""Protector"")保护。",,,,,
Buff_Basic_Protected_FunctionText,"You are protected by $ParameterString(""Protector"").",你正在被其他人保护。,,,,,
Buff_Basic_Protecting_DisplayName,Protecting,保护,,,,,
Buff_Basic_Protecting_FunctionText,"You are protecting $ParameterString(""Target""), for $ParameterInt(""Count"") rounds.","你正在$ParameterInt(""Count"")回合内保护$ParameterString(""Target"")。",,,,,
1 Key English Simplified Chinese Traditional Chinese Japanese Korean Vietnamese Thai
40 Buff_Basic_Protecting_DisplayName Protecting 保护
41 Buff_Basic_Protecting_FunctionText You are protecting $ParameterString("Target"), for $ParameterInt("Count") rounds. 你正在$ParameterInt("Count")回合内保护$ParameterString("Target")。
42
43
44
45

View File

@@ -90,4 +90,8 @@ MonoBehaviour:
Value:
index: 18
isKeyDuplicated: 0
- Key: Reuse
Value:
index: 19
isKeyDuplicated: 0
dividerPosProp: 0.3

View File

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

Before

Width:  |  Height:  |  Size: 2.2 MiB

After

Width:  |  Height:  |  Size: 2.2 MiB

View File

@@ -146,6 +146,20 @@ namespace Continentis.MainGame.Card
{
return ModManager.GetData<CardData>(cardData.derivativeCardDataRefs[index]);
}
/// <summary>
/// 获取衍生卡牌数据
/// </summary>
public CardData GetDerivativeCardData(string dataName)
{
if (cardData.derivativeCardDataRefs.Contains(dataName))
{
return ModManager.GetData<CardData>(dataName);
}
Debug.LogError($"Card {cardData.className} does not contain derivative card data '{dataName}'.");
return null;
}
}
/// <summary>

View File

@@ -63,7 +63,7 @@ namespace Continentis.MainGame.Card
public virtual void DetectTargetsValidity(out List<CharacterBase> valid, out List<CharacterBase> notMet, out List<CharacterBase> invalid)
{
List<CharacterBase> characters = CombatMainManager.Instance.characterController.characters;
invalid = new List<CharacterBase>();
invalid = new List<CharacterBase>(characters);
notMet = new List<CharacterBase>();
valid = new List<CharacterBase>();
@@ -71,98 +71,48 @@ namespace Continentis.MainGame.Card
if (targetCount <= -2)
{
Debug.LogError("Invalid target count setting on card: " + contentSubmodule.cardName);
return;
}
if (targetCount == 0 || HasKeyword("TargetSelf")) // 卡牌目标为自身
{
valid.Add(user);
invalid.AddRange(characters);
invalid.Remove(user);
}
else if (HasKeyword("TargetAllies")) // 卡牌目标为友方单位
{
if(user.fraction is Fraction.Ally or Fraction.Player)
{
foreach (CharacterBase character in characters)
{
if (character.fraction is Fraction.Ally or Fraction.Player)
{
valid.Add(character);
}
else
{
invalid.Add(character);
}
}
}
else
{
foreach (CharacterBase character in characters)
{
if (character.fraction == user.fraction)
{
valid.Add(character);
}
else
{
invalid.Add(character);
}
}
}
}
else if (HasKeyword("TargetEnemies")) // 卡牌目标为敌人
{
if (user.fraction is Fraction.Ally or Fraction.Player)
{
foreach (CharacterBase character in characters)
{
if (character.fraction is Fraction.Enemy or Fraction.Neutral)
{
valid.Add(character);
}
else
{
invalid.Add(character);
}
}
}
else
{
foreach (CharacterBase character in characters)
{
if (character.fraction != user.fraction)
{
valid.Add(character);
}
else
{
invalid.Add(character);
}
}
}
if (targetCount != -1)
{
if (valid.Any(target => target.statusSubmodule.HasStatus(StatusType.Taunt)))
{
List<CharacterBase> protectedTargets = valid
.Where(target => !target.statusSubmodule.HasStatus(StatusType.Taunt))
.ToList();
notMet.AddRange(protectedTargets);
valid.RemoveAll(target => !target.statusSubmodule.HasStatus(StatusType.Taunt));
}
}
}
else if(HasKeyword("TargetAll")) // 卡牌目标为全体
if (HasKeyword("TargetAll"))
{
valid.AddRange(characters);
}
else
{
valid.AddRange(characters);// 默认卡牌目标为所有单位
Debug.Log("No valid target found");
if (HasKeyword("TargetAllies"))
{
valid.AddRange(user.fraction is Fraction.Ally or Fraction.Player
? characters.Where(character => character.fraction is Fraction.Ally or Fraction.Player)
: characters.Where(character => character.fraction == user.fraction));
valid.Remove(user);
}
if (HasKeyword("TargetSelf"))
{
valid.Add(user);
}
if (HasKeyword("TargetEnemies"))
{
valid.AddRange(user.fraction is Fraction.Ally or Fraction.Player
? characters.Where(character => character.fraction is Fraction.Enemy or Fraction.Neutral)
: characters.Where(character => character.fraction != user.fraction));
//处理保护,嘲讽等
if (targetCount != -1)
{
List<CharacterBase> protectedTargets = valid.Where(target => target.statusSubmodule.HasStatus(StatusType.Protected)).ToList();
notMet.AddRange(protectedTargets);
valid.RemoveRange(protectedTargets);
}
}
}
foreach (CharacterBase validTarget in valid)
{
invalid.Remove(validTarget);
}
}
@@ -260,6 +210,7 @@ namespace Continentis.MainGame.Card
});
AfterPlayEffect(targetList);
playSubmodule.isDuringPlayEffect = false;
handCardView.isDuringPlaying = false;
}));
return true;
}
@@ -287,7 +238,7 @@ namespace Continentis.MainGame.Card
{
playerHero.deckSubmodule.ExhaustCard(cardInstance);
}
else
else if(!HasKeyword("Reuse"))
{
playerHero.deckSubmodule.DiscardCard(cardInstance);
CommandQueueManager.Instance.AddCommand(new Cmd_Function(() =>

View File

@@ -116,6 +116,10 @@ namespace Continentis.MainGame.Combat
}
}
}
character.eventSubmodule.onRoundStart.Invoke();
character.equipmentSubmodule.currentEquipments.ForEach(equipment => equipment.eventSubmodule.onRoundStart.Invoke());
character.combatBuffSubmodule.RoundStart();
}
NextAction();
@@ -126,6 +130,13 @@ namespace Continentis.MainGame.Combat
{
if (characterController.actionOrderList.Count == 0)
{
foreach (CharacterBase character in characterController.characters)
{
character.eventSubmodule.onRoundEnd.Invoke();
character.equipmentSubmodule.currentEquipments.ForEach(equipment => equipment.eventSubmodule.onRoundEnd.Invoke());
character.combatBuffSubmodule.RoundEnd();
}
NextRound();
return;
}

View File

@@ -103,6 +103,14 @@ namespace SLSFramework.General
return newList;
}
public static void RemoveRange<T>(this IList<T> list, IEnumerable<T> elements)
{
foreach (T element in elements)
{
list.Remove(element);
}
}
/// <summary>
/// 根据指定的过滤器函数,返回一个新的列表,包含符合条件的元素
/// </summary>