package com.asteria.game.character.player.content;
import static com.asteria.game.character.player.skill.Skills.AGILITY;
import static com.asteria.game.character.player.skill.Skills.ATTACK;
import static com.asteria.game.character.player.skill.Skills.DEFENCE;
import static com.asteria.game.character.player.skill.Skills.FISHING;
import static com.asteria.game.character.player.skill.Skills.HITPOINTS;
import static com.asteria.game.character.player.skill.Skills.MAGIC;
import static com.asteria.game.character.player.skill.Skills.PRAYER;
import static com.asteria.game.character.player.skill.Skills.RANGED;
import static com.asteria.game.character.player.skill.Skills.STRENGTH;
import java.util.Optional;
import com.asteria.game.World;
import com.asteria.game.character.Animation;
import com.asteria.game.character.player.Player;
import com.asteria.game.character.player.skill.Skill;
import com.asteria.game.character.player.skill.Skills;
import com.asteria.game.item.Item;
import com.asteria.task.Task;
/**
* The enumerated type managing consumable potion types.
*
* @author Ryley Kimmel <ryley.kimmel@live.com>
* @author lare96 <http://github.com/lare96>
*/
public enum PotionConsumable {
ZAMORAK_BREW(2450, 189, 191, 193) {
@Override
public void onEffect(Player player) {
PotionConsumable.onZamorakEffect(player);
}
},
SARADOMIN_BREW(6685, 6687, 6689, 6691) {
@Override
public void onEffect(Player player) {
PotionConsumable.onSaradominEffect(player);
}
},
ANTIDOTE_PLUS(5943, 5945, 5947, 5949) {
@Override
public void onEffect(Player player) {
PotionConsumable.onAntiPoisonEffect(player, true, 1000);
}
},
ANTIDOTE_PLUS_PLUS(5952, 5954, 5956, 5958) {
@Override
public void onEffect(Player player) {
PotionConsumable.onAntiPoisonEffect(player, true, 1200);
}
},
AGILITY_POTION(3032, 3034, 3036, 3038) {
@Override
public void onEffect(Player player) {
PotionConsumable.onAgilityEffect(player);
}
},
FISHING_POTION(2438, 151, 153, 155) {
@Override
public void onEffect(Player player) {
PotionConsumable.onFishingEffect(player);
}
},
RANGE_POTIONS(2444, 169, 171, 173) {
@Override
public void onEffect(Player player) {
PotionConsumable.onBasicEffect(player, RANGED, BoostType.NORMAL);
}
},
ENERGY_POTIONS(3008, 3010, 3012, 3014) {
@Override
public void onEffect(Player player) {
PotionConsumable.onEnergyEffect(player, false);
}
},
SUPER_ENERGY_POTIONS(3016, 3018, 3020, 3022) {
@Override
public void onEffect(Player player) {
PotionConsumable.onEnergyEffect(player, true);
}
},
MAGIC_POTIONS(3040, 3042, 3044, 3046) {
@Override
public void onEffect(Player player) {
PotionConsumable.onBasicEffect(player, MAGIC, BoostType.NORMAL);
}
},
DEFENCE_POTIONS(2432, 133, 135, 137) {
@Override
public void onEffect(Player player) {
PotionConsumable.onBasicEffect(player, DEFENCE, BoostType.NORMAL);
}
},
STRENGTH_POTIONS(113, 115, 117, 119) {
@Override
public void onEffect(Player player) {
PotionConsumable.onBasicEffect(player, STRENGTH, BoostType.NORMAL);
}
},
ATTACK_POTIONS(2428, 121, 123, 125) {
@Override
public void onEffect(Player player) {
PotionConsumable.onBasicEffect(player, ATTACK, BoostType.NORMAL);
}
},
SUPER_DEFENCE_POTIONS(2442, 163, 165, 167) {
@Override
public void onEffect(Player player) {
PotionConsumable.onBasicEffect(player, DEFENCE, BoostType.SUPER);
}
},
SUPER_ATTACK_POTIONS(2436, 145, 147, 149) {
@Override
public void onEffect(Player player) {
PotionConsumable.onBasicEffect(player, ATTACK, BoostType.SUPER);
}
},
SUPER_STRENGTH_POTIONS(2440, 157, 159, 161) {
@Override
public void onEffect(Player player) {
PotionConsumable.onBasicEffect(player, STRENGTH, BoostType.SUPER);
}
},
SUPER_RESTORE_POTIONS(3024, 3026, 3028, 3030) {
@Override
public void onEffect(Player player) {
PotionConsumable.onPrayerEffect(player, true);
}
},
PRAYER_POTIONS(2434, 139, 141, 143) {
@Override
public void onEffect(Player player) {
PotionConsumable.onPrayerEffect(player, false);
}
},
ANTI_FIRE_POTIONS(2452, 2454, 2456, 2458) {
@Override
public void onEffect(Player player) {
PotionConsumable.onAntiFireEffect(player);
}
},
ANTIPOISON_POTIONS(2446, 175, 177, 179) {
@Override
public void onEffect(Player player) {
PotionConsumable.onAntiPoisonEffect(player, false, 0);
}
},
SUPER_ANTIPOISON_POTIONS(2448, 181, 183, 185) {
@Override
public void onEffect(Player player) {
PotionConsumable.onAntiPoisonEffect(player, true, 500);
}
};
/**
* The default item representing the final potion dose.
*/
private static final Item VIAL = new Item(229);
/**
* The identifiers which represent this potion type.
*/
private final int[] ids;
/**
* Create a new {@link PotionConsumable}.
*
* @param ids
* the identifiers which represent this potion type.
*/
private PotionConsumable(int... ids) {
this.ids = ids;
}
/**
* Attempts to consume {@code item} in {@code slot} for {@code player}.
*
* @param player
* the player attempting to consume the item.
* @param item
* the item being consumed by the player.
* @param slot
* the slot the player is consuming from.
* @return {@code true} if the item was consumed, {@code false} otherwise.
*/
public static boolean consume(Player player, Item item, int slot) {
Optional<PotionConsumable> potion = forId(item.getId());
// TODO: Check duel rule for no potions.
if (!potion.isPresent() || player.isDead() || !player.getPotionTimer().elapsed(1200))
return false;
player.animation(new Animation(829));
player.getPotionTimer().reset();
player.getInventory().remove(item, slot);
player.getInventory().add(getReplacementItem(item));
potion.get().onEffect(player);
return true;
}
/**
* The method that executes the fishing potion action.
*
* @param player
* the player to do this action for.
*/
private static void onFishingEffect(Player player) {
Skill fishing = player.getSkills()[FISHING];
fishing.increaseLevelReal(3);
Skills.refresh(player, FISHING);
}
/**
* The method that executes the agility potion action.
*
* @param player
* the player to do this action for.
*/
private static void onAgilityEffect(Player player) {
Skill agility = player.getSkills()[AGILITY];
agility.increaseLevelReal(3);
Skills.refresh(player, AGILITY);
}
/**
* The method that executes the Saradomin brew action.
*
* @param player
* the player to do this action for.
*/
private static void onSaradominEffect(Player player) {
Skill attack = player.getSkills()[ATTACK];
Skill strength = player.getSkills()[STRENGTH];
Skill defence = player.getSkills()[DEFENCE];
Skill hp = player.getSkills()[HITPOINTS];
Skill ranged = player.getSkills()[RANGED];
Skill magic = player.getSkills()[MAGIC];
defence.increaseLevelReal((int) Math.floor(2 + (0.20 * defence.getRealLevel())));
hp.increaseLevelReal((int) Math.floor(2 + (0.15 * hp.getRealLevel())));
attack.decreaseLevelReal((int) Math.floor(0.10 * attack.getRealLevel()));
strength.decreaseLevelReal((int) Math.floor(0.10 * strength.getRealLevel()));
magic.decreaseLevelReal((int) Math.floor(0.10 * magic.getRealLevel()));
ranged.decreaseLevelReal((int) Math.floor(0.10 * ranged.getRealLevel()));
Skills.refresh(player, ATTACK, STRENGTH, DEFENCE, HITPOINTS, RANGED, MAGIC);
}
/**
* The method that executes the Zamorak brew action.
*
* @param player
* the player to do this action for.
*/
private static void onZamorakEffect(Player player) {
Skill attack = player.getSkills()[ATTACK];
Skill strength = player.getSkills()[STRENGTH];
Skill defence = player.getSkills()[DEFENCE];
Skill hp = player.getSkills()[HITPOINTS];
Skill prayer = player.getSkills()[PRAYER];
attack.increaseLevelReal((int) Math.floor(2 + (0.20 * attack.getRealLevel())));
strength.increaseLevelReal((int) Math.floor(2 + (0.12 * strength.getRealLevel())));
defence.decreaseLevelReal((int) Math.floor(2 + (0.10 * defence.getRealLevel())));
hp.decreaseLevelReal((int) Math.floor(2 + (0.10 * hp.getRealLevel())));
prayer.increaseLevel((int) Math.floor(0.10 * prayer.getRealLevel()), prayer.getRealLevel());
Skills.refresh(player, ATTACK, STRENGTH, DEFENCE, HITPOINTS, PRAYER);
}
/**
* The method that executes the prayer potion action.
*
* @param player
* the player to do this action for.
* @param restorePotion
* {@code true} if this potion is a restore potion, {@code false}
* otherwise.
*/
private static void onPrayerEffect(Player player, boolean restorePotion) {
Skill skill = player.getSkills()[PRAYER];
int realLevel = skill.getRealLevel();
skill.increaseLevel((int) Math.floor(7 + (realLevel / 4)), realLevel);
if (restorePotion) {
skill.increaseLevel(1, realLevel);
onRestoreEffect(player);
}
Skills.refresh(player, PRAYER);
}
/**
* The method that executes the anti-poison potion action.
*
* @param player
* the player to do this action for.
* @param superPotion
* {@code true} if this potion is a super potion, {@code false}
* otherwise.
* @param length
* the length that the effect lingers for.
*/
private static void onAntiPoisonEffect(Player player, boolean superPotion, int length) {
if (player.isPoisoned()) {
player.getPoisonDamage().set(0);
player.getMessages().sendMessage("You have been cured of your poison!");
}
if (superPotion) {
if (player.getPoisonImmunity().get() <= 0) {
player.getMessages().sendMessage("You have been granted immunity against poison.");
player.getPoisonImmunity().incrementAndGet(length);
System.out.println(player.getPoisonImmunity().get());
World.submit(new Task(50, false) {
@Override
public void execute() {
if (player.getPoisonImmunity().get() <= 0)
this.cancel();
if (player.getPoisonImmunity().decrementAndGet(50) <= 50)
player.getMessages().sendMessage("Your resistance to poison is about to wear off!");
if (player.getPoisonImmunity().get() <= 0)
this.cancel();
}
@Override
public void onCancel() {
player.getMessages().sendMessage("Your resistance to poison has worn off!");
player.getPoisonImmunity().set(0);
}
}.attach(player));
} else if (player.getPoisonImmunity().get() > 0) {
player.getMessages().sendMessage("Your immunity against poison has been restored!");
player.getPoisonImmunity().set(length);
}
}
}
/**
* The method that executes the energy potion action.
*
* @param player
* the player to do this action for.
* @param superPotion
* {@code true} if this potion is a super potion, {@code false}
* otherwise.
*/
private static void onEnergyEffect(Player player, boolean superPotion) {
int amount = superPotion ? 100 : 50;
player.getRunEnergy().incrementAndGet(amount, 100);
player.getMessages().sendString(player.getRunEnergy() + "%", 149);
}
/**
* The method that executes the restore potion action.
*
* @param player
* the player to do this action for.
*/
private static void onRestoreEffect(Player player) {
for (int index = 0; index <= 6; index++) {
if ((index == PRAYER) || (index == HITPOINTS)) {
continue;
}
Skill skill = player.getSkills()[index];
int realLevel = skill.getRealLevel();
skill.increaseLevel((int) Math.floor(8 + (realLevel / 4)), realLevel);
Skills.refresh(player, index);
}
}
/**
* The method that executes the anti-fire potion action.
*
* @param player
* the player to do this action for.
*/
private static void onAntiFireEffect(Player player) {
int count = player.getFireImmunity().get();
player.getMessages().sendMessage(
count <= 0 ? "You have been granted " + "immunity against dragon fire."
: "Your immunity against " + "dragon fire has been restored.");
if (count <= 0) {
World.submit(new Task(30, false) {
@Override
public void execute() {
player.getFireImmunity().decrementAndGet(30);
if (player.getFireImmunity().get() == 30) {
player.getMessages().sendMessage("Your resistance to " + "dragon fire is about to wear off!");
} else if (player.getFireImmunity().get() <= 0) {
this.cancel();
}
}
@Override
public void onCancel() {
player.getMessages().sendMessage("Your resistance to " + "dragon fire has worn off!");
player.getFireImmunity().set(0);
}
}.attach(player));
}
player.getFireImmunity().set(360);
}
/**
* The method that executes the basic effect potion action that will
* increment the level of {@code skill}.
*
* @param player
* the player to do this action for.
*/
private static void onBasicEffect(Player player, int skill, BoostType type) {
Skill s = player.getSkills()[skill];
int realLevel = s.getRealLevel();
int boostLevel = Math.round(realLevel * type.getAmount());
int cap = realLevel + boostLevel;
if (type == BoostType.NORMAL) {
boostLevel += 1;
}
if ((s.getLevel() + boostLevel) > (realLevel + boostLevel + 1)) {
boostLevel = (realLevel + boostLevel) - s.getLevel();
}
s.increaseLevel(boostLevel, cap);
Skills.refresh(player, skill);
}
/**
* Retrieves the replacement item for {@code item}.
*
* @param item
* the item to retrieve the replacement item for.
* @return the replacement item wrapped in an optional, or an empty optional
* if no replacement item is available.
*/
private static Item getReplacementItem(Item item) {
Optional<PotionConsumable> potion = forId(item.getId());
if (potion.isPresent()) {
int length = potion.get().getIds().length;
for (int index = 0; index < length; index++) {
if (potion.get().getIds()[index] == item.getId() && index + 1 < length) {
return new Item(potion.get().getIds()[index + 1]);
}
}
}
return VIAL;
}
/**
* Retrieves the potion consumable element for {@code id}.
*
* @param id
* the id that the potion consumable is attached to.
* @return the potion consumable wrapped in an optional, or an empty
* optional if no potion consumable was found.
*/
private static Optional<PotionConsumable> forId(int id) {
for (PotionConsumable potion : PotionConsumable.values()) {
for (int potionId : potion.getIds()) {
if (id == potionId) {
return Optional.of(potion);
}
}
}
return Optional.empty();
}
/**
* The method executed when this potion type activated.
*
* @param player
* the player to execute this effect for.
*/
public abstract void onEffect(Player player);
/**
* Gets the identifiers which represent this potion type.
*
* @return the identifiers for this potion.
*/
public final int[] getIds() {
return ids;
}
/**
* The enumerated type whose elements represent the boost types for potions.
*
* @author Ryley Kimmel <ryley.kimmel@live.com>
* @author lare96 <http://github.com/lare96>
*/
private enum BoostType {
NORMAL(.13F),
SUPER(.20F);
/**
* The amount this type will boost by.
*/
private final float amount;
/**
* Creates a new {@link BoostType}.
*
* @param boostAmount
* the amount this type will boost by.
*/
private BoostType(float boostAmount) {
this.amount = boostAmount;
}
/**
* Gets the amount this type will boost by.
*
* @return the boost amount.
*/
public final float getAmount() {
return amount;
}
}
}