Added positional audio support

Added positional audio for combat and cannons
Added numerous missing audio effects for various item equips and charge spells
This commit is contained in:
Avi Weinstock
2022-02-18 14:49:40 +00:00
committed by Ryan
parent 9e6bf08e61
commit 25fb27040c
11 changed files with 149 additions and 39 deletions
@@ -1,18 +1,17 @@
package core.game.interaction.object.dmc;
import core.game.node.entity.skill.Skills;
import core.game.node.entity.combat.CombatStyle;
import rs09.game.node.entity.combat.CombatSwingHandler;
import core.game.node.entity.combat.ImpactHandler.HitsplatType;
import core.game.node.entity.impl.Projectile;
import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.audio.Audio;
import core.game.node.entity.skill.Skills;
import core.game.node.item.Item;
import core.game.node.scenery.Scenery;
import core.game.node.scenery.SceneryBuilder;
import core.game.system.task.LogoutTask;
import core.game.system.task.Pulse;
import rs09.game.world.GameWorld;
import core.game.world.map.Direction;
import core.game.world.map.Location;
import core.game.world.map.RegionManager;
@@ -20,6 +19,8 @@ import core.game.world.map.zone.ZoneRestriction;
import core.game.world.update.flag.context.Animation;
import core.plugin.Plugin;
import core.tools.RandomFunction;
import rs09.game.node.entity.combat.CombatSwingHandler;
import rs09.game.world.GameWorld;
/**
* Handles a player's Dwarf Multi-cannon.
@@ -109,11 +110,13 @@ public final class DMCHandler {
}
player.getPacketDispatch().sendSceneryAnimation(cannon, Animation.create(direction.getAnimationId()));
Location l = cannon.getLocation().transform(1, 1, 0);
player.getAudioManager().send(new Audio(2877), true, l);
direction = DMCRevolution.values()[(direction.ordinal() + 1) % DMCRevolution.values().length];
for (NPC npc : RegionManager.getLocalNpcs(l, 10)) {
if (direction.isInSight(npc.getLocation().getX() - l.getX(), npc.getLocation().getY() - l.getY()) && npc.isAttackable(player, CombatStyle.RANGE) && CombatSwingHandler.isProjectileClipped(npc, l, false)) {
int speed = (int) (25 + (l.getDistance(npc.getLocation()) * 10));
Projectile.create(l, npc.getLocation(), 53, 40, 36, 20, speed, 0, 128).send();
player.getAudioManager().send(new Audio(1667), true, l);
cannonballs--;
int hit = 0;
if (player.getSwingHandler(false).isAccurateImpact(player, npc, CombatStyle.RANGE, 1.2, 1.0)) {
@@ -233,7 +236,7 @@ public final class DMCHandler {
case 0:
object = SceneryBuilder.add(new Scenery(7, spawn));
player.getPacketDispatch().sendMessage("You place the cannon base on the ground.");
return count++ == 666;
break;
case 1:
player.getPacketDispatch().sendMessage("You add the stand.");
break;
@@ -246,8 +249,11 @@ public final class DMCHandler {
handler.configure(SceneryBuilder.add(object = object.transform(6)));
return true;
}
SceneryBuilder.remove(object);
SceneryBuilder.add(object = object.transform(object.getId() + 1));
player.getAudioManager().send(new Audio(2876), true);
if(count != 0) {
SceneryBuilder.remove(object);
SceneryBuilder.add(object = object.transform(object.getId() + 1));
}
return ++count == 4;
}
});
@@ -338,4 +344,4 @@ public final class DMCHandler {
this.cannonballs = cannonballs;
}
}
}
@@ -1,6 +1,7 @@
package core.game.node.entity.player.link.audio;
import core.game.node.entity.player.Player;
import core.game.world.map.Location;
import java.util.List;
@@ -15,6 +16,16 @@ public class Audio {
*/
public static final int VOLUME = 10;
/**
* The default delay.
*/
public static final int DELAY = 0;
/**
* The default radius in tiles of positional audio in [0,16).
*/
public static final int RADIUS = 15;
/**
* The id of the audio piece.
*/
@@ -30,6 +41,25 @@ public class Audio {
*/
private final int delay;
/**
* The radius.
*/
private final int radius;
/**
* Constructs a new {@Code Audio} {@Code Object}
* @param id the id.
* @param volume the volume.
* @param delay the delay.
* @param radius the radius.
*/
public Audio(int id, int volume, int delay, int radius) {
this.id = id;
this.volume = volume;
this.delay = delay;
this.radius = radius;
}
/**
* Constructs a new {@Code Audio} {@Code Object}
* @param id the id.
@@ -37,9 +67,7 @@ public class Audio {
* @param delay the delay.
*/
public Audio(int id, int volume, int delay) {
this.id = id;
this.volume = volume;
this.delay = delay;
this(id, volume, delay, RADIUS);
}
/**
@@ -48,7 +76,7 @@ public class Audio {
* @param volume the volume.
*/
public Audio(int id, int volume) {
this(id, volume, 0);
this(id, volume, DELAY);
}
/**
@@ -65,7 +93,11 @@ public class Audio {
* @param global the global.
*/
public void send(Player player, boolean global) {
player.getAudioManager().send(this, global);
send(player, global, null);
}
public void send(Player player, boolean global, Location loc) {
player.getAudioManager().send(this, global, loc);
}
/**
@@ -113,4 +145,11 @@ public class Audio {
return delay;
}
/**
* Gets the radius.
* @return the radius
*/
public int getRadius() {
return radius;
}
}
@@ -1,6 +1,7 @@
package core.game.node.entity.player.link.audio;
import core.game.node.entity.player.Player;
import core.game.world.map.Location;
import core.game.world.map.MapDistance;
import core.game.world.map.RegionManager;
import core.net.packet.PacketRepository;
@@ -72,17 +73,21 @@ public class AudioManager {
send(audio, false);
}
public void send(Audio audio, boolean global) {
send(audio, global, null);
}
/**
* Sends an audio packet.
* @param audio the audio.
* @param global if globally heard.
*/
public void send(Audio audio, boolean global) {
public void send(Audio audio, boolean global, Location loc) {
if (global) {
send(audio, RegionManager.getLocalPlayers(player, MapDistance.SOUND.getDistance()));
send(audio, RegionManager.getLocalPlayers(player, MapDistance.SOUND.getDistance()), loc);
return;
}
PacketRepository.send(AudioPacket.class, new DefaultContext(player, audio));
PacketRepository.send(AudioPacket.class, new DefaultContext(player, audio, loc));
}
/**
@@ -90,12 +95,12 @@ public class AudioManager {
* @param audio the audio.
* @param players the players.
*/
public void send(Audio audio, List<Player> players) {
public void send(Audio audio, List<Player> players, Location loc) {
for (Player p : players) {
if (p == null) {
continue;
}
p.getAudioManager().send(audio);
p.getAudioManager().send(audio, false, loc);
}
}
@@ -6,6 +6,7 @@ import core.game.node.Node;
import core.game.node.entity.Entity;
import core.game.node.entity.combat.equipment.SpellType;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.audio.Audio;
import core.game.node.entity.player.link.SpellBookManager.SpellBook;
import core.game.node.item.Item;
import core.game.node.scenery.Scenery;
@@ -67,8 +68,8 @@ public final class ChargeOrbSpells extends MagicSpell {
* @param g The graphics.
* @param runes The runes required.
*/
public ChargeOrbSpells(int level, int objectId, int itemId, int buttonId, Graphics g, Item... runes) {
super(SpellBook.MODERN, level, level + 10, ANIMATION, g, null, runes);
public ChargeOrbSpells(int level, int objectId, int itemId, int buttonId, Graphics g, Audio a, Item... runes) {
super(SpellBook.MODERN, level, level + 10, ANIMATION, g, a, runes);
this.objectId = objectId;
this.itemId = itemId;
this.buttonId = buttonId;
@@ -76,10 +77,10 @@ public final class ChargeOrbSpells extends MagicSpell {
@Override
public Plugin<SpellType> newInstance(SpellType arg) throws Throwable {
SpellBook.MODERN.register(35, new ChargeOrbSpells(56, 2151, 571, 35, new Graphics(149, 96), Runes.WATER_RUNE.getItem(30), Runes.COSMIC_RUNE.getItem(3), UNPOWERED_ORB));
SpellBook.MODERN.register(39, new ChargeOrbSpells(60, 29415, 575, 39, new Graphics(151, 96), Runes.EARTH_RUNE.getItem(30), Runes.COSMIC_RUNE.getItem(3), UNPOWERED_ORB));
SpellBook.MODERN.register(46, new ChargeOrbSpells(63, 2153, 569, 46, new Graphics(152, 96), Runes.FIRE_RUNE.getItem(30), Runes.COSMIC_RUNE.getItem(3), UNPOWERED_ORB));
SpellBook.MODERN.register(49, new ChargeOrbSpells(66, 2152, 573, 49, new Graphics(150, 96), Runes.AIR_RUNE.getItem(30), Runes.COSMIC_RUNE.getItem(3), UNPOWERED_ORB));
SpellBook.MODERN.register(35, new ChargeOrbSpells(56, 2151, 571, 35, new Graphics(149, 96), new Audio(118), Runes.WATER_RUNE.getItem(30), Runes.COSMIC_RUNE.getItem(3), UNPOWERED_ORB));
SpellBook.MODERN.register(39, new ChargeOrbSpells(60, 29415, 575, 39, new Graphics(151, 96), new Audio(115), Runes.EARTH_RUNE.getItem(30), Runes.COSMIC_RUNE.getItem(3), UNPOWERED_ORB));
SpellBook.MODERN.register(46, new ChargeOrbSpells(63, 2153, 569, 46, new Graphics(152, 96), new Audio(117), Runes.FIRE_RUNE.getItem(30), Runes.COSMIC_RUNE.getItem(3), UNPOWERED_ORB));
SpellBook.MODERN.register(49, new ChargeOrbSpells(66, 2152, 573, 49, new Graphics(150, 96), new Audio(116), Runes.AIR_RUNE.getItem(30), Runes.COSMIC_RUNE.getItem(3), UNPOWERED_ORB));
return this;
}
@@ -4,6 +4,7 @@ import core.game.node.Node;
import core.game.node.entity.Entity;
import core.game.node.entity.combat.equipment.SpellType;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.audio.Audio;
import core.game.node.entity.player.link.SpellBookManager.SpellBook;
import core.game.node.entity.state.EntityState;
import core.game.node.item.Item;
@@ -24,7 +25,7 @@ public final class ChargeSpell extends MagicSpell {
* Constructs a new {@code ChargeSpell} {@code Object}.
*/
public ChargeSpell() {
super(SpellBook.MODERN, 80, 180, Animation.create(811), new Graphics(6, 96), null, new Item[] { Runes.FIRE_RUNE.getItem(3), Runes.BLOOD_RUNE.getItem(3), Runes.AIR_RUNE.getItem(3) });
super(SpellBook.MODERN, 80, 180, Animation.create(811), new Graphics(6, 96), new Audio(1651), new Item[] { Runes.FIRE_RUNE.getItem(3), Runes.BLOOD_RUNE.getItem(3), Runes.AIR_RUNE.getItem(3) });
}
@Override
@@ -293,7 +293,8 @@ public final class Location extends Node {
*/
public int getChunkOffsetX() {
int x = getLocalX();
return x - ((x / RegionChunk.SIZE) * RegionChunk.SIZE);
//return x - ((x / RegionChunk.SIZE) * RegionChunk.SIZE);
return x & 7;
}
/**
@@ -302,7 +303,8 @@ public final class Location extends Node {
*/
public int getChunkOffsetY() {
int y = getLocalY();
return y - ((y / RegionChunk.SIZE) * RegionChunk.SIZE);
//return y - ((y / RegionChunk.SIZE) * RegionChunk.SIZE);
return y & 7;
}
/**
@@ -330,23 +332,23 @@ public final class Location extends Node {
}
/**
* Gets the local x-coordinate on the current region.
* Gets the local x-coordinate on the current region in [0, 64).
* @return The local x-coordinate.
*/
public int getLocalX() {
return x - ((x >> 6) << 6);
return x & 63;
}
/**
* Gets the local y-coordinate on the current region.
* Gets the local y-coordinate on the current region in [0, 64).
* @return The local y-coordinate.
*/
public int getLocalY() {
return y - ((y >> 6) << 6);
return y & 63;
}
/**
* Gets the local x-coordinate.
* Gets the scene x-coordinate in [48, 55] (note that 104/2 = 52).
* @return The local x-coordinate.
*/
public int getSceneX() {
@@ -354,7 +356,7 @@ public final class Location extends Node {
}
/**
* Gets the local y-coordinate.
* Gets the local y-coordinate in [48, 55] (note that 104/2 = 52).
* @return The local y-coordinate.
*/
public int getSceneY() {
@@ -1,6 +1,7 @@
package core.net.packet.out;
import core.game.node.entity.player.link.audio.Audio;
import core.game.world.map.Location;
import core.net.packet.IoBuffer;
import core.net.packet.OutgoingPacket;
import core.net.packet.context.DefaultContext;
@@ -11,17 +12,38 @@ import core.net.packet.context.DefaultContext;
*/
public class AudioPacket implements OutgoingPacket<DefaultContext> {
public static IoBuffer write(IoBuffer buffer, Audio audio, Location loc) {
if(loc == null) {
buffer.put((byte) 172);
buffer.putShort(audio.getId());
buffer.put((byte) audio.getVolume());
buffer.putShort(audio.getDelay());
} else {
buffer.put((byte) 97);
buffer.put((byte) (loc.getChunkOffsetX() << 4 | loc.getChunkOffsetY()));
buffer.putShort(audio.getId());
buffer.put((byte) (audio.getRadius() << 4 | audio.getVolume() & 7));
buffer.put((byte) audio.getDelay());
}
return buffer;
}
//208 music effect
//4 music
//172 sound effect
@Override
public void send(DefaultContext context) {
final Audio audio = (Audio) context.getObjects()[0];
IoBuffer buffer = new IoBuffer(172);
buffer.putShort(audio.getId());
buffer.put((byte) audio.getVolume());
buffer.putShort(audio.getDelay());
buffer.cypherOpcode(context.getPlayer().getSession().getIsaacPair().getOutput());context.getPlayer().getSession().write(buffer);
final Location loc = (Location) context.getObjects()[1];
IoBuffer buffer;
if(loc == null) {
buffer = new IoBuffer();
} else {
buffer = UpdateAreaPosition.getBuffer(context.getPlayer(), loc.getChunkBase());
}
write(buffer, audio, loc);
buffer.cypherOpcode(context.getPlayer().getSession().getIsaacPair().getOutput());
context.getPlayer().getSession().write(buffer);
}
}