package client;
import client.status.MonsterStatus;
import database.DatabaseConnection;
import java.awt.Point;
import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import provider.MapleData;
import provider.MapleDataDirectoryEntry;
import provider.MapleDataFileEntry;
import provider.MapleDataProvider;
import provider.MapleDataProviderFactory;
import provider.MapleDataTool;
import server.Randomizer;
import tools.StringUtil;
import tools.Triple;
public class SkillFactory {
private static final MapleData delayData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath", "wz") + "/Character.wz")).getData("00002000.img");
private static final MapleData stringData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath", "wz") + "/String.wz")).getData("Skill.img");
private static final MapleDataProvider datasource = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath", "wz") + "/Skill.wz"));
private static final Map<Integer, Skill> skills = new HashMap();
private static final Map<String, Integer> delays = new HashMap();
private static final Map<Integer, CraftingEntry> crafts = new HashMap();
private static final Map<Integer, FamiliarEntry> familiars = new HashMap();
private static final Map<Integer, List<Integer>> skillsByJob = new HashMap();
private static final Map<Integer, SummonSkillEntry> SummonSkillInformation = new HashMap();
// @TODO 这里要处理
public static void loadAllSkills(boolean reload) {
if (reload) {
skills.clear();
}
if (!skills.isEmpty()) {
return;
}
MapleDataDirectoryEntry root = datasource.getRoot();
int del = 0;
for (MapleData delay : delayData) {
if (!delay.getName().equals("info")) {
delays.put(delay.getName(), del);
del++;
}
}
for (MapleDataFileEntry topDir : root.getFiles()) {
if (topDir.getName().length() <= 9) {
// 普通技能
for (MapleData data : datasource.getData(topDir.getName())) {
if (data.getName().equals("skill")) {
for (MapleData data2 : data) {
if (data2 != null) {
int skillid = Integer.parseInt(data2.getName());
Skill skil = Skill.loadFromData(skillid, data2, delayData);
List job = (List) skillsByJob.get(Integer.valueOf(skillid / 10000));
if (job == null) {
job = new ArrayList();
skillsByJob.put(skillid / 10000, job);
}
job.add(skillid);
skil.setName(getName(skillid, stringData));
skills.put(skillid, skil);
MapleData summon_data = data2.getChildByPath("summon/attack1/info");
if (summon_data != null) {
SummonSkillEntry sse = new SummonSkillEntry();
sse.type = (byte) MapleDataTool.getInt("type", summon_data, 0);
sse.mobCount = (byte) MapleDataTool.getInt("mobCount", summon_data, 1);
sse.attackCount = (byte) MapleDataTool.getInt("attackCount", summon_data, 1);
if (summon_data.getChildByPath("range/lt") != null) {
MapleData ltd = summon_data.getChildByPath("range/lt");
sse.lt = ((Point) ltd.getData());
sse.rb = ((Point) summon_data.getChildByPath("range/rb").getData());
} else {
sse.lt = new Point(-100, -100);
sse.rb = new Point(100, 100);
}
sse.delay = (MapleDataTool.getInt("effectAfter", summon_data, 0) + MapleDataTool.getInt("attackAfter", summon_data, 0));
for (MapleData effect : summon_data) {
if (effect.getChildren().size() > 0) {
for (MapleData effectEntry : effect) {
sse.delay += MapleDataTool.getIntConvert("delay", effectEntry, 0);
}
}
}
for (MapleData effect : data2.getChildByPath("summon/attack1")) {
sse.delay += MapleDataTool.getIntConvert("delay", effect, 0);
}
SummonSkillInformation.put(skillid, sse);
}
}
}
}
}
} else if (topDir.getName().startsWith("Familiar")) {
// 家族技能?
for (MapleData data : datasource.getData(topDir.getName())) {
int skillid = Integer.parseInt(data.getName());
FamiliarEntry skil = new FamiliarEntry();
skil.prop = (byte) MapleDataTool.getInt("prop", data, 0);
skil.time = (byte) MapleDataTool.getInt("time", data, 0);
skil.attackCount = (byte) MapleDataTool.getInt("attackCount", data, 1);
skil.targetCount = (byte) MapleDataTool.getInt("targetCount", data, 1);
skil.speed = (byte) MapleDataTool.getInt("speed", data, 1);
skil.knockback = ((MapleDataTool.getInt("knockback", data, 0) > 0) || (MapleDataTool.getInt("attract", data, 0) > 0));
if (data.getChildByPath("lt") != null) {
skil.lt = ((Point) data.getChildByPath("lt").getData());
skil.rb = ((Point) data.getChildByPath("rb").getData());
}
if (MapleDataTool.getInt("stun", data, 0) > 0) {
skil.status.add(MonsterStatus.眩晕);
}
if (MapleDataTool.getInt("slow", data, 0) > 0) {
skil.status.add(MonsterStatus.速度);
}
familiars.put(skillid, skil);
}
} else if (topDir.getName().startsWith("Recipe")) {
// 锻造技能?
for (MapleData data : datasource.getData(topDir.getName())) {
int skillid = Integer.parseInt(data.getName());
CraftingEntry skil = new CraftingEntry(skillid, (byte) MapleDataTool.getInt("incFatigability", data, 0), (byte) MapleDataTool.getInt("reqSkillLevel", data, 0), (byte) MapleDataTool.getInt("incSkillProficiency", data, 0), MapleDataTool.getInt("needOpenItem", data, 0) > 0, MapleDataTool.getInt("period", data, 0));
for (MapleData d : data.getChildByPath("target")) {
skil.targetItems.add(new Triple(MapleDataTool.getInt("item", d, 0), MapleDataTool.getInt("count", d, 0), MapleDataTool.getInt("probWeight", d, 0)));
}
for (MapleData d : data.getChildByPath("recipe")) {
skil.reqItems.put(MapleDataTool.getInt("item", d, 0), MapleDataTool.getInt("count", d, 0));
}
crafts.put(skillid, skil);
}
}
}
}
public static List<Integer> getSkillsByJob(int jobId) {
return (List) skillsByJob.get(jobId);
}
public static String getSkillName(int id) {
Skill skil = getSkill(id);
if (skil != null) {
return skil.getName();
}
String strId = Integer.toString(id);
strId = StringUtil.getLeftPaddedStr(strId, '0', 7);
MapleData skillroot = stringData.getChildByPath(strId);
if (skillroot != null) {
return MapleDataTool.getString(skillroot.getChildByPath("name"), "");
}
return null;
}
public static Integer getDelay(String id) {
if (Delay.fromString(id) != null) {
return Delay.fromString(id).i;
}
return delays.get(id);
}
private static String getName(int id, MapleData stringData) {
String strId = Integer.toString(id);
strId = StringUtil.getLeftPaddedStr(strId, '0', 7);
MapleData skillroot = stringData.getChildByPath(strId);
if (skillroot != null) {
return MapleDataTool.getString(skillroot.getChildByPath("name"), "");
}
return "";
}
public static SummonSkillEntry getSummonData(int skillid) {
return (SummonSkillEntry) SummonSkillInformation.get(skillid);
}
public static Collection<Skill> getAllSkills() {
Map<Integer, Skill> mapVK = new TreeMap<>(
new Comparator<Integer>() {
@Override
public int compare(Integer obj1, Integer obj2) {
Integer v1 = obj1;
Integer v2 = obj2;
int s = v1.compareTo(v2);
return s;
}
}
);
Set col = skills.keySet();
Iterator iter = col.iterator();
while (iter.hasNext()) {
Integer key = (Integer) iter.next();
Skill value = (Skill) skills.get(key);
mapVK.put(key, value);
}
return mapVK.values();
}
public static Skill getSkill(int skillid) {
if (!skills.isEmpty()) {
if ((skillid >= 92000000) && (skillid < 100000000) && (crafts.containsKey(skillid))) {
return (Skill) crafts.get(skillid);
}
return (Skill) skills.get(skillid);
}
return null;
}
public static long getDefaultSExpiry(Skill skill) {
if (skill == null) {
return -1L;
}
return skill.isTimeLimited() ? System.currentTimeMillis() + 2592000000L : -1L;
}
public static CraftingEntry getCraft(int id) {
if (!crafts.isEmpty()) {
return (CraftingEntry) crafts.get(id);
}
return null;
}
public static FamiliarEntry getFamiliar(int id) {
if (!familiars.isEmpty()) {
return (FamiliarEntry) familiars.get(id);
}
return null;
}
public static enum Delay {
walk1(0),
walk2(1),
stand1(2),
stand2(3),
alert(4),
swingO1(5),
swingO2(6),
swingO3(7),
swingOF(8),
swingT1(9),
swingT2(10),
swingT3(11),
swingTF(12),
swingP1(13),
swingP2(14),
swingPF(15),
stabO1(16),
stabO2(17),
stabOF(18),
stabT1(19),
stabT2(20),
stabTF(21),
swingD1(22),
swingD2(23),
stabD1(24),
swingDb1(25),
swingDb2(26),
swingC1(27),
swingC2(28),
rushBoom(28),
tripleBlow(25),
quadBlow(26),
deathBlow(27),
finishBlow(28),
finishAttack(29),
finishAttack_link(30),
finishAttack_link2(30),
shoot1(31),
shoot2(32),
shootF(33),
shootDb2(40),
shotC1(41),
dash(37),
dash2(38),
proneStab(41),
prone(42),
heal(43),
fly(44),
jump(45),
sit(46),
rope(47),
dead(48),
ladder(49),
rain(50),
alert2(52),
alert3(53),
alert4(54),
alert5(55),
alert6(56),
alert7(57),
ladder2(58),
rope2(59),
shoot6(60),
magic1(61),
magic2(62),
magic3(63),
magic5(64),
magic6(65),
explosion(65),
burster1(66),
burster2(67),
savage(68),
avenger(69),
assaulter(70),
prone2(71),
assassination(72),
assassinationS(73),
tornadoDash(76),
tornadoDashStop(76),
tornadoRush(76),
rush(77),
rush2(78),
brandish1(79),
brandish2(80),
braveSlash(81),
braveslash1(81),
braveslash2(81),
braveslash3(81),
braveslash4(81),
darkImpale(97),
sanctuary(82),
meteor(83),
paralyze(84),
blizzard(85),
genesis(86),
blast(88),
smokeshell(89),
showdown(90),
ninjastorm(91),
chainlightning(92),
holyshield(93),
resurrection(94),
somersault(95),
straight(96),
eburster(97),
backspin(98),
eorb(99),
screw(100),
doubleupper(101),
dragonstrike(102),
doublefire(103),
triplefire(104),
fake(105),
airstrike(106),
edrain(107),
octopus(108),
backstep(109),
shot(110),
rapidfire(110),
fireburner(112),
coolingeffect(113),
fist(114),
timeleap(115),
homing(117),
ghostwalk(118),
ghoststand(119),
ghostjump(120),
ghostproneStab(121),
ghostladder(122),
ghostrope(123),
ghostfly(124),
ghostsit(125),
cannon(126),
torpedo(127),
darksight(128),
bamboo(129),
pyramid(130),
wave(131),
blade(132),
souldriver(133),
firestrike(134),
flamegear(135),
stormbreak(136),
vampire(137),
swingT2PoleArm(139),
swingP1PoleArm(140),
swingP2PoleArm(141),
doubleSwing(142),
tripleSwing(143),
fullSwingDouble(144),
fullSwingTriple(145),
overSwingDouble(146),
overSwingTriple(147),
rollingSpin(148),
comboSmash(149),
comboFenrir(150),
comboTempest(151),
finalCharge(152),
finalBlow(154),
finalToss(155),
magicmissile(156),
lightningBolt(157),
dragonBreathe(158),
breathe_prepare(159),
dragonIceBreathe(160),
icebreathe_prepare(161),
blaze(162),
fireCircle(163),
illusion(164),
magicFlare(165),
elementalReset(166),
magicRegistance(167),
magicBooster(168),
magicShield(169),
recoveryAura(170),
flameWheel(171),
killingWing(172),
OnixBlessing(173),
Earthquake(174),
soulStone(175),
dragonThrust(176),
ghostLettering(177),
darkFog(178),
slow(179),
mapleHero(180),
Awakening(181),
flyingAssaulter(182),
tripleStab(183),
fatalBlow(184),
slashStorm1(185),
slashStorm2(186),
bloodyStorm(187),
flashBang(188),
upperStab(189),
bladeFury(190),
chainPull(192),
chainAttack(192),
owlDead(193),
monsterBombPrepare(195),
monsterBombThrow(195),
finalCut(196),
finalCutPrepare(196),
suddenRaid(198),
fly2(199),
fly2Move(200),
fly2Skill(201),
knockback(202),
rbooster_pre(206),
rbooster(206),
rbooster_after(206),
crossRoad(209),
nemesis(210),
tank(217),
tank_laser(221),
siege_pre(223),
tank_siegepre(223),
sonicBoom(226),
darkLightning(228),
darkChain(229),
cyclone_pre(0),
cyclone(0),
glacialchain(247),
flamethrower(233),
flamethrower_pre(233),
flamethrower2(234),
flamethrower_pre2(234),
gatlingshot(239),
gatlingshot2(240),
drillrush(241),
earthslug(242),
rpunch(243),
clawCut(244),
swallow(247),
swallow_attack(247),
swallow_loop(247),
flashRain(249),
OnixProtection(264),
OnixWill(265),
phantomBlow(266),
comboJudgement(267),
arrowRain(268),
arrowEruption(269),
iceStrike(270),
swingT2Giant(273),
cannonJump(295),
swiftShot(296),
giganticBackstep(298),
mistEruption(299),
cannonSmash(300),
cannonSlam(301),
flamesplash(302),
noiseWave(306),
superCannon(310),
jShot(312),
demonSlasher(313),
bombExplosion(314),
cannonSpike(315),
speedDualShot(316),
strikeDual(317),
bluntSmash(319),
crossPiercing(320),
piercing(321),
elfTornado(323),
immolation(324),
multiSniping(327),
windEffect(328),
elfrush(329),
elfrush2(329),
dealingRush(334),
maxForce0(336),
maxForce1(337),
maxForce2(338),
maxForce3(339),
iceAttack1(274),
iceAttack2(275),
iceSmash(276),
iceTempest(277),
iceChop(278),
icePanic(279),
iceDoubleJump(280),
shockwave(292),
demolition(293),
snatch(294),
windspear(295),
windshot(296);
public int i;
private Delay(int i) {
this.i = i;
}
public static Delay fromString(String s) {
for (Delay b : values()) {
if (b.name().equalsIgnoreCase(s)) {
return b;
}
}
return null;
}
}
public static class FamiliarEntry {
public byte prop;
public byte time;
public byte attackCount;
public byte targetCount;
public byte speed;
public Point lt;
public Point rb;
public boolean knockback;
public EnumSet<MonsterStatus> status = EnumSet.noneOf(MonsterStatus.class);
public boolean makeChanceResult() {
return (this.prop >= 100) || (Randomizer.nextInt(100) < this.prop);
}
}
public static class CraftingEntry extends Skill {
public boolean needOpenItem;
public int period;
public byte incFatigability;
public byte reqSkillLevel;
public byte incSkillProficiency;
public List<Triple<Integer, Integer, Integer>> targetItems = new ArrayList();
public Map<Integer, Integer> reqItems = new HashMap();
public CraftingEntry(int id, byte incFatigability, byte reqSkillLevel, byte incSkillProficiency, boolean needOpenItem, int period) {
super(id);
this.incFatigability = incFatigability;
this.reqSkillLevel = reqSkillLevel;
this.incSkillProficiency = incSkillProficiency;
this.needOpenItem = needOpenItem;
this.period = period;
}
}
}