Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion src/controllers/movement-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
Emote,
} from '@/render';
import { playSfxById, SfxId } from '@/sfx';
import { randomRange } from '@/utils';
import { getPrevCoords, isSteppingStoneWalk, randomRange } from '@/utils';
import type { Vector2 } from '@/vector';

export class MovementController {
Expand Down Expand Up @@ -52,6 +52,17 @@ export class MovementController {
.map!.tileSpecRows.find((r) => r.y === coords.y)
?.tiles.find((t) => t.x === coords.x);

const from = getPrevCoords(
coords,
direction,
this.client.map.width,
this.client.map.height,
);

if (isSteppingStoneWalk(this.client.map, from, coords)) {
playSfxById(SfxId.JumpStone);
}

if (spec && spec.tileSpec === MapTileSpec.Water) {
const metadata = this.client.getEffectMetadata(9);
playSfxById(metadata.sfx);
Expand Down
26 changes: 14 additions & 12 deletions src/handlers/walk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import {
EffectAnimation,
EffectTargetCharacter,
} from '@/render';
import { playSfxById } from '@/sfx';
import { getPrevCoords } from '@/utils';
import { playSfxById, SfxId } from '@/sfx';
import { getPrevCoords, isSteppingStoneWalk } from '@/utils';

function handleWalkPlayer(client: Client, reader: EoReader) {
const packet = WalkPlayerServerPacket.deserialize(reader);
Expand All @@ -26,24 +26,26 @@ function handleWalkPlayer(client: Client, reader: EoReader) {
return;
}

const from = getPrevCoords(
packet.coords,
packet.direction,
client.map.width,
client.map.height,
);

client.animationController.pendingCharacterAnimations.set(
packet.playerId,
new CharacterWalkAnimation(
getPrevCoords(
packet.coords,
packet.direction,
client.map.width,
client.map.height,
),
packet.coords,
packet.direction,
),
new CharacterWalkAnimation(from, packet.coords, packet.direction),
);

if (character.invisible && client.admin === AdminLevel.Player) {
return;
}

if (isSteppingStoneWalk(client.map, from, packet.coords)) {
playSfxById(SfxId.JumpStone);
}

const spec = client!
.map!.tileSpecRows.find((r) => r.y === packet.coords.y)
?.tiles.find((t) => t.x === packet.coords.x);
Expand Down
53 changes: 39 additions & 14 deletions src/map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ const WALK_OFFSETS = [
[Direction.Left]: { x: -WALK_WIDTH_FACTOR * 4, y: -WALK_HEIGHT_FACTOR * 4 },
},
];
// Wasn't sure where best to place this yet, so it's beside WALK_OFFSETS for now.
const STEPPING_STONE_Y_OFFSETS = [-8, -16, -16, -8];

export class MapRenderer {
client: Client;
Expand Down Expand Up @@ -470,6 +472,35 @@ export class MapRenderer {
};
}

private getCharacterWalkState(
animation: CharacterWalkAnimation,
dying: boolean,
): { frame: number; offset: Vector2 } {
const steppingStone =
this.getTileSpec(animation.from.x, animation.from.y) ===
MapTileSpec.Jump ||
this.getTileSpec(animation.to.x, animation.to.y) === MapTileSpec.Jump;
const offset = dying
? WALK_OFFSETS[animation.animationFrame][animation.direction]
: this.interpolateWalkOffset(
animation.animationFrame,
animation.direction,
);

return {
frame:
steppingStone && animation.animationFrame > 0
? 0
: animation.animationFrame,
offset: steppingStone
? {
x: offset.x,
y: offset.y + STEPPING_STONE_Y_OFFSETS[animation.animationFrame],
}
: offset,
};
}

update(interpolation: number) {
if (!this.client.map || this.buildingCache) {
return;
Expand Down Expand Up @@ -954,16 +985,12 @@ export class MapRenderer {
let coords: Vector2 = character.coords;
switch (true) {
case animation instanceof CharacterWalkAnimation: {
walkOffset = dying
? WALK_OFFSETS[animation.animationFrame][animation.direction]
: this.interpolateWalkOffset(
animation.animationFrame,
animation.direction,
);
const walkState = this.getCharacterWalkState(animation, dying);
walkOffset = walkState.offset;
coords = animation.from;
characterFrame = downRight
? CharacterFrame.WalkingDownRight1 + animation.animationFrame
: CharacterFrame.WalkingUpLeft1 + animation.animationFrame;
? CharacterFrame.WalkingDownRight1 + walkState.frame
: CharacterFrame.WalkingUpLeft1 + walkState.frame;
break;
}
case animation instanceof CharacterAttackAnimation:
Expand Down Expand Up @@ -1760,12 +1787,10 @@ export class MapRenderer {
}

if (animation instanceof CharacterWalkAnimation) {
const walkOffset = dying
? WALK_OFFSETS[animation.animationFrame][animation.direction]
: this.interpolateWalkOffset(
animation.animationFrame,
animation.direction,
);
const walkOffset = this.getCharacterWalkState(
animation,
dying,
).offset;
offset.x += walkOffset.x;
offset.y += walkOffset.y;
coords.x = animation.from.x;
Expand Down
1 change: 1 addition & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export { getPrevCoords } from './get-prev-coords';
export { getShieldMetaData, ShieldMetadata } from './get-shield-metadata';
export { getVolumeFromDistance } from './get-volume-from-distance';
export { getWeaponMetaData, WeaponMetadata } from './get-weapon-metadata';
export { isSteppingStoneWalk } from './is-stepping-stone';
export { isoToScreen } from './iso-to-screen';
export { makeDrunk } from './make-drunk';
export { padWithZeros } from './pad-with-zeros';
Expand Down
18 changes: 18 additions & 0 deletions src/utils/is-stepping-stone.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { type Emf, MapTileSpec } from 'eolib';
import type { Vector2 } from '@/vector';

function getTileSpec(map: Emf, coords: Vector2): MapTileSpec | null {
const row = map.tileSpecRows.find((r) => r.y === coords.y);
return row?.tiles.find((t) => t.x === coords.x)?.tileSpec ?? null;
}

export function isSteppingStoneWalk(
map: Emf,
from: Vector2,
to: Vector2,
): boolean {
return (
getTileSpec(map, from) === MapTileSpec.Jump ||
getTileSpec(map, to) === MapTileSpec.Jump
);
}
Loading