fix(client): face skill-cast targets with the 1.13c dir64
ClientUnit.direction is a dir64 since the facing fix, but the SkillCast handler from the online gameplay loops still stored an 8-direction atan2 index (0 = +X). 0..7 passes assertDir64, so a casting unit silently drew a near-south row. Face the cast target through dir64FromPoints, the same 1.13c direction table as movement; a target underfoot keeps the facing.
This commit is contained in:
parent
dd775c8156
commit
8fcd2238cc
|
|
@ -18,6 +18,7 @@ import {
|
||||||
type UnitType,
|
type UnitType,
|
||||||
} from '../../netproto/index.ts'
|
} from '../../netproto/index.ts'
|
||||||
import { onlineItemDataToUiInventoryItem } from '../../common/items/item-bridge.ts'
|
import { onlineItemDataToUiInventoryItem } from '../../common/items/item-bridge.ts'
|
||||||
|
import { dir64FromPoints } from '../../common/units/direction.ts'
|
||||||
import { ClientUnit, makeUnitKey, type UnitCastState } from './client-unit.ts'
|
import { ClientUnit, makeUnitKey, type UnitCastState } from './client-unit.ts'
|
||||||
import { ClientInventoryManager, type ClientItemContainers } from './inventory.ts'
|
import { ClientInventoryManager, type ClientItemContainers } from './inventory.ts'
|
||||||
import { MutableSelfPlayerState, type SelfPlayerState } from './self.ts'
|
import { MutableSelfPlayerState, type SelfPlayerState } from './self.ts'
|
||||||
|
|
@ -218,13 +219,9 @@ export class ClientWorld {
|
||||||
private applySkillCastToUnit(unit: ClientUnit, skillId: number, targetX: number, targetY: number): void {
|
private applySkillCastToUnit(unit: ClientUnit, skillId: number, targetX: number, targetY: number): void {
|
||||||
unit.targetX = targetX
|
unit.targetX = targetX
|
||||||
unit.targetY = targetY
|
unit.targetY = targetY
|
||||||
const dx = targetX - unit.x
|
// `ClientUnit.direction` is a dir64 (`common/units/direction.ts`): face the target through the
|
||||||
const dy = targetY - unit.y
|
// same 1.13c direction table as movement; a target on the unit's own position keeps the facing.
|
||||||
if (dx !== 0 || dy !== 0) {
|
unit.direction = dir64FromPoints(unit.x, unit.y, targetX, targetY, unit.direction)
|
||||||
const angle = Math.atan2(dy, dx)
|
|
||||||
const normalized = ((angle + Math.PI * 2) % (Math.PI * 2)) / (Math.PI * 2)
|
|
||||||
unit.direction = Math.floor(normalized * 8) % 8
|
|
||||||
}
|
|
||||||
const isAttack = PHYSICAL_ATTACK_SKILL_IDS.has(skillId)
|
const isAttack = PHYSICAL_ATTACK_SKILL_IDS.has(skillId)
|
||||||
const mode = unit.unitType === 'monster' ? (isAttack ? 4 : 7) : isAttack ? 7 : 10
|
const mode = unit.unitType === 'monster' ? (isAttack ? 4 : 7) : isAttack ? 7 : 10
|
||||||
unit.mode = mode
|
unit.mode = mode
|
||||||
|
|
|
||||||
|
|
@ -261,3 +261,17 @@ describe('remote unit facing (RemoteEntityInterpolator)', () => {
|
||||||
expect(snapped).toMatchObject({ x: 5003.1, moving: false, dir64: glide.dir64 })
|
expect(snapped).toMatchObject({ x: 5003.1, moving: false, dir64: glide.dir64 })
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('skill-cast facing (ClientWorld)', () => {
|
||||||
|
it('turns the caster toward the target as a dir64 and keeps it for a target underfoot', () => {
|
||||||
|
const world = new ClientWorld()
|
||||||
|
world.apply({ type: 'UnitAssign', unit: { unitType: 1, id: 40, classId: 5, x: 5000, y: 5000 } })
|
||||||
|
const castAt = (x: number, y: number): number => {
|
||||||
|
world.apply({ type: 'SkillCast', caster: { unitType: 1, id: 40 }, skill: 0, level: 1, target: { x, y } })
|
||||||
|
return world.getUnit('monster', 40)!.direction
|
||||||
|
}
|
||||||
|
expect(castAt(5010, 5000)).toBe(56) // world +X: screen south-east
|
||||||
|
expect(castAt(5000, 5000)).toBe(56)
|
||||||
|
expect(castAt(4990, 4990)).toBe(32) // world −X−Y: screen north
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue