Jump to content

Featured Replies

Posted
comment_24762

I've had to develop this in ~20 hours of total time for a service, with the quality of code not being a matter (by preference of customer).

It's external instead of embedded, I didn't want to bother adapting to an already bad system, so I made it cycle based - it's working just fine, beside auto-retaliation (you can force that none the less, figure out on your own)

It has: All attacks (Ranged, Prayer deactivation, Poison, Magic, Dragonfire) - as well as the freezing with the small alien pet, the big dragon fire (one-shot) & acid splatters.

If you don't use this, at least recognize the approach on how I did the calculation for acid splatters landing AROUND the circle instead because all vorkaths I saw so far had half-assed acid splatters. 

Lacking stuff:
The projectile height of the one-shot ball is a bit too low
The delays are off on the smaller dragon balls, yet walking/dodging works fine
The projectiles shoot from a tile instead of relative to vorkaths mouth/face
The code is utter trash - lets be for real
The delays obviously are not the same as OSRS
There is no defensive stance animation / vorkath
Death animation is lacking / Alien

If I forgot a method, let me know

link for the standalone classes
https://www.mediafire.com/file/cnnav02szvbbi85/vorkath.zip/file

Yasin: Me on R-S

If I forget anything, I'll tweak it asap on here

Media:
https://i.gyazo.com/b058a5f20630b9f00ad3a67faf210a03.mp4
https://i.gyazo.com/13731ecdd3dee54338810ecb3e0a2f4c.mp4
AttackType class

package osv.model.npcs.bosses.vorkath;

/**
 * @author Yasin
 */
public enum AttackType {

    MAGIC(7952, 1479, 1480),
    RANGED(7952, 1477, 1478),
    ONE_HIT(7960, 1491, 157),
    PRAYER_SNIPE(7952, 1471, 1473),
    POISON(7952, 1470, 1472),
    DRAGON_FIRE(7952, 393, 157),
    SPECIAL_1(7957, 1486, 1473), //acid
    SPECIAL_2(7952, 395, 369); //jihad

    private int animationId;

    private int projectileId;

    private int endGfx;

    AttackType(int animationId, int projectileId, int endGfx) {
        this.animationId = animationId;
        this.projectileId = projectileId;
        this.endGfx = endGfx;
    }


    public int getAnimationId() {
        return animationId;
    }

    public int getProjectileId() {
        return projectileId;
    }

    public int getEndGfx() {
        return endGfx;
    }
}


Vorkath class

package osv.model.npcs.bosses.vorkath;


import osv.Server;
import osv.event.CycleEvent;
import osv.event.CycleEventContainer;
import osv.event.CycleEventHandler;
import osv.event.DelayEvent;
import osv.model.content.instances.InstancedAreaManager;
import osv.model.content.instances.SingleInstancedArea;
import osv.model.content.instances.impl.SingleInstancedVorkath;
import osv.model.entity.HealthStatus;
import osv.model.npcs.NPC;
import osv.model.npcs.NPCDumbPathFinder;
import osv.model.npcs.NPCHandler;
import osv.model.npcs.bosses.vorkath.impl.DeathStage;
import osv.model.npcs.bosses.vorkath.impl.SpawnStage;
import osv.model.npcs.bosses.vorkath.impl.WakeUpStage;
import osv.model.players.Player;
import osv.model.players.Position;
import osv.model.players.combat.Hitmark;
import osv.util.Misc;
import osv.world.objects.GlobalObject;

import java.util.Arrays;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author Yasin
 */
public class Vorkath {

    private final Player player;

    private AttackType specialAttackType;

    private AttackType attackType;

    private VorkathState vorkathState;

    private final Object eventLock;

    private int attacks;

    private NPC vorkath;

    private boolean zombieSpawned;
    

    private boolean forceDeath;

    private SingleInstancedVorkath vorkathInstance;

    public Vorkath(Player player) {
        this.player = player;
        this.specialAttackType = Arrays.stream(AttackType.values()).filter(type -> type.name().toLowerCase().contains("special")).collect(Collectors.toList()).get(Misc.random(1));//only 0 or 1
        this.vorkathState = VorkathState.SLEEPING;
        this.eventLock = new Object();
    }

