bug修复
This commit is contained in:
parent
65a7b40a8c
commit
de2f9439a7
@ -213,50 +213,50 @@
|
|||||||
"giant_enum": "NorwayReimu",
|
"giant_enum": "NorwayReimu",
|
||||||
"name": "博丽灵梦",
|
"name": "博丽灵梦",
|
||||||
"subtitle": "帝国的御札巫女",
|
"subtitle": "帝国的御札巫女",
|
||||||
"desc": "临时图鉴文案。可向友方施加<color=green>博丽加护</color>抵消伤害,并以<color=red>退治</color>标记敌方英雄,通过连动攻击与御札效果获得额外收益。",
|
"desc": "饰演<color=red>克努特大帝</color>的博丽巫女。她原本只是为了奖金和可疑黑幕参加比赛,直到抵达赛场后,才发现本该留在神社看家的阿吽也站在队伍里。",
|
||||||
"diag": "暂未设置",
|
"diag": "我不是让你看家吗?……堇子,你最好解释一下。",
|
||||||
"english_name": "REIMU HAKUREI",
|
"english_name": "REIMU HAKUREI",
|
||||||
"achieve_pre_id": 0
|
"achieve_pre_id": 221
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"giant_type": 22,
|
"giant_type": 22,
|
||||||
"giant_enum": "NorwaySumireko",
|
"giant_enum": "NorwaySumireko",
|
||||||
"name": "宇佐见堇子",
|
"name": "宇佐见堇子",
|
||||||
"subtitle": "帝国的灵异使者",
|
"subtitle": "帝国的灵异使者",
|
||||||
"desc": "临时图鉴文案。可在战场上发射不同地形的灵异珠,影响附近单位的移动、攻击、防御与承伤规则。",
|
"desc": "饰演<color=red>诺曼底的爱玛</color>的女高中生。为了追寻灵异现象,她告诉阿吽“比赛非常需要你这样出色的狛犬来守护,而且守护规模是博丽神社的一百倍”,成功获得了可靠的保镖。",
|
||||||
"diag": "暂未设置",
|
"diag": "这个游戏非常可疑!充斥着各种灵异现象……什么,你说这个叫“bug”?",
|
||||||
"english_name": "SUMIREKO USAMI",
|
"english_name": "SUMIREKO USAMI",
|
||||||
"achieve_pre_id": 0
|
"achieve_pre_id": 222
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"giant_type": 23,
|
"giant_type": 23,
|
||||||
"giant_enum": "NorwayKasen",
|
"giant_enum": "NorwayKasen",
|
||||||
"name": "茨木华扇",
|
"name": "茨木华扇",
|
||||||
"subtitle": "帝国的兽引仙人",
|
"subtitle": "帝国的独臂仙人",
|
||||||
"desc": "临时图鉴文案。可设置全场唯一的<color=green>兽引</color>作为战术支点,通过召回、减伤、回复与传送能力支援战线。",
|
"desc": "饰演<color=red>沃尔夫斯坦</color>的独臂仙人。为了阻止巫女沉迷可疑的游戏,她连续数日亲自研究规则、检查阵容、推演棋盘。她坚称这只是必要的调查,绝不是因为再打一局就能赢。",
|
||||||
"diag": "暂未设置",
|
"diag": "监督者当然要熟悉规则。容我再研究一局,应该就能确认问题所在了。",
|
||||||
"english_name": "KASEN IBARAKI",
|
"english_name": "KASEN IBARAKI",
|
||||||
"achieve_pre_id": 0
|
"achieve_pre_id": 223
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"giant_type": 24,
|
"giant_type": 24,
|
||||||
"giant_enum": "NorwayAunn",
|
"giant_enum": "NorwayAunn",
|
||||||
"name": "高丽野阿吽",
|
"name": "高丽野阿吽",
|
||||||
"subtitle": "帝国的狛犬守卫",
|
"subtitle": "帝国的狛犬守卫",
|
||||||
"desc": "临时图鉴文案。攻击后可选择逃脱或石化,升级后可生成双身并共享生命,在防守与承伤中保护附近英雄。",
|
"desc": "饰演<color=red>莱夫·埃里克松</color>的狛犬守卫。她本该留在博丽神社看家,却被堇子轻易地骗来了比赛现场,她至今仍认为自己只是认真履行守护职责,并没有被“超大型守护任务”这些字眼骗到。",
|
||||||
"diag": "暂未设置",
|
"diag": "天呐,比神社大一百倍……咳,我只是担心灵梦小姐一个人忙不过来!",
|
||||||
"english_name": "AUNN KOMANO",
|
"english_name": "AUNN KOMANO",
|
||||||
"achieve_pre_id": 0
|
"achieve_pre_id": 224
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"giant_type": 25,
|
"giant_type": 25,
|
||||||
"giant_enum": "NorwaySuika",
|
"giant_enum": "NorwaySuika",
|
||||||
"name": "伊吹萃香",
|
"name": "伊吹萃香",
|
||||||
"subtitle": "帝国的鬼族怪力",
|
"subtitle": "帝国的鬼族怪力",
|
||||||
"desc": "临时图鉴文案。移动后生成小萃香,通过附着叠层进入大萃香或巨大萃香形态,以投掷和从天而降改写正面战场。",
|
"desc": "饰演<color=red>高个子索克尔</color>的酒豪。她听说比赛现场很热闹,有各种各样的宴会,便立刻在灵梦身边“聚集”齐了5位选手组队参赛。自她加入比赛之后,似乎每天到赛场报名的选手越来越多。",
|
||||||
"diag": "暂未设置",
|
"diag": "庆功宴!好耶!!啊,原来输了吗?那就更该喝一场了吧~",
|
||||||
"english_name": "SUIKA IBUKI",
|
"english_name": "SUIKA IBUKI",
|
||||||
"achieve_pre_id": 0
|
"achieve_pre_id": 225
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"giant_type": 26,
|
"giant_type": 26,
|
||||||
@ -841,7 +841,7 @@
|
|||||||
"civ_name": "维京",
|
"civ_name": "维京",
|
||||||
"force_name": "博丽帝国",
|
"force_name": "博丽帝国",
|
||||||
"leader_name": "博丽灵梦",
|
"leader_name": "博丽灵梦",
|
||||||
"empire_desc": "",
|
"empire_desc": "从约克到哥本哈根,从奥斯陆到温彻斯特,征服北海的辽阔疆域,如同制霸幻想乡一般易如反掌。继承了征服巨浪的意志,灵梦将以巫女的直觉和征服者的铁腕,将汇聚而来的信仰、财富与怨念统统塞进奉纳箱中,让博丽之名在瓦尔哈拉永恒传唱。",
|
||||||
"leader_desc": "懒散的博丽巫女抽到了<color=blue>维京</color>帝国卡,原本她只是在神社里无精打采的喝茶,结果听到奖金金额后当场坐直了。她加入比赛的理由很纯粹:奖金,顺带退治可疑的对手。",
|
"leader_desc": "懒散的博丽巫女抽到了<color=blue>维京</color>帝国卡,原本她只是在神社里无精打采的喝茶,结果听到奖金金额后当场坐直了。她加入比赛的理由很纯粹:奖金,顺带退治可疑的对手。",
|
||||||
"lines": {
|
"lines": {
|
||||||
"StartChatBubble": [
|
"StartChatBubble": [
|
||||||
|
|||||||
@ -158,36 +158,36 @@ Do not edit this file by hand; rerun `scripts/extract_dialogue_corpus.py` after
|
|||||||
|
|
||||||
- GiantType: `21`
|
- GiantType: `21`
|
||||||
- Subtitle: 帝国的御札巫女
|
- Subtitle: 帝国的御札巫女
|
||||||
- TH1 setting: 临时图鉴文案。可向友方施加<color=green>博丽加护</color>抵消伤害,并以<color=red>退治</color>标记敌方英雄,通过连动攻击与御札效果获得额外收益。
|
- TH1 setting: 饰演<color=red>克努特大帝</color>的博丽巫女。她原本只是为了奖金和可疑黑幕参加比赛,直到抵达赛场后,才发现本该留在神社看家的阿吽也站在队伍里。
|
||||||
- Dialogue: 暂未设置
|
- Dialogue: 我不是让你看家吗?……堇子,你最好解释一下。
|
||||||
|
|
||||||
### 宇佐见堇子 (NorwaySumireko)
|
### 宇佐见堇子 (NorwaySumireko)
|
||||||
|
|
||||||
- GiantType: `22`
|
- GiantType: `22`
|
||||||
- Subtitle: 帝国的灵异使者
|
- Subtitle: 帝国的灵异使者
|
||||||
- TH1 setting: 临时图鉴文案。可在战场上发射不同地形的灵异珠,影响附近单位的移动、攻击、防御与承伤规则。
|
- TH1 setting: 饰演<color=red>诺曼底的爱玛</color>的女高中生。为了追寻灵异现象,她告诉阿吽“比赛非常需要你这样出色的狛犬来守护,而且守护规模是博丽神社的一百倍”,成功获得了可靠的保镖。
|
||||||
- Dialogue: 暂未设置
|
- Dialogue: 这个游戏非常可疑!充斥着各种灵异现象……什么,你说这个叫“bug”?
|
||||||
|
|
||||||
### 茨木华扇 (NorwayKasen)
|
### 茨木华扇 (NorwayKasen)
|
||||||
|
|
||||||
- GiantType: `23`
|
- GiantType: `23`
|
||||||
- Subtitle: 帝国的兽引仙人
|
- Subtitle: 帝国的独臂仙人
|
||||||
- TH1 setting: 临时图鉴文案。可设置全场唯一的<color=green>兽引</color>作为战术支点,通过召回、减伤、回复与传送能力支援战线。
|
- TH1 setting: 饰演<color=red>沃尔夫斯坦</color>的独臂仙人。为了阻止巫女沉迷可疑的游戏,她连续数日亲自研究规则、检查阵容、推演棋盘。她坚称这只是必要的调查,绝不是因为再打一局就能赢。
|
||||||
- Dialogue: 暂未设置
|
- Dialogue: 监督者当然要熟悉规则。容我再研究一局,应该就能确认问题所在了。
|
||||||
|
|
||||||
### 高丽野阿吽 (NorwayAunn)
|
### 高丽野阿吽 (NorwayAunn)
|
||||||
|
|
||||||
- GiantType: `24`
|
- GiantType: `24`
|
||||||
- Subtitle: 帝国的狛犬守卫
|
- Subtitle: 帝国的狛犬守卫
|
||||||
- TH1 setting: 临时图鉴文案。攻击后可选择逃脱或石化,升级后可生成双身并共享生命,在防守与承伤中保护附近英雄。
|
- TH1 setting: 饰演<color=red>莱夫·埃里克松</color>的狛犬守卫。她本该留在博丽神社看家,却被堇子轻易地骗来了比赛现场,她至今仍认为自己只是认真履行守护职责,并没有被“超大型守护任务”这些字眼骗到。
|
||||||
- Dialogue: 暂未设置
|
- Dialogue: 天呐,比神社大一百倍……咳,我只是担心灵梦小姐一个人忙不过来!
|
||||||
|
|
||||||
### 伊吹萃香 (NorwaySuika)
|
### 伊吹萃香 (NorwaySuika)
|
||||||
|
|
||||||
- GiantType: `25`
|
- GiantType: `25`
|
||||||
- Subtitle: 帝国的鬼族怪力
|
- Subtitle: 帝国的鬼族怪力
|
||||||
- TH1 setting: 临时图鉴文案。移动后生成小萃香,通过附着叠层进入大萃香或巨大萃香形态,以投掷和从天而降改写正面战场。
|
- TH1 setting: 饰演<color=red>高个子索克尔</color>的酒豪。她听说比赛现场很热闹,有各种各样的宴会,便立刻在灵梦身边“聚集”齐了5位选手组队参赛。自她加入比赛之后,似乎每天到赛场报名的选手越来越多。
|
||||||
- Dialogue: 暂未设置
|
- Dialogue: 庆功宴!好耶!!啊,原来输了吗?那就更该喝一场了吧~
|
||||||
|
|
||||||
### 圣白莲(木偶) (BritishByakuren)
|
### 圣白莲(木偶) (BritishByakuren)
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"nextId": 388,
|
"nextId": 389,
|
||||||
"bugs": [
|
"bugs": [
|
||||||
{
|
{
|
||||||
"id": 2,
|
"id": 2,
|
||||||
@ -3970,6 +3970,17 @@
|
|||||||
"longTerm": false,
|
"longTerm": false,
|
||||||
"createdAt": 1782311317232,
|
"createdAt": 1782311317232,
|
||||||
"updatedAt": 1782311317232
|
"updatedAt": 1782311317232
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 388,
|
||||||
|
"title": "学者转化的白板巨人主动下海不是巨人船,没有溅射",
|
||||||
|
"description": "",
|
||||||
|
"status": "open",
|
||||||
|
"priority": "medium",
|
||||||
|
"module": "",
|
||||||
|
"longTerm": false,
|
||||||
|
"createdAt": 1782453603577,
|
||||||
|
"updatedAt": 1782453603577
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -8,11 +8,16 @@
|
|||||||
|
|
||||||
Player feedback: when Suika Ibuki is Lv.4 and uses the 3-grid self falling splash attack against an enemy unit, if the attack does not kill the target, Suika's own sprite does not visibly move to the landing position. The gameplay logic may move the unit, but the animation is wrong.
|
Player feedback: when Suika Ibuki is Lv.4 and uses the 3-grid self falling splash attack against an enemy unit, if the attack does not kill the target, Suika's own sprite does not visibly move to the landing position. The gameplay logic may move the unit, but the animation is wrong.
|
||||||
|
|
||||||
|
Follow-up feedback on the first dedicated Fragment fix: the jump animation was still too fast, the parabola was too low to read as "falling from the sky", and a projectile/bomb trail could still appear during Suika's jump presentation.
|
||||||
|
|
||||||
|
Follow-up feedback after the projectile/timing fix: when Suika jumps exactly 3 grids, neither the kill case where Suika lands on the enemy grid nor the non-kill case where Suika moves to an adjacent final grid visibly opens fog around the new landing position.
|
||||||
|
|
||||||
Affected entrypoint:
|
Affected entrypoint:
|
||||||
|
|
||||||
- `Unity/Assets/Scripts/TH1_Logic/Skill/AllSkill/HakureiNorwayHeroSkill.cs`
|
- `Unity/Assets/Scripts/TH1_Logic/Skill/AllSkill/HakureiNorwayHeroSkill.cs`
|
||||||
- `Unity/Assets/Scripts/TH1_Logic/Action/ActionLogic.cs`
|
- `Unity/Assets/Scripts/TH1_Logic/Action/ActionLogic.cs`
|
||||||
- `Unity/Assets/Scripts/TH1_Anim/Fragments/FragmentSuikaFallingSplash.cs`
|
- `Unity/Assets/Scripts/TH1_Anim/Fragments/FragmentSuikaFallingSplash.cs`
|
||||||
|
- `Unity/Assets/Scripts/TH1_Anim/Fragments/FragmentAttackGround.cs`
|
||||||
- `Unity/Assets/Scripts/TH1_Anim/UnitAtomAnim/UnitAtomAnimMove.cs`
|
- `Unity/Assets/Scripts/TH1_Anim/UnitAtomAnim/UnitAtomAnimMove.cs`
|
||||||
- `SuikaFallingSplashSkill.AfterActiveAttackOther`
|
- `SuikaFallingSplashSkill.AfterActiveAttackOther`
|
||||||
- `HakureiNorwayHeroSkillUtil.TryExecuteSuikaFlyAfterAttack`
|
- `HakureiNorwayHeroSkillUtil.TryExecuteSuikaFlyAfterAttack`
|
||||||
@ -31,6 +36,10 @@ That was still the wrong model for Suika Lv.4. The required presentation has thr
|
|||||||
|
|
||||||
When the target survives, the center target grid remains occupied, so the data layer correctly chooses a nearby landing grid. Without a dedicated Fragment, the renderer never had an explicit "land on target, splash, then move away" sequence.
|
When the target survives, the center target grid remains occupied, so the data layer correctly chooses a nearby landing grid. Without a dedicated Fragment, the renderer never had an explicit "land on target, splash, then move away" sequence.
|
||||||
|
|
||||||
|
The first dedicated Fragment still reused global attack timing (`AttackAnimTime` = 0.15s) and a low local arc height, so the jump read as a short hop instead of a sky-fall. The ground-target Suika path also still passed `SkillType.SuikaFallingSplash` through `FragmentAttackGround`, where it was mapped to `ProjectileType.Bomb`, creating a stray projectile.
|
||||||
|
|
||||||
|
The next miss was sight presentation. The logic did call `UpdateSightByPath` after Suika's data position changed, but the dedicated Suika Fragment only refreshed origin/target/final grids. It did not carry the set of newly opened sight grids into the landing presentation. For ground self-jump, the new-sight list was even collected after `AttackGroundExecute` had already mutated `SightGidSet`, so the list was empty.
|
||||||
|
|
||||||
## Root-Cause Fix
|
## Root-Cause Fix
|
||||||
|
|
||||||
Suika falling splash now uses a dedicated animation pipeline:
|
Suika falling splash now uses a dedicated animation pipeline:
|
||||||
@ -41,6 +50,14 @@ Suika falling splash now uses a dedicated animation pipeline:
|
|||||||
- `UnitAttackAction` switches Suika's Lv.4 falling-splash attack to the dedicated Fragment.
|
- `UnitAttackAction` switches Suika's Lv.4 falling-splash attack to the dedicated Fragment.
|
||||||
- The Fragment plays the parabola from origin to target, then the target/landing impact, then injected area-damage visuals, then an optional final `UnitAtomAnimType.Move` from target grid to final grid if the target survived.
|
- The Fragment plays the parabola from origin to target, then the target/landing impact, then injected area-damage visuals, then an optional final `UnitAtomAnimType.Move` from target grid to final grid if the target survived.
|
||||||
- The settle step refreshes Suika, origin/target/final grids, related cities, and map highlights.
|
- The settle step refreshes Suika, origin/target/final grids, related cities, and map highlights.
|
||||||
|
- Suika's parabola atom now uses a dedicated 1.1s duration and 18-world-unit arc height instead of inheriting the 0.15s attack timing.
|
||||||
|
- The Fragment waits briefly after splash impact before moving Suika away on non-kill results.
|
||||||
|
- Suika's self-jump-to-ground path now uses the same dedicated Fragment and data-only reposition, so it does not play `FragmentAttackGround`'s bomb projectile.
|
||||||
|
- `FragmentAttackGround` also has a defensive guard so `SkillType.SuikaFallingSplash` cannot map to `ProjectileType.Bomb` again.
|
||||||
|
- `CollectSuikaFallingSplashNewSightGrids` caches the newly opened sight grids before `UpdateSightByPath` mutates `SightGidSet`.
|
||||||
|
- `AttackInfo.SuikaFallingSplashSightRefreshGrids` carries attack landing sight refresh data into `FragmentSuikaFallingSplashData`.
|
||||||
|
- Suika's ground self-jump caches the same sight refresh data before `AttackGroundExecute`, then passes it into the dedicated Fragment.
|
||||||
|
- `FragmentSuikaFallingSplash.RefreshLandingSight` plays fog disappearance, forces grid refresh, and refreshes highlights for every newly opened grid at settle time.
|
||||||
|
|
||||||
This keeps the authoritative data mutation in the skill logic while making the presentation sequence match the actual player-facing behavior.
|
This keeps the authoritative data mutation in the skill logic while making the presentation sequence match the actual player-facing behavior.
|
||||||
|
|
||||||
@ -51,17 +68,23 @@ Added `Tools/CheckSuikaFallingSplashAnimation.ps1`.
|
|||||||
The checker verifies that Suika falling splash still:
|
The checker verifies that Suika falling splash still:
|
||||||
|
|
||||||
- Uses `UnitAtomAnimType.ParabolaMove`.
|
- Uses `UnitAtomAnimType.ParabolaMove`.
|
||||||
|
- Requires the dedicated 1.1s/18-height Suika jump constants.
|
||||||
- Builds `FragmentType.SuikaFallingSplash` from `UnitAttackAction`.
|
- Builds `FragmentType.SuikaFallingSplash` from `UnitAttackAction`.
|
||||||
|
- Builds `FragmentType.SuikaFallingSplash` for Suika self-jump-to-ground.
|
||||||
- Flushes area-damage visual steps into the dedicated Fragment after impact.
|
- Flushes area-damage visual steps into the dedicated Fragment after impact.
|
||||||
- Runs optional final `UnitAtomAnimType.Move` only after the impact phase.
|
- Runs optional final `UnitAtomAnimType.Move` only after the impact phase.
|
||||||
|
- Rejects any `FragmentAttackGround` mapping from `SkillType.SuikaFallingSplash` to `ProjectileType.Bomb`.
|
||||||
- Refreshes unit position, unit state, origin/landing grids, cities, and highlights after the landing move.
|
- Refreshes unit position, unit state, origin/landing grids, cities, and highlights after the landing move.
|
||||||
- Keeps `TryExecuteSuikaFlyAfterAttack` ordered as splash damage settlement, final data reposition, then dedicated animation marker.
|
- Keeps `TryExecuteSuikaFlyAfterAttack` ordered as splash damage settlement, new-sight cache, final data reposition, dedicated animation marker, and sight update.
|
||||||
|
- Verifies attack and ground self-jump both pass sight refresh grids into the dedicated Fragment.
|
||||||
|
- Verifies the Fragment iterates `Data.SightRefreshGrids` and forces grid refresh for opened fog.
|
||||||
|
|
||||||
`Tools/GitCheckpoint.ps1` now runs this checker when Suika falling-splash skill/action/Fragment/atom animation files change.
|
`Tools/GitCheckpoint.ps1` now runs this checker when Suika falling-splash skill/action/Fragment/atom animation files change.
|
||||||
|
|
||||||
- `Unity/Assets/Scripts/TH1_Logic/Skill/AllSkill/HakureiNorwayHeroSkill.cs`
|
- `Unity/Assets/Scripts/TH1_Logic/Skill/AllSkill/HakureiNorwayHeroSkill.cs`
|
||||||
- `Unity/Assets/Scripts/TH1_Logic/Action/ActionLogic.cs`
|
- `Unity/Assets/Scripts/TH1_Logic/Action/ActionLogic.cs`
|
||||||
- `Unity/Assets/Scripts/TH1_Anim/Fragments/FragmentSuikaFallingSplash.cs`
|
- `Unity/Assets/Scripts/TH1_Anim/Fragments/FragmentSuikaFallingSplash.cs`
|
||||||
|
- `Unity/Assets/Scripts/TH1_Anim/Fragments/FragmentData.cs`
|
||||||
- `Unity/Assets/Scripts/TH1_Anim/UnitAtomAnim/UnitAtomAnimMove.cs`
|
- `Unity/Assets/Scripts/TH1_Anim/UnitAtomAnim/UnitAtomAnimMove.cs`
|
||||||
- `Tools/CheckSuikaFallingSplashAnimation.ps1`
|
- `Tools/CheckSuikaFallingSplashAnimation.ps1`
|
||||||
|
|
||||||
@ -74,4 +97,5 @@ The checker verifies that Suika falling splash still:
|
|||||||
|
|
||||||
- Unity Editor gameplay validation: Suika Lv.4, 4 Suika Shadow stacks, attack an enemy exactly 3 grids away and do not kill it; confirm Suika visibly moves from the origin grid to the chosen landing grid and final sprite position matches data.
|
- Unity Editor gameplay validation: Suika Lv.4, 4 Suika Shadow stacks, attack an enemy exactly 3 grids away and do not kill it; confirm Suika visibly moves from the origin grid to the chosen landing grid and final sprite position matches data.
|
||||||
- Unity Editor gameplay validation: same attack with target killed; confirm the landing animation and death cleanup both play in the correct order.
|
- Unity Editor gameplay validation: same attack with target killed; confirm the landing animation and death cleanup both play in the correct order.
|
||||||
|
- Unity Editor gameplay validation: same kill and non-kill cases from fog boundary; confirm newly revealed tiles around Suika's final logical position visibly open.
|
||||||
- Unity Editor gameplay validation: same path with counterattack and with no counterattack, because both Fragment timelines have different step lists.
|
- Unity Editor gameplay validation: same path with counterattack and with no counterattack, because both Fragment timelines have different step lists.
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
| ID | 日期 | 状态 | 严重度 | 问题 | 根治方向 | 记录 |
|
| ID | 日期 | 状态 | 严重度 | 问题 | 根治方向 | 记录 |
|
||||||
| --- | --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- | --- |
|
||||||
| TH1-CI-2026-06-26-002 | 2026-06-26 | Fixed in code; guardrail added; Unity validation pending | Critical | Aunn shared HP ignored `DamageBearer` substitute-damage paths | Treat shared HP as an invariant over the actual mutated unit, `DamageBearer ?? DamageTarget`, with entrypoint fallback and shared-death cleanup | [record](2026-06-26-aunn-shared-health-damage-bearer.md) |
|
| TH1-CI-2026-06-26-002 | 2026-06-26 | Fixed in code; guardrail added; Unity validation pending | Critical | Aunn shared HP ignored `DamageBearer` substitute-damage paths | Treat shared HP as an invariant over the actual mutated unit, `DamageBearer ?? DamageTarget`, with entrypoint fallback and shared-death cleanup | [record](2026-06-26-aunn-shared-health-damage-bearer.md) |
|
||||||
| TH1-CI-2026-06-26-001 | 2026-06-26 | Fixed in code; guardrail added; Unity validation pending | High | Suika Lv4 falling splash can move data without showing the landing movement after a non-lethal 3-grid attack | Inject a real landing UnitAtomAnim.Move into the attack Fragment before the final renderer refresh | [record](2026-06-26-suika-falling-splash-landing-animation.md) |
|
| TH1-CI-2026-06-26-001 | 2026-06-26 | Fixed in code; guardrail added; Unity validation pending | High | Suika Lv4 falling splash can move data without complete landing, projectile, and fog/sight presentation after a 3-grid jump | Use a dedicated Suika falling-splash Fragment that owns jump, splash, final landing, and newly opened fog refresh | [record](2026-06-26-suika-falling-splash-landing-animation.md) |
|
||||||
| TH1-CI-2026-06-25-004 | 2026-06-25 | Fixed after correcting Aunn 331/332/342/344 source-buff map; Unity validation pending | Critical | Aunn hero source skills and same-name runtime buffs were conflated and edited without a confirmed skill source map | Enforce 331 as defense-only runtime buff, 332 as hidden approach state, 342 as Lv3+ Aunn Unique/source skill, and 344 as same-name Positive beneficiary damage-bearing buff | [record](2026-06-25-aunn-lv3-petrified-defense-aura-display.md) |
|
| TH1-CI-2026-06-25-004 | 2026-06-25 | Fixed after correcting Aunn 331/332/342/344 source-buff map; Unity validation pending | Critical | Aunn hero source skills and same-name runtime buffs were conflated and edited without a confirmed skill source map | Enforce 331 as defense-only runtime buff, 332 as hidden approach state, 342 as Lv3+ Aunn Unique/source skill, and 344 as same-name Positive beneficiary damage-bearing buff | [record](2026-06-25-aunn-lv3-petrified-defense-aura-display.md) |
|
||||||
| TH1-CI-2026-06-25-003 | 2026-06-25 | Fixed in assets; guardrails expanded; Unity validation pending | Critical | DataAssets/Export can silently accept corrupt text and missing Unity object GUIDs | Validate SkillDataAssets text/icon semantics and globally scan DataAssets/Export GUID references from GitCheckpoint | [record](2026-06-25-skill-dataasset-export-yaml-leak.md) |
|
| TH1-CI-2026-06-25-003 | 2026-06-25 | Fixed in assets; guardrails expanded; Unity validation pending | Critical | DataAssets/Export can silently accept corrupt text and missing Unity object GUIDs | Validate SkillDataAssets text/icon semantics and globally scan DataAssets/Export GUID references from GitCheckpoint | [record](2026-06-25-skill-dataasset-export-yaml-leak.md) |
|
||||||
| TH1-CI-2026-06-25-002 | 2026-06-25 | Fixed in code; guardrail added; Unity validation pending | High | Aunn twin auto-petrify regressed to movement-only trigger before Lv4 | Restore any-successful-Aunn-action trigger and checkpoint the lifecycle predicate | [record](2026-06-25-aunn-twin-auto-petrify-action-trigger.md) |
|
| TH1-CI-2026-06-25-002 | 2026-06-25 | Fixed in code; guardrail added; Unity validation pending | High | Aunn twin auto-petrify regressed to movement-only trigger before Lv4 | Restore any-successful-Aunn-action trigger and checkpoint the lifecycle predicate | [record](2026-06-25-aunn-twin-auto-petrify-action-trigger.md) |
|
||||||
|
|||||||
@ -2,6 +2,9 @@ param(
|
|||||||
[string]$SkillFile = "Unity/Assets/Scripts/TH1_Logic/Skill/AllSkill/HakureiNorwayHeroSkill.cs",
|
[string]$SkillFile = "Unity/Assets/Scripts/TH1_Logic/Skill/AllSkill/HakureiNorwayHeroSkill.cs",
|
||||||
[string]$ActionFile = "Unity/Assets/Scripts/TH1_Logic/Action/ActionLogic.cs",
|
[string]$ActionFile = "Unity/Assets/Scripts/TH1_Logic/Action/ActionLogic.cs",
|
||||||
[string]$FragmentFile = "Unity/Assets/Scripts/TH1_Anim/Fragments/FragmentSuikaFallingSplash.cs",
|
[string]$FragmentFile = "Unity/Assets/Scripts/TH1_Anim/Fragments/FragmentSuikaFallingSplash.cs",
|
||||||
|
[string]$FragmentDataFile = "Unity/Assets/Scripts/TH1_Anim/Fragments/FragmentData.cs",
|
||||||
|
[string]$AttackGroundFragmentFile = "Unity/Assets/Scripts/TH1_Anim/Fragments/FragmentAttackGround.cs",
|
||||||
|
[string]$UnitLogicFile = "Unity/Assets/Scripts/TH1_Logic/Unit/UnitLogic.cs",
|
||||||
[string]$FragmentManagerFile = "Unity/Assets/Scripts/TH1_Anim/FragmentManager.cs",
|
[string]$FragmentManagerFile = "Unity/Assets/Scripts/TH1_Anim/FragmentManager.cs",
|
||||||
[string]$AtomFile = "Unity/Assets/Scripts/TH1_Anim/UnitAtomAnim/UnitAtomAnim.cs",
|
[string]$AtomFile = "Unity/Assets/Scripts/TH1_Anim/UnitAtomAnim/UnitAtomAnim.cs",
|
||||||
[string]$AtomDataFile = "Unity/Assets/Scripts/TH1_Anim/UnitAtomAnim/UnitAtomAnimData.cs",
|
[string]$AtomDataFile = "Unity/Assets/Scripts/TH1_Anim/UnitAtomAnim/UnitAtomAnimData.cs",
|
||||||
@ -26,6 +29,9 @@ function Read-RepoFile([string]$relativePath) {
|
|||||||
$skillText = Read-RepoFile $SkillFile
|
$skillText = Read-RepoFile $SkillFile
|
||||||
$actionText = Read-RepoFile $ActionFile
|
$actionText = Read-RepoFile $ActionFile
|
||||||
$fragmentText = Read-RepoFile $FragmentFile
|
$fragmentText = Read-RepoFile $FragmentFile
|
||||||
|
$fragmentDataText = Read-RepoFile $FragmentDataFile
|
||||||
|
$attackGroundFragmentText = Read-RepoFile $AttackGroundFragmentFile
|
||||||
|
$unitLogicText = Read-RepoFile $UnitLogicFile
|
||||||
$fragmentManagerText = Read-RepoFile $FragmentManagerFile
|
$fragmentManagerText = Read-RepoFile $FragmentManagerFile
|
||||||
$atomText = Read-RepoFile $AtomFile
|
$atomText = Read-RepoFile $AtomFile
|
||||||
$atomDataText = Read-RepoFile $AtomDataFile
|
$atomDataText = Read-RepoFile $AtomDataFile
|
||||||
@ -40,28 +46,57 @@ function Assert-Contains([string]$text, [string]$needle, [string]$label) {
|
|||||||
Assert-Contains $atomText 'ParabolaMove' 'atom animation type'
|
Assert-Contains $atomText 'ParabolaMove' 'atom animation type'
|
||||||
Assert-Contains $atomText 'UnitAtomAnimType.ParabolaMove => new UnitAtomAnimParabolaMove' 'atom animation factory'
|
Assert-Contains $atomText 'UnitAtomAnimType.ParabolaMove => new UnitAtomAnimParabolaMove' 'atom animation factory'
|
||||||
Assert-Contains $atomDataText 'UnitAtomAnimParabolaMoveData' 'atom animation data'
|
Assert-Contains $atomDataText 'UnitAtomAnimParabolaMoveData' 'atom animation data'
|
||||||
|
Assert-Contains $atomDataText 'float duration = 1.1f' 'parabola default duration'
|
||||||
|
Assert-Contains $atomDataText 'float height = 18f' 'parabola default height'
|
||||||
Assert-Contains $atomMoveText 'class UnitAtomAnimParabolaMove' 'parabola atom animation'
|
Assert-Contains $atomMoveText 'class UnitAtomAnimParabolaMove' 'parabola atom animation'
|
||||||
Assert-Contains $fragmentManagerText 'FragmentType.SuikaFallingSplash => new FragmentSuikaFallingSplash' 'fragment factory'
|
Assert-Contains $fragmentManagerText 'FragmentType.SuikaFallingSplash => new FragmentSuikaFallingSplash' 'fragment factory'
|
||||||
Assert-Contains $fragmentText 'class FragmentSuikaFallingSplash' 'Suika fragment'
|
Assert-Contains $fragmentText 'class FragmentSuikaFallingSplash' 'Suika fragment'
|
||||||
|
Assert-Contains $fragmentText 'private const float JumpDuration = 1.1f;' 'Suika fragment jump duration'
|
||||||
|
Assert-Contains $fragmentText 'private const float JumpHeight = 18f;' 'Suika fragment jump height'
|
||||||
|
Assert-Contains $fragmentText 'SplashImpactPause' 'Suika fragment post-splash pause'
|
||||||
Assert-Contains $fragmentText 'UnitAtomAnimType.ParabolaMove' 'Suika fragment launch arc'
|
Assert-Contains $fragmentText 'UnitAtomAnimType.ParabolaMove' 'Suika fragment launch arc'
|
||||||
Assert-Contains $fragmentText 'AnimPhase.AttackImpact + 20' 'post-impact final move phase'
|
Assert-Contains $fragmentText 'AnimPhase.AttackImpact + 20' 'post-impact final move phase'
|
||||||
Assert-Contains $fragmentText 'UnitAtomAnimType.Move' 'post-impact final move'
|
Assert-Contains $fragmentText 'UnitAtomAnimType.Move' 'post-impact final move'
|
||||||
Assert-Contains $fragmentText 'RefreshFinalState' 'final refresh'
|
Assert-Contains $fragmentText 'RefreshFinalState' 'final refresh'
|
||||||
|
Assert-Contains $fragmentText 'RefreshLandingSight' 'landing sight refresh'
|
||||||
|
Assert-Contains $fragmentText 'foreach (var grid in Data.SightRefreshGrids)' 'new sight grid iteration'
|
||||||
|
Assert-Contains $fragmentText 'gridRenderer?.InstantUpdateGrid(true)' 'new sight grid force refresh'
|
||||||
|
Assert-Contains $fragmentDataText 'public List<GridData> SightRefreshGrids;' 'fragment sight refresh data'
|
||||||
|
Assert-Contains $unitLogicText 'public List<GridData> SuikaFallingSplashSightRefreshGrids;' 'attack info sight refresh data'
|
||||||
|
Assert-Contains $actionText 'sightRefreshGrids: attackInfo.SuikaFallingSplashSightRefreshGrids' 'attack fragment sight refresh handoff'
|
||||||
|
Assert-Contains $actionText 'List<GridData> suikaGroundSightRefreshGrids = null;' 'ground jump sight refresh cache'
|
||||||
|
Assert-Contains $actionText 'sightRefreshGrids: suikaGroundSightRefreshGrids' 'ground jump fragment sight refresh handoff'
|
||||||
|
Assert-Contains $actionText 'FragmentType.SuikaFallingSplash, suikaData' 'ground self-jump fragment'
|
||||||
Assert-Contains $actionText 'TryCreateSuikaFallingSplashFragment' 'attack action fragment switch'
|
Assert-Contains $actionText 'TryCreateSuikaFallingSplashFragment' 'attack action fragment switch'
|
||||||
Assert-Contains $actionText 'FragmentType.SuikaFallingSplash' 'attack action fragment type'
|
Assert-Contains $actionText 'FragmentType.SuikaFallingSplash' 'attack action fragment type'
|
||||||
Assert-Contains $actionText 'visualCollector?.FlushTo(suikaFallingSplashFragment)' 'splash damage visual collection'
|
Assert-Contains $actionText 'visualCollector?.FlushTo(suikaFallingSplashFragment)' 'splash damage visual collection'
|
||||||
|
Assert-Contains $skillText 'TryRepositionUnitWithoutMoveSideEffects(map, suika, target)' 'ground self-jump data-only reposition'
|
||||||
|
Assert-Contains $skillText 'CollectSuikaFallingSplashNewSightGrids' 'Suika sight refresh collector'
|
||||||
Assert-Contains $skillText 'attackInfo.IsSuikaFallingSplash = true;' 'skill attack marker'
|
Assert-Contains $skillText 'attackInfo.IsSuikaFallingSplash = true;' 'skill attack marker'
|
||||||
Assert-Contains $skillText 'attackInfo.SuikaFallingSplashFinalGrid = landingGrid;' 'skill final grid marker'
|
Assert-Contains $skillText 'attackInfo.SuikaFallingSplashFinalGrid = landingGrid;' 'skill final grid marker'
|
||||||
Assert-Contains $skillText 'ExecuteSuikaFallingSplashDamage(map, suika, targetGrid, AnimPhase.AttackImpact + 10)' 'post-impact splash visual phase'
|
Assert-Contains $skillText 'ExecuteSuikaFallingSplashDamage(map, suika, targetGrid, AnimPhase.AttackImpact + 10)' 'post-impact splash visual phase'
|
||||||
|
|
||||||
|
if ($attackGroundFragmentText -match 'SkillType\.SuikaFallingSplash\s*=>\s*ProjectileType\.Bomb') {
|
||||||
|
throw "Suika falling splash animation guardrail failed: FragmentAttackGround must not map SuikaFallingSplash to Bomb projectile."
|
||||||
|
}
|
||||||
|
|
||||||
$method = [regex]::Match($skillText, '(?ms)public static bool TryExecuteSuikaFlyAfterAttack\(MapData map, AttackInfo attackInfo\).*?^\s*private static void ExecuteSuikaFallingSplashDamage')
|
$method = [regex]::Match($skillText, '(?ms)public static bool TryExecuteSuikaFlyAfterAttack\(MapData map, AttackInfo attackInfo\).*?^\s*private static void ExecuteSuikaFallingSplashDamage')
|
||||||
if (-not $method.Success) {
|
if (-not $method.Success) {
|
||||||
throw "Suika falling splash animation guardrail failed: cannot locate TryExecuteSuikaFlyAfterAttack body."
|
throw "Suika falling splash animation guardrail failed: cannot locate TryExecuteSuikaFlyAfterAttack body."
|
||||||
}
|
}
|
||||||
|
|
||||||
$body = $method.Value
|
$body = $method.Value
|
||||||
if ($body -notmatch 'ExecuteSuikaFallingSplashDamage\(map, suika, targetGrid, AnimPhase\.AttackImpact \+ 10\);[\s\S]*?TryRepositionUnitWithoutMoveSideEffects\(map, suika, landingGrid\)[\s\S]*?attackInfo\.IsSuikaFallingSplash = true;[\s\S]*?attackInfo\.SuikaFallingSplashFinalGrid = landingGrid;') {
|
if ($body -notmatch 'ExecuteSuikaFallingSplashDamage\(map, suika, targetGrid, AnimPhase\.AttackImpact \+ 10\);[\s\S]*?sightRefreshGrids = CollectSuikaFallingSplashNewSightGrids\(map, suika, attackInfo\.OriginPlayer,[\s\S]*?landingGrid\);[\s\S]*?TryRepositionUnitWithoutMoveSideEffects\(map, suika, landingGrid\)[\s\S]*?attackInfo\.IsSuikaFallingSplash = true;[\s\S]*?attackInfo\.SuikaFallingSplashFinalGrid = landingGrid;[\s\S]*?attackInfo\.SuikaFallingSplashSightRefreshGrids = sightRefreshGrids;[\s\S]*?UpdateSightByPath') {
|
||||||
throw "Suika falling splash animation guardrail failed: attack-after-splash must settle damage, reposition data, then mark the dedicated animation fragment."
|
throw "Suika falling splash animation guardrail failed: attack-after-splash must settle damage, reposition data, cache new sight grids, then update sight."
|
||||||
|
}
|
||||||
|
|
||||||
|
$groundMethod = [regex]::Match($actionText, '(?ms)public class UnitAttackGroundAction.*?protected override bool Execute\(CommonActionParams actionParams\).*?^\s*public override bool CheckCan')
|
||||||
|
if (-not $groundMethod.Success) {
|
||||||
|
throw "Suika falling splash animation guardrail failed: cannot locate UnitAttackGroundAction execute body."
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($groundMethod.Value -notmatch 'suikaGroundSightRefreshGrids = HakureiNorwayHeroSkillUtil\.CollectSuikaFallingSplashNewSightGrids[\s\S]*?unit1\.AttackGroundExecute\(actionParams\.MapData, targetGrid, out animSkillData\)[\s\S]*?sightRefreshGrids: suikaGroundSightRefreshGrids') {
|
||||||
|
throw "Suika falling splash animation guardrail failed: ground self-jump must cache sight grids before AttackGroundExecute updates sight, then pass them into the Suika fragment."
|
||||||
}
|
}
|
||||||
|
|
||||||
$fragmentMethod = [regex]::Match($fragmentText, '(?ms)public class FragmentSuikaFallingSplash.*?^\s*public override void OnUpdate')
|
$fragmentMethod = [regex]::Match($fragmentText, '(?ms)public class FragmentSuikaFallingSplash.*?^\s*public override void OnUpdate')
|
||||||
@ -69,8 +104,8 @@ if (-not $fragmentMethod.Success) {
|
|||||||
throw "Suika falling splash animation guardrail failed: cannot locate FragmentSuikaFallingSplash body."
|
throw "Suika falling splash animation guardrail failed: cannot locate FragmentSuikaFallingSplash body."
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($fragmentMethod.Value -notmatch 'UnitAtomAnimType\.ParabolaMove[\s\S]*?PlayTargetAttackImpact\(\);[\s\S]*?PlayLandingImpact\(\);[\s\S]*?AnimPhase\.AttackImpact \+ 20[\s\S]*?UnitAtomAnimType\.Move[\s\S]*?AnimPhase\.Settle') {
|
if ($fragmentMethod.Value -notmatch 'UnitAtomAnimParabolaMoveData[\s\S]*?JumpHeight[\s\S]*?JumpDuration[\s\S]*?PlayTargetAttackImpact\(\);[\s\S]*?PlayLandingImpact\(\);[\s\S]*?AnimPhase\.AttackImpact \+ 15[\s\S]*?SplashImpactPause[\s\S]*?AnimPhase\.AttackImpact \+ 20[\s\S]*?UnitAtomAnimType\.Move[\s\S]*?AnimPhase\.Settle') {
|
||||||
throw "Suika falling splash animation guardrail failed: fragment must play parabola, impact, optional final move, then settle refresh."
|
throw "Suika falling splash animation guardrail failed: fragment must play a high, slow parabola, impact/splash pause, optional final move, then settle refresh."
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host "Suika falling splash animation guardrail passed."
|
Write-Host "Suika falling splash animation guardrail passed."
|
||||||
|
|||||||
Binary file not shown.
File diff suppressed because one or more lines are too long
@ -1493,7 +1493,7 @@ MonoBehaviour:
|
|||||||
- SkillType: 111
|
- SkillType: 111
|
||||||
SkillViewType: 2
|
SkillViewType: 2
|
||||||
SkillName: "\u94F6\u4E4B\u8DF3\u8DC3"
|
SkillName: "\u94F6\u4E4B\u8DF3\u8DC3"
|
||||||
SkillDesc: "\u53EF\u4EE5\u79FB\u52A8\u81F3\u4EFB\u610F**<\u5DF1\u65B9\u82F1\u96C4>**1\u683C\u8303\u56F4\u5185\uFF0C\u5E76\u4F7F**<1\u683C\u8303\u56F4\u5185>**\u7684**<\u5DF1\u65B9\u82F1\u96C4>**\u83B7\u5F97**<\u5973\u4EC6\u957F\u62A4\u4F51>**\u3002\u540C\u56DE\u5408\u5185\u591A\u6B21\u4F7F\u7528\u4F1A\u7D2F\u8BA1\u5C42\u6570\u3002\u6BCF\u6B21**<\u94F6\u4E4B\u8DF3\u8DC3>**\u90FD\u4F1A\u53E0\u52A0\u4E0E\u5F53\u524D\u5C42\u6570\u76F8\u540C\u7684**<\u75B2\u52B3>**"
|
SkillDesc: "可以**<传送移动>**至任意**<己方英雄>**1格范围内,并使**<1格范围内>**的**<己方英雄>**获得**<女仆长护佑>**。同回合内多次使用会累计层数。每次**<银之跳跃>**都会叠加与当前层数相同的**<疲劳>**"
|
||||||
NotShow: 0
|
NotShow: 0
|
||||||
ShowOnUnitMono: 0
|
ShowOnUnitMono: 0
|
||||||
SkillIcon: {fileID: 21300000, guid: f5cb587a9626a694b885c473e6c3fe6d, type: 3}
|
SkillIcon: {fileID: 21300000, guid: f5cb587a9626a694b885c473e6c3fe6d, type: 3}
|
||||||
@ -1521,7 +1521,7 @@ MonoBehaviour:
|
|||||||
- SkillType: 113
|
- SkillType: 113
|
||||||
SkillViewType: 2
|
SkillViewType: 2
|
||||||
SkillName: "\u54B2\u591C\u7684\u4E16\u754C"
|
SkillName: "\u54B2\u591C\u7684\u4E16\u754C"
|
||||||
SkillDesc: "\u54B2\u591C\u51FB\u6740\u5355\u4F4D\u65F6\uFF0C\u53EF\u4EE5\u518D\u6B21\u8FDB\u884C\u79FB\u52A8\u5E76\u4F7F\u7528**<\u94F6\u4E4B\u8DF3\u8DC3>**\u3002"
|
SkillDesc: "咲夜击杀单位时,获得**<移动行动点>**并可以再次使用**<银之跳跃>**。"
|
||||||
NotShow: 0
|
NotShow: 0
|
||||||
ShowOnUnitMono: 0
|
ShowOnUnitMono: 0
|
||||||
SkillIcon: {fileID: 21300000, guid: dbf7a694fcc82734b9cccae0da91a35c, type: 3}
|
SkillIcon: {fileID: 21300000, guid: dbf7a694fcc82734b9cccae0da91a35c, type: 3}
|
||||||
@ -1967,7 +1967,7 @@ MonoBehaviour:
|
|||||||
- SkillType: 180
|
- SkillType: 180
|
||||||
SkillViewType: 1
|
SkillViewType: 1
|
||||||
SkillName: "\u9AD8\u5929\u539F\u6025\u884C"
|
SkillName: "\u9AD8\u5929\u539F\u6025\u884C"
|
||||||
SkillDesc: "\u53EF\u4EE5\u5728\u4EFB\u610F\u6211\u65B9**<\u57CE\u5E02\u4E2D\u5FC3>**\u548C**<\u5929\u72D7\u9152\u9986>**\u95F4\u4F20\u9001\u3002\u53EA\u80FD\u5728**<\u5C71\u8109>**\u4E4B\u95F4\u79FB\u52A8\u3002"
|
SkillDesc: "可以在任意我方**<城市中心>**和**<天狗酒馆>**间**<传送移动>**。只能在**<山脉>**之间移动。"
|
||||||
NotShow: 0
|
NotShow: 0
|
||||||
ShowOnUnitMono: 0
|
ShowOnUnitMono: 0
|
||||||
SkillIcon: {fileID: 21300000, guid: 8a0140bbadde3444d821374ce2874af5, type: 3}
|
SkillIcon: {fileID: 21300000, guid: 8a0140bbadde3444d821374ce2874af5, type: 3}
|
||||||
@ -3760,7 +3760,7 @@ MonoBehaviour:
|
|||||||
- SkillType: 288
|
- SkillType: 288
|
||||||
SkillViewType: 2
|
SkillViewType: 2
|
||||||
SkillName: "\u6DF1\u79D8\u6295\u5C04"
|
SkillName: "\u6DF1\u79D8\u6295\u5C04"
|
||||||
SkillDesc: "\u79FB\u52A8\u540E\u5411\u4E0D\u540C\u5730\u5F62\u53D1\u5C04**<\u7075\u5F02\u73E0>**\uFF0C\u968F\u7740\u7B49\u7EA7\u589E\u957F\u53EF\u4EE5\u53D1\u5C04**<\u632A\u5A01\u4E4B\u73E0>**\uFF0C**<\u4E39\u9EA6\u4E4B\u73E0>**\u4EE5\u53CA**<\u82F1\u683C\u5170\u4E4B\u73E0>**\u3002\u53EF\u5728**<\u7075\u5F02\u73E0>**\u9644\u8FD1\u4F20\u9001\u3002"
|
SkillDesc: "**<主动移动>**或**<传送移动>**后可向不同地形发射**<灵异珠>**,随着等级增长(Lv1/Lv2/Lv3)可以发射**<挪威之珠>**,**<丹麦之珠>**以及**<英格兰之珠>**。可在**<灵异珠>**附近**<传送移动>**。"
|
||||||
NotShow: 0
|
NotShow: 0
|
||||||
ShowOnUnitMono: 0
|
ShowOnUnitMono: 0
|
||||||
SkillIcon: {fileID: 21300000, guid: 7c846219dc9d4435a2e756c7e6be0508, type: 3}
|
SkillIcon: {fileID: 21300000, guid: 7c846219dc9d4435a2e756c7e6be0508, type: 3}
|
||||||
@ -3872,7 +3872,7 @@ MonoBehaviour:
|
|||||||
- SkillType: 296
|
- SkillType: 296
|
||||||
SkillViewType: 4
|
SkillViewType: 4
|
||||||
SkillName: "\u543D\u5F62\u77F3\u5B88"
|
SkillName: "\u543D\u5F62\u77F3\u5B88"
|
||||||
SkillDesc: "\u83B7\u5F97\u989D\u5916\u9632\u5FA1\u548C\u4F24\u5BB3\u51CF\u514D(\u6570\u989D\u4E0E**<\u82F1\u96C4\u7B49\u7EA7>**\u76F8\u540C)\uFF0C\u5E76\u4E3A\u9644\u8FD1\u53CB\u65B9\u63D0\u4F9B\u989D\u5916\u9632\u5FA1\u3002\u4E3B\u52A8\u79FB\u52A8\u6216\u4E3B\u52A8\u653B\u51FB\u540E\u81EA\u52A8\u89E3\u9664\u8BE5\u72B6\u6001\u3002"
|
SkillDesc: "获得额外防御,获得伤害减免(数额与**<英雄等级>**相同),无法反击,为附近友方提供额外防御(不包括**<高丽野阿吽>**)。**<主动移动>**或**<主动攻击>**后自动解除该状态。"
|
||||||
NotShow: 0
|
NotShow: 0
|
||||||
ShowOnUnitMono: 0
|
ShowOnUnitMono: 0
|
||||||
SkillIcon: {fileID: 21300000, guid: a994762e362347569aaac57eda527bbd, type: 3}
|
SkillIcon: {fileID: 21300000, guid: a994762e362347569aaac57eda527bbd, type: 3}
|
||||||
@ -4054,7 +4054,7 @@ MonoBehaviour:
|
|||||||
- SkillType: 330
|
- SkillType: 330
|
||||||
SkillViewType: 2
|
SkillViewType: 2
|
||||||
SkillName: "\u543D\u5F62\u77F3\u5B88"
|
SkillName: "\u543D\u5F62\u77F3\u5B88"
|
||||||
SkillDesc: "\u53EF\u4E3B\u52A8\u8FDB\u5165**<\u543D\u5F62\u77F3\u5B88>**\uFF1B\u82E5\u56DE\u5408\u7ED3\u675F\u65F6\u4ECD\u6709\u884C\u52A8\u70B9\uFF0C\u4F1A\u81EA\u52A8\u8FDB\u5165**<\u543D\u5F62\u77F3\u5B88>**\u3002**<\u543D\u5F62\u77F3\u5B88>**\u72B6\u6001\u4E0B\u83B7\u5F97\u989D\u5916\u7684\u9632\u5FA1\uFF0C\u6240\u53D7\u4EFB\u610F\u4F24\u5BB3\u83B7\u5F97\u51CF\u514D(\u51CF\u514D\u6570\u989D\u4E0E**<\u82F1\u96C4\u7B49\u7EA7>**\u76F8\u540C)\uFF0C\u4F7F\u5468\u56F4\u53CB\u65B9\u5355\u4F4D\u83B7\u5F97**<\u72DB\u72AC\u7684\u5B88\u62A4>**\u3002"
|
SkillDesc: "可主动进入**<吽形石守>**;若回合结束时仍有行动点,会自动进入**<吽形石守>**。"
|
||||||
NotShow: 0
|
NotShow: 0
|
||||||
ShowOnUnitMono: 0
|
ShowOnUnitMono: 0
|
||||||
SkillIcon: {fileID: 21300000, guid: a994762e362347569aaac57eda527bbd, type: 3}
|
SkillIcon: {fileID: 21300000, guid: a994762e362347569aaac57eda527bbd, type: 3}
|
||||||
@ -4082,7 +4082,7 @@ MonoBehaviour:
|
|||||||
- SkillType: 332
|
- SkillType: 332
|
||||||
SkillViewType: 4
|
SkillViewType: 4
|
||||||
SkillName: "\u963F\u543D\u53C2\u9053"
|
SkillName: "\u963F\u543D\u53C2\u9053"
|
||||||
SkillDesc: "\u4F4D\u4E8E**<\u9AD8\u4E3D\u91CE\u963F\u543D>**\u9644\u8FD1\u65F6\uFF0C\u53EF\u4F20\u9001\u79FB\u52A8\u5230\u53E6\u4E00\u53EA**<\u9AD8\u4E3D\u91CE\u963F\u543D>**\u9644\u8FD1\u3002"
|
SkillDesc: "位于**<高丽野阿吽>**附近时,可**<传送移动>**到另一只**<高丽野阿吽>**附近。"
|
||||||
NotShow: 0
|
NotShow: 0
|
||||||
ShowOnUnitMono: 0
|
ShowOnUnitMono: 0
|
||||||
SkillIcon: {fileID: 21300000, guid: 4e8a40912d3d450c92996e337cad1067, type: 3}
|
SkillIcon: {fileID: 21300000, guid: 4e8a40912d3d450c92996e337cad1067, type: 3}
|
||||||
@ -4292,7 +4292,7 @@ MonoBehaviour:
|
|||||||
- SkillType: 320
|
- SkillType: 320
|
||||||
SkillViewType: 1
|
SkillViewType: 1
|
||||||
SkillName: "\u6781\u5149\u884C\u6B4C"
|
SkillName: "\u6781\u5149\u884C\u6B4C"
|
||||||
SkillDesc: "\u79FB\u52A8\u65F6\u4E3A\u5468\u56F41\u683C\u5185\u53CB\u65B9\u5355\u4F4D\u6062\u590D2\u70B9\u751F\u547D\uFF1B\u5468\u56F41\u683C\u5185\u5355\u4F4D\u6B7B\u4EA1\u65F6\uFF0C\u81EA\u8EAB\u6062\u590D5\u70B9\u751F\u547D\u3002"
|
SkillDesc: "**<主动移动>**时为周围1格内**<友方单位>**恢复2点生命;周围1格内**<友方单位>**死亡时,自身恢复5点生命。"
|
||||||
NotShow: 0
|
NotShow: 0
|
||||||
ShowOnUnitMono: 0
|
ShowOnUnitMono: 0
|
||||||
SkillIcon: {fileID: 21300000, guid: c1262ff24c1847a3b0695c0471bfbdcf, type: 3}
|
SkillIcon: {fileID: 21300000, guid: c1262ff24c1847a3b0695c0471bfbdcf, type: 3}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -1493,7 +1493,7 @@ MonoBehaviour:
|
|||||||
- SkillType: 111
|
- SkillType: 111
|
||||||
SkillViewType: 2
|
SkillViewType: 2
|
||||||
SkillName: 2289
|
SkillName: 2289
|
||||||
SkillDesc: 19580
|
SkillDesc: 22031
|
||||||
NotShow: 0
|
NotShow: 0
|
||||||
ShowOnUnitMono: 0
|
ShowOnUnitMono: 0
|
||||||
SkillIcon: {fileID: 21300000, guid: f5cb587a9626a694b885c473e6c3fe6d, type: 3}
|
SkillIcon: {fileID: 21300000, guid: f5cb587a9626a694b885c473e6c3fe6d, type: 3}
|
||||||
@ -1521,7 +1521,7 @@ MonoBehaviour:
|
|||||||
- SkillType: 113
|
- SkillType: 113
|
||||||
SkillViewType: 2
|
SkillViewType: 2
|
||||||
SkillName: 2293
|
SkillName: 2293
|
||||||
SkillDesc: 2294
|
SkillDesc: 22032
|
||||||
NotShow: 0
|
NotShow: 0
|
||||||
ShowOnUnitMono: 0
|
ShowOnUnitMono: 0
|
||||||
SkillIcon: {fileID: 21300000, guid: dbf7a694fcc82734b9cccae0da91a35c, type: 3}
|
SkillIcon: {fileID: 21300000, guid: dbf7a694fcc82734b9cccae0da91a35c, type: 3}
|
||||||
@ -1964,7 +1964,7 @@ MonoBehaviour:
|
|||||||
- SkillType: 180
|
- SkillType: 180
|
||||||
SkillViewType: 1
|
SkillViewType: 1
|
||||||
SkillName: 16640
|
SkillName: 16640
|
||||||
SkillDesc: 17053
|
SkillDesc: 22033
|
||||||
NotShow: 0
|
NotShow: 0
|
||||||
ShowOnUnitMono: 0
|
ShowOnUnitMono: 0
|
||||||
SkillIcon: {fileID: 21300000, guid: 8a0140bbadde3444d821374ce2874af5, type: 3}
|
SkillIcon: {fileID: 21300000, guid: 8a0140bbadde3444d821374ce2874af5, type: 3}
|
||||||
@ -3755,7 +3755,7 @@ MonoBehaviour:
|
|||||||
- SkillType: 288
|
- SkillType: 288
|
||||||
SkillViewType: 2
|
SkillViewType: 2
|
||||||
SkillName: 21640
|
SkillName: 21640
|
||||||
SkillDesc: 21632
|
SkillDesc: 22034
|
||||||
NotShow: 0
|
NotShow: 0
|
||||||
ShowOnUnitMono: 0
|
ShowOnUnitMono: 0
|
||||||
SkillIcon: {fileID: 21300000, guid: 7c846219dc9d4435a2e756c7e6be0508, type: 3}
|
SkillIcon: {fileID: 21300000, guid: 7c846219dc9d4435a2e756c7e6be0508, type: 3}
|
||||||
@ -3867,7 +3867,7 @@ MonoBehaviour:
|
|||||||
- SkillType: 296
|
- SkillType: 296
|
||||||
SkillViewType: 4
|
SkillViewType: 4
|
||||||
SkillName: 21502
|
SkillName: 21502
|
||||||
SkillDesc: 21828
|
SkillDesc: 22035
|
||||||
NotShow: 0
|
NotShow: 0
|
||||||
ShowOnUnitMono: 0
|
ShowOnUnitMono: 0
|
||||||
SkillIcon: {fileID: 21300000, guid: a994762e362347569aaac57eda527bbd, type: 3}
|
SkillIcon: {fileID: 21300000, guid: a994762e362347569aaac57eda527bbd, type: 3}
|
||||||
@ -4049,7 +4049,7 @@ MonoBehaviour:
|
|||||||
- SkillType: 330
|
- SkillType: 330
|
||||||
SkillViewType: 2
|
SkillViewType: 2
|
||||||
SkillName: 21502
|
SkillName: 21502
|
||||||
SkillDesc: 21833
|
SkillDesc: 22036
|
||||||
NotShow: 0
|
NotShow: 0
|
||||||
ShowOnUnitMono: 0
|
ShowOnUnitMono: 0
|
||||||
SkillIcon: {fileID: 21300000, guid: a994762e362347569aaac57eda527bbd, type: 3}
|
SkillIcon: {fileID: 21300000, guid: a994762e362347569aaac57eda527bbd, type: 3}
|
||||||
@ -4077,7 +4077,7 @@ MonoBehaviour:
|
|||||||
- SkillType: 332
|
- SkillType: 332
|
||||||
SkillViewType: 4
|
SkillViewType: 4
|
||||||
SkillName: 21844
|
SkillName: 21844
|
||||||
SkillDesc: 21845
|
SkillDesc: 22037
|
||||||
NotShow: 0
|
NotShow: 0
|
||||||
ShowOnUnitMono: 0
|
ShowOnUnitMono: 0
|
||||||
SkillIcon: {fileID: 21300000, guid: 4e8a40912d3d450c92996e337cad1067, type: 3}
|
SkillIcon: {fileID: 21300000, guid: 4e8a40912d3d450c92996e337cad1067, type: 3}
|
||||||
@ -4287,7 +4287,7 @@ MonoBehaviour:
|
|||||||
- SkillType: 320
|
- SkillType: 320
|
||||||
SkillViewType: 1
|
SkillViewType: 1
|
||||||
SkillName: 21663
|
SkillName: 21663
|
||||||
SkillDesc: 21649
|
SkillDesc: 22038
|
||||||
NotShow: 0
|
NotShow: 0
|
||||||
ShowOnUnitMono: 0
|
ShowOnUnitMono: 0
|
||||||
SkillIcon: {fileID: 21300000, guid: c1262ff24c1847a3b0695c0471bfbdcf, type: 3}
|
SkillIcon: {fileID: 21300000, guid: c1262ff24c1847a3b0695c0471bfbdcf, type: 3}
|
||||||
|
|||||||
@ -42,20 +42,24 @@ namespace TH1_Anim.Fragments
|
|||||||
SkillType.SumirekoDenmarkOrbSwapAttackDefense or
|
SkillType.SumirekoDenmarkOrbSwapAttackDefense or
|
||||||
SkillType.SumirekoEnglandOrbDamageProxy => ProjectileType.SumirekoOccultOrb,
|
SkillType.SumirekoEnglandOrbDamageProxy => ProjectileType.SumirekoOccultOrb,
|
||||||
SkillType.KasenBeastGuideOwner or SkillType.KasenBeastGuideAura or
|
SkillType.KasenBeastGuideOwner or SkillType.KasenBeastGuideAura or
|
||||||
SkillType.KasenBeastGuideGrid => ProjectileType.ReimuAttack,
|
SkillType.KasenBeastGuideGrid => ProjectileType.ReimuAttack,
|
||||||
SkillType.SuikaFallingSplash => ProjectileType.Bomb,
|
|
||||||
_ => ProjectileType.Bomb
|
_ => ProjectileType.Bomb
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!Table.Instance.ProjectileTypeDataAssets.GetProjectileTypeInfo(_projectileType, out _attackInfo))
|
if (Data.SkillType != SkillType.SuikaFallingSplash &&
|
||||||
|
!Table.Instance.ProjectileTypeDataAssets.GetProjectileTypeInfo(_projectileType, out _attackInfo))
|
||||||
{
|
{
|
||||||
State = FragmentState.Wrong;
|
State = FragmentState.Wrong;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_step1_start = 0;
|
_step1_start = 0;
|
||||||
_step2_start = _step1_start + _attackInfo.AnimTime;
|
_step2_start = Data.SkillType == SkillType.SuikaFallingSplash
|
||||||
Duration = _step2_start + (_attackInfo.ProjectileType == ProjectileType.Melee ? animTable.AttackReturnAnimTime : 0);
|
? 0f
|
||||||
|
: _step1_start + _attackInfo.AnimTime;
|
||||||
|
Duration = Data.SkillType == SkillType.SuikaFallingSplash
|
||||||
|
? 0.05f
|
||||||
|
: _step2_start + (_attackInfo.ProjectileType == ProjectileType.Melee ? animTable.AttackReturnAnimTime : 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,6 +80,8 @@ namespace TH1_Anim.Fragments
|
|||||||
if (progressTime >= _step1_start && !_step1_attack)
|
if (progressTime >= _step1_start && !_step1_attack)
|
||||||
{
|
{
|
||||||
_step1_attack = true;
|
_step1_attack = true;
|
||||||
|
if (Data.SkillType == SkillType.SuikaFallingSplash)
|
||||||
|
return;
|
||||||
|
|
||||||
var originPos = Data.OriginGrid.Pos.V2();
|
var originPos = Data.OriginGrid.Pos.V2();
|
||||||
var targetPos = Data.TargetGrid.Pos.V2();
|
var targetPos = Data.TargetGrid.Pos.V2();
|
||||||
@ -113,6 +119,9 @@ namespace TH1_Anim.Fragments
|
|||||||
Data.TargetGrid.Renderer(Main.MapData)?.PlayVFXInSight(
|
Data.TargetGrid.Renderer(Main.MapData)?.PlayVFXInSight(
|
||||||
new GridVFXParams(GridVFXType.SkillIcon, Data.SkillType, skillIconUnitFullType));
|
new GridVFXParams(GridVFXType.SkillIcon, Data.SkillType, skillIconUnitFullType));
|
||||||
break;
|
break;
|
||||||
|
case SkillType.SuikaFallingSplash:
|
||||||
|
Data.TargetGrid.Renderer(Main.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -293,6 +293,9 @@ namespace TH1_Anim
|
|||||||
public int AttackDmg;
|
public int AttackDmg;
|
||||||
public bool TargetKilled;
|
public bool TargetKilled;
|
||||||
public bool TargetCanNotBeKilled;
|
public bool TargetCanNotBeKilled;
|
||||||
|
public bool HasAttackTarget;
|
||||||
|
public bool IsGroundLanding;
|
||||||
|
public List<GridData> SightRefreshGrids;
|
||||||
public List<FragmentStep> SplashSteps;
|
public List<FragmentStep> SplashSteps;
|
||||||
|
|
||||||
public FragmentSuikaFallingSplashData(
|
public FragmentSuikaFallingSplashData(
|
||||||
@ -307,7 +310,10 @@ namespace TH1_Anim
|
|||||||
int attackDmg,
|
int attackDmg,
|
||||||
bool targetKilled,
|
bool targetKilled,
|
||||||
bool targetCanNotBeKilled,
|
bool targetCanNotBeKilled,
|
||||||
List<FragmentStep> splashSteps) : base(FragmentType.SuikaFallingSplash)
|
List<FragmentStep> splashSteps,
|
||||||
|
bool hasAttackTarget = true,
|
||||||
|
bool isGroundLanding = false,
|
||||||
|
List<GridData> sightRefreshGrids = null) : base(FragmentType.SuikaFallingSplash)
|
||||||
{
|
{
|
||||||
SuikaRenderer = suikaRenderer;
|
SuikaRenderer = suikaRenderer;
|
||||||
TargetUnitRenderer = targetUnitRenderer;
|
TargetUnitRenderer = targetUnitRenderer;
|
||||||
@ -321,6 +327,9 @@ namespace TH1_Anim
|
|||||||
TargetKilled = targetKilled;
|
TargetKilled = targetKilled;
|
||||||
TargetCanNotBeKilled = targetCanNotBeKilled;
|
TargetCanNotBeKilled = targetCanNotBeKilled;
|
||||||
SplashSteps = splashSteps;
|
SplashSteps = splashSteps;
|
||||||
|
HasAttackTarget = hasAttackTarget;
|
||||||
|
IsGroundLanding = isGroundLanding;
|
||||||
|
SightRefreshGrids = sightRefreshGrids;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,6 +11,12 @@ namespace TH1_Anim.Fragments
|
|||||||
{
|
{
|
||||||
public class FragmentSuikaFallingSplash : FragmentBase
|
public class FragmentSuikaFallingSplash : FragmentBase
|
||||||
{
|
{
|
||||||
|
private const float JumpDuration = 1.1f;
|
||||||
|
private const float JumpHeight = 18f;
|
||||||
|
private const float FinalMoveDuration = 0.35f;
|
||||||
|
private const float SplashImpactPause = 0.2f;
|
||||||
|
private const float GroundLandingImpactDuration = 0.2f;
|
||||||
|
|
||||||
public FragmentSuikaFallingSplashData Data;
|
public FragmentSuikaFallingSplashData Data;
|
||||||
|
|
||||||
public FragmentSuikaFallingSplash(FragmentSuikaFallingSplashData data) : base()
|
public FragmentSuikaFallingSplash(FragmentSuikaFallingSplashData data) : base()
|
||||||
@ -26,16 +32,18 @@ namespace TH1_Anim.Fragments
|
|||||||
var animTable = Table.Instance.AnimDataAssets;
|
var animTable = Table.Instance.AnimDataAssets;
|
||||||
InitSteps();
|
InitSteps();
|
||||||
|
|
||||||
AddStep(AnimPhase.AttackStart, animTable.AttackAnimTime, () =>
|
AddStep(AnimPhase.AttackStart, JumpDuration, () =>
|
||||||
{
|
{
|
||||||
var animData = UnitAtomAnimDataFactory.Create(UnitAtomAnimType.ParabolaMove,
|
var animData = new UnitAtomAnimParabolaMoveData(
|
||||||
Data.OriginGrid.Pos.V2(), Data.TargetGrid.Pos.V2());
|
Data.OriginGrid.Pos.V2(), Data.TargetGrid.Pos.V2(), JumpHeight, JumpDuration);
|
||||||
Data.SuikaRenderer.AnimManager.EnqueueAnim(UnitAtomAnimType.ParabolaMove, animData);
|
Data.SuikaRenderer.AnimManager.EnqueueAnim(UnitAtomAnimType.ParabolaMove, animData);
|
||||||
Data.OriginGrid.Renderer(Main.MapData)?.InstantUpdateGrid();
|
Data.OriginGrid.Renderer(Main.MapData)?.InstantUpdateGrid();
|
||||||
AudioManager.Instance.PlayAudio("SFX/UNIT_attack");
|
AudioManager.Instance.PlayAudio("SFX/UNIT_attack");
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep(AnimPhase.AttackImpact, animTable.BounceDownTime + animTable.BounceUpTime, () =>
|
AddStep(AnimPhase.AttackImpact,
|
||||||
|
Data.IsGroundLanding ? GroundLandingImpactDuration : animTable.BounceDownTime + animTable.BounceUpTime,
|
||||||
|
() =>
|
||||||
{
|
{
|
||||||
PlayTargetAttackImpact();
|
PlayTargetAttackImpact();
|
||||||
PlayLandingImpact();
|
PlayLandingImpact();
|
||||||
@ -47,13 +55,16 @@ namespace TH1_Anim.Fragments
|
|||||||
AddStep(AnimPhase.AttackImpact + 10, step.Duration, step.Execute);
|
AddStep(AnimPhase.AttackImpact + 10, step.Duration, step.Execute);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Data.IsGroundLanding)
|
||||||
|
AddStep(AnimPhase.AttackImpact + 15, SplashImpactPause, () => { });
|
||||||
|
|
||||||
if (!Data.TargetKilled && Data.FinalGrid.Id != Data.TargetGrid.Id)
|
if (!Data.TargetKilled && Data.FinalGrid.Id != Data.TargetGrid.Id)
|
||||||
{
|
{
|
||||||
AddStep(AnimPhase.AttackImpact + 20, animTable.MoveAnimTime, () =>
|
AddStep(AnimPhase.AttackImpact + 20, FinalMoveDuration, () =>
|
||||||
{
|
{
|
||||||
var path = new List<Vector2Int> { Data.TargetGrid.Pos.V2(), Data.FinalGrid.Pos.V2() };
|
var path = new List<Vector2Int> { Data.TargetGrid.Pos.V2(), Data.FinalGrid.Pos.V2() };
|
||||||
var animData = UnitAtomAnimDataFactory.Create(UnitAtomAnimType.Move, Data.TargetGrid.Pos.V2(),
|
var animData = new UnitAtomAnimMoveData(Data.TargetGrid.Pos.V2(), Data.FinalGrid.Pos.V2(), path,
|
||||||
Data.FinalGrid.Pos.V2(), path);
|
FinalMoveDuration);
|
||||||
Data.SuikaRenderer.AnimManager.EnqueueAnim(UnitAtomAnimType.Move, animData);
|
Data.SuikaRenderer.AnimManager.EnqueueAnim(UnitAtomAnimType.Move, animData);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -65,6 +76,13 @@ namespace TH1_Anim.Fragments
|
|||||||
private void PlayTargetAttackImpact()
|
private void PlayTargetAttackImpact()
|
||||||
{
|
{
|
||||||
var targetGridRenderer = Data.TargetGrid.Renderer(Main.MapData);
|
var targetGridRenderer = Data.TargetGrid.Renderer(Main.MapData);
|
||||||
|
if (!Data.HasAttackTarget)
|
||||||
|
{
|
||||||
|
targetGridRenderer?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog));
|
||||||
|
targetGridRenderer?.InstantUpdateGrid();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (Data.TargetKilled)
|
if (Data.TargetKilled)
|
||||||
{
|
{
|
||||||
Data.TargetUnitRenderer?.Die();
|
Data.TargetUnitRenderer?.Die();
|
||||||
@ -101,6 +119,7 @@ namespace TH1_Anim.Fragments
|
|||||||
Data.OriginGrid.Renderer(Main.MapData)?.InstantUpdateGrid();
|
Data.OriginGrid.Renderer(Main.MapData)?.InstantUpdateGrid();
|
||||||
Data.TargetGrid.Renderer(Main.MapData)?.InstantUpdateGrid();
|
Data.TargetGrid.Renderer(Main.MapData)?.InstantUpdateGrid();
|
||||||
Data.FinalGrid.Renderer(Main.MapData)?.InstantUpdateGrid();
|
Data.FinalGrid.Renderer(Main.MapData)?.InstantUpdateGrid();
|
||||||
|
RefreshLandingSight();
|
||||||
Data.OriginCity?.SetCityRenderer(Main.MapData);
|
Data.OriginCity?.SetCityRenderer(Main.MapData);
|
||||||
Data.TargetCity?.SetCityRenderer(Main.MapData);
|
Data.TargetCity?.SetCityRenderer(Main.MapData);
|
||||||
Data.FinalCity?.SetCityRenderer(Main.MapData);
|
Data.FinalCity?.SetCityRenderer(Main.MapData);
|
||||||
@ -109,6 +128,20 @@ namespace TH1_Anim.Fragments
|
|||||||
MapRenderer.Instance?.UpdateAroundHighlight(Main.MapData, Data.FinalGrid);
|
MapRenderer.Instance?.UpdateAroundHighlight(Main.MapData, Data.FinalGrid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void RefreshLandingSight()
|
||||||
|
{
|
||||||
|
if (Data.SightRefreshGrids == null) return;
|
||||||
|
|
||||||
|
foreach (var grid in Data.SightRefreshGrids)
|
||||||
|
{
|
||||||
|
if (grid == null) continue;
|
||||||
|
var gridRenderer = grid.Renderer(Main.MapData);
|
||||||
|
gridRenderer?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog));
|
||||||
|
gridRenderer?.InstantUpdateGrid(true);
|
||||||
|
MapRenderer.Instance?.UpdateAroundHighlight(Main.MapData, grid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override bool CheckDone(float progressTime)
|
public override bool CheckDone(float progressTime)
|
||||||
{
|
{
|
||||||
return CheckStepsDone(progressTime);
|
return CheckStepsDone(progressTime);
|
||||||
|
|||||||
@ -78,12 +78,15 @@ namespace TH1_Renderer.UnitAtomAnim
|
|||||||
public List<Vector2Int> Path;
|
public List<Vector2Int> Path;
|
||||||
public Vector2Int OriginGridPos;
|
public Vector2Int OriginGridPos;
|
||||||
public Vector2Int TargetGridPos;
|
public Vector2Int TargetGridPos;
|
||||||
|
public float DurationOverride;
|
||||||
|
|
||||||
public UnitAtomAnimMoveData(Vector2Int originGridPos, Vector2Int targetGridPos,List<Vector2Int> path) : base(UnitAtomAnimType.Move)
|
public UnitAtomAnimMoveData(Vector2Int originGridPos, Vector2Int targetGridPos,List<Vector2Int> path,
|
||||||
|
float durationOverride = 0f) : base(UnitAtomAnimType.Move)
|
||||||
{
|
{
|
||||||
Path = path;
|
Path = path;
|
||||||
OriginGridPos = originGridPos;
|
OriginGridPos = originGridPos;
|
||||||
TargetGridPos = targetGridPos;
|
TargetGridPos = targetGridPos;
|
||||||
|
DurationOverride = durationOverride;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,13 +110,16 @@ namespace TH1_Renderer.UnitAtomAnim
|
|||||||
public Vector2Int OriginGridPos;
|
public Vector2Int OriginGridPos;
|
||||||
public Vector2Int TargetGridPos;
|
public Vector2Int TargetGridPos;
|
||||||
public float Height;
|
public float Height;
|
||||||
|
public float Duration;
|
||||||
|
|
||||||
public UnitAtomAnimParabolaMoveData(Vector2Int originGridPos, Vector2Int targetGridPos, float height = 1.2f)
|
public UnitAtomAnimParabolaMoveData(Vector2Int originGridPos, Vector2Int targetGridPos, float height = 18f,
|
||||||
|
float duration = 1.1f)
|
||||||
: base(UnitAtomAnimType.ParabolaMove)
|
: base(UnitAtomAnimType.ParabolaMove)
|
||||||
{
|
{
|
||||||
OriginGridPos = originGridPos;
|
OriginGridPos = originGridPos;
|
||||||
TargetGridPos = targetGridPos;
|
TargetGridPos = targetGridPos;
|
||||||
Height = height;
|
Height = height;
|
||||||
|
Duration = duration;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,6 +25,8 @@ namespace TH1_Anim.UnitAtomAnim
|
|||||||
Duration = Table.Instance.AnimDataAssets.AttackAnimTime;
|
Duration = Table.Instance.AnimDataAssets.AttackAnimTime;
|
||||||
if(_data.Path != null)
|
if(_data.Path != null)
|
||||||
Duration = Table.Instance.AnimDataAssets.AttackAnimTime / 2f * _data.Path.Count;
|
Duration = Table.Instance.AnimDataAssets.AttackAnimTime / 2f * _data.Path.Count;
|
||||||
|
if (_data.DurationOverride > 0f)
|
||||||
|
Duration = _data.DurationOverride;
|
||||||
|
|
||||||
_originPos = Table.Instance.GridPosToWorld(_data.OriginGridPos, "isUnit");
|
_originPos = Table.Instance.GridPosToWorld(_data.OriginGridPos, "isUnit");
|
||||||
_targetPos = Table.Instance.GridPosToWorld(_data.TargetGridPos, "isUnit");
|
_targetPos = Table.Instance.GridPosToWorld(_data.TargetGridPos, "isUnit");
|
||||||
@ -102,7 +104,7 @@ namespace TH1_Anim.UnitAtomAnim
|
|||||||
public override bool OnStart(UnitMono unitMono)
|
public override bool OnStart(UnitMono unitMono)
|
||||||
{
|
{
|
||||||
if (_data == null) return false;
|
if (_data == null) return false;
|
||||||
Duration = Table.Instance.AnimDataAssets.AttackAnimTime;
|
Duration = _data.Duration > 0f ? _data.Duration : 1.1f;
|
||||||
_originPos = Table.Instance.GridPosToWorld(_data.OriginGridPos, "isUnit");
|
_originPos = Table.Instance.GridPosToWorld(_data.OriginGridPos, "isUnit");
|
||||||
_targetPos = Table.Instance.GridPosToWorld(_data.TargetGridPos, "isUnit");
|
_targetPos = Table.Instance.GridPosToWorld(_data.TargetGridPos, "isUnit");
|
||||||
_height = Mathf.Max(0.1f, _data.Height);
|
_height = Mathf.Max(0.1f, _data.Height);
|
||||||
|
|||||||
@ -2874,7 +2874,8 @@ namespace Logic.Action
|
|||||||
attackDmg,
|
attackDmg,
|
||||||
attackInfo.IsKill,
|
attackInfo.IsKill,
|
||||||
targetCanNotBeKilled,
|
targetCanNotBeKilled,
|
||||||
null);
|
null,
|
||||||
|
sightRefreshGrids: attackInfo.SuikaFallingSplashSightRefreshGrids);
|
||||||
fragment = FragmentFactory.Create(FragmentType.SuikaFallingSplash, data);
|
fragment = FragmentFactory.Create(FragmentType.SuikaFallingSplash, data);
|
||||||
return fragment != null;
|
return fragment != null;
|
||||||
}
|
}
|
||||||
@ -2927,6 +2928,7 @@ namespace Logic.Action
|
|||||||
GridData targetGrid = actionParams.GridData;
|
GridData targetGrid = actionParams.GridData;
|
||||||
UnitRenderer originUnitRenderer = null;
|
UnitRenderer originUnitRenderer = null;
|
||||||
GridRenderer targetGridRenderer = null;
|
GridRenderer targetGridRenderer = null;
|
||||||
|
CityData targetCity = null;
|
||||||
|
|
||||||
bool isTrueMap = actionParams.MapData == Main.MapData;
|
bool isTrueMap = actionParams.MapData == Main.MapData;
|
||||||
|
|
||||||
@ -2935,6 +2937,7 @@ namespace Logic.Action
|
|||||||
{
|
{
|
||||||
MapRenderer.Instance.ROUnitMap.TryGetValue(actionParams.UnitData.Id, out originUnitRenderer);
|
MapRenderer.Instance.ROUnitMap.TryGetValue(actionParams.UnitData.Id, out originUnitRenderer);
|
||||||
targetGridRenderer = targetGrid.Renderer(Main.MapData);
|
targetGridRenderer = targetGrid.Renderer(Main.MapData);
|
||||||
|
targetCity = targetGrid.City(Main.MapData, out var city) ? city : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2949,6 +2952,7 @@ namespace Logic.Action
|
|||||||
bool hasSuwakoAttack = unit1.GetSkill(SkillType.SUWAKOATTACK, out var _);
|
bool hasSuwakoAttack = unit1.GetSkill(SkillType.SUWAKOATTACK, out var _);
|
||||||
bool hadSuikaThrowReady = unit1.GetSkill(SkillType.SuikaThrowReady, out _);
|
bool hadSuikaThrowReady = unit1.GetSkill(SkillType.SuikaThrowReady, out _);
|
||||||
bool handledBySkillAttackGround = false;
|
bool handledBySkillAttackGround = false;
|
||||||
|
List<GridData> suikaGroundSightRefreshGrids = null;
|
||||||
|
|
||||||
if (unit1.GetSkill(SkillType.INFILTRATE, out _)
|
if (unit1.GetSkill(SkillType.INFILTRATE, out _)
|
||||||
&& targetGrid.Resource == ResourceType.CityCenter
|
&& targetGrid.Resource == ResourceType.CityCenter
|
||||||
@ -2964,6 +2968,17 @@ namespace Logic.Action
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cache Suika sight before AttackGroundExecute mutates SightGidSet.
|
||||||
|
if (!hasSuwakoAttack && !hadSuikaThrowReady &&
|
||||||
|
HakureiNorwayHeroSkillUtil.CanSuikaFlyToGrid(actionParams.MapData, unit1, targetGrid))
|
||||||
|
{
|
||||||
|
var suikaSightPlayer = actionParams.PlayerData;
|
||||||
|
if (suikaSightPlayer == null)
|
||||||
|
unit1.Player(actionParams.MapData, out suikaSightPlayer);
|
||||||
|
suikaGroundSightRefreshGrids = HakureiNorwayHeroSkillUtil.CollectSuikaFallingSplashNewSightGrids(
|
||||||
|
actionParams.MapData, unit1, suikaSightPlayer, targetGrid);
|
||||||
|
}
|
||||||
|
|
||||||
//处理SUWAKO的地面攻击
|
//处理SUWAKO的地面攻击
|
||||||
if (!hasSuwakoAttack &&
|
if (!hasSuwakoAttack &&
|
||||||
unit1.AttackGroundExecute(actionParams.MapData, targetGrid, out animSkillData))
|
unit1.AttackGroundExecute(actionParams.MapData, targetGrid, out animSkillData))
|
||||||
@ -3020,6 +3035,30 @@ namespace Logic.Action
|
|||||||
(Main.MapData.PlayerMap.SelfPlayerData.Sight.CheckIsInSight(originGrid.Id) ||
|
(Main.MapData.PlayerMap.SelfPlayerData.Sight.CheckIsInSight(originGrid.Id) ||
|
||||||
Main.MapData.PlayerMap.SelfPlayerData.Sight.CheckIsInSight(targetGrid.Id)))
|
Main.MapData.PlayerMap.SelfPlayerData.Sight.CheckIsInSight(targetGrid.Id)))
|
||||||
{
|
{
|
||||||
|
if (animSkillData == SkillType.SuikaFallingSplash && !hadSuikaThrowReady)
|
||||||
|
{
|
||||||
|
var suikaData = new FragmentSuikaFallingSplashData(
|
||||||
|
originUnitRenderer,
|
||||||
|
null,
|
||||||
|
originGrid,
|
||||||
|
targetGrid,
|
||||||
|
targetGrid,
|
||||||
|
city1,
|
||||||
|
null,
|
||||||
|
targetCity,
|
||||||
|
0,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
hasAttackTarget: false,
|
||||||
|
isGroundLanding: true,
|
||||||
|
sightRefreshGrids: suikaGroundSightRefreshGrids);
|
||||||
|
var suikaFragment = FragmentFactory.Create(FragmentType.SuikaFallingSplash, suikaData);
|
||||||
|
PresentationManager.EnqueueTask(new FragmentSequencerTask(suikaFragment));
|
||||||
|
_duration = suikaFragment.Duration;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
var data = new FragmentAttackGroundData(FragmentType.AttackGround, originUnitRenderer,
|
var data = new FragmentAttackGroundData(FragmentType.AttackGround, originUnitRenderer,
|
||||||
targetGridRenderer, originGrid, targetGrid, animSkillData,city1);
|
targetGridRenderer, originGrid, targetGrid, animSkillData,city1);
|
||||||
|
|
||||||
|
|||||||
@ -1733,7 +1733,7 @@ namespace Logic.Skill
|
|||||||
{
|
{
|
||||||
animSkillType = SkillType.SuikaFallingSplash;
|
animSkillType = SkillType.SuikaFallingSplash;
|
||||||
if (!CanSuikaFlyToGrid(map, suika, target)) return false;
|
if (!CanSuikaFlyToGrid(map, suika, target)) return false;
|
||||||
if (!TryMoveUnit(map, suika, target, MoveType.PushMove, playFogVfx: true)) return false;
|
if (!TryRepositionUnitWithoutMoveSideEffects(map, suika, target)) return false;
|
||||||
suika.ClearActionPoint();
|
suika.ClearActionPoint();
|
||||||
var player = suika.Player(map);
|
var player = suika.Player(map);
|
||||||
player?.Sight.UpdateSightByPath(suika, player, target.Pos.V2(), map);
|
player?.Sight.UpdateSightByPath(suika, player, target.Pos.V2(), map);
|
||||||
@ -1775,16 +1775,36 @@ namespace Logic.Skill
|
|||||||
var originGrid = suika.Grid(map);
|
var originGrid = suika.Grid(map);
|
||||||
var originCity = suika.City(map);
|
var originCity = suika.City(map);
|
||||||
var landingCity = landingGrid.City(map, out var city) ? city : null;
|
var landingCity = landingGrid.City(map, out var city) ? city : null;
|
||||||
|
var sightRefreshGrids = CollectSuikaFallingSplashNewSightGrids(map, suika, attackInfo.OriginPlayer,
|
||||||
|
landingGrid);
|
||||||
|
|
||||||
if (!TryRepositionUnitWithoutMoveSideEffects(map, suika, landingGrid)) return false;
|
if (!TryRepositionUnitWithoutMoveSideEffects(map, suika, landingGrid)) return false;
|
||||||
attackInfo.IsSuikaFallingSplash = true;
|
attackInfo.IsSuikaFallingSplash = true;
|
||||||
attackInfo.SuikaFallingSplashFinalGrid = landingGrid;
|
attackInfo.SuikaFallingSplashFinalGrid = landingGrid;
|
||||||
attackInfo.SuikaFallingSplashFinalCity = landingCity;
|
attackInfo.SuikaFallingSplashFinalCity = landingCity;
|
||||||
attackInfo.SuikaFallingSplashOriginCity = originCity;
|
attackInfo.SuikaFallingSplashOriginCity = originCity;
|
||||||
|
attackInfo.SuikaFallingSplashSightRefreshGrids = sightRefreshGrids;
|
||||||
attackInfo.OriginPlayer?.Sight.UpdateSightByPath(suika, attackInfo.OriginPlayer, landingGrid.Pos.V2(), map);
|
attackInfo.OriginPlayer?.Sight.UpdateSightByPath(suika, attackInfo.OriginPlayer, landingGrid.Pos.V2(), map);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<GridData> CollectSuikaFallingSplashNewSightGrids(MapData map, UnitData suika,
|
||||||
|
PlayerData player, GridData landingGrid)
|
||||||
|
{
|
||||||
|
if (map == null || suika == null || player?.Sight == null || landingGrid == null) return null;
|
||||||
|
var range = suika.GetSightRange(map, landingGrid);
|
||||||
|
var gridIds = map.GridMap.GetAroundGridIdList(range, landingGrid);
|
||||||
|
var result = new List<GridData>();
|
||||||
|
foreach (var gid in gridIds)
|
||||||
|
{
|
||||||
|
if (player.Sight.CheckIsInSight(gid)) continue;
|
||||||
|
if (!map.GridMap.GetGridDataByGid(gid, out var grid)) continue;
|
||||||
|
result.Add(grid);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.Count > 0 ? result : null;
|
||||||
|
}
|
||||||
|
|
||||||
private static void ExecuteSuikaFallingSplashDamage(MapData map, UnitData suika, GridData center,
|
private static void ExecuteSuikaFallingSplashDamage(MapData map, UnitData suika, GridData center,
|
||||||
int visualPhase = AnimPhase.Settle)
|
int visualPhase = AnimPhase.Settle)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -68,6 +68,7 @@ namespace Logic
|
|||||||
public GridData SuikaFallingSplashFinalGrid;
|
public GridData SuikaFallingSplashFinalGrid;
|
||||||
public CityData SuikaFallingSplashFinalCity;
|
public CityData SuikaFallingSplashFinalCity;
|
||||||
public CityData SuikaFallingSplashOriginCity;
|
public CityData SuikaFallingSplashOriginCity;
|
||||||
|
public List<GridData> SuikaFallingSplashSightRefreshGrids;
|
||||||
public bool IsSuikaFallingSplash;
|
public bool IsSuikaFallingSplash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user