815 lines
31 KiB
Markdown
815 lines
31 KiB
Markdown
|
|
# AIDM 项目测试分析报告
|
|||
|
|
|
|||
|
|
> 生成日期:2026-05-30
|
|||
|
|
> 项目:D:\MatrixTA\AIGameDev\AIDM
|
|||
|
|
> 基于:LivingWorldSystem Spec、ARPGGameDevelopment Research Report、修仙流派设计文档
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
[TOC]
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 任务 1:NPC 系统完整架构
|
|||
|
|
|
|||
|
|
### 一、分级机制
|
|||
|
|
|
|||
|
|
项目采用 **三层 NPC 分级模型**(来自 `rationale_npc_tier_abc` 超边):
|
|||
|
|
|
|||
|
|
| 级别 | 名称 | 特征 | 数据承载 |
|
|||
|
|
|------|------|------|----------|
|
|||
|
|
| **A 级** | 核心 NPC(玩家、重要角色) | 完整 3D Actor、行为树、动画、GAS 属性 | `ARPGCharacterBase` + `URPGAbilitySystemComponent` |
|
|||
|
|
| **B 级** | 势力 NPC(宗门弟子、城镇守卫) | 轻量 Actor + 基础动画,结合纯数据模拟 | `ARPGAICharacter` + 部分 `FLWSNpcData` 字段 |
|
|||
|
|
| **C 级** | 泛 NPC(平民、路人、妖兽) | **纯数据 USTRUCT**,无 Actor,不走 NavMesh,六边形坐标跳转 | `FLWSNpcData`(位于 `LWSNpcTypes.h`) |
|
|||
|
|
|
|||
|
|
分级依据文档 `00_项目总控/游戏核心创意.md` 中的"NPC锚点和分级"概念,结合 `LivingWorldSystem Spec` 中明确的"NPC 纯数据模拟"策略。
|
|||
|
|
|
|||
|
|
### 二、决策模型
|
|||
|
|
|
|||
|
|
**核心架构:Utility AI + 性格权重 + 目标驱动**
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
每个 NPC 每日 Tick:
|
|||
|
|
┌────────────────────────────────────────────┐
|
|||
|
|
│ ULWSNpcSimulationSubsystem (UWorldSubsystem) │
|
|||
|
|
│ ├─ 订阅 URPGGameTimeSubsystem::OnGameTimeChanged │
|
|||
|
|
│ ├─ SimulateDays(DeltaDays) │
|
|||
|
|
│ └─ 每日遍历 ActiveNpcs │
|
|||
|
|
└──────────────┬─────────────────────────────┘
|
|||
|
|
│
|
|||
|
|
▼
|
|||
|
|
┌────────────────────────────────────────────┐
|
|||
|
|
│ ULWSNpcDecisionSystem (决策引擎) │
|
|||
|
|
│ ├─ DecayNeeds() — 需求自然衰减(生存↑/安全↑/社交↑...) │
|
|||
|
|
│ ├─ ScoreAction() — 对所有可能行为打分 │
|
|||
|
|
│ │ ├─ 当前需求值 × 行为匹配度 │
|
|||
|
|
│ │ └─ 性格权重因子 PersonalityFactor │
|
|||
|
|
│ └─ ApplyActionToBehavior() — 选最高分执行 │
|
|||
|
|
└──────────────┬─────────────────────────────┘
|
|||
|
|
│
|
|||
|
|
▼
|
|||
|
|
ELWSNpcAction { Idle, Wander, MoveTo, Trade, Fight, Socialize, Cultivate, ... }
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**性格三维度**(`FLWSNpcPersonality`,位于 `LWSNpcPersonalityTypes.h`):
|
|||
|
|
|
|||
|
|
- **冷 ↔ 热**:影响社交行为权重
|
|||
|
|
- **慎 ↔ 莽**:影响战斗/探索行为权重
|
|||
|
|
- **私 ↔ 义**:影响帮助盟友 vs 追求私利
|
|||
|
|
|
|||
|
|
**需求六维度**(`ELWSNpcNeed`):生存、安全、社交、权力、资源、修炼
|
|||
|
|
|
|||
|
|
**决策实现位置**:
|
|||
|
|
|
|||
|
|
- `Plugins/RPGGameCore/Source/LivingWorldSystem/Public/LWSNpcDecisionSystem.h`
|
|||
|
|
- `Plugins/RPGGameCore/Source/LivingWorldSystem/Private/LWSNpcDecisionSystem.cpp`
|
|||
|
|
|
|||
|
|
### 三、与时间系统的关系
|
|||
|
|
|
|||
|
|
**时间模型:回合+实时混合制,日为原子单位**(Community 15:策划世界系统)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
URPGGameTimeSubsystem (UGameInstanceSubsystem,跨 World 持续)
|
|||
|
|
│
|
|||
|
|
├─ FSDHGameRawTime / FSDHGameTime (30天/月, 12月/年)
|
|||
|
|
├─ OnGameTimeChanged 委托广播
|
|||
|
|
├─ 世界时间推进 → AddGameTime(DeltaDays)
|
|||
|
|
│
|
|||
|
|
└──→ ULWSNpcSimulationSubsystem::SimulateDays(DeltaDays)
|
|||
|
|
├─ 每日遍历所有 NPC
|
|||
|
|
├─ Wander 算法(WanderStayProbability 概率不动,否则随机六邻一步)
|
|||
|
|
├─ 调用决策系统 DecideAction
|
|||
|
|
└─ 缓存轨迹(环形 buffer 32 步)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**关键时间常量**:
|
|||
|
|
|
|||
|
|
- 1 日 = 最小原子单位
|
|||
|
|
- 2 帧完成一轮完整 NPC 模拟(60 FPS 下每帧处理 1/30 NPC)
|
|||
|
|
- NPC 模拟在**后台线程**批量执行
|
|||
|
|
|
|||
|
|
### 四、存档方式
|
|||
|
|
|
|||
|
|
**双层存档架构**(Community 5 + Community 15):
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
第一层:世界永久层(跨存档持久化)
|
|||
|
|
│
|
|||
|
|
├─ LWSWorldSaveGame (USaveGame 子类)
|
|||
|
|
│ ├─ CachedTileCoords / TileBuffer → 瓦片数据
|
|||
|
|
│ ├─ CachedRivers / CachedLakes → 水文数据
|
|||
|
|
│ ├─ CachedFactions → 势力数据
|
|||
|
|
│ ├─ CachedNpcs → NPC 数据 (TArray<FLWSNpcData>)
|
|||
|
|
│ ├─ CachedSpiritualVeins → 灵脉数据
|
|||
|
|
│ └─ CachedSettlements / Resources → 聚落/资源数据
|
|||
|
|
│
|
|||
|
|
└─ 世界编年史(跨存档的人生记录,待阶段二实现)
|
|||
|
|
|
|||
|
|
第二层:角色存档层(可删除/重建)
|
|||
|
|
│
|
|||
|
|
└─ URPGPlayerSaveGame
|
|||
|
|
├─ RPGAttributeData → FRPGCharacterAttributeData
|
|||
|
|
├─ SkillTreeDataPool → 技能树学习状态
|
|||
|
|
├─ RPGSkilllActionPoseTree → 架势-技能装配绑定
|
|||
|
|
├─ RPGItemDataMap → 物品容器数据
|
|||
|
|
└─ TalentComponentSaveData → 天赋数据
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**存档关键实现**:
|
|||
|
|
|
|||
|
|
- `ALWSWorldGenerator::SaveWorld()` 写入 `ULWSWorldSaveGame`(蓝图可调用)
|
|||
|
|
- `ALWSWorldGenerator::LoadWorld()` 从存档完整还原世界
|
|||
|
|
- NPC 数据通过 `ULWSNpcSimulationSubsystem::GetActiveNpcsCopy()` / `RestoreNpcsFromSave()` 同步
|
|||
|
|
- **角色存档删除后,世界永久层不受影响**——势力变迁、NPC 死亡/成长、资源消耗写入世界层
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 任务 2:新增「商队 NPC」跨系统依赖分析
|
|||
|
|
|
|||
|
|
### 一、需要修改的模块及文件
|
|||
|
|
|
|||
|
|
#### 1. NPC 数据结构层(核心修改)
|
|||
|
|
|
|||
|
|
| 文件 | 修改内容 |
|
|||
|
|
|------|---------|
|
|||
|
|
| `Plugins/RPGGameCore/Source/LivingWorldSystem/Public/LWSNpcTypes.h` | `FLWSNpcData` 新增字段:`TradeRouteIndex`(商队路线 ID)、`TradeGoods`(货物数组 TMap)、`TradeFactionOrigin`/`TradeFactionDestination`(起止势力)、`TradeSpeed`(行进速度,单位 hex/日) |
|
|||
|
|
| `Plugins/RPGGameCore/Source/LivingWorldSystem/Public/LWSNpcPersonalityTypes.h` | 新增 `ELWSNpcBehavior::Trade` 行为枚举值;新增 `ELWSNpcRole::CaravanTrader` 角色类型 |
|
|||
|
|
|
|||
|
|
#### 2. 行为/决策系统
|
|||
|
|
|
|||
|
|
| 文件 | 修改内容 |
|
|||
|
|
|------|---------|
|
|||
|
|
| `Plugins/RPGGameCore/Source/LivingWorldSystem/Public/LWSNpcDecisionSystem.h` | `DecideAction()` 新增商队逻辑:到达目的地时触发交易结算、反向切换目的地 |
|
|||
|
|
| `Plugins/RPGGameCore/Source/LivingWorldSystem/Private/LWSNpcDecisionSystem.cpp` | 实现 `ScoreAction_Trade()`:需求权重(资源需求×商队距离评分) |
|
|||
|
|
| `Plugins/RPGGameCore/Source/LivingWorldSystem/Public/LWSNpcSimulationSubsystem.h` | `SimulateDays()` 新增商队每日推进:沿 A* 路径逐格移动(有别于 Wander 随机) |
|
|||
|
|
|
|||
|
|
#### 3. 势力与生成
|
|||
|
|
|
|||
|
|
| 文件 | 修改内容 |
|
|||
|
|
|------|---------|
|
|||
|
|
| `Plugins/RPGGameCore/Source/LivingWorldSystem/Public/LWSNpcGenerator.h/.cpp` | `GenerateNpcs()` 新增商队生成逻辑:势力边界间配对生成商队 NPC,泊松碟约束 + 路线预计算 |
|
|||
|
|
| `Plugins/RPGGameCore/Source/LivingWorldSystem/Public/LWSFactionTypes.h` | `FLWSFaction` 新增 `TradePartners`(贸易伙伴势力 ID 列表)、`TradeRouteFrequencies`(每条路线商队生成频率) |
|
|||
|
|
| `Plugins/RPGGameCore/Source/LivingWorldSystem/Private/LWSFactionGenerator.cpp` | 势力生成后自动配对邻近势力建立贸易路线 |
|
|||
|
|
|
|||
|
|
#### 4. 寻路系统
|
|||
|
|
|
|||
|
|
| 文件 | 修改内容 |
|
|||
|
|
|------|---------|
|
|||
|
|
| `Plugins/RPGGameCore/Source/LivingWorldSystem/Public/LWSPathfinder.h` | 商队寻路需在 `FLWSPathfindingParams` 中支持路线成本(避开高危势力区、倾向道路/平原) |
|
|||
|
|
|
|||
|
|
#### 5. 存档
|
|||
|
|
|
|||
|
|
| 文件 | 修改内容 |
|
|||
|
|
|------|---------|
|
|||
|
|
| `Plugins/RPGGameCore/Source/LivingWorldSystem/Public/LWSWorldSaveGame.h` | `FLWSNpcData` 新增字段会自然序列化;新增 `CachedTradeRoutes`(`TArray<FLWSTradeRoute>` 路线拓扑数据) |
|
|||
|
|
| `Plugins/RPGGameCore/Source/LivingWorldSystem/Public/LWSTradeTypes.h` | **新建**:`FLWSTradeGoods`(物品 ID + 数量)、`FLWSTradeRoute`(起始势力、途经 hex 坐标数组、路线等级) |
|
|||
|
|
|
|||
|
|
#### 6. 调试可视化
|
|||
|
|
|
|||
|
|
| 文件 | 修改内容 |
|
|||
|
|
|------|---------|
|
|||
|
|
| `Plugins/RPGGameCore/Source/LivingWorldSystem/Private/LWSWorldGenerator.cpp` | 新增 `DebugDrawTradeRoutes()`:商队路线以黄色虚线绘制;商队位置以金色圆点标记 |
|
|||
|
|
| `Plugins/RPGGameCore/Source/LivingWorldSystem/Public/LWSResourceTypes.h` | `ELWSDebugViewMode` 新增 `TradeRoutes` 枚举 |
|
|||
|
|
|
|||
|
|
### 二、存档结构变化
|
|||
|
|
|
|||
|
|
**不需要破坏性变更**。`FLWSNpcData` 的字段扩展会被 UE 序列化自动兼容(USTRUCT 标记 UPROPERTY 的字段)。需要新增:
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
// 新建 LWSTradeTypes.h
|
|||
|
|
USTRUCT()
|
|||
|
|
struct FLWSTradeRoute
|
|||
|
|
{
|
|||
|
|
UPROPERTY() int32 RouteId;
|
|||
|
|
UPROPERTY() int32 OriginFactionId;
|
|||
|
|
UPROPERTY() int32 DestinationFactionId;
|
|||
|
|
UPROPERTY() TArray<FLWSAxialCoord> Waypoints; // A* 预计算路径
|
|||
|
|
UPROPERTY() float RouteLevel; // 路线等级(影响货物品质)
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// LWSWorldSaveGame 新增
|
|||
|
|
UPROPERTY() TArray<FLWSTradeRoute> CachedTradeRoutes;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**双层存档不受影响**:商队 NPC 属于 `CachedNpcs`(世界永久层),角色存档删除不影响商队。
|
|||
|
|
|
|||
|
|
### 三、对 GAS 属性系统的影响
|
|||
|
|
|
|||
|
|
**不影响 GAS 属性系统。** 原因:
|
|||
|
|
|
|||
|
|
1. 商队 NPC 是**纯数据 C 级 NPC**(`FLWSNpcData`),不持有 `URPGAbilitySystemComponent`,不参与 GAS Attribute 同步
|
|||
|
|
2. 商队交易结算是**数值运算**(货物价值 = 距离 × 势力稀缺度 × 路线等级),不涉及战斗伤害管线
|
|||
|
|
3. 如果未来需要"商队被劫掠"战斗,才需要通过 C→B 级 NPC 升级机制接入 GAS
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 任务 3:为「御剑飞行」新增 ActionPose
|
|||
|
|
|
|||
|
|
### 设计分析
|
|||
|
|
|
|||
|
|
当前 `ELM_ActionPose` 已有 `AirFlying`(空行)作为通用空中飞行态,但**御剑飞行**是剑修专属的战斗力+移动融合态:站在飞剑上高速移动,可在飞行中发起剑技攻击。需要作为独立主架势加入。
|
|||
|
|
|
|||
|
|
**状态流转:**
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
地面起势 (GroundDefault)
|
|||
|
|
│ 释放御剑飞行技能
|
|||
|
|
▼
|
|||
|
|
御剑飞行 (AirSwordFlight) ← 新增
|
|||
|
|
│
|
|||
|
|
├── 输入方向 → 高速移动(飞行移动速度 ×2.5)
|
|||
|
|
├── 左键 (SubPose0) → 飞剑斩(空中剑技连段)
|
|||
|
|
├── 右键 (SubPose1) → 剑罡护体
|
|||
|
|
├── 闪避键 → 御剑急转 (AirSwordFlight → AirDash)
|
|||
|
|
│
|
|||
|
|
├── 耐力耗尽/被击落 → AirFalling
|
|||
|
|
└── 主动取消/落地 → GroundLanding
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 1. RPGTypes.h — 新增枚举值
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
// RPGTypes.h — 在 ELM_ActionPose 枚举中 AirDash 之后插入
|
|||
|
|
enum class ELM_ActionPose : uint8
|
|||
|
|
{
|
|||
|
|
// ... 现有值不变 ...
|
|||
|
|
AirDash, // 空冲(飞行状态下的快速冲击)
|
|||
|
|
|
|||
|
|
// === 御剑飞行(新增)===
|
|||
|
|
AirSwordFlight, // 御剑飞行态:剑修站在飞剑上高速移动+空中战斗
|
|||
|
|
|
|||
|
|
AirSpring, // 空遁
|
|||
|
|
// ... 后续值不变 ...
|
|||
|
|
};
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. RPGSwordFlightAbility.h — 御剑飞行 GA 头文件(新建)
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
// Plugins/RPGGameCore/Source/RPGGameplayAbility/Public/Abilities/RPGSwordFlightAbility.h
|
|||
|
|
|
|||
|
|
#pragma once
|
|||
|
|
|
|||
|
|
#include "SDHGameplayAbility.h"
|
|||
|
|
#include "GameplayTagContainer.h"
|
|||
|
|
#include "RPGSwordFlightAbility.generated.h"
|
|||
|
|
|
|||
|
|
class AWeaponBase;
|
|||
|
|
class UNiagaraSystem;
|
|||
|
|
class UGameplayEffect;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 御剑飞行 GameplayAbility
|
|||
|
|
* Lifecycle: ActivateAbility → UpdateAbility(每帧) → EndAbility
|
|||
|
|
* 角色站在飞剑上进入 AirSwordFlight 架势,高速飞行 + 空中剑技
|
|||
|
|
*/
|
|||
|
|
UCLASS(BlueprintType, Blueprintable)
|
|||
|
|
class RPGGAMEPLAYABILITY_API URPGSwordFlightAbility : public URPGGameplayAbility
|
|||
|
|
{
|
|||
|
|
GENERATED_BODY()
|
|||
|
|
|
|||
|
|
public:
|
|||
|
|
URPGSwordFlightAbility();
|
|||
|
|
|
|||
|
|
virtual void ActivateAbility() override;
|
|||
|
|
virtual void UpdateAbility(float DeltaTime) override;
|
|||
|
|
virtual void EndAbility() override;
|
|||
|
|
|
|||
|
|
// === 配置属性 ===
|
|||
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "SwordFlight|Movement")
|
|||
|
|
float FlightSpeed = 2000.f; // 基础飞行速度 (cm/s)
|
|||
|
|
|
|||
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "SwordFlight|Movement")
|
|||
|
|
float MaxAcceleration = 3000.f; // 最大加速度
|
|||
|
|
|
|||
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "SwordFlight|Movement")
|
|||
|
|
float TurnRate = 180.f; // 转向速率 (deg/s)
|
|||
|
|
|
|||
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "SwordFlight|Resource")
|
|||
|
|
float ManaDrainPerSecond = 8.f; // 每秒法力消耗
|
|||
|
|
|
|||
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "SwordFlight|Resource")
|
|||
|
|
float MinManaToActivate = 30.f; // 最低法力阈值(低于此值强制解除)
|
|||
|
|
|
|||
|
|
// === 视觉 ===
|
|||
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "SwordFlight|Visual")
|
|||
|
|
TSubclassOf<AActor> SwordFlightActorClass; // 飞剑 Actor(附着到角色脚下)
|
|||
|
|
|
|||
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "SwordFlight|Visual")
|
|||
|
|
UNiagaraSystem* FlightTrailEffect; // 飞行拖尾 Niagara 特效
|
|||
|
|
|
|||
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "SwordFlight|Visual")
|
|||
|
|
FRotator SwordMountRotation = FRotator(0.f, 0.f, 15.f); // 飞剑倾斜角度
|
|||
|
|
|
|||
|
|
// === GAS Effect ===
|
|||
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "SwordFlight|Effects")
|
|||
|
|
TSubclassOf<UGameplayEffect> SwordFlightMovementGE; // 修改 MoveSpeed、GravityScale
|
|||
|
|
|
|||
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "SwordFlight|Effects")
|
|||
|
|
TSubclassOf<UGameplayEffect> SwordFlightDamageBonusGE; // 飞剑期间剑技伤害 +25%
|
|||
|
|
|
|||
|
|
// === 蓝图事件 ===
|
|||
|
|
UFUNCTION(BlueprintImplementableEvent, Category = "SwordFlight")
|
|||
|
|
void OnSwordMounted(AActor* SwordActor);
|
|||
|
|
|
|||
|
|
UFUNCTION(BlueprintImplementableEvent, Category = "SwordFlight")
|
|||
|
|
void OnSwordDismounted();
|
|||
|
|
|
|||
|
|
UFUNCTION(BlueprintImplementableEvent, Category = "SwordFlight")
|
|||
|
|
void OnFlightManaDepleted(); // 法力耗尽事件
|
|||
|
|
|
|||
|
|
private:
|
|||
|
|
// === 内部状态 ===
|
|||
|
|
UPROPERTY()
|
|||
|
|
TObjectPtr<AActor> MountedSword; // 当前挂载的飞剑 Actor
|
|||
|
|
|
|||
|
|
UPROPERTY()
|
|||
|
|
TObjectPtr<UNiagaraComponent> TrailNiagara; // 拖尾特效组件
|
|||
|
|
|
|||
|
|
UPROPERTY()
|
|||
|
|
FActiveGameplayEffectHandle MovementGEHandle; // 移动 GE 句柄
|
|||
|
|
|
|||
|
|
UPROPERTY()
|
|||
|
|
FActiveGameplayEffectHandle DamageBonusHandle; // 伤害加成 GE 句柄
|
|||
|
|
|
|||
|
|
bool bIsActive = false;
|
|||
|
|
float CurrentManaDrainAccum = 0.f; // 法力消耗累加器
|
|||
|
|
|
|||
|
|
// --- 内部方法 ---
|
|||
|
|
void SpawnAndMountSword();
|
|||
|
|
void ApplyFlightEffects();
|
|||
|
|
void RemoveFlightEffects();
|
|||
|
|
bool CheckManaSufficient() const;
|
|||
|
|
void DrainManaPerTick(float DeltaTime);
|
|||
|
|
};
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. RPGSwordFlightAbility.cpp — 关键逻辑实现(核心)
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
// Plugins/RPGGameCore/Source/RPGGameplayAbility/Private/Abilities/RPGSwordFlightAbility.cpp
|
|||
|
|
|
|||
|
|
#include "Abilities/RPGSwordFlightAbility.h"
|
|||
|
|
#include "Character/RPGCharacterBase.h"
|
|||
|
|
#include "Character/Attribute/RPGAttributeSet.h"
|
|||
|
|
#include "Character/Attribute/RPGAttributeComponent.h"
|
|||
|
|
#include "NiagaraComponent.h"
|
|||
|
|
#include "NiagaraFunctionLibrary.h"
|
|||
|
|
#include "GameFramework/CharacterMovementComponent.h"
|
|||
|
|
#include "AbilitySystemComponent.h"
|
|||
|
|
|
|||
|
|
URPGSwordFlightAbility::URPGSwordFlightAbility()
|
|||
|
|
{
|
|||
|
|
// 标记为持续型 Ability(非一次性瞬发)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void URPGSwordFlightAbility::ActivateAbility()
|
|||
|
|
{
|
|||
|
|
Super::ActivateAbility();
|
|||
|
|
|
|||
|
|
ARPGCharacterBase* Owner = Cast<ARPGCharacterBase>(GetSkillUser());
|
|||
|
|
if (!Owner || !CheckManaSufficient())
|
|||
|
|
{
|
|||
|
|
SetAbilityValid(false);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 1. 生成飞剑并挂载到角色脚底
|
|||
|
|
SpawnAndMountSword();
|
|||
|
|
|
|||
|
|
// 2. 应用飞行 GE(修改 CMC MoveSpeed、GravityScale)
|
|||
|
|
ApplyFlightEffects();
|
|||
|
|
|
|||
|
|
// 3. 角色进入飞行模式
|
|||
|
|
if (UCharacterMovementComponent* CMC = Owner->GetCharacterMovement())
|
|||
|
|
{
|
|||
|
|
CMC->SetMovementMode(MOVE_Flying);
|
|||
|
|
CMC->MaxFlySpeed = FlightSpeed;
|
|||
|
|
CMC->MaxAcceleration = MaxAcceleration;
|
|||
|
|
CMC->BrakingDecelerationFlying = 1000.f;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 4. 设置架势为 御剑飞行
|
|||
|
|
if (USkillSMInstance* SM = Owner->GetSkillSMInstance())
|
|||
|
|
{
|
|||
|
|
SM->SetActionPose(ELM_ActionPose::AirSwordFlight);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 5. 生成长剑拖尾特效
|
|||
|
|
if (FlightTrailEffect)
|
|||
|
|
{
|
|||
|
|
TrailNiagara = UNiagaraFunctionLibrary::SpawnSystemAttached(
|
|||
|
|
FlightTrailEffect,
|
|||
|
|
Owner->GetRootComponent(),
|
|||
|
|
NAME_None,
|
|||
|
|
FVector::ZeroVector,
|
|||
|
|
FRotator::ZeroRotator,
|
|||
|
|
EAttachLocation::KeepRelativeOffset,
|
|||
|
|
true
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bIsActive = true;
|
|||
|
|
SetAbilityValid(true);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void URPGSwordFlightAbility::UpdateAbility(float DeltaTime)
|
|||
|
|
{
|
|||
|
|
Super::UpdateAbility(DeltaTime);
|
|||
|
|
if (!bIsActive) return;
|
|||
|
|
|
|||
|
|
// 法力消耗检查
|
|||
|
|
DrainManaPerTick(DeltaTime);
|
|||
|
|
if (!CheckManaSufficient())
|
|||
|
|
{
|
|||
|
|
OnFlightManaDepleted();
|
|||
|
|
EndAbility();
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 可选:根据输入方向调整飞剑倾斜
|
|||
|
|
// 通过蓝图 OnFlightUpdate 事件暴露给设计师微调
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void URPGSwordFlightAbility::EndAbility()
|
|||
|
|
{
|
|||
|
|
Super::EndAbility();
|
|||
|
|
|
|||
|
|
ARPGCharacterBase* Owner = Cast<ARPGCharacterBase>(GetSkillUser());
|
|||
|
|
if (!Owner) return;
|
|||
|
|
|
|||
|
|
// 1. 恢复地面移动模式
|
|||
|
|
if (UCharacterMovementComponent* CMC = Owner->GetCharacterMovement())
|
|||
|
|
{
|
|||
|
|
CMC->SetMovementMode(MOVE_Walking);
|
|||
|
|
CMC->MaxFlySpeed = 600.f; // 恢复默认
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 2. 移除 GE
|
|||
|
|
RemoveFlightEffects();
|
|||
|
|
|
|||
|
|
// 3. 销毁拖尾
|
|||
|
|
if (TrailNiagara)
|
|||
|
|
{
|
|||
|
|
TrailNiagara->Deactivate();
|
|||
|
|
TrailNiagara = nullptr;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 4. 拆卸飞剑 → 切换到 AirFalling
|
|||
|
|
OnSwordDismounted();
|
|||
|
|
if (MountedSword)
|
|||
|
|
{
|
|||
|
|
MountedSword->Destroy();
|
|||
|
|
MountedSword = nullptr;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 5. 架势切换:御剑 → 空中下落
|
|||
|
|
if (USkillSMInstance* SM = Owner->GetSkillSMInstance())
|
|||
|
|
{
|
|||
|
|
SM->SetActionPose(ELM_ActionPose::AirFalling);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bIsActive = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ============ 内部实现 ============
|
|||
|
|
|
|||
|
|
void URPGSwordFlightAbility::SpawnAndMountSword()
|
|||
|
|
{
|
|||
|
|
ARPGCharacterBase* Owner = Cast<ARPGCharacterBase>(GetSkillUser());
|
|||
|
|
if (!Owner || !SwordFlightActorClass) return;
|
|||
|
|
|
|||
|
|
FActorSpawnParameters SpawnParams;
|
|||
|
|
SpawnParams.Owner = Owner;
|
|||
|
|
SpawnParams.Instigator = Owner;
|
|||
|
|
|
|||
|
|
// 飞剑生成在角色脚下
|
|||
|
|
FVector SpawnLoc = Owner->GetActorLocation() + FVector(0, 0, -70.f);
|
|||
|
|
MountedSword = GetWorld()->SpawnActor<AActor>(
|
|||
|
|
SwordFlightActorClass, SpawnLoc, FRotator::ZeroRotator, SpawnParams
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
if (MountedSword)
|
|||
|
|
{
|
|||
|
|
MountedSword->AttachToComponent(
|
|||
|
|
Owner->GetRootComponent(),
|
|||
|
|
FAttachmentTransformRules::KeepRelativeTransform
|
|||
|
|
);
|
|||
|
|
MountedSword->SetActorRelativeLocation(FVector(0, 0, -70.f));
|
|||
|
|
MountedSword->SetActorRelativeRotation(SwordMountRotation);
|
|||
|
|
OnSwordMounted(MountedSword);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void URPGSwordFlightAbility::ApplyFlightEffects()
|
|||
|
|
{
|
|||
|
|
ARPGCharacterBase* Owner = Cast<ARPGCharacterBase>(GetSkillUser());
|
|||
|
|
if (!Owner) return;
|
|||
|
|
|
|||
|
|
URPGAbilitySystemComponent* ASC = Owner->GetRPGAbilitySystemComponent();
|
|||
|
|
if (!ASC) return;
|
|||
|
|
|
|||
|
|
// 施加飞行移动 GE
|
|||
|
|
if (SwordFlightMovementGE)
|
|||
|
|
{
|
|||
|
|
MovementGEHandle = ASC->ApplyGameplayEffectToSelf(
|
|||
|
|
SwordFlightMovementGE->GetDefaultObject<UGameplayEffect>(),
|
|||
|
|
1.f, ASC->MakeEffectContext()
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 施加伤害加成 GE
|
|||
|
|
if (SwordFlightDamageBonusGE)
|
|||
|
|
{
|
|||
|
|
DamageBonusHandle = ASC->ApplyGameplayEffectToSelf(
|
|||
|
|
SwordFlightDamageBonusGE->GetDefaultObject<UGameplayEffect>(),
|
|||
|
|
1.f, ASC->MakeEffectContext()
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void URPGSwordFlightAbility::RemoveFlightEffects()
|
|||
|
|
{
|
|||
|
|
ARPGCharacterBase* Owner = Cast<ARPGCharacterBase>(GetSkillUser());
|
|||
|
|
if (!Owner) return;
|
|||
|
|
|
|||
|
|
URPGAbilitySystemComponent* ASC = Owner->GetRPGAbilitySystemComponent();
|
|||
|
|
if (!ASC) return;
|
|||
|
|
|
|||
|
|
if (MovementGEHandle.IsValid())
|
|||
|
|
ASC->RemoveActiveGameplayEffect(MovementGEHandle);
|
|||
|
|
if (DamageBonusHandle.IsValid())
|
|||
|
|
ASC->RemoveActiveGameplayEffect(DamageBonusHandle);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool URPGSwordFlightAbility::CheckManaSufficient() const
|
|||
|
|
{
|
|||
|
|
ARPGCharacterBase* Owner = Cast<ARPGCharacterBase>(GetSkillUser());
|
|||
|
|
if (!Owner) return false;
|
|||
|
|
|
|||
|
|
URPGAbilitySystemComponent* ASC = Owner->GetRPGAbilitySystemComponent();
|
|||
|
|
if (!ASC) return false;
|
|||
|
|
|
|||
|
|
return ASC->GetNumericAttribute(URPGAttributeSet::GetManaAttribute()) >= MinManaToActivate;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void URPGSwordFlightAbility::DrainManaPerTick(float DeltaTime)
|
|||
|
|
{
|
|||
|
|
CurrentManaDrainAccum += ManaDrainPerSecond * DeltaTime;
|
|||
|
|
if (CurrentManaDrainAccum >= 1.f)
|
|||
|
|
{
|
|||
|
|
int32 DrainAmount = FMath::FloorToInt(CurrentManaDrainAccum);
|
|||
|
|
CurrentManaDrainAccum -= DrainAmount;
|
|||
|
|
|
|||
|
|
ARPGCharacterBase* Owner = Cast<ARPGCharacterBase>(GetSkillUser());
|
|||
|
|
if (Owner)
|
|||
|
|
{
|
|||
|
|
Owner->GetRPGAbilitySystemComponent()->SetNumericAttributeBase(
|
|||
|
|
URPGAttributeSet::GetManaAttribute(),
|
|||
|
|
FMath::Max(0.f, Owner->GetRPGAbilitySystemComponent()->
|
|||
|
|
GetNumericAttribute(URPGAttributeSet::GetManaAttribute()) - DrainAmount)
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 任务 4:「符修」技能效果系统设计(映射到 GAS Effect)
|
|||
|
|
|
|||
|
|
### 设计前提
|
|||
|
|
|
|||
|
|
符修在流派体系中的定位:通过绘制**符文符箓**将法术封印在纸上,战斗中消耗符箓瞬间释放。核心机制是**制符(战前准备)→ 释符(战斗中消耗)**。符文效果通过 GAS GameplayEffect 实现。
|
|||
|
|
|
|||
|
|
### 一、符修核心机制数据模型
|
|||
|
|
|
|||
|
|
#### FRTalismanData.h(新建)
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
// Plugins/RPGGameCore/Source/RPGGameplayAbility/Public/Abilities/Talisman/FRTalismanData.h
|
|||
|
|
|
|||
|
|
#pragma once
|
|||
|
|
|
|||
|
|
#include "GameplayTagContainer.h"
|
|||
|
|
#include "GameplayEffect.h"
|
|||
|
|
#include "FRTalismanData.generated.h"
|
|||
|
|
|
|||
|
|
/** 符箓等级 */
|
|||
|
|
UENUM(BlueprintType)
|
|||
|
|
enum class ERPGTalismanTier : uint8
|
|||
|
|
{
|
|||
|
|
YellowPaper UMETA(DisplayName = "黄纸符"), // 基础符,单次效果
|
|||
|
|
SilverScript UMETA(DisplayName = "银篆符"), // 中级符,可叠加2层
|
|||
|
|
GoldSeal UMETA(DisplayName = "金印符"), // 高级符,效果翻倍
|
|||
|
|
JadeEdict UMETA(DisplayName = "玉敕符"), // 顶级符,范围效果
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/** 符箓触发方式 */
|
|||
|
|
UENUM(BlueprintType)
|
|||
|
|
enum class ERPGTalismanTrigger : uint8
|
|||
|
|
{
|
|||
|
|
OnUse UMETA(DisplayName = "主动释放"), // 主动从快捷栏使用
|
|||
|
|
OnHit UMETA(DisplayName = "受击触发"), // 被攻击时自动触发
|
|||
|
|
OnLowHP UMETA(DisplayName = "濒死护身"), // HP < 30% 自动触发
|
|||
|
|
OnTimer UMETA(DisplayName = "定时触发"), // 定时延迟触发
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/** 单个符箓效果定义 — 映射到 1 个 GAS GameplayEffect */
|
|||
|
|
USTRUCT(BlueprintType)
|
|||
|
|
struct RPGGAMEPLAYABILITY_API FRPGTalismanEffect
|
|||
|
|
{
|
|||
|
|
GENERATED_BODY()
|
|||
|
|
|
|||
|
|
// 符箓配置
|
|||
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Talisman|Identity")
|
|||
|
|
FName TalismanId; // 符箓唯一 ID
|
|||
|
|
|
|||
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Talisman|Identity")
|
|||
|
|
FText TalismanName; // 显示名:"烈火符"、"金刚符"
|
|||
|
|
|
|||
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Talisman|Identity")
|
|||
|
|
ERPGTalismanTier Tier = ERPGTalismanTier::YellowPaper;
|
|||
|
|
|
|||
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Talisman|Identity")
|
|||
|
|
ERPGTalismanTrigger TriggerType = ERPGTalismanTrigger::OnUse;
|
|||
|
|
|
|||
|
|
// === GAS 映射 ===
|
|||
|
|
// 核心:每个符箓效果对应一个 UGameplayEffect 蓝图子类
|
|||
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Talisman|GAS")
|
|||
|
|
TSubclassOf<UGameplayEffect> PrimaryEffectClass; // 主 GE(修改属性/施加 Tag)
|
|||
|
|
|
|||
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Talisman|GAS")
|
|||
|
|
TSubclassOf<UGameplayEffect> SecondaryEffectClass; // 副 GE(可选,范围/连锁效果)
|
|||
|
|
|
|||
|
|
// SetByCaller 动态参数(符箓等级越高,倍率越大)
|
|||
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Talisman|GAS")
|
|||
|
|
TMap<FGameplayTag, float> SetByCallerMagnitudes; // Tag → 基础数值
|
|||
|
|
|
|||
|
|
// 消耗
|
|||
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Talisman|Cost")
|
|||
|
|
int32 ManaCost = 20; // 释符消耗法力
|
|||
|
|
|
|||
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Talisman|Cost")
|
|||
|
|
float CooldownSeconds = 3.f; // 释符冷却
|
|||
|
|
};
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 二、符修五大符系 → GAS GameplayEffect 映射表
|
|||
|
|
|
|||
|
|
| 符系 | 代表符箓 | GAS GE 类型 | 修改的 Attribute | Duration Policy | 关键 SetByCaller Tag |
|
|||
|
|
|------|---------|------------|-----------------|-----------------|---------------------|
|
|||
|
|
| **攻击符系** | 烈火符 | `GE_Talisman_Fire` (Instant) | `Damage` (临时变量) | Instant | `SetByCaller.FireDamage` |
|
|||
|
|
| | 冰封符 | `GE_Talisman_Ice` (HasDuration) | `MoveSpeed` (减速 %) | 5s Duration | `SetByCaller.SlowPercent` |
|
|||
|
|
| | 雷击符 | `GE_Talisman_Thunder` (Instant) | `Damage` + `Tough` (削韧) | Instant | `SetByCaller.ThunderDamage` |
|
|||
|
|
| **防御符系** | 金刚符 | `GE_Talisman_Barrier` (HasDuration) | `Shield` (+护盾值) | 10s Duration | `SetByCaller.ShieldAmount` |
|
|||
|
|
| | 铁壁符 | `GE_Talisman_IronWall` (HasDuration) | `DefensePower` (+%) | 15s Duration | `SetByCaller.DefenseBonus` |
|
|||
|
|
| | 净身符 | `GE_Talisman_Cleanse` (Instant) | 移除 `State.Debuff.*` Tag | Instant | — |
|
|||
|
|
| **辅助符系** | 神行符 | `GE_Talisman_Speed` (HasDuration) | `MoveSpeed` (+%) | 20s Duration | `SetByCaller.SpeedBonus` |
|
|||
|
|
| | 聚灵符 | `GE_Talisman_Meditate` (HasDuration) | `Mana` (回复速率) | 30s Duration | `SetByCaller.ManaRegenRate` |
|
|||
|
|
| | 破阵符 | `GE_Talisman_Break` (Instant) | 移除敌方 Buff Tag | Instant | `SetByCaller.DispelCount` |
|
|||
|
|
| **诅咒符系** | 虚弱符 | `GE_Talisman_Weaken` (HasDuration) | `AttackPower` (-%敌方) | 8s Duration | `SetByCaller.AttackReduce` |
|
|||
|
|
| | 定身符 | `GE_Talisman_Root` (HasDuration) | 施加 `State.CrowdControl.Root` Tag | 3s Duration | `SetByCaller.RootDuration` |
|
|||
|
|
| | 噬魂符 | `GE_Talisman_SoulDrain` (HasDuration) | 敌方 `Health` DoT + 自身 `Health` Heal | 6s Duration | `SetByCaller.DrainAmount` |
|
|||
|
|
| **阵法符系** | 困龙阵符 | `GE_Talisman_TrapField` (Infinite/HasDuration) | 范围 `MoveSpeed` -80% | 15s 范围 Duration | `SetByCaller.TrapRadius` |
|
|||
|
|
| | 万剑阵符 | `GE_Talisman_SwordArray` (Instant × N) | 范围内 N 次 `Damage` 结算 | Instant (周期触发) | `SetByCaller.PerSwordDamage` |
|
|||
|
|
| | 回春阵符 | `GE_Talisman_HealField` (Infinite) | 范围内友方 `Health` 持续回复 | UntilCancelled | `SetByCaller.HealPerTick` |
|
|||
|
|
|
|||
|
|
### 三、与现有 GAS Effect 架构的融合
|
|||
|
|
|
|||
|
|
#### 3.1 对接伤害管线
|
|||
|
|
|
|||
|
|
符修攻击符接入现有五段伤害管线(来自 Community 5):
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
释符(烈火符)
|
|||
|
|
│ URPGGameplayAbility::ActivateAbility()
|
|||
|
|
├── 构造 FSkillDamageData
|
|||
|
|
│ ├─ SkillDamage = SetByCaller.FireDamage × TierMultiplier
|
|||
|
|
│ ├─ SkillToughDamage = SetByCaller.FireDamage × 0.3
|
|||
|
|
│ └─ HitLevel = ERPGHitLevel::LV1(黄纸)~ LV3(玉敕)
|
|||
|
|
│
|
|||
|
|
└── ARPGCharacterBase::ReceiveDamageEvent()
|
|||
|
|
├── USDHDamageCaculationSetting::CaculateDamage()
|
|||
|
|
│ ├─ 暴击 / 命中 / 闪避 / 防御减伤
|
|||
|
|
│ └─ 输出 { ShieldDamage, ToughDamage, HealthDamage }
|
|||
|
|
├── 优先扣 Shield → 再扣 Tough → 最后扣 Health
|
|||
|
|
└── URPGAttributeSet::PostGameplayEffectExecute
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3.2 符箓充能与释放系统
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
// URPGFuXiuAbilityComponent — 符修专属 ASC 扩展
|
|||
|
|
UCLASS()
|
|||
|
|
class URPGFuXiuAbilityComponent : public UActorComponent
|
|||
|
|
{
|
|||
|
|
// 符箓背包(最多携带 N 张符)
|
|||
|
|
UPROPERTY()
|
|||
|
|
TArray<FRPGTalismanEffect> EquippedTalismans;
|
|||
|
|
|
|||
|
|
// 制符(非战斗状态,消耗材料+法力+时间)
|
|||
|
|
UFUNCTION(BlueprintCallable)
|
|||
|
|
FRPGTalismanEffect CraftTalisman(FName TalismanId, ERPGTalismanTier Tier);
|
|||
|
|
|
|||
|
|
// 释符(战斗中触发 GAS GE)
|
|||
|
|
UFUNCTION(BlueprintCallable)
|
|||
|
|
bool ActivateTalisman(int32 TalismanIndex, AActor* Target = nullptr);
|
|||
|
|
|
|||
|
|
// 符箓等级倍率
|
|||
|
|
float GetTierMultiplier(ERPGTalismanTier Tier) const
|
|||
|
|
{
|
|||
|
|
static const TMap<ERPGTalismanTier, float> Multipliers = {
|
|||
|
|
{ ERPGTalismanTier::YellowPaper, 1.0f },
|
|||
|
|
{ ERPGTalismanTier::SilverScript, 1.5f },
|
|||
|
|
{ ERPGTalismanTier::GoldSeal, 2.2f },
|
|||
|
|
{ ERPGTalismanTier::JadeEdict, 3.0f },
|
|||
|
|
};
|
|||
|
|
return Multipliers.FindRef(Tier);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3.3 SetByCaller 符箓 Tag 体系
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
// 在 SDHGameTagSettings 中新增符箓专属 SetByCaller Tag
|
|||
|
|
namespace RPGSetByCaller
|
|||
|
|
{
|
|||
|
|
// 攻击符
|
|||
|
|
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Talisman_Fire_Damage);
|
|||
|
|
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Talisman_Ice_SlowPercent);
|
|||
|
|
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Talisman_Thunder_Damage);
|
|||
|
|
|
|||
|
|
// 防御符
|
|||
|
|
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Talisman_Barrier_ShieldAmount);
|
|||
|
|
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Talisman_IronWall_DefenseBonus);
|
|||
|
|
|
|||
|
|
// 辅助符
|
|||
|
|
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Talisman_Speed_Bonus);
|
|||
|
|
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Talisman_Meditate_ManaRegen);
|
|||
|
|
|
|||
|
|
// 诅咒符
|
|||
|
|
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Talisman_Weaken_AttackReduce);
|
|||
|
|
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Talisman_SoulDrain_Amount);
|
|||
|
|
|
|||
|
|
// 阵法符
|
|||
|
|
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Talisman_Trap_Radius);
|
|||
|
|
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Talisman_SwordArray_PerSwordDamage);
|
|||
|
|
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Talisman_HealField_HealPerTick);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 四、符箓效果示例:「裂空·雷击符」
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
蓝图配置(BP_GE_Talisman_Thunder_Base):
|
|||
|
|
|
|||
|
|
Modifiers:
|
|||
|
|
├─ URPGAttributeSet::Damage
|
|||
|
|
│ ├─ ModifierOp: Override
|
|||
|
|
│ └─ Magnitude: SetByCaller (Tag=Talisman_Thunder_Damage)
|
|||
|
|
├─ URPGAttributeSet::Tough
|
|||
|
|
│ ├─ ModifierOp: Add
|
|||
|
|
│ └─ Magnitude: SetByCaller (Tag=Talisman_Thunder_Damage) × -0.3
|
|||
|
|
└─ GameplayTag:
|
|||
|
|
└─ Grant: State.HitReaction.Stagger(击退硬直)
|
|||
|
|
|
|||
|
|
Duration Policy: Instant
|
|||
|
|
|
|||
|
|
Damage 计算链:
|
|||
|
|
Base Damage = SetByCaller.Talisman_Thunder_Damage (50)
|
|||
|
|
× TierMultiplier (黄纸=1.0 / 银篆=1.5 / 金印=2.2 / 玉敕=3.0)
|
|||
|
|
× 符修修为加成 (境界 × 0.05)
|
|||
|
|
× 当前灵力系数 (Mana/MaxMana × 0.5 + 0.5)
|
|||
|
|
|
|||
|
|
黄纸雷击符 = 50 × 1.0 × 1.0 × 1.0 = 50 伤害 + 15 削韧
|
|||
|
|
玉敕雷击符 = 50 × 3.0 × 2.0 × 1.0 = 300 伤害 + 90 削韧
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 五、涉及文件清单
|
|||
|
|
|
|||
|
|
| 文件(新建/修改) | 内容 |
|
|||
|
|
|------|------|
|
|||
|
|
| `Public/Abilities/Talisman/FRTalismanData.h` | **新建**:符箓数据结构、枚举 |
|
|||
|
|
| `Public/Abilities/Talisman/URPGFuXiuAbilityComponent.h/.cpp` | **新建**:符修 ASC 扩展组件 |
|
|||
|
|
| `Public/Abilities/Talisman/GE_Talisman_*.h` | **新建**:5 类 14 个 GameplayEffect 蓝图基类 |
|
|||
|
|
| `Public/Config/SDHGameTagSettings.h` | **修改**:新增 SetByCaller.Talisman_* Tag |
|
|||
|
|
| `Public/Character/Attribute/RPGAttributeSet.h` | **不变**:符箓几何修改现有 Health/Shield/Tough/Mana/MoveSpeed/AttackPower/DefensePower 属性 |
|
|||
|
|
| `Public/Items/RPGItem.h` | **修改**:新增 `URPGTalismanItem` 物品类型 |
|
|||
|
|
| `.trae/documents/01_策划设计/修仙基础概念设定/修仙流派.md` | **修改**:符修独立为独立流派(当前在魔修路径下) |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 附录:关键文件速查
|
|||
|
|
|
|||
|
|
| 缩写 | 全称 | 核心文件位置 |
|
|||
|
|
|------|------|------------|
|
|||
|
|
| LWS | LivingWorldSystem | `Plugins/RPGGameCore/Source/LivingWorldSystem/` |
|
|||
|
|
| GA/GAS | Gameplay Ability System | `Plugins/RPGGameCore/Source/RPGGameplayAbility/` |
|
|||
|
|
| ASC | AbilitySystemComponent | `URPGAbilitySystemComponent` |
|
|||
|
|
| GE | GameplayEffect | UGameplayEffect 蓝图子类 |
|
|||
|
|
| CMC | CharacterMovementComponent | `LCMCharacterMovementComponent` |
|
|||
|
|
| ActionPose | 架势(主姿态) | `ELM_ActionPose` 在 `RPGTypes.h:203`,24 个主架势 |
|
|||
|
|
| SM | SkillStateMachine | `USkillSMInstance` (LogicDriver) |
|