    public void start() {
        if (vorkathInstance != null) {
            disposeInstance();
            //player.sendMessage("Vorkath instance is not null, fyi! Disposing..");
        }
        int height = InstancedAreaManager.getSingleton().getNextOpenHeight(VorkathConstants.VORKATH_BOUNDARY);
        vorkathInstance = new SingleInstancedVorkath(player, VorkathConstants.VORKATH_BOUNDARY, height);
        InstancedAreaManager.getSingleton().add(height, vorkathInstance);
        if (vorkathInstance == null) {
            player.getDH().sendStatement("Vorkath can't be fought right now.", "Please try again shortly.");
            player.nextChat = -1;
            return;
        }
        CycleEventHandler.getSingleton().addEvent(eventLock, new SpawnStage(this, player), 1);
    }

    public void disposeInstance() {
        forceDeath = true;
        if (vorkath != null) {
            setVorkathState(VorkathState.SLEEPING);
            Server.npcHandler.kill(vorkath.npcType, vorkathInstance.getHeight());
        }
        attacks = 0;
        InstancedAreaManager.getSingleton().disposeOf(vorkathInstance);
        Server.getGlobalObjects().remove(32000, vorkathInstance.getHeight());
        vorkathInstance = null;
        forceDeath = false;
    }

    public void resetCombat() {
        if (vorkath == null) {
            return;
        }
        player.getCombat().resetPlayerAttack();
        vorkath.underAttack = false;
        vorkath.face = 0;
        if (vorkathState == VorkathState.RESTING) {
            vorkath.attackTimer += 1;
        }
        vorkath.underAttackBy = 0;
    }


    public boolean canSpecial() {
        return attacks % 7 == 0 && attacks > 0;
    }

    public void wakeUp() {
        if(vorkathState == VorkathState.AWAKE) {
            return;
        }
        if (vorkathState != VorkathState.RESTING) { //just to make sure
            vorkathState = VorkathState.AWAKE;
            CycleEventHandler.getSingleton().addEvent(eventLock, new WakeUpStage(this, player, false), 1);
        }
        if (vorkathState == VorkathState.RESTING) { //just to make sure
            vorkathState = VorkathState.AWAKE;
            CycleEventHandler.getSingleton().addEvent(eventLock, new WakeUpStage(this, player, true), 1);
        }
    }

    public void handleAttack() {
        if (player != null && vorkath != null && !vorkath.isDead && !player.isDead && !zombieSpawned) {
            int distance = player.distanceToPoint(vorkath.getX(), vorkath.getY());
            if (vorkath.actionTimer > 0) {
                return;
            }
            if(distance >= 15) {
                return;
            }
            if(distance <= 3) {
                vorkath.actionTimer += 2;
            }
            vorkath.actionTimer += 5;
            attacks += 1;
            if (canSpecial()) { //Every 7 attacks
                specialAttackType = specialAttackType == AttackType.SPECIAL_1 ? AttackType.SPECIAL_2 : AttackType.SPECIAL_1;
                vorkath.startAnimation(specialAttackType.getAnimationId());
                if (specialAttackType == AttackType.SPECIAL_1) { //acid
                    CycleEventHandler.getSingleton().addEvent(eventLock, handleAcidSpecial(), 1);
                    vorkath.actionTimer += 22;
                } else if (specialAttackType == AttackType.SPECIAL_2) { //jihad
                    fireTargetedProjectile(specialAttackType.getProjectileId());
                    CycleEventHandler.getSingleton().addEvent(eventLock, handleJihadSpecial(), 1);
                    player.stopMovement();
                    vorkath.actionTimer += 7;
                }
            } else {
                attackType = Arrays.stream(AttackType.values()).filter(type ->
                        !type.name().toLowerCase().contains("special")).
                        collect(Collectors.toList()).get(Misc.random(5));
                vorkath.actionTimer += 1;
                vorkath.startAnimation(attackType.getAnimationId());
                if (attackType != AttackType.ONE_HIT) {
                    CycleEventHandler.getSingleton().addEvent(eventLock, handleAttackType(), 1);
                    fireTargetedProjectile(attackType.getProjectileId());
                } else {
                    CycleEventHandler.getSingleton().addEvent(eventLock, handleOneHit(), 1);
                    fireOneshit(attackType.getProjectileId(), 110, player.getX(), player.getY(),
                            50, 50); //50 -> current angle, 50 -> current start height

                }
            }
        }
    }

