diff --git a/engine/src/main/kotlin/world/gregs/voidps/engine/GameLoop.kt b/engine/src/main/kotlin/world/gregs/voidps/engine/GameLoop.kt index f4b8390255..5da6b3b6a1 100644 --- a/engine/src/main/kotlin/world/gregs/voidps/engine/GameLoop.kt +++ b/engine/src/main/kotlin/world/gregs/voidps/engine/GameLoop.kt @@ -53,7 +53,7 @@ class GameLoop( companion object { var tick: Int = 0 private const val ENGINE_DELAY = 600L - private const val MILLI_THRESHOLD = 0L + private const val MILLI_THRESHOLD = 10L private const val MILLI_WARNING_THRESHOLD = 100L } } diff --git a/game/src/main/kotlin/content/entity/death/PlayerDeath.kt b/game/src/main/kotlin/content/entity/death/PlayerDeath.kt index b09b73c6c6..922bf23d97 100644 --- a/game/src/main/kotlin/content/entity/death/PlayerDeath.kt +++ b/game/src/main/kotlin/content/entity/death/PlayerDeath.kt @@ -7,6 +7,8 @@ import content.entity.combat.* import content.entity.combat.Target import content.entity.combat.hit.directHit import content.entity.gfx.areaGfx +import content.entity.player.effect.energy.MAX_RUN_ENERGY +import content.entity.player.effect.energy.runEnergy import content.entity.player.inv.item.tradeable import content.entity.player.kept.ItemsKeptOnDeath import content.entity.proj.shoot @@ -80,6 +82,7 @@ class PlayerDeath : Script { dropItems(player, killer, tile, wilderness) } levels.clear() + runEnergy = MAX_RUN_ENERGY if (onDeath.teleport != null) { tele(onDeath.teleport!!) } else { diff --git a/game/src/main/kotlin/content/entity/npc/combat/Attack.kt b/game/src/main/kotlin/content/entity/npc/combat/Attack.kt index 68c893de44..a8d0f76884 100644 --- a/game/src/main/kotlin/content/entity/npc/combat/Attack.kt +++ b/game/src/main/kotlin/content/entity/npc/combat/Attack.kt @@ -47,7 +47,7 @@ class Attack( val def = def(primaryTarget) def["combat_def", get("transform_id", def.stringId)] } else { - get("transform_id", id) + def["combat_def", get("transform_id", id)] } val definition = definitions.getOrNull(defId) ?: return@npcCombatSwing if (definition.attacks.isEmpty()) { diff --git a/game/src/main/kotlin/content/entity/player/dialogue/type/PlayerDialogue.kt b/game/src/main/kotlin/content/entity/player/dialogue/type/PlayerDialogue.kt index 50cf761e1a..7fd32377f7 100644 --- a/game/src/main/kotlin/content/entity/player/dialogue/type/PlayerDialogue.kt +++ b/game/src/main/kotlin/content/entity/player/dialogue/type/PlayerDialogue.kt @@ -18,9 +18,19 @@ suspend inline fun Player.player(text: String, largeHea player(expression, text, largeHead, clickToContinue, title) } +@JvmName("playerExpression") suspend fun Player.player(expression: String, text: String, largeHead: Boolean = false, clickToContinue: Boolean = true, title: String? = null) { val lines = if (text.contains("\n")) text.trimIndent().lines() else get().get("q8_full").splitLines(text, 380) - check(lines.size <= 4) { "Maximum player chat lines exceeded ${lines.size} for $this" } + if (lines.size > 4) { + for (chunk in lines.chunked(4)) { + player(expression, chunk, largeHead, clickToContinue, title) + } + } else { + player(expression, lines, largeHead, clickToContinue, title) + } +} + +private suspend fun Player.player(expression: String, lines: List, largeHead: Boolean, clickToContinue: Boolean, title: String?) { val id = getInterfaceId(lines.size, clickToContinue) check(open(id)) { "Unable to open player dialogue for $this" } val head = getChatHeadComponentName(largeHead) diff --git a/game/src/main/kotlin/content/skill/magic/book/modern/TelekineticGrab.kt b/game/src/main/kotlin/content/skill/magic/book/modern/TelekineticGrab.kt index 8999fc5af0..aede5bf108 100644 --- a/game/src/main/kotlin/content/skill/magic/book/modern/TelekineticGrab.kt +++ b/game/src/main/kotlin/content/skill/magic/book/modern/TelekineticGrab.kt @@ -66,16 +66,12 @@ class TelekineticGrab(val definitions: SpellDefinitions) : Script { } start("action_delay", 3) AuditLog.event(this@onFloorItemApproach, "telegrab", floorItem, floorItem.tile) - if (tile != floorItem.tile) { - face(floorItem.tile.delta(tile)) - anim("take") - } Items.take(this@onFloorItemApproach, floorItem) } } onNPCApproach("modern_spellbook:telekinetic_grab") { - message("You can't use Telekineetic Grab on them.") + message("You can't use Telekinetic Grab on them.") } } } diff --git a/game/src/main/resources/logback.xml b/game/src/main/resources/logback.xml index 0a7e34fbd0..de3cd9e807 100644 --- a/game/src/main/resources/logback.xml +++ b/game/src/main/resources/logback.xml @@ -7,7 +7,7 @@ %colour(%level) %green([%logger{0}]) %message(%msg){}%n%red(%ex) - + diff --git a/game/src/test/kotlin/content/entity/player/dialogue/type/PlayerChatTest.kt b/game/src/test/kotlin/content/entity/player/dialogue/type/PlayerChatTest.kt index 6c07bd2031..d40b8ef43e 100644 --- a/game/src/test/kotlin/content/entity/player/dialogue/type/PlayerChatTest.kt +++ b/game/src/test/kotlin/content/entity/player/dialogue/type/PlayerChatTest.kt @@ -109,14 +109,19 @@ internal class PlayerChatTest : DialogueTest() { } @Test - fun `Sending five or more lines to chat throws exception`() { - assertThrows { - dialogueBlocking { - player(text = "\nOne\nTwo\nThree\nFour\nFive") - } + fun `Sending five or more lines to splits into multiple messages`() { + dialogue { + player(text = "\nOne\nTwo\nThree\nFour\nFive") } - verify(exactly = 0) { - player.open(any()) + (player.dialogueSuspension as ContinueSuspension).resume(Unit) + verifyOrder { + player.open("dialogue_chat4") + interfaces.sendText("dialogue_chat4", "line1", "One") + interfaces.sendText("dialogue_chat4", "line2", "Two") + interfaces.sendText("dialogue_chat4", "line3", "Three") + interfaces.sendText("dialogue_chat4", "line4", "Four") + player.open("dialogue_chat1") + interfaces.sendText("dialogue_chat1", "line1", "Five") } } diff --git a/network/src/main/kotlin/world/gregs/voidps/network/login/protocol/decode/InterfaceOnFloorItemDecoder.kt b/network/src/main/kotlin/world/gregs/voidps/network/login/protocol/decode/InterfaceOnFloorItemDecoder.kt index 4d84672746..90b513b51b 100644 --- a/network/src/main/kotlin/world/gregs/voidps/network/login/protocol/decode/InterfaceOnFloorItemDecoder.kt +++ b/network/src/main/kotlin/world/gregs/voidps/network/login/protocol/decode/InterfaceOnFloorItemDecoder.kt @@ -18,7 +18,11 @@ class InterfaceOnFloorItemDecoder : Decoder(15) { val itemSlot = packet.readShortLittleEndian().toInt() val y = packet.readShort().toInt() val run = packet.readBoolean() - val item = packet.readUnsignedShortAdd() + var item = packet.readUnsignedShortAdd() + if (item == 65535) { + // readShortAdd doesn't seem to decode > 20k correctly, but client always sends -1 anyway + item = -1 + } val packed = packet.readUnsignedIntMiddle() return InteractInterfaceFloorItem( floorItem, diff --git a/network/src/test/kotlin/world/gregs/voidps/network/login/protocol/DecoderTest.kt b/network/src/test/kotlin/world/gregs/voidps/network/login/protocol/DecoderTest.kt index 20bb2bd85e..d04f9a37de 100644 --- a/network/src/test/kotlin/world/gregs/voidps/network/login/protocol/DecoderTest.kt +++ b/network/src/test/kotlin/world/gregs/voidps/network/login/protocol/DecoderTest.kt @@ -119,8 +119,7 @@ class DecoderTest { val decoders = decoders(huffman) val decoder = decoders[id] assertNotNull(decoder) - val size = decoder!!.length - when (size) { + when (decoder!!.length) { Decoder.BYTE -> assertTrue(data.size <= Byte.MAX_VALUE) Decoder.SHORT -> assertTrue(data.size <= Short.MAX_VALUE) else -> assertEquals(decoder.length, data.size)