DocumentBase.java 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. /*
  2. * This program is free software: you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation, either version 3 of the License, or (at your option) any later
  5. * version.
  6. *
  7. * This program is distributed in the hope that it will be useful, but WITHOUT
  8. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  9. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  10. * details.
  11. *
  12. * You should have received a copy of the GNU General Public License along with
  13. * this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. package net.sf.l2j.gameserver.skills;
  16. import java.io.File;
  17. import java.util.ArrayList;
  18. import java.util.List;
  19. import java.util.Map;
  20. import java.util.StringTokenizer;
  21. import java.util.logging.Level;
  22. import java.util.logging.Logger;
  23. import javax.xml.parsers.DocumentBuilderFactory;
  24. import javolution.text.TextBuilder;
  25. import javolution.util.FastList;
  26. import javolution.util.FastMap;
  27. import net.sf.l2j.Config;
  28. import net.sf.l2j.gameserver.datatables.SkillTable;
  29. import net.sf.l2j.gameserver.model.L2Character;
  30. import net.sf.l2j.gameserver.model.L2Skill;
  31. import net.sf.l2j.gameserver.model.base.Race;
  32. import net.sf.l2j.gameserver.skills.conditions.Condition;
  33. import net.sf.l2j.gameserver.skills.conditions.ConditionChangeWeapon;
  34. import net.sf.l2j.gameserver.skills.conditions.ConditionForceBuff;
  35. import net.sf.l2j.gameserver.skills.conditions.ConditionGameChance;
  36. import net.sf.l2j.gameserver.skills.conditions.ConditionGameTime;
  37. import net.sf.l2j.gameserver.skills.conditions.ConditionLogicAnd;
  38. import net.sf.l2j.gameserver.skills.conditions.ConditionLogicNot;
  39. import net.sf.l2j.gameserver.skills.conditions.ConditionLogicOr;
  40. import net.sf.l2j.gameserver.skills.conditions.ConditionMinDistance;
  41. import net.sf.l2j.gameserver.skills.conditions.ConditionPlayerCp;
  42. import net.sf.l2j.gameserver.skills.conditions.ConditionPlayerHp;
  43. import net.sf.l2j.gameserver.skills.conditions.ConditionPlayerHpPercentage;
  44. import net.sf.l2j.gameserver.skills.conditions.ConditionPlayerLevel;
  45. import net.sf.l2j.gameserver.skills.conditions.ConditionPlayerMp;
  46. import net.sf.l2j.gameserver.skills.conditions.ConditionPlayerRace;
  47. import net.sf.l2j.gameserver.skills.conditions.ConditionPlayerState;
  48. import net.sf.l2j.gameserver.skills.conditions.ConditionPlayerWeight;
  49. import net.sf.l2j.gameserver.skills.conditions.ConditionSkillStats;
  50. import net.sf.l2j.gameserver.skills.conditions.ConditionSlotItemId;
  51. import net.sf.l2j.gameserver.skills.conditions.ConditionTargetActiveEffectId;
  52. import net.sf.l2j.gameserver.skills.conditions.ConditionTargetActiveSkillId;
  53. import net.sf.l2j.gameserver.skills.conditions.ConditionTargetAggro;
  54. import net.sf.l2j.gameserver.skills.conditions.ConditionTargetClassIdRestriction;
  55. import net.sf.l2j.gameserver.skills.conditions.ConditionTargetLevel;
  56. import net.sf.l2j.gameserver.skills.conditions.ConditionTargetRaceId;
  57. import net.sf.l2j.gameserver.skills.conditions.ConditionTargetUsesWeaponKind;
  58. import net.sf.l2j.gameserver.skills.conditions.ConditionUsingItemType;
  59. import net.sf.l2j.gameserver.skills.conditions.ConditionUsingSkill;
  60. import net.sf.l2j.gameserver.skills.conditions.ConditionWithSkill;
  61. import net.sf.l2j.gameserver.skills.conditions.ConditionGameTime.CheckGameTime;
  62. import net.sf.l2j.gameserver.skills.conditions.ConditionPlayerState.CheckPlayerState;
  63. import net.sf.l2j.gameserver.skills.effects.EffectTemplate;
  64. import net.sf.l2j.gameserver.skills.funcs.FuncTemplate;
  65. import net.sf.l2j.gameserver.skills.funcs.Lambda;
  66. import net.sf.l2j.gameserver.skills.funcs.LambdaCalc;
  67. import net.sf.l2j.gameserver.skills.funcs.LambdaConst;
  68. import net.sf.l2j.gameserver.skills.funcs.LambdaStats;
  69. import net.sf.l2j.gameserver.templates.StatsSet;
  70. import net.sf.l2j.gameserver.templates.item.L2ArmorType;
  71. import net.sf.l2j.gameserver.templates.item.L2Item;
  72. import net.sf.l2j.gameserver.templates.item.L2Weapon;
  73. import net.sf.l2j.gameserver.templates.item.L2WeaponType;
  74. import org.w3c.dom.Document;
  75. import org.w3c.dom.NamedNodeMap;
  76. import org.w3c.dom.Node;
  77. /**
  78. * @author mkizub
  79. *
  80. * TODO To change the template for this generated type comment go to
  81. * Window - Preferences - Java - Code Style - Code Templates
  82. */
  83. abstract class DocumentBase
  84. {
  85. static Logger _log = Logger.getLogger(DocumentBase.class.getName());
  86. private File _file;
  87. protected Map<String, String[]> _tables;
  88. DocumentBase(File pFile)
  89. {
  90. _file = pFile;
  91. _tables = new FastMap<String, String[]>();
  92. }
  93. Document parse()
  94. {
  95. Document doc;
  96. try
  97. {
  98. DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  99. factory.setValidating(false);
  100. factory.setIgnoringComments(true);
  101. doc = factory.newDocumentBuilder().parse(_file);
  102. }
  103. catch (Exception e)
  104. {
  105. _log.log(Level.SEVERE, "Error loading file " + _file, e);
  106. return null;
  107. }
  108. try
  109. {
  110. parseDocument(doc);
  111. }
  112. catch (Exception e)
  113. {
  114. _log.log(Level.SEVERE, "Error in file " + _file, e);
  115. return null;
  116. }
  117. return doc;
  118. }
  119. protected abstract void parseDocument(Document doc);
  120. protected abstract StatsSet getStatsSet();
  121. protected abstract String getTableValue(String name);
  122. protected abstract String getTableValue(String name, int idx);
  123. protected void resetTable()
  124. {
  125. _tables = new FastMap<String, String[]>();
  126. }
  127. protected void setTable(String name, String[] table)
  128. {
  129. _tables.put(name, table);
  130. }
  131. protected void parseTemplate(Node n, Object template)
  132. {
  133. Condition condition = null;
  134. n = n.getFirstChild();
  135. if (n == null) return;
  136. if ("cond".equalsIgnoreCase(n.getNodeName()))
  137. {
  138. condition = parseCondition(n.getFirstChild(), template);
  139. Node msg = n.getAttributes().getNamedItem("msg");
  140. if (condition != null && msg != null) condition.setMessage(msg.getNodeValue());
  141. n = n.getNextSibling();
  142. }
  143. for (; n != null; n = n.getNextSibling())
  144. {
  145. if ("add".equalsIgnoreCase(n.getNodeName())) attachFunc(n, template, "Add", condition);
  146. else if ("sub".equalsIgnoreCase(n.getNodeName())) attachFunc(n, template, "Sub", condition);
  147. else if ("mul".equalsIgnoreCase(n.getNodeName())) attachFunc(n, template, "Mul", condition);
  148. else if ("basemul".equalsIgnoreCase(n.getNodeName())) attachFunc(n, template, "BaseMul", condition);
  149. else if ("div".equalsIgnoreCase(n.getNodeName())) attachFunc(n, template, "Div", condition);
  150. else if ("set".equalsIgnoreCase(n.getNodeName())) attachFunc(n, template, "Set", condition);
  151. else if ("enchant".equalsIgnoreCase(n.getNodeName())) attachFunc(n, template, "Enchant",
  152. condition);
  153. //else if ("skill".equalsIgnoreCase(n.getNodeName())) attachSkill(n, template, condition);
  154. else if ("effect".equalsIgnoreCase(n.getNodeName()))
  155. {
  156. if (template instanceof EffectTemplate) throw new RuntimeException("Nested effects");
  157. attachEffect(n, template, condition);
  158. }
  159. }
  160. }
  161. protected void attachFunc(Node n, Object template, String name, Condition attachCond)
  162. {
  163. Stats stat = Stats.valueOfXml(n.getAttributes().getNamedItem("stat").getNodeValue());
  164. String order = n.getAttributes().getNamedItem("order").getNodeValue();
  165. Lambda lambda = getLambda(n, template);
  166. int ord = Integer.decode(getValue(order, template));
  167. Condition applayCond = parseCondition(n.getFirstChild(), template);
  168. FuncTemplate ft = new FuncTemplate(attachCond, applayCond, name, stat, ord, lambda);
  169. if (template instanceof L2Item) ((L2Item) template).attach(ft);
  170. else if (template instanceof L2Skill) ((L2Skill) template).attach(ft);
  171. else if (template instanceof EffectTemplate) ((EffectTemplate) template).attach(ft);
  172. }
  173. protected void attachLambdaFunc(Node n, Object template, LambdaCalc calc)
  174. {
  175. String name = n.getNodeName();
  176. TextBuilder sb = new TextBuilder(name);
  177. sb.setCharAt(0, Character.toUpperCase(name.charAt(0)));
  178. name = sb.toString();
  179. Lambda lambda = getLambda(n, template);
  180. FuncTemplate ft = new FuncTemplate(null, null, name, null, calc.funcs.length, lambda);
  181. calc.addFunc(ft.getFunc(new Env(), calc));
  182. }
  183. protected void attachEffect(Node n, Object template, Condition attachCond)
  184. {
  185. NamedNodeMap attrs = n.getAttributes();
  186. String name = attrs.getNamedItem("name").getNodeValue();
  187. int time, count = 1;
  188. if (attrs.getNamedItem("count") != null)
  189. {
  190. count = Integer.decode(getValue(attrs.getNamedItem("count").getNodeValue(), template));
  191. }
  192. if (attrs.getNamedItem("time") != null)
  193. {
  194. time = Integer.decode(getValue(attrs.getNamedItem("time").getNodeValue(),template));
  195. if (Config.ENABLE_MODIFY_SKILL_DURATION)
  196. {
  197. if (Config.SKILL_DURATION_LIST.containsKey(((L2Skill) template).getId()))
  198. {
  199. if (((L2Skill) template).getLevel() < 100)
  200. time = Config.SKILL_DURATION_LIST.get(((L2Skill) template).getId());
  201. else if ((((L2Skill) template).getLevel() >= 100) && (((L2Skill) template).getLevel() < 140))
  202. time += Config.SKILL_DURATION_LIST.get(((L2Skill) template).getId());
  203. else if (((L2Skill) template).getLevel() > 140)
  204. time = Config.SKILL_DURATION_LIST.get(((L2Skill) template).getId());
  205. if (Config.DEBUG)
  206. _log.info("*** Skill " + ((L2Skill) template).getName() + " (" + ((L2Skill) template).getLevel() + ") changed duration to " + time + " seconds.");
  207. }
  208. }
  209. }
  210. else time = ((L2Skill) template).getBuffDuration() / 1000 / count;
  211. boolean self = false;
  212. if (attrs.getNamedItem("self") != null)
  213. {
  214. if (Integer.decode(getValue(attrs.getNamedItem("self").getNodeValue(),template)) == 1)
  215. self = true;
  216. }
  217. boolean icon = true;
  218. if (attrs.getNamedItem("noicon") !=null)
  219. {
  220. if (Integer.decode(getValue(attrs.getNamedItem("noicon").getNodeValue(),template)) == 1)
  221. icon = false;
  222. }
  223. Lambda lambda = getLambda(n, template);
  224. Condition applayCond = parseCondition(n.getFirstChild(), template);
  225. int abnormal = 0;
  226. if (attrs.getNamedItem("abnormal") != null)
  227. {
  228. String abn = attrs.getNamedItem("abnormal").getNodeValue();
  229. if (abn.equals("poison")) abnormal = L2Character.ABNORMAL_EFFECT_POISON;
  230. else if (abn.equals("bleeding")) abnormal = L2Character.ABNORMAL_EFFECT_BLEEDING;
  231. else if (abn.equals("flame")) abnormal = L2Character.ABNORMAL_EFFECT_FLAME;
  232. else if (abn.equals("bighead")) abnormal = L2Character.ABNORMAL_EFFECT_BIG_HEAD;
  233. else if (abn.equals("stealth")) abnormal = L2Character.ABNORMAL_EFFECT_STEALTH;
  234. }
  235. float stackOrder = 0;
  236. String stackType = "none";
  237. if (attrs.getNamedItem("stackType") != null)
  238. {
  239. stackType = attrs.getNamedItem("stackType").getNodeValue();
  240. }
  241. if (attrs.getNamedItem("stackOrder") != null)
  242. {
  243. stackOrder = Float.parseFloat(getValue(attrs.getNamedItem("stackOrder").getNodeValue(), template));
  244. }
  245. EffectTemplate lt = new EffectTemplate(attachCond, applayCond, name, lambda, count, time,
  246. abnormal, stackType, stackOrder, icon);
  247. parseTemplate(n, lt);
  248. if (template instanceof L2Item) ((L2Item) template).attach(lt);
  249. else if (template instanceof L2Skill && !self) ((L2Skill) template).attach(lt);
  250. else if (template instanceof L2Skill && self) ((L2Skill) template).attachSelf(lt);
  251. }
  252. protected void attachSkill(Node n, Object template, Condition attachCond)
  253. {
  254. NamedNodeMap attrs = n.getAttributes();
  255. int id = 0, lvl = 1;
  256. if (attrs.getNamedItem("id") != null)
  257. {
  258. id = Integer.decode(getValue(attrs.getNamedItem("id").getNodeValue(), template));
  259. }
  260. if (attrs.getNamedItem("lvl") != null)
  261. {
  262. lvl = Integer.decode(getValue(attrs.getNamedItem("lvl").getNodeValue(), template));
  263. }
  264. L2Skill skill = SkillTable.getInstance().getInfo(id, lvl);
  265. if (attrs.getNamedItem("chance") != null)
  266. {
  267. if (template instanceof L2Weapon || template instanceof L2Item)
  268. {
  269. skill.attach(new ConditionGameChance(Integer.decode(getValue(attrs.getNamedItem("chance").getNodeValue(), template))), true);
  270. }
  271. else
  272. {
  273. skill.attach(new ConditionGameChance(Integer.decode(getValue(attrs.getNamedItem("chance").getNodeValue(), template))), false);
  274. }
  275. }
  276. if (template instanceof L2Weapon)
  277. {
  278. if (attrs.getNamedItem("onUse") != null
  279. || (attrs.getNamedItem("onCrit") == null && attrs.getNamedItem("onCast") == null))
  280. ((L2Weapon) template).attach(skill); // Attach as skill triggered on use
  281. //if (attrs.getNamedItem("onCrit") != null) ((L2Weapon) template).attachOnCrit(skill); // Attach as skill triggered on critical hit
  282. //if (attrs.getNamedItem("onCast") != null) ((L2Weapon) template).attachOnCast(skill); // Attach as skill triggered on cast
  283. }
  284. else if (template instanceof L2Item)
  285. {
  286. ((L2Item) template).attach(skill); // Attach as skill triggered on use
  287. }
  288. }
  289. protected Condition parseCondition(Node n, Object template)
  290. {
  291. while (n != null && n.getNodeType() != Node.ELEMENT_NODE)
  292. n = n.getNextSibling();
  293. if (n == null) return null;
  294. if ("and".equalsIgnoreCase(n.getNodeName())) return parseLogicAnd(n, template);
  295. if ("or".equalsIgnoreCase(n.getNodeName())) return parseLogicOr(n, template);
  296. if ("not".equalsIgnoreCase(n.getNodeName())) return parseLogicNot(n, template);
  297. if ("player".equalsIgnoreCase(n.getNodeName())) return parsePlayerCondition(n);
  298. if ("target".equalsIgnoreCase(n.getNodeName())) return parseTargetCondition(n, template);
  299. if ("skill".equalsIgnoreCase(n.getNodeName())) return parseSkillCondition(n);
  300. if ("using".equalsIgnoreCase(n.getNodeName())) return parseUsingCondition(n);
  301. if ("game".equalsIgnoreCase(n.getNodeName())) return parseGameCondition(n);
  302. return null;
  303. }
  304. protected Condition parseLogicAnd(Node n, Object template)
  305. {
  306. ConditionLogicAnd cond = new ConditionLogicAnd();
  307. for (n = n.getFirstChild(); n != null; n = n.getNextSibling())
  308. {
  309. if (n.getNodeType() == Node.ELEMENT_NODE) cond.add(parseCondition(n, template));
  310. }
  311. if (cond.conditions == null || cond.conditions.length == 0)
  312. _log.severe("Empty <and> condition in " + _file);
  313. return cond;
  314. }
  315. protected Condition parseLogicOr(Node n, Object template)
  316. {
  317. ConditionLogicOr cond = new ConditionLogicOr();
  318. for (n = n.getFirstChild(); n != null; n = n.getNextSibling())
  319. {
  320. if (n.getNodeType() == Node.ELEMENT_NODE) cond.add(parseCondition(n, template));
  321. }
  322. if (cond.conditions == null || cond.conditions.length == 0)
  323. _log.severe("Empty <or> condition in " + _file);
  324. return cond;
  325. }
  326. protected Condition parseLogicNot(Node n, Object template)
  327. {
  328. for (n = n.getFirstChild(); n != null; n = n.getNextSibling())
  329. {
  330. if (n.getNodeType() == Node.ELEMENT_NODE)
  331. {
  332. return new ConditionLogicNot(parseCondition(n, template));
  333. }
  334. }
  335. _log.severe("Empty <not> condition in " + _file);
  336. return null;
  337. }
  338. protected Condition parsePlayerCondition(Node n)
  339. {
  340. Condition cond = null;
  341. byte[] forces = new byte[2];
  342. NamedNodeMap attrs = n.getAttributes();
  343. for (int i = 0; i < attrs.getLength(); i++)
  344. {
  345. Node a = attrs.item(i);
  346. if ("race".equalsIgnoreCase(a.getNodeName()))
  347. {
  348. Race race = Race.valueOf(a.getNodeValue());
  349. cond = joinAnd(cond, new ConditionPlayerRace(race));
  350. }
  351. else if ("level".equalsIgnoreCase(a.getNodeName()))
  352. {
  353. int lvl = Integer.decode(getValue(a.getNodeValue(), null));
  354. cond = joinAnd(cond, new ConditionPlayerLevel(lvl));
  355. }
  356. else if ("resting".equalsIgnoreCase(a.getNodeName()))
  357. {
  358. boolean val = Boolean.valueOf(a.getNodeValue());
  359. cond = joinAnd(cond, new ConditionPlayerState(CheckPlayerState.RESTING, val));
  360. }
  361. else if ("flying".equalsIgnoreCase(a.getNodeName()))
  362. {
  363. boolean val = Boolean.valueOf(a.getNodeValue());
  364. cond = joinAnd(cond, new ConditionPlayerState(CheckPlayerState.FLYING, val));
  365. }
  366. else if ("moving".equalsIgnoreCase(a.getNodeName()))
  367. {
  368. boolean val = Boolean.valueOf(a.getNodeValue());
  369. cond = joinAnd(cond, new ConditionPlayerState(CheckPlayerState.MOVING, val));
  370. }
  371. else if ("running".equalsIgnoreCase(a.getNodeName()))
  372. {
  373. boolean val = Boolean.valueOf(a.getNodeValue());
  374. cond = joinAnd(cond, new ConditionPlayerState(CheckPlayerState.RUNNING, val));
  375. }
  376. else if ("behind".equalsIgnoreCase(a.getNodeName()))
  377. {
  378. boolean val = Boolean.valueOf(a.getNodeValue());
  379. cond = joinAnd(cond, new ConditionPlayerState(CheckPlayerState.BEHIND, val));
  380. }
  381. else if ("front".equalsIgnoreCase(a.getNodeName()))
  382. {
  383. boolean val = Boolean.valueOf(a.getNodeValue());
  384. cond = joinAnd(cond, new ConditionPlayerState(CheckPlayerState.FRONT, val));
  385. }
  386. else if ("hp".equalsIgnoreCase(a.getNodeName()))
  387. {
  388. int hp = Integer.decode(getValue(a.getNodeValue(), null));
  389. cond = joinAnd(cond, new ConditionPlayerHp(hp));
  390. }
  391. else if ("hprate".equalsIgnoreCase(a.getNodeName()))
  392. {
  393. double rate = Double.parseDouble(getValue(a.getNodeValue(), null));
  394. cond = joinAnd(cond, new ConditionPlayerHpPercentage(rate));
  395. }
  396. else if ("mp".equalsIgnoreCase(a.getNodeName()))
  397. {
  398. int hp = Integer.decode(getValue(a.getNodeValue(), null));
  399. cond = joinAnd(cond, new ConditionPlayerMp(hp));
  400. }
  401. else if ("cp".equalsIgnoreCase(a.getNodeName()))
  402. {
  403. int cp = Integer.decode(getValue(a.getNodeValue(), null));
  404. cond = joinAnd(cond, new ConditionPlayerCp(cp));
  405. }
  406. else if ("battle_force".equalsIgnoreCase(a.getNodeName()))
  407. {
  408. forces[0] = Byte.decode(getValue(a.getNodeValue(), null));
  409. }
  410. else if ("spell_force".equalsIgnoreCase(a.getNodeName()))
  411. {
  412. forces[1] = Byte.decode(getValue(a.getNodeValue(), null));
  413. }
  414. else if ("weight".equalsIgnoreCase(a.getNodeName()))
  415. {
  416. int weight = Integer.decode(getValue(a.getNodeValue(), null));
  417. cond = joinAnd(cond, new ConditionPlayerWeight(weight));
  418. }
  419. }
  420. if(forces[0] + forces[1] > 0)
  421. {
  422. cond = joinAnd(cond, new ConditionForceBuff(forces));
  423. }
  424. if (cond == null) _log.severe("Unrecognized <player> condition in " + _file);
  425. return cond;
  426. }
  427. protected Condition parseTargetCondition(Node n, Object template)
  428. {
  429. Condition cond = null;
  430. NamedNodeMap attrs = n.getAttributes();
  431. for (int i = 0; i < attrs.getLength(); i++)
  432. {
  433. Node a = attrs.item(i);
  434. if ("aggro".equalsIgnoreCase(a.getNodeName()))
  435. {
  436. boolean val = Boolean.valueOf(a.getNodeValue());
  437. cond = joinAnd(cond, new ConditionTargetAggro(val));
  438. }
  439. else if ("level".equalsIgnoreCase(a.getNodeName()))
  440. {
  441. int lvl = Integer.decode(getValue(a.getNodeValue(), template));
  442. cond = joinAnd(cond, new ConditionTargetLevel(lvl));
  443. }
  444. else if ("class_id_restriction".equalsIgnoreCase(a.getNodeName()))
  445. {
  446. FastList<Integer> array = new FastList<Integer>();
  447. StringTokenizer st = new StringTokenizer(a.getNodeValue(), ",");
  448. while (st.hasMoreTokens())
  449. {
  450. String item = st.nextToken().trim();
  451. array.add(Integer.decode(getValue(item, null)));
  452. }
  453. cond = joinAnd(cond, new ConditionTargetClassIdRestriction(array));
  454. }
  455. else if ("active_effect_id".equalsIgnoreCase(a.getNodeName()))
  456. {
  457. int effect_id = Integer.decode(getValue(a.getNodeValue(), template));
  458. cond = joinAnd(cond, new ConditionTargetActiveEffectId(effect_id));
  459. }
  460. else if ("active_skill_id".equalsIgnoreCase(a.getNodeName()))
  461. {
  462. int skill_id = Integer.decode(getValue(a.getNodeValue(), template));
  463. cond = joinAnd(cond, new ConditionTargetActiveSkillId(skill_id));
  464. }
  465. else if("mindistance".equalsIgnoreCase(a.getNodeName()))
  466. {
  467. int distance = Integer.decode(getValue(a.getNodeValue(),null));
  468. cond = joinAnd(cond, new ConditionMinDistance(distance*distance));
  469. }
  470. else if ("race_id".equalsIgnoreCase(a.getNodeName()))
  471. {
  472. ArrayList<Integer> array = new ArrayList<Integer>();
  473. StringTokenizer st = new StringTokenizer(a.getNodeValue(), ",");
  474. while (st.hasMoreTokens())
  475. {
  476. String item = st.nextToken().trim();
  477. array.add(Integer.decode(getValue(item, null)));
  478. }
  479. cond = joinAnd(cond, new ConditionTargetRaceId(array));
  480. }
  481. else if ("using".equalsIgnoreCase(a.getNodeName()))
  482. {
  483. int mask = 0;
  484. StringTokenizer st = new StringTokenizer(a.getNodeValue(), ",");
  485. while (st.hasMoreTokens())
  486. {
  487. String item = st.nextToken().trim();
  488. for (L2WeaponType wt : L2WeaponType.values())
  489. {
  490. if (wt.toString().equals(item))
  491. {
  492. mask |= wt.mask();
  493. break;
  494. }
  495. }
  496. for (L2ArmorType at : L2ArmorType.values())
  497. {
  498. if (at.toString().equals(item))
  499. {
  500. mask |= at.mask();
  501. break;
  502. }
  503. }
  504. }
  505. cond = joinAnd(cond, new ConditionTargetUsesWeaponKind(mask));
  506. }
  507. }
  508. if (cond == null) _log.severe("Unrecognized <target> condition in " + _file);
  509. return cond;
  510. }
  511. protected Condition parseSkillCondition(Node n)
  512. {
  513. NamedNodeMap attrs = n.getAttributes();
  514. Stats stat = Stats.valueOfXml(attrs.getNamedItem("stat").getNodeValue());
  515. return new ConditionSkillStats(stat);
  516. }
  517. protected Condition parseUsingCondition(Node n)
  518. {
  519. Condition cond = null;
  520. NamedNodeMap attrs = n.getAttributes();
  521. for (int i = 0; i < attrs.getLength(); i++)
  522. {
  523. Node a = attrs.item(i);
  524. if ("kind".equalsIgnoreCase(a.getNodeName()))
  525. {
  526. int mask = 0;
  527. StringTokenizer st = new StringTokenizer(a.getNodeValue(), ",");
  528. while (st.hasMoreTokens())
  529. {
  530. String item = st.nextToken().trim();
  531. for (L2WeaponType wt : L2WeaponType.values())
  532. {
  533. if (wt.toString().equals(item))
  534. {
  535. mask |= wt.mask();
  536. break;
  537. }
  538. }
  539. for (L2ArmorType at : L2ArmorType.values())
  540. {
  541. if (at.toString().equals(item))
  542. {
  543. mask |= at.mask();
  544. break;
  545. }
  546. }
  547. }
  548. cond = joinAnd(cond, new ConditionUsingItemType(mask));
  549. }
  550. else if ("skill".equalsIgnoreCase(a.getNodeName()))
  551. {
  552. int id = Integer.parseInt(a.getNodeValue());
  553. cond = joinAnd(cond, new ConditionUsingSkill(id));
  554. }
  555. else if ("slotitem".equalsIgnoreCase(a.getNodeName()))
  556. {
  557. StringTokenizer st = new StringTokenizer(a.getNodeValue(), ";");
  558. int id = Integer.parseInt(st.nextToken().trim());
  559. int slot = Integer.parseInt(st.nextToken().trim());
  560. int enchant = 0;
  561. if (st.hasMoreTokens()) enchant = Integer.parseInt(st.nextToken().trim());
  562. cond = joinAnd(cond, new ConditionSlotItemId(slot, id, enchant));
  563. }
  564. else if ("weaponChange".equalsIgnoreCase(a.getNodeName()))
  565. {
  566. boolean val = Boolean.valueOf(a.getNodeValue());
  567. cond = joinAnd(cond, new ConditionChangeWeapon(val));
  568. }
  569. }
  570. if (cond == null) _log.severe("Unrecognized <using> condition in " + _file);
  571. return cond;
  572. }
  573. protected Condition parseGameCondition(Node n)
  574. {
  575. Condition cond = null;
  576. NamedNodeMap attrs = n.getAttributes();
  577. for (int i = 0; i < attrs.getLength(); i++)
  578. {
  579. Node a = attrs.item(i);
  580. if ("skill".equalsIgnoreCase(a.getNodeName()))
  581. {
  582. boolean val = Boolean.valueOf(a.getNodeValue());
  583. cond = joinAnd(cond, new ConditionWithSkill(val));
  584. }
  585. if ("night".equalsIgnoreCase(a.getNodeName()))
  586. {
  587. boolean val = Boolean.valueOf(a.getNodeValue());
  588. cond = joinAnd(cond, new ConditionGameTime(CheckGameTime.NIGHT, val));
  589. }
  590. if ("chance".equalsIgnoreCase(a.getNodeName()))
  591. {
  592. int val = Integer.decode(getValue(a.getNodeValue(), null));
  593. cond = joinAnd(cond, new ConditionGameChance(val));
  594. }
  595. }
  596. if (cond == null) _log.severe("Unrecognized <game> condition in " + _file);
  597. return cond;
  598. }
  599. protected void parseTable(Node n)
  600. {
  601. NamedNodeMap attrs = n.getAttributes();
  602. String name = attrs.getNamedItem("name").getNodeValue();
  603. if (name.charAt(0) != '#') throw new IllegalArgumentException("Table name must start with #");
  604. StringTokenizer data = new StringTokenizer(n.getFirstChild().getNodeValue());
  605. List<String> array = new FastList<String>();
  606. while (data.hasMoreTokens())
  607. array.add(data.nextToken());
  608. String[] res = new String[array.size()];
  609. int i = 0;
  610. for (String str : array)
  611. {
  612. res[i++] = str;
  613. }
  614. setTable(name, res);
  615. }
  616. protected void parseBeanSet(Node n, StatsSet set, Integer level)
  617. {
  618. String name = n.getAttributes().getNamedItem("name").getNodeValue().trim();
  619. String value = n.getAttributes().getNamedItem("val").getNodeValue().trim();
  620. char ch = value.length() == 0 ? ' ' : value.charAt(0);
  621. if (ch == '#' || ch == '-' || Character.isDigit(ch)) set.set(name,
  622. String.valueOf(getValue(value,
  623. level)));
  624. else set.set(name, value);
  625. }
  626. protected Lambda getLambda(Node n, Object template)
  627. {
  628. Node nval = n.getAttributes().getNamedItem("val");
  629. if (nval != null)
  630. {
  631. String val = nval.getNodeValue();
  632. if (val.charAt(0) == '#')
  633. { // table by level
  634. return new LambdaConst(Double.parseDouble(getTableValue(val)));
  635. }
  636. else if (val.charAt(0) == '$')
  637. {
  638. if (val.equalsIgnoreCase("$player_level"))
  639. return new LambdaStats(LambdaStats.StatsType.PLAYER_LEVEL);
  640. if (val.equalsIgnoreCase("$target_level"))
  641. return new LambdaStats(LambdaStats.StatsType.TARGET_LEVEL);
  642. if (val.equalsIgnoreCase("$player_max_hp"))
  643. return new LambdaStats(LambdaStats.StatsType.PLAYER_MAX_HP);
  644. if (val.equalsIgnoreCase("$player_max_mp"))
  645. return new LambdaStats(LambdaStats.StatsType.PLAYER_MAX_MP);
  646. // try to find value out of item fields
  647. StatsSet set = getStatsSet();
  648. String field = set.getString(val.substring(1));
  649. if (field != null)
  650. {
  651. return new LambdaConst(Double.parseDouble(getValue(field, template)));
  652. }
  653. // failed
  654. throw new IllegalArgumentException("Unknown value " + val);
  655. }
  656. else
  657. {
  658. return new LambdaConst(Double.parseDouble(val));
  659. }
  660. }
  661. LambdaCalc calc = new LambdaCalc();
  662. n = n.getFirstChild();
  663. while (n != null && n.getNodeType() != Node.ELEMENT_NODE)
  664. n = n.getNextSibling();
  665. if (n == null || !"val".equals(n.getNodeName()))
  666. throw new IllegalArgumentException("Value not specified");
  667. for (n = n.getFirstChild(); n != null; n = n.getNextSibling())
  668. {
  669. if (n.getNodeType() != Node.ELEMENT_NODE) continue;
  670. attachLambdaFunc(n, template, calc);
  671. }
  672. return calc;
  673. }
  674. protected String getValue(String value, Object template)
  675. {
  676. // is it a table?
  677. if (value.charAt(0) == '#')
  678. {
  679. if (template instanceof L2Skill) return getTableValue(value);
  680. else if (template instanceof Integer) return getTableValue(value, ((Integer) template).intValue());
  681. else throw new IllegalStateException();
  682. }
  683. return value;
  684. }
  685. protected Condition joinAnd(Condition cond, Condition c)
  686. {
  687. if (cond == null) return c;
  688. if (cond instanceof ConditionLogicAnd)
  689. {
  690. ((ConditionLogicAnd) cond).add(c);
  691. return cond;
  692. }
  693. ConditionLogicAnd and = new ConditionLogicAnd();
  694. and.add(cond);
  695. and.add(c);
  696. return and;
  697. }
  698. }