    public void jump() {
        CycleEventHandler.getSingleton().addEvent(eventLock, new CycleEvent() {
            boolean north;

            @Override
            public void execute(CycleEventContainer container) {
                if (container.getOwner() == null || player == null || player.isDead || player.animationRequest != -1) {
                    container.stop();
                    return;
                }
                int cycle = container.getTotalTicks();
                if (cycle == 1) {
                    if (player.getX() <= 2273 && player.getX() >= 2271 && player.getY() == 4052) {
                        north = true;
                    }
                    player.startAnimation(1115);
                    player.sendMessage("You jump over the ice bricks..");
                }
                if (cycle == 3) {
                    player.stopAnimation();
                    player.sendMessage("and reach the other side..");
                    if(north && vorkathInstance == null) {
                        start();
                    }
                    if(vorkathInstance == null) { //height will be set in spawnstage
                        player.getPA().movePlayer(player.getX(), north ? player.getY() + 2 : player.getY() - 2);
                    } else { //so the player can continue
                        player.getPA().movePlayer(player.getX(), north ? player.getY() + 2 : player.getY() - 2, vorkathInstance.getHeight());
                    }
                    container.stop();
                }

            }
        }, 1);
    }

    private CycleEvent handleJihadSpecial() {
        return new CycleEvent() {
            int SPAWN_X;
            int SPAWN_Y;
            NPC spawn;

            private void killSpawn(boolean explode) {
                spawn.gfx0(542);
                zombieSpawned = false;
                spawn.needRespawn = false;
                spawn.isDead = true;
                if(explode) {
                    player.appendDamage(Misc.random(60) + 10, Hitmark.HIT);
                }
                player.freezeTimer = 0;
            }
            @Override
            public void execute(CycleEventContainer container) {
                if (container.getOwner() == null || vorkath == null || player == null || player.isDead || vorkathInstance == null) {
                    container.stop();
                    return;
                }
                int cycle = container.getTotalTicks();
                if (cycle == 4) {
                    player.gfx0(specialAttackType.getEndGfx());
                    player.freezeTimer = 500;
                    player.sendMessage("You've been frozen.");
                }
                if (cycle == 5) {
                    SPAWN_X = vorkath.getX() + Misc.random(7) + 3;
                    SPAWN_Y = vorkath.getY() - 2;
                    player.sendMessage("The dragon throws a creature towards you..");
                    zombieSpawned = true;
                    fireProjectileToLocation(1484, 130, SPAWN_X, SPAWN_Y, 50);
                }
                if (cycle == 9) {
                    spawn = Server.npcHandler.spawnNpc(player, VorkathConstants.ZOMBIE_SPAWN, SPAWN_X, SPAWN_Y, vorkathInstance.getHeight(), 1, VorkathConstants.ZOMBIE_SPAWN_LIFE_POINTS, 1, 1, 1, false, false);
                }
                if (cycle >= 10) {
                    int distance = player.distanceToPoint(spawn.getX(), spawn.getY());
                    if(zombieSpawned && spawn.isDead) {
                        killSpawn(false);
                        container.stop();
                    }
                    if (distance <= 1 && zombieSpawned) {
                        killSpawn(true);
                        container.stop();
                    }
                }
                if (zombieSpawned && cycle >= 10) {
                    if (spawn.getX() != player.absX - 1 && spawn.getY() != player.absY - 1) {
                        NPCDumbPathFinder.walkTowards(spawn, player.getX(), player.getY());
                    }
                }

                if (!zombieSpawned && cycle >= 20) {
                    container.stop();
                }


                if (zombieSpawned && cycle >= 20 && player.distanceToPoint(spawn.getX(), spawn.getY()) >= 5) { 
                    if (player.distanceToPoint(spawn.getX(), spawn.getY()) < 40) { 
                       killSpawn(false);
                        player.sendMessage("The spawn lost its orientation and blew up..");
                    }
                }
            }
        };
    }

