package org.moparscape.msc.gs.event; import java.util.ArrayList; import org.moparscape.msc.config.Config; import org.moparscape.msc.config.Formulae; import org.moparscape.msc.gs.Instance; import org.moparscape.msc.gs.core.GameEngine; import org.moparscape.msc.gs.model.InvItem; import org.moparscape.msc.gs.model.Item; import org.moparscape.msc.gs.model.Mob; import org.moparscape.msc.gs.model.Npc; import org.moparscape.msc.gs.model.Player; import org.moparscape.msc.gs.model.Projectile; import org.moparscape.msc.gs.model.landscape.PathGenerator; import org.moparscape.msc.gs.model.mini.Damage; import org.moparscape.msc.gs.states.Action; import org.moparscape.msc.gs.tools.DataConversions; public class RangeEvent extends DelayedEvent { private Mob affectedMob; public int[][] allowedArrows = { { 189, 11, 638 }, // Shortbow { 188, 11, 638 }, // Longbow { 649, 11, 638 }, // Oak Shortbow { 648, 11, 638, 640 }, // Oak Longbow { 651, 11, 638, 640 }, // Willow Shortbow { 650, 11, 638, 640, 642 }, // Willow Longbow { 653, 11, 638, 640, 642 }, // Maple Shortbow { 652, 11, 638, 640, 642, 644 }, // Maple Longbow { 655, 11, 638, 640, 642, 644 }, // Yew Shortbow { 654, 11, 638, 640, 642, 644, 646 }, // Yew Longbow { 657, 11, 638, 640, 642, 644, 646 }, // Magic Shortbow { 656, 11, 638, 640, 642, 644, 646 } // Magic Longbow }; private boolean firstRun = true; public RangeEvent(Player owner, Mob affectedMob) { super(owner, 2000); this.affectedMob = affectedMob; } public boolean equals(Object o) { if (o instanceof RangeEvent) { RangeEvent e = (RangeEvent) o; return e.belongsTo(owner); } return false; } public Mob getAffectedMob() { return affectedMob; } private Item getArrows(int id) { for (Item i : world.getTile(affectedMob.getLocation()).getItems()) { if (i.getID() == id && i.visibleTo(owner) && !i.isRemoved()) { return i; } } return null; } public void run() { int bowID = owner.getRangeEquip(); if (!owner.loggedIn() || (affectedMob instanceof Player && !((Player) affectedMob) .loggedIn()) || affectedMob.getHits() <= 0 || !owner.checkAttack(affectedMob, true) || bowID < 0) { owner.resetRange(); this.stop(); return; } if (owner.withinRange(affectedMob, 5)) { if (owner.isFollowing()) { owner.resetFollowing(); } if (!owner.finishedPath()) { owner.resetPath(); } } else { owner.setFollowing(affectedMob); return; } if (!new PathGenerator(owner.getX(), owner.getY(), affectedMob.getX(), affectedMob.getY()).isValid()) { owner.getActionSender().sendMessage( "I can't get a clear shot from here"); owner.resetPath(); this.stop(); return; } boolean xbow = DataConversions.inArray(Formulae.xbowIDs, bowID); int arrowID = -1; for (int aID : (xbow ? Formulae.getBoltIDs() : Formulae.getArrowIDs())) { int slot = owner.getInventory().getLastIndexById(aID); if (slot < 0) { continue; } InvItem arrow = owner.getInventory().get(slot); if (arrow == null) { // This shouldn't happen continue; } arrowID = aID; if (owner.getLocation().inWilderness() && Config.f2pWildy) { if (arrowID != 11 && arrowID != 190) { owner.getActionSender() .sendMessage( "You may not use P2P (Member Item) Arrows in the F2P Wilderness"); owner.resetRange(); this.stop(); return; } } int newAmount = arrow.getAmount() - 1; if (!xbow && arrowID > 0) { int temp = -1; for (int i = 0; i < allowedArrows.length; i++) if (allowedArrows[i][0] == owner.getRangeEquip()) temp = i; boolean canFire = false; for (int i = 0; i < allowedArrows[temp].length; i++) if (allowedArrows[temp][i] == aID) canFire = true; if (!canFire) { owner.getActionSender().sendMessage( "Your arrows are too powerful for your Bow."); owner.resetRange(); this.stop(); return; } } if (newAmount <= 0) { owner.getInventory().remove(slot); owner.getActionSender().sendInventory(); } else { arrow.setAmount(newAmount); owner.getActionSender().sendUpdateItem(slot); } break; } if (arrowID < 0) { owner.getActionSender().sendMessage( "You have run out of " + (xbow ? "bolts" : "arrows")); owner.resetRange(); this.stop(); return; } if (affectedMob.isPrayerActivated(13)) { if (!owner.shouldRangePass()) { owner.getActionSender().sendMessage("Your missile was blocked"); this.stop(); return; } } // if(owner.getRangeEquip()) int damage = Formulae.calcRangeHit(owner.getCurStat(4), owner.getRangePoints(), affectedMob.getArmourPoints(), arrowID); if (affectedMob instanceof Npc) { Npc npc = (Npc) affectedMob; if (damage > 1 && npc.getID() == 477) damage = damage / 2; } if (!Formulae.looseArrow(damage)) { Item arrows = getArrows(arrowID); if (arrows == null) { world.registerItem(new Item(arrowID, affectedMob.getX(), affectedMob.getY(), 1, owner)); } else { arrows.setAmount(arrows.getAmount() + 1); } } if (firstRun) { firstRun = false; if (affectedMob instanceof Player) { if (((Player) affectedMob).isSleeping()) { ((Player) affectedMob).getActionSender().sendWakeUp(false); } ((Player) affectedMob).getActionSender().sendMessage("Warning! " + owner.getUsername() + " is shooting at you!"); } } if (affectedMob instanceof Npc && ((Npc) affectedMob).isScripted()) { Instance.getPluginHandler().getNpcAIHandler(affectedMob.getID()) .onRangedAttack(owner, (Npc) affectedMob); } if (affectedMob instanceof Npc) { Npc npc = (Npc) affectedMob; npc.getSyndicate().addDamage(owner, damage, Damage.RANGE_DAMAGE); } Projectile projectile = new Projectile(owner, affectedMob, 2); ArrayList playersToInform = new ArrayList(); playersToInform.addAll(owner.getViewArea().getPlayersInView()); playersToInform.addAll(affectedMob.getViewArea().getPlayersInView()); for (Player p : playersToInform) { p.informOfProjectile(projectile); } if (GameEngine.getTime() - affectedMob.lastTimeShot > 500) { affectedMob.lastTimeShot = GameEngine.getTime(); affectedMob.setLastDamage(damage); int newHp = affectedMob.getHits() - damage; affectedMob.setHits(newHp); if (affectedMob instanceof Npc && newHp > 0) { Npc n = (Npc) affectedMob; double max = n.getDef().hits; double cur = n.getHits(); int percent = (int) ((cur / max) * 100); if (n.isScripted()) Instance.getPluginHandler().getNpcAIHandler(n.getID()) .onHealthPercentage(n, percent); } for (Player p : playersToInform) { p.informOfModifiedHits(affectedMob); } if (affectedMob instanceof Player) { Player affectedPlayer = (Player) affectedMob; affectedPlayer.getActionSender().sendStat(3); } owner.getActionSender().sendSound("shoot"); owner.setArrowFired(); if (newHp <= 0) { affectedMob.killedBy(owner, false); owner.resetRange(); if (owner instanceof Player) { if (affectedMob instanceof Npc) { Npc npc = (Npc) affectedMob; npc.getSyndicate().distributeExp(npc); } } } else { // We're ranging an NPC, so make it chase the player. if (owner instanceof Player && affectedMob instanceof Npc) { final Npc npc = (Npc) affectedMob; final Player player = (Player) owner; if (npc.isBusy() || npc.getChasing() != null) return; npc.resetPath(); //setChasing stops range? npc.setChasing(player); // Radius is 0 to prevent wallhacking by NPCs. Easiest // method I // can come up with for now. Instance.getDelayedEventHandler().add( new WalkMobToMobEvent(affectedMob, owner, 0) { public void arrived() { if (affectedMob.isBusy() || player.isBusy()) { npc.setChasing(null); this.stop(); return; } npc.resetPath(); player.setBusy(true); player.resetPath(); player.resetAll(); if (npc.isScripted()) Instance.getPluginHandler() .getNpcAIHandler(npc.getID()) .onNpcAttack(npc, player); player.setStatus(Action.FIGHTING_MOB); player.getActionSender().sendSound( "underattack"); player.getActionSender().sendMessage( "You are under attack!"); npc.setLocation(player.getLocation(), true); for (Player p : npc.getViewArea() .getPlayersInView()) p.removeWatchedNpc(npc); player.setBusy(true); player.setSprite(9); player.setOpponent(npc); player.setCombatTimer(); npc.setBusy(true); npc.setSprite(8); npc.setOpponent(player); npc.setCombatTimer(); npc.setChasing(null); FightEvent fighting = new FightEvent( player, npc, true); fighting.setLastRun(0); Instance.getDelayedEventHandler().add( fighting); this.stop(); } public void failed() { npc.setChasing(null); } }); // target is still alive? is still around? if (!npc.isRemoved() || owner.withinRange(npc)) { return; } this.stop(); } } } } }