多轮审查和修复
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
using UnityEngine;
|
||||
using BaseGames.Core.Save;
|
||||
|
||||
namespace BaseGames.Progression
|
||||
{
|
||||
/// <summary>收集指定数量魅饰(Charm)的成就条件。</summary>
|
||||
[CreateAssetMenu(menuName = "Achievement/Condition/CollectedAllCharms", fileName = "COND_CollectedAllCharms")]
|
||||
public class CollectedAllCharmsCondition : AchievementCondition
|
||||
{
|
||||
[Tooltip("需要收集的魅饰总数(游戏设计时确定)")]
|
||||
[Min(1)] public int totalCharmsCount = 45;
|
||||
|
||||
public override bool IsMet(SaveData save)
|
||||
=> save?.Equipment != null && save.Equipment.OwnedCharmIds.Count >= totalCharmsCount;
|
||||
|
||||
public override float GetProgress(SaveData save)
|
||||
{
|
||||
if (save?.Equipment == null || totalCharmsCount <= 0) return 0f;
|
||||
return UnityEngine.Mathf.Clamp01((float)save.Equipment.OwnedCharmIds.Count / totalCharmsCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7705d5b84ab1d90479faba8e44b35026
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,16 @@
|
||||
using UnityEngine;
|
||||
using BaseGames.Core.Save;
|
||||
|
||||
namespace BaseGames.Progression
|
||||
{
|
||||
/// <summary>收集指定道具的成就条件(使用 World.CollectedIds)。</summary>
|
||||
[CreateAssetMenu(menuName = "Achievement/Condition/CollectedItem", fileName = "COND_CollectedItem_")]
|
||||
public class CollectedItemCondition : AchievementCondition
|
||||
{
|
||||
[Tooltip("道具唯一标识符(与 CollectibleItem.itemId 匹配)")]
|
||||
public string itemId;
|
||||
|
||||
public override bool IsMet(SaveData save)
|
||||
=> save?.World != null && save.World.CollectedIds.Contains(itemId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8209dfbb9f9b3a8488930367b42d3ec9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,30 @@
|
||||
using UnityEngine;
|
||||
using BaseGames.Core.Save;
|
||||
|
||||
namespace BaseGames.Progression
|
||||
{
|
||||
/// <summary>击败全部指定 Boss 列表的成就条件。</summary>
|
||||
[CreateAssetMenu(menuName = "Achievement/Condition/DefeatedAllBosses", fileName = "COND_DefeatedAllBosses")]
|
||||
public class DefeatedAllBossesCondition : AchievementCondition
|
||||
{
|
||||
[Tooltip("需要全部击败的 Boss ID 列表")]
|
||||
public string[] requiredBossIds;
|
||||
|
||||
public override bool IsMet(SaveData save)
|
||||
{
|
||||
if (save?.World == null || requiredBossIds == null) return false;
|
||||
foreach (var id in requiredBossIds)
|
||||
if (!save.World.DefeatedBossIds.Contains(id)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public override float GetProgress(SaveData save)
|
||||
{
|
||||
if (save?.World == null || requiredBossIds == null || requiredBossIds.Length == 0) return 0f;
|
||||
int met = 0;
|
||||
foreach (var id in requiredBossIds)
|
||||
if (save.World.DefeatedBossIds.Contains(id)) met++;
|
||||
return (float)met / requiredBossIds.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fd55de95ca7807c4992067e47a5cd8b1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,16 @@
|
||||
using UnityEngine;
|
||||
using BaseGames.Core.Save;
|
||||
|
||||
namespace BaseGames.Progression
|
||||
{
|
||||
/// <summary>击败指定 Boss 的成就条件。</summary>
|
||||
[CreateAssetMenu(menuName = "Achievement/Condition/DefeatedBoss", fileName = "COND_DefeatedBoss_")]
|
||||
public class DefeatedBossCondition : AchievementCondition
|
||||
{
|
||||
[Tooltip("Boss 唯一标识符(与 BossRecord.bossId 匹配)")]
|
||||
public string bossId;
|
||||
|
||||
public override bool IsMet(SaveData save)
|
||||
=> save?.World != null && save.World.DefeatedBossIds.Contains(bossId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 37994d104d819474285eb6cee592425b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,16 @@
|
||||
using UnityEngine;
|
||||
using BaseGames.Core.Save;
|
||||
|
||||
namespace BaseGames.Progression
|
||||
{
|
||||
/// <summary>进入指定场景(区域)的成就条件。</summary>
|
||||
[CreateAssetMenu(menuName = "Achievement/Condition/EnteredRegion", fileName = "COND_EnteredRegion_")]
|
||||
public class EnteredRegionCondition : AchievementCondition
|
||||
{
|
||||
[Tooltip("目标场景名称(Build Settings 中的 Scene name)")]
|
||||
public string sceneName;
|
||||
|
||||
public override bool IsMet(SaveData save)
|
||||
=> save?.World != null && save.World.VisitedScenes.Contains(sceneName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8bc9a9ed170dcd143bdd0fedd52eaf3f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,22 @@
|
||||
using UnityEngine;
|
||||
using BaseGames.Core.Save;
|
||||
|
||||
namespace BaseGames.Progression
|
||||
{
|
||||
/// <summary>
|
||||
/// 由事件触发的成就条件(使用 World.Switches 中的布尔标志位)。
|
||||
/// 由代码(如剧情节点、NPC 交互)写入标志,AchievementManager 轮询检查。
|
||||
/// </summary>
|
||||
[CreateAssetMenu(menuName = "Achievement/Condition/EventTriggered", fileName = "COND_EventTriggered_")]
|
||||
public class EventTriggeredCondition : AchievementCondition
|
||||
{
|
||||
[Tooltip("World.Switches 中用于标记此事件发生的布尔 Key")]
|
||||
public string flagKey;
|
||||
|
||||
public override bool IsMet(SaveData save)
|
||||
{
|
||||
if (save?.World?.Switches == null || string.IsNullOrEmpty(flagKey)) return false;
|
||||
return save.World.Switches.TryGetValue(flagKey, out bool val) && val;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1362775eb8b474f449a27210400b7e58
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,22 @@
|
||||
using UnityEngine;
|
||||
using BaseGames.Core.Save;
|
||||
|
||||
namespace BaseGames.Progression
|
||||
{
|
||||
/// <summary>地图探索率(已探索房间数)的成就条件。</summary>
|
||||
[CreateAssetMenu(menuName = "Achievement/Condition/MapExploration", fileName = "COND_MapExploration_")]
|
||||
public class MapExplorationCondition : AchievementCondition
|
||||
{
|
||||
[Tooltip("需要探索的最少房间数量")]
|
||||
[Min(1)] public int requiredRoomCount = 1;
|
||||
|
||||
public override bool IsMet(SaveData save)
|
||||
=> save?.Map != null && save.Map.ExploredRooms.Count >= requiredRoomCount;
|
||||
|
||||
public override float GetProgress(SaveData save)
|
||||
{
|
||||
if (save?.Map == null || requiredRoomCount <= 0) return 0f;
|
||||
return UnityEngine.Mathf.Clamp01((float)save.Map.ExploredRooms.Count / requiredRoomCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a3ed424ac2b64bf48b89ca798a633fec
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,32 @@
|
||||
using UnityEngine;
|
||||
using BaseGames.Core.Save;
|
||||
|
||||
namespace BaseGames.Progression
|
||||
{
|
||||
/// <summary>
|
||||
/// 累计钉击碰撞(NailClash)次数的成就条件。
|
||||
/// 使用 Stats.SkillUseCounts["NailClash"] 追踪(由 CombatSystem 写入)。
|
||||
/// </summary>
|
||||
[CreateAssetMenu(menuName = "Achievement/Condition/NailClashCount", fileName = "COND_NailClashCount_")]
|
||||
public class NailClashCountCondition : AchievementCondition
|
||||
{
|
||||
public const string NailClashKey = "NailClash";
|
||||
|
||||
[Tooltip("需要累计触发钉击碰撞的次数")]
|
||||
[Min(1)] public int requiredCount = 5;
|
||||
|
||||
public override bool IsMet(SaveData save)
|
||||
{
|
||||
if (save?.Stats?.SkillUseCounts == null) return false;
|
||||
save.Stats.SkillUseCounts.TryGetValue(NailClashKey, out int count);
|
||||
return count >= requiredCount;
|
||||
}
|
||||
|
||||
public override float GetProgress(SaveData save)
|
||||
{
|
||||
if (save?.Stats?.SkillUseCounts == null || requiredCount <= 0) return 0f;
|
||||
save.Stats.SkillUseCounts.TryGetValue(NailClashKey, out int count);
|
||||
return UnityEngine.Mathf.Clamp01((float)count / requiredCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ba114c279c716d44797693ddf74474d1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
29
Assets/Scripts/Progression/Achievement/NoHealRunCondition.cs
Normal file
29
Assets/Scripts/Progression/Achievement/NoHealRunCondition.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using UnityEngine;
|
||||
using BaseGames.Core.Save;
|
||||
|
||||
namespace BaseGames.Progression
|
||||
{
|
||||
/// <summary>
|
||||
/// 无治疗通关成就条件。
|
||||
/// 依赖 World.Switches 中的标志位:AchievementManager 在玩家治疗时写入 noHeal_failed=true。
|
||||
/// 满足条件:Boss 已击败 且 无治疗标志未被置入失败状态。
|
||||
/// </summary>
|
||||
[CreateAssetMenu(menuName = "Achievement/Condition/NoHealRun", fileName = "COND_NoHealRun_")]
|
||||
public class NoHealRunCondition : AchievementCondition
|
||||
{
|
||||
[Tooltip("追踪的 Boss ID(击败此 Boss 时检查是否治疗过)")]
|
||||
public string targetBossId;
|
||||
|
||||
[Tooltip("Switches 中记录「已治疗」失败状态的 Key(由 AchievementManager 设置)")]
|
||||
public string healFailFlagKey;
|
||||
|
||||
public override bool IsMet(SaveData save)
|
||||
{
|
||||
if (save?.World == null) return false;
|
||||
// Boss 已击败 且 未触发治疗失败标志
|
||||
bool bossDefeated = save.World.DefeatedBossIds.Contains(targetBossId);
|
||||
bool didHeal = save.World.Switches.TryGetValue(healFailFlagKey, out bool val) && val;
|
||||
return bossDefeated && !didHeal;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 97aec3097b5445b4ea79a691a0c068c1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,22 @@
|
||||
using UnityEngine;
|
||||
using BaseGames.Core.Save;
|
||||
|
||||
namespace BaseGames.Progression
|
||||
{
|
||||
/// <summary>累计弹反成功次数的成就条件(使用 Stats.ParrySuccess)。</summary>
|
||||
[CreateAssetMenu(menuName = "Achievement/Condition/ParryCount", fileName = "COND_ParryCount_")]
|
||||
public class ParryCountCondition : AchievementCondition
|
||||
{
|
||||
[Tooltip("需要累计成功弹反的次数")]
|
||||
[Min(1)] public int requiredCount = 10;
|
||||
|
||||
public override bool IsMet(SaveData save)
|
||||
=> save?.Stats != null && save.Stats.ParrySuccess >= requiredCount;
|
||||
|
||||
public override float GetProgress(SaveData save)
|
||||
{
|
||||
if (save?.Stats == null || requiredCount <= 0) return 0f;
|
||||
return UnityEngine.Mathf.Clamp01((float)save.Stats.ParrySuccess / requiredCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3b6049404747c16438050523fac4a5e8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,23 @@
|
||||
using UnityEngine;
|
||||
using BaseGames.Core.Save;
|
||||
|
||||
namespace BaseGames.Progression
|
||||
{
|
||||
/// <summary>在指定时间内击败 Boss 的成就条件(使用 ChallengeRooms.Records 的 BestTime)。</summary>
|
||||
[CreateAssetMenu(menuName = "Achievement/Condition/TimedBossKill", fileName = "COND_TimedBossKill_")]
|
||||
public class TimedBossKillCondition : AchievementCondition
|
||||
{
|
||||
[Tooltip("Boss 的 ChallengeRoom 记录 ID(与 ChallengeRoomRecord key 匹配)")]
|
||||
public string bossRoomId;
|
||||
|
||||
[Tooltip("需要在此秒数内完成击败(含)")]
|
||||
public float maxSeconds = 60f;
|
||||
|
||||
public override bool IsMet(SaveData save)
|
||||
{
|
||||
if (save?.ChallengeRooms?.Records == null) return false;
|
||||
if (!save.ChallengeRooms.Records.TryGetValue(bossRoomId, out var record)) return false;
|
||||
return record.BestTime > 0f && record.BestTime <= maxSeconds;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fee1576a0fc522045bf2986c1e266fd2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,38 @@
|
||||
using UnityEngine;
|
||||
using BaseGames.Core.Save;
|
||||
using BaseGames.Player;
|
||||
|
||||
namespace BaseGames.Progression
|
||||
{
|
||||
/// <summary>解锁所有指定能力的成就条件(位掩码检查)。</summary>
|
||||
[CreateAssetMenu(menuName = "Achievement/Condition/UnlockedAllAbilities", fileName = "COND_UnlockedAllAbilities")]
|
||||
public class UnlockedAllAbilitiesCondition : AchievementCondition
|
||||
{
|
||||
[Tooltip("需要全部解锁的能力组合(位掩码)")]
|
||||
public AbilityType requiredAbilities = AbilityType.AllMovement;
|
||||
|
||||
public override bool IsMet(SaveData save)
|
||||
{
|
||||
if (save?.Player == null) return false;
|
||||
var flags = (AbilityType)save.Player.AbilityFlags;
|
||||
return (flags & requiredAbilities) == requiredAbilities;
|
||||
}
|
||||
|
||||
public override float GetProgress(SaveData save)
|
||||
{
|
||||
if (save?.Player == null) return 0f;
|
||||
var flags = (AbilityType)save.Player.AbilityFlags;
|
||||
int required = 0, met = 0;
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
var bit = (AbilityType)(1u << i);
|
||||
if ((requiredAbilities & bit) != 0)
|
||||
{
|
||||
required++;
|
||||
if ((flags & bit) != 0) met++;
|
||||
}
|
||||
}
|
||||
return required > 0 ? (float)met / required : 0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2aa2ebe291ae4ef4fbea3251af89f70f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user