    private CycleEvent handleAcidSpecial() {
        return new CycleEvent() {
            int x;
            int y;

            @Override
            public void execute(CycleEventContainer container) {
                if (container.getOwner() == null || vorkath == null || player == null || player.isDead || vorkathInstance == null) {
                    container.stop();
                    return;
                }
                int cycle = container.getTotalTicks();
                if(Server.getGlobalObjects().exists(32000, player.getX(), player.getY(), player.getHeight())) {
                    int randomDamage = Misc.random(10) + 7;
                    vorkath.getHealth().increase(randomDamage);
                    vorkath.updateRequired = true;
                    player.appendDamage(randomDamage, Hitmark.HIT);
                    player.sendMessage("You step on the acid and take some damage");
                }
                if (cycle == 1) {
                    int minX = VorkathConstants.VORKATH_BOUNDARY.getMinimumX();
                    int maxX = VorkathConstants.VORKATH_BOUNDARY.getMaximumX();
                    int minY = 4054; //it's bugged in the boundaries
                    int maxY = VorkathConstants.VORKATH_BOUNDARY.getMaximumY();
                    for (int i = 0; i < 40; i++) {
                        int randomX = minX + Misc.random(maxX - minX);
                        int randomY = minY + Misc.random(maxY - minY);
                        if ((randomX <= 2276 && randomX >= 2268 && randomY <= 4069 && randomY >= 4061)) {
                            continue;
                        }
                        fireProjectileToLocation(1486, 100,
                                randomX,
                                randomY, 60);
                        Server.getEventHandler().submit(new DelayEvent(5) {
                            @Override
                            public void onExecute() {
                                Server.getGlobalObjects().add(new GlobalObject(32000, randomX, randomY, vorkathInstance.getHeight(), Misc.random(3) + 1, 10, -1, -1));
                            }
                        });
                    }
                }
                if (cycle >= 3 && cycle <= 25) {
                    if (cycle >= 5) {
                         if (x == player.getX() && y == player.getY()) {
                              player.appendDamage(30, Hitmark.HIT);
                          }
                    }
                    x = player.getX();
                    y = player.getY();
                    fireProjectileToLocation(1482, 95, x, y, 35);
                    player.getPA().stillGfx(131, x, y, 15, 95);
                    fireProjectileToLocation(1482, 70, x, y, 35);
                    player.getPA().stillGfx(131, x, y, 15, 70);
                }
                if (cycle == 30) {
                    Server.getGlobalObjects().remove(32000, vorkathInstance.getHeight());
                    container.stop();
                }
            }
        };
    }

    private CycleEvent handleOneHit() {
        return new CycleEvent() {
            Position arrival;

            @Override
            public void execute(CycleEventContainer container) {
                if (container.getOwner() == null || vorkath == null || player == null || player.isDead || vorkathInstance == null) {
                    container.stop();
                    return;
                }
                int cycle = container.getTotalTicks();
                if (cycle == 0) {
                    arrival = new Position(player.getX(), player.getY());
                }
                if (cycle == 5) {
                    int arrivalX = arrival.getX();
                    int arrivalY = arrival.getY();
                    int playerX = player.getX();
                    int playerY = player.getY();
                    if (playerX == arrivalX && playerY == arrivalY) {
                        applyRandomDamage(player.getHealth().getMaximum());
                        player.getPA().stillGfx(attackType.getEndGfx(), arrival.getX(), arrival.getY(), 100, 0);
                    } if(playerX == (arrivalX + 1)
                            || playerX == (arrivalX - 1)
                            || playerY == (arrivalY + 1)
                            || arrivalY == (arrivalY - 1)) {
                        applyRandomDamage(player.getHealth().getMaximum() / 2);
                        player.getPA().stillGfx(attackType.getEndGfx(), arrivalX, arrivalY, 100, 0);
                    } else {
                        player.getPA().stillGfx(attackType.getEndGfx(), arrivalX, arrivalY, 20, 0);
                    }
                    container.stop();
                }
            }
        };
    }

    private void fireTargetedProjectile(int projectileId) {
        int offY = (vorkath.getX() - player.getX()) * -1;
        int offX = (vorkath.getY() - player.getY()) * -1;
        int delay = 0;
        player.getPA().createPlayersProjectile(vorkath.getX() + 3, vorkath.getY(), offX, offY, 50, 110, projectileId, 35, 31, -player.getIndex() - 1, 65, delay);
    }

    private void fireProjectileToLocation(int projectileId, int projectileSpeed, int targetX, int targetY, int startHeight) {
        int offY = (vorkath.getX() - targetX) * -1;
        int offX = (vorkath.getY() - targetY) * -1;
        int delay = 0;
        player.getPA().createPlayersProjectile(vorkath.getX() + 3, vorkath.getY(), offX, offY - 3, 50, projectileSpeed, projectileId, startHeight, 31, 0, 65, delay);
    }

    private void fireOneshit(int projectileId, int projectileSpeed, int targetX, int targetY, int angle, int startHeight) {
        int offY = (vorkath.getX() - targetX) * -1;
        int offX = (vorkath.getY() - targetY) * -1;
        int delay = 0;
        player.getPA().createPlayersProjectile(vorkath.getX() + 3, vorkath.getY(), offX, offY - 3, 50, projectileSpeed, projectileId, startHeight, 31, 0, 65, delay);
    }


