Files
pixel.horse/src/ts/client/playerActions.ts
T

244 lines
7.3 KiB
TypeScript

import { isCommand, processCommand, hasFlag, includes, point } from '../common/utils';
import { canPonyLie, canPonyFlyUp, canPonyStand, canPonySit, doBoopPonyAction } from '../common/pony';
import { PonyTownGame } from './game';
import {
setPonyState, canBoop, isPonyLying, isPonyFlying, isPonyStanding, isPonySitting, getInteractBounds,
isFacingRight, closestEntity, entityInRange
} from '../common/entityUtils';
import { EntityState, Action, Pony, ChatType, EntityFlags, Point, TileType } from '../common/interfaces';
import { FLY_DELAY } from '../common/constants';
import { randomString } from '../common/stringUtils';
import { pickEntitiesByRect, pickAnyEntities } from '../common/worldMap';
import { centerPoint } from '../common/rect';
import { pointToWorld, roundPositionX, roundPositionY } from '../common/positionUtils';
import { hammer, shovel } from '../common/entities';
export function handleActionCommand(message: string, game: PonyTownGame): boolean {
if (isCommand(message)) {
const { command = '' } = processCommand(message);
const player = game.player;
if (DEVELOPMENT) {
if (command === 'spammessages') {
let i = 0;
setInterval(() => game.send(server => server.say(0, randomString(5) + ` #${i++}`, ChatType.Say)), 100);
return true;
}
}
switch (command.toLowerCase()) {
case 'testerrorreporting':
throw new Error('test error');
case 'disablepixelratio':
game.togglePixelRatio();
return true;
case 'lie':
case 'lay':
if (player) {
if (isPonyLying(player)) {
sitAction(player, game);
} else {
lieAction(player, game);
}
}
return true;
case 'sit':
if (player) {
if (isPonyFlying(player)) {
standAction(player, game);
} else {
sitAction(player, game);
}
}
return true;
case 'stand':
if (player) {
standAction(player, game);
}
return true;
case 'fly':
if (player) {
if (isPonyFlying(player)) {
standAction(player, game);
} else {
flyAction(player, game);
}
}
return true;
}
}
return false;
}
export function upAction(game: PonyTownGame) {
const player = game.player;
if (player) {
if (isPonyLying(player)) {
sitAction(player, game);
} else if (isPonySitting(player)) {
standAction(player, game);
} else if (isPonyStanding(player)) {
flyAction(player, game);
}
}
}
export function downAction(game: PonyTownGame) {
const player = game.player;
if (player) {
if (isPonySitting(player)) {
lieAction(player, game);
} else if (isPonyStanding(player)) {
sitAction(player, game);
} else if (isPonyFlying(player)) {
standAction(player, game);
}
}
}
export function sitAction(player: Pony, game: PonyTownGame) {
if (canPonySit(player, game.map) && game.send(server => server.action(Action.Sit))) {
player.state = setPonyState(player.state, EntityState.PonySitting);
game.stateOverride = EntityState.PonySitting;
game.onActionsUpdate.next();
}
}
export function standAction(player: Pony, game: PonyTownGame) {
if (canPonyStand(player, game.map) && game.send(server => server.action(Action.Stand))) {
player.state = setPonyState(player.state, EntityState.PonyStanding);
game.stateOverride = EntityState.PonyStanding;
game.onActionsUpdate.next();
}
}
export function lieAction(player: Pony, game: PonyTownGame) {
if (canPonyLie(player, game.map) && game.send(server => server.action(Action.Lie))) {
player.state = setPonyState(player.state, EntityState.PonyLying);
game.stateOverride = EntityState.PonyLying;
game.onActionsUpdate.next();
}
}
export function flyAction(player: Pony, game: PonyTownGame) {
if (canPonyFlyUp(player) && game.send(server => server.action(Action.Fly))) {
player.state = setPonyState(player.state, EntityState.PonyFlying);
player.inTheAirDelay = FLY_DELAY;
game.stateOverride = EntityState.PonyFlying;
game.onActionsUpdate.next();
}
}
export function boopAction(game: PonyTownGame) {
if (game.player && canBoop(game.player) && game.send(server => server.action(Action.Boop))) {
doBoopPonyAction(game, game.player);
}
}
export function turnHeadAction(game: PonyTownGame) {
if (!game.player) {
return;
}
if (game.player.animator.state) {
const disabledFrames = game.player.animator.state.animation.disableHeadTurnFrames;
if (disabledFrames > 0) {
const disabledTime = disabledFrames / game.player.animator.state.animation.fps;
if (disabledTime >= game.player.animator.time) {
return;
}
}
}
if (game.send(server => server.action(Action.TurnHead))) {
game.player.state = game.player.state ^ EntityState.HeadTurned;
game.headTurnedOverride = hasFlag(game.player.state, EntityState.HeadTurned);
game.onActionsUpdate.next();
}
}
export function interact(game: PonyTownGame, shift: boolean) {
const player = game.player;
if (player) {
const bounds = getInteractBounds(player);
const entities = pickEntitiesByRect(game.map, bounds, true, false);
const center = centerPoint(bounds);
center.x += (bounds.w / 4) * (isFacingRight(player) ? -1 : 1);
const entity = closestEntity(pointToWorld(center), entities);
if (entity && entityInRange(entity, player)) {
game.send(server => server.interact(entity.id));
} else if (player.hold === hammer.type) {
game.changePlaceEntity(shift);
} else if (player.hold === shovel.type) {
game.changePlaceTile(shift);
} else if (player.ponyState.holding && hasFlag(player.ponyState.holding.flags, EntityFlags.Usable)) {
game.send(server => server.use());
}
}
}
export function toggleWall(game: PonyTownGame, hover: Point) {
const x = hover.x | 0;
const y = hover.y | 0;
const dx = hover.x - x;
const dy = hover.y - y;
if (dx > dy) {
if ((dx + dy) < 1) {
game.send(server => server.changeTile(x, y, TileType.WallH));
} else {
game.send(server => server.changeTile(x + 1, y, TileType.WallV));
}
} else {
if ((dx + dy) < 1) {
game.send(server => server.changeTile(x, y, TileType.WallV));
} else {
game.send(server => server.changeTile(x, y + 1, TileType.WallH));
}
}
}
export function editorSelectEntities(game: PonyTownGame, hover: Point, shift: boolean) {
game.apply(() => {
const entities = pickAnyEntities(game.map, hover);
if (shift) {
const entity = entities.filter(e => !includes(game.editor.selectedEntities, e))[0];
entity && game.editor.selectedEntities.push(entity);
} else {
const index = entities.findIndex(e => includes(game.editor.selectedEntities, e));
const entity = entities[(index + 1) % entities.length];
game.editor.selectedEntities = entity ? [entity] : [];
}
});
}
export function editorDragEntities(game: PonyTownGame, hover: Point, buttonPressed: boolean) {
if (buttonPressed) {
const dx = hover.x - game.editor.draggingStart.x;
const dy = hover.y - game.editor.draggingStart.y;
game.editor.selectedEntities.forEach(e => {
e.x = roundPositionX(e.draggingStart!.x + dx);
e.y = roundPositionY(e.draggingStart!.y + dy);
});
} else {
game.apply(() => game.editor.draggingEntities = false);
game.send(server => server.editorAction({
type: 'move',
entities: game.editor.selectedEntities.map(({ id, x, y }) => ({ id, x, y })),
}));
}
}
export function editorMoveEntities(game: PonyTownGame, hover: Point) {
game.editor.draggingEntities = true;
game.editor.draggingStart = hover;
game.editor.selectedEntities.forEach(e => e.draggingStart = point(e.x, e.y));
}