Reintroduced PvP to level 49 deep wilderness and above (beyond the gate)

Traveling into the PvP area will auto-skull the player, but only whilst they remain in the area
PvP in the deep wilderness does not apply a hard skull
Deep wilderness soft skull is removed immediately upon leaving the deep wilderness
Gates into the deep wilderness now give a warning about the danger of entering
Gates allowing exit from the deep wilderness will not allow a player to leave if they are in combat
The obelisk teleporter in the deep wilderness will not allow a player to use it if they are in combat
All NPCs in the deep wilderness now drop PvP gear and brawlers
The drop rate of PvP gear and brawlers in the deep wilderness has been boosted
Fixed an issue that allowed PvP outside of explicit PvP scenarios
This commit is contained in:
Ceikry 2023-06-29 11:10:25 +00:00 committed by Ryan
parent 9b822d1dff
commit cb16fe4305
9 changed files with 182 additions and 60 deletions

View file

@ -22,7 +22,6 @@
<ObjectAction mode="add" id="39242" x="2955" y="3273" z="0" direction="w"/> <ObjectAction mode="add" id="39242" x="2955" y="3273" z="0" direction="w"/>
<ObjectAction mode="add" id="39241" x="2955" y="3274" z="0" /> <ObjectAction mode="add" id="39241" x="2955" y="3274" z="0" />
<ObjectAction mode="add" id="20987" x="2821" y="2996" z="0" direction="s"/> <ObjectAction mode="add" id="20987" x="2821" y="2996" z="0" direction="s"/>
<ObjectAction mode="add" id="9472" x="3353" y="3951" z="0" direction="s"/>
<ObjectAction mode="add" id="21301" x="2662" y="3162" z="0" direction="e"/> <ObjectAction mode="add" id="21301" x="2662" y="3162" z="0" direction="e"/>
<ObjectAction mode="add" id="4176" x="2629" y="3661" z="2" type="4" direction="e"/> <ObjectAction mode="add" id="4176" x="2629" y="3661" z="2" type="4" direction="e"/>

View file

