/*
* Copyright (C) 2004-2014 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.gameserver.model.actor.stat;
import java.util.logging.Logger;
import com.l2jserver.Config;
import com.l2jserver.gameserver.datatables.ExperienceTable;
import com.l2jserver.gameserver.datatables.PetDataTable;
import com.l2jserver.gameserver.instancemanager.ZoneManager;
import com.l2jserver.gameserver.model.actor.L2Playable;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PetInstance;
import com.l2jserver.gameserver.model.events.EventDispatcher;
import com.l2jserver.gameserver.model.events.impl.character.playable.OnPlayableExpChanged;
import com.l2jserver.gameserver.model.events.returns.TerminateReturn;
import com.l2jserver.gameserver.model.zone.ZoneId;
import com.l2jserver.gameserver.model.zone.type.L2SwampZone;
import com.l2jserver.gameserver.network.communityserver.CommunityServerThread;
import com.l2jserver.gameserver.network.communityserver.writepackets.WorldInfo;
public class PlayableStat extends CharStat
{
protected static final Logger _log = Logger.getLogger(PlayableStat.class.getName());
public PlayableStat(L2Playable activeChar)
{
super(activeChar);
}
public boolean addExp(long value)
{
final TerminateReturn term = EventDispatcher.getInstance().notifyEvent(new OnPlayableExpChanged(getActiveChar(), getExp(), getExp() + value), getActiveChar(), TerminateReturn.class);
if ((term != null) && term.terminate())
{
return false;
}
if (((getExp() + value) < 0) || ((value > 0) && (getExp() == (getExpForLevel(getMaxLevel()) - 1))))
{
return true;
}
if ((getExp() + value) >= getExpForLevel(getMaxLevel()))
{
value = getExpForLevel(getMaxLevel()) - 1 - getExp();
}
setExp(getExp() + value);
byte minimumLevel = 1;
if (getActiveChar() instanceof L2PetInstance)
{
// get minimum level from L2NpcTemplate
minimumLevel = (byte) PetDataTable.getInstance().getPetMinLevel(((L2PetInstance) getActiveChar()).getTemplate().getId());
}
byte level = minimumLevel; // minimum level
for (byte tmp = level; tmp <= getMaxLevel(); tmp++)
{
if (getExp() >= getExpForLevel(tmp))
{
continue;
}
level = --tmp;
break;
}
if ((level != getLevel()) && (level >= minimumLevel))
{
addLevel((byte) (level - getLevel()));
}
return true;
}
public boolean removeExp(long value)
{
if ((getExp() - value) < 0)
{
value = getExp() - 1;
}
setExp(getExp() - value);
byte minimumLevel = 1;
if (getActiveChar() instanceof L2PetInstance)
{
// get minimum level from L2NpcTemplate
minimumLevel = (byte) PetDataTable.getInstance().getPetMinLevel(((L2PetInstance) getActiveChar()).getTemplate().getId());
}
byte level = minimumLevel;
for (byte tmp = level; tmp <= getMaxLevel(); tmp++)
{
if (getExp() >= getExpForLevel(tmp))
{
continue;
}
level = --tmp;
break;
}
if ((level != getLevel()) && (level >= minimumLevel))
{
addLevel((byte) (level - getLevel()));
}
return true;
}
public boolean removeExpAndSp(long removeExp, int removeSp)
{
boolean expRemoved = false;
boolean spRemoved = false;
if (removeExp > 0)
{
expRemoved = removeExp(removeExp);
}
if (removeSp > 0)
{
spRemoved = removeSp(removeSp);
}
return expRemoved || spRemoved;
}
public boolean addLevel(byte value)
{
if ((getLevel() + value) > (getMaxLevel() - 1))
{
if (getLevel() < (getMaxLevel() - 1))
{
value = (byte) (getMaxLevel() - 1 - getLevel());
}
else
{
return false;
}
}
boolean levelIncreased = ((getLevel() + value) > getLevel());
value += getLevel();
setLevel(value);
// Sync up exp with current level
if ((getExp() >= getExpForLevel(getLevel() + 1)) || (getExpForLevel(getLevel()) > getExp()))
{
setExp(getExpForLevel(getLevel()));
}
if (!levelIncreased && (getActiveChar() instanceof L2PcInstance) && !((L2PcInstance) (getActiveChar())).isGM() && Config.DECREASE_SKILL_LEVEL)
{
((L2PcInstance) (getActiveChar())).checkPlayerSkills();
}
if (!levelIncreased)
{
return false;
}
getActiveChar().getStatus().setCurrentHp(getActiveChar().getStat().getMaxHp());
getActiveChar().getStatus().setCurrentMp(getActiveChar().getStat().getMaxMp());
if (getActiveChar() instanceof L2PcInstance)
{
CommunityServerThread.getInstance().sendPacket(new WorldInfo((L2PcInstance) getActiveChar(), null, WorldInfo.TYPE_UPDATE_PLAYER_DATA));
}
return true;
}
public boolean addSp(int value)
{
if (value < 0)
{
_log.warning("wrong usage");
return false;
}
int currentSp = getSp();
if (currentSp == Integer.MAX_VALUE)
{
return false;
}
if (currentSp > (Integer.MAX_VALUE - value))
{
value = Integer.MAX_VALUE - currentSp;
}
setSp(currentSp + value);
return true;
}
public boolean removeSp(int value)
{
int currentSp = getSp();
if (currentSp < value)
{
value = currentSp;
}
setSp(getSp() - value);
return true;
}
public long getExpForLevel(int level)
{
return level;
}
@Override
public double getRunSpeed()
{
if (getActiveChar().isInsideZone(ZoneId.SWAMP))
{
final L2SwampZone zone = ZoneManager.getInstance().getZone(getActiveChar(), L2SwampZone.class);
if (zone != null)
{
return super.getRunSpeed() * zone.getMoveBonus();
}
}
return super.getRunSpeed();
}
@Override
public double getWalkSpeed()
{
if (getActiveChar().isInsideZone(ZoneId.SWAMP))
{
final L2SwampZone zone = ZoneManager.getInstance().getZone(getActiveChar(), L2SwampZone.class);
if (zone != null)
{
return super.getWalkSpeed() * zone.getMoveBonus();
}
}
return super.getWalkSpeed();
}
@Override
public L2Playable getActiveChar()
{
return (L2Playable) super.getActiveChar();
}
public int getMaxLevel()
{
return ExperienceTable.getInstance().getMaxLevel();
}
}