Skip to content

Commit

Permalink
server: Add slime attacks
Browse files Browse the repository at this point in the history
  • Loading branch information
0xVector committed Sep 9, 2024
1 parent 857f62e commit fbb39c5
Showing 1 changed file with 31 additions and 5 deletions.
36 changes: 31 additions & 5 deletions server/src/implementation/entities/mobs/slime/abstract-slime.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Mob } from "../mob";
import { EventEmitter2 } from "@nestjs/event-emitter";
import { EntityMoveEvent } from "updater/updater.event";
import { EntityAttackEvent, EntityMoveEvent } from "updater/updater.event";
import { EntityType } from "../../entity";
import { WorldService } from "world/world.service";
import { distance, projectDistance } from "utils/coordinates";
Expand All @@ -14,7 +14,10 @@ import { Direction } from "../../creature";
export abstract class AbstractSlime extends Mob {
static readonly MAX_HP: number;
static readonly MAX_SPEED: number;
readonly ATTACK_DISTANCE: number;
protected readonly ATTACK_DISTANCE: number;
protected readonly ATTACK_COOLDOWN: number = 1; // in seconds

protected lastAttackAt: number = 0; // The last tick the slime attacked

constructor(type: EntityType, x: number, y: number, hp: number, speed: number) {
super(type, x, y, hp);
Expand All @@ -26,12 +29,16 @@ export abstract class AbstractSlime extends Mob {
*
* Moves the slime every few ticks
* @param tick The current game tick
* @param serverService A reference to the server service
* @param world A reference to the world service
* @param eventEmitter A reference to the event emitter
*/
public override tick(tick: number, world: WorldService, eventEmitter: EventEmitter2): void {
super.tick(tick, world, eventEmitter);
eventEmitter.emit("entity.move", this.move(WorldService.MS_PER_TICK / 1000, world));

// Attack
const attack = this.tryAttack(tick, world);
if (attack) eventEmitter.emit("entity.attack", attack);
}

/**
Expand All @@ -44,8 +51,8 @@ export abstract class AbstractSlime extends Mob {
public move(time: number, world: WorldService): EntityMoveEvent {
let target = world.getClosestEntity(this.x, this.y, EntityType.PLAYER) ?? this;
const dist = distance(this.x, this.y, target.x, target.y);
if (dist <= this.ATTACK_DISTANCE) target = this; // If close enough for attack, don't move closer
if (dist <= this.ATTACK_DISTANCE) target = this; // Don't move closer

this.isMoving = target != this;

const maxDist = Math.min(time * this.speed); // Maximum distance the slime can move in this move
Expand All @@ -54,6 +61,25 @@ export abstract class AbstractSlime extends Mob {
return this.moveTo(x, y);
}

/**
* Attempt to attack the nearest player
*
* @param tick The current game tick
* @param world A reference to the world service
* @returns An event representing the attack, or null if the slime is not attacking
*/
public tryAttack(tick: number, world: WorldService): EntityAttackEvent | null {
if (this.isMoving) return null;
if ((tick - this.lastAttackAt)*WorldService.MS_PER_TICK/1000 < this.ATTACK_COOLDOWN) return null;

const target = world.getClosestEntity(this.x, this.y, EntityType.PLAYER);
if (target && distance(this.x, this.y, target.x, target.y) <= this.ATTACK_DISTANCE) {
this.lastAttackAt = tick;
return { id: this.id };
}
return null;
}

/**
* Override the default getDirTo method for the horizontally moving slime
*
Expand Down

0 comments on commit fbb39c5

Please sign in to comment.