DocumentBase.java 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036
  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 com.l2jserver.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.NoSuchElementException;
  21. import java.util.StringTokenizer;
  22. import java.util.logging.Level;
  23. import java.util.logging.Logger;
  24. import javax.xml.parsers.DocumentBuilderFactory;
  25. import javolution.util.FastMap;
  26. import org.w3c.dom.Document;
  27. import org.w3c.dom.NamedNodeMap;
  28. import org.w3c.dom.Node;
  29. import com.l2jserver.Config;
  30. import com.l2jserver.gameserver.datatables.ItemTable;
  31. import com.l2jserver.gameserver.model.ChanceCondition;
  32. import com.l2jserver.gameserver.model.L2Object.InstanceType;
  33. import com.l2jserver.gameserver.model.L2Skill;
  34. import com.l2jserver.gameserver.model.base.PlayerState;
  35. import com.l2jserver.gameserver.model.base.Race;
  36. import com.l2jserver.gameserver.skills.conditions.Condition;
  37. import com.l2jserver.gameserver.skills.conditions.ConditionChangeWeapon;
  38. import com.l2jserver.gameserver.skills.conditions.ConditionForceBuff;
  39. import com.l2jserver.gameserver.skills.conditions.ConditionGameChance;
  40. import com.l2jserver.gameserver.skills.conditions.ConditionGameTime;
  41. import com.l2jserver.gameserver.skills.conditions.ConditionGameTime.CheckGameTime;
  42. import com.l2jserver.gameserver.skills.conditions.ConditionLogicAnd;
  43. import com.l2jserver.gameserver.skills.conditions.ConditionLogicNot;
  44. import com.l2jserver.gameserver.skills.conditions.ConditionLogicOr;
  45. import com.l2jserver.gameserver.skills.conditions.ConditionMinDistance;
  46. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerActiveEffectId;
  47. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerActiveSkillId;
  48. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerAgathionId;
  49. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerCharges;
  50. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerClassIdRestriction;
  51. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerCloakStatus;
  52. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerCp;
  53. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerFlyMounted;
  54. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerGrade;
  55. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerHasCastle;
  56. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerHasClanHall;
  57. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerHasFort;
  58. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerHasPet;
  59. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerHp;
  60. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerInstanceId;
  61. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerInvSize;
  62. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerIsClanLeader;
  63. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerIsHero;
  64. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerLandingZone;
  65. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerLevel;
  66. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerMp;
  67. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerPkCount;
  68. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerPledgeClass;
  69. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerRace;
  70. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerServitorNpcId;
  71. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerSex;
  72. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerSiegeSide;
  73. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerSouls;
  74. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerState;
  75. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerSubclass;
  76. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerTvTEvent;
  77. import com.l2jserver.gameserver.skills.conditions.ConditionPlayerWeight;
  78. import com.l2jserver.gameserver.skills.conditions.ConditionSiegeZone;
  79. import com.l2jserver.gameserver.skills.conditions.ConditionSkillStats;
  80. import com.l2jserver.gameserver.skills.conditions.ConditionSlotItemId;
  81. import com.l2jserver.gameserver.skills.conditions.ConditionTargetAbnormal;
  82. import com.l2jserver.gameserver.skills.conditions.ConditionTargetActiveEffectId;
  83. import com.l2jserver.gameserver.skills.conditions.ConditionTargetActiveSkillId;
  84. import com.l2jserver.gameserver.skills.conditions.ConditionTargetAggro;
  85. import com.l2jserver.gameserver.skills.conditions.ConditionTargetClassIdRestriction;
  86. import com.l2jserver.gameserver.skills.conditions.ConditionTargetLevel;
  87. import com.l2jserver.gameserver.skills.conditions.ConditionTargetNpcId;
  88. import com.l2jserver.gameserver.skills.conditions.ConditionTargetNpcType;
  89. import com.l2jserver.gameserver.skills.conditions.ConditionTargetRace;
  90. import com.l2jserver.gameserver.skills.conditions.ConditionTargetRaceId;
  91. import com.l2jserver.gameserver.skills.conditions.ConditionTargetUsesWeaponKind;
  92. import com.l2jserver.gameserver.skills.conditions.ConditionUsingItemType;
  93. import com.l2jserver.gameserver.skills.conditions.ConditionUsingSkill;
  94. import com.l2jserver.gameserver.skills.conditions.ConditionWithSkill;
  95. import com.l2jserver.gameserver.skills.effects.EffectChanceSkillTrigger;
  96. import com.l2jserver.gameserver.skills.funcs.FuncTemplate;
  97. import com.l2jserver.gameserver.skills.funcs.Lambda;
  98. import com.l2jserver.gameserver.skills.funcs.LambdaCalc;
  99. import com.l2jserver.gameserver.skills.funcs.LambdaConst;
  100. import com.l2jserver.gameserver.skills.funcs.LambdaStats;
  101. import com.l2jserver.gameserver.templates.StatsSet;
  102. import com.l2jserver.gameserver.templates.effects.EffectTemplate;
  103. import com.l2jserver.gameserver.templates.item.L2ArmorType;
  104. import com.l2jserver.gameserver.templates.item.L2Item;
  105. import com.l2jserver.gameserver.templates.item.L2WeaponType;
  106. import com.l2jserver.gameserver.templates.skills.L2SkillType;
  107. /**
  108. * @author mkizub
  109. */
  110. abstract class DocumentBase
  111. {
  112. static Logger _log = Logger.getLogger(DocumentBase.class.getName());
  113. private File _file;
  114. protected Map<String, String[]> _tables;
  115. DocumentBase(File pFile)
  116. {
  117. _file = pFile;
  118. _tables = new FastMap<String, String[]>();
  119. }
  120. Document parse()
  121. {
  122. Document doc;
  123. try
  124. {
  125. DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  126. factory.setValidating(false);
  127. factory.setIgnoringComments(true);
  128. doc = factory.newDocumentBuilder().parse(_file);
  129. }
  130. catch (Exception e)
  131. {
  132. _log.log(Level.SEVERE, "Error loading file " + _file, e);
  133. return null;
  134. }
  135. try
  136. {
  137. parseDocument(doc);
  138. }
  139. catch (Exception e)
  140. {
  141. _log.log(Level.SEVERE, "Error in file " + _file, e);
  142. return null;
  143. }
  144. return doc;
  145. }
  146. protected abstract void parseDocument(Document doc);
  147. protected abstract StatsSet getStatsSet();
  148. protected abstract String getTableValue(String name);
  149. protected abstract String getTableValue(String name, int idx);
  150. protected void resetTable()
  151. {
  152. _tables = new FastMap<String, String[]>();
  153. }
  154. protected void setTable(String name, String[] table)
  155. {
  156. _tables.put(name, table);
  157. }
  158. protected void parseTemplate(Node n, Object template)
  159. {
  160. Condition condition = null;
  161. n = n.getFirstChild();
  162. if (n == null) return;
  163. if ("cond".equalsIgnoreCase(n.getNodeName()))
  164. {
  165. condition = parseCondition(n.getFirstChild(), template);
  166. Node msg = n.getAttributes().getNamedItem("msg");
  167. Node msgId = n.getAttributes().getNamedItem("msgId");
  168. if (condition != null && msg != null)
  169. condition.setMessage(msg.getNodeValue());
  170. else if (condition != null && msgId != null)
  171. {
  172. condition.setMessageId(Integer.decode(getValue(msgId.getNodeValue(), null)));
  173. Node addName = n.getAttributes().getNamedItem("addName");
  174. if (addName != null && Integer.decode(getValue(msgId.getNodeValue(), null)) > 0)
  175. condition.addName();
  176. }
  177. n = n.getNextSibling();
  178. }
  179. for (; n != null; n = n.getNextSibling())
  180. {
  181. if ("add".equalsIgnoreCase(n.getNodeName())) attachFunc(n, template, "Add", condition);
  182. else if ("sub".equalsIgnoreCase(n.getNodeName())) attachFunc(n, template, "Sub", condition);
  183. else if ("mul".equalsIgnoreCase(n.getNodeName())) attachFunc(n, template, "Mul", condition);
  184. else if ("basemul".equalsIgnoreCase(n.getNodeName())) attachFunc(n, template, "BaseMul", condition);
  185. else if ("div".equalsIgnoreCase(n.getNodeName())) attachFunc(n, template, "Div", condition);
  186. else if ("set".equalsIgnoreCase(n.getNodeName())) attachFunc(n, template, "Set", condition);
  187. else if ("enchant".equalsIgnoreCase(n.getNodeName())) attachFunc(n, template, "Enchant", condition);
  188. else if ("enchanthp".equalsIgnoreCase(n.getNodeName())) attachFunc(n, template, "EnchantHp", condition);
  189. //else if ("skill".equalsIgnoreCase(n.getNodeName())) attachSkill(n, template, condition);
  190. else if ("effect".equalsIgnoreCase(n.getNodeName()))
  191. {
  192. if (template instanceof EffectTemplate) throw new RuntimeException("Nested effects");
  193. attachEffect(n, template, condition);
  194. }
  195. }
  196. }
  197. protected void attachFunc(Node n, Object template, String name, Condition attachCond)
  198. {
  199. Stats stat = Stats.valueOfXml(n.getAttributes().getNamedItem("stat").getNodeValue());
  200. String order = n.getAttributes().getNamedItem("order").getNodeValue();
  201. Lambda lambda = getLambda(n, template);
  202. int ord = Integer.decode(getValue(order, template));
  203. Condition applayCond = parseCondition(n.getFirstChild(), template);
  204. FuncTemplate ft = new FuncTemplate(attachCond, applayCond, name, stat, ord, lambda);
  205. if (template instanceof L2Item) ((L2Item) template).attach(ft);
  206. else if (template instanceof L2Skill) ((L2Skill) template).attach(ft);
  207. else if (template instanceof EffectTemplate) ((EffectTemplate) template).attach(ft);
  208. }
  209. protected void attachLambdaFunc(Node n, Object template, LambdaCalc calc)
  210. {
  211. String name = n.getNodeName();
  212. final StringBuilder sb = new StringBuilder(name);
  213. sb.setCharAt(0, Character.toUpperCase(name.charAt(0)));
  214. name = sb.toString();
  215. Lambda lambda = getLambda(n, template);
  216. FuncTemplate ft = new FuncTemplate(null, null, name, null, calc.funcs.length, lambda);
  217. calc.addFunc(ft.getFunc(new Env(), calc));
  218. }
  219. protected void attachEffect(Node n, Object template, Condition attachCond)
  220. {
  221. NamedNodeMap attrs = n.getAttributes();
  222. String name = getValue(attrs.getNamedItem("name").getNodeValue().intern(), template);
  223. /**
  224. * Keep this values as default ones, DP needs it
  225. */
  226. int time = 1;
  227. int count = 1;
  228. if (attrs.getNamedItem("count") != null)
  229. {
  230. count = Integer.decode(getValue(attrs.getNamedItem("count").getNodeValue(), template));
  231. }
  232. if (attrs.getNamedItem("time") != null)
  233. {
  234. time = Integer.decode(getValue(attrs.getNamedItem("time").getNodeValue(),template));
  235. if (Config.ENABLE_MODIFY_SKILL_DURATION)
  236. {
  237. if (Config.SKILL_DURATION_LIST.containsKey(((L2Skill) template).getId()))
  238. {
  239. if (((L2Skill) template).getLevel() < 100)
  240. time = Config.SKILL_DURATION_LIST.get(((L2Skill) template).getId());
  241. else if ((((L2Skill) template).getLevel() >= 100) && (((L2Skill) template).getLevel() < 140))
  242. time += Config.SKILL_DURATION_LIST.get(((L2Skill) template).getId());
  243. else if (((L2Skill) template).getLevel() > 140)
  244. time = Config.SKILL_DURATION_LIST.get(((L2Skill) template).getId());
  245. if (Config.DEBUG)
  246. _log.info("*** Skill " + ((L2Skill) template).getName() + " (" + ((L2Skill) template).getLevel() + ") changed duration to " + time + " seconds.");
  247. }
  248. }
  249. }
  250. else if (((L2Skill) template).getBuffDuration() > 0)
  251. time = ((L2Skill) template).getBuffDuration() / 1000 / count;
  252. boolean self = false;
  253. if (attrs.getNamedItem("self") != null)
  254. {
  255. if (Integer.decode(getValue(attrs.getNamedItem("self").getNodeValue(),template)) == 1)
  256. self = true;
  257. }
  258. boolean icon = true;
  259. if (attrs.getNamedItem("noicon") !=null)
  260. {
  261. if (Integer.decode(getValue(attrs.getNamedItem("noicon").getNodeValue(),template)) == 1)
  262. icon = false;
  263. }
  264. Lambda lambda = getLambda(n, template);
  265. Condition applayCond = parseCondition(n.getFirstChild(), template);
  266. AbnormalEffect abnormal = AbnormalEffect.NULL;
  267. if (attrs.getNamedItem("abnormal") != null)
  268. {
  269. String abn = attrs.getNamedItem("abnormal").getNodeValue();
  270. abnormal = AbnormalEffect.getByName(abn);
  271. }
  272. AbnormalEffect special = AbnormalEffect.NULL;
  273. if (attrs.getNamedItem("special") != null)
  274. {
  275. String spc = attrs.getNamedItem("special").getNodeValue();
  276. special = AbnormalEffect.getByName(spc);
  277. }
  278. AbnormalEffect event = AbnormalEffect.NULL;
  279. if (attrs.getNamedItem("event") != null)
  280. {
  281. String spc = attrs.getNamedItem("event").getNodeValue();
  282. event = AbnormalEffect.getByName(spc);
  283. }
  284. float stackOrder = 0;
  285. String stackType = "none";
  286. if (attrs.getNamedItem("stackType") != null)
  287. {
  288. stackType = attrs.getNamedItem("stackType").getNodeValue();
  289. }
  290. if (attrs.getNamedItem("stackOrder") != null)
  291. {
  292. stackOrder = Float.parseFloat(getValue(attrs.getNamedItem("stackOrder").getNodeValue(), template));
  293. }
  294. double effectPower = -1;
  295. if (attrs.getNamedItem("effectPower") != null)
  296. effectPower = Double.parseDouble( getValue(attrs.getNamedItem("effectPower").getNodeValue(), template));
  297. L2SkillType type = null;
  298. if (attrs.getNamedItem("effectType") != null)
  299. {
  300. String typeName = getValue(attrs.getNamedItem("effectType").getNodeValue(), template);
  301. try
  302. {
  303. type = Enum.valueOf(L2SkillType.class, typeName);
  304. }
  305. catch (Exception e)
  306. {
  307. throw new IllegalArgumentException("Not skilltype found for: "+typeName);
  308. }
  309. }
  310. EffectTemplate lt;
  311. final boolean isChanceSkillTrigger = (name == EffectChanceSkillTrigger.class.getName());
  312. int trigId = 0;
  313. if (attrs.getNamedItem("triggeredId") != null)
  314. trigId = Integer.parseInt(getValue(attrs.getNamedItem("triggeredId").getNodeValue(), template));
  315. else if (isChanceSkillTrigger)
  316. throw new NoSuchElementException(name + " requires triggerId");
  317. int trigLvl = 1;
  318. if (attrs.getNamedItem("triggeredLevel") != null)
  319. trigLvl = Integer.parseInt(getValue(attrs.getNamedItem("triggeredLevel").getNodeValue(), template));
  320. String chanceCond = null;
  321. if (attrs.getNamedItem("chanceType") != null)
  322. chanceCond = getValue(attrs.getNamedItem("chanceType").getNodeValue(), template);
  323. else if (isChanceSkillTrigger)
  324. throw new NoSuchElementException(name + " requires chanceType");
  325. int activationChance = -1;
  326. if (attrs.getNamedItem("activationChance") != null)
  327. activationChance = Integer.parseInt(getValue(attrs.getNamedItem("activationChance").getNodeValue(), template));
  328. int activationMinDamage = -1;
  329. if (attrs.getNamedItem("activationMinDamage") != null)
  330. activationMinDamage = Integer.parseInt(getValue(attrs.getNamedItem("activationMinDamage").getNodeValue(), template));
  331. String activationElements = null;
  332. if (attrs.getNamedItem("activationElements") != null)
  333. activationElements = getValue(attrs.getNamedItem("activationElements").getNodeValue(), template);
  334. boolean pvpOnly = false;
  335. if (attrs.getNamedItem("pvpChanceOnly") != null)
  336. pvpOnly = Boolean.parseBoolean(getValue(attrs.getNamedItem("pvpChanceOnly").getNodeValue(), template));
  337. ChanceCondition chance = ChanceCondition.parse(chanceCond, activationChance, activationMinDamage, activationElements, pvpOnly);
  338. if (chance == null && isChanceSkillTrigger)
  339. throw new NoSuchElementException("Invalid chance condition: " + chanceCond + " "
  340. + activationChance);
  341. lt = new EffectTemplate(attachCond, applayCond, name, lambda, count, time, abnormal, special, event, stackType, stackOrder, icon, effectPower, type, trigId, trigLvl, chance);
  342. parseTemplate(n, lt);
  343. if (template instanceof L2Item)
  344. ((L2Item) template).attach(lt);
  345. else if (template instanceof L2Skill)
  346. {
  347. if (self)
  348. ((L2Skill) template).attachSelf(lt);
  349. else
  350. ((L2Skill) template).attach(lt);
  351. }
  352. }
  353. protected Condition parseCondition(Node n, Object template)
  354. {
  355. while (n != null && n.getNodeType() != Node.ELEMENT_NODE)
  356. n = n.getNextSibling();
  357. if (n == null) return null;
  358. if ("and".equalsIgnoreCase(n.getNodeName())) return parseLogicAnd(n, template);
  359. if ("or".equalsIgnoreCase(n.getNodeName())) return parseLogicOr(n, template);
  360. if ("not".equalsIgnoreCase(n.getNodeName())) return parseLogicNot(n, template);
  361. if ("player".equalsIgnoreCase(n.getNodeName())) return parsePlayerCondition(n, template);
  362. if ("target".equalsIgnoreCase(n.getNodeName())) return parseTargetCondition(n, template);
  363. if ("skill".equalsIgnoreCase(n.getNodeName())) return parseSkillCondition(n);
  364. if ("using".equalsIgnoreCase(n.getNodeName())) return parseUsingCondition(n);
  365. if ("game".equalsIgnoreCase(n.getNodeName())) return parseGameCondition(n);
  366. return null;
  367. }
  368. protected Condition parseLogicAnd(Node n, Object template)
  369. {
  370. ConditionLogicAnd cond = new ConditionLogicAnd();
  371. for (n = n.getFirstChild(); n != null; n = n.getNextSibling())
  372. {
  373. if (n.getNodeType() == Node.ELEMENT_NODE) cond.add(parseCondition(n, template));
  374. }
  375. if (cond.conditions == null || cond.conditions.length == 0)
  376. _log.severe("Empty <and> condition in " + _file);
  377. return cond;
  378. }
  379. protected Condition parseLogicOr(Node n, Object template)
  380. {
  381. ConditionLogicOr cond = new ConditionLogicOr();
  382. for (n = n.getFirstChild(); n != null; n = n.getNextSibling())
  383. {
  384. if (n.getNodeType() == Node.ELEMENT_NODE) cond.add(parseCondition(n, template));
  385. }
  386. if (cond.conditions == null || cond.conditions.length == 0)
  387. _log.severe("Empty <or> condition in " + _file);
  388. return cond;
  389. }
  390. protected Condition parseLogicNot(Node n, Object template)
  391. {
  392. for (n = n.getFirstChild(); n != null; n = n.getNextSibling())
  393. {
  394. if (n.getNodeType() == Node.ELEMENT_NODE)
  395. {
  396. return new ConditionLogicNot(parseCondition(n, template));
  397. }
  398. }
  399. _log.severe("Empty <not> condition in " + _file);
  400. return null;
  401. }
  402. protected Condition parsePlayerCondition(Node n, Object template)
  403. {
  404. Condition cond = null;
  405. byte[] forces = new byte[2];
  406. NamedNodeMap attrs = n.getAttributes();
  407. for (int i = 0; i < attrs.getLength(); i++)
  408. {
  409. Node a = attrs.item(i);
  410. if ("race".equalsIgnoreCase(a.getNodeName()))
  411. {
  412. Race race = Race.valueOf(a.getNodeValue());
  413. cond = joinAnd(cond, new ConditionPlayerRace(race));
  414. }
  415. else if ("level".equalsIgnoreCase(a.getNodeName()))
  416. {
  417. int lvl = Integer.decode(getValue(a.getNodeValue(), template));
  418. cond = joinAnd(cond, new ConditionPlayerLevel(lvl));
  419. }
  420. else if ("resting".equalsIgnoreCase(a.getNodeName()))
  421. {
  422. boolean val = Boolean.valueOf(a.getNodeValue());
  423. cond = joinAnd(cond, new ConditionPlayerState(PlayerState.RESTING, val));
  424. }
  425. else if ("flying".equalsIgnoreCase(a.getNodeName()))
  426. {
  427. boolean val = Boolean.valueOf(a.getNodeValue());
  428. cond = joinAnd(cond, new ConditionPlayerState(PlayerState.FLYING, val));
  429. }
  430. else if ("moving".equalsIgnoreCase(a.getNodeName()))
  431. {
  432. boolean val = Boolean.valueOf(a.getNodeValue());
  433. cond = joinAnd(cond, new ConditionPlayerState(PlayerState.MOVING, val));
  434. }
  435. else if ("running".equalsIgnoreCase(a.getNodeName()))
  436. {
  437. boolean val = Boolean.valueOf(a.getNodeValue());
  438. cond = joinAnd(cond, new ConditionPlayerState(PlayerState.RUNNING, val));
  439. }
  440. else if ("behind".equalsIgnoreCase(a.getNodeName()))
  441. {
  442. boolean val = Boolean.valueOf(a.getNodeValue());
  443. cond = joinAnd(cond, new ConditionPlayerState(PlayerState.BEHIND, val));
  444. }
  445. else if ("front".equalsIgnoreCase(a.getNodeName()))
  446. {
  447. boolean val = Boolean.valueOf(a.getNodeValue());
  448. cond = joinAnd(cond, new ConditionPlayerState(PlayerState.FRONT, val));
  449. }
  450. else if ("chaotic".equalsIgnoreCase(a.getNodeName()))
  451. {
  452. boolean val = Boolean.valueOf(a.getNodeValue());
  453. cond = joinAnd(cond, new ConditionPlayerState(PlayerState.CHAOTIC, val));
  454. }
  455. else if ("olympiad".equalsIgnoreCase(a.getNodeName()))
  456. {
  457. boolean val = Boolean.valueOf(a.getNodeValue());
  458. cond = joinAnd(cond, new ConditionPlayerState(PlayerState.OLYMPIAD, val));
  459. }
  460. else if ("ishero".equalsIgnoreCase(a.getNodeName()))
  461. {
  462. boolean val = Boolean.valueOf(a.getNodeValue());
  463. cond = joinAnd(cond, new ConditionPlayerIsHero(val));
  464. }
  465. else if ("hp".equalsIgnoreCase(a.getNodeName()))
  466. {
  467. int hp = Integer.decode(getValue(a.getNodeValue(), null));
  468. cond = joinAnd(cond, new ConditionPlayerHp(hp));
  469. }
  470. else if ("mp".equalsIgnoreCase(a.getNodeName()))
  471. {
  472. int hp = Integer.decode(getValue(a.getNodeValue(), null));
  473. cond = joinAnd(cond, new ConditionPlayerMp(hp));
  474. }
  475. else if ("cp".equalsIgnoreCase(a.getNodeName()))
  476. {
  477. int cp = Integer.decode(getValue(a.getNodeValue(), null));
  478. cond = joinAnd(cond, new ConditionPlayerCp(cp));
  479. }
  480. else if ("grade".equalsIgnoreCase(a.getNodeName()))
  481. {
  482. int expIndex = Integer.decode(getValue(a.getNodeValue(), template));
  483. cond = joinAnd(cond, new ConditionPlayerGrade(expIndex));
  484. }
  485. else if ("pkCount".equalsIgnoreCase(a.getNodeName()))
  486. {
  487. int expIndex = Integer.decode(getValue(a.getNodeValue(), template));
  488. cond = joinAnd(cond, new ConditionPlayerPkCount(expIndex));
  489. }
  490. else if ("siegezone".equalsIgnoreCase(a.getNodeName()))
  491. {
  492. int value = Integer.decode(getValue(a.getNodeValue(), null));
  493. cond = joinAnd(cond, new ConditionSiegeZone(value, true));
  494. }
  495. else if ("siegeside".equalsIgnoreCase(a.getNodeName()))
  496. {
  497. int value = Integer.decode(getValue(a.getNodeValue(), null));
  498. cond = joinAnd(cond, new ConditionPlayerSiegeSide(value));
  499. }
  500. else if ("battle_force".equalsIgnoreCase(a.getNodeName()))
  501. {
  502. forces[0] = Byte.decode(getValue(a.getNodeValue(), null));
  503. }
  504. else if ("spell_force".equalsIgnoreCase(a.getNodeName()))
  505. {
  506. forces[1] = Byte.decode(getValue(a.getNodeValue(), null));
  507. }
  508. else if ("charges".equalsIgnoreCase(a.getNodeName()))
  509. {
  510. int value = Integer.decode(getValue(a.getNodeValue(), template));
  511. cond = joinAnd(cond, new ConditionPlayerCharges(value));
  512. }
  513. else if ("souls".equalsIgnoreCase(a.getNodeName()))
  514. {
  515. int value = Integer.decode(getValue(a.getNodeValue(), template));
  516. cond = joinAnd(cond, new ConditionPlayerSouls(value));
  517. }
  518. else if ("weight".equalsIgnoreCase(a.getNodeName()))
  519. {
  520. int weight = Integer.decode(getValue(a.getNodeValue(), null));
  521. cond = joinAnd(cond, new ConditionPlayerWeight(weight));
  522. }
  523. else if ("invSize".equalsIgnoreCase(a.getNodeName()))
  524. {
  525. int size = Integer.decode(getValue(a.getNodeValue(), null));
  526. cond = joinAnd(cond, new ConditionPlayerInvSize(size));
  527. }
  528. else if ("isClanLeader".equalsIgnoreCase(a.getNodeName()))
  529. {
  530. boolean val = Boolean.valueOf(a.getNodeValue());
  531. cond = joinAnd(cond, new ConditionPlayerIsClanLeader(val));
  532. }
  533. else if ("onTvTEvent".equalsIgnoreCase(a.getNodeName()))
  534. {
  535. boolean val = Boolean.valueOf(a.getNodeValue());
  536. cond = joinAnd(cond, new ConditionPlayerTvTEvent(val));
  537. }
  538. else if ("pledgeClass".equalsIgnoreCase(a.getNodeName()))
  539. {
  540. int pledgeClass = Integer.decode(getValue(a.getNodeValue(), null));
  541. cond = joinAnd(cond, new ConditionPlayerPledgeClass(pledgeClass));
  542. }
  543. else if ("clanHall".equalsIgnoreCase(a.getNodeName()))
  544. {
  545. StringTokenizer st = new StringTokenizer(a.getNodeValue(), ",");
  546. ArrayList<Integer> array = new ArrayList<Integer>(st.countTokens());
  547. while (st.hasMoreTokens())
  548. {
  549. String item = st.nextToken().trim();
  550. array.add(Integer.decode(getValue(item, null)));
  551. }
  552. cond = joinAnd(cond, new ConditionPlayerHasClanHall(array));
  553. }
  554. else if ("fort".equalsIgnoreCase(a.getNodeName()))
  555. {
  556. int fort = Integer.decode(getValue(a.getNodeValue(), null));
  557. cond = joinAnd(cond, new ConditionPlayerHasFort(fort));
  558. }
  559. else if ("castle".equalsIgnoreCase(a.getNodeName()))
  560. {
  561. int castle = Integer.decode(getValue(a.getNodeValue(), null));
  562. cond = joinAnd(cond, new ConditionPlayerHasCastle(castle));
  563. }
  564. else if ("sex".equalsIgnoreCase(a.getNodeName()))
  565. {
  566. int sex = Integer.decode(getValue(a.getNodeValue(), null));
  567. cond = joinAnd(cond, new ConditionPlayerSex(sex));
  568. }
  569. else if ("flyMounted".equalsIgnoreCase(a.getNodeName()))
  570. {
  571. boolean val = Boolean.valueOf(a.getNodeValue());
  572. cond = joinAnd(cond, new ConditionPlayerFlyMounted(val));
  573. }
  574. else if ("landingZone".equalsIgnoreCase(a.getNodeName()))
  575. {
  576. boolean val = Boolean.valueOf(a.getNodeValue());
  577. cond = joinAnd(cond, new ConditionPlayerLandingZone(val));
  578. }
  579. else if ("active_effect_id".equalsIgnoreCase(a.getNodeName()))
  580. {
  581. int effect_id = Integer.decode(getValue(a.getNodeValue(), template));
  582. cond = joinAnd(cond, new ConditionPlayerActiveEffectId(effect_id));
  583. }
  584. else if ("active_effect_id_lvl".equalsIgnoreCase(a.getNodeName()))
  585. {
  586. String val = getValue(a.getNodeValue(), template);
  587. int effect_id = Integer.decode(getValue(val.split(",")[0], template));
  588. int effect_lvl = Integer.decode(getValue(val.split(",")[1], template));
  589. cond = joinAnd(cond, new ConditionPlayerActiveEffectId(effect_id, effect_lvl));
  590. }
  591. else if ("active_skill_id".equalsIgnoreCase(a.getNodeName()))
  592. {
  593. int skill_id = Integer.decode(getValue(a.getNodeValue(), template));
  594. cond = joinAnd(cond, new ConditionPlayerActiveSkillId(skill_id));
  595. }
  596. else if ("active_skill_id_lvl".equalsIgnoreCase(a.getNodeName()))
  597. {
  598. String val = getValue(a.getNodeValue(), template);
  599. int skill_id = Integer.decode(getValue(val.split(",")[0], template));
  600. int skill_lvl = Integer.decode(getValue(val.split(",")[1], template));
  601. cond = joinAnd(cond, new ConditionPlayerActiveSkillId(skill_id, skill_lvl));
  602. }
  603. else if ("class_id_restriction".equalsIgnoreCase(a.getNodeName()))
  604. {
  605. StringTokenizer st = new StringTokenizer(a.getNodeValue(), ",");
  606. ArrayList<Integer> array = new ArrayList<Integer>(st.countTokens());
  607. while (st.hasMoreTokens())
  608. {
  609. String item = st.nextToken().trim();
  610. array.add(Integer.decode(getValue(item, null)));
  611. }
  612. cond = joinAnd(cond, new ConditionPlayerClassIdRestriction(array));
  613. }
  614. else if ("subclass".equalsIgnoreCase(a.getNodeName()))
  615. {
  616. boolean val = Boolean.valueOf(a.getNodeValue());
  617. cond = joinAnd(cond, new ConditionPlayerSubclass(val));
  618. }
  619. else if ("instanceId".equalsIgnoreCase(a.getNodeName()))
  620. {
  621. StringTokenizer st = new StringTokenizer(a.getNodeValue(), ",");
  622. ArrayList<Integer> array = new ArrayList<Integer>(st.countTokens());
  623. while (st.hasMoreTokens())
  624. {
  625. String item = st.nextToken().trim();
  626. array.add(Integer.decode(getValue(item, null)));
  627. }
  628. cond = joinAnd(cond, new ConditionPlayerInstanceId(array));
  629. }
  630. else if ("agathionId".equalsIgnoreCase(a.getNodeName()))
  631. {
  632. int agathionId = Integer.decode(a.getNodeValue());
  633. cond = joinAnd(cond, new ConditionPlayerAgathionId(agathionId));
  634. }
  635. else if ("cloakStatus".equalsIgnoreCase(a.getNodeName()))
  636. {
  637. int val = Integer.valueOf(a.getNodeValue());
  638. cond = joinAnd(cond, new ConditionPlayerCloakStatus(val));
  639. }
  640. else if ("hasPet".equalsIgnoreCase(a.getNodeName()))
  641. {
  642. StringTokenizer st = new StringTokenizer(a.getNodeValue(), ",");
  643. ArrayList<Integer> array = new ArrayList<Integer>(st.countTokens());
  644. while (st.hasMoreTokens())
  645. {
  646. String item = st.nextToken().trim();
  647. array.add(Integer.decode(getValue(item, null)));
  648. }
  649. cond = joinAnd(cond, new ConditionPlayerHasPet(array));
  650. }
  651. else if ("servitorNpcId".equalsIgnoreCase(a.getNodeName()))
  652. {
  653. StringTokenizer st = new StringTokenizer(a.getNodeValue(), ",");
  654. ArrayList<Integer> array = new ArrayList<Integer>(st.countTokens());
  655. while (st.hasMoreTokens())
  656. {
  657. String item = st.nextToken().trim();
  658. array.add(Integer.decode(getValue(item, null)));
  659. }
  660. cond = joinAnd(cond, new ConditionPlayerServitorNpcId(array));
  661. }
  662. }
  663. if (forces[0] + forces[1] > 0)
  664. cond = joinAnd(cond, new ConditionForceBuff(forces));
  665. if (cond == null) _log.severe("Unrecognized <player> condition in " + _file);
  666. return cond;
  667. }
  668. protected Condition parseTargetCondition(Node n, Object template)
  669. {
  670. Condition cond = null;
  671. NamedNodeMap attrs = n.getAttributes();
  672. for (int i = 0; i < attrs.getLength(); i++)
  673. {
  674. Node a = attrs.item(i);
  675. if ("aggro".equalsIgnoreCase(a.getNodeName()))
  676. {
  677. boolean val = Boolean.valueOf(a.getNodeValue());
  678. cond = joinAnd(cond, new ConditionTargetAggro(val));
  679. }
  680. else if ("siegezone".equalsIgnoreCase(a.getNodeName()))
  681. {
  682. int value = Integer.decode(getValue(a.getNodeValue(), null));
  683. cond = joinAnd(cond, new ConditionSiegeZone(value, false));
  684. }
  685. else if ("level".equalsIgnoreCase(a.getNodeName()))
  686. {
  687. int lvl = Integer.decode(getValue(a.getNodeValue(), template));
  688. cond = joinAnd(cond, new ConditionTargetLevel(lvl));
  689. }
  690. else if ("class_id_restriction".equalsIgnoreCase(a.getNodeName()))
  691. {
  692. StringTokenizer st = new StringTokenizer(a.getNodeValue(), ",");
  693. ArrayList<Integer> array = new ArrayList<Integer>(st.countTokens());
  694. while (st.hasMoreTokens())
  695. {
  696. String item = st.nextToken().trim();
  697. array.add(Integer.decode(getValue(item, null)));
  698. }
  699. cond = joinAnd(cond, new ConditionTargetClassIdRestriction(array));
  700. }
  701. else if ("active_effect_id".equalsIgnoreCase(a.getNodeName()))
  702. {
  703. int effect_id = Integer.decode(getValue(a.getNodeValue(), template));
  704. cond = joinAnd(cond, new ConditionTargetActiveEffectId(effect_id));
  705. }
  706. else if ("active_effect_id_lvl".equalsIgnoreCase(a.getNodeName()))
  707. {
  708. String val = getValue(a.getNodeValue(), template);
  709. int effect_id = Integer.decode(getValue(val.split(",")[0], template));
  710. int effect_lvl = Integer.decode(getValue(val.split(",")[1], template));
  711. cond = joinAnd(cond, new ConditionTargetActiveEffectId(effect_id, effect_lvl));
  712. }
  713. else if ("active_skill_id".equalsIgnoreCase(a.getNodeName()))
  714. {
  715. int skill_id = Integer.decode(getValue(a.getNodeValue(), template));
  716. cond = joinAnd(cond, new ConditionTargetActiveSkillId(skill_id));
  717. }
  718. else if ("active_skill_id_lvl".equalsIgnoreCase(a.getNodeName()))
  719. {
  720. String val = getValue(a.getNodeValue(), template);
  721. int skill_id = Integer.decode(getValue(val.split(",")[0], template));
  722. int skill_lvl = Integer.decode(getValue(val.split(",")[1], template));
  723. cond = joinAnd(cond, new ConditionTargetActiveSkillId(skill_id, skill_lvl));
  724. }
  725. else if ("abnormal".equalsIgnoreCase(a.getNodeName()))
  726. {
  727. int abnormalId = Integer.decode(getValue(a.getNodeValue(), template));
  728. cond = joinAnd(cond, new ConditionTargetAbnormal(abnormalId));
  729. }
  730. else if("mindistance".equalsIgnoreCase(a.getNodeName()))
  731. {
  732. int distance = Integer.decode(getValue(a.getNodeValue(),null));
  733. cond = joinAnd(cond, new ConditionMinDistance(distance*distance));
  734. }
  735. // used for npc race
  736. else if ("race_id".equalsIgnoreCase(a.getNodeName()))
  737. {
  738. StringTokenizer st = new StringTokenizer(a.getNodeValue(), ",");
  739. ArrayList<Integer> array = new ArrayList<Integer>(st.countTokens());
  740. while (st.hasMoreTokens())
  741. {
  742. String item = st.nextToken().trim();
  743. array.add(Integer.decode(getValue(item, null)));
  744. }
  745. cond = joinAnd(cond, new ConditionTargetRaceId(array));
  746. }
  747. // used for pc race
  748. else if ("race".equalsIgnoreCase(a.getNodeName()))
  749. {
  750. Race race = Race.valueOf(a.getNodeValue());
  751. cond = joinAnd(cond, new ConditionTargetRace(race));
  752. }
  753. else if ("using".equalsIgnoreCase(a.getNodeName()))
  754. {
  755. int mask = 0;
  756. StringTokenizer st = new StringTokenizer(a.getNodeValue(), ",");
  757. while (st.hasMoreTokens())
  758. {
  759. String item = st.nextToken().trim();
  760. for (L2WeaponType wt : L2WeaponType.values())
  761. {
  762. if (wt.toString().equals(item))
  763. {
  764. mask |= wt.mask();
  765. break;
  766. }
  767. }
  768. for (L2ArmorType at : L2ArmorType.values())
  769. {
  770. if (at.toString().equals(item))
  771. {
  772. mask |= at.mask();
  773. break;
  774. }
  775. }
  776. }
  777. cond = joinAnd(cond, new ConditionTargetUsesWeaponKind(mask));
  778. }
  779. else if ("npcId".equalsIgnoreCase(a.getNodeName()))
  780. {
  781. StringTokenizer st = new StringTokenizer(a.getNodeValue(), ",");
  782. ArrayList<Integer> array = new ArrayList<Integer>(st.countTokens());
  783. while (st.hasMoreTokens())
  784. {
  785. String item = st.nextToken().trim();
  786. array.add(Integer.decode(getValue(item, null)));
  787. }
  788. cond = joinAnd(cond, new ConditionTargetNpcId(array));
  789. }
  790. else if ("npcType".equalsIgnoreCase(a.getNodeName()))
  791. {
  792. String values = getValue(a.getNodeValue(), template).trim();
  793. String[] valuesSplit = values.split(",");
  794. InstanceType[] types = new InstanceType[valuesSplit.length];
  795. InstanceType type;
  796. for (int j = 0; j < valuesSplit.length; j++)
  797. {
  798. type = Enum.valueOf(InstanceType.class, valuesSplit[j]);
  799. if (type == null)
  800. throw new IllegalArgumentException("Instance type not recognized: "+valuesSplit[j]);
  801. types[j] = type;
  802. }
  803. cond = joinAnd(cond, new ConditionTargetNpcType(types));
  804. }
  805. }
  806. if (cond == null) _log.severe("Unrecognized <target> condition in " + _file);
  807. return cond;
  808. }
  809. protected Condition parseSkillCondition(Node n)
  810. {
  811. NamedNodeMap attrs = n.getAttributes();
  812. Stats stat = Stats.valueOfXml(attrs.getNamedItem("stat").getNodeValue());
  813. return new ConditionSkillStats(stat);
  814. }
  815. protected Condition parseUsingCondition(Node n)
  816. {
  817. Condition cond = null;
  818. NamedNodeMap attrs = n.getAttributes();
  819. for (int i = 0; i < attrs.getLength(); i++)
  820. {
  821. Node a = attrs.item(i);
  822. if ("kind".equalsIgnoreCase(a.getNodeName()))
  823. {
  824. int mask = 0;
  825. StringTokenizer st = new StringTokenizer(a.getNodeValue(), ",");
  826. while (st.hasMoreTokens())
  827. {
  828. int old = mask;
  829. String item = st.nextToken().trim();
  830. if (ItemTable._weaponTypes.containsKey(item))
  831. mask |= ItemTable._weaponTypes.get(item).mask();
  832. if (ItemTable._armorTypes.containsKey(item))
  833. mask |= ItemTable._armorTypes.get(item).mask();
  834. if (old == mask)
  835. _log.info("[parseUsingCondition=\"kind\"] Unknown item type name: "+item);
  836. }
  837. cond = joinAnd(cond, new ConditionUsingItemType(mask));
  838. }
  839. else if ("skill".equalsIgnoreCase(a.getNodeName()))
  840. {
  841. int id = Integer.parseInt(a.getNodeValue());
  842. cond = joinAnd(cond, new ConditionUsingSkill(id));
  843. }
  844. else if ("slotitem".equalsIgnoreCase(a.getNodeName()))
  845. {
  846. StringTokenizer st = new StringTokenizer(a.getNodeValue(), ";");
  847. int id = Integer.parseInt(st.nextToken().trim());
  848. int slot = Integer.parseInt(st.nextToken().trim());
  849. int enchant = 0;
  850. if (st.hasMoreTokens()) enchant = Integer.parseInt(st.nextToken().trim());
  851. cond = joinAnd(cond, new ConditionSlotItemId(slot, id, enchant));
  852. }
  853. else if ("weaponChange".equalsIgnoreCase(a.getNodeName()))
  854. {
  855. boolean val = Boolean.valueOf(a.getNodeValue());
  856. cond = joinAnd(cond, new ConditionChangeWeapon(val));
  857. }
  858. }
  859. if (cond == null) _log.severe("Unrecognized <using> condition in " + _file);
  860. return cond;
  861. }
  862. protected Condition parseGameCondition(Node n)
  863. {
  864. Condition cond = null;
  865. NamedNodeMap attrs = n.getAttributes();
  866. for (int i = 0; i < attrs.getLength(); i++)
  867. {
  868. Node a = attrs.item(i);
  869. if ("skill".equalsIgnoreCase(a.getNodeName()))
  870. {
  871. boolean val = Boolean.valueOf(a.getNodeValue());
  872. cond = joinAnd(cond, new ConditionWithSkill(val));
  873. }
  874. if ("night".equalsIgnoreCase(a.getNodeName()))
  875. {
  876. boolean val = Boolean.valueOf(a.getNodeValue());
  877. cond = joinAnd(cond, new ConditionGameTime(CheckGameTime.NIGHT, val));
  878. }
  879. if ("chance".equalsIgnoreCase(a.getNodeName()))
  880. {
  881. int val = Integer.decode(getValue(a.getNodeValue(), null));
  882. cond = joinAnd(cond, new ConditionGameChance(val));
  883. }
  884. }
  885. if (cond == null) _log.severe("Unrecognized <game> condition in " + _file);
  886. return cond;
  887. }
  888. protected void parseTable(Node n)
  889. {
  890. NamedNodeMap attrs = n.getAttributes();
  891. String name = attrs.getNamedItem("name").getNodeValue();
  892. if (name.charAt(0) != '#') throw new IllegalArgumentException("Table name must start with #");
  893. StringTokenizer data = new StringTokenizer(n.getFirstChild().getNodeValue());
  894. List<String> array = new ArrayList<String>(data.countTokens());
  895. while (data.hasMoreTokens())
  896. array.add(data.nextToken());
  897. setTable(name, array.toArray(new String[array.size()]));
  898. }
  899. protected void parseBeanSet(Node n, StatsSet set, Integer level)
  900. {
  901. String name = n.getAttributes().getNamedItem("name").getNodeValue().trim();
  902. String value = n.getAttributes().getNamedItem("val").getNodeValue().trim();
  903. char ch = value.length() == 0 ? ' ' : value.charAt(0);
  904. if (ch == '#' || ch == '-' || Character.isDigit(ch)) set.set(name,
  905. String.valueOf(getValue(value,
  906. level)));
  907. else set.set(name, value);
  908. }
  909. protected Lambda getLambda(Node n, Object template)
  910. {
  911. Node nval = n.getAttributes().getNamedItem("val");
  912. if (nval != null)
  913. {
  914. String val = nval.getNodeValue();
  915. if (val.charAt(0) == '#')
  916. { // table by level
  917. return new LambdaConst(Double.parseDouble(getTableValue(val)));
  918. }
  919. else if (val.charAt(0) == '$')
  920. {
  921. if (val.equalsIgnoreCase("$player_level"))
  922. return new LambdaStats(LambdaStats.StatsType.PLAYER_LEVEL);
  923. if (val.equalsIgnoreCase("$target_level"))
  924. return new LambdaStats(LambdaStats.StatsType.TARGET_LEVEL);
  925. if (val.equalsIgnoreCase("$player_max_hp"))
  926. return new LambdaStats(LambdaStats.StatsType.PLAYER_MAX_HP);
  927. if (val.equalsIgnoreCase("$player_max_mp"))
  928. return new LambdaStats(LambdaStats.StatsType.PLAYER_MAX_MP);
  929. // try to find value out of item fields
  930. StatsSet set = getStatsSet();
  931. String field = set.getString(val.substring(1));
  932. if (field != null)
  933. {
  934. return new LambdaConst(Double.parseDouble(getValue(field, template)));
  935. }
  936. // failed
  937. throw new IllegalArgumentException("Unknown value " + val);
  938. }
  939. else
  940. {
  941. return new LambdaConst(Double.parseDouble(val));
  942. }
  943. }
  944. LambdaCalc calc = new LambdaCalc();
  945. n = n.getFirstChild();
  946. while (n != null && n.getNodeType() != Node.ELEMENT_NODE)
  947. n = n.getNextSibling();
  948. if (n == null || !"val".equals(n.getNodeName()))
  949. throw new IllegalArgumentException("Value not specified");
  950. for (n = n.getFirstChild(); n != null; n = n.getNextSibling())
  951. {
  952. if (n.getNodeType() != Node.ELEMENT_NODE) continue;
  953. attachLambdaFunc(n, template, calc);
  954. }
  955. return calc;
  956. }
  957. protected String getValue(String value, Object template)
  958. {
  959. // is it a table?
  960. if (value.charAt(0) == '#')
  961. {
  962. if (template instanceof L2Skill) return getTableValue(value);
  963. else if (template instanceof Integer) return getTableValue(value, ((Integer) template).intValue());
  964. else throw new IllegalStateException();
  965. }
  966. return value;
  967. }
  968. protected Condition joinAnd(Condition cond, Condition c)
  969. {
  970. if (cond == null) return c;
  971. if (cond instanceof ConditionLogicAnd)
  972. {
  973. ((ConditionLogicAnd) cond).add(c);
  974. return cond;
  975. }
  976. ConditionLogicAnd and = new ConditionLogicAnd();
  977. and.add(cond);
  978. and.add(c);
  979. return and;
  980. }
  981. }