    private CycleEvent handleAttackType() {
        return new CycleEvent() {
            @Override
            public void execute(CycleEventContainer container) {
                if (container.getOwner() == null || vorkath == null || player == null || player.isDead || vorkathInstance == null) {
                    container.stop();
                    return;
                }
                int cycle = container.getTotalTicks();
                //player.getPA().stillGfx(attackType.getEndGfx(), player.getX(), player.getY(), 100, 110);
                if (cycle == 4) {
                    handleEffect();
                }
                if (cycle == 5) {
                    player.getPA().stillGfx(attackType.getEndGfx(), player.getX(), player.getY(), 100, 0);
                    container.stop();
                }
            }
        };
    }

    private void applyRandomDamage(int amount) {
        player.appendDamage(Misc.random(amount) + 1, Hitmark.HIT);
    }

    private void handleEffect() {
        switch (attackType) {
            case MAGIC:
                if (player.prayerActive[16]) {
                    player.appendDamage(0, Hitmark.MISS);
                    return;
                } else {
                    applyRandomDamage(35);
                }
                break;
            case POISON:
                applyRandomDamage(3);
                player.getHealth().proposeStatus(HealthStatus.POISON, Misc.random(12), Optional.of(vorkath));
                break;
            case RANGED:
                if (player.prayerActive[17]) {
                    player.appendDamage(0, Hitmark.MISS);
                    return;
                } else {
                    applyRandomDamage(30);
                }
                break;
            case DRAGON_FIRE:
                boolean isResistent =
                        player.getItems().isWearingItem(1540)
                                || player.getItems().isWearingItem(11283)
                                || player.getItems().isWearingItem(11284)
                                || (System.currentTimeMillis() - player.lastAntifirePotion < player.antifireDelay);
                if (isResistent) {
                    player.sendMessage("Your resistance reflects the dragons fire!");
                    player.appendDamage(0, Hitmark.MISS);
                    return;
                } else {
                    applyRandomDamage(35);
                    player.sendMessage("You got horribly burned by the dragons fire.");
                }
                break;
            case PRAYER_SNIPE:
                for (int i = 0; i < player.prayerActive.length - 1; i++) {
                    if (!player.prayerActive[i])
                        continue;
                    player.prayerActive[i] = false;
                    player.getPA().sendFrame36(player.PRAYER_GLOW[i], 0);
                }
                player.headIcon = -1;
                player.getPA().requestUpdates();
                applyRandomDamage(3);
                break;
        default:
            break;
        }
    }


    public void handleDeath() {
        vorkathState = VorkathState.RESTING;
        CycleEventHandler.getSingleton().addEvent(eventLock, new DeathStage(this, player), 1);
    }

    public void setVorkathInstance(SingleInstancedVorkath vorkathInstance) {
        this.vorkathInstance = vorkathInstance;
    }

    public AttackType getAttackType() {
        return attackType;
    }

    public VorkathState getVorkathState() {
        return vorkathState;
    }

    public SingleInstancedArea getVorkathInstance() {
        return vorkathInstance;
    }

    public Object getEventLock() {
        return eventLock;
    }

    public AttackType getSpecialAttackType() {
        return specialAttackType;
    }

    public void setVorkathState(VorkathState vorkathState) {
        this.vorkathState = vorkathState;
    }

    public NPC getNpc() {
        return vorkath;
    }

    public void setVorkath(NPC vorkath) {
        this.vorkath = vorkath;
    }

    public int getAttacks() {
        return attacks;
    }

    public void setAttacks(int attacks) {
        this.attacks = attacks;
    }

    public boolean isForceDeath() {
        return forceDeath;
    }

    public void setForceDeath(boolean forceDeath) {
        this.forceDeath = forceDeath;
    }    public boolean isZombieSpawned() {
        return zombieSpawned;
    }
}



VorkathConstants class

package osv.model.npcs.bosses.vorkath;

import osv.model.players.Boundary;

/**
 * @author Yasin
 */
public class VorkathConstants {

    public static final int SLEEPING_VORKATH_ID = 8059;
    public static final int AWAKENED_VORKATH_ID = 8061;

    public static final int ZOMBIE_SPAWN = 8063;
    public static final int ZOMBIE_SPAWN_LIFE_POINTS = 38;

    public static final int VORKATH_LIFE_POINTS = 769;


    public static final int X_COORDINATE = 2269;
    public static final int Y_COORDINATE = 4062;

    public static final Boundary VORKATH_BOUNDARY = new Boundary(2262, 4061, 2282, 4072);


}


VorkathState class

package osv.model.npcs.bosses.vorkath;

/**
 * @author Yasin
 */
public enum VorkathState {
    SLEEPING(-1, -1),
    RESTING(-1, -1),
    AWAKE(-1, -1);