@ -38,6 +38,34 @@ class BankBoothListener : InteractionListener {
Scenery.BANK_BOOTH_29085, Scenery.BANK_BOOTH_30015, Scenery.BANK_BOOTH_30016, Scenery.BANK_BOOTH_34205, Scenery.BANK_BOOTH_29085, Scenery.BANK_BOOTH_30015, Scenery.BANK_BOOTH_30016, Scenery.BANK_BOOTH_34205,
Scenery.BANK_BOOTH_34752, Scenery.BANK_BOOTH_35647, Scenery.BANK_BOOTH_36786, Scenery.BANK_BOOTH_37474 Scenery.BANK_BOOTH_34752, Scenery.BANK_BOOTH_35647, Scenery.BANK_BOOTH_36786, Scenery.BANK_BOOTH_37474
) )
public fun convertToNotes (used: Node, player: Player) {
val item = used as Item
if (item.noteChange != item.id) {
if (item.definition.isUnnoted) {
val amount = amountInInventory(player, item.id)
if (removeItem(player, Item(item.id, amount))) {
addItem(player, item.noteChange, amount)
}
} else {
var amount = item.amount
val freeSlotCount = freeSlots(player)
if (amount > freeSlotCount) {
amount = freeSlotCount
}
if (removeItem(player, Item(item.id, amount))) {
addItem(player, item.noteChange, amount)
}
}
return
}
sendMessage(player, "This item can't be noted.")
}
} }
/** /**
@ -147,31 +175,7 @@ class BankBoothListener : InteractionListener {
return true return true
} }
val item = used as Item convertToNotes (used, player)
if (item.noteChange != item.id) {
if (item.definition.isUnnoted) {
val amount = amountInInventory(player, item.id)
if (removeItem(player, Item(item.id, amount))) {
addItem(player, item.noteChange, amount)
}
} else {
var amount = item.amount
val freeSlotCount = freeSlots(player)
if (amount > freeSlotCount) {
amount = freeSlotCount
}
if (removeItem(player, Item(item.id, amount))) {
addItem(player, item.noteChange, amount)
}
}
return true
}
sendMessage(player, "This item can't be noted.")
return true return true
} }

View file

@ -1,11 +1,13 @@
package content.minigame.allfiredup package content.minigame.allfiredup
import core.game.dialogue.DialoguePlugin import core.ServerConstants
import core.game.dialogue.*
import core.game.node.entity.npc.NPC import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player import core.game.node.entity.player.Player
import core.game.node.entity.skill.Skills import core.game.node.entity.skill.Skills
import core.game.node.item.Item import core.game.node.item.Item
import core.plugin.Initializable import core.plugin.Initializable
import content.region.wilderness.dialogue.*
import org.rs09.consts.Items import org.rs09.consts.Items
private val VALID_LOGS = arrayOf(Items.LOGS_1511, Items.OAK_LOGS_1521, Items.WILLOW_LOGS_1519, Items.MAPLE_LOGS_1517, Items.YEW_LOGS_1515, Items.MAGIC_LOGS_1513) private val VALID_LOGS = arrayOf(Items.LOGS_1511, Items.OAK_LOGS_1521, Items.WILLOW_LOGS_1519, Items.MAPLE_LOGS_1517, Items.YEW_LOGS_1515, Items.MAGIC_LOGS_1513)
@ -20,6 +22,7 @@ class BeaconTenderDialogue(player: Player? = null) : core.game.dialogue.Dialogue
} }
override fun open(vararg args: Any?): Boolean { override fun open(vararg args: Any?): Boolean {
npc = (args[0] as NPC).getShownNPC(player)
index = getIndexOf((args[0] as NPC).originalId) index = getIndexOf((args[0] as NPC).originalId)
if(index == content.minigame.allfiredup.AFUBeacon.GWD.ordinal && player.skills.getLevel(Skills.SUMMONING) < 81){ if(index == content.minigame.allfiredup.AFUBeacon.GWD.ordinal && player.skills.getLevel(Skills.SUMMONING) < 81){
npc("Awwf uurrrhur","(You need 81 Summoning to communicate with Nanuq.)") npc("Awwf uurrrhur","(You need 81 Summoning to communicate with Nanuq.)")
@ -27,11 +30,10 @@ class BeaconTenderDialogue(player: Player? = null) : core.game.dialogue.Dialogue
return true return true
} }
if(index == content.minigame.allfiredup.AFUBeacon.MONASTERY.ordinal && player.skills.getLevel(Skills.PRAYER) < 53){ if(index == content.minigame.allfiredup.AFUBeacon.MONASTERY.ordinal && player.skills.getLevel(Skills.PRAYER) < 53){
npc("I will aid you when your devotion is","strong enough.","(You need 53 Prayer for him to watch the beacon.)") npc("I will aid you when your devotion is","strong enough.","(You need 53 Prayer for him to assist you.)")
stage = 1000 stage = 1000
return true return true
} }
npc = (args[0] as NPC).getShownNPC(player)
npc("Hello, adventurer.") npc("Hello, adventurer.")
return true return true
} }

View file

@ -0,0 +1,52 @@
package content.region.wilderness.handlers
import core.api.*
import core.game.interaction.*
import core.game.node.entity.player.Player
import core.game.node.scenery.Scenery
import core.game.node.Node
import core.game.global.action.DoorActionHandler
import core.game.dialogue.*
import core.tools.*
class WildernessGateHandler : InteractionListener {
val gates = intArrayOf(1597, 1596)
override fun defineListeners() {
on (gates, IntType.SCENERY, "open", handler = ::handleGate)
}
private fun handleGate (player: Player, node: Node) : Boolean {
val isEntering = !player.skullManager.isDeepWilderness()
if (isEntering)
openDialogue (player, GateDialogue(node.asScenery()))
else {
if (player.properties.combatPulse.isInCombat)
sendMessage (player, "You cannot leave while you are under attack.")
else {
DoorActionHandler.handleAutowalkDoor (player, node.asScenery())
player.skullManager.isDeepWilderness = false
}
}
return true
}
class GateDialogue (val gate: Scenery) : DialogueFile() {
override fun handle (interfaceId: Int, buttonId: Int) {
when (stage) {
0 -> sendDialogueLines(player!!, "WARNING!", "Beyond this gate you enter the deep wilderness!", "Anyone will be able to attack you without consequence!", "You WILL NOT be able to leave during combat!").also { stage++ }
1 -> showTopics (
Topic(FacialExpression.NEUTRAL, "I wish to proceed.", 10, true),
Topic(FacialExpression.NEUTRAL, "Nevermind.", END_DIALOGUE, true)
)
10 -> {
end()
DoorActionHandler.handleAutowalkDoor (player!!, gate)
player!!.skullManager.isDeepWilderness = true
}
}
}
}
}

View file

@ -43,6 +43,12 @@ public final class WildernessObeliskPlugin extends OptionHandler {
if (stationObelisk == null) { if (stationObelisk == null) {
return false; return false;
} }
if (player.getSkullManager().isDeepWilderness()) {
if (player.getProperties().getCombatPulse().isInCombat()) {
player.sendMessage("You can't use this while in combat.");
return false;
}
}
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
int x = stationObelisk.getLocation().getX(); int x = stationObelisk.getLocation().getX();
int y = stationObelisk.getLocation().getY(); int y = stationObelisk.getLocation().getY();

View file

@ -86,6 +86,8 @@ import static core.api.ContentAPIKt.*;
import static core.game.system.command.sets.StatAttributeKeysKt.STATS_BASE; import static core.game.system.command.sets.StatAttributeKeysKt.STATS_BASE;
import static core.game.system.command.sets.StatAttributeKeysKt.STATS_DEATHS; import static core.game.system.command.sets.StatAttributeKeysKt.STATS_DEATHS;
import static core.tools.GlobalsKt.colorize; import static core.tools.GlobalsKt.colorize;
import static core.game.world.map.zone.impl.WildernessZone.WILDERNESS_PROT_ATTR;
import static core.game.world.map.zone.impl.WildernessZone.WILDERNESS_HIGHER_NEXTFEE;
/** /**
* Represents a player entity. * Represents a player entity.
@ -549,6 +551,16 @@ public class Player extends Entity {
return this.getIndex() | 0x8000; return this.getIndex() | 0x8000;
} }
@Override
public void onAttack (Entity e) {
if (e instanceof Player) {
Player p = (Player) e;
if (skullManager.isWildernessDisabled()) {
return;
}
}
}
@Override @Override
public CombatSwingHandler getSwingHandler(boolean swing) { public CombatSwingHandler getSwingHandler(boolean swing) {
CombatStyle style = getProperties().getCombatPulse().getStyle(); CombatStyle style = getProperties().getCombatPulse().getStyle();
@ -716,6 +728,18 @@ public class Player extends Entity {
if (entity instanceof NPC && !((NPC) entity).getDefinition().hasAction("attack") && !((NPC) entity).isIgnoreAttackRestrictions(this)) { if (entity instanceof NPC && !((NPC) entity).getDefinition().hasAction("attack") && !((NPC) entity).isIgnoreAttackRestrictions(this)) {
return false; return false;
} }
if (entity instanceof Player) {
Player p = (Player) entity;
if (p.getSkullManager().isWilderness() && skullManager.isWilderness()) {
if (!GameWorld.getSettings().getWild_pvp_enabled())
return false;
if (p.getSkullManager().hasWildernessProtection())
return false;
if (skullManager.hasWildernessProtection())
return false;
return true;
} else return false;
}
return super.isAttackable(entity, style, message); return super.isAttackable(entity, style, message);
} }

View file

@ -3,10 +3,14 @@ package core.game.node.entity.player.link;
import core.game.node.entity.Entity; import core.game.node.entity.Entity;
import core.game.node.entity.player.Player; import core.game.node.entity.player.Player;
import core.game.node.entity.state.EntityState; import core.game.node.entity.state.EntityState;
import core.ServerConstants;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static core.tools.GlobalsKt.colorize;
import static core.game.world.map.zone.impl.WildernessZone.WILDERNESS_PROT_ATTR;
/** /**
* Represents a managing class of the active player skulls. * Represents a managing class of the active player skulls.
* @author Vexia * @author Vexia
@ -49,6 +53,8 @@ public final class SkullManager {
*/ */
private boolean skullCheckDisabled; private boolean skullCheckDisabled;
private boolean deepWilderness;
/** /**
* Constructs a new {@code SkullManager} {@code Object}. * Constructs a new {@code SkullManager} {@code Object}.
* @param player the player. * @param player the player.
@ -95,6 +101,7 @@ public final class SkullManager {
skullCauses.clear(); skullCauses.clear();
setSkullIcon(-1); setSkullIcon(-1);
setSkulled(false); setSkulled(false);
player.getAppearance().sync();
} }
/** /**
@ -118,6 +125,10 @@ public final class SkullManager {
* @param level the level to set. * @param level the level to set.
*/ */
public void setLevel(int level) { public void setLevel(int level) {
if (!deepWilderness && level >= 49)
setDeepWilderness(true);
else if (deepWilderness && level < 48)
setDeepWilderness(false);
this.level = level; this.level = level;
} }
@ -161,6 +172,10 @@ public final class SkullManager {
return wildernessDisabled; return wildernessDisabled;
} }
public boolean hasWildernessProtection() {
return level < 49;
}
/** /**
* Sets the wildernessDisabled. * Sets the wildernessDisabled.
* @param wildernessDisabled The wildernessDisabled to set. * @param wildernessDisabled The wildernessDisabled to set.
@ -174,7 +189,17 @@ public final class SkullManager {
* @return The skulled. * @return The skulled.
*/ */
public boolean isSkulled() { public boolean isSkulled() {
return skulled; return skulled || deepWilderness;
}
public boolean isDeepWilderness() {
return deepWilderness;
}
public void setDeepWilderness (boolean deepWildy) {
setSkullIcon(deepWildy ? 1 : skulled ? 0 : -1);
setSkullCheckDisabled(deepWildy);
deepWilderness = deepWildy;
} }
/** /**

View file

@ -39,6 +39,9 @@ public final class WildernessZone extends MapZone {
*/ */
private static final WildernessZone INSTANCE = new WildernessZone(new ZoneBorders(2944, 3525, 3400, 3975), new ZoneBorders(3070, 9924, 3135, 10002), ZoneBorders.forRegion(12193), ZoneBorders.forRegion(11937)); private static final WildernessZone INSTANCE = new WildernessZone(new ZoneBorders(2944, 3525, 3400, 3975), new ZoneBorders(3070, 9924, 3135, 10002), ZoneBorders.forRegion(12193), ZoneBorders.forRegion(11937));
public static final String WILDERNESS_PROT_ATTR = "/save:wilderness-protection-active";
public static final String WILDERNESS_HIGHER_NEXTFEE = "/save:wilderness-higher-next-fee";
/** /**
* The zone borders. * The zone borders.
*/ */
@ -69,7 +72,7 @@ public final class WildernessZone extends MapZone {
double x = combatLevel; double x = combatLevel;
double A = 44044.5491; double A = 44044.5491;
double B = -7360.19548; double B = -7360.19548;
return (int) (A + (B * Math.log(x))) / 2; return (int) (A + (B * Math.log(x)));
} }
/** /**
@ -87,21 +90,29 @@ public final class WildernessZone extends MapZone {
} }
private void rollWildernessExclusiveLoot(Entity e, Entity killer) { private void rollWildernessExclusiveLoot(Entity e, Entity killer) {
//Roll for PVP gear and Brawling Gloves from revenants if (!(killer instanceof Player)) return;
if (e instanceof NPC && killer instanceof Player && (e.asNpc().getName().contains("Revenant") || e.getId() == NPCs.CHAOS_ELEMENTAL_3200)) {
boolean gloveDrop = e.getId() == NPCs.CHAOS_ELEMENTAL_3200 ? RandomFunction.roll(75) : RandomFunction.roll(100); boolean isDeepWildy = ((Player) killer).getSkullManager().isDeepWilderness();
if (gloveDrop) { boolean isValidTarget = e instanceof NPC && (isDeepWildy || e.asNpc().getName().contains("Revenant") || e.getId() == NPCs.CHAOS_ELEMENTAL_3200);
if (!isValidTarget) return;
int cEleGloveRate = isDeepWildy ? 50 : 150;
int normalGloveRate = isDeepWildy ? 75 : 150;
int pvpGearRate = getNewDropRate(e.asNpc().getDefinition().getCombatLevel());
if (isDeepWildy)
pvpGearRate /= 2;
if (RandomFunction.roll(e.getId() == NPCs.CHAOS_ELEMENTAL_3200 ? cEleGloveRate : normalGloveRate)) {
byte glove = (byte) RandomFunction.random(1, 13); byte glove = (byte) RandomFunction.random(1, 13);
Item reward = new Item(BrawlingGloves.forIndicator(glove).getId()); Item reward = new Item(BrawlingGloves.forIndicator(glove).getId());
GroundItemManager.create(reward, e.asNpc().getDropLocation(), killer.asPlayer()); GroundItemManager.create(reward, e.asNpc().getDropLocation(), killer.asPlayer());
Repository.sendNews(killer.getUsername() + " has received " + reward.getName().toLowerCase() + " from a " + e.asNpc().getName() + "!"); Repository.sendNews(killer.getUsername() + " has received " + reward.getName().toLowerCase() + " from a " + e.asNpc().getName() + "!");
} }
int combatLevel = e.asNpc().getDefinition().getCombatLevel();
int dropRate = getNewDropRate(combatLevel);
for (int j : PVP_GEAR) { for (int j : PVP_GEAR) {
boolean chance = RandomFunction.roll(dropRate); boolean chance = RandomFunction.roll(pvpGearRate);
if (chance) { if (chance) {
Item reward; Item reward;
if (j == 13879 || j == 13883) { // checks if it's a javelin or throwing axe if (j == 13879 || j == 13883) { // checks if it's a javelin or throwing axe
@ -114,7 +125,6 @@ public final class WildernessZone extends MapZone {
} }
} }
} }
}
/** /**
* Fixes attack options for the revs * Fixes attack options for the revs

View file

@ -67,7 +67,7 @@ increased_door_time = false
enable_botting = false enable_botting = false
max_adv_bots = 100 max_adv_bots = 100
enable_doubling_money_scammers = true enable_doubling_money_scammers = true
wild_pvp_enabled = false wild_pvp_enabled = true
jad_practice_enabled = true jad_practice_enabled = true
#minimum HA value for announcements of bots selling on ge #minimum HA value for announcements of bots selling on ge
ge_announcement_limit = 500 ge_announcement_limit = 500