Rewrote Canifis warewolf handling, fixed stats

Fixed bandit aggression
This commit is contained in:
GregF 2024-07-13 06:13:31 +00:00 committed by Ryan
parent a44472e559
commit 53357d20f3
18 changed files with 675 additions and 1281 deletions

View file

@ -25464,8 +25464,8 @@
"maxAmount": "1"
}
],
"ids": "1665,6006,6007,6008,6009,6010,6011,6012,6013,6014,6015,6016,6017,6018,6019,6020,6021,6022,6023,6024,6025,6212,6213",
"description": "",
"ids": "6006,6007,6008,6009,6010,6011,6012,6013,6014,6015,6016,6017,6018,6019,6020,6021,6022,6023,6024,6025,6026,6027,6028,6029,6030,6031,6032,6033,6034,6035,6036,6037,6038,6039,6040,6041,6042,6043,6044,6045,6212,6213",
"description": "Werewolves (and human form for Canifis)",
"main": [
{
"minAmount": "5",
@ -43345,280 +43345,6 @@
}
]
},
{
"default": [
{
"minAmount": "1",
"weight": "100.0",
"id": "2859",
"maxAmount": "1"
}
],
"charm": [
{
"minAmount": "1",
"weight": "100.0",
"id": "12158",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "100.0",
"id": "12159",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "100.0",
"id": "12160",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "100.0",
"id": "12163",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "5600.0",
"id": "0",
"maxAmount": "1"
}
],
"ids": "6028",
"description": "",
"main": [
{
"minAmount": "5",
"weight": "50.0",
"id": "2138",
"maxAmount": "5"
},
{
"minAmount": "5",
"weight": "50.0",
"id": "2132",
"maxAmount": "5"
},
{
"minAmount": "5",
"weight": "50.0",
"id": "2136",
"maxAmount": "5"
},
{
"minAmount": "1",
"weight": "50.0",
"id": "1993",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "50.0",
"id": "1325",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "50.0",
"id": "1353",
"maxAmount": "1"
},
{
"minAmount": "50",
"weight": "25.0",
"id": "886",
"maxAmount": "50"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "1157",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "1329",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "1181",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "1109",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "1147",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "830",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "50.0",
"id": "203",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "50.0",
"id": "199",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "50.0",
"id": "201",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "207",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "211",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "215",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "205",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "209",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "5.0",
"id": "213",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "5.0",
"id": "2485",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "5.0",
"id": "217",
"maxAmount": "1"
},
{
"minAmount": "10",
"weight": "50.0",
"id": "995",
"maxAmount": "10"
},
{
"minAmount": "90",
"weight": "50.0",
"id": "995",
"maxAmount": "90"
},
{
"minAmount": "1",
"weight": "50.0",
"id": "6814",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "50.0",
"id": "958",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "50.0",
"id": "7868",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "50.0",
"id": "227",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "5.0",
"id": "1",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "5.0",
"id": "245",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "5.0",
"id": "983",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "5.0",
"id": "239",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "5.0",
"id": "1925",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "5.0",
"id": "440",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "5.0",
"id": "31",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "100.0",
"id": "0",
"maxAmount": "1"
}
]
},
{
"default": [],
"charm": [],

View file

@ -38696,7 +38696,7 @@
},
{
"destroy_message": "Another can be received from pickpocketing Dr. Fenkenstrain in the tower.",
"examine": "Unactivated: The Ring of charos.Activated: The power within this ring has been activated.",
"examine": "The Ring of charos",
"durability": null,
"name": "Ring of charos",
"tradeable": "false",
@ -59397,7 +59397,7 @@
},
{
"destroy_message": "Another can be received from pickpocketing Dr. Fenkenstrain in the tower.",
"examine": "Unactivated: The Ring of charos.Activated: The power within this ring has been activated.",
"examine": "The power within this ring has been activated.",
"durability": null,
"name": "Ring of charos(a)",
"tradeable": "false",

File diff suppressed because it is too large Load diff

View file

@ -1,46 +0,0 @@
package content.region.desert.bandits.handlers
import core.api.*
import core.game.node.entity.Entity
import core.game.node.entity.combat.BattleState
import core.game.node.entity.npc.NPC
import core.game.node.entity.npc.NPCBehavior
import core.game.world.map.RegionManager
import core.tools.RandomFunction
import org.rs09.consts.NPCs
class BanditBehavior : NPCBehavior(NPCs.BANDIT_1926) {
override fun tick(self: NPC): Boolean {
if (!self.inCombat() && RandomFunction.roll(3) && getWorldTicks() % 5 == 0) {
val players = RegionManager.getLocalPlayers(self, 5)
for (player in players) {
if (player.inCombat()) continue
if (hasGodItem(player, God.SARADOMIN)) {
sendChat(self, "Prepare to die, Saradominist scum!")
self.attack(player)
break
}
else if (hasGodItem(player, God.ZAMORAK)) {
sendChat(self, "Prepare to die, Zamorakian scum!")
self.attack(player)
break
}
}
}
return true
}
override fun afterDamageReceived(self: NPC, attacker: Entity, state: BattleState) {
if (getAttribute(self, "alerted-others", false)) return
val otherBandits = RegionManager.getLocalNpcs(self, 3).filter { it.id == self.id }
for (bandit in otherBandits) {
if (!bandit.inCombat())
bandit.attack(attacker)
}
setAttribute(self, "alerted-others", true)
}
override fun onDeathStarted(self: NPC, killer: Entity) {
removeAttribute(self, "alerted-others")
}
}

View file

@ -0,0 +1,62 @@
package content.region.desert.bandits.handlers
import core.api.God
import core.api.hasGodItem
import core.game.node.entity.Entity
import core.game.node.entity.combat.BattleState
import core.game.node.entity.npc.AbstractNPC
import core.game.node.entity.player.Player
import core.game.world.map.Location
import core.game.world.map.RegionManager
import core.plugin.Initializable
import org.rs09.consts.NPCs
@Initializable
class BanditNPC(id: Int = NPCs.BANDIT_1926, location: Location? = null) : AbstractNPC(id, location) {
private val supportRange: Int = 3
override fun construct(id: Int, location: Location, vararg objects: Any): AbstractNPC {
return BanditNPC(id, location)
}
override fun tick() {
if (!inCombat()) {
val players = RegionManager.getLocalPlayers(this, 5)
for (player in players) {
if (player.inCombat()) continue
if (hasGodItem(player, God.SARADOMIN)) {
sendChat("Time to die, Saradominist filth!")
attack(player)
break
} else if (hasGodItem(player, God.ZAMORAK)) {
sendChat("Prepare to suffer, Zamorakian scum!")
attack(player)
break
}
}
}
super.tick()
}
//Clear target on death
override fun finalizeDeath(killer: Entity?) {
super.finalizeDeath(killer)
}
override fun onImpact(entity: Entity?, state: BattleState?) {
if (entity is Player) {
RegionManager.getLocalNpcs(entity, supportRange).forEach {
if (it.id == NPCs.BANDIT_1926 && !it.properties.combatPulse.isAttacking && it != this) {
it.sendChat("You picked the wrong place to start trouble!")
it.attack(entity)
}
}
}
super.onImpact(entity, state)
}
override fun getIds(): IntArray {
return intArrayOf(NPCs.BANDIT_1926)
}
}

View file

@ -1,61 +0,0 @@
package content.region.morytania.canifis.dialogue;
import core.game.dialogue.DialoguePlugin;
import core.game.dialogue.FacialExpression;
import core.game.node.entity.npc.NPC;
import core.plugin.Initializable;
import core.game.node.entity.player.Player;
/**
* Represents the dialogue plugin used for the bros np.c
* @author 'Vexia
* @version 1.0
*/
@Initializable
public final class BrosDialogue extends DialoguePlugin {
/**
* Constructs a new {@code BrosDialogue} {@code Object}.
*/
public BrosDialogue() {
/**
* empty.
*/
}
/**
* Constructs a new {@code BrosDialogue} {@code Object}.
* @param player the player.
*/
public BrosDialogue(Player player) {
super(player);
}
@Override
public DialoguePlugin newInstance(Player player) {
return new BrosDialogue(player);
}
@Override
public boolean open(Object... args) {
npc = (NPC) args[0];
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Out of my way, punk");
stage = 1;
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
switch (stage) {
case 1:
end();
break;
}
return true;
}
@Override
public int[] getIds() {
return new int[] { 6026, 6032 };
}
}

View file

@ -1,61 +0,0 @@
package content.region.morytania.canifis.dialogue;
import core.game.dialogue.DialoguePlugin;
import core.game.dialogue.FacialExpression;
import core.game.node.entity.npc.NPC;
import core.plugin.Initializable;
import core.game.node.entity.player.Player;
/**
* Represents the dialogue plugin used for the gregory npc.
* @author 'Vexia
* @version 1.0
*/
@Initializable
public final class GregoryDialogue extends DialoguePlugin {
/**
* Constructs a new {@code GregoryDialogue} {@code Object}.
*/
public GregoryDialogue() {
/**
* empty.
*/
}
/**
* Constructs a new {@code GregoryDialogue} {@code Object}.
* @param player the player.
*/
public GregoryDialogue(Player player) {
super(player);
}
@Override
public DialoguePlugin newInstance(Player player) {
return new GregoryDialogue(player);
}
@Override
public boolean open(Object... args) {
npc = (NPC) args[0];
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "If I were as ugly as you I would not dare to show my", "face in public!");
stage = 1;
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
switch (stage) {
case 1:
end();
break;
}
return true;
}
@Override
public int[] getIds() {
return new int[] { 6033, 6027, 6043, 6036, 6040, 6038, 6045 };
}
}

View file

@ -0,0 +1,66 @@
package content.region.morytania.canifis.dialogue
import core.api.anyInEquipment
import core.api.toIntArray
import core.game.dialogue.DialoguePlugin
import core.game.dialogue.FacialExpression
import core.game.node.entity.player.Player
import core.plugin.Initializable
import core.tools.END_DIALOGUE
import core.tools.START_DIALOGUE
import org.rs09.consts.Items
@Initializable
class HumanWerewolfDialogue(player: Player? = null) : DialoguePlugin(player) {
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
when (stage){
START_DIALOGUE -> {
// There are 10 random different messages for all of the werewolves in human form
// If you have the Ring of Charos they think you're a werewolf and talk differently
if (anyInEquipment(player, Items.RING_OF_CHAROS_4202, Items.RING_OF_CHAROSA_6465)){
// Nice talks
when ((1..10).random()){
1 -> npcl(FacialExpression.HAPPY, "I bet you have wonderful paws.").also { stage = END_DIALOGUE }
2 -> npcl(FacialExpression.NEUTRAL, "A very miserable day, altogether... enjoy it while it lasts.").also { stage = END_DIALOGUE }
3 -> npcl(FacialExpression.ASKING, "If you catch anyone promise me you'll share.").also { stage = END_DIALOGUE }
4 -> npcl(FacialExpression.ASKING, "I haven't smelt you around here before...").also { stage = END_DIALOGUE }
5 -> npcl(FacialExpression.FRIENDLY, "You smell familiar...").also { stage = END_DIALOGUE }
6 -> npcl(FacialExpression.ASKING, "Seen any humans around here? I'm v-e-r-y hungry.").also { stage = END_DIALOGUE }
7 -> npcl(FacialExpression.FRIENDLY, "You look to me like someone with a healthy taste for blood.").also { stage = END_DIALOGUE }
8 -> npcl(FacialExpression.FRIENDLY, "Good day to you, my friend.").also { stage = END_DIALOGUE }
9 -> npcl(FacialExpression.ASKING, "Fancy going up to the castle for a bit of a snack?").also { stage = END_DIALOGUE }
10 -> npcl(FacialExpression.NEUTRAL, "Give me a moment, I have a bit of someone stuck in my teeth...").also { stage = END_DIALOGUE }
}
}
else {
// Mean talks
when ((1..10).random()){
1 -> npcl(FacialExpression.ANNOYED, "If I were as ugly as you I would not dare to show my face in public!").also { stage = END_DIALOGUE }
2 -> npcl(FacialExpression.ANGRY, "Out of my way, punk.").also { stage = END_DIALOGUE }
// The only one that has a path
3 -> npcl(FacialExpression.ASKING, "Hmm... you smell strange...").also { stage++ }
4 -> npcl(FacialExpression.ANGRY, "Leave me alone.").also { stage = END_DIALOGUE }
5 -> npcl(FacialExpression.ANNOYED, "Don't talk to me again if you value your life!").also { stage = END_DIALOGUE }
6 -> npcl(FacialExpression.ANNOYED, "Get lost!").also { stage = END_DIALOGUE }
7 -> npcl(FacialExpression.ANNOYED, "I don't have anything to give you so leave me alone, mendicant.").also { stage = END_DIALOGUE }
8 -> npcl(FacialExpression.ANGRY, "Have you no manners?").also { stage = END_DIALOGUE }
9 -> npcl(FacialExpression.ANNOYED, "I don't have time for this right now.").also { stage = END_DIALOGUE }
10 -> npcl(FacialExpression.ANGRY, "I have no interest in talking to a pathetic meat bag like yourself.").also{ stage = END_DIALOGUE}
}
}
}
// There's one path that the player can respond to (3 without the ring)
1 -> playerl(FacialExpression.ASKING, "Strange how?").also { stage++ }
2 -> npcl(FacialExpression.EVIL_LAUGH, "Like a human!").also { stage++ }
3 -> playerl(FacialExpression.PANICKED, "Oh! Er... I just ate one is why!").also { stage = END_DIALOGUE }
else -> {
end()
}
}
return true
}
override fun getIds(): IntArray {
return (6026..6046).toIntArray()
}
}

