Immersive sound update

Fixed all skills to play their correct level up jingles
All skills except agility have 2 level up jingles
Most skills play a different jingle for new unlocks
Some skills have specific jingles based on level/range (Strength, Hitpoints, Hunter, Construction, Summoning)
Implemented furnace sound when crafting silver and gold jewelry at a furnace using moulds
Implemented emptying sound for fishbowls
Fixed cow milking sound so it plays for more than one bucket
Implemented sound when pushing a canoe into the water from a canoe station
Fixed quest complete jingles to play a random 1 of 3 quest jingles
Implemented jingle that plays when changing clothes at Thessalia in Varrock
Implemented jingle that plays when spying on a penguin
Implemented jingle that plays on login with completed grand exchange offers
Implemented sound when spinning items at a spinning wheel
This commit is contained in:
Zerken
2023-07-29 05:14:11 +00:00
committed by Ryan
parent 421c419f69
commit 686a2c9141
13 changed files with 98 additions and 12 deletions
@@ -1,5 +1,6 @@
package content.global.activity.penguinhns package content.global.activity.penguinhns
import core.api.*
import core.game.node.entity.npc.NPC import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player import core.game.node.entity.player.Player
import core.game.system.task.Pulse import core.game.system.task.Pulse
@@ -17,6 +18,7 @@ class PenguinSpyingHandler : InteractionListener {
player.sendMessage("You've already tagged this penguin.") player.sendMessage("You've already tagged this penguin.")
} else { } else {
GameWorld.submit(SpyPulse(player, npc)) GameWorld.submit(SpyPulse(player, npc))
playJingle(player, 345)
} }
return@on true return@on true
} }
@@ -1,5 +1,6 @@
package content.global.handlers.iface package content.global.handlers.iface
import core.api.playJingle
import core.game.component.Component import core.game.component.Component
import core.game.component.ComponentDefinition import core.game.component.ComponentDefinition
import core.game.component.ComponentPlugin import core.game.component.ComponentPlugin
@@ -154,6 +155,7 @@ class ThessaliaInterface : ComponentPlugin(){
component.setCloseEvent{pl,_ -> component.setCloseEvent{pl,_ ->
pl?.toggleWardrobe(false) pl?.toggleWardrobe(false)
pl.attributes.remove("thes-type") pl.attributes.remove("thes-type")
playJingle(pl, 266)
if(!pl.getAttribute("thes-paid",false)){ if(!pl.getAttribute("thes-paid",false)){
pl.appearance.torso.changeLook(pl.getAttribute("orig-torso",0)) pl.appearance.torso.changeLook(pl.getAttribute("orig-torso",0))
pl.appearance.torso.changeColor(pl.getAttribute("orig-torso-color",0)) pl.appearance.torso.changeColor(pl.getAttribute("orig-torso-color",0))
@@ -20,6 +20,9 @@ import core.tools.RandomFunction;
import core.game.dialogue.DialogueInterpreter; import core.game.dialogue.DialogueInterpreter;
import core.game.dialogue.DialoguePlugin; import core.game.dialogue.DialoguePlugin;
import core.game.node.entity.skill.Skills; import core.game.node.entity.skill.Skills;
import org.rs09.consts.Sounds;
import static core.api.ContentAPIKt.*;
// Sources: // Sources:
// https://www.youtube.com/watch?v=xu7Err9YUgw // https://www.youtube.com/watch?v=xu7Err9YUgw
@@ -71,6 +74,7 @@ public class FishbowlPlugin extends OptionHandler {
if (player.getInventory().remove(item)) { if (player.getInventory().remove(item)) {
player.lock(2); player.lock(2);
player.getInventory().add(new Item(FISHBOWL_EMPTY)); player.getInventory().add(new Item(FISHBOWL_EMPTY));
playAudio(player, Sounds.LIQUID_2401, 1);
player.getPacketDispatch().sendMessage("You empty the contents of the fishbowl onto the ground."); player.getPacketDispatch().sendMessage("You empty the contents of the fishbowl onto the ground.");
} }
break; break;
@@ -15,6 +15,8 @@ import core.plugin.Initializable;
import core.plugin.ClassScanner; import core.plugin.ClassScanner;
import org.rs09.consts.Sounds; import org.rs09.consts.Sounds;
import static core.api.ContentAPIKt.*;
/** /**
* Represents the plugin used to milk a cow. * Represents the plugin used to milk a cow.
* @author 'Vexia * @author 'Vexia
@@ -56,7 +58,7 @@ public final class CowMilkingPlugin extends OptionHandler {
} }
player.animate(ANIMATION); player.animate(ANIMATION);
player.getAudioManager().send(Sounds.MILK_COW_372); playAudio(player, Sounds.MILK_COW_372);
player.getPulseManager().run(new Pulse(8, player) { player.getPulseManager().run(new Pulse(8, player) {
@Override @Override
public boolean pulse() { public boolean pulse() {
@@ -66,6 +68,7 @@ public final class CowMilkingPlugin extends OptionHandler {
} }
if (player.getInventory().contains(1925, 1) || player.getInventory().contains(3727, 1)) { if (player.getInventory().contains(1925, 1) || player.getInventory().contains(3727, 1)) {
player.animate(ANIMATION); player.animate(ANIMATION);
playAudio(player, Sounds.MILK_COW_372);
return false; return false;
} }
return true; return true;
@@ -5,6 +5,9 @@ import core.game.node.entity.skill.Skills;
import core.game.node.entity.player.Player; import core.game.node.entity.player.Player;
import core.game.node.item.Item; import core.game.node.item.Item;
import core.game.world.update.flag.context.Animation; import core.game.world.update.flag.context.Animation;
import org.rs09.consts.Sounds;
import static core.api.ContentAPIKt.*;
/** /**
* Represents the pulse used to craft jewllery. * Represents the pulse used to craft jewllery.
@@ -55,6 +58,7 @@ public final class JewelleryPulse extends SkillPulse<Item> {
public void animate() { public void animate() {
if (ticks % 5 == 0) { if (ticks % 5 == 0) {
player.animate(ANIMATION); player.animate(ANIMATION);
playAudio(player, Sounds.FURNACE_2725, 1);
} }
} }
@@ -8,6 +8,7 @@ import core.game.node.scenery.Scenery
import core.game.system.task.Pulse import core.game.system.task.Pulse
import org.rs09.consts.Animations import org.rs09.consts.Animations
import org.rs09.consts.Items import org.rs09.consts.Items
import org.rs09.consts.Sounds
/** /**
* Handles tick-based silver crafting logic. * Handles tick-based silver crafting logic.
@@ -28,6 +29,7 @@ class SilverCraftingPulse(
} }
animate(player, Animations.HUMAN_FURNACE_SMELTING_3243) animate(player, Animations.HUMAN_FURNACE_SMELTING_3243)
playAudio(player, Sounds.FURNACE_2725, 1)
if (removeItem(player, Items.SILVER_BAR_2355, Container.INVENTORY)) { if (removeItem(player, Items.SILVER_BAR_2355, Container.INVENTORY)) {
addItem(player, product.producedItemId, product.amountProduced) addItem(player, product.producedItemId, product.amountProduced)
@@ -9,6 +9,9 @@ import core.game.node.entity.skill.Skills;
import core.game.node.entity.player.Player; import core.game.node.entity.player.Player;
import core.game.node.item.Item; import core.game.node.item.Item;
import core.game.world.update.flag.context.Animation; import core.game.world.update.flag.context.Animation;
import org.rs09.consts.Sounds;
import static core.api.ContentAPIKt.playAudio;
/** /**
* Represents the pulse used to spin an item. * Represents the pulse used to spin an item.
@@ -67,6 +70,7 @@ public final class SpinningPulse extends SkillPulse<Item> {
public void animate() { public void animate() {
if (ticks % 5 == 0) { if (ticks % 5 == 0) {
player.animate(ANIMATION); player.animate(ANIMATION);
playAudio(player, Sounds.SPINNING_2590, 1);
} }
} }
@@ -10,6 +10,7 @@ import core.game.interaction.InteractionListener
import core.game.interaction.IntType import core.game.interaction.IntType
import core.api.* import core.api.*
import org.rs09.consts.Sounds
class CanoeStationListener : InteractionListener { class CanoeStationListener : InteractionListener {
@@ -80,6 +81,7 @@ class CanoeStationListener : InteractionListener {
val canoe = CanoeUtils.getCanoeFromVarbit(player, varbit) val canoe = CanoeUtils.getCanoeFromVarbit(player, varbit)
player.animator.animate(PUSH) player.animator.animate(PUSH)
lock(player, 2) lock(player, 2)
playAudio(player, Sounds.CANOE_ROLL_2731)
player.faceLocation(CanoeUtils.getFaceLocation(player.location)) player.faceLocation(CanoeUtils.getFaceLocation(player.location))
player.pulseManager.run(object : Pulse(){ player.pulseManager.run(object : Pulse(){
override fun pulse(): Boolean { override fun pulse(): Boolean {
@@ -1,5 +1,6 @@
package content.region.misthalin.varrock.dialogue package content.region.misthalin.varrock.dialogue
import core.api.playJingle
import core.game.component.Component import core.game.component.Component
import core.plugin.Initializable import core.plugin.Initializable
import core.game.dialogue.DialoguePlugin import core.game.dialogue.DialoguePlugin
@@ -22,6 +23,7 @@ class ThessaliaDialogue(player: Player? = null): core.game.dialogue.DialoguePlug
end() end()
player.interfaceManager.open(Component(Components.THESSALIA_CLOTHES_FEMALE_594)) player.interfaceManager.open(Component(Components.THESSALIA_CLOTHES_FEMALE_594))
} }
playJingle(player, 273)
} else { //Has some armour equipped } else { //Has some armour equipped
interpreter.sendDialogues(548, core.game.dialogue.FacialExpression.WORRIED, "You can't try them on while wearing armour. Take", "it off and speak to me again.") interpreter.sendDialogues(548, core.game.dialogue.FacialExpression.WORRIED, "You can't try them on while wearing armour. Take", "it off and speak to me again.")
stage = 52 stage = 52
@@ -213,6 +213,7 @@ class GrandExchangeRecords(private val player: Player? = null) : PersistPlayer,
} }
if (updated) { if (updated) {
sendMessage(player!!, "You have items from the Grand Exchange waiting in your collection box.") sendMessage(player!!, "You have items from the Grand Exchange waiting in your collection box.")
playJingle(player, 284)
} }
} }
@@ -7,6 +7,9 @@ import core.plugin.PluginManifest;
import core.plugin.PluginType; import core.plugin.PluginType;
import java.util.Arrays; import java.util.Arrays;
import java.util.Random;
import static core.api.ContentAPIKt.*;
/** /**
* A skeleton plugin for a quest. * A skeleton plugin for a quest.
@@ -138,7 +141,8 @@ public abstract class Quest implements Plugin<Object> {
player.getPacketDispatch().sendString("" + player.getQuestRepository().getPoints() + "", 277, 7); player.getPacketDispatch().sendString("" + player.getQuestRepository().getPoints() + "", 277, 7);
player.getPacketDispatch().sendString("You have completed the " + getName() + " Quest!", 277, 4); player.getPacketDispatch().sendString("You have completed the " + getName() + " Quest!", 277, 4);
player.getPacketDispatch().sendMessage("Congratulations! Quest complete!"); player.getPacketDispatch().sendMessage("Congratulations! Quest complete!");
player.getPacketDispatch().sendTempMusic(152); int questJingles[] = {152, 153, 154};
playJingle(player, questJingles[new Random().nextInt(3)]);
} }
/** /**
@@ -10,6 +10,7 @@ import core.net.packet.context.MusicContext;
import core.net.packet.out.MusicPacket; import core.net.packet.out.MusicPacket;
import static core.api.ContentAPIKt.*; import static core.api.ContentAPIKt.*;
import static core.game.node.entity.skill.LevelUpJinglesKt.getSkillJingle;
/** /**
@@ -17,12 +18,7 @@ import static core.api.ContentAPIKt.*;
* @author Emperor * @author Emperor
*/ */
public final class LevelUp { public final class LevelUp {
/**
* Level up sound ids.
*/
private static final int[] SOUND_EFFECTS = { 29, 37, 65, 48, 57, 55, 52, 33, 69, 44, 41, 39, 35, 43, 53, 45, 28, 34, 62, 11, 60, 49, 31, 300 };
/** /**
* The skillcapes data. * The skillcapes data.
*/ */
@@ -118,10 +114,7 @@ public final class LevelUp {
if (!player.getAttribute("tutorial:complete", false)) { if (!player.getAttribute("tutorial:complete", false)) {
return; return;
} }
int soundId = SOUND_EFFECTS[slot]; playJingle(player, getSkillJingle(player, slot));
if (soundId > -1) {
PacketRepository.send(MusicPacket.class, new MusicContext(player, soundId, true));
}
handleMilestones(player, slot, amount); handleMilestones(player, slot, amount);
player.getPacketDispatch().sendGraphic(199); player.getPacketDispatch().sendGraphic(199);
player.getPacketDispatch().sendString("<col=00008B>Congratulations, you've just advanced a " + Skills.SKILL_NAME[slot] + " level!", 740, 0); player.getPacketDispatch().sendString("<col=00008B>Congratulations, you've just advanced a " + Skills.SKILL_NAME[slot] + " level!", 740, 0);
@@ -0,0 +1,63 @@
package core.game.node.entity.skill
import core.api.getStatLevel
import core.game.node.entity.player.Player
/**
* Skill levels with unlocks
**/
private val attack: IntArray = intArrayOf(5, 10, 15, 20, 30, 40, 50, 60, 70, 75 ,78, 99)
private val mining: IntArray = intArrayOf(6, 10, 15, 20, 21, 30, 31, 35, 40, 41, 45, 46, 50, 55, 60, 70, 80, 85, 90, 99)
private val smithing: IntArray = intArrayOf(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 68, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99)
private val defence: IntArray = intArrayOf(5, 10, 20, 25, 30, 40, 45, 50, 55, 60, 65, 70, 75, 78, 80, 99)
private val herblore: IntArray = intArrayOf(3, 5, 8, 11, 12, 19, 20, 22, 25, 26, 30, 31, 34, 35, 36, 38, 39, 40, 44, 45, 48, 50, 52, 53, 54, 55, 57, 59, 60, 63, 65, 66, 67, 68, 69, 70, 72, 73, 75, 76, 78, 80, 81, 82, 99)
private val fishing: IntArray = intArrayOf(5, 10, 15, 16, 20, 23, 25, 28, 30, 33, 35, 38, 40, 46, 48, 50, 53, 55, 58, 62, 65, 68, 70, 76, 79, 81, 90, 96, 99)
private val ranged: IntArray = intArrayOf(5, 10, 16, 19, 20, 21, 25, 26, 28, 31, 30, 33, 35, 36, 37, 39, 40, 42, 45, 46, 50, 55, 60, 61, 65, 70, 78, 80, 99)
private val thieving: IntArray = intArrayOf(2, 5, 10, 13, 15, 20, 22, 25, 27, 28, 30, 32, 35, 36, 38, 40, 42, 43, 44, 45, 47, 49, 50, 52, 53, 55, 59, 63, 65, 70, 72, 75, 78, 80, 82, 85, 99)
private val cooking: IntArray = intArrayOf(4, 5, 6, 7, 8, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 28, 29, 30, 31, 32, 33, 34, 35, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 57, 58, 59, 60, 62, 64, 65, 67, 68, 70, 80, 82, 85, 91, 95, 99)
private val prayer: IntArray = intArrayOf(2, 4, 7, 8, 9, 10, 13, 16, 19, 22, 25, 26, 28, 31, 34, 35, 37, 40, 43, 44, 45, 46, 49, 52, 60, 70, 85, 90, 99)
private val crafting: IntArray = intArrayOf(3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 62, 63, 64, 66, 67, 68, 70, 71, 73, 74, 75, 77, 79, 80, 82, 84, 85, 87, 90, 99)
private val firemaking: IntArray = intArrayOf(4, 5, 11, 12, 15, 20, 21, 25, 26, 30, 33, 35, 40, 42, 43, 45, 47, 48, 49, 50, 52, 53, 55, 58, 59, 60, 62, 63, 65, 68, 70, 72, 75, 76, 78, 79, 80, 83, 85, 87, 89, 92, 95, 99)
private val magic: IntArray = intArrayOf(4, 5, 7, 9, 11, 13, 14, 15, 17, 19, 20, 21, 23, 24, 25, 27, 29, 30, 31, 32, 33, 35, 37, 39, 40, 43, 45, 47, 49, 50, 51, 52, 53, 54, 55, 56, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 90, 91, 92, 93, 94, 95, 96, 97, 99)
private val fletching: IntArray = intArrayOf(5, 7, 9, 10, 11, 15, 18, 20, 22, 24, 25, 26, 30, 32, 33, 35, 37, 38, 39, 40, 41, 42, 43, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 55, 56, 58, 59, 60, 61, 62, 63, 65, 67, 69, 70, 71, 73, 75, 77, 80, 81, 85, 90, 95, 99)
private val woodcutting: IntArray = intArrayOf(6, 10, 12, 15, 20, 21, 27, 30, 31, 35, 37, 40, 41, 42, 44, 45, 50, 54, 56, 57, 58, 60, 61, 75, 80, 82, 99)
private val runecrafting: IntArray = intArrayOf(2, 5, 6, 9, 10, 11, 13, 14, 15, 19, 20, 22, 23, 26, 27, 28, 33, 35, 38, 40, 42, 44, 46, 52, 54, 55, 56, 57, 59, 65, 66, 70, 74, 76, 77, 78, 82, 84, 91, 92, 95, 98, 99)
private val slayer: IntArray = intArrayOf(5, 7, 10, 15, 17, 20, 22, 25, 30, 32, 33, 35, 37, 39, 40, 42, 45, 47, 50, 51, 52, 55, 56, 57, 58, 59, 60, 63, 65, 68, 70, 72, 75, 80, 83, 85, 90, 99)
private val farming: IntArray = intArrayOf(2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 36, 38, 39, 42, 44, 45, 47, 48, 50, 51, 52, 53, 55, 56, 57, 59, 60, 62, 63, 67, 68, 70, 72, 73, 75, 79, 83, 85, 99)
/**
* Gets the jingleId to play based on skill slot id and skill level
* @param player the player
* @param slot the skill slot id
**/
fun getSkillJingle(player: Player, slot: Int) : Int {
val skillLevel = getStatLevel(player, slot)
when (slot) {
0 -> return if (attack.contains(skillLevel)) 30 else 29
1 -> return if (defence.contains(skillLevel)) 38 else 37
2 -> return if (skillLevel < 50) 65 else 66 //Strength
3 -> return if (skillLevel < 50) 47 else 48 //Hitpoints
4 -> return if (ranged.contains(skillLevel)) 58 else 57
5 -> return if (prayer.contains(skillLevel)) 56 else 55
6 -> return if (magic.contains(skillLevel)) 52 else 51
7 -> return if (cooking.contains(skillLevel)) 34 else 33
8 -> return if (woodcutting.contains(skillLevel)) 70 else 69
9 -> return if (fletching.contains(skillLevel)) 44 else 43
10 -> return if (fishing.contains(skillLevel)) 42 else 41
11 -> return if (firemaking.contains(skillLevel)) 40 else 39
12 -> return if (crafting.contains(skillLevel)) 36 else 35
13 -> return if (smithing.contains(skillLevel)) 64 else 63
14 -> return if (mining.contains(skillLevel)) 54 else 53
15 -> return if (herblore.contains(skillLevel)) 46 else 45
16 -> return 28 //Agility
17 -> return if (thieving.contains(skillLevel)) 68 else 67
18 -> return if (slayer.contains(skillLevel)) 62 else 61
19 -> return if (farming.contains(skillLevel)) 11 else 10
20 -> return if (runecrafting.contains(skillLevel)) 60 else 59
21 -> return if ((skillLevel % 2 == 0)) 49 else 50 //Hunter
22 -> return if ((skillLevel % 10 == 0)) 31 else 32 //Construction
23 -> return if ((skillLevel < 50)) 300 else 301 //Summoning
}
return 40
}