/* * This file is part of aion-unique <aion-unique.org>. * * aion-unique is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * aion-unique is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with aion-unique. If not, see <http://www.gnu.org/licenses/>. */ package com.aionemu.gameserver.controllers; import java.util.Iterator; import java.util.List; import java.util.SortedMap; import java.util.TreeMap; import com.aionemu.commons.utils.Rnd; import com.aionemu.gameserver.controllers.movement.StartMovingListener; import com.aionemu.gameserver.dataholders.DataManager; import com.aionemu.gameserver.model.DescriptionId; import com.aionemu.gameserver.model.gameobjects.Gatherable; import com.aionemu.gameserver.model.gameobjects.player.Player; import com.aionemu.gameserver.model.templates.GatherableTemplate; import com.aionemu.gameserver.model.templates.gather.Material; import com.aionemu.gameserver.network.aion.serverpackets.SM_SYSTEM_MESSAGE; import com.aionemu.gameserver.skillengine.task.GatheringTask; import com.aionemu.gameserver.skillengine.task.SkillTaskFactory; import com.aionemu.gameserver.utils.PacketSendUtility; import com.google.inject.Inject; /** * @author ATracer, sphinx (03/20/2010) * */ public class GatherableController extends VisibleObjectController<Gatherable> { private int gatherCount; private int currentGatherer; private GatheringTask task; @Inject private SkillTaskFactory taskFactory; public enum GatherState { GATHERED, GATHERING, IDLE } private GatherState state = GatherState.IDLE; /** * Start gathering process * * @param player */ public void onStartUse(final Player player) { //basic actions, need to improve here final GatherableTemplate template = this.getOwner().getObjectTemplate(); if(!checkPlayerSkill(player, template)) return; List<Material> materials = template.getMaterials().getMaterial(); int index = 0; Material material = materials.get(index); //default is 0 int count = materials.size(); if(count < 1) { //error - theoretically if XML data is correct, this should never happen. return; } else if(count == 1) { //default is 0 } else { int gatherRate = 1; // 1x rates (probably make config later, if fixed to non-linear statistic probability) float maxrate = 0; int rate = 0; int i = 0; //index counter //sort materials to ascending order SortedMap<Integer, Integer> hasMat = new TreeMap<Integer, Integer>(); for(Material mat : materials) { maxrate += mat.getRate(); //get maxrate hasMat.put(mat.getRate(), i); //sort and save index of materials (key is rate and rate is unique on each gatherId) i++; } Iterator<Integer> it = hasMat.keySet().iterator(); while(it.hasNext()) { rate = it.next(); float percent = Rnd.get() * 100f; float chance = ((rate/maxrate) * 100f * gatherRate); // default index is to 0, look to up little bit on 'material' if(percent < chance) { index = hasMat.get(rate); //return index material = materials.get(index); break; } } } final Material finalMaterial = material; if(state != GatherState.GATHERING) { state = GatherState.GATHERING; currentGatherer = player.getObjectId(); player.getObserveController().attach(new StartMovingListener(){ @Override public void moved() { finishGathering(player); } }); int skillLvlDiff = player.getSkillList().getSkillLevel(template.getHarvestSkill())-template.getSkillLevel(); task = taskFactory.gatheringTask(player, getOwner(), finalMaterial, skillLvlDiff); task.start(); } } /** * Checks whether player have needed skill for gathering and skill level is sufficient * * @param player * @param template * @return */ private boolean checkPlayerSkill(final Player player, final GatherableTemplate template) { int harvestSkillId = template.getHarvestSkill(); //check skill is available if(!player.getSkillList().isSkillPresent(harvestSkillId)) { //TODO send some message ? return false; } if(player.getSkillList().getSkillLevel(harvestSkillId) < template.getSkillLevel()) { //TODO send some message ? return false; } return true; } public void completeInteraction() { state = GatherState.IDLE; gatherCount++; if(gatherCount == getOwner().getObjectTemplate().getHarvestCount()) onDie(); } public void rewardPlayer(Player player) { if(player != null) { int skillLvl = getOwner().getObjectTemplate().getSkillLevel(); int xpReward = (int)((0.008*(skillLvl+100)*(skillLvl+100)+60)*player.getRates().getGatheringXPRate()); if (player.getSkillList().addSkillXp(player, getOwner().getObjectTemplate().getHarvestSkill(), xpReward)) player.getCommonData().addExp(xpReward); else PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.MSG_DONT_GET_PRODUCTION_EXP(new DescriptionId(DataManager.SKILL_DATA.getSkillTemplate(getOwner().getObjectTemplate().getHarvestSkill()).getNameId()))); } } /** * Called by client when some action is performed or on finish gathering * Called by move observer on player move * * @param player */ public void finishGathering(Player player) { if(currentGatherer == player.getObjectId()) { if(state == GatherState.GATHERING) { task.abort(); } currentGatherer = 0; state = GatherState.IDLE; } } private void onDie() { Gatherable owner = getOwner(); sp.getRespawnService().scheduleRespawnTask(owner); sp.getWorld().despawn(owner); } @Override public void onRespawn() { this.gatherCount = 0; } @Override public Gatherable getOwner() { return (Gatherable) super.getOwner(); } }