View file

@ -1,61 +0,0 @@
package content.region.morytania.canifis.dialogue;
import core.game.dialogue.DialoguePlugin;
import core.game.dialogue.FacialExpression;
import core.game.node.entity.npc.NPC;
import core.plugin.Initializable;
import core.game.node.entity.player.Player;
/**
* Represents the dialogue plugin used for the irina npc.
* @author 'Vexia
* @version 1.0
*/
@Initializable
public final class IrinaDialogue extends DialoguePlugin {
/**
* Constructs a new {@code IrinaDialogue} {@code Object}.
*/
public IrinaDialogue() {
/**
* empty.
*/
}
/**
* Constructs a new {@code IrinaDialogue} {@code Object}.
* @param player the player.
*/
public IrinaDialogue(Player player) {
super(player);
}
@Override
public DialoguePlugin newInstance(Player player) {
return new IrinaDialogue(player);
}
@Override
public boolean open(Object... args) {
npc = (NPC) args[0];
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Out of my way, punk.");
stage = 0;
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
switch (stage) {
case 0:
end();
break;
}
return true;
}
@Override
public int[] getIds() {
return new int[] { 6035 };
}
}

View file

@ -1,61 +0,0 @@
package content.region.morytania.canifis.dialogue;
import core.game.dialogue.DialoguePlugin;
import core.game.dialogue.FacialExpression;
import core.game.node.entity.npc.NPC;
import core.plugin.Initializable;
import core.game.node.entity.player.Player;
/**
* Represents the dialogue plugin used for the joseph npc.
* @author 'Vexia
* @version 1.0
*/
@Initializable
public final class JosephDialogue extends DialoguePlugin {
/**
* Constructs a new {@code JosephDialogue} {@code Object}.
*/
public JosephDialogue() {
/**
* empty.
*/
}
/**
* Constructs a new {@code JosephDialogue} {@code Object}.
* @param player the player.
*/
public JosephDialogue(Player player) {
super(player);
}
@Override
public DialoguePlugin newInstance(Player player) {
return new JosephDialogue(player);
}
@Override
public boolean open(Object... args) {
npc = (NPC) args[0];
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "I have no interest in talking to a pathetic meat bag like", "yourself.");
stage = 0;
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
switch (stage) {
case 0:
end();
break;
}
return true;
}
@Override
public int[] getIds() {
return new int[] { 6029 };
}
}

