Skip to content
Merged
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
2 changes: 1 addition & 1 deletion src/net/outgoing-packets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export class OutgoingPackets {
this.queue(packet);
}

public playSoundAtPosition(chunk: Chunk, soundId: number, soundX: number, soundY: number, volume: number, radius: number = 5, delay: number = 0): void {
public playSoundAtPosition(soundId: number, soundX: number, soundY: number, volume: number, radius: number = 5, delay: number = 0): void {
const packet = new Packet(9);
const offset = 0;
packet.writeUnsignedByte(offset);
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/skills/crafting/sheep-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const initAction: npcInitAction = (details) => {
setInterval(() => {
if (Math.random() >= 0.66) {
details.npc.updateFlags.addChatMessage({message: `Baa!`});
details.npc.sendSound(soundIds.sheepBaa, 4);
details.npc.playSound(soundIds.sheepBaa, 4);
}
}, (Math.floor(Math.random() * 20) + 10) * World.TICK_LENGTH);
};
Expand All @@ -30,7 +30,7 @@ export const shearAction: itemOnNpcAction = (details) => {
details.player.outgoingPackets.chatboxMessage('You get some wool.');
details.player.giveItem(itemIds.wool);
details.npc.updateFlags.addChatMessage({message: 'Baa!'});
details.npc.sendSound(soundIds.sheepBaa, 4);
details.npc.playSound(soundIds.sheepBaa, 4);
details.npc.setNewId(npcIds.nakedSheep);

setTimeout(() => {
Expand Down
50 changes: 25 additions & 25 deletions src/world/actor/actor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,49 +30,49 @@ export abstract class Actor extends Entity {
this._walkingQueue = new WalkingQueue(this);
this._walkDirection = -1;
this._runDirection = -1;
this._faceDirection = -1;
this._faceDirection = 6;
this._inventory = new ItemContainer(28);
this.skills = new Skills(this);
this._busy = false;
}

public face(face: Position | Actor, clearWalkingQueue: boolean = true, autoClear: boolean = true): void {
if (face instanceof Position) {
if(face instanceof Position) {
this.updateFlags.facePosition = face;
} else if (face instanceof Actor) {
} else if(face instanceof Actor) {
this.updateFlags.faceActor = face;
this.metadata['faceActor'] = face;

if (autoClear) {
if(autoClear) {
setTimeout(() => {
this.clearFaceActor();
}, 20000);
}
}

if (clearWalkingQueue) {
if(clearWalkingQueue) {
this.walkingQueue.clear();
this.walkingQueue.valid = false;
}
}

public clearFaceActor(): void {
if (this.metadata['faceActor']) {
if(this.metadata['faceActor']) {
this.updateFlags.faceActor = null;
this.metadata['faceActor'] = undefined;
}
}

public playAnimation(animation: number | Animation): void {
if (typeof animation === 'number') {
if(typeof animation === 'number') {
animation = {id: animation, delay: 0};
}

this.updateFlags.animation = animation;
}

public playGraphics(graphics: number | Graphic): void {
if (typeof graphics === 'number') {
if(typeof graphics === 'number') {
graphics = {id: graphics, delay: 0, height: 120};
}

Expand Down Expand Up @@ -101,31 +101,31 @@ export abstract class Actor extends Entity {

public initiateRandomMovement(): void {
setInterval(() => {
if (!this.canMove()) {
if(!this.canMove()) {
return;
}

const movementChance = Math.floor(Math.random() * 10);

if (movementChance < 7) {
if(movementChance < 7) {
return;
}

let px: number;
let py: number;
let movementAllowed = false;

while (!movementAllowed) {
while(!movementAllowed) {
px = this.position.x;
py = this.position.y;

const moveXChance = Math.floor(Math.random() * 10);

if (moveXChance > 6) {
if(moveXChance > 6) {
const moveXAmount = Math.floor(Math.random() * 5);
const moveXMod = Math.floor(Math.random() * 2);

if (moveXMod === 0) {
if(moveXMod === 0) {
px -= moveXAmount;
} else {
px += moveXAmount;
Expand All @@ -134,11 +134,11 @@ export abstract class Actor extends Entity {

const moveYChance = Math.floor(Math.random() * 10);

if (moveYChance > 6) {
if(moveYChance > 6) {
const moveYAmount = Math.floor(Math.random() * 5);
const moveYMod = Math.floor(Math.random() * 2);

if (moveYMod === 0) {
if(moveYMod === 0) {
py -= moveYAmount;
} else {
py += moveYAmount;
Expand All @@ -147,8 +147,8 @@ export abstract class Actor extends Entity {

let valid = true;

if (this instanceof Npc) {
if (px > this.initialPosition.x + this.movementRadius || px < this.initialPosition.x - this.movementRadius
if(this instanceof Npc) {
if(px > this.initialPosition.x + this.movementRadius || px < this.initialPosition.x - this.movementRadius
|| py > this.initialPosition.y + this.movementRadius || py < this.initialPosition.y - this.movementRadius) {
valid = false;
}
Expand All @@ -157,7 +157,7 @@ export abstract class Actor extends Entity {
movementAllowed = valid;
}

if (px !== this.position.x || py !== this.position.y) {
if(px !== this.position.x || py !== this.position.y) {
this.walkingQueue.clear();
this.walkingQueue.valid = true;
this.walkingQueue.add(px, py);
Expand All @@ -166,29 +166,29 @@ export abstract class Actor extends Entity {
}

public forceMovement(direction: number, steps: number): void {
if (!this.canMove()) {
if(!this.canMove()) {
return;
}

let px: number;
let py: number;
let movementAllowed = false;

while (!movementAllowed) {
while(!movementAllowed) {
px = this.position.x;
py = this.position.y;

const movementDirection: DirectionData = directionFromIndex(direction);
if (!movementDirection) {
if(!movementDirection) {
return;
}
let valid = true;
for (let step = 0; step < steps; step++) {
for(let step = 0; step < steps; step++) {
px += movementDirection.deltaX;
py += movementDirection.deltaY;

if (this instanceof Npc) {
if (px > this.initialPosition.x + this.movementRadius || px < this.initialPosition.x - this.movementRadius
if(this instanceof Npc) {
if(px > this.initialPosition.x + this.movementRadius || px < this.initialPosition.x - this.movementRadius
|| py > this.initialPosition.y + this.movementRadius || py < this.initialPosition.y - this.movementRadius) {
valid = false;
}
Expand All @@ -201,7 +201,7 @@ export abstract class Actor extends Entity {

}

if (px !== this.position.x || py !== this.position.y) {
if(px !== this.position.x || py !== this.position.y) {
this.walkingQueue.clear();
this.walkingQueue.valid = true;
this.walkingQueue.add(px, py);
Expand Down
55 changes: 27 additions & 28 deletions src/world/actor/npc/npc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { NpcDefinition } from '@runejs/cache-parser';
import uuidv4 from 'uuid/v4';
import { Position } from '@server/world/position';
import { world } from '@server/game-server';
import { Direction } from '@server/world/direction';
import { Direction, directionData } from '@server/world/direction';
import { QuadtreeKey } from '@server/world/world';
import { ActionPlugin } from '@server/plugins/plugin';
import { basicNumberFilter } from '@server/plugins/plugin-loader';
Expand Down Expand Up @@ -42,7 +42,6 @@ export class Npc extends Actor {
private _animations: NpcAnimations;
public readonly options: string[];
private _movementRadius: number = 0;
private _initialFaceDirection: Direction = 'NORTH';
public readonly initialPosition: Position;
private quadtreeKey: QuadtreeKey = null;

Expand All @@ -57,12 +56,12 @@ export class Npc extends Actor {
this.position = new Position(npcSpawn.x, npcSpawn.y, npcSpawn.level);
this.initialPosition = new Position(npcSpawn.x, npcSpawn.y, npcSpawn.level);

if (npcSpawn.radius) {
if(npcSpawn.radius) {
this._movementRadius = npcSpawn.radius;
}

if (npcSpawn.face) {
this._initialFaceDirection = npcSpawn.face;
if(npcSpawn.face) {
this.faceDirection = directionData[npcSpawn.face].index;
}
}

Expand Down Expand Up @@ -92,12 +91,33 @@ export class Npc extends Actor {
});
}

/**
* Whether or not the Npc can currently move.
*/
public canMove(): boolean {
return this.updateFlags.faceActor === undefined && this.updateFlags.animation === undefined;
}

/**
* Plays a sound at the Npc's location for all nearby players.
* @param soundId The ID of the sound effect.
* @param volume The volume to play the sound at.
*/
public playSound(soundId: number, volume: number): void {
world.playLocationSound(this.position, soundId, volume);
}

/**
* Transforms the Npc visually into a different Npc.
* @param id The id of the Npc to transform into.
*/
public setNewId(id: number): void {
this.id = id;
this.updateFlags.appearanceUpdateRequired = true;
}

public equals(other: Npc): boolean {
if (!other) {
if(!other) {
return false;
}

Expand All @@ -107,7 +127,7 @@ export class Npc extends Actor {
public set position(position: Position) {
super.position = position;

if (this.quadtreeKey !== null) {
if(this.quadtreeKey !== null) {
world.npcTree.remove(this.quadtreeKey);
}

Expand Down Expand Up @@ -135,25 +155,4 @@ export class Npc extends Actor {
return this._movementRadius;
}

public get initialFaceDirection(): Direction {
return this._initialFaceDirection;
}

public sendSound(soundid: number, volume: number): void {
world.findNearbyPlayers(this.position, 10).forEach(player => {
player.outgoingPackets.updateReferencePosition(this.position);
player.outgoingPackets.playSoundAtPosition(
world.chunkManager.getChunkForWorldPosition(this.position),
soundid,
this.position.x,
this.position.y,
volume
);
});
}

public setNewId(id: number): void {
this.id = id;
this.updateFlags.appearanceUpdateRequired = true;
}
}
5 changes: 2 additions & 3 deletions src/world/actor/player/updating/npc-update-task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { RsBuffer } from '@server/net/rs-buffer';
import { Npc } from '@server/world/actor/npc/npc';
import { world } from '@server/game-server';
import { registerNewActors, updateTrackedActors } from './actor-updating';
import { directionData } from '@server/world/direction';

/**
* Handles the chonky npc updating packet for a specific player.
Expand Down Expand Up @@ -45,7 +46,7 @@ export class NpcUpdateTask extends Task<void> {

// Notify the client of the new npc and their worldIndex
npcUpdatePacket.writeBits(15, newNpc.worldIndex);
npcUpdatePacket.writeBits(3, 0); // @TODO default face direction
npcUpdatePacket.writeBits(3, newNpc.faceDirection);
npcUpdatePacket.writeBits(5, positionOffsetX); // World Position X axis offset relative to the player
npcUpdatePacket.writeBits(5, positionOffsetY); // World Position Y axis offset relative to the player
npcUpdatePacket.writeBits(1, newNpc.updateFlags.updateBlockRequired ? 1 : 0); // Update is required
Expand Down Expand Up @@ -81,7 +82,6 @@ export class NpcUpdateTask extends Task<void> {
if(updateFlags.appearanceUpdateRequired) {
mask |= 0x80;
}

if(updateFlags.faceActor !== undefined) {
mask |= 0x4;
}
Expand Down Expand Up @@ -131,7 +131,6 @@ export class NpcUpdateTask extends Task<void> {
updateMaskData.writeOffsetShortBE(npc.id);
}


if(updateFlags.facePosition) {
const position = updateFlags.facePosition;
updateMaskData.writeOffsetShortBE(position.x * 2 + 1);
Expand Down
2 changes: 1 addition & 1 deletion src/world/actor/player/updating/player-update-task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export class PlayerUpdateTask extends Task<void> {

playerUpdatePacket.writeBits(5, positionOffsetX); // World Position X axis offset relative to the main player
playerUpdatePacket.writeBits(5, positionOffsetY); // World Position Y axis offset relative to the main player
playerUpdatePacket.writeBits(3, 0); // @TODO default face direction
playerUpdatePacket.writeBits(3, newPlayer.faceDirection);
playerUpdatePacket.writeBits(1, 1); // Update is required
playerUpdatePacket.writeBits(1, 1); // Discard client walking queues

Expand Down
21 changes: 20 additions & 1 deletion src/world/world.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Player } from './actor/player/player';
import { ChunkManager } from './map/chunk-manager';
import { logger } from '@runejs/logger';
import { ItemDetails, parseItemData } from './config/item-data';
import { gameCache } from '@server/game-server';
import { gameCache, world } from '@server/game-server';
import { Position } from './position';
import { NpcSpawn, parseNpcSpawns } from './config/npc-spawn';
import { Npc } from './actor/npc/npc';
Expand Down Expand Up @@ -66,6 +66,25 @@ export class World {
});
}

/**
* Players a sound at a specific position for all players within range of that position.
* @param position The position to play the sound at.
* @param soundId The ID of the sound effect.
* @param volume The volume the sound should play at.
* @param distance The distance which the sound should reach.
*/
public playLocationSound(position: Position, soundId: number, volume: number, distance: number = 10): void {
this.findNearbyPlayers(position, distance).forEach(player => {
player.outgoingPackets.updateReferencePosition(position);
player.outgoingPackets.playSoundAtPosition(
soundId,
position.x,
position.y,
volume
);
});
}

/**
* Removes a world item from the world.
* @param worldItem The WorldItem object to spawn remove.
Expand Down