Skip to content

Commit 97896a3

Browse files
tlf30garyttierney
authored andcommitted
Add implementation of runecrafting skill
1 parent 397d9b2 commit 97896a3

File tree

8 files changed

+297
-5
lines changed

8 files changed

+297
-5
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
plugin {
2+
name = "runecrafting-skill"
3+
packageName = "org.apollo.game.plugin.skills.runecrafting"
4+
authors = [
5+
"Major",
6+
"BugCrusher",
7+
"tlf30"
8+
]
9+
10+
dependencies = ["util:lookup", "api"]
11+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import org.apollo.game.action.ActionBlock
2+
import org.apollo.game.action.AsyncDistancedAction
3+
import org.apollo.game.action.DistancedAction
4+
import org.apollo.game.model.Animation
5+
import org.apollo.game.model.Graphic
6+
import org.apollo.game.model.Position
7+
import org.apollo.game.model.entity.Player
8+
import org.apollo.game.plugin.api.Definitions
9+
import org.apollo.game.plugin.api.runecraft
10+
import org.apollo.util.LanguageUtil
11+
12+
private val blankTiaraId = 5525
13+
private val runecraftingAnimation = Animation(791)
14+
private val runecraftingGraphic = Graphic(186, 0, 100)
15+
private val runeEssenceId = 1436
16+
17+
class TeleportAction(val player: Player, val start: Position, val distance: Int, val end: Position) : DistancedAction<Player>(0, true, player, start, distance) {
18+
override fun executeAction() {
19+
player.teleport(end)
20+
stop()
21+
}
22+
}
23+
24+
class CreateTiaraAction(val player: Player, val position: Position, val tiara: Tiara, val altar: Altar) : DistancedAction<Player>(0, true, player, position, 2) {
25+
override fun executeAction() {
26+
if (tiara.altar != altar) {
27+
player.sendMessage("You can't use that talisman on this altar.")
28+
stop()
29+
return
30+
}
31+
32+
if (player.inventory.contains(blankTiaraId)) {
33+
player.inventory.remove(blankTiaraId)
34+
player.inventory.add(tiara.id)
35+
player.runecraft.experience += tiara.xp
36+
player.playAnimation(runecraftingAnimation)
37+
player.playGraphic(runecraftingGraphic)
38+
stop()
39+
}
40+
}
41+
}
42+
43+
class RunecraftingAction(val player: Player, val rune: Rune, altar: Altar) : AsyncDistancedAction<Player>(0, true, player, altar.center, 3) {
44+
override fun action(): ActionBlock = {
45+
if (player.runecraft.current < rune.level) {
46+
player.sendMessage("You need a runecrafting level of ${rune.level} to craft this rune.")
47+
stop()
48+
}
49+
50+
if (!player.inventory.contains(runeEssenceId)) {
51+
player.sendMessage("You need rune essence to craft runes.")
52+
stop()
53+
}
54+
55+
player.turnTo(position)
56+
player.playAnimation(runecraftingAnimation)
57+
player.playGraphic(runecraftingGraphic)
58+
59+
wait(1)
60+
61+
val name = Definitions.item(rune.id)?.name;
62+
val nameArticle = LanguageUtil.getIndefiniteArticle(name)
63+
val essenceAmount = player.inventory.removeAll(runeEssenceId)
64+
val runeAmount = essenceAmount * rune.getBonus()
65+
val runesDescription = if (runeAmount > 1) "some ${name}s" else "$nameArticle $name"
66+
67+
player.sendMessage("You craft the rune essence into $runesDescription")
68+
player.inventory.add(rune.id, runeAmount.toInt())
69+
player.runecraft.experience += rune.xp
70+
stop()
71+
}
72+
73+
}
74+
75+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import org.apollo.game.model.Position
2+
3+
enum class Altar(val entranceId: Int, val craftingId: Int, val portalId: Int, val entrance: Position, val exit: Position, val center: Position) {
4+
AIR_ALTAR(2452, 2478, 2465, Position(2841, 4829), Position(2983, 3292), Position(2844, 4834)),
5+
MIND_ALTAR(2453, 2479, 2466, Position(2793, 4828), Position(2980, 3514), Position(2786, 4841)),
6+
WATER_ALTAR(2454, 2480, 2467, Position(2726, 4832), Position(3187, 3166), Position(2716, 4836)),
7+
EARTH_ALTAR(2455, 2481, 2468, Position(2655, 4830), Position(3304, 3474), Position(2658, 4841)),
8+
FIRE_ALTAR(2456, 2482, 2469, Position(2574, 4849), Position(3311, 3256), Position(2585, 4838)),
9+
BODY_ALTAR(2457, 2483, 2470, Position(2524, 4825), Position(3051, 3445), Position(2525, 4832)),
10+
COSMIC_ALTAR(2458, 2484, 2471, Position(2142, 4813), Position(2408, 4379), Position(2142, 4833)),
11+
LAW_ALTAR(2459, 2485, 2472, Position(2464, 4818), Position(2858, 3379), Position(2464, 4832)),
12+
NATURE_ALTAR(2460, 2486, 2473, Position(2400, 4835), Position(2867, 3019), Position(2400, 4841)),
13+
CHAOS_ALTAR(2461, 2487, 2474, Position(2268, 4842), Position(3058, 3591), Position(2271, 4842)),
14+
DEATH_ALTAR(2462, 2488, 2475, Position(2208, 4830), Position(3222, 3222), Position(2205, 4836));
15+
16+
companion object {
17+
private val ALTARS = Altar.values()
18+
19+
fun findByEntranceId(id: Int): Altar? = ALTARS.find { Altar -> Altar.entranceId == id }
20+
fun findByPortalId(id: Int): Altar? = ALTARS.find { Altar -> Altar.portalId == id }
21+
fun findByCraftingId(id: Int): Altar? = ALTARS.find { Altar -> Altar.craftingId == id }
22+
}
23+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import Altar.*
2+
3+
enum class Rune(val id: Int, val altar: Altar, val level: Int, val xp: Double) {
4+
AIR_RUNE(556, AIR_ALTAR, 1, 5.0),
5+
MIND_RUNE(558, MIND_ALTAR, 1, 5.5),
6+
WATER_RUNE(555, WATER_ALTAR, 5, 6.0),
7+
EARTH_RUNE(557, EARTH_ALTAR, 9, 6.5),
8+
FIRE_RUNE(554, FIRE_ALTAR, 14, 7.0),
9+
BODY_RUNE(559, BODY_ALTAR, 20, 7.5),
10+
COSMIC_RUNE(564, COSMIC_ALTAR, 27, 8.0),
11+
CHAOS_RUNE(562, CHAOS_ALTAR, 35, 8.5),
12+
NATURE_RUNE(561, NATURE_ALTAR, 44, 9.0),
13+
LAW_RUNE(563, LAW_ALTAR, 54, 9.5),
14+
DEATH_RUNE(560, DEATH_ALTAR, 65, 10.0);
15+
16+
companion object {
17+
private val RUNES = Rune.values()
18+
19+
fun findById(id: Int): Rune? = RUNES.find { rune -> rune.id == id }
20+
fun findByAltarId(id: Int): Rune? = RUNES.find { rune -> rune.altar.craftingId == id }
21+
}
22+
23+
fun getBonus(): Double = when (this) {
24+
Rune.AIR_RUNE -> (Math.floor((level / 11.0)) + 1)
25+
Rune.MIND_RUNE -> (Math.floor((level / 14.0)) + 1)
26+
Rune.WATER_RUNE -> (Math.floor((level / 19.0)) + 1)
27+
Rune.EARTH_RUNE -> (Math.floor((level / 26.0)) + 1)
28+
Rune.FIRE_RUNE -> (Math.floor((level / 35.0)) + 1)
29+
Rune.BODY_RUNE -> (Math.floor((level / 46.0)) + 1)
30+
Rune.COSMIC_RUNE -> (Math.floor((level / 59.0)) + 1)
31+
Rune.CHAOS_RUNE -> (Math.floor((level / 74.0)) + 1)
32+
Rune.NATURE_RUNE -> (Math.floor((level / 91.0)) + 1)
33+
Rune.LAW_RUNE -> 1.0
34+
Rune.DEATH_RUNE -> 1.0
35+
}
36+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import org.apollo.game.message.impl.*
2+
import org.apollo.game.model.entity.EquipmentConstants
3+
import org.apollo.game.model.event.impl.LoginEvent
4+
5+
private val changeAltarObjectConfigId = 491
6+
7+
on_player_event { LoginEvent::class }
8+
.then {
9+
val equippedHat = player.equipment.get(EquipmentConstants.HAT)
10+
val equippedTiaraConfig = equippedHat?.let { item -> Tiara.findById(item.id)?.configId } ?: 0
11+
val configValue = 1 shl equippedTiaraConfig
12+
13+
player.send(ConfigMessage(changeAltarObjectConfigId, configValue))
14+
}
15+
16+
on { ObjectActionMessage::class }
17+
.where { option == 2 }
18+
.then {
19+
val tiara = Tiara.findByAltarId(id) ?: return@then
20+
val hat = it.equipment.get(EquipmentConstants.HAT) ?: return@then
21+
22+
if (hat.id == tiara.id && tiara.altar.entranceId == id) {
23+
it.startAction(TeleportAction(it, position, 2, tiara.altar.entrance))
24+
terminate()
25+
}
26+
}
27+
28+
on { ItemActionMessage::class }
29+
.where { option == 1 }
30+
.then { player ->
31+
Tiara.findById(id)?.let {
32+
player.send(ConfigMessage(changeAltarObjectConfigId, 0))
33+
terminate()
34+
}
35+
}
36+
37+
on { ItemOnObjectMessage::class }
38+
.then {
39+
val tiara = Tiara.findByTalismanId(id) ?: return@then
40+
val altar = Altar.findByCraftingId(objectId) ?: return@then
41+
42+
it.startAction(CreateTiaraAction(it, position, tiara, altar))
43+
terminate()
44+
}
45+
46+
on { ItemOptionMessage::class }
47+
.where { option == 4 }
48+
.then {
49+
val talisman = Talisman.findById(id) ?: return@then
50+
51+
talisman.sendProximityMessageTo(it)
52+
terminate()
53+
}
54+
55+
on { ItemOnObjectMessage::class }
56+
.then {
57+
val talisman = Talisman.findById(id) ?: return@then
58+
val altar = Altar.findByEntranceId(objectId) ?: return@then
59+
60+
it.startAction(TeleportAction(it, position, 2, altar.entrance))
61+
terminate()
62+
}
63+
64+
on { ObjectActionMessage::class }
65+
.where { option == 1 }
66+
.then {
67+
val altar = Altar.findByPortalId(id) ?: return@then
68+
69+
it.startAction(TeleportAction(it, altar.entrance, 1, altar.exit))
70+
terminate()
71+
}
72+
73+
on { ObjectActionMessage::class }
74+
.where { option == 1 }
75+
.then {
76+
val rune = Rune.findByAltarId(id) ?: return@then
77+
val craftingAltar = Altar.findByCraftingId(id) ?: return@then
78+
79+
it.startAction(RunecraftingAction(it, rune, craftingAltar))
80+
terminate()
81+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import org.apollo.game.model.Position
2+
import org.apollo.game.model.entity.Player
3+
4+
enum class Talisman(val id: Int, val altar: Position) {
5+
AIR_TALISMAN(1438, Position(2985, 3292)),
6+
EARTH_TALISMAN(1440, Position(3306, 3474)),
7+
FIRE_TALISMAN(1442, Position(3313, 3255)),
8+
WATER_TALISMAN(1444, Position(3185, 3165)),
9+
BODY_TALISMAN(1446, Position(3053, 3445)),
10+
MIND_TALISMAN(1448, Position(2982, 3514)),
11+
CHAOS_TALISMAN(1452, Position(3059, 3590)),
12+
COSMIC_TALISMAN(1454, Position(2408, 4377)),
13+
DEATH_TALISMAN(1456, Position(0, 0)),
14+
LAW_TALISMAN(1458, Position(2858, 3381)),
15+
NATURE_TALISMAN(1462, Position(2869, 3019));
16+
17+
companion object {
18+
private val TALISMANS = Talisman.values()
19+
20+
fun findById(id: Int): Talisman? = TALISMANS.find { talisman -> talisman.id == id }
21+
}
22+
23+
fun sendProximityMessageTo(player: Player) {
24+
if (altar.isWithinDistance(player.position, 10)) {
25+
player.sendMessage("Your talisman glows brightly.");
26+
return
27+
}
28+
29+
var direction = if (player.position.y > altar.y) "North" else "South";
30+
direction += if (player.position.x > altar.x) "-East" else "-West";
31+
32+
player.sendMessage("The talisman pulls toward the $direction");
33+
}
34+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import Altar.*
2+
import Talisman.*
3+
4+
enum class Tiara(val id: Int, val altar: Altar, val talisman: Talisman, val configId: Int, val xp: Double) {
5+
AIR_TIARA(5527, AIR_ALTAR, AIR_TALISMAN, 0, 25.0),
6+
MIND_TIARA(5529, MIND_ALTAR, MIND_TALISMAN, 1, 27.5),
7+
WATER_TIARA(5531, WATER_ALTAR, WATER_TALISMAN, 2, 30.0),
8+
BODY_TIARA(5533, BODY_ALTAR, BODY_TALISMAN, 5, 37.5),
9+
EARTH_TIARA(5535, EARTH_ALTAR, EARTH_TALISMAN, 3, 32.5),
10+
FIRE_TIARA(5537, FIRE_ALTAR, FIRE_TALISMAN, 4, 35.0),
11+
COSMIC_TIARA(5539, COSMIC_ALTAR, COSMIC_TALISMAN, 6, 40.0),
12+
NATURE_TIARA(5541, NATURE_ALTAR, NATURE_TALISMAN, 8, 45.0),
13+
CHAOS_TIARA(5543, CHAOS_ALTAR, CHAOS_TALISMAN, 9, 42.5),
14+
LAW_TIARA(5545, LAW_ALTAR, LAW_TALISMAN, 7, 47.5),
15+
DEATH_TIARA(5548, DEATH_ALTAR, DEATH_TALISMAN, 10, 50.0);
16+
17+
companion object {
18+
private val TIARAS = Tiara.values()
19+
20+
fun findById(id: Int): Tiara? = TIARAS.find { tiara -> tiara.id == id }
21+
fun findByAltarId(id: Int): Tiara? = TIARAS.find { tiara -> tiara.altar.entranceId == id }
22+
fun findByTalismanId(id: Int): Tiara? = TIARAS.find { tiara -> tiara.talisman.id == id }
23+
}
24+
}

game/src/main/java/org/apollo/game/model/inv/Inventory.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
package org.apollo.game.model.inv;
22

3+
import com.google.common.base.Preconditions;
4+
import org.apollo.cache.def.ItemDefinition;
5+
import org.apollo.game.model.Item;
6+
37
import java.util.ArrayList;
48
import java.util.Arrays;
59
import java.util.List;
610
import java.util.Optional;
711

8-
import org.apollo.cache.def.ItemDefinition;
9-
import org.apollo.game.model.Item;
10-
11-
import com.google.common.base.Preconditions;
12-
1312
/**
1413
* Represents an inventory - a collection of {@link Item}s.
1514
*
@@ -518,6 +517,15 @@ public int remove(Item item) {
518517
return remove(item.getId(), item.getAmount());
519518
}
520519

520+
/**
521+
* Remove all items with the given {@code id} and return the number of
522+
* items removed.
523+
*
524+
* @param id The id of items to remove.
525+
* @return The amount that was removed.
526+
*/
527+
public int removeAll(int id) { return remove(id, getAmount(id)); }
528+
521529
/**
522530
* Removes all the listeners.
523531
*/

0 commit comments

Comments
 (0)