View file

@ -1,48 +0,0 @@
package content.region.morytania.canifis.dialogue;
import core.game.dialogue.DialoguePlugin;
import core.game.dialogue.FacialExpression;
import core.game.node.entity.npc.NPC;
import core.plugin.Initializable;
import core.game.node.entity.player.Player;
/**
* Handles the NikitiaDialogue dialogue.
* @author 'Vexia
*/
@Initializable
public class NikitiaDialogue extends DialoguePlugin {
public NikitiaDialogue() {
}
public NikitiaDialogue(Player player) {
super(player);
}
@Override
public DialoguePlugin newInstance(Player player) {
return new NikitiaDialogue(player);
}
@Override
public boolean open(Object... args) {
npc = (NPC) args[0];
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Don't talk to me again if you value your life!");
stage = 0;
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
end();
return true;
}
@Override
public int[] getIds() {
return new int[] { 6042 };
}
}

View file

@ -1,52 +0,0 @@
package content.region.morytania.canifis.dialogue;
import core.game.dialogue.DialoguePlugin;
import core.game.dialogue.FacialExpression;
import core.game.node.entity.npc.NPC;
import core.plugin.Initializable;
import core.game.node.entity.player.Player;
/**
* Handles the SofiyaDialogue dialogue.
* @author 'Vexia
*/
@Initializable
public class SofiyaDialogue extends DialoguePlugin {
public SofiyaDialogue() {
}
public SofiyaDialogue(Player player) {
super(player);
}
@Override
public DialoguePlugin newInstance(Player player) {
return new SofiyaDialogue(player);
}
@Override
public boolean open(Object... args) {
npc = (NPC) args[0];
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Out of my way punk.");
stage = 1;
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
switch (stage) {
case 1:
end();
break;
}
return true;
}
@Override
public int[] getIds() {
return new int[] { 6039, 6030, 6037 };
}
}

