package com.asteria.game.character.player.skill.action;
import java.util.Optional;
import com.asteria.game.character.player.Player;
import com.asteria.game.character.player.skill.Skills;
import com.asteria.game.item.Item;
import com.asteria.game.location.Position;
import com.asteria.task.Task;
import com.asteria.utility.RandomGen;
import com.google.common.base.Preconditions;
/**
* The skill action that represents an action where items are periodically added
* to and removed from an inventory based on a success factor. This type of
* skill action is more complicated and requires that a player have the items to
* be removed and the space for the items to harvest.
* <p>
* <p>
* The skills that may use this type skill action include, but are not limited
* to {@code FISHING} and {@code WOODCUTTING}.
*
* @author lare96 <http://github.com/lare96>
* @see SkillAction
* @see DestructionSkillAction
* @see ProducingSkillAction
*/
public abstract class HarvestingSkillAction extends SkillAction {
/**
* The factor boost that determines the success rate for harvesting based on
* skill level. The higher the number the less frequently harvest will be
* obtained. A value higher than {@code 99} or lower than {@code 0} will
* throw an {@link IllegalStateException}.
*/
private static final int SUCCESS_FACTOR = 10;
/**
* The random generator instance that will generate random numbers.
*/
private final RandomGen random = new RandomGen();
/**
* Creates a new {@link HarvestingSkillAction}.
*
* @param player
* the player this skill action is for.
* @param position
* the position the player should face.
*/
public HarvestingSkillAction(Player player, Optional<Position> position) {
super(player, position);
}
@Override
public final void execute(Task t) {
Preconditions.checkState(SUCCESS_FACTOR >= 0 && SUCCESS_FACTOR <= 99, "Invalid success factor for harvesting!");
Player player = getPlayer();
int factor = (player.getSkills()[skill().getId()].getLevel() / SUCCESS_FACTOR);
double boost = (factor * 0.01);
if (random.success((successFactor() + boost))) {
Optional<Item[]> removeItems = removeItems();
Item[] harvestItems = harvestItems();
if (removeItems.isPresent()) {
if (!player.getInventory().containsAll(removeItems.get())) {
player.getMessages().sendMessage("You do not have the " + "required items to perform this!");
t.cancel();
return;
}
}
for (Item item : harvestItems) {
if (player.getInventory().add(item)) {
player.getMessages().sendMessage("You get some " + item.getDefinition().getName() + ".");
Skills.experience(player, experience(), skill().getId());
removeItems.ifPresent(player.getInventory()::removeAll);
onHarvest(t, item, true);
} else {
onHarvest(t, item, false);
player.getMessages().sendMessage("You do not have any " + "space left in your inventory!");
t.cancel();
return;
}
}
}
}
@Override
public int delay() {
return 1;
}
/**
* The method executed upon harvest of the items.
*
* @param t
* the task executing this method.
* @param item
* the item being harvested.
* @param success
* determines if the harvest was successful or not.
*/
public void onHarvest(Task t, Item item, boolean success) {
}
/**
* The success factor for the harvest. The higher the number means the more
* frequently harvest will be obtained.
*
* @return the success factor.
*/
public abstract double successFactor();
/**
* The items to be removed upon a successful harvest.
*
* @return the items to be removed.
*/
public abstract Optional<Item[]> removeItems();
/**
* The items to be harvested upon a successful harvest.
*
* @return the items to be harvested.
*/
public abstract Item[] harvestItems();
}