feat(effect): 实现战斗效果1785、2195、2215、2219并更新文档规则 新增战斗效果1785:N回合内每回合使用技能吸取对手最大体力的1/M, 满体力时额外恢复己方所有不在场精灵O点体力 修复战斗效果2195:当对方回合存在效果时才降低技能优先级,
10 KiB
name, description
| name | description |
|---|---|
| fight-effect-impl | Implement or repair Go fight effects in the Blazing battle system. Use when working in logic/service/fight/effect or nearby boss hooks, especially for missing effect tasks, effect registration, hook selection, delayed/round effects, status application, effect_info_map updates, and package-level validation. |
Fight Effect Impl
Implement effect work in the existing battle framework instead of inventing a parallel pattern.
Workflow
-
Read the task source first. If the request comes from
docs/effect-unimplemented-tasks/, open the task file and extract effect IDs, arg counts, and description text. -
Confirm whether each effect is actually missing. Search for both type names and registrations. Do not rely only on direct
InitEffect(...)grep results. Also inspect shared registration files such as:
logic/service/fight/effect/sterStatusEffects.gologic/service/fight/effect/effect_power_doblue.gologic/service/fight/effect/EffectAttackMiss.gologic/service/fight/effect/EffectPhysicalAttackAddStatus.gologic/service/fight/effect/EffectDefeatTrigger.gologic/service/fight/effect/effect_attr.go
-
Reuse the nearest local pattern. Open effects with similar timing or semantics before writing code. Prefer matching existing hooks, helper bases, registration style, and comments over building a generic abstraction.
-
Choose the hook from battle flow, not from description text alone. Read
logic/service/fight/input/interface.go,logic/service/fight/fightc.go, andlogic/service/fight/loop.gowhen timing is unclear.
Effect Hooks
Use this section when effect timing is unclear.
Core call order
The main references are:
logic/service/fight/input/interface.gologic/service/fight/fightc.gologic/service/fight/loop.go
Typical attack flow inside processSkillAttack and enterturn is:
- defender
SkillHit_ex() - attacker
SkillHit() - attacker
CalculatePre() - attacker
OnSkill() - defender
Damage(...)settles red/fixed/true damage - defender
Skill_Use_ex() - attacker
Skill_Use() - defender
Action_end_ex() - attacker
Action_end() - both sides
TurnEnd()at round end - all live effects
OnBattleEnd()at fight end
Hook selection cheatsheet
-
SkillHit_ex()Use for defender-side pre-hit interception, miss forcing, and hit-rate disruption. -
SkillHit()Use for attacker-side power, crit, or skill-property changes before damage is computed. -
CalculatePre()Use for temporary state rewrites that must exist during power calculation and then be restored. -
OnSkill()Use for on-hit side effects, extra fixed damage setup, healing, status attach, or delayed-effect spawning. -
ActionStartEx()Use for defender-side pre-action gates. -
ActionStart()Use for attacker-side action gating, forced no-action behavior, and same-turn priority-sensitive logic. -
Skill_Use_ex()Use for defender-side after-being-targeted behavior. -
Skill_Use()Use for attacker-side after-using-skill behavior. -
ComparePre()Use for priority changes before turn order is finalized. -
TurnStart()Use for per-round setup or replacing the current round's selected action before execution. -
TurnEnd()Use for countdown or expiry. The default node decrements positive durations and clears zero-duration effects. -
OnBattleEnd()Use only when the effect truly settles at battle end. Confirm any reward path can be persisted from this hook.
Repo-specific cautions
-
EffectCachematters. Parsed skill effects are stored inEffectCachebefore execution. If a first-turn charge effect must suppress the rest of the skill's side effects, explicitly disable sibling cached effects for that turn. -
addSubEffect(...)is lightweight. Readlogic/service/fight/effect/sub_effect_helper.gobefore assuming helper behavior. The current helper forwards IDs and args, but does not automatically apply thedurationargument to the sub-effect instance. -
Team-wide healing is limited by current model. There is no generic battle-target abstraction for friendly bench targets. If the effect heals all owned pets, iterate
AllPetand mutate non-active pets carefully. -
Static task scans can be false positives. Task documents may flag effects as missing even when they already exist in grouped files or shared registration files. Verify before editing.
Implementation Rules
- Prefer existing base structs in
logic/service/fight/effect/sub_effect_helper.gowhen they already match duration behavior. - Verify helper semantics before using them. In this repo, some helpers are thinner than their names suggest.
- For status effects, create them through
InitEffect(input.EffectType.Status, ...)and add them throughAddEffect(...)on the target input. - For healing, use
Input.Heal(...)for the active battler and mutate non-active owned pets only when the current model already stores them inAllPet. - For battle-end rewards or delayed settlement, confirm the hook is actually executed in
loop.gobefore coding against it. - Keep comments short and effect-focused.
Batch Work Rules
When continuing docs/effect-unimplemented-tasks/ in batches:
- Split work by grouped file and assign disjoint write ranges.
- Avoid touching
logic/service/fight/effect/effect_info_map.goduring parallel effect implementation unless the user explicitly asks for description-map updates in the same pass. - Treat task docs as a backlog, not ground truth. A task file may still exist even when some IDs in the slice were already implemented or partially repaired.
- Prefer finishing the easiest grounded IDs in a partial slice instead of repeatedly rescanning the entire slice.
- Keep a clear list of:
- newly implemented IDs,
- already-existing IDs,
- still-partial IDs,
- task docs safe to delete.
Frequent Compile Pitfalls
Before considering a slice done, check these repo-specific issues:
input.InitEffect(...)always needs all three args: effect type, numeric ID, effect instance.- If a new sub-effect type is added, also register the sub-effect explicitly in
init(). SkillEntity.XML.PowerandPriorityareint-based in current generated structs; avoid mixing withint8,int32, orint64arithmetic.- Skill PP on runtime battle state is commonly
uint32; cast carefully when subtracting or restoring PP. model.SkillInfodoes not expose fields likeMaxPPorCategory; look them up throughxmlres.SkillMap[int(skill.ID)].xmlres.Movedoes not expose every runtime field. Use runtime state such asSkillEntity.AttackTimewhen the XML struct lacks a field.input.Inputdoes not always expose nested objects assumed by task text, such asOpp.SkillEntity; verify available runtime fields before coding.- Decimal math must use
alpacadecimalvalues, not raw integer literals. - Large grouped files can accidentally keep stale duplicate
init()registration blocks after manual merges or batch patches. Check the file tail before closing out a slice.
Partial Slice Strategy
When a grouped file is only partially grounded:
- Do not delete the task docs for that slice yet.
- Keep the implemented IDs in place and make the remaining gaps explicit.
- Prefer conservative, repo-shaped implementations over speculative full feature work for heavy system effects.
- Good candidates to finish in partial slices are:
- simple priority modifiers,
- PP-based power changes,
- round-based sub-effects using existing helper bases,
- status immunity or status application patterns that already exist nearby.
- Leave highly coupled systems partial if they appear to depend on larger mechanics not yet modeled in nearby code, such as custom resource tracks or complex transformation states.
Task Doc Deletion
Delete a task file only when one of these is true:
- every effect ID in the task range is now implemented in repo code,
- the IDs already existed and were verified as not missing,
- or the user explicitly accepts documented non-implementation for reserved placeholders.
Do not delete the task doc when the slice is still mixed between implemented and partial IDs.
Common Tasks
Random power or conditional power effects
Use SkillHit() when the effect changes SkillEntity.XML.Power before damage is calculated.
Examples in repo: 139.go, effect_power_doblue.go, 600_605.go.
Hit-time status or side effects
Use OnSkill() when the effect should fire after hit/damage calculation setup and before final damage application is settled.
For direct status application, initialize the status effect from the source input and add it to the opponent.
Round or delayed effects
For multi-turn logic, confirm whether the effect should:
- modify this turn only,
- start next turn,
- trigger when attacked,
- or replace the next selected skill.
For next-turn logic, inspect nearby effects such as 62, 407, 440, 499, 551, 560, and any adjacent ID patterns.
Two-turn charge effects
Preserve the repo's existing battle loop assumptions. A practical pattern is:
- cache the release skill on the first turn,
- suppress first-turn damage/effect output,
- inject the cached skill into the next turn's selected action in
TurnStart, - avoid double PP consumption in
HookPP.
Reward-on-battle-end effects
Check OnBattleEnd() execution in logic/service/fight/loop.go.
If a reward has a daily cap, prefer the shared counter utilities under common/data/share/ over inventing new state.
Validation
Run, at minimum:
cd /workspace/logic && go test ./service/fight/effectcd /workspace/logic && go build ./...
If the user explicitly says tests are not required for the current pass, downgrade validation to:
gofmt -won every edited Go file,- fix current editor/compiler diagnostics for touched files,
- and report that package tests/build were intentionally skipped by user request.
If the task came from docs/effect-unimplemented-tasks/, remove the completed task file when the user asked for it.
Output
When finishing a task, report:
- which effect IDs were truly implemented,
- which IDs already existed and were left untouched,
- validation commands actually run,
- any remaining model limitations or behavior assumptions.