View file

@ -1,48 +0,0 @@
package content.region.morytania.canifis.dialogue;
import core.game.dialogue.DialoguePlugin;
import core.game.dialogue.FacialExpression;
import core.game.node.entity.npc.NPC;
import core.plugin.Initializable;
import core.game.node.entity.player.Player;
/**
* Handles the SvetlanaDialogue dialogue.
* @author 'Vexia
*/
@Initializable
public class SvetlanaDialogue extends DialoguePlugin {
public SvetlanaDialogue() {
}
public SvetlanaDialogue(Player player) {
super(player);
}
@Override
public DialoguePlugin newInstance(Player player) {
return new SvetlanaDialogue(player);
}
@Override
public boolean open(Object... args) {
npc = (NPC) args[0];
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Hmm... you smell strange...");
stage = 0;
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
end();
return true;
}
@Override
public int[] getIds() {
return new int[] { 6034 };
}
}

View file

@ -1,61 +0,0 @@
package content.region.morytania.canifis.dialogue;
import core.game.dialogue.DialoguePlugin;
import core.game.dialogue.FacialExpression;
import core.game.node.entity.npc.NPC;
import core.plugin.Initializable;
import core.game.node.entity.player.Player;
/**
* Represents the yadviga dialogue plugin.
* @author 'Vexia
* @version 1.0
*/
@Initializable
public final class YadvigaDialogue extends DialoguePlugin {
/**
* Constructs a new {@code YadvigaDialogue} {@code Object}.
*/
public YadvigaDialogue() {
/**
* empty.
*/
}
/**
* Constructs a new {@code YadvigaDialogue} {@code Object}.
* @param player the player.
*/
public YadvigaDialogue(Player player) {
super(player);
}
@Override
public DialoguePlugin newInstance(Player player) {
return new YadvigaDialogue(player);
}
@Override
public boolean open(Object... args) {
npc = (NPC) args[0];
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Get lost!");
stage = 0;
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
switch (stage) {
case 0:
end();
break;
}
return true;
}
@Override
public int[] getIds() {
return new int[] { 6041 };
}
}

View file

@ -1,57 +0,0 @@
package content.region.morytania.canifis.dialogue;
import core.game.dialogue.DialoguePlugin;
import core.game.dialogue.FacialExpression;
import core.game.node.entity.npc.NPC;
import core.plugin.Initializable;
import core.game.node.entity.player.Player;
/**
* Represents the dialogue used for the yuri npc.
* @author 'Vexia
* @version 1.0
*/
@Initializable
public final class YuriDialogue extends DialoguePlugin {
/**
* Constructs a new {@code YuriDialogue} {@code Object}.
*/
public YuriDialogue() {
/**
* empty.
*/
}
/**
* Constructs a new {@code YuriDialogue} {@code Object}.
* @param player the player.
*/
public YuriDialogue(Player player) {
super(player);
}
@Override
public DialoguePlugin newInstance(Player player) {
return new YuriDialogue(player);
}
@Override
public boolean open(Object... args) {
npc = (NPC) args[0];
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Hmm... you smell strange...");
stage = 0;
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
end();
return true;
}
@Override
public int[] getIds() {
return new int[] { 6028 };
}
}

View file

