Fixed Seal skill not working for Blaze Wizard. Added a check against Seal skill on bosses. Reviewed improper usage of "random spawn point arrival" at several warps on scripts. Refactored CPQ modules fetching players from the channel storage, this should be unneeded after a recent update on the player object from MPC. Added door objects as a visible map object for the player server-side view component. Fixed a few scenarios where mobs would unexpectedly show up impervious to mob status. Fixed scenario where a player wouldn't receive disease informations from other players after changing maps. Fixed some magic-type skills (such as Magic Claw or Freeze) not displaying damage value for other players when the player is within melee-range from the mob. Added check for whether a given quest is scripted before trying to find the script. Fixed registering items onto MTS leading to loss of a few of its properties (expiration, item level, etc). Fixed "Improved MaxHP" skill gains not working for Thunderbreakers. Refactored pet autopot to also apply on HP/MP consumption by items/skills. Added portal sound effect on Mystic Doors.
407 lines
16 KiB
Java
407 lines
16 KiB
Java
/*
|
|
This file is part of the OdinMS Maple Story Server
|
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
|
Matthias Butz <matze@odinms.de>
|
|
Jan Christian Meyer <vimes@odinms.de>
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Affero General Public License as
|
|
published by the Free Software Foundation version 3 as published by
|
|
the Free Software Foundation. You may not use, modify or distribute
|
|
this program under any other version of the GNU Affero General Public
|
|
License.
|
|
|
|
This program 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 Affero General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
package client;
|
|
|
|
import constants.skills.Aran;
|
|
import constants.skills.Archer;
|
|
import constants.skills.Assassin;
|
|
import constants.skills.Bandit;
|
|
import constants.skills.Beginner;
|
|
import constants.skills.Bishop;
|
|
import constants.skills.BlazeWizard;
|
|
import constants.skills.Bowmaster;
|
|
import constants.skills.Buccaneer;
|
|
import constants.skills.ChiefBandit;
|
|
import constants.skills.Cleric;
|
|
import constants.skills.Corsair;
|
|
import constants.skills.Crossbowman;
|
|
import constants.skills.Crusader;
|
|
import constants.skills.DarkKnight;
|
|
import constants.skills.DawnWarrior;
|
|
import constants.skills.DragonKnight;
|
|
import constants.skills.Evan;
|
|
import constants.skills.FPArchMage;
|
|
import constants.skills.FPMage;
|
|
import constants.skills.FPWizard;
|
|
import constants.skills.Fighter;
|
|
import constants.skills.GM;
|
|
import constants.skills.Gunslinger;
|
|
import constants.skills.Hermit;
|
|
import constants.skills.Hero;
|
|
import constants.skills.Hunter;
|
|
import constants.skills.ILArchMage;
|
|
import constants.skills.ILMage;
|
|
import constants.skills.ILWizard;
|
|
import constants.skills.Legend;
|
|
import constants.skills.Magician;
|
|
import constants.skills.Marauder;
|
|
import constants.skills.Marksman;
|
|
import constants.skills.NightLord;
|
|
import constants.skills.NightWalker;
|
|
import constants.skills.Noblesse;
|
|
import constants.skills.Page;
|
|
import constants.skills.Paladin;
|
|
import constants.skills.Pirate;
|
|
import constants.skills.Priest;
|
|
import constants.skills.Ranger;
|
|
import constants.skills.Rogue;
|
|
import constants.skills.Shadower;
|
|
import constants.skills.Sniper;
|
|
import constants.skills.Spearman;
|
|
import constants.skills.SuperGM;
|
|
import constants.skills.Warrior;
|
|
import constants.skills.ThunderBreaker;
|
|
import constants.skills.WhiteKnight;
|
|
import constants.skills.WindArcher;
|
|
|
|
import java.io.File;
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
|
|
import provider.MapleData;
|
|
import provider.MapleDataDirectoryEntry;
|
|
import provider.MapleDataFileEntry;
|
|
import provider.MapleDataProvider;
|
|
import provider.MapleDataProviderFactory;
|
|
import provider.MapleDataTool;
|
|
import server.MapleStatEffect;
|
|
import server.life.Element;
|
|
|
|
public class SkillFactory {
|
|
private static Map<Integer, Skill> skills = new HashMap<>();
|
|
private static MapleDataProvider datasource = MapleDataProviderFactory.getDataProvider(MapleDataProviderFactory.fileInWZPath("Skill.wz"));
|
|
|
|
public static Skill getSkill(int id) {
|
|
if (!skills.isEmpty()) {
|
|
return skills.get(Integer.valueOf(id));
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public static void loadAllSkills() {
|
|
final MapleDataDirectoryEntry root = datasource.getRoot();
|
|
int skillid;
|
|
for (MapleDataFileEntry topDir : root.getFiles()) { // Loop thru jobs
|
|
if (topDir.getName().length() <= 8) {
|
|
for (MapleData data : datasource.getData(topDir.getName())) { // Loop thru each jobs
|
|
if (data.getName().equals("skill")) {
|
|
for (MapleData data2 : data) { // Loop thru each jobs
|
|
if (data2 != null) {
|
|
skillid = Integer.parseInt(data2.getName());
|
|
skills.put(skillid, loadFromData(skillid, data2));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private static Skill loadFromData(int id, MapleData data) {
|
|
Skill ret = new Skill(id);
|
|
boolean isBuff = false;
|
|
int skillType = MapleDataTool.getInt("skillType", data, -1);
|
|
String elem = MapleDataTool.getString("elemAttr", data, null);
|
|
if (elem != null) {
|
|
ret.setElement(Element.getFromChar(elem.charAt(0)));
|
|
} else {
|
|
ret.setElement(Element.NEUTRAL);
|
|
}
|
|
MapleData effect = data.getChildByPath("effect");
|
|
if (skillType != -1) {
|
|
if (skillType == 2) {
|
|
isBuff = true;
|
|
}
|
|
} else {
|
|
MapleData action_ = data.getChildByPath("action");
|
|
boolean action = false;
|
|
if (action_ == null) {
|
|
if (data.getChildByPath("prepare/action") != null) {
|
|
action = true;
|
|
} else {
|
|
switch (id) {
|
|
case Gunslinger.INVISIBLE_SHOT:
|
|
case Corsair.HYPNOTIZE:
|
|
action = true;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
action = true;
|
|
}
|
|
ret.setAction(action);
|
|
MapleData hit = data.getChildByPath("hit");
|
|
MapleData ball = data.getChildByPath("ball");
|
|
isBuff = effect != null && hit == null && ball == null;
|
|
isBuff |= action_ != null && MapleDataTool.getString("0", action_, "").equals("alert2");
|
|
switch (id) {
|
|
case Hero.RUSH:
|
|
case Paladin.RUSH:
|
|
case DarkKnight.RUSH:
|
|
case DragonKnight.SACRIFICE:
|
|
case FPMage.EXPLOSION:
|
|
case FPMage.POISON_MIST:
|
|
case Cleric.HEAL:
|
|
case Ranger.MORTAL_BLOW:
|
|
case Sniper.MORTAL_BLOW:
|
|
case Assassin.DRAIN:
|
|
case Hermit.SHADOW_WEB:
|
|
case Bandit.STEAL:
|
|
case Shadower.SMOKE_SCREEN:
|
|
case SuperGM.HEAL_PLUS_DISPEL:
|
|
case Hero.MONSTER_MAGNET:
|
|
case Paladin.MONSTER_MAGNET:
|
|
case DarkKnight.MONSTER_MAGNET:
|
|
case Evan.ICE_BREATH:
|
|
case Evan.FIRE_BREATH:
|
|
case Gunslinger.RECOIL_SHOT:
|
|
case Marauder.ENERGY_DRAIN:
|
|
case BlazeWizard.FLAME_GEAR:
|
|
case NightWalker.SHADOW_WEB:
|
|
case NightWalker.POISON_BOMB:
|
|
case NightWalker.VAMPIRE:
|
|
case ChiefBandit.CHAKRA:
|
|
case Aran.COMBAT_STEP:
|
|
case Evan.RECOVERY_AURA:
|
|
isBuff = false;
|
|
break;
|
|
case Beginner.RECOVERY:
|
|
case Beginner.NIMBLE_FEET:
|
|
case Beginner.MONSTER_RIDER:
|
|
case Beginner.ECHO_OF_HERO:
|
|
case Beginner.MAP_CHAIR:
|
|
case Warrior.IRON_BODY:
|
|
case Fighter.AXE_BOOSTER:
|
|
case Fighter.POWER_GUARD:
|
|
case Fighter.RAGE:
|
|
case Fighter.SWORD_BOOSTER:
|
|
case Crusader.ARMOR_CRASH:
|
|
case Crusader.COMBO:
|
|
case Hero.ENRAGE:
|
|
case Hero.HEROS_WILL:
|
|
case Hero.MAPLE_WARRIOR:
|
|
case Hero.STANCE:
|
|
case Page.BW_BOOSTER:
|
|
case Page.POWER_GUARD:
|
|
case Page.SWORD_BOOSTER:
|
|
case Page.THREATEN:
|
|
case WhiteKnight.BW_FIRE_CHARGE:
|
|
case WhiteKnight.BW_ICE_CHARGE:
|
|
case WhiteKnight.BW_LIT_CHARGE:
|
|
case WhiteKnight.MAGIC_CRASH:
|
|
case WhiteKnight.SWORD_FIRE_CHARGE:
|
|
case WhiteKnight.SWORD_ICE_CHARGE:
|
|
case WhiteKnight.SWORD_LIT_CHARGE:
|
|
case Paladin.BW_HOLY_CHARGE:
|
|
case Paladin.HEROS_WILL:
|
|
case Paladin.MAPLE_WARRIOR:
|
|
case Paladin.STANCE:
|
|
case Paladin.SWORD_HOLY_CHARGE:
|
|
case Spearman.HYPER_BODY:
|
|
case Spearman.IRON_WILL:
|
|
case Spearman.POLEARM_BOOSTER:
|
|
case Spearman.SPEAR_BOOSTER:
|
|
case DragonKnight.DRAGON_BLOOD:
|
|
case DragonKnight.POWER_CRASH:
|
|
case DarkKnight.AURA_OF_BEHOLDER:
|
|
case DarkKnight.BEHOLDER:
|
|
case DarkKnight.HEROS_WILL:
|
|
case DarkKnight.HEX_OF_BEHOLDER:
|
|
case DarkKnight.MAPLE_WARRIOR:
|
|
case DarkKnight.STANCE:
|
|
case Magician.MAGIC_GUARD:
|
|
case Magician.MAGIC_ARMOR:
|
|
case FPWizard.MEDITATION:
|
|
case FPWizard.SLOW:
|
|
case FPMage.SEAL:
|
|
case FPMage.SPELL_BOOSTER:
|
|
case FPArchMage.HEROS_WILL:
|
|
case FPArchMage.INFINITY:
|
|
case FPArchMage.MANA_REFLECTION:
|
|
case FPArchMage.MAPLE_WARRIOR:
|
|
case ILWizard.MEDITATION:
|
|
case ILMage.SEAL:
|
|
case ILWizard.SLOW:
|
|
case ILMage.SPELL_BOOSTER:
|
|
case ILArchMage.HEROS_WILL:
|
|
case ILArchMage.INFINITY:
|
|
case ILArchMage.MANA_REFLECTION:
|
|
case ILArchMage.MAPLE_WARRIOR:
|
|
case Cleric.INVINCIBLE:
|
|
case Cleric.BLESS:
|
|
case Priest.DISPEL:
|
|
case Priest.DOOM:
|
|
case Priest.HOLY_SYMBOL:
|
|
case Priest.MYSTIC_DOOR:
|
|
case Bishop.HEROS_WILL:
|
|
case Bishop.HOLY_SHIELD:
|
|
case Bishop.INFINITY:
|
|
case Bishop.MANA_REFLECTION:
|
|
case Bishop.MAPLE_WARRIOR:
|
|
case Archer.FOCUS:
|
|
case Hunter.BOW_BOOSTER:
|
|
case Hunter.SOUL_ARROW:
|
|
case Ranger.PUPPET:
|
|
case Bowmaster.CONCENTRATE:
|
|
case Bowmaster.HEROS_WILL:
|
|
case Bowmaster.MAPLE_WARRIOR:
|
|
case Bowmaster.SHARP_EYES:
|
|
case Crossbowman.CROSSBOW_BOOSTER:
|
|
case Crossbowman.SOUL_ARROW:
|
|
case Sniper.PUPPET:
|
|
case Marksman.BLIND:
|
|
case Marksman.HEROS_WILL:
|
|
case Marksman.MAPLE_WARRIOR:
|
|
case Marksman.SHARP_EYES:
|
|
case Rogue.DARK_SIGHT:
|
|
case Assassin.CLAW_BOOSTER:
|
|
case Assassin.HASTE:
|
|
case Hermit.MESO_UP:
|
|
case Hermit.SHADOW_PARTNER:
|
|
case NightLord.HEROS_WILL:
|
|
case NightLord.MAPLE_WARRIOR:
|
|
case NightLord.NINJA_AMBUSH:
|
|
case NightLord.SHADOW_STARS:
|
|
case Bandit.DAGGER_BOOSTER:
|
|
case Bandit.HASTE:
|
|
case ChiefBandit.MESO_GUARD:
|
|
case ChiefBandit.PICKPOCKET:
|
|
case Shadower.HEROS_WILL:
|
|
case Shadower.MAPLE_WARRIOR:
|
|
case Shadower.NINJA_AMBUSH:
|
|
case Pirate.DASH:
|
|
case Marauder.TRANSFORMATION:
|
|
case Buccaneer.SUPER_TRANSFORMATION:
|
|
case Corsair.BATTLE_SHIP:
|
|
case GM.HIDE:
|
|
case SuperGM.HASTE:
|
|
case SuperGM.HOLY_SYMBOL:
|
|
case SuperGM.BLESS:
|
|
case SuperGM.HIDE:
|
|
case SuperGM.HYPER_BODY:
|
|
case Noblesse.BLESSING_OF_THE_FAIRY:
|
|
case Noblesse.ECHO_OF_HERO:
|
|
case Noblesse.MONSTER_RIDER:
|
|
case Noblesse.NIMBLE_FEET:
|
|
case Noblesse.RECOVERY:
|
|
case Noblesse.MAP_CHAIR:
|
|
case DawnWarrior.COMBO:
|
|
case DawnWarrior.FINAL_ATTACK:
|
|
case DawnWarrior.IRON_BODY:
|
|
case DawnWarrior.RAGE:
|
|
case DawnWarrior.SOUL:
|
|
case DawnWarrior.SOUL_CHARGE:
|
|
case DawnWarrior.SWORD_BOOSTER:
|
|
case BlazeWizard.ELEMENTAL_RESET:
|
|
case BlazeWizard.FLAME:
|
|
case BlazeWizard.IFRIT:
|
|
case BlazeWizard.MAGIC_ARMOR:
|
|
case BlazeWizard.MAGIC_GUARD:
|
|
case BlazeWizard.MEDITATION:
|
|
case BlazeWizard.SEAL:
|
|
case BlazeWizard.SLOW:
|
|
case BlazeWizard.SPELL_BOOSTER:
|
|
case WindArcher.BOW_BOOSTER:
|
|
case WindArcher.EAGLE_EYE:
|
|
case WindArcher.FINAL_ATTACK:
|
|
case WindArcher.FOCUS:
|
|
case WindArcher.PUPPET:
|
|
case WindArcher.SOUL_ARROW:
|
|
case WindArcher.STORM:
|
|
case WindArcher.WIND_WALK:
|
|
case NightWalker.CLAW_BOOSTER:
|
|
case NightWalker.DARKNESS:
|
|
case NightWalker.DARK_SIGHT:
|
|
case NightWalker.HASTE:
|
|
case NightWalker.SHADOW_PARTNER:
|
|
case ThunderBreaker.DASH:
|
|
case ThunderBreaker.ENERGY_CHARGE:
|
|
case ThunderBreaker.ENERGY_DRAIN:
|
|
case ThunderBreaker.KNUCKLER_BOOSTER:
|
|
case ThunderBreaker.LIGHTNING:
|
|
case ThunderBreaker.SPARK:
|
|
case ThunderBreaker.LIGHTNING_CHARGE:
|
|
case ThunderBreaker.SPEED_INFUSION:
|
|
case ThunderBreaker.TRANSFORMATION:
|
|
case Legend.BLESSING_OF_THE_FAIRY:
|
|
case Legend.AGILE_BODY:
|
|
case Legend.ECHO_OF_HERO:
|
|
case Legend.RECOVERY:
|
|
case Legend.MONSTER_RIDER:
|
|
case Legend.MAP_CHAIR:
|
|
case Aran.MAPLE_WARRIOR:
|
|
case Aran.HEROS_WILL:
|
|
case Aran.POLEARM_BOOSTER:
|
|
case Aran.COMBO_DRAIN:
|
|
case Aran.SNOW_CHARGE:
|
|
case Aran.BODY_PRESSURE:
|
|
case Aran.SMART_KNOCKBACK:
|
|
case Aran.COMBO_BARRIER:
|
|
case Aran.COMBO_ABILITY:
|
|
case Evan.BLESSING_OF_THE_FAIRY:
|
|
case Evan.RECOVERY:
|
|
case Evan.NIMBLE_FEET:
|
|
case Evan.HEROS_WILL:
|
|
case Evan.ECHO_OF_HERO:
|
|
case Evan.MAGIC_BOOSTER:
|
|
case Evan.MAGIC_GUARD:
|
|
case Evan.ELEMENTAL_RESET:
|
|
case Evan.MAPLE_WARRIOR:
|
|
case Evan.MAGIC_RESISTANCE:
|
|
case Evan.MAGIC_SHIELD:
|
|
case Evan.SLOW:
|
|
isBuff = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (MapleData level : data.getChildByPath("level")) {
|
|
ret.addLevelEffect(MapleStatEffect.loadSkillEffectFromData(level, id, isBuff));
|
|
}
|
|
ret.setAnimationTime(0);
|
|
if (effect != null) {
|
|
for (MapleData effectEntry : effect) {
|
|
ret.incAnimationTime(MapleDataTool.getIntConvert("delay", effectEntry, 0));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
public static String getSkillName(int skillid) {
|
|
MapleData data = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/" + "String.wz")).getData("Skill.img");
|
|
StringBuilder skill = new StringBuilder();
|
|
skill.append(String.valueOf(skillid));
|
|
if (skill.length() == 4) {
|
|
skill.delete(0, 4);
|
|
skill.append("000").append(String.valueOf(skillid));
|
|
}
|
|
if (data.getChildByPath(skill.toString()) != null) {
|
|
for (MapleData skilldata : data.getChildByPath(skill.toString()).getChildren()) {
|
|
if (skilldata.getName().equals("name"))
|
|
return MapleDataTool.getString(skilldata, null);
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|