    private int animation;

    private int npcId;

    VorkathState(int animation, int npcId) {
        this.animation = animation;
        this.npcId = npcId;
    }

    public int getAnimation() {
        return animation;
    }

    public int getNpcId() {
        return npcId;
    }
}


impl/DeathStage

package osv.model.npcs.bosses.vorkath.impl;


import osv.Server;
import osv.event.CycleEventContainer;
import osv.event.CycleEventHandler;
import osv.model.npcs.NPCHandler;
import osv.model.npcs.bosses.vorkath.Vorkath;
import osv.model.npcs.bosses.vorkath.VorkathConstants;
import osv.model.npcs.bosses.vorkath.VorkathState;
import osv.model.players.Player;

/**
 * @author Yasin
 */
public class DeathStage extends Stage {
    public DeathStage(Vorkath vorkath, Player player) {
        super(vorkath, player);
    }

    @Override
    public void execute(CycleEventContainer container) {
        if (container.getOwner() == null || vorkath == null || player == null || player.isDead || vorkath.getVorkathInstance() == null) {
            container.stop();
            return;
        }
        int cycle = container.getTotalTicks();
        int height = vorkath.getVorkathInstance().getHeight();
        //reset both combat until stage ends
        vorkath.resetCombat();
        player.getCombat().resetPlayerAttack();
       // player.sendMessage("Death stage Cycle: " + cycle);
        if (cycle == 1) {
            vorkath.setVorkathState(VorkathState.RESTING);
            vorkath.getNpc().isDead = false;
            vorkath.getNpc().spawnedMinions = false;
            player.sendMessage("The dragon died..");
            vorkath.getNpc().startAnimation(7949);//death animation
            vorkath.getNpc().requestTransform(8059);
            vorkath.setVorkath(Server.npcHandler.getNpc(VorkathConstants.SLEEPING_VORKATH_ID, VorkathConstants.X_COORDINATE, VorkathConstants.Y_COORDINATE, height));
            container.stop();
        }
        /*if (cycle == 10) {
            CycleEventHandler.getSingleton().addEvent(vorkath.getEventLock(), new WakeUpStage(vorkath, player, true), 1);
            container.stop();
        }*/
    }
}


impl/SpawnStage
 

package osv.model.npcs.bosses.vorkath.impl;


import osv.Server;
import osv.event.CycleEventContainer;
import osv.model.npcs.bosses.vorkath.Vorkath;
import osv.model.npcs.bosses.vorkath.VorkathConstants;
import osv.model.players.Player;

/**
 * @author Yasin
 */
public class SpawnStage extends Stage {

    public SpawnStage(Vorkath vorkath, Player player) {
        super(vorkath, player);
    }

    @Override
    public void execute(CycleEventContainer container) {
        if (container.getOwner() == null || vorkath == null || player == null || player.isDead || player.disconnected || vorkath.getVorkathInstance() == null) {
            container.stop();
            return;
        }
        int cycle = container.getTotalTicks();
        int height = vorkath.getVorkathInstance().getHeight();
        if(cycle == 1) {
           // player.sendMessage("Height before:" + player.heightLevel);
            player.setHeight(height);
            player.heightLevel = height;
            Server.getGlobalObjects().remove(32000, height);
            //player.sendMessage("Height after: " + player.getHeight());
            vorkath.setVorkath(Server.npcHandler.spawnNpc(player, VorkathConstants.SLEEPING_VORKATH_ID, VorkathConstants.X_COORDINATE, VorkathConstants.Y_COORDINATE, height, -1, VorkathConstants.VORKATH_LIFE_POINTS, 1, 500, 500, false, false));
            //player.sendMessage("On height: " + height);
        }
        if(cycle == 2) {
            player.sendMessage("You find yourself in a cave, with a dragon sleeping..");
        }
        if(cycle >= 3) {
            container.stop();
        }
    }
}


**Please move Stage outside of the impl package, hence Stage is not an implementation of itself..**

impl/Stage class

package osv.model.npcs.bosses.vorkath.impl;


import osv.event.CycleEvent;
import osv.event.CycleEventContainer;
import osv.model.npcs.bosses.vorkath.Vorkath;
import osv.model.players.Player;

/**
 * @author Yasin
 */
public class Stage extends CycleEvent {

    protected Vorkath vorkath;

    protected Player player;

    public Stage(Vorkath vorkath, Player player) {
        this.vorkath = vorkath;
        this.player = player;
    }

    @Override
    public void execute(CycleEventContainer container) {

    }
}


 

