Skip to content

Commit dc7652f

Browse files
committed
test: cover authored reward descriptor precedence
1 parent ca7d2d1 commit dc7652f

2 files changed

Lines changed: 42 additions & 0 deletions

File tree

internal/minimal/shared_world_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9052,6 +9052,47 @@ func TestSharedWorldStaticActorDeathRewardFallsBackToRegisteredFormulaProfileDef
90529052
}
90539053
}
90549054

9055+
func TestSharedWorldStaticActorDeathRewardPrefersAuthoredDescriptorOverRegisteredProfileDefault(t *testing.T) {
9056+
const profile = "practice_authored_reward_override_mob"
9057+
if !worldruntime.RegisterStaticActorCombatProfile(profile, worldruntime.StaticActorCombatProfileDefaults{
9058+
MaxHP: 8,
9059+
DamagePerNormalAttack: 2,
9060+
RespawnDelay: worldruntime.PracticeMobBootstrapRespawnDelay,
9061+
DeathReward: worldruntime.StaticActorDeathReward{Experience: 11, Gold: 7, DropVnums: []uint32{27002}},
9062+
}) {
9063+
t.Fatalf("expected %q profile registration to succeed", profile)
9064+
}
9065+
t.Cleanup(func() { worldruntime.UnregisterStaticActorCombatProfileForTest(profile) })
9066+
9067+
runtime := newSharedWorldRegistry()
9068+
actor := worldruntime.StaticEntity{
9069+
Entity: worldruntime.Entity{ID: 0x01050245, Kind: worldruntime.EntityKindStaticActor, VID: 0x01050245, Name: "AuthoredRewardOverrideMob"},
9070+
Position: worldruntime.NewPosition(bootstrapMapIndex, 1200, 2200),
9071+
RaceNum: 20350,
9072+
CombatProfile: profile,
9073+
CombatKind: profile,
9074+
SpawnGroupRef: "practice.authored_reward_override_mob",
9075+
}
9076+
if _, ok := runtime.registerStaticActor(actor.Entity.ID, actor.Entity.Name, actor.Position.MapIndex, actor.Position.X, actor.Position.Y, actor.RaceNum, "", "", actor.CombatKind, actor.SpawnGroupRef, worldruntime.StaticActorDeathReward{Experience: 101, Gold: 55, DropVnums: []uint32{27004, 27003}}); !ok {
9077+
t.Fatal("expected authored reward override mob registration to succeed")
9078+
}
9079+
9080+
storedActor, ok := runtime.entities.StaticActor(actor.Entity.ID)
9081+
if !ok {
9082+
t.Fatal("expected authored reward override mob to remain registered")
9083+
}
9084+
reward := runtime.staticActorDeathRewardLocked(storedActor)
9085+
if reward.Experience != 101 || reward.Gold != 55 || len(reward.DropVnums) != 2 || reward.DropVnums[0] != 27003 || reward.DropVnums[1] != 27004 {
9086+
t.Fatalf("expected authored reward descriptor to override profile default, got %+v", reward)
9087+
}
9088+
9089+
reward.DropVnums[0] = 99999
9090+
reward = runtime.staticActorDeathRewardLocked(storedActor)
9091+
if len(reward.DropVnums) != 2 || reward.DropVnums[0] != 27003 || reward.DropVnums[1] != 27004 {
9092+
t.Fatalf("expected authored reward override lookup to return isolated clone, got %+v", reward)
9093+
}
9094+
}
9095+
90559096
func TestGameRuntimeCombinedScalarAndDropRewardEmitsAllRewards(t *testing.T) {
90569097
store := loginticket.NewFileStore(t.TempDir())
90579098
actor := worldruntime.StaticEntity{

spec/protocol/non-player-reward-bootstrap.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ That includes a drop-only profile default case where the killing hit emits the n
4848
That runtime coverage now also includes formula-only registered profiles whose `damage_per_normal_attack` is canonicalized from `attack_value - defense_value`, so the profile can both drive deterministic HP mutation and apply its reward descriptor on the same death edge.
4949
A formula-only registered profile may carry a combined descriptor as well; the killing hit still uses the formula-derived HP mutation first, then emits death/clear, scalar EXP/gold point changes, and deterministic owned drop frames in the normal reward ordering.
5050
If the authored spawn-group snapshot also carries an explicit reward descriptor, that authored descriptor wins over the profile-level default for the current actor life; profile defaults are only the fallback for spawn-backed actors whose live/authored snapshot has no explicit reward descriptor.
51+
Dedicated coverage freezes this precedence and clone isolation so a registered profile default cannot silently replace an authored EXP/gold/drop override.
5152
That profile-level default still does **not** make standalone runtime static actors reward-bearing: without a non-empty `spawn_group_ref` or explicit authored live snapshot descriptor, the shared-world death attempt returns a rewardless descriptor.
5253

5354
## Validation

0 commit comments

Comments
 (0)