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
1 change: 0 additions & 1 deletion data/area/kandarin/ardougne/east_ardougne.npc-spawns.toml
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,6 @@ spawns = [
{ id = "ambassador_gimblewap", x = 2572, y = 3299, level = 1 },
{ id = "banker_4", x = 2616, y = 3330 },
{ id = "my_arm_ardougne", x = 2684, y = 3274, members = true },
{ id = "captain_barnaby_1", x = 2683, y = 3275, members = true },
{ id = "charlie_ardougne", x = 2607, y = 3264, members = true },
{ id = "penguin_ardougne", x = 2596, y = 3270, members = true },
{ id = "silver_merchant_ardougne", x = 2659, y = 3316 },
Expand Down
12 changes: 12 additions & 0 deletions data/area/kandarin/ardougne/east_ardougne.objs.toml
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,15 @@ id = 5792
[dairy_churn_ardougne]
id = 34800
examine = "Used to make dairy products."

[gangplank_ardougne_enter]
id = 2085
examine = "Handy for boarding the ship."

[gangplank_ardougne_exit]
id = 2086
examine = "Handy for boarding the ship."

[captain_barnaby_ship_ladder]
id = 9745
examine = "A sturdy wooden ladder."
10 changes: 10 additions & 0 deletions data/area/kandarin/ardougne/east_ardougne.teles.toml
Original file line number Diff line number Diff line change
Expand Up @@ -272,3 +272,13 @@ to = { x = 2044, y = 4649 }
option = "Climb-up"
tile = { x = 2044, y = 4650 }
to = { x = 2543, y = 3327 }

[gangplank_ardougne_enter]
option = "Cross"
tile = { x = 2683, y = 3270 }
to = { x = 2683, y = 3268, level = 1 }

[gangplank_ardougne_exit]
option = "Cross"
tile = { x = 2683, y = 3269, level = 1 }
to = { x = 2683, y = 3271 }
10 changes: 9 additions & 1 deletion data/area/karamja/brimhaven/brimhaven.objs.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,12 @@ examine = "A closed overgrown dungeon entrance"

[brimhaven_vine_4]
id = 5106
examine = "A closed overgrown dungeon entrance"
examine = "A closed overgrown dungeon entrance"

[gangplank_brimhaven_enter]
id = 2087
examine = "Handy for boarding the ship."

[gangplank_brimhaven_exit]
id = 2088
examine = "Handy for boarding the ship."
12 changes: 11 additions & 1 deletion data/area/karamja/brimhaven/brimhaven.teles.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,14 @@ to = { x = 2636, y = 9510, level = 2}
[brimhaven_walk_down_4]
option = "Walk-down"
tile = { x = 2635, y = 9511, level = 2}
to = { x = 2636, y = 9517}
to = { x = 2636, y = 9517}

[gangplank_brimhaven_enter]
option = "Cross"
tile = { x = 2773, y = 3234 }
to = { x = 2775, y = 3234, level = 1 }

[gangplank_brimhaven_exit]
option = "Cross"
tile = { x = 2774, y = 3234, level = 1 }
to = { x = 2772, y = 3234 }
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import world.gregs.voidps.network.login.protocol.visual.update.player.BodyPart
data class BodyParts(
override var male: Boolean = true,
val looks: IntArray = if (male) DEFAULT_LOOK_MALE.clone() else DEFAULT_LOOK_FEMALE.clone(),
val colours: IntArray = DEFAULT_COLOURS.clone(),
val colours: IntArray = if (male) DEFAULT_COLOURS_MALE.clone() else DEFAULT_COLOURS_FEMALE.clone(),
) : Body {
private val parts = IntArray(12)

Expand Down Expand Up @@ -134,8 +134,11 @@ data class BodyParts(
}

companion object {
val DEFAULT_LOOK_MALE = intArrayOf(0, 14, 18, 26, 34, 38, 42)
// Hair, beard, chest, arms, hands, legs, feet. Hair 5 = "Short" body_look_id.
val DEFAULT_LOOK_MALE = intArrayOf(5, 14, 18, 26, 34, 38, 42)
val DEFAULT_LOOK_FEMALE = intArrayOf(45, -1, 58, 61, 68, 72, 80)
val DEFAULT_COLOURS = IntArray(5)
// Hair, top, legs, feet, skin. Hair 7 = "Willow brown" (light brown).
val DEFAULT_COLOURS_MALE = intArrayOf(7, 0, 0, 0, 0)
val DEFAULT_COLOURS_FEMALE = IntArray(5)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ class ShootingStar : Script {
}

fun getLayerPercentage(totalCollected: Int, totalNeeded: Int): String {
val remaining = totalNeeded - totalCollected
val remaining = (totalNeeded - totalCollected).coerceAtLeast(0)
val percentageRemaining = (remaining.toDouble() / totalNeeded.toDouble()) * 100
return String.format("%.2f", percentageRemaining)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package content.area.kandarin.ardougne

import content.entity.obj.ship.boatTravel
import content.entity.player.dialogue.Happy
import content.entity.player.dialogue.Neutral
import content.entity.player.dialogue.Quiz
import content.entity.player.dialogue.Sad
import content.entity.player.dialogue.type.choice
import content.entity.player.dialogue.type.npc
import content.entity.player.dialogue.type.player
import content.entity.player.dialogue.type.statement
import world.gregs.voidps.engine.Script
import world.gregs.voidps.engine.client.message
import world.gregs.voidps.engine.entity.character.player.Player
import world.gregs.voidps.engine.inv.inventory
import world.gregs.voidps.engine.inv.remove
import world.gregs.voidps.type.Tile

class CaptainBarnaby : Script {

Check warning on line 19 in game/src/main/kotlin/content/area/kandarin/ardougne/CaptainBarnaby.kt

View workflow job for this annotation

GitHub Actions / qodana

Unused symbol

Class "CaptainBarnaby" is never used

init {
npcOperate("Talk-to", "captain_barnaby_2") {
npc<Quiz>("Do you want to go on a trip to Brimhaven?")
npc<Neutral>("The trip will cost you 30 coins.")
choice {
option<Happy>("Yes please.") {
if (!inventory.remove("coins", 30)) {
player<Sad>("Oh dear, I don't seem to have enough money.")
return@option
}
travel()
}
option<Neutral>("No, thank you.")
}
}

npcOperate("Pay-fare", "captain_barnaby_2") {
if (!inventory.remove("coins", 30)) {
message("You do not have enough money for that.")
return@npcOperate
}
travel()
}

// Boarding the docked ship doesn't set sail; the trip starts by talking to the operator.
objTeleportLand("Cross", "gangplank_ardougne_enter") { _, _ ->
message("You must speak to Captain Barnaby before it will set sail.")
}
objTeleportLand("Cross", "gangplank_brimhaven_enter") { _, _ ->
message("You must speak to the Customs officer before it will set sail.")
}

objectOperate("Climb-down", "captain_barnaby_ship_ladder") { (ladder) ->
if (ladder.tile != Tile(2682, 3267, 1)) {
return@objectOperate
}
message("I don't think Captain Barnaby wants me going down there.")
}
}

private suspend fun Player.travel() {
message("You pay 30 coins and board the ship.")
boatTravel("ardougne_to_brimhaven", 5, Tile(2775, 3234, 1))
statement("The ship arrives at Brimhaven.")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import content.entity.player.dialogue.type.player
import content.entity.player.dialogue.type.statement
import world.gregs.voidps.engine.Script
import world.gregs.voidps.engine.client.message
import world.gregs.voidps.engine.data.definition.Areas
import world.gregs.voidps.engine.entity.character.npc.NPC
import world.gregs.voidps.engine.entity.character.player.Player
import world.gregs.voidps.engine.inv.inventory
import world.gregs.voidps.engine.inv.remove
Expand All @@ -18,7 +20,7 @@ import world.gregs.voidps.type.Tile
class CustomsOfficer : Script {

init {
npcOperate("Talk-to", "customs_officer_brimhaven") {
npcOperate("Talk-to", "customs_officer_brimhaven") { (officer) ->
npc<Neutral>("Can I help you?")
choice {
option<Quiz>("Can I journey on this ship?") {
Expand All @@ -30,7 +32,7 @@ class CustomsOfficer : Script {
player<Sad>("Oh dear, I don't seem to have enough money.")
return@option
}
travel()
travel(officer)
}
option<Neutral>("Oh, I'll not bother then.")
}
Expand All @@ -42,18 +44,23 @@ class CustomsOfficer : Script {
}
}

npcOperate("Pay-Fare", "customs_officer_brimhaven") {
npcOperate("Pay-Fare", "customs_officer_brimhaven") { (officer) ->
if (!inventory.remove("coins", 30)) {
message("You do not have enough money for that.")
return@npcOperate
}
travel()
travel(officer)
}
}

private suspend fun Player.travel() {
private suspend fun Player.travel(officer: NPC) {
message("You pay 30 coins and board the ship.")
boatTravel("karamja_to_port_sarim", 7, Tile(3032, 3217, 1))
statement("The ship arrives at Port Sarim.")
if (officer.tile in Areas["brimhaven"]) {
boatTravel("brimhaven_to_ardougne", 5, Tile(2683, 3268, 1))
statement("The ship arrives at Ardougne.")
} else {
boatTravel("karamja_to_port_sarim", 7, Tile(3032, 3217, 1))
statement("The ship arrives at Port Sarim.")
}
}
}
5 changes: 4 additions & 1 deletion game/src/main/kotlin/content/skill/mining/Mining.kt
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,10 @@ class Mining : Script {
val totalStarDust = player.inventory.count(ore) + player.bank.count(ore)
if (totalStarDust >= 200) {
player.message("You have the maximum amount of stardust but was still rewarded experience.")
return -1
// Still count as a successful mine so the star depletes and experience is awarded,
// even though the dust can't be carried. Returning <1 here would skip deplete() and
// let totalCollected grow unbounded (negative "% left of this layer").
return 1
}
}
var amount = when (target.id) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package content.activity.shooting_star

import WorldTest
import content.entity.player.bank.bank
import objectOption
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
import world.gregs.voidps.engine.entity.character.player.skill.Skill
import world.gregs.voidps.engine.entity.obj.GameObjects
import world.gregs.voidps.engine.entity.obj.ObjectLayer
import world.gregs.voidps.engine.inv.add
import world.gregs.voidps.engine.inv.inventory
import world.gregs.voidps.type.setRandom
import kotlin.random.Random

internal class ShootingStarTest : WorldTest() {

/**
* Regression test for https://github.com/GregHib/void/issues/1043
*
* A player holding the maximum amount of stardust (>= 200) used to make `addOre` return -1,
* which short-circuited `deplete()` in the mining loop so the star's layer never advanced and
* the shared `totalCollected` counter grew without bound - an infinite star with a negative
* "% left of this layer". A maxed-out mine must still count towards depleting the star.
*/
@Test
fun `Mining a star with maximum stardust still depletes a layer`() {
setRandom(Random)
val player = createPlayer(emptyTile)
player.levels.set(Skill.Mining, 99)
player.inventory.add("rune_pickaxe")
// Maxed out on stardust so every successful mine goes through the >= 200 branch of addOre.
player.bank.add("stardust", 200)

val tile = emptyTile.addY(1)
val star = createObject("crashed_star_tier_9", tile) // collect_for_next_layer = 15
ShootingStarHandler.currentStarTile = tile
ShootingStarHandler.currentActiveObject = star
ShootingStarHandler.totalCollected = 14 // one successful mine away from the next layer

player.objectOption(star, "Mine")
// The very next stardust mined by the maxed player must advance the star to the next tier.
tickIf(limit = 200) {
GameObjects.getLayer(tile, ObjectLayer.GROUND)?.id == "crashed_star_tier_9"
}

assertEquals("crashed_star_tier_8", GameObjects.getLayer(tile, ObjectLayer.GROUND)?.id)
assertEquals(0, ShootingStarHandler.totalCollected) // counter reset, never runs away negative
assertEquals(0, player.inventory.count("stardust")) // none carried while maxed out
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package content.area.kandarin.ardougne

import WorldTest
import containsMessage
import npcOption
import objectOption
import org.junit.jupiter.api.Test
import world.gregs.voidps.engine.entity.obj.GameObjects
import world.gregs.voidps.engine.inv.add
import world.gregs.voidps.engine.inv.inventory
import world.gregs.voidps.type.Tile
import kotlin.test.assertEquals
import kotlin.test.assertTrue

class CaptainBarnabyTest : WorldTest() {

@Test
fun `Pay fare from Ardougne sails to Brimhaven`() {
val player = createPlayer(Tile(2683, 3274))
player.inventory.add("coins", 30)
val barnaby = createNPC("captain_barnaby_2", Tile(2683, 3275))

player.npcOption(barnaby, "Pay-fare")

tickIf(limit = 200) { player.tile != Tile(2775, 3234, 1) }

assertEquals(Tile(2775, 3234, 1), player.tile)
assertEquals(0, player.inventory.count("coins"))
}

@Test
fun `Boarding the Ardougne ship warns to speak to Captain Barnaby`() {
val player = createPlayer(Tile(2683, 3270))
val gangplank = GameObjects.find(Tile(2683, 3270), "gangplank_ardougne_enter")

player.objectOption(gangplank, "Cross")
tickIf(limit = 20) { player.tile != Tile(2683, 3268, 1) }

assertEquals(Tile(2683, 3268, 1), player.tile)
assertTrue(player.containsMessage("You must speak to Captain Barnaby before it will set sail."))
}

@Test
fun `Ship's ladder cannot be climbed`() {
val player = createPlayer(Tile(2683, 3268, 1))
val ladder = GameObjects.find(Tile(2682, 3267, 1), "captain_barnaby_ship_ladder")

player.objectOption(ladder, "Climb-down")
tick(2)

assertTrue(player.containsMessage("I don't think Captain Barnaby wants me going down there."))
}
}
Loading
Loading