Compare commits
16
Commits
de53890de6
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
91b8e177c5 | ||
|
|
051c075183 | ||
|
|
c61eb7fb68 | ||
|
|
02f4c67464 | ||
|
|
ba25ec1926 | ||
|
|
92e1ea0d55 | ||
|
|
1e4d3ef8d7 | ||
|
|
88ed35e757 | ||
|
|
421f8bf619 | ||
|
|
17ee268416 | ||
|
|
5fbeec2476 | ||
|
|
9c54905f85 | ||
|
|
b628a8537c | ||
|
|
091a29db63 | ||
|
|
e2fdb660ab | ||
|
|
7dc529a840 |
@@ -0,0 +1,109 @@
|
||||
---
|
||||
name: code-hygiene
|
||||
description: >-
|
||||
Inspect and clean up code in the Seek-Battle-Evacuate (SBE) project according to AGENTS.md
|
||||
null-checking rules, error handling specifications, and anti-defensive programming guidelines.
|
||||
Use this skill whenever the user asks to format code per AGENTS.md, clean up redundant null checks,
|
||||
remove over-defensive fallbacks, or review code hygiene.
|
||||
---
|
||||
|
||||
# SBE Code Hygiene & Defensive Cleanup
|
||||
|
||||
本技能用于规范 SBE 项目中的 C# 代码质量,消除过度防御(Over-Defensive Programming)、冗余判空与静默吞错,严格对齐 `AGENTS.md` 规范与敏捷“Fail Fast”(快速失败)原则。
|
||||
|
||||
---
|
||||
|
||||
## 一、三项核心红线(AGENTS.md 必须遵守)
|
||||
|
||||
1. **声明处已初始化的变量,之后绝对不判空**
|
||||
- 坏:字段或局部变量已有 `= new List<T>()` / `= new Dictionary<...>()`,后续还写 `if (_list != null)`。
|
||||
- 好:直接使用 `_list.Add(...)`、`_list.Clear()`。
|
||||
|
||||
2. **严禁静态兜底与静默回退(Fail Fast 原则)**
|
||||
- 坏:找不到数据、缺少配置或解析异常时,返回硬编码默认值(如 `global != null ? global.Time : 250` 或 `if (cfg == null) return 10;`)。
|
||||
- 好:异常路径直接 `Log.Error(...)` 报错并中断执行(`return` / 抛异常),绝不用伪造数据让程序带病运行。
|
||||
|
||||
3. **UI 序列化字段与 View 自动绑定字段不做判空**
|
||||
- 坏:`if (View != null && View.sortButton != null)`、`[SerializeField] private Button _btn; ... if (_btn != null)`。
|
||||
- 好:默认信任 Inspector 和 `UIAssetsTools` 自动绑定。若没绑定本应报错暴露,不加空防御掩盖。
|
||||
|
||||
---
|
||||
|
||||
## 二、六项常见“没必要”的过度防御与坏味道
|
||||
|
||||
在 Unity / UGF / C# 实际开发中,以下写法通常是冗余、降低代码可读性且增加维护负担的:
|
||||
|
||||
### 1. 集合遍历前的非空/长度双重检查
|
||||
- **没必要**:
|
||||
```csharp
|
||||
if (list != null && list.Count > 0)
|
||||
{
|
||||
foreach (var item in list) { ... }
|
||||
}
|
||||
```
|
||||
- **原则**:若列表规范为非空对象(即使为空也是包含 0 个元素的空列表),`foreach` 会自动直接跳过,根本无需任何 `if` 守卫:
|
||||
```csharp
|
||||
foreach (var item in list) { ... }
|
||||
```
|
||||
|
||||
### 2. LINQ 与内建构造返回值的非空检查
|
||||
- **没必要**:
|
||||
```csharp
|
||||
var results = items.Where(x => x.Active).ToList();
|
||||
if (results != null) { ... } // ToList() 永远返回新 List 实例,永不为 null
|
||||
```
|
||||
- **原则**:直接使用 LINQ 投影/转换结果。
|
||||
|
||||
### 3. 内部私有辅助方法的层层重复防御
|
||||
- **没必要**:公有入口方法已经做了入参断言/校验,拆分出来的内部私有方法 `private void ApplyCore(Item item)` 每一层都再写一遍 `if (item == null) return;`。
|
||||
- **原则**:私有方法属于内部信任边界,保持干净直白,将校验集中在业务入口。
|
||||
|
||||
### 4. 字典的双重查找(Double Lookup)
|
||||
- **没必要**:
|
||||
```csharp
|
||||
if (_dict.ContainsKey(key))
|
||||
{
|
||||
var val = _dict[key];
|
||||
...
|
||||
}
|
||||
```
|
||||
- **原则**:统一使用 `TryGetValue`,减少一次哈希哈希计算与冗余判断:
|
||||
```csharp
|
||||
if (_dict.TryGetValue(key, out var val))
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
### 5. 静默吞异常的空 Try-Catch
|
||||
- **没必要**:
|
||||
```csharp
|
||||
try { DoSomething(); }
|
||||
catch (Exception) { /* 留空,或者只 Log.Warning 假装没事 */ }
|
||||
```
|
||||
- **原则**:非预期异常必须 `Log.Error(...)` 暴露上下文并附带具体错误信息,绝不能掩盖致命逻辑错误或数据存盘缺失。
|
||||
|
||||
### 6. MonoBehaviour/实例方法内的自我判空
|
||||
- **没必要**:在普通实例方法内部写 `if (this == null)`,或对由 Unity 生命周期保证的对象进行反复探测。
|
||||
- **原则**:信任正常的组件调用生命周期。
|
||||
|
||||
---
|
||||
|
||||
## 三、代码排查与清理步骤(Runbook)
|
||||
|
||||
当用户发出整理请求时,按以下流程执行:
|
||||
|
||||
1. **识别范围**:
|
||||
- 检查 `git status` 涉及修改的文件,或针对用户指定的代码文件。
|
||||
2. **逐项审查**:
|
||||
- [ ] 检查是否有 `[SerializeField]`、`View.xxx` 的判空,有则移除。
|
||||
- [ ] 检查声明处赋值(如 `= new ...`)字段的二次判空,有则移除。
|
||||
- [ ] 检查是否有配置读取、存档读取的三元默认值回退(`?:` 魔法数字),改为 `Log.Error` 并中断。
|
||||
- [ ] 检查 `foreach` 外层是否有冗余的 `if (list != null && list.Count > 0)` 嵌套,若列表非空则拍平。
|
||||
- [ ] 检查是否有空 `catch` 吞错。
|
||||
3. **推演逻辑边界(静态检查)**:
|
||||
- 确认移除防御后不会导致不可预知的崩溃;
|
||||
- 确认异常路径是否确实按规范输出了 `Log.Error`。
|
||||
4. **汇报改动**:
|
||||
- 列出修改的文件路径;
|
||||
- 简要说明移除了哪些冗余防御或规范了哪些异常断言。
|
||||
@@ -0,0 +1,5 @@
|
||||
# CodeGraph data files — local to each machine, not for committing.
|
||||
# Ignore everything in .codegraph/ except this file itself, so transient
|
||||
# files (the database, daemon.pid, sockets, logs) never show up in git.
|
||||
*
|
||||
!.gitignore
|
||||
+1
-5
@@ -88,9 +88,5 @@ crashlytics-build.properties
|
||||
|
||||
~$*.xlsx
|
||||
Assets/GameMain/Configs/ResourceBuilder.xml
|
||||
/.dotnet
|
||||
/.omx
|
||||
/.vscode
|
||||
/openspec/changes/archive
|
||||
/.omc
|
||||
/.claude
|
||||
/Tools/make_atlas/input
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# AGENTS.md — SBE(Seek-Battle-Evacuate)
|
||||
# AGENTS.md
|
||||
|
||||
单人 3d 类吸血鬼幸存者游戏原型。Unity 2022.3.62f3,框架为 GameFramework(UGF,源码在 `Assets/GameFramework/`),配置表用 Luban,插件有 UniTask、DOTween 等。
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
- UGF 只对顶级 Form 调用 `OnInit/OnOpen/OnClose` 生命周期;**嵌套 Form 的这些方法永远不会执行**。事件绑定用幂等模式(`_listenersBound` 标志 + `EnsureXxx()`),放在能力入口(如 `Refresh`)里。
|
||||
- 子 Form 只提供能力(public 方法,幂等可重入),数据由调用方传入;只有顶级 Form 有编排权。子组件向上通信用 `GameEntry.Event.Fire` + `XxxEventArgs`(放 `Scripts/Base/Event/UIForm/`,`ReferencePool` + `Create`/`Clear`),禁止反向持有父 Form。
|
||||
|
||||
## Luban 约定(详见 `Docs/Tech/01_LubanDataTable.md`)
|
||||
## Luban 约定(详见 `docs/tech/01_LubanDataTable.md`)
|
||||
|
||||
- 表名小写 `tbxxxconfig`:Excel 表名、导出文件名、`Tables` 构造参数、`TableNames` 数组四处必须一致。
|
||||
- 访问入口 `GameEntry.Luban.Get<T>(id)` / `GetTable<T>()`;单行表(`mode=one`,如 `tbglobalconfig`)不注册访问器,走 `Tables.TbXxxConfig.Data`。
|
||||
@@ -36,6 +36,7 @@
|
||||
- 不做静态回退(不用默认值/兜底逻辑静默继续);异常路径直接 `Log.Error(...)` 抛出(UGF 的 `Log`,支持格式串,如 `Log.Error("Entity data is invalid.")`)。
|
||||
- UI 的序列化字段(`[SerializeField]` 及 View 生成的引用)**不做判空检查**,默认已在 Inspector 中赋值。
|
||||
- GameEntry 中提供的静态入口不对其进行判空,默认其不为空。
|
||||
- 对于从 Luban 中取出的数据,默认其是有效且不为空的,代码里不对其做任何有效性检测
|
||||
|
||||
## 代码风格
|
||||
|
||||
|
||||
Binary file not shown.
@@ -1,6 +1,7 @@
|
||||
[
|
||||
{
|
||||
"name": "近战敌人",
|
||||
"enemyType": 1,
|
||||
"logicType": "MeleeEnemy",
|
||||
"maxHealth": 50,
|
||||
"hpAddPerLevel": 50,
|
||||
"attackDamage": 1,
|
||||
@@ -8,14 +9,15 @@
|
||||
"attackRange": 1.5,
|
||||
"speed": 3,
|
||||
"coinDrop": 5,
|
||||
"expDrop": 1,
|
||||
"expDrop": 20,
|
||||
"dropPercent": 0.3,
|
||||
"scale": 1,
|
||||
"color": "#44FF44",
|
||||
"prefab": "MeleeEnemy"
|
||||
},
|
||||
{
|
||||
"name": "远程敌人",
|
||||
"enemyType": 2,
|
||||
"logicType": "RemoteEnemy",
|
||||
"maxHealth": 40,
|
||||
"hpAddPerLevel": 40,
|
||||
"attackDamage": 1,
|
||||
@@ -23,14 +25,15 @@
|
||||
"attackRange": 8,
|
||||
"speed": 2.5,
|
||||
"coinDrop": 4,
|
||||
"expDrop": 2,
|
||||
"expDrop": 20,
|
||||
"dropPercent": 0.2,
|
||||
"scale": 1,
|
||||
"color": "#FF44FF",
|
||||
"prefab": "RemoteEnemy"
|
||||
},
|
||||
{
|
||||
"name": "蝙蝠",
|
||||
"enemyType": 3,
|
||||
"logicType": "BatEnemy",
|
||||
"maxHealth": 20,
|
||||
"hpAddPerLevel": 15,
|
||||
"attackDamage": 1,
|
||||
@@ -38,14 +41,15 @@
|
||||
"attackRange": 1.2,
|
||||
"speed": 6,
|
||||
"coinDrop": 3,
|
||||
"expDrop": 1,
|
||||
"expDrop": 25,
|
||||
"dropPercent": 0.4,
|
||||
"scale": 0.5,
|
||||
"color": "#FF4444",
|
||||
"prefab": "MeleeEnemy"
|
||||
},
|
||||
{
|
||||
"name": "骷髅兵",
|
||||
"enemyType": 4,
|
||||
"logicType": "SkeletonEnemy",
|
||||
"maxHealth": 80,
|
||||
"hpAddPerLevel": 60,
|
||||
"attackDamage": 2,
|
||||
@@ -53,14 +57,15 @@
|
||||
"attackRange": 1.8,
|
||||
"speed": 2.5,
|
||||
"coinDrop": 6,
|
||||
"expDrop": 2,
|
||||
"expDrop": 25,
|
||||
"dropPercent": 0.3,
|
||||
"scale": 1.3,
|
||||
"color": "#CCCCCC",
|
||||
"prefab": "MeleeEnemy"
|
||||
},
|
||||
{
|
||||
"name": "骷髅巨人",
|
||||
"enemyType": 5,
|
||||
"logicType": "SkeletonGiantEnemy",
|
||||
"maxHealth": 200,
|
||||
"hpAddPerLevel": 120,
|
||||
"attackDamage": 3,
|
||||
@@ -68,14 +73,15 @@
|
||||
"attackRange": 2.5,
|
||||
"speed": 1.5,
|
||||
"coinDrop": 10,
|
||||
"expDrop": 3,
|
||||
"expDrop": 30,
|
||||
"dropPercent": 0.25,
|
||||
"scale": 2,
|
||||
"color": "#888888",
|
||||
"prefab": "MeleeEnemy"
|
||||
},
|
||||
{
|
||||
"name": "幽灵",
|
||||
"enemyType": 6,
|
||||
"logicType": "GhostEnemy",
|
||||
"maxHealth": 30,
|
||||
"hpAddPerLevel": 25,
|
||||
"attackDamage": 1,
|
||||
@@ -83,14 +89,15 @@
|
||||
"attackRange": 10,
|
||||
"speed": 3,
|
||||
"coinDrop": 5,
|
||||
"expDrop": 2,
|
||||
"expDrop": 30,
|
||||
"dropPercent": 0.3,
|
||||
"scale": 0.8,
|
||||
"color": "#88CCFF",
|
||||
"prefab": "RemoteEnemy"
|
||||
},
|
||||
{
|
||||
"name": "火焰法师",
|
||||
"enemyType": 7,
|
||||
"logicType": "FireMageEnemy",
|
||||
"maxHealth": 60,
|
||||
"hpAddPerLevel": 45,
|
||||
"attackDamage": 2,
|
||||
@@ -98,7 +105,7 @@
|
||||
"attackRange": 12,
|
||||
"speed": 2,
|
||||
"coinDrop": 8,
|
||||
"expDrop": 3,
|
||||
"expDrop": 30,
|
||||
"dropPercent": 0.2,
|
||||
"scale": 1.2,
|
||||
"color": "#FF8800",
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
FollowCameraFollowCamera.prefabPlayer␍Player.prefab
|
||||
FollowCameraFollowCamera.prefabPlayer␍Player.prefab
|
||||
MeleeEnemyMeleeEnemy.prefabRemoteEnemyRemoteEnemy.prefabWeaponKnifeWeaponKnife.prefab␍WeaponHandgunWeaponHandgun.prefabWeaponSlashWeaponSlash.prefabWeaponLightningWeaponLightning.prefabWeaponLanceWeaponLance.prefab
|
||||
CoinEntityCoinEntity.prefab ExpEntityExpEntity.prefab
|
||||
ProjectileProjectile.prefab
|
||||
@@ -42,5 +42,9 @@
|
||||
{
|
||||
"assetName": "ExpEntity",
|
||||
"prefabPath": "ExpEntity.prefab"
|
||||
},
|
||||
{
|
||||
"assetName": "Projectile",
|
||||
"prefabPath": "Projectile.prefab"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,3 @@
|
||||
HUDHpText {0} / {1}
|
||||
HUDExpTextLv.{0}HUDCoinText <sprite name="coin" index=0> {0}HUDCPUTimeCostTextCPU Frame: {0:F2} msHUDEnemyCountText
|
||||
Enemy: {0}LevelUpRefreshCostText(刷新 -{0} <sprite name="coin" index=0>␍ShopTitleText商店 (Lv.{0})ShopContinueButtonText继续 (Lv.{0})ShopPlayerCoinText<sprite name="coin"> {0}ShopRefreshCostText 刷新 -{0} <sprite name="coin">WeaponListTitle武器 ({0}/{1})␍PropListTitle道具 ({0})ShopGoodsCostText {0} <sprite name="coin" index=0>TooltipRecycleButtonText'出售 {0} <sprite name="coin" index=0>
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 09ee293d7e6c7b5478b17ac940bcfb8e
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,58 @@
|
||||
[
|
||||
{
|
||||
"name": "HUDHpText",
|
||||
"format": "{0} / {1}"
|
||||
},
|
||||
{
|
||||
"name": "HUDExpText",
|
||||
"format": "Lv.{0}"
|
||||
},
|
||||
{
|
||||
"name": "HUDCoinText",
|
||||
"format": "<sprite name=\"coin\" index=0> {0}"
|
||||
},
|
||||
{
|
||||
"name": "HUDCPUTimeCostText",
|
||||
"format": "CPU Frame: {0:F2} ms"
|
||||
},
|
||||
{
|
||||
"name": "HUDEnemyCountText",
|
||||
"format": "Enemy: {0}"
|
||||
},
|
||||
{
|
||||
"name": "LevelUpRefreshCostText",
|
||||
"format": "刷新 -{0} <sprite name=\"coin\" index=0>"
|
||||
},
|
||||
{
|
||||
"name": "ShopTitleText",
|
||||
"format": "商店 (Lv.{0})"
|
||||
},
|
||||
{
|
||||
"name": "ShopContinueButtonText",
|
||||
"format": "继续 (Lv.{0})"
|
||||
},
|
||||
{
|
||||
"name": "ShopPlayerCoinText",
|
||||
"format": "<sprite name=\"coin\"> {0}"
|
||||
},
|
||||
{
|
||||
"name": "ShopRefreshCostText",
|
||||
"format": "刷新 -{0} <sprite name=\"coin\">"
|
||||
},
|
||||
{
|
||||
"name": "WeaponListTitle",
|
||||
"format": "武器 ({0}/{1})"
|
||||
},
|
||||
{
|
||||
"name": "PropListTitle",
|
||||
"format": "道具 ({0})"
|
||||
},
|
||||
{
|
||||
"name": "ShopGoodsCostText",
|
||||
"format": "{0} <sprite name=\"coin\" index=0>"
|
||||
},
|
||||
{
|
||||
"name": "TooltipRecycleButtonText",
|
||||
"format": "出售 {0} <sprite name=\"coin\" index=0>"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5c1d742cd5d626e4e867ec0ca8482db7
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
@@ -1,5 +1,38 @@
|
||||
[
|
||||
{
|
||||
"elapsedTime": 1000
|
||||
"weaponCapacity": 6,
|
||||
"propMaxCount": -1,
|
||||
"playerEntity": "Player",
|
||||
"absorbSpeed": 12,
|
||||
"collectDistance": 0.5,
|
||||
"defaultAbsorbRange": 4,
|
||||
"weaponRecycleRate": 0.3,
|
||||
"shopGoodsCount": 4,
|
||||
"shopPriceRandomPercent": 0.05,
|
||||
"shopMinPrice": 1,
|
||||
"levelUpRefreshPriceBase": 2,
|
||||
"levelUpRewardCount": 4,
|
||||
"spawnEnemyMaxCount": 5000,
|
||||
"enemySpawnDistanceMin": 14,
|
||||
"enemySpawnDistanceMax": 18,
|
||||
"weaponRotateSpeed": 5,
|
||||
"weaponBaseCrit": 0.05,
|
||||
"playerGroupName": "Player",
|
||||
"enemyGroupName": "Enemy",
|
||||
"projectileGroupName": "Projectile",
|
||||
"dropGroupName": "Drop",
|
||||
"effectGroupNmae": "Effect",
|
||||
"minDamage": 1,
|
||||
"maxDodgeRate": 900,
|
||||
"minSpawnRateScale": 100,
|
||||
"projectileLifeTime": 3000,
|
||||
"projectileHeightOffset": 600,
|
||||
"projectileSpeed": 12000,
|
||||
"projectileEntity": "Projectile",
|
||||
"damageTextYOffset": 1100,
|
||||
"entityAsyncTimeout": 30000,
|
||||
"critMultiplier": 1.5,
|
||||
"enemyBodyRadius": 450,
|
||||
"enemySeparationIterations": 2
|
||||
}
|
||||
]
|
||||
Binary file not shown.
@@ -1,127 +1,152 @@
|
||||
[
|
||||
{
|
||||
"Id": 1001,
|
||||
"GoodsType": 1,
|
||||
"GoodsTypeId": 1001
|
||||
"id": 1001,
|
||||
"goodsType": 1,
|
||||
"propId": 1001,
|
||||
"weaponType": 0
|
||||
},
|
||||
{
|
||||
"Id": 1002,
|
||||
"GoodsType": 2,
|
||||
"GoodsTypeId": 1001
|
||||
"id": 1002,
|
||||
"goodsType": 2,
|
||||
"propId": 0,
|
||||
"weaponType": 1
|
||||
},
|
||||
{
|
||||
"Id": 1003,
|
||||
"GoodsType": 1,
|
||||
"GoodsTypeId": 1002
|
||||
"id": 1003,
|
||||
"goodsType": 1,
|
||||
"propId": 1002,
|
||||
"weaponType": 0
|
||||
},
|
||||
{
|
||||
"Id": 1004,
|
||||
"GoodsType": 1,
|
||||
"GoodsTypeId": 1003
|
||||
"id": 1004,
|
||||
"goodsType": 1,
|
||||
"propId": 1003,
|
||||
"weaponType": 0
|
||||
},
|
||||
{
|
||||
"Id": 1005,
|
||||
"GoodsType": 1,
|
||||
"GoodsTypeId": 1004
|
||||
"id": 1005,
|
||||
"goodsType": 1,
|
||||
"propId": 1004,
|
||||
"weaponType": 0
|
||||
},
|
||||
{
|
||||
"Id": 1006,
|
||||
"GoodsType": 2,
|
||||
"GoodsTypeId": 1002
|
||||
"id": 1006,
|
||||
"goodsType": 2,
|
||||
"propId": 0,
|
||||
"weaponType": 2
|
||||
},
|
||||
{
|
||||
"Id": 1007,
|
||||
"GoodsType": 1,
|
||||
"GoodsTypeId": 1005
|
||||
"id": 1007,
|
||||
"goodsType": 1,
|
||||
"propId": 1005,
|
||||
"weaponType": 0
|
||||
},
|
||||
{
|
||||
"Id": 1008,
|
||||
"GoodsType": 1,
|
||||
"GoodsTypeId": 1006
|
||||
"id": 1008,
|
||||
"goodsType": 1,
|
||||
"propId": 1006,
|
||||
"weaponType": 0
|
||||
},
|
||||
{
|
||||
"Id": 1009,
|
||||
"GoodsType": 1,
|
||||
"GoodsTypeId": 1007
|
||||
"id": 1009,
|
||||
"goodsType": 1,
|
||||
"propId": 1007,
|
||||
"weaponType": 0
|
||||
},
|
||||
{
|
||||
"Id": 1010,
|
||||
"GoodsType": 1,
|
||||
"GoodsTypeId": 1008
|
||||
"id": 1010,
|
||||
"goodsType": 1,
|
||||
"propId": 1008,
|
||||
"weaponType": 0
|
||||
},
|
||||
{
|
||||
"Id": 1011,
|
||||
"GoodsType": 1,
|
||||
"GoodsTypeId": 1009
|
||||
"id": 1011,
|
||||
"goodsType": 1,
|
||||
"propId": 1009,
|
||||
"weaponType": 0
|
||||
},
|
||||
{
|
||||
"Id": 1012,
|
||||
"GoodsType": 1,
|
||||
"GoodsTypeId": 1010
|
||||
"id": 1012,
|
||||
"goodsType": 1,
|
||||
"propId": 1010,
|
||||
"weaponType": 0
|
||||
},
|
||||
{
|
||||
"Id": 1013,
|
||||
"GoodsType": 1,
|
||||
"GoodsTypeId": 1011
|
||||
"id": 1013,
|
||||
"goodsType": 1,
|
||||
"propId": 1011,
|
||||
"weaponType": 0
|
||||
},
|
||||
{
|
||||
"Id": 1014,
|
||||
"GoodsType": 1,
|
||||
"GoodsTypeId": 1012
|
||||
"id": 1014,
|
||||
"goodsType": 1,
|
||||
"propId": 1012,
|
||||
"weaponType": 0
|
||||
},
|
||||
{
|
||||
"Id": 1015,
|
||||
"GoodsType": 1,
|
||||
"GoodsTypeId": 1013
|
||||
"id": 1015,
|
||||
"goodsType": 1,
|
||||
"propId": 1013,
|
||||
"weaponType": 0
|
||||
},
|
||||
{
|
||||
"Id": 1016,
|
||||
"GoodsType": 1,
|
||||
"GoodsTypeId": 1014
|
||||
"id": 1016,
|
||||
"goodsType": 1,
|
||||
"propId": 1014,
|
||||
"weaponType": 0
|
||||
},
|
||||
{
|
||||
"Id": 1017,
|
||||
"GoodsType": 1,
|
||||
"GoodsTypeId": 1015
|
||||
"id": 1017,
|
||||
"goodsType": 1,
|
||||
"propId": 1015,
|
||||
"weaponType": 0
|
||||
},
|
||||
{
|
||||
"Id": 1018,
|
||||
"GoodsType": 1,
|
||||
"GoodsTypeId": 1016
|
||||
"id": 1018,
|
||||
"goodsType": 1,
|
||||
"propId": 1016,
|
||||
"weaponType": 0
|
||||
},
|
||||
{
|
||||
"Id": 1019,
|
||||
"GoodsType": 1,
|
||||
"GoodsTypeId": 1017
|
||||
"id": 1019,
|
||||
"goodsType": 1,
|
||||
"propId": 1017,
|
||||
"weaponType": 0
|
||||
},
|
||||
{
|
||||
"Id": 1020,
|
||||
"GoodsType": 1,
|
||||
"GoodsTypeId": 1018
|
||||
"id": 1020,
|
||||
"goodsType": 1,
|
||||
"propId": 1018,
|
||||
"weaponType": 0
|
||||
},
|
||||
{
|
||||
"Id": 1021,
|
||||
"GoodsType": 1,
|
||||
"GoodsTypeId": 1019
|
||||
"id": 1021,
|
||||
"goodsType": 1,
|
||||
"propId": 1019,
|
||||
"weaponType": 0
|
||||
},
|
||||
{
|
||||
"Id": 1022,
|
||||
"GoodsType": 1,
|
||||
"GoodsTypeId": 1020
|
||||
"id": 1022,
|
||||
"goodsType": 1,
|
||||
"propId": 1020,
|
||||
"weaponType": 0
|
||||
},
|
||||
{
|
||||
"Id": 1023,
|
||||
"GoodsType": 2,
|
||||
"GoodsTypeId": 1003
|
||||
"id": 1023,
|
||||
"goodsType": 2,
|
||||
"propId": 0,
|
||||
"weaponType": 3
|
||||
},
|
||||
{
|
||||
"Id": 1024,
|
||||
"GoodsType": 2,
|
||||
"GoodsTypeId": 1004
|
||||
"id": 1024,
|
||||
"goodsType": 2,
|
||||
"propId": 0,
|
||||
"weaponType": 4
|
||||
},
|
||||
{
|
||||
"Id": 1025,
|
||||
"GoodsType": 2,
|
||||
"GoodsTypeId": 1005
|
||||
"id": 1025,
|
||||
"goodsType": 2,
|
||||
"propId": 0,
|
||||
"weaponType": 5
|
||||
}
|
||||
]
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
餈烐��䔶犖�餈𦦵��䔶犖�<餈烐��䔶犖斆<餈烐��䔶犖斆�躰�䧧< 撉琿���䧧餈𦦵��䔶犖�<餈烐��䔶犖
|
||||
��躰�箮< 撉琿���䧧撟賜�斆F�躰�䧧撟賜�䧧F餈烐��䔶犖䧧撉琿�撌其犖籖�怎�瘜訫��P 撉琿����撉琿�撌其犖炥�怎�瘜訫�䧧Z
|
||||
�躰�
|
||||
箮 撉琿���籖撟賜�䧧�怎�瘜訫��x
|
||||
� ��<�Ќ<�Ќ�И<�И� <
|
||||
�Ф�а<�И�ЌF�И�ИF�И�@��P �Ф�p�ИZ
|
||||
|
||||
�а�@�И� x
|
||||
@@ -3,12 +3,12 @@
|
||||
"id": 1,
|
||||
"enemySpawnConfigs": [
|
||||
{
|
||||
"enemyName": "近战敌人",
|
||||
"enemyType": 1,
|
||||
"enemyCount": 5,
|
||||
"interval": 4000
|
||||
},
|
||||
{
|
||||
"enemyName": "远程敌人",
|
||||
"enemyType": 2,
|
||||
"enemyCount": 2,
|
||||
"interval": 5000
|
||||
}
|
||||
@@ -19,7 +19,7 @@
|
||||
"id": 2,
|
||||
"enemySpawnConfigs": [
|
||||
{
|
||||
"enemyName": "近战敌人",
|
||||
"enemyType": 1,
|
||||
"enemyCount": 8,
|
||||
"interval": 3500
|
||||
}
|
||||
@@ -30,12 +30,12 @@
|
||||
"id": 3,
|
||||
"enemySpawnConfigs": [
|
||||
{
|
||||
"enemyName": "近战敌人",
|
||||
"enemyType": 1,
|
||||
"enemyCount": 6,
|
||||
"interval": 3500
|
||||
},
|
||||
{
|
||||
"enemyName": "蝙蝠",
|
||||
"enemyType": 3,
|
||||
"enemyCount": 4,
|
||||
"interval": 3000
|
||||
}
|
||||
@@ -46,12 +46,12 @@
|
||||
"id": 4,
|
||||
"enemySpawnConfigs": [
|
||||
{
|
||||
"enemyName": "骷髅兵",
|
||||
"enemyType": 4,
|
||||
"enemyCount": 6,
|
||||
"interval": 3000
|
||||
},
|
||||
{
|
||||
"enemyName": "远程敌人",
|
||||
"enemyType": 2,
|
||||
"enemyCount": 4,
|
||||
"interval": 4000
|
||||
}
|
||||
@@ -62,12 +62,12 @@
|
||||
"id": 5,
|
||||
"enemySpawnConfigs": [
|
||||
{
|
||||
"enemyName": "近战敌人",
|
||||
"enemyType": 1,
|
||||
"enemyCount": 10,
|
||||
"interval": 2500
|
||||
},
|
||||
{
|
||||
"enemyName": "蝙蝠",
|
||||
"enemyType": 3,
|
||||
"enemyCount": 5,
|
||||
"interval": 2000
|
||||
}
|
||||
@@ -78,12 +78,12 @@
|
||||
"id": 6,
|
||||
"enemySpawnConfigs": [
|
||||
{
|
||||
"enemyName": "骷髅兵",
|
||||
"enemyType": 4,
|
||||
"enemyCount": 6,
|
||||
"interval": 3000
|
||||
},
|
||||
{
|
||||
"enemyName": "幽灵",
|
||||
"enemyType": 6,
|
||||
"enemyCount": 5,
|
||||
"interval": 3500
|
||||
}
|
||||
@@ -94,12 +94,12 @@
|
||||
"id": 7,
|
||||
"enemySpawnConfigs": [
|
||||
{
|
||||
"enemyName": "蝙蝠",
|
||||
"enemyType": 3,
|
||||
"enemyCount": 5,
|
||||
"interval": 3000
|
||||
},
|
||||
{
|
||||
"enemyName": "幽灵",
|
||||
"enemyType": 6,
|
||||
"enemyCount": 4,
|
||||
"interval": 3000
|
||||
}
|
||||
@@ -110,17 +110,17 @@
|
||||
"id": 8,
|
||||
"enemySpawnConfigs": [
|
||||
{
|
||||
"enemyName": "近战敌人",
|
||||
"enemyType": 1,
|
||||
"enemyCount": 8,
|
||||
"interval": 3000
|
||||
},
|
||||
{
|
||||
"enemyName": "骷髅巨人",
|
||||
"enemyType": 5,
|
||||
"enemyCount": 2,
|
||||
"interval": 8000
|
||||
},
|
||||
{
|
||||
"enemyName": "火焰法师",
|
||||
"enemyType": 7,
|
||||
"enemyCount": 3,
|
||||
"interval": 5000
|
||||
}
|
||||
@@ -131,17 +131,17 @@
|
||||
"id": 9,
|
||||
"enemySpawnConfigs": [
|
||||
{
|
||||
"enemyName": "骷髅兵",
|
||||
"enemyType": 4,
|
||||
"enemyCount": 8,
|
||||
"interval": 2500
|
||||
},
|
||||
{
|
||||
"enemyName": "骷髅巨人",
|
||||
"enemyType": 5,
|
||||
"enemyCount": 3,
|
||||
"interval": 6000
|
||||
},
|
||||
{
|
||||
"enemyName": "火焰法师",
|
||||
"enemyType": 7,
|
||||
"enemyCount": 4,
|
||||
"interval": 3000
|
||||
}
|
||||
@@ -152,22 +152,22 @@
|
||||
"id": 10,
|
||||
"enemySpawnConfigs": [
|
||||
{
|
||||
"enemyName": "蝙蝠",
|
||||
"enemyType": 3,
|
||||
"enemyCount": 10,
|
||||
"interval": 2000
|
||||
},
|
||||
{
|
||||
"enemyName": "骷髅兵",
|
||||
"enemyType": 4,
|
||||
"enemyCount": 3,
|
||||
"interval": 8000
|
||||
},
|
||||
{
|
||||
"enemyName": "幽灵",
|
||||
"enemyType": 6,
|
||||
"enemyCount": 5,
|
||||
"interval": 3000
|
||||
},
|
||||
{
|
||||
"enemyName": "火焰法师",
|
||||
"enemyType": 7,
|
||||
"enemyCount": 4,
|
||||
"interval": 4000
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
┐ИХ┌▄Х┌┴2┐ЙГ┴≥И╫©2┐КХ└▒2┐ЛИ╪╩Е╜░ 2┐МХ┘©2┐НГ°╪Г²⌡2┐ОХ┌▄Х┌┴─√┐ПГ┴≥И╫©─√┐ЯХ└▒─√┐РИ╪╩Е╜░ ─√┐СХ┘©─√┐ТГ°╪Г²⌡─√┐УХ┌▄Х┌┴│,┐ЖГ┴≥И╫©│,┐ВХ└▒│,┐ЬИ╪╩Е╜░ │,┐ЫХ┘©│,┐ЗГ°╪Г²⌡│,
|
||||
┐ИХ┌▄Х┌┴млL=─хХ┌▄Х┌┴┐ЙГ┴≥И╫©млL=─хГ┴≥И╫©┐КХ└▒ млL=─хХ└▒┐ЛИ╪╩Е╜░млL=─хИ╪╩Е╜░┐МХ┘©млL=─хХ┘©┐НГ°╪Г²⌡млL=─хГ°╪Г²⌡┐ОХ┌▄Х┌┴ ≥>─хХ┌▄Х┌┴┐ПГ┴≥И╫© ≥>─хГ┴≥И╫©┐ЯХ└▒ ≥>─хХ└▒┐РИ╪╩Е╜░ ≥>─хИ╪╩Е╜░┐СХ┘© ≥>─хХ┘©┐ТГ°╪Г²⌡ ≥>─хГ°╪Г²⌡┐УХ┌▄Х┌┴ ≥≥>─хХ┌▄Х┌┴┐ЖГ┴≥И╫© ≥≥>─хГ┴≥И╫©┐ВХ└▒ ≥≥>─хХ└▒┐ЬИ╪╩Е╜░ ≥≥>─хИ╪╩Е╜░┐ЫХ┘© ≥≥>─хХ┘©┐ЗГ°╪Г²⌡ ≥≥>─хГ°╪Г²⌡
|
||||
@@ -3,216 +3,234 @@
|
||||
"id": 1001,
|
||||
"title": "肌肉",
|
||||
"rarity": 1,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 3,
|
||||
"value": 50,
|
||||
"isPercent": true
|
||||
"statType": 4,
|
||||
"value": 0.05,
|
||||
"modifierType": 200
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "肌肉"
|
||||
},
|
||||
{
|
||||
"id": 1002,
|
||||
"title": "牙齿",
|
||||
"rarity": 1,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 3,
|
||||
"value": 50,
|
||||
"isPercent": true
|
||||
"statType": 4,
|
||||
"value": 0.05,
|
||||
"modifierType": 200
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "牙齿"
|
||||
},
|
||||
{
|
||||
"id": 1003,
|
||||
"title": "脑",
|
||||
"rarity": 1,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 6,
|
||||
"value": 50,
|
||||
"isPercent": true
|
||||
"statType": 9,
|
||||
"value": 0.05,
|
||||
"modifierType": 200
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "脑"
|
||||
},
|
||||
{
|
||||
"id": 1004,
|
||||
"title": "鼻子",
|
||||
"rarity": 1,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 9,
|
||||
"value": 50,
|
||||
"isPercent": true
|
||||
"statType": 8,
|
||||
"value": 0.05,
|
||||
"modifierType": 200
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "鼻子"
|
||||
},
|
||||
{
|
||||
"id": 1005,
|
||||
"title": "腿",
|
||||
"rarity": 1,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 2,
|
||||
"value": 50,
|
||||
"isPercent": true
|
||||
"statType": 14,
|
||||
"value": 0.05,
|
||||
"modifierType": 200
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "腿"
|
||||
},
|
||||
{
|
||||
"id": 1006,
|
||||
"title": "眼睛",
|
||||
"rarity": 1,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 1,
|
||||
"value": 50,
|
||||
"isPercent": true
|
||||
"statType": 1,
|
||||
"value": 0.05,
|
||||
"modifierType": 200
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "眼睛"
|
||||
},
|
||||
{
|
||||
"id": 1007,
|
||||
"title": "肌肉",
|
||||
"rarity": 2,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 3,
|
||||
"value": 150,
|
||||
"isPercent": true
|
||||
"statType": 4,
|
||||
"value": 0.15,
|
||||
"modifierType": 200
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "肌肉"
|
||||
},
|
||||
{
|
||||
"id": 1008,
|
||||
"title": "牙齿",
|
||||
"rarity": 2,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 3,
|
||||
"value": 150,
|
||||
"isPercent": true
|
||||
"statType": 4,
|
||||
"value": 0.15,
|
||||
"modifierType": 200
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "牙齿"
|
||||
},
|
||||
{
|
||||
"id": 1009,
|
||||
"title": "脑",
|
||||
"rarity": 2,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 6,
|
||||
"value": 150,
|
||||
"isPercent": true
|
||||
"statType": 9,
|
||||
"value": 0.15,
|
||||
"modifierType": 200
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "脑"
|
||||
},
|
||||
{
|
||||
"id": 1010,
|
||||
"title": "鼻子",
|
||||
"rarity": 2,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 9,
|
||||
"value": 150,
|
||||
"isPercent": true
|
||||
"statType": 8,
|
||||
"value": 0.15,
|
||||
"modifierType": 200
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "鼻子"
|
||||
},
|
||||
{
|
||||
"id": 1011,
|
||||
"title": "腿",
|
||||
"rarity": 2,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 2,
|
||||
"value": 150,
|
||||
"isPercent": true
|
||||
"statType": 14,
|
||||
"value": 0.15,
|
||||
"modifierType": 200
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "腿"
|
||||
},
|
||||
{
|
||||
"id": 1012,
|
||||
"title": "眼睛",
|
||||
"rarity": 2,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 1,
|
||||
"value": 150,
|
||||
"isPercent": true
|
||||
"statType": 1,
|
||||
"value": 0.15,
|
||||
"modifierType": 200
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "眼睛"
|
||||
},
|
||||
{
|
||||
"id": 1013,
|
||||
"title": "肌肉",
|
||||
"rarity": 3,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 3,
|
||||
"value": 300,
|
||||
"isPercent": true
|
||||
"statType": 4,
|
||||
"value": 0.3,
|
||||
"modifierType": 200
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "肌肉"
|
||||
},
|
||||
{
|
||||
"id": 1014,
|
||||
"title": "牙齿",
|
||||
"rarity": 3,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 3,
|
||||
"value": 300,
|
||||
"isPercent": true
|
||||
"statType": 4,
|
||||
"value": 0.3,
|
||||
"modifierType": 200
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "牙齿"
|
||||
},
|
||||
{
|
||||
"id": 1015,
|
||||
"title": "脑",
|
||||
"rarity": 3,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 6,
|
||||
"value": 300,
|
||||
"isPercent": true
|
||||
"statType": 9,
|
||||
"value": 0.3,
|
||||
"modifierType": 200
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "脑"
|
||||
},
|
||||
{
|
||||
"id": 1016,
|
||||
"title": "鼻子",
|
||||
"rarity": 3,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 9,
|
||||
"value": 300,
|
||||
"isPercent": true
|
||||
"statType": 8,
|
||||
"value": 0.3,
|
||||
"modifierType": 200
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "鼻子"
|
||||
},
|
||||
{
|
||||
"id": 1017,
|
||||
"title": "腿",
|
||||
"rarity": 3,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 2,
|
||||
"value": 300,
|
||||
"isPercent": true
|
||||
"statType": 14,
|
||||
"value": 0.3,
|
||||
"modifierType": 200
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "腿"
|
||||
},
|
||||
{
|
||||
"id": 1018,
|
||||
"title": "眼睛",
|
||||
"rarity": 3,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 1,
|
||||
"value": 300,
|
||||
"isPercent": true
|
||||
"statType": 1,
|
||||
"value": 0.3,
|
||||
"modifierType": 200
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "眼睛"
|
||||
}
|
||||
]
|
||||
Binary file not shown.
@@ -4,369 +4,389 @@
|
||||
"name": "铁护腕",
|
||||
"rarity": 1,
|
||||
"price": 120,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 3,
|
||||
"statType": 5,
|
||||
"value": 10,
|
||||
"isPercent": false
|
||||
"modifierType": 100
|
||||
},
|
||||
{
|
||||
"key": 4,
|
||||
"statType": 12,
|
||||
"value": 12,
|
||||
"isPercent": false
|
||||
"modifierType": 100
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "铁护腕"
|
||||
},
|
||||
{
|
||||
"id": 1002,
|
||||
"name": "狂战士药剂",
|
||||
"rarity": 2,
|
||||
"price": 250,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 1,
|
||||
"statType": 1,
|
||||
"value": 53,
|
||||
"isPercent": false
|
||||
"modifierType": 100
|
||||
},
|
||||
{
|
||||
"key": 5,
|
||||
"value": 90,
|
||||
"isPercent": true
|
||||
"statType": 8,
|
||||
"value": 0.09,
|
||||
"modifierType": 200
|
||||
},
|
||||
{
|
||||
"key": 3,
|
||||
"statType": 5,
|
||||
"value": 11,
|
||||
"isPercent": false
|
||||
"modifierType": 100
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "狂战士药剂"
|
||||
},
|
||||
{
|
||||
"id": 1003,
|
||||
"name": "龙鳞护符",
|
||||
"rarity": 3,
|
||||
"price": 330,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 6,
|
||||
"statType": 9,
|
||||
"value": 15,
|
||||
"isPercent": false
|
||||
"modifierType": 100
|
||||
},
|
||||
{
|
||||
"key": 7,
|
||||
"statType": 5,
|
||||
"value": 21,
|
||||
"isPercent": false
|
||||
"modifierType": 100
|
||||
},
|
||||
{
|
||||
"key": 4,
|
||||
"statType": 12,
|
||||
"value": 23,
|
||||
"isPercent": false
|
||||
"modifierType": 100
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "龙鳞护符"
|
||||
},
|
||||
{
|
||||
"id": 1004,
|
||||
"name": "泰坦壁垒",
|
||||
"rarity": 5,
|
||||
"price": 423,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 4,
|
||||
"statType": 12,
|
||||
"value": 79,
|
||||
"isPercent": false
|
||||
"modifierType": 100
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "泰坦壁垒"
|
||||
},
|
||||
{
|
||||
"id": 1005,
|
||||
"name": "轻便短靴",
|
||||
"rarity": 1,
|
||||
"price": 120,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 2,
|
||||
"value": 800,
|
||||
"isPercent": false
|
||||
"statType": 14,
|
||||
"value": 0.8,
|
||||
"modifierType": 100
|
||||
},
|
||||
{
|
||||
"key": 3,
|
||||
"statType": 5,
|
||||
"value": 10,
|
||||
"isPercent": false
|
||||
"modifierType": 100
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "轻便短靴"
|
||||
},
|
||||
{
|
||||
"id": 1006,
|
||||
"name": "幽灵披风",
|
||||
"rarity": 2,
|
||||
"price": 195,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 8,
|
||||
"value": 10,
|
||||
"isPercent": false
|
||||
"statType": 13,
|
||||
"value": 0.1,
|
||||
"modifierType": 100
|
||||
},
|
||||
{
|
||||
"key": 3,
|
||||
"statType": 5,
|
||||
"value": 12,
|
||||
"isPercent": false
|
||||
"modifierType": 100
|
||||
},
|
||||
{
|
||||
"key": 1,
|
||||
"statType": 1,
|
||||
"value": 44,
|
||||
"isPercent": false
|
||||
"modifierType": 100
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "幽灵披风"
|
||||
},
|
||||
{
|
||||
"id": 1007,
|
||||
"name": "精钢胸甲",
|
||||
"rarity": 3,
|
||||
"price": 335,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 4,
|
||||
"statType": 12,
|
||||
"value": 62,
|
||||
"isPercent": false
|
||||
"modifierType": 100
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "精钢胸甲"
|
||||
},
|
||||
{
|
||||
"id": 1008,
|
||||
"name": "暗影之刃",
|
||||
"rarity": 5,
|
||||
"price": 433,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 3,
|
||||
"statType": 6,
|
||||
"value": 44,
|
||||
"isPercent": false
|
||||
"modifierType": 100
|
||||
},
|
||||
{
|
||||
"key": 8,
|
||||
"value": 27,
|
||||
"isPercent": false
|
||||
"statType": 13,
|
||||
"value": 0.27,
|
||||
"modifierType": 100
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "暗影之刃"
|
||||
},
|
||||
{
|
||||
"id": 1009,
|
||||
"name": "旅行者徽章",
|
||||
"rarity": 1,
|
||||
"price": 121,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 1,
|
||||
"statType": 1,
|
||||
"value": 32,
|
||||
"isPercent": false
|
||||
"modifierType": 100
|
||||
},
|
||||
{
|
||||
"key": 3,
|
||||
"statType": 6,
|
||||
"value": 7,
|
||||
"isPercent": false
|
||||
"modifierType": 100
|
||||
},
|
||||
{
|
||||
"key": 4,
|
||||
"statType": 12,
|
||||
"value": 8,
|
||||
"isPercent": false
|
||||
"modifierType": 100
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "旅行者徽章"
|
||||
},
|
||||
{
|
||||
"id": 1010,
|
||||
"name": "疾风手套",
|
||||
"rarity": 2,
|
||||
"price": 198,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 5,
|
||||
"value": 190,
|
||||
"isPercent": true
|
||||
"statType": 8,
|
||||
"value": 0.19,
|
||||
"modifierType": 200
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "疾风手套"
|
||||
},
|
||||
{
|
||||
"id": 1011,
|
||||
"name": "巨人之力卷轴",
|
||||
"rarity": 3,
|
||||
"price": 341,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 3,
|
||||
"statType": 6,
|
||||
"value": 57,
|
||||
"isPercent": false
|
||||
"modifierType": 100
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "巨人之力卷轴"
|
||||
},
|
||||
{
|
||||
"id": 1012,
|
||||
"name": "不死鸟之心",
|
||||
"rarity": 5,
|
||||
"price": 443,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 1,
|
||||
"statType": 1,
|
||||
"value": 139,
|
||||
"isPercent": false
|
||||
"modifierType": 100
|
||||
},
|
||||
{
|
||||
"key": 6,
|
||||
"value": 27,
|
||||
"isPercent": false
|
||||
"statType": 9,
|
||||
"value": 0.27,
|
||||
"modifierType": 100
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "不死鸟之心"
|
||||
},
|
||||
{
|
||||
"id": 1013,
|
||||
"name": "幸运草",
|
||||
"rarity": 1,
|
||||
"price": 122,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 6,
|
||||
"value": 5,
|
||||
"isPercent": false
|
||||
"statType": 9,
|
||||
"value": 0.05,
|
||||
"modifierType": 100
|
||||
},
|
||||
{
|
||||
"key": 8,
|
||||
"value": 7,
|
||||
"isPercent": false
|
||||
"statType": 13,
|
||||
"value": 0.07,
|
||||
"modifierType": 100
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "幸运草"
|
||||
},
|
||||
{
|
||||
"id": 1014,
|
||||
"name": "石肤戒指",
|
||||
"rarity": 2,
|
||||
"price": 201,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 2,
|
||||
"value": 600,
|
||||
"isPercent": false
|
||||
"statType": 14,
|
||||
"value": 0.6,
|
||||
"modifierType": 100
|
||||
},
|
||||
{
|
||||
"key": 4,
|
||||
"statType": 12,
|
||||
"value": 38,
|
||||
"isPercent": false
|
||||
"modifierType": 100
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "石肤戒指"
|
||||
},
|
||||
{
|
||||
"id": 1015,
|
||||
"name": "风行者胫甲",
|
||||
"rarity": 3,
|
||||
"price": 346,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 2,
|
||||
"value": 1600,
|
||||
"isPercent": false
|
||||
"statType": 14,
|
||||
"value": 1.6,
|
||||
"modifierType": 100
|
||||
},
|
||||
{
|
||||
"key": 4,
|
||||
"statType": 12,
|
||||
"value": 32,
|
||||
"isPercent": false
|
||||
"modifierType": 100
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "风行者胫甲"
|
||||
},
|
||||
{
|
||||
"id": 1016,
|
||||
"name": "幻影斗篷",
|
||||
"rarity": 5,
|
||||
"price": 454,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 8,
|
||||
"value": 28,
|
||||
"isPercent": false
|
||||
"statType": 13,
|
||||
"value": 0.28,
|
||||
"modifierType": 100
|
||||
},
|
||||
{
|
||||
"key": 4,
|
||||
"statType": 12,
|
||||
"value": 24,
|
||||
"isPercent": false
|
||||
"modifierType": 100
|
||||
},
|
||||
{
|
||||
"key": 3,
|
||||
"statType": 5,
|
||||
"value": 24,
|
||||
"isPercent": false
|
||||
"modifierType": 100
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "幻影斗篷"
|
||||
},
|
||||
{
|
||||
"id": 1017,
|
||||
"name": "木质盾牌",
|
||||
"rarity": 1,
|
||||
"price": 124,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 4,
|
||||
"statType": 12,
|
||||
"value": 23,
|
||||
"isPercent": false
|
||||
"modifierType": 100
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "木质盾牌"
|
||||
},
|
||||
{
|
||||
"id": 1018,
|
||||
"name": "生命之戒",
|
||||
"rarity": 2,
|
||||
"price": 204,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 3,
|
||||
"statType": 7,
|
||||
"value": 17,
|
||||
"isPercent": false
|
||||
"modifierType": 100
|
||||
},
|
||||
{
|
||||
"key": 1,
|
||||
"statType": 1,
|
||||
"value": 69,
|
||||
"isPercent": false
|
||||
"modifierType": 100
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "生命之戒"
|
||||
},
|
||||
{
|
||||
"id": 1019,
|
||||
"name": "精灵耳环",
|
||||
"rarity": 3,
|
||||
"price": 352,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 1,
|
||||
"statType": 1,
|
||||
"value": 74,
|
||||
"isPercent": false
|
||||
"modifierType": 100
|
||||
},
|
||||
{
|
||||
"key": 3,
|
||||
"statType": 7,
|
||||
"value": 19,
|
||||
"isPercent": false
|
||||
"modifierType": 100
|
||||
},
|
||||
{
|
||||
"key": 8,
|
||||
"value": 20,
|
||||
"isPercent": false
|
||||
"statType": 13,
|
||||
"value": 0.2,
|
||||
"modifierType": 100
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "精灵耳环"
|
||||
},
|
||||
{
|
||||
"id": 1020,
|
||||
"name": "战神勋章",
|
||||
"rarity": 5,
|
||||
"price": 464,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 5,
|
||||
"value": 150,
|
||||
"isPercent": true
|
||||
"statType": 8,
|
||||
"value": 0.15,
|
||||
"modifierType": 200
|
||||
},
|
||||
{
|
||||
"key": 3,
|
||||
"statType": 7,
|
||||
"value": 29,
|
||||
"isPercent": false
|
||||
"modifierType": 100
|
||||
},
|
||||
{
|
||||
"key": 4,
|
||||
"statType": 12,
|
||||
"value": 27,
|
||||
"isPercent": false
|
||||
"modifierType": 100
|
||||
}
|
||||
]
|
||||
],
|
||||
"sprite": "战神勋章"
|
||||
}
|
||||
]
|
||||
Binary file not shown.
@@ -4,28 +4,30 @@
|
||||
"maxHealth": 100,
|
||||
"speed": 6,
|
||||
"coin": 10,
|
||||
"modifiers": [
|
||||
"statModifierConfigs": [
|
||||
{
|
||||
"key": 2,
|
||||
"value": 500,
|
||||
"isPercent": true
|
||||
"statType": 14,
|
||||
"value": 0.5,
|
||||
"modifierType": 200
|
||||
},
|
||||
{
|
||||
"key": 1,
|
||||
"value": 200,
|
||||
"isPercent": true
|
||||
"statType": 1,
|
||||
"value": 0.2,
|
||||
"modifierType": 200
|
||||
}
|
||||
],
|
||||
"initialItems": [],
|
||||
"prefab": "Player"
|
||||
"prefab": "Player",
|
||||
"sprite": "全能者"
|
||||
},
|
||||
{
|
||||
"name": "老人",
|
||||
"maxHealth": 200,
|
||||
"speed": 4,
|
||||
"coin": 5,
|
||||
"modifiers": [],
|
||||
"statModifierConfigs": [],
|
||||
"initialItems": [],
|
||||
"prefab": "Player"
|
||||
"prefab": "Player",
|
||||
"sprite": "老人"
|
||||
}
|
||||
]
|
||||
Binary file not shown.
@@ -1 +1,167 @@
|
||||
[]
|
||||
[
|
||||
{
|
||||
"key": "小刀",
|
||||
"atlasPath": "Weapon.png",
|
||||
"spriteIndex": 0
|
||||
},
|
||||
{
|
||||
"key": "手枪",
|
||||
"atlasPath": "Weapon.png",
|
||||
"spriteIndex": 1
|
||||
},
|
||||
{
|
||||
"key": "斧头",
|
||||
"atlasPath": "Weapon.png",
|
||||
"spriteIndex": 2
|
||||
},
|
||||
{
|
||||
"key": "闪电",
|
||||
"atlasPath": "Weapon.png",
|
||||
"spriteIndex": 3
|
||||
},
|
||||
{
|
||||
"key": "长枪",
|
||||
"atlasPath": "Weapon.png",
|
||||
"spriteIndex": 4
|
||||
},
|
||||
{
|
||||
"key": "铁护腕",
|
||||
"atlasPath": "Prop.png",
|
||||
"spriteIndex": 0
|
||||
},
|
||||
{
|
||||
"key": "狂战士药剂",
|
||||
"atlasPath": "Prop.png",
|
||||
"spriteIndex": 1
|
||||
},
|
||||
{
|
||||
"key": "龙鳞护符",
|
||||
"atlasPath": "Prop.png",
|
||||
"spriteIndex": 2
|
||||
},
|
||||
{
|
||||
"key": "泰坦壁垒",
|
||||
"atlasPath": "Prop.png",
|
||||
"spriteIndex": 3
|
||||
},
|
||||
{
|
||||
"key": "轻便短靴",
|
||||
"atlasPath": "Prop.png",
|
||||
"spriteIndex": 4
|
||||
},
|
||||
{
|
||||
"key": "幽灵披风",
|
||||
"atlasPath": "Prop.png",
|
||||
"spriteIndex": 5
|
||||
},
|
||||
{
|
||||
"key": "精钢胸甲",
|
||||
"atlasPath": "Prop.png",
|
||||
"spriteIndex": 6
|
||||
},
|
||||
{
|
||||
"key": "暗影之刃",
|
||||
"atlasPath": "Prop.png",
|
||||
"spriteIndex": 7
|
||||
},
|
||||
{
|
||||
"key": "旅行者徽章",
|
||||
"atlasPath": "Prop.png",
|
||||
"spriteIndex": 8
|
||||
},
|
||||
{
|
||||
"key": "疾风手套",
|
||||
"atlasPath": "Prop.png",
|
||||
"spriteIndex": 9
|
||||
},
|
||||
{
|
||||
"key": "巨人之力卷轴",
|
||||
"atlasPath": "Prop.png",
|
||||
"spriteIndex": 10
|
||||
},
|
||||
{
|
||||
"key": "不死鸟之心",
|
||||
"atlasPath": "Prop.png",
|
||||
"spriteIndex": 11
|
||||
},
|
||||
{
|
||||
"key": "幸运草",
|
||||
"atlasPath": "Prop.png",
|
||||
"spriteIndex": 12
|
||||
},
|
||||
{
|
||||
"key": "石肤戒指",
|
||||
"atlasPath": "Prop.png",
|
||||
"spriteIndex": 13
|
||||
},
|
||||
{
|
||||
"key": "风行者胫甲",
|
||||
"atlasPath": "Prop.png",
|
||||
"spriteIndex": 14
|
||||
},
|
||||
{
|
||||
"key": "幻影斗篷",
|
||||
"atlasPath": "Prop.png",
|
||||
"spriteIndex": 15
|
||||
},
|
||||
{
|
||||
"key": "木质盾牌",
|
||||
"atlasPath": "Prop.png",
|
||||
"spriteIndex": 16
|
||||
},
|
||||
{
|
||||
"key": "生命之戒",
|
||||
"atlasPath": "Prop.png",
|
||||
"spriteIndex": 17
|
||||
},
|
||||
{
|
||||
"key": "精灵耳环",
|
||||
"atlasPath": "Prop.png",
|
||||
"spriteIndex": 18
|
||||
},
|
||||
{
|
||||
"key": "战神勋章",
|
||||
"atlasPath": "Prop.png",
|
||||
"spriteIndex": 19
|
||||
},
|
||||
{
|
||||
"key": "全能者",
|
||||
"atlasPath": "Role.png",
|
||||
"spriteIndex": 0
|
||||
},
|
||||
{
|
||||
"key": "老人",
|
||||
"atlasPath": "Role.png",
|
||||
"spriteIndex": 1
|
||||
},
|
||||
{
|
||||
"key": "肌肉",
|
||||
"atlasPath": "LevelUpReward.png",
|
||||
"spriteIndex": 0
|
||||
},
|
||||
{
|
||||
"key": "牙齿",
|
||||
"atlasPath": "LevelUpReward.png",
|
||||
"spriteIndex": 1
|
||||
},
|
||||
{
|
||||
"key": "脑",
|
||||
"atlasPath": "LevelUpReward.png",
|
||||
"spriteIndex": 2
|
||||
},
|
||||
{
|
||||
"key": "鼻子",
|
||||
"atlasPath": "LevelUpReward.png",
|
||||
"spriteIndex": 3
|
||||
},
|
||||
{
|
||||
"key": "腿",
|
||||
"atlasPath": "LevelUpReward.png",
|
||||
"spriteIndex": 4
|
||||
},
|
||||
{
|
||||
"key": "眼睛",
|
||||
"atlasPath": "LevelUpReward.png",
|
||||
"spriteIndex": 5
|
||||
}
|
||||
]
|
||||
Binary file not shown.
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0ee410edd089fef4d91515cb4a75589d
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,162 @@
|
||||
[
|
||||
{
|
||||
"statType": 1,
|
||||
"name": "最大生命",
|
||||
"defaultBaseValue": 100,
|
||||
"hasMin": true,
|
||||
"minValue": 1,
|
||||
"hasMax": false,
|
||||
"maxValue": 0,
|
||||
"isPercentDisplay": false
|
||||
},
|
||||
{
|
||||
"statType": 2,
|
||||
"name": "生命恢复",
|
||||
"defaultBaseValue": 5,
|
||||
"hasMin": true,
|
||||
"minValue": 0,
|
||||
"hasMax": false,
|
||||
"maxValue": 0,
|
||||
"isPercentDisplay": false
|
||||
},
|
||||
{
|
||||
"statType": 3,
|
||||
"name": "生命窃取",
|
||||
"defaultBaseValue": 0,
|
||||
"hasMin": true,
|
||||
"minValue": 0,
|
||||
"hasMax": false,
|
||||
"maxValue": 0,
|
||||
"isPercentDisplay": false
|
||||
},
|
||||
{
|
||||
"statType": 4,
|
||||
"name": "伤害",
|
||||
"defaultBaseValue": 1,
|
||||
"hasMin": true,
|
||||
"minValue": -1,
|
||||
"hasMax": false,
|
||||
"maxValue": 0,
|
||||
"isPercentDisplay": true
|
||||
},
|
||||
{
|
||||
"statType": 5,
|
||||
"name": "近战伤害",
|
||||
"defaultBaseValue": 0,
|
||||
"hasMin": false,
|
||||
"minValue": 0,
|
||||
"hasMax": false,
|
||||
"maxValue": 0,
|
||||
"isPercentDisplay": false
|
||||
},
|
||||
{
|
||||
"statType": 6,
|
||||
"name": "远程伤害",
|
||||
"defaultBaseValue": 0,
|
||||
"hasMin": false,
|
||||
"minValue": 0,
|
||||
"hasMax": false,
|
||||
"maxValue": 0,
|
||||
"isPercentDisplay": false
|
||||
},
|
||||
{
|
||||
"statType": 7,
|
||||
"name": "元素伤害",
|
||||
"defaultBaseValue": 0,
|
||||
"hasMin": false,
|
||||
"minValue": 0,
|
||||
"hasMax": false,
|
||||
"maxValue": 0,
|
||||
"isPercentDisplay": false
|
||||
},
|
||||
{
|
||||
"statType": 8,
|
||||
"name": "攻击速度",
|
||||
"defaultBaseValue": 1,
|
||||
"hasMin": true,
|
||||
"minValue": -0.8,
|
||||
"hasMax": false,
|
||||
"maxValue": 0,
|
||||
"isPercentDisplay": true
|
||||
},
|
||||
{
|
||||
"statType": 9,
|
||||
"name": "暴击率",
|
||||
"defaultBaseValue": 0,
|
||||
"hasMin": true,
|
||||
"minValue": 0,
|
||||
"hasMax": true,
|
||||
"maxValue": 0.9,
|
||||
"isPercentDisplay": true
|
||||
},
|
||||
{
|
||||
"statType": 10,
|
||||
"name": "工程学",
|
||||
"defaultBaseValue": 0,
|
||||
"hasMin": true,
|
||||
"minValue": 0,
|
||||
"hasMax": false,
|
||||
"maxValue": 0,
|
||||
"isPercentDisplay": false
|
||||
},
|
||||
{
|
||||
"statType": 11,
|
||||
"name": "攻击范围",
|
||||
"defaultBaseValue": 0,
|
||||
"hasMin": true,
|
||||
"minValue": 0,
|
||||
"hasMax": false,
|
||||
"maxValue": 0,
|
||||
"isPercentDisplay": false
|
||||
},
|
||||
{
|
||||
"statType": 12,
|
||||
"name": "护甲",
|
||||
"defaultBaseValue": 0,
|
||||
"hasMin": false,
|
||||
"minValue": 0,
|
||||
"hasMax": false,
|
||||
"maxValue": 0,
|
||||
"isPercentDisplay": false
|
||||
},
|
||||
{
|
||||
"statType": 13,
|
||||
"name": "闪避率",
|
||||
"defaultBaseValue": 0,
|
||||
"hasMin": true,
|
||||
"minValue": 0,
|
||||
"hasMax": true,
|
||||
"maxValue": 0.8,
|
||||
"isPercentDisplay": true
|
||||
},
|
||||
{
|
||||
"statType": 14,
|
||||
"name": "移动速度",
|
||||
"defaultBaseValue": 0,
|
||||
"hasMin": true,
|
||||
"minValue": 0.5,
|
||||
"hasMax": false,
|
||||
"maxValue": 0,
|
||||
"isPercentDisplay": false
|
||||
},
|
||||
{
|
||||
"statType": 15,
|
||||
"name": "收获",
|
||||
"defaultBaseValue": 0,
|
||||
"hasMin": true,
|
||||
"minValue": 0,
|
||||
"hasMax": false,
|
||||
"maxValue": 0,
|
||||
"isPercentDisplay": false
|
||||
},
|
||||
{
|
||||
"statType": 16,
|
||||
"name": "幸运",
|
||||
"defaultBaseValue": 0,
|
||||
"hasMin": true,
|
||||
"minValue": 0,
|
||||
"hasMax": false,
|
||||
"maxValue": 0,
|
||||
"isPercentDisplay": false
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b66a5cb55d1374a45b0f74f7baba5283
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
@@ -1,43 +1,48 @@
|
||||
[
|
||||
{
|
||||
"id": 1001,
|
||||
"name": "小刀",
|
||||
"weaponType": 1,
|
||||
"logicType": "WeaponKnife",
|
||||
"rarity": 1,
|
||||
"price": 120,
|
||||
"attack": 100,
|
||||
"cooldown": 1500,
|
||||
"attackRange": 5000,
|
||||
"cooldown": 1.5,
|
||||
"damageType": 1,
|
||||
"attackRange": 5,
|
||||
"attackSoundId": 10000,
|
||||
"parameters": [
|
||||
[
|
||||
1,
|
||||
2000
|
||||
2
|
||||
]
|
||||
],
|
||||
"modifiers": [],
|
||||
"prefab": "WeaponKnife"
|
||||
"statModifierConfigs": [],
|
||||
"prefab": "WeaponKnife",
|
||||
"sprite": "小刀"
|
||||
},
|
||||
{
|
||||
"id": 1002,
|
||||
"name": "手枪",
|
||||
"weaponType": 2,
|
||||
"logicType": "WeaponHandgun",
|
||||
"rarity": 1,
|
||||
"price": 130,
|
||||
"attack": 120,
|
||||
"cooldown": 1000,
|
||||
"attackRange": 15000,
|
||||
"cooldown": 1,
|
||||
"damageType": 2,
|
||||
"attackRange": 15,
|
||||
"attackSoundId": 10000,
|
||||
"parameters": [],
|
||||
"modifiers": [],
|
||||
"prefab": "WeaponHandgun"
|
||||
"statModifierConfigs": [],
|
||||
"prefab": "WeaponHandgun",
|
||||
"sprite": "手枪"
|
||||
},
|
||||
{
|
||||
"id": 1003,
|
||||
"name": "斧头",
|
||||
"weaponType": 3,
|
||||
"logicType": "WeaponSlash",
|
||||
"rarity": 1,
|
||||
"price": 100,
|
||||
"attack": 150,
|
||||
"cooldown": 2000,
|
||||
"attackRange": 5000,
|
||||
"cooldown": 2,
|
||||
"damageType": 1,
|
||||
"attackRange": 5,
|
||||
"attackSoundId": 10000,
|
||||
"parameters": [
|
||||
[
|
||||
@@ -45,51 +50,56 @@
|
||||
120
|
||||
]
|
||||
],
|
||||
"modifiers": [],
|
||||
"prefab": "WeaponSlash"
|
||||
"statModifierConfigs": [],
|
||||
"prefab": "WeaponSlash",
|
||||
"sprite": "斧头"
|
||||
},
|
||||
{
|
||||
"id": 1004,
|
||||
"name": "闪电",
|
||||
"weaponType": 4,
|
||||
"logicType": "WeaponLightning",
|
||||
"rarity": 1,
|
||||
"price": 150,
|
||||
"attack": 80,
|
||||
"cooldown": 3000,
|
||||
"attackRange": 12000,
|
||||
"cooldown": 3,
|
||||
"damageType": 4,
|
||||
"attackRange": 12,
|
||||
"attackSoundId": 10000,
|
||||
"parameters": [
|
||||
[
|
||||
1,
|
||||
3000
|
||||
3
|
||||
]
|
||||
],
|
||||
"modifiers": [],
|
||||
"prefab": "WeaponLightning"
|
||||
"statModifierConfigs": [],
|
||||
"prefab": "WeaponLightning",
|
||||
"sprite": "闪电"
|
||||
},
|
||||
{
|
||||
"id": 1005,
|
||||
"name": "长枪",
|
||||
"weaponType": 5,
|
||||
"logicType": "WeaponLance",
|
||||
"rarity": 1,
|
||||
"price": 100,
|
||||
"attack": 100,
|
||||
"cooldown": 1500,
|
||||
"attackRange": 5000,
|
||||
"cooldown": 1.5,
|
||||
"damageType": 1,
|
||||
"attackRange": 5,
|
||||
"attackSoundId": 10000,
|
||||
"parameters": [
|
||||
[
|
||||
3,
|
||||
700
|
||||
0.7
|
||||
],
|
||||
[
|
||||
4,
|
||||
4500
|
||||
4.5
|
||||
],
|
||||
[
|
||||
5,
|
||||
500
|
||||
0.5
|
||||
]
|
||||
],
|
||||
"modifiers": [],
|
||||
"prefab": "WeaponLance"
|
||||
"statModifierConfigs": [],
|
||||
"prefab": "WeaponLance",
|
||||
"sprite": "长枪"
|
||||
}
|
||||
]
|
||||
@@ -1,582 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using SepCore.Event;
|
||||
using SepCore.Definition;
|
||||
using SepCore.Entity;
|
||||
using SepCore.Components;
|
||||
using SepCore.CustomUtility;
|
||||
using SepCore.Simulation;
|
||||
using SepCore.EnemyManager;
|
||||
using SepCore.Procedure;
|
||||
using UnityEngine;
|
||||
using UnityGameFramework.Runtime;
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
using UnityEngine.InputSystem;
|
||||
#endif
|
||||
|
||||
|
||||
public class RuntimeDebugPanelComponent : MonoBehaviour
|
||||
|
||||
{
|
||||
private const float MinSpawnRate = 0.1f;
|
||||
private const float CornerTapWindow = 0.6f;
|
||||
private const int RequiredCornerTapCount = 3;
|
||||
private const int DebugHealAmount = 200;
|
||||
|
||||
[Header("Window Content")] [SerializeField]
|
||||
private bool _showBuffSection = true;
|
||||
|
||||
[SerializeField] private bool _showBattleOverview = true;
|
||||
[SerializeField] private bool _showCollisionStats = true;
|
||||
[SerializeField] private bool _showSpawnControls = true;
|
||||
[SerializeField] private bool _showBattleDurationControls = true;
|
||||
[SerializeField] private bool _showPlayerWeaponControls = true;
|
||||
[SerializeField] private bool _showPlayerHealthControls = true;
|
||||
[SerializeField] private bool _showTips = true;
|
||||
|
||||
private Rect _windowRect;
|
||||
private Vector2 _panelScroll;
|
||||
private GUISkin _panelSkin;
|
||||
private bool _isPanelVisible;
|
||||
private int _windowId;
|
||||
|
||||
private string _searchText = string.Empty;
|
||||
private int _selectedIndex;
|
||||
private int _addCount = 1;
|
||||
private Vector2 _buffScroll;
|
||||
|
||||
private float _spawnRateScaleInput = 1f;
|
||||
private float _extendDurationSeconds = 30f;
|
||||
|
||||
private PropConfig[] _allProps = Array.Empty<PropConfig>();
|
||||
private PropConfig[] _filteredProps = Array.Empty<PropConfig>();
|
||||
private string[] _displayNames = Array.Empty<string>();
|
||||
|
||||
private int _cornerTapCount;
|
||||
private float _lastCornerTapTime = -10f;
|
||||
private bool _lockPlayerHealthToMax;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_windowId = GetInstanceID();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (IsTogglePressed())
|
||||
{
|
||||
_isPanelVisible = !_isPanelVisible;
|
||||
}
|
||||
|
||||
HandleCornerTapGesture();
|
||||
if (_lockPlayerHealthToMax)
|
||||
{
|
||||
KeepPlayerHealthAtMax();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
GUISkin previousSkin = GUI.skin;
|
||||
Matrix4x4 previousMatrix = GUI.matrix;
|
||||
if (_panelSkin == null)
|
||||
{
|
||||
_panelSkin = Instantiate(previousSkin);
|
||||
_panelSkin.label.fontSize = 18;
|
||||
_panelSkin.label.wordWrap = true;
|
||||
_panelSkin.button.fontSize = 18;
|
||||
_panelSkin.button.padding = new RectOffset(12, 12, 10, 10);
|
||||
_panelSkin.button.fixedHeight = 44f;
|
||||
_panelSkin.textField.fontSize = 20;
|
||||
_panelSkin.textField.fixedHeight = 44f;
|
||||
_panelSkin.textField.padding = new RectOffset(10, 10, 10, 10);
|
||||
_panelSkin.window.padding = new RectOffset(16, 16, 12, 16);
|
||||
_panelSkin.verticalScrollbar.fixedWidth = 28f;
|
||||
_panelSkin.verticalScrollbarThumb.fixedWidth = 28f;
|
||||
}
|
||||
|
||||
Rect safeArea = Screen.safeArea;
|
||||
float scale = Mathf.Max(0.1f, Mathf.Min(safeArea.width, safeArea.height) / 480f);
|
||||
Rect bounds = new Rect(0f, 0f, safeArea.width / scale, safeArea.height / scale);
|
||||
try
|
||||
{
|
||||
GUI.skin = _panelSkin;
|
||||
GUI.matrix = Matrix4x4.TRS(
|
||||
new Vector3(safeArea.x, Screen.height - safeArea.yMax, 0f),
|
||||
Quaternion.identity, new Vector3(scale, scale, 1f));
|
||||
DrawToggleButton(bounds);
|
||||
if (!_isPanelVisible) return;
|
||||
|
||||
float width = Mathf.Min(460f, bounds.width - 24f);
|
||||
_windowRect = new Rect(bounds.width - width - 12f, 72f, width,
|
||||
Mathf.Min(760f, bounds.height - 84f));
|
||||
GUI.Window(_windowId, _windowRect, DrawWindow, string.Empty);
|
||||
}
|
||||
finally
|
||||
{
|
||||
GUI.matrix = previousMatrix;
|
||||
GUI.skin = previousSkin;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (_panelSkin != null) Destroy(_panelSkin);
|
||||
}
|
||||
|
||||
private void DrawToggleButton(Rect bounds)
|
||||
{
|
||||
const float width = 120f;
|
||||
const float height = 48f;
|
||||
Rect buttonRect = new Rect(bounds.width - width - 12f, 12f, width, height);
|
||||
if (GUI.Button(buttonRect, "DEBUG"))
|
||||
{
|
||||
_isPanelVisible = !_isPanelVisible;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawWindow(int windowId)
|
||||
{
|
||||
if (_showBuffSection)
|
||||
{
|
||||
EnsurePropList();
|
||||
}
|
||||
|
||||
GUILayout.BeginVertical();
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.Label("Runtime Debug", GUILayout.ExpandWidth(true));
|
||||
if (GUILayout.Button("Close", GUILayout.Width(90f))) _isPanelVisible = false;
|
||||
GUILayout.EndHorizontal();
|
||||
GUILayout.Space(8f);
|
||||
_panelScroll = GUILayout.BeginScrollView(_panelScroll, false, true);
|
||||
|
||||
bool hasPreviousSection = false;
|
||||
if (_showBuffSection)
|
||||
{
|
||||
DrawBuffSection();
|
||||
hasPreviousSection = true;
|
||||
}
|
||||
|
||||
if (HasVisibleBattleSection())
|
||||
{
|
||||
if (hasPreviousSection)
|
||||
{
|
||||
GUILayout.Space(8f);
|
||||
GUILayout.Label(string.Empty, GUI.skin.horizontalSlider);
|
||||
GUILayout.Space(8f);
|
||||
}
|
||||
|
||||
DrawBattleSection();
|
||||
hasPreviousSection = true;
|
||||
}
|
||||
|
||||
if (_showTips)
|
||||
{
|
||||
if (hasPreviousSection)
|
||||
{
|
||||
GUILayout.Space(8f);
|
||||
}
|
||||
|
||||
GUILayout.Label("Tips: press F8 or tap top-left corner 3 times to toggle.");
|
||||
}
|
||||
|
||||
GUILayout.EndScrollView();
|
||||
GUILayout.EndVertical();
|
||||
}
|
||||
|
||||
private void DrawBuffSection()
|
||||
{
|
||||
GUILayout.Label("Buff Debug");
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.Label("Search", GUILayout.Width(78f));
|
||||
_searchText = GUILayout.TextField(_searchText);
|
||||
if (GUILayout.Button("Refresh", GUILayout.Width(100f)))
|
||||
{
|
||||
EnsurePropList(true);
|
||||
}
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
ApplyFilter(_searchText);
|
||||
if (_displayNames.Length == 0)
|
||||
{
|
||||
GUILayout.Label("No Buff data. Enter battle and try again.");
|
||||
return;
|
||||
}
|
||||
|
||||
_selectedIndex = Mathf.Clamp(_selectedIndex, 0, _displayNames.Length - 1);
|
||||
_buffScroll = GUILayout.BeginScrollView(_buffScroll, GUILayout.Height(120f));
|
||||
_selectedIndex = GUILayout.SelectionGrid(_selectedIndex, _displayNames, 1);
|
||||
GUILayout.EndScrollView();
|
||||
|
||||
PropConfig selectedProp = GetSelectedProp();
|
||||
if (selectedProp == null) return;
|
||||
|
||||
GUILayout.Label($"Selected: {selectedProp.Title} ({selectedProp.Rarity})");
|
||||
GUILayout.Label(ItemDescUtility.CreatePropDescription(selectedProp.Modifiers), GUILayout.Height(40f));
|
||||
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.Label("Count", GUILayout.Width(78f));
|
||||
string addCountText = GUILayout.TextField(_addCount.ToString(), GUILayout.Width(88f));
|
||||
if (!int.TryParse(addCountText, out _addCount)) _addCount = 1;
|
||||
_addCount = Mathf.Clamp(_addCount, 1, 99);
|
||||
|
||||
if (GUILayout.Button("Add Buff To Player", GUILayout.Height(44f)))
|
||||
{
|
||||
AddSelectedBuffToPlayer(selectedProp, _addCount);
|
||||
}
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
private void DrawBattleSection()
|
||||
{
|
||||
GUILayout.Label("Battle Debug");
|
||||
ProcedureGame procedure = GameEntry.Procedure.CurrentProcedure as ProcedureGame;
|
||||
EnemyManagerComponent enemyManager = GameEntry.EnemyManager;
|
||||
Player player = FindPlayer();
|
||||
HealthComponent playerHealth = player != null ? player.GetComponent<HealthComponent>() : null;
|
||||
|
||||
if (enemyManager == null)
|
||||
{
|
||||
GUILayout.Label("EnemyManager unavailable.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (procedure == null)
|
||||
{
|
||||
GUILayout.Label("ProcedureGame unavailable.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_showBattleOverview)
|
||||
{
|
||||
GUILayout.Label($"Spawn Rate: {enemyManager.SpawnRateScale:F2}");
|
||||
GUILayout.Label(
|
||||
$"Battle Time: {enemyManager.ElapsedBattleTime:F1}s / {enemyManager.BattleDuration:F1}s");
|
||||
GUILayout.Label($"Enemy Count: {enemyManager.CurrentEnemyCount}");
|
||||
}
|
||||
|
||||
SimulationWorld simulationWorld = GameEntry.SimulationWorld;
|
||||
if (_showCollisionStats && simulationWorld != null)
|
||||
{
|
||||
GUILayout.Space(4f);
|
||||
GUILayout.Label(
|
||||
$"Collision Queries: total {simulationWorld.LastCollisionQueryCount} (Projectile {simulationWorld.LastProjectileCollisionQueryCount} / Area {simulationWorld.LastAreaCollisionQueryCount})");
|
||||
GUILayout.Label(
|
||||
$"Collision Candidates: total {simulationWorld.LastCollisionCandidateCount} (Projectile {simulationWorld.LastProjectileCollisionCandidateCount} / Area {simulationWorld.LastAreaCollisionCandidateCount})");
|
||||
GUILayout.Label(
|
||||
$"Area Resolve: hits {simulationWorld.LastResolvedAreaHitCount}");
|
||||
GUILayout.Label(
|
||||
$"Broad Phase: cell {simulationWorld.LastCollisionCellSize:F2}, hasEnemyTargets {(simulationWorld.LastCollisionHasEnemyTargets ? "Yes" : "No")}");
|
||||
if (simulationWorld.LastCollisionCandidateCount != 0)
|
||||
{
|
||||
Log.Info($"LastCollisionCandidateCount:{simulationWorld.LastCollisionCandidateCount}");
|
||||
}
|
||||
|
||||
if (simulationWorld.LastResolvedAreaHitCount != 0)
|
||||
{
|
||||
Log.Info($"LastResolvedAreaHitCount:{simulationWorld.LastResolvedAreaHitCount}");
|
||||
}
|
||||
}
|
||||
|
||||
if (_showSpawnControls)
|
||||
{
|
||||
GUILayout.Space(12f);
|
||||
GUILayout.Label("Enemy Spawn Rate");
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.Label("Rate", GUILayout.Width(78f));
|
||||
string rateText = GUILayout.TextField(_spawnRateScaleInput.ToString("F2"), GUILayout.Width(88f));
|
||||
if (float.TryParse(rateText, out float parsedRate))
|
||||
{
|
||||
_spawnRateScaleInput = Mathf.Clamp(parsedRate, MinSpawnRate, 50f);
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Apply", GUILayout.Width(100f)))
|
||||
{
|
||||
enemyManager.SetSpawnRateScale(_spawnRateScaleInput);
|
||||
}
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
GUILayout.BeginHorizontal();
|
||||
|
||||
if (GUILayout.Button("x0.5"))
|
||||
{
|
||||
_spawnRateScaleInput = Mathf.Max(MinSpawnRate, enemyManager.SpawnRateScale * 0.5f);
|
||||
enemyManager.SetSpawnRateScale(_spawnRateScaleInput);
|
||||
}
|
||||
|
||||
if (GUILayout.Button("x2"))
|
||||
{
|
||||
_spawnRateScaleInput = enemyManager.SpawnRateScale * 2f;
|
||||
enemyManager.SetSpawnRateScale(_spawnRateScaleInput);
|
||||
}
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
if (_showBattleDurationControls)
|
||||
{
|
||||
GUILayout.Space(12f);
|
||||
GUILayout.Label("Battle Duration");
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.Label("Add Sec", GUILayout.Width(78f));
|
||||
string durationText = GUILayout.TextField(_extendDurationSeconds.ToString("F0"), GUILayout.Width(88f));
|
||||
if (float.TryParse(durationText, out float parsedDuration))
|
||||
{
|
||||
_extendDurationSeconds = Mathf.Clamp(parsedDuration, 1f, 3600f);
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Extend Battle", GUILayout.Height(44f)))
|
||||
{
|
||||
if (procedure.CurrentGameState is GameStateBattle gameState)
|
||||
{
|
||||
gameState.AddBattleDuration(_extendDurationSeconds);
|
||||
}
|
||||
}
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
if (_showPlayerWeaponControls)
|
||||
{
|
||||
GUILayout.Space(12f);
|
||||
GUILayout.Label(
|
||||
$"Player Weapon: {(player == null ? "Player not found" : (player.WeaponEnabled ? "Enabled" : "Disabled"))}");
|
||||
GUILayout.BeginHorizontal();
|
||||
GUI.enabled = player != null;
|
||||
if (GUILayout.Button("Disable Weapons", GUILayout.Height(44f)))
|
||||
{
|
||||
player.SetWeaponEnabled(false);
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Enable Weapons", GUILayout.Height(44f)))
|
||||
{
|
||||
player.SetWeaponEnabled(true);
|
||||
}
|
||||
|
||||
GUI.enabled = true;
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
if (_showPlayerHealthControls)
|
||||
{
|
||||
GUILayout.Space(4f);
|
||||
GUILayout.Label(
|
||||
$"Player HP: {(playerHealth == null ? "Unavailable" : $"{playerHealth.CurrentHealth}/{playerHealth.MaxHealth}")}");
|
||||
GUILayout.BeginHorizontal();
|
||||
GUI.enabled = playerHealth != null;
|
||||
if (GUILayout.Button($"+{DebugHealAmount} HP", GUILayout.Height(44f)))
|
||||
{
|
||||
AddPlayerHealth(playerHealth, DebugHealAmount);
|
||||
}
|
||||
|
||||
if (GUILayout.Button(_lockPlayerHealthToMax ? "GodMode: ON" : "GodMode: OFF", GUILayout.Height(44f)))
|
||||
{
|
||||
_lockPlayerHealthToMax = !_lockPlayerHealthToMax;
|
||||
if (_lockPlayerHealthToMax)
|
||||
{
|
||||
RestorePlayerHealthToMax(playerHealth);
|
||||
}
|
||||
}
|
||||
|
||||
GUI.enabled = true;
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
|
||||
private bool HasVisibleBattleSection()
|
||||
{
|
||||
return _showBattleOverview ||
|
||||
_showCollisionStats ||
|
||||
_showSpawnControls ||
|
||||
_showBattleDurationControls ||
|
||||
_showPlayerWeaponControls ||
|
||||
_showPlayerHealthControls;
|
||||
}
|
||||
|
||||
private void EnsurePropList(bool force = false)
|
||||
{
|
||||
if (!force && _allProps != null && _allProps.Length > 0) return;
|
||||
|
||||
if (GameEntry.Luban == null)
|
||||
{
|
||||
_allProps = Array.Empty<PropConfig>();
|
||||
_filteredProps = Array.Empty<PropConfig>();
|
||||
_displayNames = Array.Empty<string>();
|
||||
return;
|
||||
}
|
||||
|
||||
var table = GameEntry.Luban.GetTable<PropConfig>();
|
||||
_allProps = table != null ? table.ToArray() : Array.Empty<PropConfig>();
|
||||
_selectedIndex = Mathf.Clamp(_selectedIndex, 0, Mathf.Max(0, _allProps.Length - 1));
|
||||
ApplyFilter(_searchText);
|
||||
}
|
||||
|
||||
private void ApplyFilter(string keyword)
|
||||
{
|
||||
if (_allProps == null || _allProps.Length == 0)
|
||||
{
|
||||
_filteredProps = Array.Empty<PropConfig>();
|
||||
_displayNames = Array.Empty<string>();
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(keyword))
|
||||
{
|
||||
_filteredProps = _allProps;
|
||||
}
|
||||
else
|
||||
{
|
||||
string search = keyword.Trim();
|
||||
_filteredProps = _allProps.Where(p =>
|
||||
p != null &&
|
||||
(p.Title?.IndexOf(search, StringComparison.OrdinalIgnoreCase) >= 0 ||
|
||||
p.Id.ToString().Contains(search))).ToArray();
|
||||
}
|
||||
|
||||
_displayNames = _filteredProps.Select(p => $"[{p.Id}] {p.Title} ({p.Rarity})").ToArray();
|
||||
if (_displayNames.Length == 0) _selectedIndex = 0;
|
||||
else _selectedIndex = Mathf.Clamp(_selectedIndex, 0, _displayNames.Length - 1);
|
||||
}
|
||||
|
||||
private PropConfig GetSelectedProp()
|
||||
{
|
||||
if (_filteredProps == null || _filteredProps.Length == 0) return null;
|
||||
_selectedIndex = Mathf.Clamp(_selectedIndex, 0, _filteredProps.Length - 1);
|
||||
return _filteredProps[_selectedIndex];
|
||||
}
|
||||
|
||||
private static Player FindPlayer()
|
||||
{
|
||||
return UnityEngine.Object.FindObjectOfType<Player>();
|
||||
}
|
||||
|
||||
private void KeepPlayerHealthAtMax()
|
||||
{
|
||||
Player player = FindPlayer();
|
||||
if (player == null) return;
|
||||
|
||||
HealthComponent playerHealth = player.GetComponent<HealthComponent>();
|
||||
if (playerHealth == null) return;
|
||||
|
||||
RestorePlayerHealthToMax(playerHealth);
|
||||
}
|
||||
|
||||
private static void AddPlayerHealth(HealthComponent playerHealth, int amount)
|
||||
{
|
||||
if (playerHealth == null || amount <= 0) return;
|
||||
if (playerHealth.CurrentHealth <= 0) return;
|
||||
|
||||
int maxHealth = playerHealth.MaxHealth;
|
||||
if (maxHealth <= 0) return;
|
||||
|
||||
int nextHealth = Mathf.Clamp(playerHealth.CurrentHealth + amount, 0, maxHealth);
|
||||
if (nextHealth == playerHealth.CurrentHealth) return;
|
||||
|
||||
playerHealth.CurrentHealth = nextHealth;
|
||||
PublishPlayerHealthChanged(playerHealth);
|
||||
}
|
||||
|
||||
private static void RestorePlayerHealthToMax(HealthComponent playerHealth)
|
||||
{
|
||||
if (playerHealth == null) return;
|
||||
if (playerHealth.CurrentHealth <= 0) return;
|
||||
|
||||
int maxHealth = playerHealth.MaxHealth;
|
||||
if (maxHealth <= 0 || playerHealth.CurrentHealth >= maxHealth) return;
|
||||
|
||||
playerHealth.CurrentHealth = maxHealth;
|
||||
PublishPlayerHealthChanged(playerHealth);
|
||||
}
|
||||
|
||||
private static void PublishPlayerHealthChanged(HealthComponent playerHealth)
|
||||
{
|
||||
if (playerHealth == null || GameEntry.Event == null) return;
|
||||
|
||||
GameEntry.Event.Fire(null,
|
||||
PlayerHealthChangeEventArgs.Create(0, playerHealth.CurrentHealth, playerHealth.MaxHealth));
|
||||
}
|
||||
|
||||
private static void AddSelectedBuffToPlayer(PropConfig prop, int count)
|
||||
{
|
||||
Player player = FindPlayer();
|
||||
if (player == null || prop == null || prop.Modifiers == null) return;
|
||||
|
||||
int applyCount = Mathf.Clamp(count, 1, 99);
|
||||
for (int i = 0; i < applyCount; i++)
|
||||
{
|
||||
player.AddProp(new PropItem(prop));
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleCornerTapGesture()
|
||||
{
|
||||
if (!TryGetTouchReleased(out Vector2 touchPosition)) return;
|
||||
if (touchPosition.x > 80f || touchPosition.y < Screen.height - 80f) return;
|
||||
|
||||
float now = Time.unscaledTime;
|
||||
if (now - _lastCornerTapTime > CornerTapWindow)
|
||||
{
|
||||
_cornerTapCount = 0;
|
||||
}
|
||||
|
||||
_lastCornerTapTime = now;
|
||||
_cornerTapCount++;
|
||||
|
||||
if (_cornerTapCount >= RequiredCornerTapCount)
|
||||
{
|
||||
_cornerTapCount = 0;
|
||||
_isPanelVisible = !_isPanelVisible;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsTogglePressed()
|
||||
{
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
Keyboard keyboard = Keyboard.current;
|
||||
if (keyboard == null) return false;
|
||||
return keyboard.backquoteKey.wasPressedThisFrame || keyboard.f8Key.wasPressedThisFrame;
|
||||
#else
|
||||
return Input.GetKeyDown(KeyCode.BackQuote) || Input.GetKeyDown(KeyCode.F8);
|
||||
#endif
|
||||
}
|
||||
|
||||
private static bool TryGetTouchReleased(out Vector2 touchPosition)
|
||||
{
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
Touchscreen touchscreen = Touchscreen.current;
|
||||
if (touchscreen == null)
|
||||
{
|
||||
touchPosition = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
var touch = touchscreen.primaryTouch;
|
||||
if (!touch.press.wasReleasedThisFrame)
|
||||
{
|
||||
touchPosition = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
touchPosition = touch.position.ReadValue();
|
||||
return true;
|
||||
#else
|
||||
if (Input.touchCount <= 0)
|
||||
{
|
||||
touchPosition = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
Touch touch = Input.GetTouch(0);
|
||||
if (touch.phase != TouchPhase.Ended)
|
||||
{
|
||||
touchPosition = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
touchPosition = touch.position;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -115,7 +115,7 @@ GameObject:
|
||||
m_Component:
|
||||
- component: {fileID: 8253353784175897923}
|
||||
m_Layer: 0
|
||||
m_Name: BulletHandgun
|
||||
m_Name: Projectile
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
namespace SepCore.Definition
|
||||
{
|
||||
public sealed partial class LevelUpRewardConfig
|
||||
{
|
||||
public string IconAssetName => $"levelupreward_{(Id >= 1000 ? Id - 900 : Id)}_icon";
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace SepCore.Definition
|
||||
{
|
||||
public sealed partial class PropConfig
|
||||
{
|
||||
public string Title => Name;
|
||||
public string IconAssetName => $"prop_{(Id >= 1000 ? Id - 900 : Id)}_icon";
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
namespace SepCore.Definition
|
||||
{
|
||||
public sealed partial class RoleConfig
|
||||
{
|
||||
public int Id => Name == "老人" ? 102 : 101;
|
||||
public string RoleName => Name;
|
||||
public string IconName => $"role_{Id}_icon";
|
||||
public int WeaponCapacity => 6;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
namespace SepCore.Definition
|
||||
{
|
||||
public sealed partial class WeaponConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 图标资源名称(映射 weapon_1_icon ~ weapon_5_icon)。
|
||||
/// </summary>
|
||||
public string IconAssetName => $"weapon_{(Id >= 1000 ? Id % 1000 : Id)}_icon";
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ namespace SepCore.Definition
|
||||
public const int DataTableAsset = 100;
|
||||
public const int DictionaryAsset = 100;
|
||||
public const int FontAsset = 50;
|
||||
public const int SpriteAsset = 40;
|
||||
public const int MusicAsset = 20;
|
||||
public const int SceneAsset = 0;
|
||||
public const int SoundAsset = 30;
|
||||
|
||||
@@ -18,12 +18,55 @@ namespace SepCore.Definition
|
||||
{
|
||||
public const string DefaultLayerName = "Default";
|
||||
public static readonly int DefaultLayerId = LayerMask.NameToLayer(DefaultLayerName);
|
||||
public static readonly LayerMask DefaultLayerMask = 1 << DefaultLayerId;
|
||||
|
||||
public const string TransparentFXLayerName = "TransparentFX";
|
||||
public static readonly int TransparentLayerId = LayerMask.NameToLayer(TransparentFXLayerName);
|
||||
public static readonly LayerMask TransparentLayerMask = 1 << TransparentLayerId;
|
||||
|
||||
public const string IgnoreRaycastLayerName = "Ignore Raycast";
|
||||
public static readonly int IgnoreLayerId = LayerMask.NameToLayer(IgnoreRaycastLayerName);
|
||||
public static readonly LayerMask IgnoreLayerMask = 1 << IgnoreLayerId;
|
||||
|
||||
public const string WaterLayerName = "Water";
|
||||
public static readonly int WaterLayerId = LayerMask.NameToLayer(WaterLayerName);
|
||||
public static readonly LayerMask WaterLayerMask = 1 << WaterLayerId;
|
||||
|
||||
public const string UILayerName = "UI";
|
||||
public static readonly int UILayerId = LayerMask.NameToLayer(UILayerName);
|
||||
public static readonly LayerMask UILayerMask = 1 << UILayerId;
|
||||
|
||||
public const string TargetableObjectLayerName = "Targetable Object";
|
||||
public static readonly int TargetableObjectLayerId = LayerMask.NameToLayer(TargetableObjectLayerName);
|
||||
public static readonly LayerMask TargetableObjectLayerMask = 1 << TargetableObjectLayerId;
|
||||
|
||||
public const string PlayerLayerName = "Player";
|
||||
public static readonly int PlayerLayerId = LayerMask.NameToLayer(PlayerLayerName);
|
||||
public static readonly LayerMask PlayerLayerMask = 1 << PlayerLayerId;
|
||||
|
||||
public const string EnemyLayerName = "Enemy";
|
||||
public static readonly int EnemyLayerId = LayerMask.NameToLayer(EnemyLayerName);
|
||||
public static readonly LayerMask EnemyLayerMask = 1 << EnemyLayerId;
|
||||
|
||||
public const string PlayerBulletLayerName = "PlayerBullet";
|
||||
public static readonly int PlayerBulletLayerId = LayerMask.NameToLayer(PlayerBulletLayerName);
|
||||
public static readonly LayerMask PlayerBulletLayerMask = 1 << PlayerBulletLayerId;
|
||||
|
||||
public const string EnemyBulletLayerName = "EnemyBullet";
|
||||
public static readonly int EnemyBulletLayerId = LayerMask.NameToLayer(EnemyBulletLayerName);
|
||||
public static readonly LayerMask EnemyBulletLayerMask = 1 << EnemyBulletLayerId;
|
||||
|
||||
public const string PlayerWeaponLayerName = "PlayerWeapon";
|
||||
public static readonly int PlayerWeaponLayerId = LayerMask.NameToLayer(PlayerWeaponLayerName);
|
||||
public static readonly LayerMask PlayerWeaponLayerMask = 1 << PlayerWeaponLayerId;
|
||||
|
||||
public const string EnemyWeaponLayerName = "EnemyWeapon";
|
||||
public static readonly int EnemyWeaponLayerId = LayerMask.NameToLayer(EnemyWeaponLayerName);
|
||||
public static readonly LayerMask EnemyWeaponLayerMask = 1 << EnemyWeaponLayerId;
|
||||
|
||||
public const string DropLayerName = "Drop";
|
||||
public static readonly int DropLayerId = LayerMask.NameToLayer(DropLayerName);
|
||||
public static readonly LayerMask DropLayerMask = 1 << DropLayerId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
namespace SepCore.Definition
|
||||
{
|
||||
public static class DamageTypeExtensions
|
||||
{
|
||||
public static StatType ToScalingStat(this DamageType damageType)
|
||||
{
|
||||
switch (damageType)
|
||||
{
|
||||
case DamageType.Melee:
|
||||
return StatType.MeleeDamage;
|
||||
case DamageType.Ranged:
|
||||
return StatType.RangedDamage;
|
||||
case DamageType.Element:
|
||||
return StatType.ElementalDamage;
|
||||
default:
|
||||
return StatType.None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 37131c7b023611f4b83978960f4b3df4
|
||||
guid: 5e6128fa910e4a778c187123490b4119
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace SepCore.Definition
|
||||
{
|
||||
/// <summary>
|
||||
/// 属性查询接口。
|
||||
/// 供战斗碰撞(ImpactData)与伤害管线解耦读取属性值。
|
||||
/// </summary>
|
||||
public interface IAttributeProvider
|
||||
{
|
||||
float GetValue(StatType statType);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6d60ad7c035b4aa4abd87deb1d572847
|
||||
guid: b483f12479014631bb5914285260aa31
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -1,37 +1,45 @@
|
||||
//------------------------------------------------------------
|
||||
// Game Framework
|
||||
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
|
||||
// Homepage: https://gameframework.cn/
|
||||
// Feedback: mailto:ellan@gameframework.cn
|
||||
//------------------------------------------------------------
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using SepCore.Definition;
|
||||
|
||||
namespace SepCore.Definition
|
||||
{
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
public struct ImpactData
|
||||
{
|
||||
public ImpactData(CampType camp /*, int health*/, int attackBase, StatProperty attackStat = null,
|
||||
StatProperty defenseStat = null, StatProperty dodgeStat = null)
|
||||
{
|
||||
Camp = camp;
|
||||
//Health = health;
|
||||
AttackBase = attackBase;
|
||||
AttackStat = attackStat;
|
||||
DefenseStat = defenseStat;
|
||||
DodgeStat = dodgeStat;
|
||||
}
|
||||
|
||||
public CampType Camp { get; }
|
||||
|
||||
public int AttackBase { get; }
|
||||
|
||||
public StatProperty AttackStat { get; }
|
||||
public DamageType DamageType { get; }
|
||||
|
||||
public StatProperty DefenseStat { get; }
|
||||
public float ScalingRatio { get; }
|
||||
|
||||
public StatProperty DodgeStat { get; }
|
||||
public float BaseCritChance { get; }
|
||||
|
||||
public float CritMultiplier { get; }
|
||||
|
||||
public IAttributeProvider AttributeProvider { get; }
|
||||
|
||||
public ImpactData(
|
||||
CampType camp,
|
||||
int attackBase,
|
||||
IAttributeProvider attributeProvider = null,
|
||||
DamageType damageType = DamageType.None,
|
||||
float scalingRatio = 1.0f,
|
||||
float baseCritChance = 0f,
|
||||
float critMultiplier = 0f)
|
||||
{
|
||||
Camp = camp;
|
||||
AttackBase = attackBase;
|
||||
AttributeProvider = attributeProvider;
|
||||
DamageType = damageType;
|
||||
ScalingRatio = scalingRatio;
|
||||
BaseCritChance = baseCritChance;
|
||||
CritMultiplier = critMultiplier;
|
||||
}
|
||||
|
||||
public ImpactData(CampType camp, int attackBase)
|
||||
: this(camp, attackBase, null, DamageType.None, 1.0f, 0f, 0f)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,24 +4,24 @@ namespace SepCore.Definition
|
||||
{
|
||||
public class PropItem
|
||||
{
|
||||
private readonly List<modifier> _modifiers = new();
|
||||
private readonly List<StatModifierConfig> _modifiers = new();
|
||||
public string Title { get; private set; }
|
||||
public string IconAssetName { get; private set; }
|
||||
public Rarity Rarity { get; private set; }
|
||||
public IReadOnlyList<modifier> Modifiers => _modifiers;
|
||||
public IReadOnlyList<StatModifierConfig> Modifiers => _modifiers;
|
||||
|
||||
public PropItem(PropConfig prop)
|
||||
{
|
||||
if (prop.Modifiers != null)
|
||||
if (prop.StatModifierConfigs != null)
|
||||
{
|
||||
_modifiers.AddRange(prop.Modifiers);
|
||||
_modifiers.AddRange(prop.StatModifierConfigs);
|
||||
}
|
||||
Title = prop.Title;
|
||||
Title = prop.Name;
|
||||
Rarity = prop.Rarity;
|
||||
IconAssetName = prop.IconAssetName;
|
||||
IconAssetName = prop.Sprite;
|
||||
}
|
||||
|
||||
public PropItem(IEnumerable<modifier> modifiers)
|
||||
public PropItem(IEnumerable<StatModifierConfig> modifiers)
|
||||
{
|
||||
if (modifiers != null)
|
||||
{
|
||||
@@ -29,7 +29,7 @@ namespace SepCore.Definition
|
||||
}
|
||||
}
|
||||
|
||||
public PropItem(IEnumerable<modifier> modifiers, Rarity rarity, string title, string iconAssetName)
|
||||
public PropItem(IEnumerable<StatModifierConfig> modifiers, Rarity rarity, string title, string iconAssetName)
|
||||
{
|
||||
if (modifiers != null)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
namespace SepCore.Definition
|
||||
{
|
||||
public sealed partial class StatConfig
|
||||
{
|
||||
public StatConfig()
|
||||
{
|
||||
}
|
||||
|
||||
public StatConfig(
|
||||
StatType statType,
|
||||
string name = "",
|
||||
float defaultBaseValue = 0f,
|
||||
bool hasMin = false,
|
||||
float minValue = 0f,
|
||||
bool hasMax = false,
|
||||
float maxValue = 0f,
|
||||
bool isPercentDisplay = false)
|
||||
{
|
||||
StatType = statType;
|
||||
Name = name;
|
||||
DefaultBaseValue = defaultBaseValue;
|
||||
HasMin = hasMin;
|
||||
MinValue = minValue;
|
||||
HasMax = hasMax;
|
||||
MaxValue = maxValue;
|
||||
IsPercentDisplay = isPercentDisplay;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 430f837865b92144c82328dc2ce58823
|
||||
guid: 7b910e53a2454b5f903517865c36ad18
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace SepCore.Definition
|
||||
{
|
||||
/// <summary>
|
||||
/// 属性修饰器。
|
||||
/// 包含修饰数值、修饰类型(固定值/百分比加算/独立乘区)以及来源对象(道具/武器/羁绊/特质/Buff)。
|
||||
/// </summary>
|
||||
public sealed class StatModifier
|
||||
{
|
||||
public float Value { get; }
|
||||
public ModifierType Type { get; }
|
||||
public object Source { get; }
|
||||
|
||||
public StatModifier(float value, ModifierType type, object source = null)
|
||||
{
|
||||
Value = value;
|
||||
Type = type;
|
||||
Source = source;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从 Luban 导出的 modifier 数据结构转换。
|
||||
/// </summary>
|
||||
/// <param name="mod">Luban modifier 数据实例</param>
|
||||
/// <param name="source">来源对象引用</param>
|
||||
public static StatModifier FromLuban(StatModifierConfig mod, object source = null)
|
||||
{
|
||||
if (mod == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(mod));
|
||||
}
|
||||
|
||||
ModifierType type = mod.ModifierType;
|
||||
return new StatModifier(mod.Value, type, source);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"[StatModifier Type={Type}, Value={Value}, Source={Source}]";
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a30aae743bbd22b4cac1ef60f96a1bed
|
||||
guid: 887b4b22fce86cb43b95cfdf3c6b967c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace SepCore.Definition
|
||||
{
|
||||
public sealed partial class StatModifierConfig
|
||||
{
|
||||
public StatModifierConfig()
|
||||
{
|
||||
}
|
||||
|
||||
public StatModifierConfig(StatType statType, float value, ModifierType modifierType)
|
||||
{
|
||||
StatType = statType;
|
||||
Value = value;
|
||||
ModifierType = modifierType;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
namespace SepCore.Definition
|
||||
{
|
||||
public class StatProperty
|
||||
{
|
||||
public float Value;
|
||||
public float Percent;
|
||||
|
||||
public StatProperty()
|
||||
{
|
||||
Value = 0f;
|
||||
Percent = 1f;
|
||||
}
|
||||
|
||||
public StatProperty(float value, float percent)
|
||||
{
|
||||
Value = value;
|
||||
Percent = percent;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18e7bc9587114ae4a91c70f829543de8
|
||||
timeCreated: 1770353735
|
||||
@@ -1,70 +0,0 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace SepCore.Definition
|
||||
{
|
||||
public sealed partial class modifier
|
||||
{
|
||||
public StatType StatType => Key;
|
||||
|
||||
/// <summary>
|
||||
/// 实际参与数值计算的浮点数值。
|
||||
/// 1. 百分比加成(IsPercent == true):表内千分比(如 200 代表 20%),转换为 0.2f。
|
||||
/// 2. 非百分比加成(IsPercent == false):移动速度原为 float 放大了 1000 倍(如 800 代表 0.8f),除以 1000f;其余(如生命+53、攻击+10)直接使用原值。
|
||||
/// </summary>
|
||||
public float RealValue
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsPercent)
|
||||
{
|
||||
return Value / 1000f;
|
||||
}
|
||||
|
||||
if (Key == StatType.MovementSpeed)
|
||||
{
|
||||
return Value / 1000f;
|
||||
}
|
||||
|
||||
return Value;
|
||||
}
|
||||
}
|
||||
|
||||
public modifier()
|
||||
{
|
||||
}
|
||||
|
||||
public modifier(StatType key, int value, bool isPercent)
|
||||
{
|
||||
Key = key;
|
||||
Value = value;
|
||||
IsPercent = isPercent;
|
||||
}
|
||||
|
||||
public modifier(StatType key, float value, bool isPercent)
|
||||
{
|
||||
Key = key;
|
||||
Value = (isPercent || key == StatType.MovementSpeed)
|
||||
? Mathf.RoundToInt(value * 1000f)
|
||||
: Mathf.RoundToInt(value);
|
||||
IsPercent = isPercent;
|
||||
}
|
||||
|
||||
public string ToDisplayString()
|
||||
{
|
||||
if (IsPercent)
|
||||
{
|
||||
float percent = Value / 10f;
|
||||
return $"{Key} +{percent:0.##}%";
|
||||
}
|
||||
|
||||
if (Key == StatType.MovementSpeed)
|
||||
{
|
||||
float speed = Value / 1000f;
|
||||
return $"{Key} +{speed:0.##}";
|
||||
}
|
||||
|
||||
return $"{Key} +{Value}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
namespace SepCore.Definition
|
||||
{
|
||||
public enum EnemyType : byte
|
||||
{
|
||||
None = 0,
|
||||
MeleeEnemy = 1,
|
||||
RemoteEnemy = 2,
|
||||
BatEnemy = 3,
|
||||
SkeletonEnemy = 4,
|
||||
SkeletonGiantEnemy = 5,
|
||||
GhostEnemy = 6,
|
||||
FireMageEnemy = 7,
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2aa817d65bcc425a9e015f3c1de7c9a9
|
||||
timeCreated: 1770209105
|
||||
@@ -1,12 +0,0 @@
|
||||
namespace SepCore.Definition
|
||||
{
|
||||
public enum WeaponType : int
|
||||
{
|
||||
None = 0,
|
||||
WeaponKnife = 1001,
|
||||
WeaponHandgun = 1002,
|
||||
WeaponSlash = 1003,
|
||||
WeaponLightning = 1004,
|
||||
WeaponLance = 1005,
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SepCore.Definition;
|
||||
using UnityEngine;
|
||||
|
||||
namespace SepCore.Entity
|
||||
{
|
||||
[Serializable]
|
||||
public class EnemyData : TargetableObjectData
|
||||
{
|
||||
private readonly EnemyConfig _enemyConfig;
|
||||
private readonly EnemyType _enemyType;
|
||||
|
||||
public EnemyData(int entityId, EnemyConfig enemyConfig, EnemyType enemyType, int level)
|
||||
: base(enemyConfig != null ? enemyConfig.Prefab : string.Empty, entityId, CampType.Enemy)
|
||||
{
|
||||
_enemyConfig = enemyConfig;
|
||||
_enemyType = enemyType;
|
||||
int effectiveLevel = Mathf.Max(1, level);
|
||||
MaxHealthBase = _enemyConfig != null
|
||||
? _enemyConfig.MaxHealth + _enemyConfig.HpAddPerLevel * (effectiveLevel - 1)
|
||||
: 100;
|
||||
}
|
||||
|
||||
public EnemyType EnemyType => _enemyType;
|
||||
|
||||
public override int MaxHealthBase { get; }
|
||||
|
||||
public int AttackDamage => _enemyConfig?.AttackDamage ?? 0;
|
||||
|
||||
public float AttackCooldown => _enemyConfig?.AttackCooldown ?? 1f;
|
||||
|
||||
public float AttackRange => _enemyConfig?.AttackRange ?? 1.5f;
|
||||
|
||||
public float SpeedBase => _enemyConfig?.Speed ?? 2f;
|
||||
|
||||
public int DropCoin => _enemyConfig?.CoinDrop ?? 0;
|
||||
|
||||
public int DropExp => _enemyConfig?.ExpDrop ?? 0;
|
||||
|
||||
public float DropPercent => _enemyConfig?.DropPercent ?? 0f;
|
||||
|
||||
public float Scale => _enemyConfig?.Scale ?? 1f;
|
||||
|
||||
public Color Color
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_enemyConfig != null &&
|
||||
!string.IsNullOrEmpty(_enemyConfig.Color) &&
|
||||
ColorUtility.TryParseHtmlString(_enemyConfig.Color, out Color color))
|
||||
{
|
||||
return color;
|
||||
}
|
||||
|
||||
return Color.white;
|
||||
}
|
||||
}
|
||||
|
||||
public IReadOnlyDictionary<string, string> Params => null;
|
||||
|
||||
public bool TryGetParam(string key, out string value)
|
||||
{
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SepCore.Definition;
|
||||
|
||||
namespace SepCore.Entity
|
||||
{
|
||||
[Serializable]
|
||||
public class WeaponData : AccessoryObjectData
|
||||
{
|
||||
private readonly WeaponConfig _weaponConfig;
|
||||
|
||||
public WeaponData(int entityId, WeaponConfig weaponConfig, int ownerId, CampType ownerCamp)
|
||||
: base(weaponConfig.Prefab, entityId, ownerId, ownerCamp)
|
||||
{
|
||||
_weaponConfig = weaponConfig;
|
||||
}
|
||||
|
||||
public WeaponConfig Config => _weaponConfig;
|
||||
|
||||
public WeaponType WeaponType => (WeaponType)_weaponConfig.Id;
|
||||
|
||||
public int Attack => _weaponConfig.Attack;
|
||||
|
||||
public string Title => _weaponConfig.Name;
|
||||
|
||||
public string IconAssetName => _weaponConfig.IconAssetName;
|
||||
|
||||
public Rarity Rarity => _weaponConfig.Rarity;
|
||||
|
||||
public int Price => _weaponConfig.Price;
|
||||
|
||||
public float Cooldown => _weaponConfig.Cooldown / 1000f;
|
||||
|
||||
public float AttackRange => _weaponConfig.AttackRange / 1000f;
|
||||
|
||||
public int AttackSoundId => _weaponConfig.AttackSoundId;
|
||||
|
||||
public IReadOnlyDictionary<ParamType, int> Parameters => _weaponConfig.Parameters;
|
||||
|
||||
public IReadOnlyList<modifier> Modifiers => _weaponConfig.Modifiers;
|
||||
|
||||
public int GetParam(ParamType paramType, int defaultValue = 0)
|
||||
{
|
||||
return _weaponConfig.Parameters.TryGetValue(paramType, out int value) ? value : defaultValue;
|
||||
}
|
||||
|
||||
public float GetParamFloat(ParamType paramType, float defaultValue = 0f)
|
||||
{
|
||||
if (_weaponConfig.Parameters.TryGetValue(paramType, out int val))
|
||||
{
|
||||
return paramType == ParamType.SectorAngle ? val : val / 1000f;
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
using System;
|
||||
using SepCore.Definition;
|
||||
|
||||
namespace SepCore.Entity
|
||||
{
|
||||
[Serializable]
|
||||
public sealed class WeaponHandgunParamsData
|
||||
{
|
||||
}
|
||||
|
||||
public class WeaponHandgunData : WeaponData
|
||||
{
|
||||
public WeaponHandgunParamsData ParamsData { get; }
|
||||
|
||||
public WeaponHandgunData(int entityId, WeaponConfig weaponConfig, int ownerId, CampType ownerCamp)
|
||||
: base(entityId, weaponConfig, ownerId, ownerCamp)
|
||||
{
|
||||
ParamsData = new WeaponHandgunParamsData();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 574d105bf89bf7546a682ed407708034
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,25 +0,0 @@
|
||||
using System;
|
||||
using SepCore.Definition;
|
||||
|
||||
namespace SepCore.Entity
|
||||
{
|
||||
[Serializable]
|
||||
public sealed class WeaponKnifeParamsData
|
||||
{
|
||||
public float HitRadius { get; set; }
|
||||
}
|
||||
|
||||
public class WeaponKnifeData : WeaponData
|
||||
{
|
||||
public WeaponKnifeParamsData ParamsData { get; }
|
||||
|
||||
public WeaponKnifeData(int entityId, WeaponConfig weaponConfig, int ownerId, CampType ownerCamp)
|
||||
: base(entityId, weaponConfig, ownerId, ownerCamp)
|
||||
{
|
||||
ParamsData = new WeaponKnifeParamsData
|
||||
{
|
||||
HitRadius = GetParamFloat(ParamType.HitRadius)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: da25d8e0669f0194d8f56f4283c67b38
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,76 +0,0 @@
|
||||
using System;
|
||||
using SepCore.Definition;
|
||||
|
||||
namespace SepCore.Entity
|
||||
{
|
||||
[Serializable]
|
||||
public sealed class WeaponLanceParamsData
|
||||
{
|
||||
/// <summary>
|
||||
/// 横向半宽,表示前戳矩形判定的一半宽度。
|
||||
/// </summary>
|
||||
public float HitHalfWidth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 旧字段兼容,未配置 HitHalfWidth 时回退使用。
|
||||
/// </summary>
|
||||
public float HitRadius { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 前戳判定盒体的总高度。
|
||||
/// </summary>
|
||||
public float HitHeight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 判定盒体中心相对战斗平面的高度偏移。
|
||||
/// </summary>
|
||||
public float HitCenterYOffset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 前刺距离,同时驱动武器位移和命中长度。
|
||||
/// </summary>
|
||||
public float PierceLength { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 旧字段兼容,未配置 PierceLength 时回退使用。
|
||||
/// </summary>
|
||||
public float ThrustDistance { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 判定起点相对武器当前位置的前置偏移。
|
||||
/// </summary>
|
||||
public float ForwardOffset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 追踪目标时的转向速度。
|
||||
/// </summary>
|
||||
public float RotateSpeed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 向前突刺阶段耗时。
|
||||
/// </summary>
|
||||
public float AttackDuration { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 收枪返回阶段耗时。
|
||||
/// </summary>
|
||||
public float ReturnDuration { get; set; }
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class WeaponLanceData : WeaponData
|
||||
{
|
||||
public WeaponLanceParamsData ParamsData { get; }
|
||||
|
||||
public WeaponLanceData(int entityId, WeaponConfig weaponConfig, int ownerId, CampType ownerCamp)
|
||||
: base(entityId, weaponConfig, ownerId, ownerCamp)
|
||||
{
|
||||
ParamsData = new WeaponLanceParamsData
|
||||
{
|
||||
HitHalfWidth = GetParamFloat(ParamType.HitHalfWidth),
|
||||
PierceLength = GetParamFloat(ParamType.PierceLength),
|
||||
HitHeight = GetParamFloat(ParamType.HitHeight)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4d1a821e8ee1a9a4b912b70b0a1616eb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,27 +0,0 @@
|
||||
using System;
|
||||
using SepCore.Definition;
|
||||
|
||||
namespace SepCore.Entity
|
||||
{
|
||||
[Serializable]
|
||||
public sealed class WeaponLightningParamsData
|
||||
{
|
||||
public float HitRadius { get; set; }
|
||||
public float HoverHeight { get; set; }
|
||||
}
|
||||
|
||||
public class WeaponLightningData : WeaponData
|
||||
{
|
||||
public WeaponLightningParamsData ParamsData { get; }
|
||||
|
||||
public WeaponLightningData(int entityId, WeaponConfig weaponConfig, int ownerId, CampType ownerCamp)
|
||||
: base(entityId, weaponConfig, ownerId, ownerCamp)
|
||||
{
|
||||
ParamsData = new WeaponLightningParamsData
|
||||
{
|
||||
HitRadius = GetParamFloat(ParamType.HitRadius),
|
||||
HoverHeight = 0f
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 25b0006918fd46959c7f6b8ec1bbc8ab
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,25 +0,0 @@
|
||||
using System;
|
||||
using SepCore.Definition;
|
||||
|
||||
namespace SepCore.Entity
|
||||
{
|
||||
[Serializable]
|
||||
public sealed class WeaponSlashParamsData
|
||||
{
|
||||
public float SectorAngle { get; set; }
|
||||
}
|
||||
|
||||
public class WeaponSlashData : WeaponData
|
||||
{
|
||||
public WeaponSlashParamsData ParamsData { get; }
|
||||
|
||||
public WeaponSlashData(int entityId, WeaponConfig weaponConfig, int ownerId, CampType ownerCamp)
|
||||
: base(entityId, weaponConfig, ownerId, ownerCamp)
|
||||
{
|
||||
ParamsData = new WeaponSlashParamsData
|
||||
{
|
||||
SectorAngle = GetParamFloat(ParamType.SectorAngle)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4aa6473525dc4c62aeee02ff562ec453
|
||||
timeCreated: 1771484661
|
||||
-4
@@ -9,10 +9,6 @@ namespace SepCore.Entity
|
||||
_value = value;
|
||||
}
|
||||
|
||||
public CoinData(int value, int entityId, int typeId) : this(value, entityId, "CoinEntity")
|
||||
{
|
||||
}
|
||||
|
||||
public int Value
|
||||
{
|
||||
get => _value;
|
||||
@@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SepCore.Definition;
|
||||
using UnityEngine;
|
||||
|
||||
namespace SepCore.Entity
|
||||
{
|
||||
[Serializable]
|
||||
public class EnemyData : TargetableObjectData
|
||||
{
|
||||
public EnemyConfig Config { get; }
|
||||
|
||||
public EnemyData(int entityId, EnemyConfig enemyConfig, int level)
|
||||
: base(enemyConfig.Prefab, entityId, CampType.Enemy)
|
||||
{
|
||||
Config = enemyConfig;
|
||||
int effectiveLevel = Mathf.Max(1, level);
|
||||
MaxHealthBase = enemyConfig.MaxHealth + enemyConfig.HpAddPerLevel * (effectiveLevel - 1);
|
||||
}
|
||||
|
||||
public EnemyType EnemyType => Config.EnemyType;
|
||||
|
||||
public string LogicType => Config.LogicType;
|
||||
|
||||
public override int MaxHealthBase { get; }
|
||||
|
||||
public int AttackDamage => Config.AttackDamage;
|
||||
|
||||
public float AttackCooldown => Config.AttackCooldown;
|
||||
|
||||
public float AttackRange => Config.AttackRange;
|
||||
|
||||
public float SpeedBase => Config.Speed;
|
||||
|
||||
public int DropCoin => Config.CoinDrop;
|
||||
|
||||
public int DropExp => Config.ExpDrop;
|
||||
|
||||
public float DropPercent => Config.DropPercent;
|
||||
|
||||
public float Scale => Config.Scale;
|
||||
|
||||
public Color Color
|
||||
{
|
||||
get
|
||||
{
|
||||
// 空/非法颜色值视为无染色(乘以白色)。
|
||||
return ColorUtility.TryParseHtmlString(Config.Color, out Color color)
|
||||
? color
|
||||
: Color.white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -8,7 +8,7 @@ namespace SepCore.Entity
|
||||
public class EnemyProjectileData : EntityDataBase
|
||||
{
|
||||
public EnemyProjectileData(int entityId, int ownerEntityId, CampType ownerCamp, int attackDamage,
|
||||
float speed, float lifeTime, Vector3 direction, string assetName = "BulletHandgun")
|
||||
float speed, float lifeTime, Vector3 direction, string assetName = "Projectile")
|
||||
: base(assetName, entityId)
|
||||
{
|
||||
OwnerEntityId = ownerEntityId;
|
||||
-4
@@ -9,10 +9,6 @@ namespace SepCore.Entity
|
||||
_value = value;
|
||||
}
|
||||
|
||||
public ExpData(int value, int entityId, int typeId) : this(value, entityId, "ExpEntity")
|
||||
{
|
||||
}
|
||||
|
||||
public int Value
|
||||
{
|
||||
get => _value;
|
||||
-4
@@ -13,10 +13,6 @@ namespace SepCore.Entity
|
||||
MaxHealthBase = 100;
|
||||
}
|
||||
|
||||
public PlayerData(int entityId, int typeId) : this(entityId, "Player")
|
||||
{
|
||||
}
|
||||
|
||||
public override int MaxHealthBase { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SepCore.Definition;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace SepCore.Entity
|
||||
{
|
||||
[Serializable]
|
||||
public class WeaponData : AccessoryObjectData
|
||||
{
|
||||
public WeaponConfig Config { get; }
|
||||
|
||||
public WeaponData(int entityId, WeaponConfig weaponConfig, int ownerId, CampType ownerCamp)
|
||||
: base(weaponConfig.Prefab, entityId, ownerId, ownerCamp)
|
||||
{
|
||||
Config = weaponConfig;
|
||||
}
|
||||
|
||||
public WeaponType WeaponType => Config.WeaponType;
|
||||
|
||||
public string LogicType => Config.LogicType;
|
||||
|
||||
public int Attack => Config.Attack;
|
||||
|
||||
public DamageType DamageType => Config.DamageType;
|
||||
|
||||
public string Title => Config.WeaponType.ToString();
|
||||
|
||||
public string Sprite => Config.Sprite;
|
||||
|
||||
public Rarity Rarity => Config.Rarity;
|
||||
|
||||
public int Price => Config.Price;
|
||||
|
||||
public float Cooldown => Config.Cooldown;
|
||||
|
||||
public float AttackRange => Config.AttackRange;
|
||||
|
||||
public int AttackSoundId => Config.AttackSoundId;
|
||||
|
||||
public IReadOnlyDictionary<ParamType, float> Parameters => Config.Parameters;
|
||||
|
||||
public IReadOnlyList<StatModifierConfig> Modifiers => Config.StatModifierConfigs;
|
||||
|
||||
public float GetParamFloat(ParamType paramType)
|
||||
{
|
||||
if (Config.Parameters.TryGetValue(paramType, out float val))
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
Log.Error("Weapon parameter '{0}' not found for weapon '{1}'.", paramType, Config.WeaponType);
|
||||
return 0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,18 +9,18 @@ namespace SepCore.Event
|
||||
|
||||
public override int Id => EventId;
|
||||
|
||||
public int RoleId { get; private set; } = -1;
|
||||
public string RoleName { get; private set; }
|
||||
|
||||
public static SelectRoleHoverEventArgs Create(int roleId)
|
||||
public static SelectRoleHoverEventArgs Create(string roleName)
|
||||
{
|
||||
var args = ReferencePool.Acquire<SelectRoleHoverEventArgs>();
|
||||
args.RoleId = roleId;
|
||||
args.RoleName = roleName;
|
||||
return args;
|
||||
}
|
||||
|
||||
public override void Clear()
|
||||
{
|
||||
RoleId = -1;
|
||||
RoleName = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
namespace SepCore.Definition
|
||||
{
|
||||
/// <summary>
|
||||
/// 伤害类型
|
||||
/// </summary>
|
||||
[System.Flags]
|
||||
public enum DamageType : int
|
||||
{
|
||||
/// <summary>
|
||||
/// 无
|
||||
/// </summary>
|
||||
None = 0,
|
||||
/// <summary>
|
||||
/// 近战伤害
|
||||
/// </summary>
|
||||
Melee = 1,
|
||||
/// <summary>
|
||||
/// 远程伤害
|
||||
/// </summary>
|
||||
Ranged = 2,
|
||||
/// <summary>
|
||||
/// 元素伤害
|
||||
/// </summary>
|
||||
Element = 4,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 178341689d25049458e8460d398db2dc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -16,7 +16,8 @@ public sealed partial class EnemyConfig : Luban.BeanBase
|
||||
{
|
||||
public EnemyConfig(ByteBuf _buf)
|
||||
{
|
||||
Name = _buf.ReadString();
|
||||
EnemyType = (EnemyType)_buf.ReadInt();
|
||||
LogicType = _buf.ReadString();
|
||||
MaxHealth = _buf.ReadInt();
|
||||
HpAddPerLevel = _buf.ReadInt();
|
||||
AttackDamage = _buf.ReadInt();
|
||||
@@ -38,9 +39,13 @@ public sealed partial class EnemyConfig : Luban.BeanBase
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// 敌人类型
|
||||
/// </summary>
|
||||
public readonly string Name;
|
||||
public readonly EnemyType EnemyType;
|
||||
/// <summary>
|
||||
/// 逻辑类型
|
||||
/// </summary>
|
||||
public readonly string LogicType;
|
||||
/// <summary>
|
||||
/// 最大生命
|
||||
/// </summary>
|
||||
@@ -108,13 +113,15 @@ public sealed partial class EnemyConfig : Luban.BeanBase
|
||||
|
||||
|
||||
|
||||
|
||||
Prefab_Ref = tables.TbEntityConfig.GetOrDefault(Prefab);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "{ "
|
||||
+ "name:" + Name + ","
|
||||
+ "enemyType:" + EnemyType + ","
|
||||
+ "logicType:" + LogicType + ","
|
||||
+ "maxHealth:" + MaxHealth + ","
|
||||
+ "hpAddPerLevel:" + HpAddPerLevel + ","
|
||||
+ "attackDamage:" + AttackDamage + ","
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
namespace SepCore.Definition
|
||||
{
|
||||
/// <summary>
|
||||
/// 敌人状态
|
||||
/// </summary>
|
||||
public enum EnemyStateType : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// 无
|
||||
/// </summary>
|
||||
None = 0,
|
||||
/// <summary>
|
||||
/// 攻击
|
||||
/// </summary>
|
||||
Attack = 1,
|
||||
/// <summary>
|
||||
/// 待机
|
||||
/// </summary>
|
||||
Idle = 2,
|
||||
/// <summary>
|
||||
/// 搜索
|
||||
/// </summary>
|
||||
Seek = 3,
|
||||
/// <summary>
|
||||
/// 追逐
|
||||
/// </summary>
|
||||
Chase = 4,
|
||||
/// <summary>
|
||||
/// 死亡
|
||||
/// </summary>
|
||||
Dead = 5,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d55e30fdec251d141bab19b1b87806b3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user