Implemented Strange Plant Random Event

This commit is contained in:
Zerken 2023-11-03 14:55:41 +00:00 committed by Ryan
parent 0eecab4057
commit dbb8b5a133
7 changed files with 190 additions and 2 deletions

View file

@ -72424,5 +72424,21 @@
"examine": "A delicate creature from this strange realm.",
"name": "Fairy",
"id": "4443"
},
{
"examine": "A very strange plant.",
"death_animation": "355",
"name": "Strange Plant",
"defence_level": "300",
"melee_animation": "353",
"lifepoints": "100",
"id": "408",
"magic_level": "200",
"defence_animation": "354"
},
{
"examine": "A very strange plant.",
"name": "Strange Plant",
"id": "407"
}
]

View file

@ -14,6 +14,7 @@ import content.global.ame.events.rivertroll.RiverTrollRENPC
import content.global.ame.events.rockgolem.RockGolemRENPC
import content.global.ame.events.sandwichlady.SandwichLadyRENPC
import content.global.ame.events.shade.ShadeRENPC
import content.global.ame.events.strangeplant.StrangePlantNPC
import content.global.ame.events.swarm.SwarmNPC
import content.global.ame.events.treespirit.TreeSpiritRENPC
import content.global.ame.events.zombie.ZombieRENPC
@ -44,6 +45,7 @@ enum class RandomEvents(val npc: RandomEventNPC, val loot: WeightBasedTable? = n
)),
DRILL_DEMON(npc = SeargentDamienNPC()),
EVIL_CHICKEN(npc = EvilChickenNPC()),
STRANGE_PLANT(npc = StrangePlantNPC()),
SWARM(npc = SwarmNPC()),
EVIL_BOB(npc = EvilBobNPC(), skillIds = intArrayOf(Skills.FISHING, Skills.MAGIC)),
DRUNKEN_DWARF(npc = DrunkenDwarfNPC()),

View file

@ -0,0 +1,35 @@
package content.global.ame.events.strangeplant
import core.api.applyPoison
import core.game.node.entity.Entity
import core.game.node.entity.combat.BattleState
import core.game.node.entity.combat.CombatStyle
import core.game.node.entity.npc.NPC
import core.game.node.entity.npc.NPCBehavior
import core.game.node.entity.player.Player
import core.game.system.timer.impl.AntiMacro
import core.tools.RandomFunction
import org.rs09.consts.NPCs
class StrangePlantBehavior() : NPCBehavior(NPCs.STRANGE_PLANT_408) {
override fun canBeAttackedBy(self: NPC, attacker: Entity, style: CombatStyle, shouldSendMessage: Boolean): Boolean {
return !(attacker !is Player || AntiMacro.getEventNpc(attacker.asPlayer()) != self)
}
override fun beforeAttackFinalized(self: NPC, victim: Entity, state: BattleState) {
state.estimatedHit = RandomFunction.getRandom(3)
if (RandomFunction.roll(10))
applyPoison(victim, self, 10)
}
override fun beforeDamageReceived(self: NPC, attacker: Entity, state: BattleState) {
if (state.estimatedHit > 3)
state.estimatedHit = RandomFunction.getRandom(3)
if (state.secondaryHit > 3)
state.secondaryHit = RandomFunction.getRandom(3)
}
override fun onDeathStarted(self: NPC, killer: Entity) {
AntiMacro.terminateEventNpc(killer.asPlayer())
}
}

View file

@ -0,0 +1,33 @@
package content.global.ame.events.strangeplant
import core.api.addItemOrDrop
import core.api.getAttribute
import core.api.sendMessage
import core.api.setAttribute
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
import core.game.system.timer.impl.AntiMacro
import org.rs09.consts.Items
import org.rs09.consts.NPCs
class StrangePlantListener : InteractionListener {
override fun defineListeners() {
on(NPCs.STRANGE_PLANT_407, IntType.NPC, "pick") { player, node ->
if (AntiMacro.getEventNpc(player) != node) {
sendMessage(player, "This isn't your strange plant.")
return@on true
}
if (!getAttribute(node.asNpc(), "fruit-grown", false)) {
sendMessage(player, "The fruit isn't ready to be picked.")
return@on true
}
if (!getAttribute(node.asNpc(), "fruit-picked", false)) {
setAttribute(node.asNpc(), "fruit-picked", true)
addItemOrDrop(player, Items.STRANGE_FRUIT_464)
}
return@on true
}
}
}

