public static double getPlayerMaxHit(Player player, int strBonusIncrease)
        {
            AttackStyle.CombatSkill fightType = player.getAttackStyle().getSkill();
            double myCurStrength = player.getSkills().getCurLevel(Skills.SKILL.STRENGTH);
            double myEquipStrengthBonus = (player.getEquipment().getBonus(Equipment.BONUS.STRENGTH) + strBonusIncrease);
            double fightingStyle = 0;
            double powerMultiplier = 1;
            double dharokModifier = 1;
            double damageMultiplier = 1;
            int strPrayer = player.getPrayers().getStrengthPrayer();
            if (strPrayer == 1)
            {
                powerMultiplier += 0.05;
            }
            else if (strPrayer == 2)
            {
                powerMultiplier += 0.1;
            }
            else if (strPrayer == 3)
            {
                powerMultiplier += 0.15;
            }
            else if (player.getPrayers().getSuperPrayer() == 1)
            {
                powerMultiplier += 0.18;
            }
            else if (player.getPrayers().getSuperPrayer() == 2)
            {
                powerMultiplier += 0.23;
            }

            if (wearingMeleeVoid(player))
            {
                damageMultiplier += 0.1;
            } else if (wearingDharok(player))
            {
                dharokModifier = (player.getSkills().getGreaterLevel(Skills.SKILL.HITPOINTS) - player.getSkills().getCurLevel(Skills.SKILL.HITPOINTS)) * 0.1;
            }
            if (fightType.Equals(AttackStyle.CombatSkill.AGGRESSIVE))
            {
                fightingStyle = 3;
            } else if (fightType.Equals(AttackStyle.CombatSkill.CONTROLLED))
            {
                fightingStyle = 1;
            }

            double cumulativeStrength = ((myCurStrength) * (powerMultiplier) + fightingStyle) * dharokModifier;
            //Can't change this. For huge damage it's a visual effect, not real maxHit!
            double maxHit = ((13 + (cumulativeStrength) + (myEquipStrengthBonus / 8) + ((cumulativeStrength * myEquipStrengthBonus) / 64)) * damageMultiplier) / 10; // NEW MAX HIT FORMULA
            return maxHit;
        }
	    public static void displayItemsInterface(Player p) {
		    int amountToKeep = p.isSkulled() ? 0 : 3;
		    if (p.getPrayers().isProtectItem()) {
			    amountToKeep = p.isSkulled() ? 1 : 4;
		    }
		    int item1 = getProtectedItem1(p)[0];
		    int item2 = getProtectedItem2(p)[0];
		    int item3 = getProtectedItem3(p)[0];
		    int item4 = amountToKeep == 4 ? getProtectedItem4(p)[0] : -1;
		    if (amountToKeep == 1) {
			    item2 = 65535;
			    item3 = 65535;
			    item3 = item1;
		    }
		    if (amountToKeep == 0) {
			    item1 = 65535;
			    item2 = 65535;
			    item3 = 65535;
			    item4 = 65535;
		    }
		    object[] opts = new object[]{17598720, 20221838, "You're marked with a <col=ff3333>skull<col=ff981f>.", 0, 1, item4, item1, item2, item3, /* Items to keep */ amountToKeep /* Items to keep */, 0};
		    p.getPackets().displayInterface(102);
            p.getPackets().sendClientScript(118, opts, "iiooooiisii");
            p.getPackets().setRightClickOptions(1278, (102 * 65536) + 21, 0, 40);
            p.getPackets().setRightClickOptions(1278, (102 * 65536) + 18, 0, 4);
	    }
        public static double getRangeDefence(Player p)
        {
            int rangedDefenceBonus = p.getEquipment().getBonus(Equipment.BONUS.RANGED_DEFENCE);
            double defenceLevel = p.getSkills().getCurLevel(Skills.SKILL.DEFENCE);
            AttackStyle.CombatSkill fightType = p.getAttackStyle().getSkill();
            if (fightType.Equals(AttackStyle.CombatSkill.DEFENSIVE))
                defenceLevel *= 1.10; //%10 increase.

            if(p.getPrayers().isPrayerActive(PrayerData.Prayer.THICK_SKIN))
                defenceLevel *= 1.05; //5% increase.
            else if (p.getPrayers().isPrayerActive(PrayerData.Prayer.ROCK_SKIN))
                defenceLevel *= 1.10; //10% increase.
            else if (p.getPrayers().isPrayerActive(PrayerData.Prayer.STEEL_SKIN))
                defenceLevel *= 1.15; //15% increase.
            else if (p.getPrayers().isPrayerActive(PrayerData.Prayer.SMITE))
                defenceLevel *= 1.20; //20% increase.
            else if (p.getPrayers().isPrayerActive(PrayerData.Prayer.CHIVALRY))
                defenceLevel *= 1.25; //25% increase.

            double rangeDefence = (defenceLevel * rangedDefenceBonus) / 200;
            return rangeDefence;

        }
	    public static double getRangeMaxHit(Player p, int bow, int arrow) {
            /*
            int a = p.getEquipment().getBonus(Equipment.BONUS.CRUSH_ATTACK);
            int b = p.getEquipment().getBonus(Equipment.BONUS.CRUSH_DEFENCE);
            int c = p.getEquipment().getBonus(Equipment.BONUS.MAGIC_ATTACK);
            int d = p.getEquipment().getBonus(Equipment.BONUS.MAGIC_DEFENCE);
            int e = p.getEquipment().getBonus(Equipment.BONUS.PRAYER);
            int f = p.getEquipment().getBonus(Equipment.BONUS.RANGED_ATTACK);
            int g = p.getEquipment().getBonus(Equipment.BONUS.RANGED_DEFENCE);
            int h = p.getEquipment().getBonus(Equipment.BONUS.SLASH_ATTACK);
            int i = p.getEquipment().getBonus(Equipment.BONUS.SLASH_DEFENCE);
            int j = p.getEquipment().getBonus(Equipment.BONUS.STAB_ATTACK);
            int k = p.getEquipment().getBonus(Equipment.BONUS.STAB_DEFENCE);
            int l = p.getEquipment().getBonus(Equipment.BONUS.STRENGTH);
            int m = p.getEquipment().getBonus(Equipment.BONUS.SUMMONING);
            */

            double rangeLevel = p.getSkills().getCurLevel(Skills.SKILL.RANGE);
            //TODO: use rangeAttackBonus in the formula somehow!.
            double rangeAttackBonus = p.getEquipment().getBonus(Equipment.BONUS.RANGED_ATTACK);
		    double rangeAttackMultipler = 1.00;
		    double rangeAttack = 0;
            int rangedWeaponArrowStrength = getRangeWeaponArrowStrength(p);
		    int rangePrayer = p.getPrayers().getRangePrayer();

            if (rangePrayer == 1)
                rangeAttackMultipler *= 1.05; //5% increase
            else if (rangePrayer == 2)
                rangeAttackMultipler *= 1.10; //10% increase
            else if (rangePrayer == 3)
                rangeAttackMultipler *= 1.15; //15% increase

		    if (wearingRangeVoid(p)) {
                rangeAttackMultipler *= 1.15; //15% increase
		    }
            rangeAttack = (rangeLevel * rangeAttackMultipler);
		    if (p.getAttackStyle().getStyle().Equals(AttackStyle.CombatStyle.RANGE_ACCURATE)) {
                rangeAttack += 3.00;
		    }
            double rangeMaxHit = ((rangeAttack + 8) * (rangedWeaponArrowStrength + 64) / 640);
            return rangeMaxHit;
	    }
	    private static double getMagicAttack(Player p) {
            int magicAttackBonus = p.getEquipment().getBonus(Equipment.BONUS.MAGIC_ATTACK);
            double magicLevel = Convert.ToDouble(p.getSkills().getCurLevel(Skills.SKILL.MAGIC));
		    double power = 1.800;
		    double amount = 0.0205;
            if (magicAttackBonus >= 80)  // equivalent of max mage w/ zerker+whip
			    amount = 0.0500;
            else if (magicAttackBonus >= 90) // equivalent of max mage w/whip or mystic + ancient staff
			    amount = 0.0780;
            else if (magicAttackBonus >= 105) // equivalent of max mage w/ ancient staff
			    amount = 0.920;
            else if (magicAttackBonus >= 115) // equivalent of max mage w/ wand or better
			    amount = 0.1110;
            power *= (magicAttackBonus * amount) + (magicLevel *= 0.0120);
		    int magicPrayer = p.getPrayers().getMagicPrayer();
            if (magicPrayer > 0)
            {
                if (magicPrayer == 1)
				    power *= 1.05; //5% increase
                else if (magicPrayer == 2)
				    power *= 1.10; //10% increase
                else if (magicPrayer == 3)
				    power *= 1.15; //15% increase
		    }
		    return power;
	    }
	    public static double getMeleeAttack(Player p) {
            //TODO: implement all Equipment Bonuses to be used for all of these Defence/Melee Attack functions.
            /*
            int a = p.getEquipment().getBonus(Equipment.BONUS.CRUSH_ATTACK);
            int b = p.getEquipment().getBonus(Equipment.BONUS.CRUSH_DEFENCE);
            int c = p.getEquipment().getBonus(Equipment.BONUS.MAGIC_ATTACK);
            int d = p.getEquipment().getBonus(Equipment.BONUS.MAGIC_DEFENCE);
            int e = p.getEquipment().getBonus(Equipment.BONUS.PRAYER);
            int f = p.getEquipment().getBonus(Equipment.BONUS.RANGED_ATTACK);
            int g = p.getEquipment().getBonus(Equipment.BONUS.RANGED_DEFENCE);
            int h = p.getEquipment().getBonus(Equipment.BONUS.SLASH_ATTACK);
            int i = p.getEquipment().getBonus(Equipment.BONUS.SLASH_DEFENCE);
            int j = p.getEquipment().getBonus(Equipment.BONUS.STAB_ATTACK);
            int k = p.getEquipment().getBonus(Equipment.BONUS.STAB_DEFENCE);
            int l = p.getEquipment().getBonus(Equipment.BONUS.STRENGTH);
            int m = p.getEquipment().getBonus(Equipment.BONUS.SUMMONING);
            */

		    int highestAttackBonus = getHighestAttackBonus(p);
            int attackLevel = p.getSkills().getCurLevel(Skills.SKILL.ATTACK);
            double multipler = 1.00;

		    if (p.getPrayers().getAttackPrayer() == 1) {
                multipler *= 1.05; //5% increase
		    } else if (p.getPrayers().getAttackPrayer() == 2) {
                multipler *= 1.10; //10% increase
		    } else if (p.getPrayers().getAttackPrayer() == 3 || p.getPrayers().getSuperPrayer() == 1) {
                multipler *= 1.15; //15% increase
		    } else if (p.getPrayers().getSuperPrayer() == 2) {
                multipler *= 1.20; //20% increase
		    }
		    if (wearingMeleeVoid(p)) {
                multipler *= 1.10; //10% increase
		    }

            double effectiveAttack = (attackLevel * multipler);
            return effectiveAttack * (highestAttackBonus > 0 ? highestAttackBonus : 1);
	    }
        private static void appendAppearanceUpdate(Player p, PacketBuilder updateBlock) {
		    PacketBuilder playerProps = new PacketBuilder().setSize(Packet.Size.Bare);
		
		    Appearance app = p.getAppearance();
		    playerProps.addByte((byte) (app.getGender() & 0xFF));
		    if((app.getGender() & 0x2) == 2) {
			    playerProps.addByte((byte) 0);
			    playerProps.addByte((byte) 0);
		    }
		    playerProps.addByte((byte) p.getPrayers().getPkIcon());
		    playerProps.addByte((byte) p.getPrayers().getHeadIcon());
		    if (!app.isInvisible()) {
			    if(!app.isNpc()) {
				    for(int i = 0; i < 4; i++) {
					    if(p.getEquipment().getItemInSlot((ItemData.EQUIP)i) != -1) {
                            playerProps.addUShort(32768 + p.getEquipment().getSlot((ItemData.EQUIP)i).getDefinition().getEquipId());
					    } else {
						    playerProps.addByte((byte) 0);
					    }
				    }
                    if (p.getEquipment().getItemInSlot(ItemData.EQUIP.CHEST) != -1)
                    {
                        playerProps.addUShort(32768 + p.getEquipment().getSlot(ItemData.EQUIP.CHEST).getDefinition().getEquipId());
				    } else {
                        playerProps.addUShort(0x100 + app.getLook(ItemData.EQUIP.AMULET));
				    }
                    if (p.getEquipment().getItemInSlot(ItemData.EQUIP.SHIELD) != -1)
                    {
                        playerProps.addUShort(32768 + p.getEquipment().getSlot(ItemData.EQUIP.SHIELD).getDefinition().getEquipId());
				    } else {
					    playerProps.addByte((byte) 0);
				    }
                    Item chest = p.getEquipment().getSlot(ItemData.EQUIP.CHEST);
                    if (chest != null && chest.getDefinition() != null)
                    {
					    if(!ItemData.isFullBody(chest.getDefinition())) {
                            playerProps.addUShort(0x100 + app.getLook(ItemData.EQUIP.WEAPON));
					    } else {
						    playerProps.addByte((byte) 0);
					    }
				    } else {
                        playerProps.addUShort(0x100 + app.getLook(ItemData.EQUIP.WEAPON));
				    }
                    if (p.getEquipment().getItemInSlot(ItemData.EQUIP.LEGS) != -1)
                    {
                        playerProps.addUShort(32768 + p.getEquipment().getSlot(ItemData.EQUIP.LEGS).getDefinition().getEquipId());
				    } else {
                        playerProps.addUShort(0x100 + app.getLook(ItemData.EQUIP.SHIELD));
				    }
                    Item hat = p.getEquipment().getSlot(ItemData.EQUIP.HAT);
                    if (hat != null && hat.getDefinition() != null)
                    {
					    if(!ItemData.isFullHat(hat.getDefinition()) && !ItemData.isFullMask(hat.getDefinition())) {
                            playerProps.addUShort(0x100 + app.getLook(ItemData.EQUIP.HAT));
					    } else {
						    playerProps.addByte((byte) 0);
					    }
				    } else {
                        playerProps.addUShort(0x100 + app.getLook(ItemData.EQUIP.HAT));
				    }
                    if (p.getEquipment().getItemInSlot(ItemData.EQUIP.HANDS) != -1)
                    {
                        playerProps.addUShort(32768 + p.getEquipment().getSlot(ItemData.EQUIP.HANDS).getDefinition().getEquipId());
				    } else {
                        playerProps.addUShort(0x100 + app.getLook(ItemData.EQUIP.CHEST));
				    }
                    if (p.getEquipment().getItemInSlot(ItemData.EQUIP.FEET) != -1)
                    {
                        playerProps.addUShort(32768 + p.getEquipment().getSlot(ItemData.EQUIP.FEET).getDefinition().getEquipId());
				    } else {
					    playerProps.addUShort(0x100 + app.getLook(6));
				    }
                    if (hat != null && hat.getDefinition() != null)
                    {
					    if(!ItemData.isFullMask(hat.getDefinition())) {
                            playerProps.addUShort(0x100 + app.getLook(ItemData.EQUIP.CAPE));
					    } else {
						    playerProps.addByte((byte) 0);
					    }
				    } else {
                        playerProps.addUShort(0x100 + app.getLook(ItemData.EQUIP.CAPE));
				    }
			    } else {
				    playerProps.addUShort(-1);
				    playerProps.addUShort(app.getNpcId());
				    playerProps.addByte((byte) 255);
			    }
		    } else {
			    for (int i = 0; i < 12; i++) {
				    playerProps.addByte((byte) 0);
			    }
		    }
		    foreach(int colour in app.getColoursArray()) {
			    playerProps.addByte((byte) colour);
		    }
		    playerProps.addUShort(p.getEquipment().getStandWalkAnimation());
		    playerProps.addLong(p.getLoginDetails().getLongName());
		    playerProps.addByte((byte) p.getSkills().getCombatLevel());
		    playerProps.addUShort(0);
		    playerProps.addByte((byte) 0);
		    updateBlock.addByteA((byte) (playerProps.getLength() & 0xFF));
		    updateBlock.addBytes(playerProps.toPacket().getData(), 0, playerProps.getLength());
	    }
	    public static void fightCaveAttacks(Npc npc, Player p) {
		    if (npc.isDead() || npc.isDestroyed() || p.isDead() || p.isDestroyed() || p.isDead() || !Location.inFightCave(p.getLocation()) || p.getTeleportTo() != null) {
			    return;
		    }
		    double damage = misc.randomDouble(npc.getMaxHit());
            PrayerData.PrayerHeadIcon prayerHeadIcon = p.getPrayers().getHeadIcon();
		    int hitDelay = npc.getHitDelay();
		    int animation = npc.getAttackAnimation();
		    switch(npc.getId()) {
			    case 2734: // Tz-Kih (lvl 22)
			    case 2735:
                    if (prayerHeadIcon == PrayerData.PrayerHeadIcon.MELEE)
                    {
					    damage = 0;
				    }
				    break;
				
			    case 2739: // Tz-Xil (lvl 90)
			    case 2740:
                    if (prayerHeadIcon == PrayerData.PrayerHeadIcon.RANGE)
                    {
					    damage = 0;
				    }
				    p.getPackets().sendProjectile(npc.getLocation(), p.getLocation(), 32, 1616, 50, 40, 34, 50, p);
				    break;
				
			    case 2741: // Yt-MejKot (lvl 180)
			    case 2742:
                    if (prayerHeadIcon == PrayerData.PrayerHeadIcon.MELEE)
                    {
					    damage = 0;
				    }
				    // TODO healing
				    break;
				
			    case 2743: // Ket-Zek (lvl 360)
			    case 2744:
				    if (!p.getLocation().withinDistance(npc.getLocation(), 2)) {
					    hitDelay = 1600;
					    animation = 9266;
					    npc.setLastGraphics(new Graphics(1622));
					    damage = misc.randomDouble(49);
                        if (prayerHeadIcon == PrayerData.PrayerHeadIcon.MAGIC)
                        {
						    damage = 0;
					    }
                        Event sendProjectileToNpc = new Event(300);
                        sendProjectileToNpc.setAction(() => {
							sendProjectileToNpc.stop();
							p.getPackets().sendProjectile(npc.getLocation(), p.getLocation(), 32, 1623, 50, 40, 34, 80, p);
					    });
                        Server.registerEvent(sendProjectileToNpc);
				    } else {
					    damage = misc.randomDouble(64);
                        if (prayerHeadIcon == PrayerData.PrayerHeadIcon.MELEE)
                        {
						    damage = 0;
					    }
				    }
				    break;
				
			    case 2745: // TzTok Jad (lvl 702)
				    doJadAttacks(p, npc);
				    break;
		    }
		    if (npc.getId() == 2745){
			    return;
		    }
		    if (animation != 65535) {
			    npc.setLastAnimation(new Animation(animation));
		    }
            p.setLastAttacked(Environment.TickCount);
            npc.setLastAttack(Environment.TickCount);
		    p.setAttacker(npc);
		    npc.resetCombatTurns();
		    if (damage > p.getHp()) {
			    damage = p.getHp();
		    }
		    int npcId = npc.getId();

            Event losePrayerFightingEvent = new Event(hitDelay);
            losePrayerFightingEvent.setAction(() => {
				losePrayerFightingEvent.stop();
				if (!Location.inFightCave(p.getLocation()) || p.getTeleportTo() != null) {
					return;
				}
				if (npcId == 2734 || npcId == 2735) {
                    int prayerLevel = p.getSkills().getCurLevel(Skills.SKILL.PRAYER);
                    int newPrayerLevel = prayerLevel -= (int)(damage + 1);
					if (newPrayerLevel <= 0) {
						newPrayerLevel = 0;
					}
					p.getSkills().setCurLevel(Skills.SKILL.PRAYER, newPrayerLevel);
                    p.getPackets().sendSkillLevel(Skills.SKILL.PRAYER);
				} else if (npcId == 2743 || npcId == 2744) {
					if (misc.random(1) == 0) {
						p.setLastGraphics(new Graphics(1624, 0));
					}
				}
				if ((p.getCombatTurns() > 2 || p.getCombatTurns() < 0)) {
					p.setLastAnimation(new Animation(p.getDefenceAnimation()));
				}
                p.hit(damage);
		    });
            Server.registerEvent(losePrayerFightingEvent);
	    }
	    private static void doJadAttacks(Player p, Npc npc) {
		    if (npc.getHp() <= (npc.getMaxHp() * 0.50)) {
			    if (p.getFightCave() != null) {
                    if (!p.getFightCave().isHealersSpawned())
                    {
					    summonJadHealers(p, npc);
					    p.getFightCave().setHealersSpawned(true);
				    }
			    }
		    }
		    npc.resetCombatTurns();
		    npc.setEntityFocus(p.getClientIndex());
		    switch(misc.random(1)) {
			    case 0: // Range
				    npc.setLastAnimation(new Animation(9276));
				    npc.setLastGraphics(new Graphics(1625));
                    Event jadRangeAttackEvent = new Event(1600);
                    int jadRangeAttackStatus = 0;
                    jadRangeAttackEvent.setAction(() => {
					    double hit = 0;
                        PrayerData.PrayerHeadIcon prayerHeadIcon = p.getPrayers().getHeadIcon();
                        if (jadRangeAttackStatus == 0)
                        {
                            jadRangeAttackStatus++;
							jadRangeAttackEvent.setTick(1500);
							p.setLastGraphics(new Graphics(451));
                            if (prayerHeadIcon == PrayerData.PrayerHeadIcon.RANGE)
								hit = 0;
							else
								hit = misc.randomDouble(96);
						} else {
                            if (prayerHeadIcon != PrayerData.PrayerHeadIcon.RANGE)
								hit = misc.randomDouble(96);
							jadRangeAttackEvent.stop();
                            p.setLastAttacked(Environment.TickCount);
                            npc.setLastAttack(Environment.TickCount);
							p.setAttacker(npc);
							if (hit > p.getHp()) {
								hit = p.getHp();
							}
							if (!Location.inFightCave(p.getLocation()) || p.getTeleportTo() != null) {
								return;
							}
							if ((p.getCombatTurns() > 2 || p.getCombatTurns() < 0)) {
								p.setLastAnimation(new Animation(p.getDefenceAnimation()));
							}
							p.hit(hit);
                            Event animationEvent = new Event(100);
                            animationEvent.setAction(() => {
								animationEvent.stop();
								p.setLastGraphics(new Graphics(157, 0, 100));
							});
                            Server.registerEvent(animationEvent);
						}
				    });
                    Server.registerEvent(jadRangeAttackEvent);
				    break;
	
			    case 1: // Magic
				    npc.setLastGraphics(new Graphics(1626));
                    Event jadMagicAttackEvent = new Event(300);
                    int jadMagicAttackStatus = 0;
                    jadMagicAttackEvent.setAction(() => {
					    double hit = 0;
						PrayerData.PrayerHeadIcon prayerHeadIcon = p.getPrayers().getHeadIcon();
						npc.setLastAnimation(new Animation(9278));
                        if (jadMagicAttackStatus == 0)
                        {
                            jadMagicAttackStatus++;
							jadMagicAttackEvent.setTick(1600);
							p.getPackets().sendProjectile(npc.getLocation(), p.getLocation(), 32, 1627, 50, 40, 34, 90, p);
						} else {
							jadMagicAttackEvent.stop();
                            if (prayerHeadIcon == PrayerData.PrayerHeadIcon.MAGIC)
                            {
								hit = 0;
							} else {
								hit = misc.randomDouble(96);
							}
                            p.setLastAttacked(Environment.TickCount);
                            npc.setLastAttack(Environment.TickCount);
							p.setAttacker(npc);
							if (hit > p.getHp()) {
								hit = p.getHp();
							}
							if (!Location.inFightCave(p.getLocation()) || p.getTeleportTo() != null) {
								return;
							}
							if ((p.getCombatTurns() > 2 || p.getCombatTurns() < 0)) {
								p.setLastAnimation(new Animation(p.getDefenceAnimation()));
							}
							p.hit(hit);
                            Event animationEvent = new Event(100);
                            animationEvent.setAction(() => {
								animationEvent.stop();
								p.setLastGraphics(new Graphics(157, 0, 100));
							});
                            Server.registerEvent(animationEvent);
						}
				    });
                    Server.registerEvent(jadMagicAttackEvent);
				    break;
		    }
	    }