package osv.model.npcs.bosses.vorkath.impl;


import osv.Server;
import osv.event.CycleEventContainer;
import osv.model.npcs.NPCHandler;
import osv.model.npcs.bosses.vorkath.Vorkath;
import osv.model.npcs.bosses.vorkath.VorkathConstants;
import osv.model.npcs.bosses.vorkath.VorkathState;
import osv.model.players.Player;

/**
 * @author Yasin
 */
public class WakeUpStage extends Stage {

    private boolean alreadyAlive;

    public WakeUpStage(Vorkath vorkath, Player player) {
        super(vorkath, player);
    }

    public WakeUpStage(Vorkath vorkath, Player player, boolean alreadyAlive) {
        super(vorkath, player);
        this.alreadyAlive = alreadyAlive;
    }

    @Override
    public void execute(CycleEventContainer container) {
        if (container.getOwner() == null || vorkath == null || player == null || player.isDead) {
            container.stop();
            return;
        }
        int cycle = container.getTotalTicks();
        //reset both combat until stage ends
        if(vorkath != null) {
            vorkath.resetCombat();
        }
        if(alreadyAlive) {
            if(cycle == 3) {
                vorkath.getNpc().getHealth().setAmount(VorkathConstants.VORKATH_LIFE_POINTS);
            }
            if(cycle == 6) {
                vorkath.getNpc().startAnimation(7950);
            }
            if(cycle == 9) {
                vorkath.setAttacks(0);
                vorkath.getNpc().requestTransform(VorkathConstants.AWAKENED_VORKATH_ID);
                vorkath.setVorkath(Server.npcHandler.getNpc(VorkathConstants.AWAKENED_VORKATH_ID, VorkathConstants.X_COORDINATE, VorkathConstants.Y_COORDINATE, player.getHeight()));
                vorkath.setVorkathState(VorkathState.AWAKE);
            }
            if(cycle >= 12) {
                container.stop();
            }
        } else {
            if(cycle == 1) {
                player.startAnimation(2292);
                player.sendMessage("You poke the dragon..");
            }
            if(cycle == 2) {
                vorkath.getNpc().startAnimation(7950);
                player.turnPlayerTo(vorkath.getNpc().getX(), vorkath.getNpc().getY() - 3);
                vorkath.getNpc().getHealth().setAmount(VorkathConstants.VORKATH_LIFE_POINTS);
            }
            if(cycle == 9) {
                vorkath.getNpc().requestTransform(VorkathConstants.AWAKENED_VORKATH_ID);
                vorkath.setVorkathState(VorkathState.AWAKE);
                container.stop();
            }
        }


    }
}

 

AttackAnimation class, handleEmote method
Under the switch case

case VorkathConstants.AWAKENED_VORKATH_ID:
            case VorkathConstants.SLEEPING_VORKATH_ID:
                Player player = PlayerHandler.players[Server.npcHandler.npcs[i].spawnedBy];
                if (player == null || player.getVorkath() == null || player.getVorkath().getNpc() == null) {
                    return -1;
                }
                if (player.getVorkath().canSpecial()) {
                    return player.getVorkath().getSpecialAttackType().getAnimationId();
                } else if (player.distanceToPoint(Server.npcHandler.npcs[i].getX(), Server.npcHandler.npcs[i].getY()) > 4) {
                    return player.getVorkath().getAttackType().getAnimationId(); //regular attacks (distance)
                }
                return 7951;

 

DeathAnimation class, handleEmote method
under the switch case

case VorkathConstants.ZOMBIE_SPAWN:
            case VorkathConstants.AWAKENED_VORKATH_ID:
            case VorkathConstants.SLEEPING_VORKATH_ID:
                return 102;

 

NPCHandler class,  getNpcDelay method
under the switch case

case VorkathConstants.AWAKENED_VORKATH_ID:
            case VorkathConstants.SLEEPING_VORKATH_ID:
                return 4;

 

NPCHandler class, process method
under 