View file

@ -0,0 +1,85 @@
package content.global.ame.events.strangeplant
import content.global.ame.RandomEventNPC
import core.api.*
import core.api.utils.WeightBasedTable
import core.game.interaction.QueueStrength
import core.game.node.entity.npc.NPC
import core.game.world.update.flag.context.Animation
import core.tools.minutesToTicks
import core.tools.secondsToTicks
import org.rs09.consts.NPCs
class StrangePlantNPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(NPCs.STRANGE_PLANT_407) {
private val strangePlantGrowAnim = Animation(348)
private val strangePlantTransformAnim = Animation(351)
private val strangePlantPickedAnim = Animation(350)
private var fruitPicked = false
private var transformed = false
private var attacking = false
override fun init() {
spawnLocation = getPathableCardinal(player, player.location)
super.init()
ticksLeft = minutesToTicks(1)
animate(this, strangePlantGrowAnim)
queueScript(this, strangePlantGrowAnim.duration + 2, QueueStrength.SOFT) {
setAttribute(this, "fruit-grown", true)
return@queueScript stopExecuting(this)
}
}
override fun tick() {
super.tick()
if (getAttribute(this, "fruit-picked", false) && !fruitPicked) {
fruitPicked = true
ticksLeft = secondsToTicks(60)
queueScript(this, 1, QueueStrength.SOFT) { stage: Int ->
when (stage) {
0 -> {
this.animate(strangePlantPickedAnim)
return@queueScript delayScript(this, strangePlantPickedAnim.duration - 1)
}
1 -> {
this.isInvisible = true
terminate()
return@queueScript stopExecuting(this)
}
else -> return@queueScript stopExecuting(this)
}
}
}
if (ticksLeft <= secondsToTicks(10)) {
ticksLeft = secondsToTicks(10)
if (!attacking) {
attacking = true
queueScript(this, 1, QueueStrength.SOFT) { stage: Int ->
when (stage) {
0 -> {
animate(this, strangePlantTransformAnim)
return@queueScript delayScript(this, strangePlantTransformAnim.duration)
}
1 -> {
this.transform(NPCs.STRANGE_PLANT_408)
this.behavior = StrangePlantBehavior()
this.attack(player)
transformed = true
return@queueScript stopExecuting(this)
}
else -> return@queueScript stopExecuting(this)
}
}
}
if (transformed && !this.inCombat())
this.attack(player)
}
}
override fun follow() {
if (transformed)
super.follow()
}
override fun talkTo(npc: NPC) {
}
}

View file

@ -2191,6 +2191,23 @@ fun getPathableRandomLocalCoordinate(target: Entity, radius: Int, center: Locati
return target.location
}
/**
* Returns a pathable cardinal location in a 1 tile radius in order of west, south, east, north.
* @param entity the entity used to check if the loc is pathable
* @param center the center location
*/
fun getPathableCardinal(target: Entity, center: Location) : Location {
var tiles = center.cardinalTiles
for (tile in tiles) {
val path = Pathfinder.find(center, tile, target.size())
if (path.isSuccessful && !path.isMoveNear)
return tile
}
return center
}
/**
* Returns the player's active slayer task.
* @author bushtail

View file

@ -294,10 +294,10 @@ public final class Location extends Node {
public ArrayList<Location> getCardinalTiles() {
ArrayList<Location> locs = new ArrayList<>();
locs.add(transform(0, 1, 0));
locs.add(transform(0, -1, 0));
locs.add(transform(-1, 0, 0));
locs.add(transform(0, -1, 0));
locs.add(transform(1, 0, 0));
locs.add(transform(0, 1, 0));
return locs;
}