mirror of
https://gitlab.com/2009scape/2009scape.git
synced 2026-08-25 20:35:10 -06:00
Merge branch 2009scape:master into valid-shop-repairs
This commit is contained in:
commit
147e12623c
11 changed files with 141 additions and 39 deletions
|
|
@ -139,6 +139,13 @@ public final class AgilityHandler {
|
|||
* @return The force movement instance, if force movement is used.
|
||||
*/
|
||||
public static ForceMovement forceWalk(final Player player, final int courseIndex, Location start, Location end, Animation animation, int speed, final double experience, final String message) {
|
||||
return forceWalk(player, courseIndex, start, end, animation, speed, experience, message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Walks across an obstacle while using an explicit force-movement facing direction.
|
||||
*/
|
||||
public static ForceMovement forceWalk(final Player player, final int courseIndex, Location start, Location end, Animation animation, int speed, final double experience, final String message, Direction direction) {
|
||||
player.logoutListeners.put("forcewalk", p -> {
|
||||
p.setLocation(player.getLocation().transform(0,0,0));
|
||||
return Unit.INSTANCE;
|
||||
|
|
@ -158,6 +165,9 @@ public final class AgilityHandler {
|
|||
player.logoutListeners.remove("forcewalk");
|
||||
}
|
||||
};
|
||||
if (direction != null) {
|
||||
movement.setDirection(direction);
|
||||
}
|
||||
movement.start();
|
||||
GameWorld.getPulser().submit(movement);
|
||||
return movement;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,9 @@ import core.game.node.entity.Entity;
|
|||
import core.game.node.entity.player.Player;
|
||||
import core.game.system.task.MovementHook;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.net.packet.PacketRepository;
|
||||
import core.net.packet.context.PlayerContext;
|
||||
import core.net.packet.out.ClearMinimapFlag;
|
||||
import kotlin.Unit;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.map.Direction;
|
||||
|
|
@ -24,6 +27,10 @@ public final class BladeTrap implements MovementHook {
|
|||
final Direction dir = e.getDirection();
|
||||
final Player player = (Player) e;
|
||||
final Location start = l.transform(-dir.getStepX(), -dir.getStepY(), 0);
|
||||
player.getPulseManager().clear();
|
||||
player.getWalkingQueue().reset();
|
||||
PacketRepository.send(ClearMinimapFlag.class, new PlayerContext(player));
|
||||
|
||||
e.lock(5);
|
||||
if(e.isPlayer())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -119,6 +119,8 @@ public final class BrimhavenCourse extends OptionHandler {
|
|||
final Direction dir = direction;
|
||||
final Direction faceDirection = Direction.get(object.getDirection().toInteger() - 1 & 3);
|
||||
final Location start = player.getLocation();
|
||||
player.setDirection(faceDirection);
|
||||
player.faceLocation(start.transform(faceDirection));
|
||||
player.getAppearance().setAnimations(Animation.create(1118 + m));
|
||||
player.getAppearance().sync();
|
||||
AgilityHandler.climb(player, -1, new Animation(1117 + m), start.transform(dir), 0.0, null);
|
||||
|
|
@ -143,12 +145,12 @@ public final class BrimhavenCourse extends OptionHandler {
|
|||
} else if (count == 6) {
|
||||
player.getAppearance().setAnimations();
|
||||
player.getAppearance().sync();
|
||||
AgilityHandler.forceWalk(player, -1, last, last.transform(dir), Animation.create(1120 + m), 5, getExp(player, 22.0), null).setDirection(faceDirection);
|
||||
AgilityHandler.forceWalk(player, -1, last, last.transform(dir), Animation.create(1120 + m), 5, getExp(player, 22.0), null, faceDirection);
|
||||
player.logoutListeners.remove("brimcourse");
|
||||
return true;
|
||||
}
|
||||
player.logoutListeners.remove("brimcourse");
|
||||
AgilityHandler.forceWalk(player, -1, last, last = last.transform(dir), Animation.create(1118 + m), 5, 0.0, null).setDirection(faceDirection);
|
||||
AgilityHandler.forceWalk(player, -1, last, last = last.transform(dir), Animation.create(1118 + m), 5, 0.0, null, faceDirection);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
|
@ -272,7 +274,7 @@ public final class BrimhavenCourse extends OptionHandler {
|
|||
public boolean pulse() {
|
||||
if (!finish) {
|
||||
setDelay(2);
|
||||
AgilityHandler.fail(player, 1, player.getLocation().transform(0, 0, -3), Animation.create(189), getHitAmount(player), "You stepped on a broken piece of plank!");
|
||||
AgilityHandler.fail(player, 1, player.getLocation().transform(0, 0, -3), Animation.create(768), getHitAmount(player), "You stepped on a broken piece of plank!");
|
||||
finish = true;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -282,7 +284,7 @@ public final class BrimhavenCourse extends OptionHandler {
|
|||
});
|
||||
return;
|
||||
}
|
||||
AgilityHandler.walk(player, -1, start, end, ForceMovement.WALK_ANIMATION, getExp(player, 6.0), null);
|
||||
AgilityHandler.walk(player, -1, start, end, Animation.create(1426), getExp(player, 6.0), null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -389,6 +391,7 @@ public final class BrimhavenCourse extends OptionHandler {
|
|||
}
|
||||
break;
|
||||
case 3551:
|
||||
case 3583:
|
||||
return n.getLocation();
|
||||
}
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ import core.game.node.entity.impl.Projectile;
|
|||
import core.game.node.entity.player.Player;
|
||||
import core.game.system.task.MovementHook;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.net.packet.context.PlayerContext;
|
||||
import core.net.packet.out.ClearMinimapFlag;
|
||||
import kotlin.Unit;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.map.Direction;
|
||||
|
|
@ -29,6 +31,9 @@ public final class DartTrap implements MovementHook {
|
|||
final Direction dir = e.getDirection();
|
||||
final Player player = (Player) e;
|
||||
final Location start = l.transform(-dir.getStepX(), -dir.getStepY(), 0);
|
||||
player.getPulseManager().clear();
|
||||
player.getWalkingQueue().reset();
|
||||
PacketRepository.send(ClearMinimapFlag.class, new PlayerContext(player));
|
||||
e.lock(6);
|
||||
if(e.isPlayer())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ import core.game.node.entity.Entity;
|
|||
import core.game.node.entity.player.Player;
|
||||
import core.game.system.task.MovementHook;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.net.packet.PacketRepository;
|
||||
import core.net.packet.context.PlayerContext;
|
||||
import core.net.packet.out.ClearMinimapFlag;
|
||||
import kotlin.Unit;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.map.Direction;
|
||||
|
|
@ -24,6 +27,9 @@ public final class FloorSpikes implements MovementHook {
|
|||
final Direction dir = e.getDirection();
|
||||
final Player player = (Player) e;
|
||||
final Location start = l.transform(-dir.getStepX(), -dir.getStepY(), 0);
|
||||
player.getPulseManager().clear();
|
||||
player.getWalkingQueue().reset();
|
||||
PacketRepository.send(ClearMinimapFlag.class, new PlayerContext(player));
|
||||
e.lock(5);
|
||||
if(e.isPlayer())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ import core.game.node.entity.Entity;
|
|||
import core.game.node.entity.player.Player;
|
||||
import core.game.system.task.MovementHook;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.net.packet.PacketRepository;
|
||||
import core.net.packet.context.PlayerContext;
|
||||
import core.net.packet.out.ClearMinimapFlag;
|
||||
import kotlin.Unit;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.map.Direction;
|
||||
|
|
@ -24,6 +27,10 @@ public final class PressurePad implements MovementHook {
|
|||
final Direction dir = e.getDirection();
|
||||
final Player player = (Player) e;
|
||||
final Location start = dest.transform(-dir.getStepX(), -dir.getStepY(), 0);
|
||||
player.getPulseManager().clear();
|
||||
player.getWalkingQueue().reset();
|
||||
PacketRepository.send(ClearMinimapFlag.class, new PlayerContext(player));
|
||||
|
||||
e.lock(5);
|
||||
if(e.isPlayer())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ import core.game.node.entity.Entity;
|
|||
import core.game.node.entity.player.Player;
|
||||
import core.game.system.task.MovementHook;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.net.packet.PacketRepository;
|
||||
import core.net.packet.context.PlayerContext;
|
||||
import core.net.packet.out.ClearMinimapFlag;
|
||||
import kotlin.Unit;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.map.Direction;
|
||||
|
|
@ -24,6 +27,9 @@ public final class SpinningBlades implements MovementHook {
|
|||
final Direction dir = e.getDirection();
|
||||
final Player player = (Player) e;
|
||||
final Location start = l.transform(-dir.getStepX(), -dir.getStepY(), 0);
|
||||
player.getPulseManager().clear();
|
||||
player.getWalkingQueue().reset();
|
||||
PacketRepository.send(ClearMinimapFlag.class, new PlayerContext(player));
|
||||
e.lock(5);
|
||||
if(e.isPlayer())
|
||||
{
|
||||
|
|
@ -70,4 +76,4 @@ public final class SpinningBlades implements MovementHook {
|
|||
}
|
||||
player.getPacketDispatch().sendSceneryAnimation(RegionManager.getObject(l), Animation.create(1107));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,10 @@ import org.rs09.consts.Items
|
|||
import org.rs09.consts.Sounds
|
||||
import kotlin.math.floor
|
||||
|
||||
private const val DREAM_HEAL_INTERVAL_TICKS = 50
|
||||
private const val DREAM_HARD_RESET_INTERVAL_TICKS = 90
|
||||
private const val DREAM_HARD_RESET_DELAY_TICKS = 0
|
||||
|
||||
class LunarListeners : SpellListener("lunar"), Commands {
|
||||
|
||||
override fun defineListeners() {
|
||||
|
|
@ -592,32 +596,46 @@ class LunarListeners : SpellListener("lunar"), Commands {
|
|||
|
||||
// Level 79
|
||||
private fun dream(player: Player) {
|
||||
if(player.skills.lifepoints >= getStatLevel(player, Skills.HITPOINTS)) {
|
||||
if (player.skills.lifepoints >= getStatLevel(player, Skills.HITPOINTS)) {
|
||||
sendMessage(player, "You have no need to cast this spell since your hitpoints are already full.")
|
||||
throw IllegalStateException()
|
||||
}
|
||||
|
||||
// https://runescape.wiki/w/Dream?oldid=880976 claims Dream makes you heal 1 hp every 20 seconds
|
||||
// https://oldschool.runescape.wiki/w/Dream claims that Dream has its own timer, so the Dream heals don't need
|
||||
// to align with the natural heals
|
||||
val timer = getOrStartTimer<SkillRestore>(player)
|
||||
val dreamStartAnimationTicks = animationDuration(Animation(Animations.LUNAR_SPELLBOOK_DREAM_START_6295))
|
||||
var nextHealTick = getWorldTicks() + dreamStartAnimationTicks + DREAM_HEAL_INTERVAL_TICKS
|
||||
var nextHardResetTick = -1
|
||||
var waitingForHardReset = false
|
||||
animate(player, Animations.LUNAR_SPELLBOOK_DREAM_START_6295)
|
||||
removeRunes(player, true)
|
||||
addXP(player, 82.0)
|
||||
delayEntity(player, 4)
|
||||
queueScript(player, 4, QueueStrength.WEAK) { stage: Int ->
|
||||
delayEntity(player, dreamStartAnimationTicks)
|
||||
queueScript(player, dreamStartAnimationTicks, QueueStrength.WEAK) { stage: Int ->
|
||||
if (stage == 0) {
|
||||
sendGraphics(Graphics.LUNAR_SPELLBOOK_DREAM_1056, player.location)
|
||||
playAudio(player, Sounds.LUNAR_SLEEP_3619)
|
||||
return@queueScript delayScript(player, 5)
|
||||
}
|
||||
if (waitingForHardReset) {
|
||||
waitingForHardReset = false
|
||||
nextHardResetTick = getWorldTicks() + DREAM_HARD_RESET_INTERVAL_TICKS
|
||||
} else if (nextHardResetTick != -1 && getWorldTicks() >= nextHardResetTick) {
|
||||
// The 530 client eventually drops Dream back to idle if it only sees repeated 6296 updates
|
||||
// Sending an explicit reset makes the next 6296 a full restart instead of a same-sequence refresh
|
||||
resetAnimator(player)
|
||||
waitingForHardReset = true
|
||||
return@queueScript delayScript(player, DREAM_HARD_RESET_DELAY_TICKS)
|
||||
} else if (nextHardResetTick == -1) {
|
||||
nextHardResetTick = getWorldTicks() + DREAM_HARD_RESET_INTERVAL_TICKS
|
||||
}
|
||||
animate(player, Animations.LUNAR_SPELLBOOK_DREAM_MID_6296)
|
||||
sendGraphics(Graphics.LUNAR_SPELLBOOK_DREAM_1056, player.location)
|
||||
// This heals 2 HP every min. Naturally you heal 1 for a total of 3
|
||||
// The script steps every 5 ticks and we want 50 ticks before a heal
|
||||
if (stage.mod(10) == 0) {
|
||||
if (getWorldTicks() >= nextHealTick) {
|
||||
val amt = timer.getHealAmount(player) //accounts for regen brace
|
||||
heal(player, amt)
|
||||
nextHealTick += DREAM_HEAL_INTERVAL_TICKS
|
||||
if (player.skills.lifepoints >= getStatLevel(player, Skills.HITPOINTS)) {
|
||||
animate(player, Animations.LUNAR_SPELLBOOK_DREAM_END_6297)
|
||||
return@queueScript stopExecuting(player)
|
||||
|
|
@ -874,4 +892,3 @@ class LunarListeners : SpellListener("lunar"), Commands {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -82,6 +82,8 @@ public abstract class Familiar extends NPC implements Plugin<Object> {
|
|||
* The amount of special points left.
|
||||
*/
|
||||
protected int specialPoints = 60;
|
||||
|
||||
public static final String INFINITE_SPECIAL_MOVE_ATTRIBUTE = "infinite-special-move";
|
||||
|
||||
/**
|
||||
* The pouch id.
|
||||
|
|
@ -494,7 +496,9 @@ public abstract class Familiar extends NPC implements Plugin<Object> {
|
|||
owner.getInventory().remove(new Item(scroll.getItemId()));
|
||||
playAudio(owner, Sounds.SPELL_4161);
|
||||
visualizeSpecialMove();
|
||||
updateSpecialPoints(specialCost);
|
||||
if (!owner.getAttribute(INFINITE_SPECIAL_MOVE_ATTRIBUTE, false)) {
|
||||
updateSpecialPoints(specialCost);
|
||||
}
|
||||
owner.getSkills().addExperience(Skills.SUMMONING, scroll.getExperience(), true);
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -145,11 +145,6 @@ public final class TzhaarFightCavesPlugin extends ActivityPlugin {
|
|||
public void leave(Player player, int wave) {
|
||||
activeNPCs.clear();
|
||||
player.getProperties().setTeleportLocation(getSpawnLocation());
|
||||
player.getSkills().restore();
|
||||
player.timers.removeTimer("poison");
|
||||
player.timers.removeTimer("disease");
|
||||
player.timers.removeTimer("teleblock");
|
||||
player.getSettings().updateRunEnergy(-100);
|
||||
boolean practice = player.getAttribute("fc_practice_jad", false);
|
||||
if (wave == 63) {
|
||||
if (!practice) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package core.game.system.command.sets
|
||||
|
||||
import content.global.handlers.iface.*
|
||||
import content.global.skill.summoning.familiar.Familiar
|
||||
import content.global.skill.cooking.fermenting.BrewGrowth
|
||||
import content.global.skill.farming.timers.*
|
||||
import content.minigame.fishingtrawler.TrawlerLoot
|
||||
|
|
@ -40,6 +41,27 @@ import java.awt.HeadlessException
|
|||
import java.awt.Toolkit
|
||||
import java.awt.datatransfer.StringSelection
|
||||
|
||||
private const val INFINITE_SPECIAL_ATTRIBUTE = "infinite-special"
|
||||
private const val ALLOW_ADMIN_AGGRESSION_ATTRIBUTE = "/save:allow_admin_aggression"
|
||||
|
||||
private fun resolveBooleanToggle(player: Player, args: Array<String>, attribute: String): Boolean? {
|
||||
return when {
|
||||
args.size < 2 -> !player.getAttribute(attribute, false)
|
||||
args[1].equals("true", ignoreCase = true) -> true
|
||||
args[1].equals("false", ignoreCase = true) -> false
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun setBooleanAttribute(player: Player, attribute: String, enabled: Boolean, label: String) {
|
||||
if (enabled) {
|
||||
setAttribute(player, attribute, true)
|
||||
} else {
|
||||
removeAttribute(player, attribute)
|
||||
}
|
||||
sendMessage(player, "$label is now ${if (enabled) "enabled" else "disabled"}.")
|
||||
}
|
||||
|
||||
@Initializable
|
||||
class MiscCommandSet : CommandSet(Privilege.ADMIN){
|
||||
override fun defineCommands() {
|
||||
|
|
@ -662,29 +684,49 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
|
|||
notify(player,"No parent NPC found.")
|
||||
}
|
||||
}
|
||||
define("infinitespecial", Privilege.ADMIN, "::infinitespecial <true|false>", "Turns the infinite special-attack flag on or off for your player."){ player, args ->
|
||||
val usageStr = "Usage: ::infinitespecial true|false"
|
||||
if(args.size < 2){
|
||||
reject(player, usageStr)
|
||||
}
|
||||
when(args[1]){
|
||||
"true" -> player.setAttribute("infinite-special", true)
|
||||
"false" -> player.removeAttribute("infinite-special")
|
||||
else -> reject(player, usageStr)
|
||||
}
|
||||
}
|
||||
define("allowaggro", Privilege.ADMIN, "allowaggro true | false", "Toggle NPCs aggroing on you") { player, args ->
|
||||
val usageStr = "Usage: ::allowaggro true | false"
|
||||
if(args.size < 2) {
|
||||
notify(player, "Allow admin aggression is currently ${player.getAttribute("/save:allow_admin_aggression", false)}")
|
||||
define(
|
||||
"infinitespecial",
|
||||
Privilege.ADMIN,
|
||||
"::infinitespecial [true|false]",
|
||||
"Toggles infinite special attack energy for your player (special-attack flag)."
|
||||
) { player, args ->
|
||||
val enabled = resolveBooleanToggle(player, args, INFINITE_SPECIAL_ATTRIBUTE)
|
||||
if (enabled == null) {
|
||||
reject(player, "Usage: ::infinitespecial [true|false]")
|
||||
return@define
|
||||
}
|
||||
when(args[1]) {
|
||||
"true" -> player.setAttribute("/save:allow_admin_aggression", true)
|
||||
"false" -> player.setAttribute("/save:allow_admin_aggression", false)
|
||||
else -> reject(player, usageStr)
|
||||
setBooleanAttribute(player, INFINITE_SPECIAL_ATTRIBUTE, enabled, "Infinite special attack")
|
||||
}
|
||||
define(
|
||||
"infinitespecialmove",
|
||||
Privilege.ADMIN,
|
||||
"::infinitespecialmove [true|false]",
|
||||
"Toggles infinite Summoning familiar special move points for your player."
|
||||
) { player, args ->
|
||||
val enabled = resolveBooleanToggle(player, args, Familiar.INFINITE_SPECIAL_MOVE_ATTRIBUTE)
|
||||
if (enabled == null) {
|
||||
reject(player, "Usage: ::infinitespecialmove [true|false]")
|
||||
return@define
|
||||
}
|
||||
notify(player, "Setting aggro ${args[1]}")
|
||||
setBooleanAttribute(
|
||||
player,
|
||||
Familiar.INFINITE_SPECIAL_MOVE_ATTRIBUTE,
|
||||
enabled,
|
||||
"Infinite familiar special move energy"
|
||||
)
|
||||
}
|
||||
define(
|
||||
"allowaggro",
|
||||
Privilege.ADMIN,
|
||||
"::allowaggro [true|false]",
|
||||
"Toggles NPCs aggroing on you as an admin."
|
||||
) { player, args ->
|
||||
val enabled = resolveBooleanToggle(player, args, ALLOW_ADMIN_AGGRESSION_ATTRIBUTE)
|
||||
if (enabled == null) {
|
||||
reject(player, "Usage: ::allowaggro [true|false]")
|
||||
return@define
|
||||
}
|
||||
setBooleanAttribute(player, ALLOW_ADMIN_AGGRESSION_ATTRIBUTE, enabled, "Admin NPC aggression")
|
||||
}
|
||||
|
||||
define("rules", Privilege.STANDARD, "", "Shows the rules."){ player, _ ->
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue