Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
a3ed4be
Create GnomeStrongholdCoursePlugin.kt
Eikenb00m Nov 23, 2025
4e30b58
Added more obstacles and Course State
Eikenb00m Nov 23, 2025
3fc947f
fix bonus xp
Eikenb00m Nov 23, 2025
19f9412
Named Attribute
Eikenb00m Nov 24, 2025
04f96d0
Update GnomeStrongholdCoursePlugin.kt
Eikenb00m Nov 24, 2025
f09ae22
Add Mark of Grace spawn to Gnome Agility Course
Eikenb00m Nov 24, 2025
15262f2
Track and display Gnome Agility lap count
Eikenb00m Nov 24, 2025
fa6b8e1
MarkTestCommand
Mark7625 Nov 26, 2025
4efdb5f
create Draynor rooftop
Devexity-fivem Nov 26, 2025
7ed3b72
Fix Mark of Grace spawn logic and expose groundItems
Eikenb00m Dec 1, 2025
31df4f2
Support RSCM Ground items
Mark7625 Dec 1, 2025
801c9fb
Merge branch 'Agility' of https://github.com/Eikenb00m/Alter-C into p…
Mark7625 Dec 1, 2025
f1a4dcb
Update GnomeStrongholdCoursePlugin.kt
Eikenb00m Dec 1, 2025
929bd45
Update GroundItem.kt
Mark7625 Dec 1, 2025
7b15d84
Merge branch 'Agility' of https://github.com/Eikenb00m/Alter-C into p…
Mark7625 Dec 1, 2025
864f256
Refactor Mark of Grace logic into service class
Eikenb00m Dec 1, 2025
d30dffa
Merge branch 'Agility' of https://github.com/Eikenb00m/Alter-C into A…
Eikenb00m Dec 1, 2025
be0ac0e
Update MarkOfGraceService.kt
Eikenb00m Dec 1, 2025
24c752f
Update MarkOfGraceService.kt
Eikenb00m Dec 1, 2025
3fe3651
Update GnomeStrongholdCoursePlugin.kt
Eikenb00m Dec 1, 2025
5950080
Update MarkOfGraceService.kt
Eikenb00m Dec 1, 2025
473feb4
Refactor agility course plugins into subpackages
Eikenb00m Dec 1, 2025
41a1e19
Create GeneralShortcuts.kt
Eikenb00m Dec 1, 2025
b4f33e4
Delete GeneralShortcuts.kt
Eikenb00m Dec 2, 2025
2fcd084
Fixed some anims
Eikenb00m Dec 2, 2025
5f45ffe
Update .gitignore
Eikenb00m Dec 4, 2025
c9431e6
Update with upstream main
Eikenb00m Dec 4, 2025
af3b0ff
Merge remote-tracking branch 'upstream/main' into Agility
Eikenb00m Dec 4, 2025
1302ca6
Update MarkOfGraceService.kt
Eikenb00m Dec 4, 2025
7cdf7cf
Create BarbianOutpostCoursePlugin.kt
Eikenb00m Dec 4, 2025
a249efe
Update BarbianOutpostCoursePlugin.kt
Eikenb00m Dec 6, 2025
f52721d
First fail version
Eikenb00m Dec 6, 2025
f3069d3
Fixed damage
Eikenb00m Dec 8, 2025
16f9ea2
Update LadderPlugin.kt
Eikenb00m Dec 8, 2025
eb4a47c
Update BarbianOutpostCoursePlugin.kt
Eikenb00m Dec 8, 2025
0cb813a
Create ShayzienCoursePlugin.kt
Eikenb00m Dec 8, 2025
4f7fd54
Ai remove of obstacle handle
Eikenb00m Dec 8, 2025
50d85ad
Update ShayzienCoursePlugin.kt
Eikenb00m Dec 8, 2025
dfa64ce
Full basic course
Eikenb00m Dec 9, 2025
04ac412
Preps for advanced stage
Eikenb00m Dec 9, 2025
7fd0d3e
Update ShayzienCoursePlugin.kt
Eikenb00m Dec 9, 2025
8c8c9dd
Update ShayzienCoursePlugin.kt
Eikenb00m Dec 9, 2025
456b71a
Update ShayzienCoursePlugin.kt
Eikenb00m Dec 11, 2025
ecb4272
Update ShayzienCoursePlugin.kt
Eikenb00m Dec 12, 2025
61aa743
override walk in BAS
advnau Dec 12, 2025
1da0af9
Update ShayzienCoursePlugin.kt
advnau Dec 12, 2025
8c4d04c
Update PlayerInfo.kt
advnau Dec 12, 2025
a30107c
Revert "Update ShayzienCoursePlugin.kt"
advnau Dec 12, 2025
ce90f02
Update ShayzienCoursePlugin.kt
advnau Dec 12, 2025
e5ed298
add: noclip option to mq
advnau Dec 12, 2025
0dd683a
add: ability to force steps to a dest
advnau Dec 12, 2025
d329cc2
Update ShayzienCoursePlugin.kt
Eikenb00m Dec 18, 2025
f9d1d8b
Converted Gnome course to new structure
Eikenb00m Dec 18, 2025
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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,8 @@ dump.hprof
/web-api/website/node_modules
/content/src/main/kotlin/generated/org/alter/tables
/content/src/main/kotlin/org/generated
<<<<<<< HEAD
/data/cfg/gamevals-binary
=======
*.dat
>>>>>>> upstream/main
18 changes: 17 additions & 1 deletion content/src/main/kotlin/org/alter/objects/ladder/LadderPlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,23 @@ class LadderPlugin : PluginEvent() {
player.moveTo(3210, 9616, 0)
}
onObjectOption("objects.ladder_from_cellar", "climb-up") {
player.moveTo(3210, 3216, 0)
when(player.tile.regionId) {
10139 -> {
player.moveTo(2547, 3552, 0)
}
12950 -> {
player.moveTo(3210, 3216, 0)
}
else -> player.message("Nothing interesting happens.")
}
}
onObjectOption("objects.ladder_outside_to_underground", "climb-down") {
when(player.tile.regionId) {
10039 -> {
player.moveTo(2548, 9951, 0)
}
else -> player.message("Nothing interesting happens.")
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,302 @@
package org.alter.skills.agility.regularcourses

import org.alter.api.HitType
import org.alter.api.Skills
import org.alter.api.ext.filterableMessage
import org.alter.api.ext.hit
import org.alter.game.model.Direction
import org.alter.game.model.ForcedMovement
import org.alter.game.model.Tile
import org.alter.game.model.attr.AttributeKey
import org.alter.game.model.entity.Player
import org.alter.game.model.move.moveTo
import org.alter.game.pluginnew.PluginEvent
import org.alter.game.pluginnew.event.impl.onObjectOption
import org.alter.rscm.RSCM
import org.alter.skills.agility.MarkOfGraceService

class BarbianOutpostCoursePlugin : PluginEvent() {

private val MAX_STAGES = 8
private val BONUS_XP = 46.3
private val STRENGTH_XP = 41.3

private val DROP_CHANCE = 1.0 / 5.0 // 20%

private val FAIL_ROPE = 1.0 / 3.0
private val FAIL_LOG = 1.0 / 10.0
private val FAIL_LEDGE = 1.0 / 7.0

private val MARK_SPAWN_TILES = listOf(
Tile(2504, 3545, 1),
Tile(2533, 3555, 0)
)
private val GraceService = MarkOfGraceService(
spawnTiles = MARK_SPAWN_TILES,
dropChance = DROP_CHANCE
)

val BARBARIAN_AGILITY_STAGE = AttributeKey<Int>("BarbarianAgilityStage")
private fun Player.getStage(): Int = attr[BARBARIAN_AGILITY_STAGE] ?: 0
private fun Player.setStage(v: Int) { attr[BARBARIAN_AGILITY_STAGE] = v }

val BARBARIAN_LAPS = AttributeKey<Int>("BarbarianAgilityLaps")
private fun Player.getLaps(): Int = attr[BARBARIAN_LAPS] ?: 0
private fun Player.setLaps(v: Int) { attr[BARBARIAN_LAPS] = v }

override fun init() {

onObjectOption("objects.obstical_ropeswing1", "Swing-on") {
handleObstacle(
player = player,
destination = Tile(2551, 3549, 0),
anim = "sequences.human_ropeswing_long",
duration1 = 5,
duration2 = 250,
angle = Direction.SOUTH.angle,
xp = 22.0,
messageStart = "You grab the rope...",
messageEnd = "... and land safely.",
stage = 1,

failChance = FAIL_ROPE,
onFail = { p ->
p.queue {
p.filterableMessage("You lose your grip and fall the pit below!")
p.animate("sequences.human_ropeswing_long_miss")
wait(3)
p.moveTo(Tile(2552, 9950, 0))
wait(1)
p.animate(RSCM.NONE)
p.hit(damage = 2, type = HitType.HIT)
}
}
)
}

onObjectOption("objects.barbarian_log_balance1", "walk-across") {
handleObstacle(
player = player,
destination = Tile(2541, 3546, 0),
anim = "sequences.human_walk_logbalance_loop",
duration1 = 250,
duration2 = 250,
angle = Direction.WEST.angle,
xp = 13.7,
messageStart = "You walk carefully across the slippery log...",
messageEnd = "... and make it safely to the other side.",
stage = 2,

failChance = FAIL_LOG,
onFail = { p ->
p.queue {
p.filterableMessage("You lose your footing and fall off the log!")
p.animate("sequences.human_walk_logbalance_stumble")
wait(1)
p.animate("sequences.human_drowning")
wait(2)
p.moveTo(Tile(2545, 3546, 0))
wait(1)
p.hit(damage = 3, type = HitType.HIT)
}
}
)
}

onObjectOption("objects.agility_obstical_net_barbarian", "climb-over") {
if (player.tile.z !in 3545..3546) return@onObjectOption
handleObstacle(
player = player,
destination = Tile(2537, player.tile.z, 1),
anim = "sequences.human_reachforladder",
simpleMove = true,
xp = 8.2,
messageStart = "You climb up the netting...",
stage = 3
)
}

onObjectOption("objects.balancing_ledge1", "Walk-across") {
handleObstacle(
player = player,
destination = Tile(2532, 3547, 1),
anim = "sequences.human_walk_sidestepl",
duration1 = 5,
duration2 = 250,
angle = Direction.WEST.angle,
xp = 22.0,
messageStart = "You carefully edge across the ledge...",
stage = 4,

failChance = FAIL_LEDGE,
onFail = { p ->
p.queue {
p.filterableMessage("You lose your balance and fall!")
p.animate("sequences.human_sidestep_fall")
wait(2)
p.moveTo(Tile(2534, 3546, 0))
wait(1)
p.hit(damage = 2, type = HitType.HIT)
p.animate(RSCM.NONE)
}
}

)
}

onObjectOption("objects.barbarian_laddertop_norim", "Climb-down") {
handleObstacle(
player = player,
destination = Tile(2532, 3546, 0),
anim = "sequences.human_reachforladder",
simpleMove = true,
messageStart = "You climb down the ladder...",
stage = 5
)
}

onObjectOption("objects.castlecrumbly1", "climb-over") {

when (player.tile.x) {

2535, 2536 ->
handleObstacle(
player = player,
destination = Tile(2537, 3553, 0),
anim = "sequences.human_walk_crumbledwall",
simpleMove = true,
xp = 13.7,
messageStart = "You climb over the crumbling wall...",
stage = 6,
)

2538, 2539 ->
handleObstacle(
player = player,
destination = Tile(2540, 3553, 0),
anim = "sequences.human_walk_crumbledwall",
simpleMove = true,
xp = 13.7,
messageStart = "You climb over the crumbling wall...",
stage = 7,
)

2541, 2542 ->
handleObstacle(
player = player,
destination = Tile(2543, 3553, 0),
anim = "sequences.human_walk_crumbledwall",
simpleMove = true,
xp = 13.7,
messageStart = "You climb over the crumbling wall...",
stage = 8,
endStage = true,
)
}
}
}

private fun handleObstacle(
player: Player,
destination: Tile,
simpleMove: Boolean = false,
angle: Int? = null,
duration1: Int? = null,
duration2: Int? = null,
anim: String? = null,
xp: Double = 0.0,
messageStart: String? = null,
messageEnd: String? = null,
stage: Int = -1,
endStage: Boolean = false,

failChance: Double = 0.0,
onFail: ((Player) -> Unit)? = null
) {

val doForcedMove = angle != null && duration1 != null && duration2 != null
val current = player.getStage()

val isNext = current + 1 == stage
val isRepeat = current == stage

if (isNext) {
player.setStage(stage)
} else if (!isRepeat) {
player.setStage(0)
}

player.queue {

if (failChance > 0 && Math.random() < failChance) {
player.setStage(0)
onFail?.invoke(player)
return@queue
}

messageStart?.let { player.filterableMessage(it) }
anim?.let { player.animate(it) }

if (doForcedMove) {
val movement = ForcedMovement.of(
src = player.tile,
dst = destination,
clientDuration1 = duration1,
clientDuration2 = duration2,
directionAngle = angle
)
player.forceMove(this, movement)
wait(1)
player.animate(RSCM.NONE)

} else if (simpleMove) {
wait(2)
player.moveTo(destination)
wait(1)
player.animate(RSCM.NONE)
}

wait(1)

if (xp > 0.0)
player.addXp(Skills.AGILITY, xp)

messageEnd?.let { player.filterableMessage(it) }

handleStage(player, stage, endStage)
}
}

private fun handleStage(
player: Player,
stage: Int,
endStage: Boolean
) {
val cur = player.getStage()

if (!endStage && stage >= 0) {
if (stage == cur + 1) {
player.setStage(stage)
}
return
}

if (endStage) {
val completed = cur == MAX_STAGES

if (completed) {
player.addXp(Skills.AGILITY, BONUS_XP)
player.addXp(Skills.STRENGTH, STRENGTH_XP)

val laps = player.getLaps() + 1
player.setLaps(laps)

player.filterableMessage("Your Barbarian Agility lap count is: <col=ff0000>$laps</col>.")

GraceService.spawnMarkofGrace(player)
}

player.setStage(0)
}
}
}
Loading