Android build v1.1.27
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
import type { Iwt2PartyEntityState } from '../sim'
|
||||
import type { Iwt2ClassWeaponLayer } from '../content/classes'
|
||||
|
||||
export type PartyAttackPulse = {
|
||||
startedAt: number
|
||||
}
|
||||
|
||||
export type PartyRenderMotion = {
|
||||
x: number
|
||||
y: number
|
||||
rotation: number
|
||||
scaleX: number
|
||||
scaleY: number
|
||||
tint?: number
|
||||
}
|
||||
|
||||
export type PartyWeaponLayerMotion = {
|
||||
offsetXScale: number
|
||||
offsetYScale: number
|
||||
rotation: number
|
||||
}
|
||||
|
||||
const ATTACK_DURATION_SECONDS = 0.22
|
||||
const RANGED_ATTACK_DURATION_SECONDS = 0.16
|
||||
|
||||
export function partyRenderMotion(
|
||||
entity: Iwt2PartyEntityState,
|
||||
timeSeconds: number,
|
||||
attackPulse?: PartyAttackPulse,
|
||||
): PartyRenderMotion {
|
||||
const speed = Math.hypot(entity.velocity.x, entity.velocity.y)
|
||||
const facingX = entity.facing.x < -0.05 ? -1 : 1
|
||||
const motion: PartyRenderMotion = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
rotation: 0,
|
||||
scaleX: 1,
|
||||
scaleY: 1,
|
||||
}
|
||||
|
||||
if (entity.health <= 0) return { ...motion, rotation: facingX * 0.08, scaleY: 0.92 }
|
||||
if (entity.status.stunnedSeconds > 0 || entity.status.knockedDownSeconds > 0) {
|
||||
return { ...motion, y: 3, rotation: -facingX * 0.12, scaleY: 0.9 }
|
||||
}
|
||||
|
||||
const attackProgress = attackPulse ? attackProgressFor(entity, timeSeconds, attackPulse) : 1
|
||||
if (attackProgress < 1) {
|
||||
const strike = Math.sin(attackProgress * Math.PI)
|
||||
const ranged = entity.projectileSpeed > 0
|
||||
return {
|
||||
...motion,
|
||||
x: facingX * (ranged ? -3 : 4) * strike,
|
||||
y: -1.5 * strike,
|
||||
rotation: facingX * (ranged ? -0.05 : 0.09) * strike,
|
||||
scaleX: 1 + (ranged ? 0.012 : 0.035) * strike,
|
||||
scaleY: 1 - (ranged ? 0.006 : 0.018) * strike,
|
||||
tint: ranged ? 0xdff3ff : 0xffe1a6,
|
||||
}
|
||||
}
|
||||
|
||||
if (entity.castSecondsRemaining > 0) {
|
||||
const pulse = 0.5 + Math.sin(timeSeconds * Math.PI * 12) * 0.5
|
||||
return {
|
||||
...motion,
|
||||
y: -1 - pulse * 1.5,
|
||||
scaleX: 1 + pulse * 0.012,
|
||||
scaleY: 1 + pulse * 0.012,
|
||||
tint: entity.classId === 'mage' ? 0xefc4ff : 0xb9e3ff,
|
||||
}
|
||||
}
|
||||
|
||||
if (speed > 10) {
|
||||
const stride = Math.sin(timeSeconds * Math.PI * 9)
|
||||
const lift = Math.abs(stride) * Math.min(2.8, speed / 90)
|
||||
return {
|
||||
...motion,
|
||||
y: -lift,
|
||||
rotation: facingX * 0.025 * Math.min(1, speed / 190),
|
||||
scaleY: 1 - Math.abs(stride) * 0.01,
|
||||
}
|
||||
}
|
||||
|
||||
const idle = Math.sin(timeSeconds * Math.PI * 2.2)
|
||||
return {
|
||||
...motion,
|
||||
y: -Math.max(0, idle) * 0.9,
|
||||
scaleY: 1 + Math.max(0, idle) * 0.008,
|
||||
}
|
||||
}
|
||||
|
||||
export function isPartyAttackPulseActive(
|
||||
entity: Iwt2PartyEntityState,
|
||||
timeSeconds: number,
|
||||
attackPulse: PartyAttackPulse,
|
||||
): boolean {
|
||||
return attackProgressFor(entity, timeSeconds, attackPulse) < 1
|
||||
}
|
||||
|
||||
export function partyWeaponLayerMotion(
|
||||
entity: Iwt2PartyEntityState,
|
||||
layer: Iwt2ClassWeaponLayer,
|
||||
timeSeconds: number,
|
||||
attackPulse?: PartyAttackPulse,
|
||||
): PartyWeaponLayerMotion {
|
||||
if (!attackPulse || entity.health <= 0) return { offsetXScale: 0, offsetYScale: 0, rotation: 0 }
|
||||
const progress = attackProgressFor(entity, timeSeconds, attackPulse)
|
||||
if (progress >= 1) return { offsetXScale: 0, offsetYScale: 0, rotation: 0 }
|
||||
const strike = Math.sin(progress * Math.PI)
|
||||
const attackMotion = layer.attackMotion
|
||||
return {
|
||||
offsetXScale: (attackMotion?.offsetXScale ?? 0) * strike,
|
||||
offsetYScale: (attackMotion?.offsetYScale ?? 0) * strike,
|
||||
rotation: (attackMotion?.rotation ?? 0) * strike,
|
||||
}
|
||||
}
|
||||
|
||||
function attackProgressFor(
|
||||
entity: Iwt2PartyEntityState,
|
||||
timeSeconds: number,
|
||||
attackPulse: PartyAttackPulse,
|
||||
): number {
|
||||
const duration = entity.projectileSpeed > 0 ? RANGED_ATTACK_DURATION_SECONDS : ATTACK_DURATION_SECONDS
|
||||
return Math.max(0, Math.min(1, (timeSeconds - attackPulse.startedAt) / duration))
|
||||
}
|
||||
Reference in New Issue
Block a user