2
0

NpcTable.java 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808
  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.datatables;
  16. import gnu.trove.TIntObjectHashMap;
  17. import java.sql.Connection;
  18. import java.sql.PreparedStatement;
  19. import java.sql.ResultSet;
  20. import java.util.List;
  21. import java.util.Map;
  22. import java.util.Set;
  23. import java.util.logging.Level;
  24. import java.util.logging.Logger;
  25. import com.l2jserver.Config;
  26. import com.l2jserver.L2DatabaseFactory;
  27. import com.l2jserver.gameserver.model.L2DropCategory;
  28. import com.l2jserver.gameserver.model.L2DropData;
  29. import com.l2jserver.gameserver.model.L2MinionData;
  30. import com.l2jserver.gameserver.model.L2Skill;
  31. import com.l2jserver.gameserver.model.base.ClassId;
  32. import com.l2jserver.gameserver.model.L2NpcAIData;
  33. import com.l2jserver.gameserver.skills.Formulas;
  34. import com.l2jserver.gameserver.skills.Stats;
  35. import com.l2jserver.gameserver.templates.StatsSet;
  36. import com.l2jserver.gameserver.templates.chars.L2NpcTemplate;
  37. import javolution.util.FastList;
  38. import javolution.util.FastMap;
  39. /**
  40. * This class ...
  41. *
  42. * @version $Revision: 1.8.2.6.2.9 $ $Date: 2005/04/06 16:13:25 $
  43. */
  44. public class NpcTable
  45. {
  46. private static Logger _log = Logger.getLogger(NpcTable.class.getName());
  47. private TIntObjectHashMap<L2NpcTemplate> _npcs;
  48. public static NpcTable getInstance()
  49. {
  50. return SingletonHolder._instance;
  51. }
  52. private NpcTable()
  53. {
  54. _npcs = new TIntObjectHashMap<L2NpcTemplate>();
  55. restoreNpcData();
  56. }
  57. private void restoreNpcData()
  58. {
  59. Connection con = null;
  60. try
  61. {
  62. try
  63. {
  64. con = L2DatabaseFactory.getInstance().getConnection();
  65. PreparedStatement statement;
  66. statement = con.prepareStatement("SELECT "
  67. + L2DatabaseFactory.getInstance().safetyString(new String[] { "id", "idTemplate", "name", "serverSideName",
  68. "title", "serverSideTitle", "class", "collision_radius", "collision_height", "level", "sex", "type",
  69. "attackrange", "hp", "mp", "hpreg", "mpreg", "str", "con", "dex", "int", "wit", "men", "exp", "sp", "patk",
  70. "pdef", "matk", "mdef", "atkspd", "aggro", "matkspd", "rhand", "lhand", "armor", "enchant", "walkspd", "runspd",
  71. "isUndead", "absorb_level", "absorb_type",
  72. "drop_herbs" }) + " FROM npc");
  73. ResultSet npcdata = statement.executeQuery();
  74. fillNpcTable(npcdata, false);
  75. npcdata.close();
  76. statement.close();
  77. }
  78. catch (Exception e)
  79. {
  80. _log.log(Level.SEVERE, "NPCTable: Error creating NPC table.", e);
  81. }
  82. if (Config.CUSTOM_NPC_TABLE) // reload certain NPCs
  83. {
  84. try
  85. {
  86. PreparedStatement statement;
  87. statement = con.prepareStatement("SELECT "
  88. + L2DatabaseFactory.getInstance().safetyString(new String[] { "id", "idTemplate", "name", "serverSideName",
  89. "title", "serverSideTitle", "class", "collision_radius", "collision_height", "level", "sex", "type",
  90. "attackrange", "hp", "mp", "hpreg", "mpreg", "str", "con", "dex", "int", "wit", "men", "exp", "sp",
  91. "patk", "pdef", "matk", "mdef", "atkspd", "aggro", "matkspd", "rhand", "lhand", "armor", "enchant", "walkspd",
  92. "runspd", "isUndead", "absorb_level", "absorb_type",
  93. "drop_herbs" }) + " FROM custom_npc");
  94. ResultSet npcdata = statement.executeQuery();
  95. fillNpcTable(npcdata, true);
  96. npcdata.close();
  97. statement.close();
  98. }
  99. catch (Exception e)
  100. {
  101. _log.log(Level.SEVERE, "NPCTable: Error creating custom NPC table.", e);
  102. }
  103. }
  104. try
  105. {
  106. PreparedStatement statement = con.prepareStatement("SELECT npcid, skillid, level FROM npcskills");
  107. ResultSet npcskills = statement.executeQuery();
  108. L2NpcTemplate npcDat = null;
  109. L2Skill npcSkill = null;
  110. while (npcskills.next())
  111. {
  112. int mobId = npcskills.getInt("npcid");
  113. npcDat = _npcs.get(mobId);
  114. if (npcDat == null)
  115. {
  116. _log.warning("NPCTable: Skill data for undefined NPC. npcId: " + mobId);
  117. continue;
  118. }
  119. int skillId = npcskills.getInt("skillid");
  120. int level = npcskills.getInt("level");
  121. if (npcDat.race == null && skillId == 4416)
  122. {
  123. npcDat.setRace(level);
  124. continue;
  125. }
  126. npcSkill = SkillTable.getInstance().getInfo(skillId, level);
  127. if (npcSkill == null)
  128. continue;
  129. npcDat.addSkill(npcSkill);
  130. }
  131. npcskills.close();
  132. statement.close();
  133. }
  134. catch (Exception e)
  135. {
  136. _log.log(Level.SEVERE, "NPCTable: Error reading NPC skills table.", e);
  137. }
  138. if (Config.CUSTOM_NPC_SKILLS_TABLE)
  139. {
  140. try
  141. {
  142. PreparedStatement statement = con.prepareStatement("SELECT npcid, skillid, level FROM custom_npcskills");
  143. ResultSet npcskills = statement.executeQuery();
  144. L2NpcTemplate npcDat = null;
  145. L2Skill npcSkill = null;
  146. while (npcskills.next())
  147. {
  148. int mobId = npcskills.getInt("npcid");
  149. npcDat = _npcs.get(mobId);
  150. if (npcDat == null)
  151. {
  152. _log.warning("Custom NPCTable: Skill data for undefined NPC. npcId: " + mobId);
  153. continue;
  154. }
  155. int skillId = npcskills.getInt("skillid");
  156. int level = npcskills.getInt("level");
  157. if (npcDat.race == null && skillId == 4416)
  158. {
  159. npcDat.setRace(level);
  160. continue;
  161. }
  162. npcSkill = SkillTable.getInstance().getInfo(skillId, level);
  163. if (npcSkill == null)
  164. continue;
  165. npcDat.addSkill(npcSkill);
  166. }
  167. npcskills.close();
  168. statement.close();
  169. }
  170. catch (Exception e)
  171. {
  172. _log.log(Level.SEVERE, "Custom NPCTable: Error reading NPC skills table.", e);
  173. }
  174. }
  175. try
  176. {
  177. PreparedStatement statement2 = con.prepareStatement("SELECT "
  178. + L2DatabaseFactory.getInstance().safetyString(new String[] { "mobId", "itemId", "min", "max", "category", "chance" })
  179. + " FROM droplist ORDER BY mobId, chance DESC");
  180. ResultSet dropData = statement2.executeQuery();
  181. L2DropData dropDat = null;
  182. L2NpcTemplate npcDat = null;
  183. while (dropData.next())
  184. {
  185. int mobId = dropData.getInt("mobId");
  186. npcDat = _npcs.get(mobId);
  187. if (npcDat == null)
  188. {
  189. _log.warning("NPCTable: Drop data for undefined NPC. npcId: " + mobId);
  190. continue;
  191. }
  192. dropDat = new L2DropData();
  193. dropDat.setItemId(dropData.getInt("itemId"));
  194. dropDat.setMinDrop(dropData.getInt("min"));
  195. dropDat.setMaxDrop(dropData.getInt("max"));
  196. dropDat.setChance(dropData.getInt("chance"));
  197. int category = dropData.getInt("category");
  198. if (ItemTable.getInstance().getTemplate(dropDat.getItemId()) == null)
  199. {
  200. _log.warning("Drop data for undefined item template! NpcId: " + mobId+" itemId: "+dropDat.getItemId());
  201. continue;
  202. }
  203. npcDat.addDropData(dropDat, category);
  204. }
  205. dropData.close();
  206. statement2.close();
  207. }
  208. catch (Exception e)
  209. {
  210. _log.log(Level.SEVERE, "NPCTable: Error reading NPC dropdata. ", e);
  211. }
  212. if (Config.CUSTOM_DROPLIST_TABLE)
  213. {
  214. try
  215. {
  216. PreparedStatement statement2 = con.prepareStatement("SELECT "
  217. + L2DatabaseFactory.getInstance().safetyString(new String[] { "mobId", "itemId", "min", "max", "category",
  218. "chance" }) + " FROM custom_droplist ORDER BY mobId, chance DESC");
  219. ResultSet dropData = statement2.executeQuery();
  220. L2DropData dropDat = null;
  221. L2NpcTemplate npcDat = null;
  222. int cCount = 0;
  223. while (dropData.next())
  224. {
  225. int mobId = dropData.getInt("mobId");
  226. npcDat = _npcs.get(mobId);
  227. if (npcDat == null)
  228. {
  229. _log.warning("NPCTable: CUSTOM DROPLIST: Drop data for undefined NPC. npcId: " + mobId);
  230. continue;
  231. }
  232. dropDat = new L2DropData();
  233. dropDat.setItemId(dropData.getInt("itemId"));
  234. dropDat.setMinDrop(dropData.getInt("min"));
  235. dropDat.setMaxDrop(dropData.getInt("max"));
  236. dropDat.setChance(dropData.getInt("chance"));
  237. int category = dropData.getInt("category");
  238. if (ItemTable.getInstance().getTemplate(dropDat.getItemId()) == null)
  239. {
  240. _log.warning("Custom drop data for undefined item template! NpcId: " + mobId+" itemId: "+dropDat.getItemId());
  241. continue;
  242. }
  243. npcDat.addDropData(dropDat, category);
  244. cCount++;
  245. }
  246. dropData.close();
  247. statement2.close();
  248. _log.info("CustomDropList: Added " + cCount + " custom droplist.");
  249. }
  250. catch (Exception e)
  251. {
  252. _log.log(Level.SEVERE, "NPCTable: Error reading NPC custom dropdata.", e);
  253. }
  254. }
  255. try
  256. {
  257. PreparedStatement statement3 = con.prepareStatement("SELECT "
  258. + L2DatabaseFactory.getInstance().safetyString(new String[] { "npc_id", "class_id" }) + " FROM skill_learn");
  259. ResultSet learndata = statement3.executeQuery();
  260. while (learndata.next())
  261. {
  262. int npcId = learndata.getInt("npc_id");
  263. int classId = learndata.getInt("class_id");
  264. L2NpcTemplate npc = getTemplate(npcId);
  265. if (npc == null)
  266. {
  267. _log.warning("NPCTable: Error getting NPC template ID " + npcId + " while trying to load skill trainer data.");
  268. continue;
  269. }
  270. npc.addTeachInfo(ClassId.values()[classId]);
  271. }
  272. learndata.close();
  273. statement3.close();
  274. }
  275. catch (Exception e)
  276. {
  277. _log.log(Level.SEVERE, "NPCTable: Error reading NPC trainer data.", e);
  278. }
  279. try
  280. {
  281. PreparedStatement statement4 = con.prepareStatement("SELECT "
  282. + L2DatabaseFactory.getInstance().safetyString(new String[] { "boss_id", "minion_id", "amount_min", "amount_max" })
  283. + " FROM minions");
  284. ResultSet minionData = statement4.executeQuery();
  285. L2MinionData minionDat = null;
  286. L2NpcTemplate npcDat = null;
  287. int cnt = 0;
  288. while (minionData.next())
  289. {
  290. int raidId = minionData.getInt("boss_id");
  291. npcDat = _npcs.get(raidId);
  292. if (npcDat == null)
  293. {
  294. _log.warning("Minion references undefined boss NPC. Boss NpcId: " + raidId);
  295. continue;
  296. }
  297. minionDat = new L2MinionData();
  298. minionDat.setMinionId(minionData.getInt("minion_id"));
  299. minionDat.setAmountMin(minionData.getInt("amount_min"));
  300. minionDat.setAmountMax(minionData.getInt("amount_max"));
  301. npcDat.addRaidData(minionDat);
  302. cnt++;
  303. }
  304. minionData.close();
  305. statement4.close();
  306. _log.info("NpcTable: Loaded " + cnt + " Minions.");
  307. }
  308. catch (Exception e)
  309. {
  310. _log.log(Level.SEVERE, "NPCTable: Error loading minion data.", e);
  311. }
  312. //-------------------------------------------------------------------
  313. //NPC AI Attributes & Data ...
  314. try
  315. {
  316. PreparedStatement statement10 = con.prepareStatement("SELECT " + L2DatabaseFactory.getInstance().safetyString(new String[] {"npc_id", "primary_attack","skill_chance","canMove","soulshot","spiritshot","sschance","spschance","minrangeskill","minrangechance","maxrangeskill","maxrangechance","ischaos","clan","clan_range","enemyClan","enemyRange","ai_type","dodge"}) + " FROM npcAIData ORDER BY npc_id");
  317. ResultSet NpcAIDataTable = statement10.executeQuery();
  318. L2NpcAIData npcAIDat = null;
  319. L2NpcTemplate npcDat = null;
  320. int cont=0;
  321. while (NpcAIDataTable.next())
  322. {
  323. int npc_id = NpcAIDataTable.getInt("npc_id");
  324. npcDat = _npcs.get(npc_id);
  325. if (npcDat == null)
  326. {
  327. _log.severe("NPCTable: AI Data Error with id : " + npc_id);
  328. continue;
  329. }
  330. npcAIDat = new L2NpcAIData();
  331. npcAIDat.setPrimaryAttack(NpcAIDataTable.getInt("primary_attack"));
  332. npcAIDat.setSkillChance(NpcAIDataTable.getInt("skill_chance"));
  333. npcAIDat.setCanMove(NpcAIDataTable.getInt("canMove"));
  334. npcAIDat.setSoulShot(NpcAIDataTable.getInt("soulshot"));
  335. npcAIDat.setSpiritShot(NpcAIDataTable.getInt("spiritshot"));
  336. npcAIDat.setSoulShotChance(NpcAIDataTable.getInt("sschance"));
  337. npcAIDat.setSpiritShotChance(NpcAIDataTable.getInt("spschance"));
  338. npcAIDat.setIsChaos(NpcAIDataTable.getInt("ischaos"));
  339. npcAIDat.setShortRangeSkill(NpcAIDataTable.getInt("minrangeskill"));
  340. npcAIDat.setShortRangeChance(NpcAIDataTable.getInt("minrangechance"));
  341. npcAIDat.setLongRangeSkill(NpcAIDataTable.getInt("maxrangeskill"));
  342. npcAIDat.setLongRangeChance(NpcAIDataTable.getInt("maxrangechance"));
  343. //npcAIDat.setSwitchRangeChance(NpcAIDataTable.getInt("rangeswitchchance"));
  344. npcAIDat.setClan(NpcAIDataTable.getString("clan"));
  345. npcAIDat.setClanRange(NpcAIDataTable.getInt("clan_range"));
  346. npcAIDat.setEnemyClan(NpcAIDataTable.getString("enemyClan"));
  347. npcAIDat.setEnemyRange(NpcAIDataTable.getInt("enemyRange"));
  348. npcAIDat.setDodge(NpcAIDataTable.getInt("dodge"));
  349. npcAIDat.setAi(NpcAIDataTable.getString("ai_type"));
  350. //npcAIDat.setBaseShldRate(NpcAIDataTable.getInt("baseShldRate"));
  351. //npcAIDat.setBaseShldDef(NpcAIDataTable.getInt("baseShldDef"));
  352. //npcDat.addAIData(npcAIDat);
  353. npcDat.setAIData(npcAIDat);
  354. cont++;
  355. }
  356. NpcAIDataTable.close();
  357. statement10.close();
  358. _log.info("NPC AI Data Table: Loaded " + cont + " AI Data.");
  359. }
  360. catch (Exception e)
  361. {
  362. _log.log(Level.SEVERE, "NPCTable: Error reading NPC AI Data: " + e.getMessage(), e);
  363. }
  364. if (Config.CUSTOM_NPC_TABLE)
  365. {
  366. try
  367. {
  368. PreparedStatement statement = con.prepareStatement("SELECT " + L2DatabaseFactory.getInstance().safetyString(new String[] { "npc_id", "primary_attack", "skill_chance", "canMove", "soulshot", "spiritshot", "sschance", "spschance", "minrangeskill", "minrangechance", "maxrangeskill", "maxrangechance", "ischaos", "clan", "clan_range", "enemyClan", "enemyRange", "ai_type", "dodge" }) + " FROM custom_npcAIData ORDER BY npc_id");
  369. ResultSet NpcAIDataTable = statement.executeQuery();
  370. L2NpcAIData npcAIDat = null;
  371. L2NpcTemplate npcDat = null;
  372. int cont = 0;
  373. while (NpcAIDataTable.next())
  374. {
  375. int npc_id = NpcAIDataTable.getInt("npc_id");
  376. npcDat = _npcs.get(npc_id);
  377. if (npcDat == null)
  378. {
  379. _log.severe("NPCTable: Custom AI Data Error with id : " + npc_id);
  380. continue;
  381. }
  382. npcAIDat = new L2NpcAIData();
  383. npcAIDat.setPrimaryAttack(NpcAIDataTable.getInt("primary_attack"));
  384. npcAIDat.setSkillChance(NpcAIDataTable.getInt("skill_chance"));
  385. npcAIDat.setCanMove(NpcAIDataTable.getInt("canMove"));
  386. npcAIDat.setSoulShot(NpcAIDataTable.getInt("soulshot"));
  387. npcAIDat.setSpiritShot(NpcAIDataTable.getInt("spiritshot"));
  388. npcAIDat.setSoulShotChance(NpcAIDataTable.getInt("sschance"));
  389. npcAIDat.setSpiritShotChance(NpcAIDataTable.getInt("spschance"));
  390. npcAIDat.setIsChaos(NpcAIDataTable.getInt("ischaos"));
  391. npcAIDat.setShortRangeSkill(NpcAIDataTable.getInt("minrangeskill"));
  392. npcAIDat.setShortRangeChance(NpcAIDataTable.getInt("minrangechance"));
  393. npcAIDat.setLongRangeSkill(NpcAIDataTable.getInt("maxrangeskill"));
  394. npcAIDat.setLongRangeChance(NpcAIDataTable.getInt("maxrangechance"));
  395. //npcAIDat.setSwitchRangeChance(NpcAIDataTable.getInt("rangeswitchchance"));
  396. npcAIDat.setClan(NpcAIDataTable.getString("clan"));
  397. npcAIDat.setClanRange(NpcAIDataTable.getInt("clan_range"));
  398. npcAIDat.setEnemyClan(NpcAIDataTable.getString("enemyClan"));
  399. npcAIDat.setEnemyRange(NpcAIDataTable.getInt("enemyRange"));
  400. npcAIDat.setDodge(NpcAIDataTable.getInt("dodge"));
  401. npcAIDat.setAi(NpcAIDataTable.getString("ai_type"));
  402. //npcAIDat.setBaseShldRate(NpcAIDataTable.getInt("baseShldRate"));
  403. //npcAIDat.setBaseShldDef(NpcAIDataTable.getInt("baseShldDef"));
  404. //npcDat.addAIData(npcAIDat);
  405. npcDat.setAIData(npcAIDat);
  406. cont++;
  407. }
  408. NpcAIDataTable.close();
  409. statement.close();
  410. _log.info("NPC AI Data Table: Loaded " + cont + " Custom AI Data.");
  411. }
  412. catch (Exception e)
  413. {
  414. _log.log(Level.SEVERE, "NPCTable: Error reading NPC Custom AI Data: " + e.getMessage(), e);
  415. }
  416. }
  417. }
  418. finally
  419. {
  420. L2DatabaseFactory.close(con);
  421. }
  422. }
  423. private void fillNpcTable(ResultSet NpcData, boolean customData) throws Exception
  424. {
  425. int count = 0;
  426. while (NpcData.next())
  427. {
  428. StatsSet npcDat = new StatsSet();
  429. int id = NpcData.getInt("id");
  430. int idTemp = NpcData.getInt("idTemplate");
  431. assert idTemp < 1000000;
  432. npcDat.set("npcId", id);
  433. npcDat.set("idTemplate", idTemp);
  434. int level = NpcData.getInt("level");
  435. npcDat.set("level", level);
  436. npcDat.set("jClass", NpcData.getString("class"));
  437. npcDat.set("baseShldDef", 0);
  438. npcDat.set("baseShldRate", 0);
  439. npcDat.set("baseCritRate", 38);
  440. npcDat.set("name", NpcData.getString("name"));
  441. npcDat.set("serverSideName", NpcData.getBoolean("serverSideName"));
  442. //npcDat.set("name", "");
  443. npcDat.set("title", NpcData.getString("title"));
  444. npcDat.set("serverSideTitle", NpcData.getBoolean("serverSideTitle"));
  445. npcDat.set("collision_radius", NpcData.getDouble("collision_radius"));
  446. npcDat.set("collision_height", NpcData.getDouble("collision_height"));
  447. npcDat.set("sex", NpcData.getString("sex"));
  448. npcDat.set("type", NpcData.getString("type"));
  449. npcDat.set("baseAtkRange", NpcData.getInt("attackrange"));
  450. npcDat.set("rewardExp", NpcData.getInt("exp"));
  451. npcDat.set("rewardSp", NpcData.getInt("sp"));
  452. npcDat.set("basePAtkSpd", NpcData.getInt("atkspd"));
  453. npcDat.set("baseMAtkSpd", NpcData.getInt("matkspd"));
  454. npcDat.set("aggroRange", NpcData.getInt("aggro"));
  455. npcDat.set("rhand", NpcData.getInt("rhand"));
  456. npcDat.set("lhand", NpcData.getInt("lhand"));
  457. npcDat.set("armor", NpcData.getInt("armor"));
  458. npcDat.set("enchant", NpcData.getInt("enchant"));
  459. npcDat.set("baseWalkSpd", NpcData.getInt("walkspd"));
  460. npcDat.set("baseRunSpd", NpcData.getInt("runspd"));
  461. // constants, until we have stats in DB
  462. npcDat.safeSet("baseSTR", NpcData.getInt("str"), 0, Formulas.MAX_STAT_VALUE, "Loading npc template id: "+NpcData.getInt("idTemplate"));
  463. npcDat.safeSet("baseCON", NpcData.getInt("con"), 0, Formulas.MAX_STAT_VALUE, "Loading npc template id: "+NpcData.getInt("idTemplate"));
  464. npcDat.safeSet("baseDEX", NpcData.getInt("dex"), 0, Formulas.MAX_STAT_VALUE, "Loading npc template id: "+NpcData.getInt("idTemplate"));
  465. npcDat.safeSet("baseINT", NpcData.getInt("int"), 0, Formulas.MAX_STAT_VALUE, "Loading npc template id: "+NpcData.getInt("idTemplate"));
  466. npcDat.safeSet("baseWIT", NpcData.getInt("wit"), 0, Formulas.MAX_STAT_VALUE, "Loading npc template id: "+NpcData.getInt("idTemplate"));
  467. npcDat.safeSet("baseMEN", NpcData.getInt("men"), 0, Formulas.MAX_STAT_VALUE, "Loading npc template id: "+NpcData.getInt("idTemplate"));
  468. npcDat.set("baseHpMax", NpcData.getInt("hp"));
  469. npcDat.set("baseCpMax", 0);
  470. npcDat.set("baseMpMax", NpcData.getInt("mp"));
  471. npcDat.set("baseHpReg", NpcData.getFloat("hpreg") > 0 ? NpcData.getFloat("hpreg") : 1.5 + ((level - 1) / 10.0));
  472. npcDat.set("baseMpReg", NpcData.getFloat("mpreg") > 0 ? NpcData.getFloat("mpreg") : 0.9 + 0.3 * ((level - 1) / 10.0));
  473. npcDat.set("basePAtk", NpcData.getInt("patk"));
  474. npcDat.set("basePDef", NpcData.getInt("pdef"));
  475. npcDat.set("baseMAtk", NpcData.getInt("matk"));
  476. npcDat.set("baseMDef", NpcData.getInt("mdef"));
  477. npcDat.set("isUndead", NpcData.getString("isUndead"));
  478. npcDat.set("absorb_level", NpcData.getString("absorb_level"));
  479. npcDat.set("absorb_type", NpcData.getString("absorb_type"));
  480. npcDat.set("drop_herbs", Boolean.valueOf(NpcData.getString("drop_herbs")));
  481. L2NpcTemplate template = new L2NpcTemplate(npcDat);
  482. template.addVulnerability(Stats.BOW_WPN_VULN, 1);
  483. template.addVulnerability(Stats.CROSSBOW_WPN_VULN, 1);
  484. template.addVulnerability(Stats.BLUNT_WPN_VULN, 1);
  485. template.addVulnerability(Stats.DAGGER_WPN_VULN, 1);
  486. _npcs.put(id, template);
  487. count++;
  488. }
  489. if (!customData)
  490. _log.info("NpcTable: (Re)Loaded " + count + " NPC template(s).");
  491. else
  492. _log.info("NpcTable: (Re)Loaded " + count + " custom NPC template(s).");
  493. }
  494. public void reloadNpc(int id)
  495. {
  496. Connection con = null;
  497. try
  498. {
  499. // save a copy of the old data
  500. L2NpcTemplate old = getTemplate(id);
  501. Map<Integer, L2Skill> skills = new FastMap<Integer, L2Skill>();
  502. if (old.getSkills() != null)
  503. skills.putAll(old.getSkills());
  504. FastList<L2DropCategory> categories = new FastList<L2DropCategory>();
  505. if (old.getDropData() != null)
  506. categories.addAll(old.getDropData());
  507. ClassId[] classIds = null;
  508. if (old.getTeachInfo() != null)
  509. classIds = old.getTeachInfo().clone();
  510. List<L2MinionData> minions = new FastList<L2MinionData>();
  511. if (old.getMinionData() != null)
  512. minions.addAll(old.getMinionData());
  513. // reload the NPC base data
  514. con = L2DatabaseFactory.getInstance().getConnection();
  515. PreparedStatement st = con.prepareStatement("SELECT "
  516. + L2DatabaseFactory.getInstance().safetyString(new String[] { "id", "idTemplate", "name", "serverSideName", "title",
  517. "serverSideTitle", "class", "collision_radius", "collision_height", "level", "sex", "type", "attackrange",
  518. "hp", "mp", "hpreg", "mpreg", "str", "con", "dex", "int", "wit", "men", "exp", "sp", "patk", "pdef", "matk",
  519. "mdef", "atkspd", "aggro", "matkspd", "rhand", "lhand", "armor", "enchant", "walkspd", "runspd",
  520. "isUndead", "absorb_level", "absorb_type", "drop_herbs" })
  521. + " FROM npc WHERE id=?");
  522. st.setInt(1, id);
  523. ResultSet rs = st.executeQuery();
  524. fillNpcTable(rs, false);
  525. if (Config.CUSTOM_NPC_TABLE) // reload certain NPCs
  526. {
  527. st = con.prepareStatement("SELECT "
  528. + L2DatabaseFactory.getInstance().safetyString(new String[] { "id", "idTemplate", "name", "serverSideName",
  529. "title", "serverSideTitle", "class", "collision_radius", "collision_height", "level", "sex", "type",
  530. "attackrange", "hp", "mp", "hpreg", "mpreg", "str", "con", "dex", "int", "wit", "men", "exp", "sp", "patk",
  531. "pdef", "matk", "mdef", "atkspd", "aggro", "matkspd", "rhand", "lhand", "armor", "enchant", "walkspd", "runspd",
  532. "isUndead", "absorb_level", "absorb_type",
  533. "drop_herbs" }) + " FROM custom_npc WHERE id=?");
  534. st.setInt(1, id);
  535. rs = st.executeQuery();
  536. fillNpcTable(rs, true);
  537. }
  538. rs.close();
  539. st.close();
  540. // restore additional data from saved copy
  541. L2NpcTemplate created = getTemplate(id);
  542. for (L2Skill skill : skills.values())
  543. created.addSkill(skill);
  544. if (classIds != null)
  545. for (ClassId classId : classIds)
  546. created.addTeachInfo(classId);
  547. for (L2MinionData minion : minions)
  548. created.addRaidData(minion);
  549. }
  550. catch (Exception e)
  551. {
  552. _log.log(Level.WARNING, "NPCTable: Could not reload data for NPC " + id + ": " + e.getMessage(), e);
  553. }
  554. finally
  555. {
  556. L2DatabaseFactory.close(con);
  557. }
  558. }
  559. // just wrapper
  560. public void reloadAllNpc()
  561. {
  562. restoreNpcData();
  563. }
  564. public void saveNpc(StatsSet npc)
  565. {
  566. Connection con = null;
  567. try
  568. {
  569. con = L2DatabaseFactory.getInstance().getConnection();
  570. Map<String, Object> set = npc.getSet();
  571. int length = 0;
  572. for (Object obj : set.keySet())
  573. {
  574. // 15 is just guessed npc name length
  575. length += ((String) obj).length() + 7 + 15;
  576. }
  577. final StringBuilder sbValues = new StringBuilder(length);
  578. for (Object obj : set.keySet())
  579. {
  580. final String name = (String) obj;
  581. if (!name.equalsIgnoreCase("npcId"))
  582. {
  583. if (sbValues.length() > 0)
  584. {
  585. sbValues.append(", ");
  586. }
  587. sbValues.append(name);
  588. sbValues.append(" = '");
  589. sbValues.append(set.get(name));
  590. sbValues.append('\'');
  591. }
  592. }
  593. int updated = 0;
  594. if (Config.CUSTOM_NPC_TABLE)
  595. {
  596. final StringBuilder sbQuery = new StringBuilder(sbValues.length() + 28);
  597. sbQuery.append("UPDATE custom_npc SET ");
  598. sbQuery.append(sbValues.toString());
  599. sbQuery.append(" WHERE id = ?");
  600. PreparedStatement statement = con.prepareStatement(sbQuery.toString());
  601. statement.setInt(1, npc.getInteger("npcId"));
  602. updated = statement.executeUpdate();
  603. statement.close();
  604. }
  605. if (updated == 0)
  606. {
  607. final StringBuilder sbQuery = new StringBuilder(sbValues.length() + 28);
  608. sbQuery.append("UPDATE npc SET ");
  609. sbQuery.append(sbValues.toString());
  610. sbQuery.append(" WHERE id = ?");
  611. PreparedStatement statement = con.prepareStatement(sbQuery.toString());
  612. statement.setInt(1, npc.getInteger("npcId"));
  613. statement.executeUpdate();
  614. statement.close();
  615. }
  616. }
  617. catch (Exception e)
  618. {
  619. _log.log(Level.WARNING, "NPCTable: Could not store new NPC data in database: " + e.getMessage(), e);
  620. }
  621. finally
  622. {
  623. L2DatabaseFactory.close(con);
  624. }
  625. }
  626. public void replaceTemplate(L2NpcTemplate npc)
  627. {
  628. _npcs.put(npc.npcId, npc);
  629. }
  630. public L2NpcTemplate getTemplate(int id)
  631. {
  632. return _npcs.get(id);
  633. }
  634. public L2NpcTemplate getTemplateByName(String name)
  635. {
  636. for (Object npcTemplate : _npcs.getValues())
  637. if (((L2NpcTemplate)npcTemplate).name.equalsIgnoreCase(name))
  638. return (L2NpcTemplate) npcTemplate;
  639. return null;
  640. }
  641. public L2NpcTemplate[] getAllOfLevel(int lvl)
  642. {
  643. List<L2NpcTemplate> list = new FastList<L2NpcTemplate>();
  644. for (Object t : _npcs.getValues())
  645. if (((L2NpcTemplate)t).level == lvl)
  646. list.add((L2NpcTemplate) t);
  647. return list.toArray(new L2NpcTemplate[list.size()]);
  648. }
  649. public L2NpcTemplate[] getAllMonstersOfLevel(int lvl)
  650. {
  651. List<L2NpcTemplate> list = new FastList<L2NpcTemplate>();
  652. for (Object t : _npcs.getValues())
  653. if (((L2NpcTemplate)t).level == lvl && "L2Monster".equals(((L2NpcTemplate)t).type))
  654. list.add((L2NpcTemplate) t);
  655. return list.toArray(new L2NpcTemplate[list.size()]);
  656. }
  657. public L2NpcTemplate[] getAllNpcStartingWith(String letter)
  658. {
  659. List<L2NpcTemplate> list = new FastList<L2NpcTemplate>();
  660. for (Object t : _npcs.getValues())
  661. if (((L2NpcTemplate)t).name.startsWith(letter) && "L2Npc".equals(((L2NpcTemplate)t).type))
  662. list.add((L2NpcTemplate) t);
  663. return list.toArray(new L2NpcTemplate[list.size()]);
  664. }
  665. /**
  666. * @param classType
  667. * @return
  668. */
  669. public Set<Integer> getAllNpcOfClassType(String classType)
  670. {
  671. return null;
  672. }
  673. /**
  674. * @param class1
  675. * @return
  676. */
  677. public Set<Integer> getAllNpcOfL2jClass(Class<?> clazz)
  678. {
  679. return null;
  680. }
  681. /**
  682. * @param aiType
  683. * @return
  684. */
  685. public Set<Integer> getAllNpcOfAiType(String aiType)
  686. {
  687. return null;
  688. }
  689. @SuppressWarnings("synthetic-access")
  690. private static class SingletonHolder
  691. {
  692. protected static final NpcTable _instance = new NpcTable();
  693. }
  694. }