@ -1,66 +0,0 @@
package content.region.morytania.canifis.handlers;
import core.cache.def.impl.NPCDefinition;
import core.game.interaction.OptionHandler;
import core.game.node.Node;
import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player;
import core.game.system.task.Pulse;
import core.game.world.GameWorld;
import core.game.world.update.flag.context.Animation;
import core.plugin.Initializable;
import core.plugin.Plugin;
/**
* Represents the plugin used to handle the attacking of a werwolf.
* @author 'Vexia
* @version 1.0
*/
@Initializable
public final class CanafisWereWolfPlugin extends OptionHandler {
/**
* Represents the animation to use.
*/
private static final Animation ANIMATION = new Animation(6543);
/**
* Represents the id to transform into.
*/
private static final int TRANSFORM_ID = 6006;
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
for (int i = 6026; i < 6046; i++) {
NPCDefinition.forId(i).getHandlers().put("option:attack", this);
}
return this;
}
@Override
public boolean handle(final Player player, Node node, String option) {
if (!player.getEquipment().contains(2952, 1)) {
player.lock(2);
final NPC n = (NPC) node;
final NPC newN = NPC.create(TRANSFORM_ID, n.getLocation());
newN.init();
newN.animate(ANIMATION);
n.clear();
newN.lock(2);
newN.setRespawn(false);
newN.setAttribute("original", n.getId());
newN.setAttribute("loc", n.getProperties().getSpawnLocation());
GameWorld.getPulser().submit(new Pulse(2) {
@Override
public boolean pulse() {
newN.getProperties().getCombatPulse().attack(player);
return true;
}
});
} else {
player.getProperties().getCombatPulse().attack(node);
}
return true;
}
}

View file

@ -0,0 +1,61 @@
package content.region.morytania.canifis.handlers
import core.api.*
import core.game.interaction.QueueStrength
import core.game.node.entity.Entity
import core.game.node.entity.combat.BattleState
import core.game.node.entity.combat.DeathTask
import core.game.node.entity.npc.NPC
import core.game.node.entity.npc.NPCBehavior
import core.game.node.entity.player.Player
import core.game.world.update.flag.context.Animation
import org.rs09.consts.Items
class WerewolfBehavior : NPCBehavior(*HUMAN_NPCS) {
companion object {
// There are 20 humans that can turn into werewolves. They are all in series, so a range toIntArray() is easier.
private val HUMAN_NPCS = (6026 .. 6045).toIntArray()
private val WEREWOLF_NPCS = (6006 .. 6025).toIntArray()
private val HUMAN_OUT_ANIMATION = Animation(6554)
private val WEREWOLF_IN_ANIMATION = Animation(6543) // This is not used as there is a corresponding gfx.
private val WEREWOLF_IN_GFXS = (1079 .. 1098).toIntArray() // Play each werewolf's gfx with the animation.
}
override fun afterDamageReceived(self: NPC, attacker: Entity, state: BattleState) {
if(DeathTask.isDead(self)){
// Don't transform if you are killed
return
}
if (attacker is Player) {
if (!inEquipment(attacker, Items.WOLFBANE_2952, 1) && self.id in HUMAN_NPCS) {
delayAttack(self, 3)
delayAttack(attacker, 3)
lock(self, 3)
queueScript(self, 0, QueueStrength.SOFT) { stage: Int ->
when (stage) {
0 -> {
visualize(self, HUMAN_OUT_ANIMATION, WEREWOLF_IN_GFXS[self.id - 6026])
return@queueScript delayScript(self, WEREWOLF_IN_ANIMATION.duration)
}
1 -> {
transformNpc(self, WEREWOLF_NPCS[self.id - 6026], 200)
return@queueScript delayScript(self, 1)
}
2 -> {
self.properties.combatPulse.attack(attacker)
return@queueScript stopExecuting(self)
}
else -> return@queueScript stopExecuting(self)
}
}
}
}
}
override fun onRespawn(self: NPC) {
if (self.id in WEREWOLF_NPCS){
self.reTransform()
}
super.onRespawn(self)
}
}

View file

@ -1,50 +0,0 @@
package content.region.morytania.canifis.handlers;
import core.game.node.entity.Entity;
import core.game.node.entity.npc.AbstractNPC;
import core.game.node.entity.npc.NPC;
import core.plugin.Initializable;
import core.game.world.map.Location;
/**
* Represents the tutorial chicken npc.
* @author 'Vexia
* @version 1.0
*/
@Initializable
public final class WerewolfNPC extends AbstractNPC {
/**
* Constructs a new {@code WerewolfNPC} {@code Object}.
* @param id the id.
* @param location the location.
*/
public WerewolfNPC(int id, Location location) {
super(id, location, true);
}
/**
* Constructs a new {@code WerewolfNPC} {@code Object}.
*/
public WerewolfNPC() {
super(0, null);
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new WerewolfNPC(id, location);
}
@Override
public void finalizeDeath(Entity killer) {
super.finalizeDeath(killer);
NPC nn = NPC.create(getAttribute("original", 6026), getAttribute("loc", getLocation()));
nn.init();
}
@Override
public int[] getIds() {
return new int[] { 6006 };
}
}