if (npcs[i].actionTimer == 0 && !npcs[i].applyDead && !npcs[i].needRespawn) {

add this

if(npcs[i].npcType == VorkathConstants.SLEEPING_VORKATH_ID) {
                            npcs[i].isDead = false;
                            //player.sendMessage("HELL NO");
                            continue;
                        }
                        if (npcs[i].npcType == VorkathConstants.AWAKENED_VORKATH_ID) {
                            if (player.getVorkath().isForceDeath()) { //if forced death (ie player logout)
                                npcs[i].isDead = true;
                                npcs[i].updateRequired = true;
                            } else {
                                //player.sendMessage("Applying death");
                                npcs[i].killedBy = player.getIndex();
                                dropItems(i);
                                player.getVorkath().resetCombat();
                                player.getVorkath().handleDeath();
                            }
                            continue;
                        }

 

under

if (c.respawnTimer <= 0) {


add this:

if(npcs[i].npcType == VorkathConstants.AWAKENED_VORKATH_ID) {
                        return;
                    }

 

NPCHandler class, followPlayer method
under the switch case

case VorkathConstants.AWAKENED_VORKATH_ID:
        case VorkathConstants.SLEEPING_VORKATH_ID:
            return false;

 

NPCHandler class, attackPlayer method
under

if (npcs[i].lastX != npcs[i].getX() || npcs[i].lastY != npcs[i].getY()) {
            return;
        }

add


if(npcs[i].npcType == VorkathConstants.SLEEPING_VORKATH_ID) {
            return;
        }
if (npcs[i].npcType == VorkathConstants.AWAKENED_VORKATH_ID) {
            if (c.getVorkath() != null) {
                c.getVorkath().handleAttack();
            }
        }

 

NPCHandler class, isAggressive (this should make vorkath aggressive]
 

case VorkathConstants.AWAKENED_VORKATH_ID:
            return true;

 

NPCHandler class, dropItems method

if (npcs[i].npcType == VorkathConstants.AWAKENED_VORKATH_ID) {
                dropX = 2267;
                dropY = 4061;
                if (player.getNpcDeathTracker().getTracker().get(npcs[i].getName()) != null) {
                    int kills = player.getNpcDeathTracker().getTracker().get(npcs[i].getName());
                    if (kills == 50) {
                        Server.itemHandler.createGroundItem(player, 21907, dropX, dropY, player.heightLevel, 1);
                    }
                }
            }

 

NPCHandler class, distanceRequired method
under switch case

case VorkathConstants.AWAKENED_VORKATH_ID:
            return 35;

 

NPCHandler class, retaliates(

|| npcType == VorkathConstants.AWAKENED_VORKATH_ID

 

Config class, UNDEAD_IDS array, add this element:

VorkathConstants.ZOMBIE_SPAWN


Disposal of instance on logout:

Player class, logout method

if (vorkath.getVorkathInstance() != null) { //if logging out from vorkath or while in vorkath instance
                getPA().movePlayer(2272, 4052, 0);
                vorkath.disposeInstance();
            }


[/code]
[/SPOILER]

Disposal of instance when out of reach
[SPOILER=Player, process]

if (vorkath != null) {
            if (vorkath.getVorkathInstance() != null) {
                if (vorkath.getNpc() != null) {
                    if (distanceToPoint(vorkath.getNpc().getX(), vorkath.getNpc().getY()) >= 40) {
                        vorkath.disposeInstance();
                        sendMessage("Vorkath seems to have despawned..");
                    }
                }
            }
        }

 

at last:

Player class:
declare instance

private Vorkath vorkath = new Vorkath(this);

declare getters/setters 

public Vorkath getVorkath() {
        return vorkath;
    }

    public void setVorkath(Vorkath vorkath) {
        this.vorkath = vorkath;
    }


create class
SingleInstancedVorkath class

package osv.model.content.instances.impl;


import osv.model.content.instances.SingleInstancedArea;
import osv.model.npcs.bosses.vorkath.Vorkath;
import osv.model.players.Boundary;
import osv.model.players.Player;

/**
 * @author Yasin
 */
public class SingleInstancedVorkath extends SingleInstancedArea {
    public SingleInstancedVorkath(Boundary boundary, int height) {
        super(boundary, height);
    }

    public SingleInstancedVorkath(Player player, Boundary boundary, int height) {
        super(player, boundary, height);
    }

    @Override
    public void onDispose() {
        Vorkath vorkath = player.getVorkath();
        if (vorkath != null) {
            vorkath.disposeInstance();
        }
    }
}

 

ObjectOptionOne class, under handleOption1add to the objectType switch:

case 31990:
			if(c.getVorkath().getVorkathInstance() == null) {
				c.getVorkath().jump();
			}
			break;


 

Edited by Yasin

  • 2 weeks later...
  • 5 months later...
  • 3 months later...
  • 5 months later...
  • 1 month later...
  • 2 weeks later...
  • 4 weeks later...
  • 1 year later...
  • 2 months later...
  • 1 month later...
  • 10 months later...
  • 5 months later...

Create an account or sign in to comment