package javastory.channel.client;
import java.io.Serializable;
import java.lang.ref.WeakReference;
import java.util.Map;
import javastory.channel.ChannelCharacter;
import javastory.game.Equip;
import javastory.game.GameConstants;
import javastory.game.Item;
import javastory.game.Jobs;
import javastory.game.PlayerStats;
import javastory.game.Skills;
import javastory.game.WeaponType;
import javastory.game.data.ItemInfoProvider;
import javastory.game.data.SkillInfoProvider;
public class ActivePlayerStats extends PlayerStats implements Serializable {
private static final long serialVersionUID = -679541993413738569L;
private transient WeakReference<ChannelCharacter> character;
private transient float shouldHealHP, shouldHealMP;
private transient short passive_sharpeye_percent, passive_sharpeye_rate;
private transient int localmaxhp, localmaxmp, localSTR, localDEX, localLUK, localint_;
private transient int magic, watk, hands, accuracy;
private transient float speedMod, jumpMod, localmaxbasedamage;
// Elemental properties
public transient int element_amp_percent;
public transient int def, element_ice, element_fire, element_light, element_psn;
public ActivePlayerStats(final ChannelCharacter chr) {
// TODO, move str/dex/int etc here -_-
this.character = new WeakReference<>(chr);
}
public final void init() {
this.relocHeal();
this.recalcLocalStats();
}
public final void setStr(final int str) {
this.STR = str;
this.recalcLocalStats();
}
public final void setDex(final int dex) {
this.DEX = dex;
this.recalcLocalStats();
}
public final void setLuk(final int luk) {
this.LUK = luk;
this.recalcLocalStats();
}
public final void setInt(final int int_) {
this.INT = int_;
this.recalcLocalStats();
}
public final boolean setHp(final int newhp) {
return this.setHp(newhp, false);
}
public final boolean setHp(final int newhp, final boolean silent) {
final int oldHp = this.HP;
int thp = newhp;
if (thp < 0) {
thp = 0;
}
if (thp > this.localmaxhp) {
thp = this.localmaxhp;
}
this.HP = thp;
final ChannelCharacter chra = this.character.get();
if (chra != null) {
if (!silent) {
chra.updatePartyMemberHP();
}
if (oldHp > this.HP && !chra.isAlive()) {
chra.playerDead();
}
}
return this.HP != oldHp;
}
public final boolean setMp(final int newmp) {
final int oldMp = this.MP;
int tmp = newmp;
if (tmp < 0) {
tmp = 0;
}
if (tmp > this.localmaxmp) {
tmp = this.localmaxmp;
}
this.MP = tmp;
return this.MP != oldMp;
}
public final void setMaxHp(final int hp) {
this.MaxHP = hp;
this.recalcLocalStats();
}
public final void setMaxMp(final int mp) {
this.MaxMP = mp;
this.recalcLocalStats();
}
public final int getTotalDex() {
return this.localDEX;
}
public final int getTotalInt() {
return this.localint_;
}
public final int getTotalStr() {
return this.localSTR;
}
public final int getTotalLuk() {
return this.localLUK;
}
public final int getTotalMagic() {
return this.magic;
}
public final double getSpeedMod() {
return this.speedMod;
}
public final double getJumpMod() {
return this.jumpMod;
}
public final int getTotalWatk() {
return this.watk;
}
public final int getCurrentMaxHp() {
return this.localmaxhp;
}
public final int getCurrentMaxMp() {
return this.localmaxmp;
}
public final int getHands() {
return this.hands;
}
public final float getCurrentMaxBaseDamage() {
return this.localmaxbasedamage;
}
public void recalcLocalStats() {
final ChannelCharacter chra = this.character.get();
if (chra == null) {
return;
}
final int oldmaxhp = this.localmaxhp;
this.localmaxhp = this.getMaxHp();
this.localmaxmp = this.getMaxMp();
this.localDEX = this.getDex();
this.localint_ = this.getInt();
this.localSTR = this.getStr();
this.localLUK = this.getLuk();
int speed = 100;
int jump = 100;
this.magic = this.localint_;
this.watk = 0;
for (final Item item : chra.getEquippedItemsInventory()) {
final Equip equip = (Equip) item;
if (equip.getPosition() == -11) {
if (GameConstants.isMagicWeapon(equip.getItemId())) {
final Map<String, Integer> eqstat = ItemInfoProvider.getInstance().getEquipStats(equip.getItemId());
this.element_fire = eqstat.get("incRMAF");
this.element_ice = eqstat.get("incRMAI");
this.element_light = eqstat.get("incRMAL");
this.element_psn = eqstat.get("incRMAS");
this.def = eqstat.get("elemDefault");
} else {
this.element_fire = 100;
this.element_ice = 100;
this.element_light = 100;
this.element_psn = 100;
this.def = 100;
}
}
this.accuracy += equip.getAcc();
this.localmaxhp += equip.getHp();
this.localmaxmp += equip.getMp();
this.localDEX += equip.getDex();
this.localint_ += equip.getInt();
this.localSTR += equip.getStr();
this.localLUK += equip.getLuk();
this.magic += equip.getMatk() + equip.getInt();
this.watk += equip.getWatk();
speed += equip.getSpeed();
jump += equip.getJump();
}
Integer buff = chra.getBuffedValue(BuffStat.MAPLE_WARRIOR);
if (buff != null) {
final double d = buff.doubleValue() / 100;
this.localSTR += d * this.localSTR;
this.localDEX += d * this.localDEX;
this.localLUK += d * this.localLUK;
final int before = this.localint_;
this.localint_ += d * this.localint_;
this.magic += this.localint_ - before;
}
buff = chra.getBuffedValue(BuffStat.ECHO_OF_HERO);
if (buff != null) {
final double d = buff.doubleValue() / 100;
this.watk += this.watk / 100 * d;
this.magic += this.magic / 100 * d;
}
buff = chra.getBuffedValue(BuffStat.ARAN_COMBO);
if (buff != null) {
this.watk += buff / 10;
}
buff = chra.getBuffedValue(BuffStat.MAXHP);
if (buff != null) {
this.localmaxhp += buff.doubleValue() / 100 * this.localmaxhp;
}
buff = chra.getBuffedValue(BuffStat.MAXMP);
if (buff != null) {
this.localmaxmp += buff.doubleValue() / 100 * this.localmaxmp;
}
this.element_amp_percent = 100;
switch (chra.getJobId()) {
case 322: { // Crossbowman
final ISkill expert = SkillInfoProvider.getSkill(3220004);
final int boostLevel = chra.getCurrentSkillLevel(expert);
if (boostLevel > 0) {
this.watk += expert.getEffect(boostLevel).getX();
}
break;
}
case 312: { // Bowmaster
final ISkill expert = SkillInfoProvider.getSkill(3120005);
final int boostLevel = chra.getCurrentSkillLevel(expert);
if (boostLevel > 0) {
this.watk += expert.getEffect(boostLevel).getX();
}
break;
}
case 211:
case 212: { // IL
final ISkill amp = SkillInfoProvider.getSkill(2110001);
final int level = chra.getCurrentSkillLevel(amp);
if (level > 0) {
this.element_amp_percent = amp.getEffect(level).getY();
}
break;
}
case 221:
case 222: { // IL
final ISkill amp = SkillInfoProvider.getSkill(2210001);
final int level = chra.getCurrentSkillLevel(amp);
if (level > 0) {
this.element_amp_percent = amp.getEffect(level).getY();
}
break;
}
case 1211:
case 1212: { // flame
final ISkill amp = SkillInfoProvider.getSkill(12110001);
final int level = chra.getCurrentSkillLevel(amp);
if (level > 0) {
this.element_amp_percent = amp.getEffect(level).getY();
}
break;
}
case 2215:
case 2216:
case 2217:
case 2218: {
final ISkill amp = SkillInfoProvider.getSkill(22150000);
final int level = chra.getCurrentSkillLevel(amp);
if (level > 0) {
this.element_amp_percent = amp.getEffect(level).getY();
}
break;
}
case 2112: { // Aran
final ISkill expert = SkillInfoProvider.getSkill(21120001);
final int boostLevel = chra.getCurrentSkillLevel(expert);
if (boostLevel > 0) {
this.watk += expert.getEffect(boostLevel).getX();
}
break;
}
}
final ISkill blessoffairy = SkillInfoProvider.getSkill(Skills.getBlessOfFairyForJob(chra.getJobId()));
final int boflevel = chra.getCurrentSkillLevel(blessoffairy);
if (boflevel > 0) {
this.watk += blessoffairy.getEffect(boflevel).getX();
this.magic += blessoffairy.getEffect(boflevel).getY();
}
// switch (chra.getJob() / 100) {
// case 1:
// break;
// }
buff = chra.getBuffedValue(BuffStat.ACC);
if (buff != null) {
this.accuracy += buff.intValue();
}
buff = chra.getBuffedValue(BuffStat.WATK);
if (buff != null) {
this.watk += buff.intValue();
}
buff = chra.getBuffedValue(BuffStat.MATK);
if (buff != null) {
this.magic += buff.intValue();
}
buff = chra.getBuffedValue(BuffStat.SPEED);
if (buff != null) {
speed += buff.intValue();
}
buff = chra.getBuffedValue(BuffStat.JUMP);
if (buff != null) {
jump += buff.intValue();
}
buff = chra.getBuffedValue(BuffStat.DASH_SPEED);
if (buff != null) {
speed += buff.intValue();
}
buff = chra.getBuffedValue(BuffStat.DASH_JUMP);
if (buff != null) {
jump += buff.intValue();
}
if (speed > 140) {
speed = 140;
}
if (jump > 123) {
jump = 123;
}
this.speedMod = speed / 100.0f;
this.jumpMod = jump / 100.0f;
final Integer mount = chra.getBuffedValue(BuffStat.MONSTER_RIDING);
if (mount != null) {
this.jumpMod = 1.23f;
switch (mount.intValue()) {
case 1:
this.speedMod = 1.5f;
break;
case 2:
this.speedMod = 1.7f;
break;
case 3:
this.speedMod = 1.8f;
break;
default:
System.err.println("Unhandeled monster riding level, Speedmod = " + this.speedMod + "");
}
}
this.hands = this.localDEX + this.localint_ + this.localLUK;
this.magic = Math.min(this.magic, ChannelCharacter.magicCap);
this.localmaxhp = Math.min(30000, this.localmaxhp);
this.localmaxmp = Math.min(30000, this.localmaxmp);
this.CalcPassive_SharpEye(chra);
this.localmaxbasedamage = this.calculateMaxBaseDamage(this.watk);
if (oldmaxhp != 0 && oldmaxhp != this.localmaxhp) {
chra.updatePartyMemberHP();
}
}
private void CalcPassive_SharpEye(final ChannelCharacter player) {
switch (player.getJobId()) { // Apply passive Critical bonus
case 410:
case 411:
case 412: { // Assasin/ Hermit / NL
final ISkill critSkill = SkillInfoProvider.getSkill(4100001);
final int critlevel = player.getCurrentSkillLevel(critSkill);
if (critlevel > 0) {
this.passive_sharpeye_percent = (short) (critSkill.getEffect(critlevel).getDamage() - 100);
this.passive_sharpeye_rate = critSkill.getEffect(critlevel).getProb();
return;
}
break;
}
case 1410:
case 1411:
case 1412: { // Night Walker
final ISkill critSkill = SkillInfoProvider.getSkill(14100001);
final int critlevel = player.getCurrentSkillLevel(critSkill);
if (critlevel > 0) {
this.passive_sharpeye_percent = (short) (critSkill.getEffect(critlevel).getDamage() - 100);
this.passive_sharpeye_rate = critSkill.getEffect(critlevel).getProb();
return;
}
break;
}
case 511:
case 512: { // Buccaner, Viper
final ISkill critSkill = SkillInfoProvider.getSkill(5110000);
final int critlevel = player.getCurrentSkillLevel(critSkill);
if (critlevel > 0) {
this.passive_sharpeye_percent = (short) (critSkill.getEffect(critlevel).getDamage() - 100);
this.passive_sharpeye_rate = critSkill.getEffect(critlevel).getProb();
return;
}
break;
}
case 1511:
case 1512: {
final ISkill critSkill = SkillInfoProvider.getSkill(15110000);
final int critlevel = player.getCurrentSkillLevel(critSkill);
if (critlevel > 0) {
this.passive_sharpeye_percent = (short) (critSkill.getEffect(critlevel).getDamage() - 100);
this.passive_sharpeye_rate = critSkill.getEffect(critlevel).getProb();
return;
}
break;
}
case 2111:
case 2112: {
// Aran, TODO : only applies when there's > 10 combo
final ISkill critSkill = SkillInfoProvider.getSkill(21110000);
final int critlevel = player.getCurrentSkillLevel(critSkill);
if (critlevel > 0) {
this.passive_sharpeye_percent = critSkill.getEffect(critlevel).getDamage();
this.passive_sharpeye_rate = critSkill.getEffect(critlevel).getProb();
return;
}
break;
}
case 300:
case 310:
case 311:
case 312:
case 320:
case 321:
case 322: { // Bowman
final ISkill critSkill = SkillInfoProvider.getSkill(3000001);
final int critlevel = player.getCurrentSkillLevel(critSkill);
if (critlevel > 0) {
this.passive_sharpeye_percent = (short) (critSkill.getEffect(critlevel).getDamage() - 100);
this.passive_sharpeye_rate = critSkill.getEffect(critlevel).getProb();
return;
}
break;
}
case 1300:
case 1310:
case 1311:
case 1312: { // Bowman
final ISkill critSkill = SkillInfoProvider.getSkill(13000000);
final int critlevel = player.getCurrentSkillLevel(critSkill);
if (critlevel > 0) {
this.passive_sharpeye_percent = (short) (critSkill.getEffect(critlevel).getDamage() - 100);
this.passive_sharpeye_rate = critSkill.getEffect(critlevel).getProb();
return;
}
break;
}
case 2214:
case 2215:
case 2216:
case 2217:
case 2218: { // Evan
final ISkill critSkill = SkillInfoProvider.getSkill(22140000);
final int critlevel = player.getCurrentSkillLevel(critSkill);
if (critlevel > 0) {
this.passive_sharpeye_percent = (short) (critSkill.getEffect(critlevel).getDamage() - 100);
this.passive_sharpeye_rate = critSkill.getEffect(critlevel).getProb();
return;
}
break;
}
}
this.passive_sharpeye_percent = 0;
this.passive_sharpeye_rate = 0;
}
public final short passive_sharpeye_percent() {
return this.passive_sharpeye_percent;
}
public final short passive_sharpeye_rate() {
return this.passive_sharpeye_rate;
}
public final float calculateMaxBaseDamage(final int watk) {
final ChannelCharacter chra = this.character.get();
if (chra == null) {
return 0;
}
float maxBaseDamage;
if (watk == 0) {
maxBaseDamage = 1;
} else {
final Item weapon_item = chra.getEquippedItemsInventory().getItem((byte) -11);
if (weapon_item != null) {
final int job = chra.getJobId();
final WeaponType weapon = GameConstants.getWeaponType(weapon_item.getItemId());
int primary, secondary;
switch (weapon) {
case BOW:
case CROSSBOW:
primary = this.localDEX;
secondary = this.localSTR;
break;
case CLAW:
case DAGGER:
if (job >= 400 && job <= 422 || job >= 1400 && job <= 1412) {
primary = this.localLUK;
secondary = this.localDEX + this.localSTR;
} else { // Non Thieves
primary = this.localSTR;
secondary = this.localDEX;
}
break;
case KNUCKLE:
primary = this.localSTR;
secondary = this.localDEX;
break;
case GUN:
primary = this.localDEX;
secondary = this.localSTR;
break;
case NOT_A_WEAPON:
if (job >= 500 && job <= 522 || job >= 1500 && job <= 1512) {
primary = this.localSTR;
secondary = this.localDEX;
} else {
primary = 0;
secondary = 0;
}
break;
default:
primary = this.localSTR;
secondary = this.localDEX;
break;
}
maxBaseDamage = (weapon.getMaxDamageMultiplier() * primary + secondary) * watk / 100;
} else {
maxBaseDamage = 0;
}
}
return maxBaseDamage;
}
public final float getHealHP() {
return this.shouldHealHP;
}
public final float getHealMP() {
return this.shouldHealMP;
}
public final void relocHeal() {
final ChannelCharacter chra = this.character.get();
if (chra == null) {
return;
}
final int jobId = chra.getJobId();
this.shouldHealHP = 10; // Reset
this.shouldHealMP = 3;
if (Jobs.isJobFamily(200, jobId)) {
// Improving MP recovery
this.shouldHealMP += (float) chra.getCurrentSkillLevel(SkillInfoProvider.getSkill(2000000)) / 10 * chra.getLevel();
} else if (Jobs.isJobFamily(111, jobId)) {
final ISkill effect = SkillInfoProvider.getSkill(1110000);
// Improving MP Recovery
final int lvl = chra.getCurrentSkillLevel(effect);
if (lvl > 0) {
this.shouldHealMP += effect.getEffect(lvl).getMp();
}
} else if (Jobs.isJobFamily(121, jobId)) {
// Improving MP Recovery
final ISkill effect = SkillInfoProvider.getSkill(1210000);
final int lvl = chra.getCurrentSkillLevel(effect);
if (lvl > 0) {
this.shouldHealMP += effect.getEffect(lvl).getMp();
}
} else if (Jobs.isJobFamily(1111, jobId)) {
// Improving MP Recovery
final ISkill effect = SkillInfoProvider.getSkill(11110000);
final int lvl = chra.getCurrentSkillLevel(effect);
if (lvl > 0) {
this.shouldHealMP += effect.getEffect(lvl).getMp();
}
} else if (Jobs.isJobFamily(410, jobId)) {
// Endure
final ISkill effect = SkillInfoProvider.getSkill(4100002);
final int lvl = chra.getCurrentSkillLevel(effect);
if (lvl > 0) {
this.shouldHealHP += effect.getEffect(lvl).getHp();
this.shouldHealMP += effect.getEffect(lvl).getMp();
}
} else if (Jobs.isJobFamily(420, jobId)) {
// Endure
final ISkill effect = SkillInfoProvider.getSkill(4200001);
final int lvl = chra.getCurrentSkillLevel(effect);
if (lvl > 0) {
this.shouldHealHP += effect.getEffect(lvl).getHp();
this.shouldHealMP += effect.getEffect(lvl).getMp();
}
}
if (chra.isGM()) {
this.shouldHealHP += 1000;
this.shouldHealMP += 1000;
}
if (chra.getChair() != 0) {
// Is sitting on a chair.
// Until the values of Chair heal has been fixed,
// MP is different here, if chair data MP = 0, heal + 1.5
this.shouldHealHP += 99;
this.shouldHealMP += 99;
} else {
// Because Heal isn't multipled when there's a chair :)
final float recvRate = chra.getMap().getRecoveryRate();
this.shouldHealHP *= recvRate;
this.shouldHealMP *= recvRate;
}
// To avoid any problem with bathrobe / Sauna >.<
// 1.5
this.shouldHealHP *= 2;
this.shouldHealMP *= 2;
}
}