/* * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ package com.l2jserver.gameserver.datatables; import gnu.trove.map.hash.TIntObjectHashMap; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.logging.Level; import java.util.logging.Logger; import com.l2jserver.Config; import com.l2jserver.L2DatabaseFactory; import com.l2jserver.gameserver.model.Elementals; import com.l2jserver.gameserver.model.L2DropData; import com.l2jserver.gameserver.model.L2MinionData; import com.l2jserver.gameserver.model.L2NpcAIData; import com.l2jserver.gameserver.model.StatsSet; import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate; import com.l2jserver.gameserver.model.base.ClassId; import com.l2jserver.gameserver.model.quest.Quest; import com.l2jserver.gameserver.model.quest.Quest.QuestEventType; import com.l2jserver.gameserver.model.skills.L2Skill; import com.l2jserver.gameserver.model.stats.BaseStats; public class NpcTable { private static final Logger _log = Logger.getLogger(NpcTable.class.getName()); private final TIntObjectHashMap _npcs = new TIntObjectHashMap(); protected NpcTable() { _npcs.clear(); restoreNpcData(); } private void restoreNpcData() { loadNpcs(0); loadNpcsSkills(0); loadNpcsDrop(0); loadNpcsSkillLearn(0); loadMinions(0); loadNpcsAI(0); loadNpcsElement(0); } /** * @param NpcData * @throws Exception */ private void fillNpcTable(ResultSet NpcData) throws Exception { StatsSet npcDat = new StatsSet(); int id = NpcData.getInt("id"); int idTemp = NpcData.getInt("idTemplate"); assert idTemp < 1000000; npcDat.set("npcId", id); npcDat.set("idTemplate", idTemp); int level = NpcData.getInt("level"); npcDat.set("level", level); npcDat.set("client_class", NpcData.getString("class")); npcDat.set("baseShldDef", 0); npcDat.set("baseShldRate", 0); npcDat.set("baseCritRate", NpcData.getInt("critical")); npcDat.set("name", NpcData.getString("name")); npcDat.set("serverSideName", NpcData.getBoolean("serverSideName")); npcDat.set("title", NpcData.getString("title")); npcDat.set("serverSideTitle", NpcData.getBoolean("serverSideTitle")); npcDat.set("collision_radius", NpcData.getDouble("collision_radius")); npcDat.set("collision_height", NpcData.getDouble("collision_height")); npcDat.set("sex", NpcData.getString("sex")); npcDat.set("type", NpcData.getString("type")); npcDat.set("baseAtkRange", NpcData.getInt("attackrange")); npcDat.set("rewardExp", NpcData.getInt("exp")); npcDat.set("rewardSp", NpcData.getInt("sp")); npcDat.set("basePAtkSpd", NpcData.getInt("atkspd")); npcDat.set("baseMAtkSpd", NpcData.getInt("matkspd")); npcDat.set("rhand", NpcData.getInt("rhand")); npcDat.set("lhand", NpcData.getInt("lhand")); npcDat.set("enchant", NpcData.getInt("enchant")); npcDat.set("baseWalkSpd", NpcData.getInt("walkspd")); npcDat.set("baseRunSpd", NpcData.getInt("runspd")); // constants, until we have stats in DB npcDat.safeSet("baseSTR", NpcData.getInt("str"), 0, BaseStats.MAX_STAT_VALUE, "Loading npc template id: " + NpcData.getInt("idTemplate")); npcDat.safeSet("baseCON", NpcData.getInt("con"), 0, BaseStats.MAX_STAT_VALUE, "Loading npc template id: " + NpcData.getInt("idTemplate")); npcDat.safeSet("baseDEX", NpcData.getInt("dex"), 0, BaseStats.MAX_STAT_VALUE, "Loading npc template id: " + NpcData.getInt("idTemplate")); npcDat.safeSet("baseINT", NpcData.getInt("int"), 0, BaseStats.MAX_STAT_VALUE, "Loading npc template id: " + NpcData.getInt("idTemplate")); npcDat.safeSet("baseWIT", NpcData.getInt("wit"), 0, BaseStats.MAX_STAT_VALUE, "Loading npc template id: " + NpcData.getInt("idTemplate")); npcDat.safeSet("baseMEN", NpcData.getInt("men"), 0, BaseStats.MAX_STAT_VALUE, "Loading npc template id: " + NpcData.getInt("idTemplate")); npcDat.set("baseHpMax", NpcData.getDouble("hp")); npcDat.set("baseCpMax", 0); npcDat.set("baseMpMax", NpcData.getDouble("mp")); npcDat.set("baseHpReg", NpcData.getFloat("hpreg") > 0 ? NpcData.getFloat("hpreg") : 1.5 + ((level - 1) / 10.0)); npcDat.set("baseMpReg", NpcData.getFloat("mpreg") > 0 ? NpcData.getFloat("mpreg") : 0.9 + (0.3 * ((level - 1) / 10.0))); npcDat.set("basePAtk", NpcData.getInt("patk")); npcDat.set("basePDef", NpcData.getInt("pdef")); npcDat.set("baseMAtk", NpcData.getInt("matk")); npcDat.set("baseMDef", NpcData.getInt("mdef")); npcDat.set("dropHerbGroup", NpcData.getInt("dropHerbGroup")); // Default element resists npcDat.set("baseFireRes", 20); npcDat.set("baseWindRes", 20); npcDat.set("baseWaterRes", 20); npcDat.set("baseEarthRes", 20); npcDat.set("baseHolyRes", 20); npcDat.set("baseDarkRes", 20); _npcs.put(id, new L2NpcTemplate(npcDat)); } /** * @param id of the NPC to reload. */ public void reloadNpc(int id) { Map> quests = null; try { // save a copy of the old data L2NpcTemplate old = getTemplate(id); if (old != null) { quests = old.getEventQuests(); } loadNpcs(id); loadNpcsSkills(id); loadNpcsDrop(id); loadNpcsSkillLearn(id); loadMinions(id); loadNpcsAI(id); loadNpcsElement(id); // restore additional data from saved copy L2NpcTemplate created = getTemplate(id); if ((old != null) && (created != null)) { created.getEventQuests().putAll(quests); } } catch (Exception e) { _log.log(Level.WARNING, getClass().getSimpleName() + ": Could not reload data for NPC " + id + ": " + e.getMessage(), e); } } /** * Just wrapper. */ public void reloadAllNpc() { restoreNpcData(); } /** * @param npc */ public void saveNpc(StatsSet npc) { final Map set = npc.getSet(); int length = 0; for (Object obj : set.keySet()) { // 15 is just guessed npc name length length += ((String) obj).length() + 7 + 15; } final StringBuilder npcSb = new StringBuilder(length); final StringBuilder npcAiSb = new StringBuilder(30); String attribute; String value; for (Entry entry : set.entrySet()) { attribute = entry.getKey(); value = String.valueOf(entry.getValue()); switch (attribute) { case "npcId": break; case "aggro": case "showName": case "targetable": { appendEntry(npcAiSb, attribute, value); break; } default: { appendEntry(npcSb, attribute, value); } } } Connection con = null; try { con = L2DatabaseFactory.getInstance().getConnection(); int updated = 0; final int npcId = npc.getInteger("npcId"); if (Config.CUSTOM_NPC_TABLE) { updated = performUpdate(npcSb, "custom_npc", "id", npcId, con); performUpdate(npcAiSb, "custom_npcaidata", "npcId", npcId, con); } if (updated == 0) { performUpdate(npcSb, "npc", "id", npcId, con); performUpdate(npcAiSb, "npcaidata", "npcId", npcId, con); } } catch (Exception e) { _log.log(Level.WARNING, getClass().getSimpleName() + ": Could not store new NPC data in database: " + e.getMessage(), e); } finally { L2DatabaseFactory.close(con); } } /** * @param sb the string builder to append the attribute and value. * @param attribute the attribute to append. * @param value the value to append. */ private final void appendEntry(StringBuilder sb, String attribute, String value) { if (sb.length() > 0) { sb.append(", "); } sb.append(attribute); sb.append(" = '"); sb.append(value); sb.append('\''); } /** * @param sb the string builder with the parameters * @param table the table to update. * @param key the key of the table. * @param npcId the Npc Id. * @param con the current database connection. * @return the count of updated NPCs. * @throws SQLException the SQL exception. */ private final int performUpdate(StringBuilder sb, String table, String key, int npcId, Connection con) throws SQLException { int updated = 0; if ((sb != null) && !sb.toString().isEmpty()) { final StringBuilder sbQuery = new StringBuilder(sb.length() + 28); sbQuery.append("UPDATE "); sbQuery.append(table); sbQuery.append(" SET "); sbQuery.append(sb.toString()); sbQuery.append(" WHERE "); sbQuery.append(key); sbQuery.append(" = ?"); final PreparedStatement statement = con.prepareStatement(sbQuery.toString()); statement.setInt(1, npcId); updated = statement.executeUpdate(); statement.close(); } return updated; } /** * @param id the template Id to get. * @return the template for the given id. */ public L2NpcTemplate getTemplate(int id) { return _npcs.get(id); } /** * @param name of the template to get. * @return the template for the given name. */ public L2NpcTemplate getTemplateByName(String name) { for (L2NpcTemplate npcTemplate : _npcs.values(new L2NpcTemplate[0])) { if (npcTemplate.getName().equalsIgnoreCase(name)) { return npcTemplate; } } return null; } /** * @param lvls of all the templates to get. * @return the template list for the given level. */ public List getAllOfLevel(int... lvls) { final List list = new ArrayList<>(); for (int lvl : lvls) { for (L2NpcTemplate t : _npcs.values(new L2NpcTemplate[0])) { if (t.getLevel() == lvl) { list.add(t); } } } return list; } /** * @param lvls of all the monster templates to get. * @return the template list for the given level. */ public List getAllMonstersOfLevel(int... lvls) { final List list = new ArrayList<>(); for (int lvl : lvls) { for (L2NpcTemplate t : _npcs.values(new L2NpcTemplate[0])) { if ((t.getLevel() == lvl) && t.isType("L2Monster")) { list.add(t); } } } return list; } /** * @param letters of all the NPC templates which its name start with. * @return the template list for the given letter. */ public List getAllNpcStartingWith(String... letters) { final List list = new ArrayList<>(); for (String letter : letters) { for (L2NpcTemplate t : _npcs.values(new L2NpcTemplate[0])) { if (t.getName().startsWith(letter) && t.isType("L2Npc")) { list.add(t); } } } return list; } /** * @param classTypes of all the templates to get. * @return the template list for the given class type. */ public List getAllNpcOfClassType(String... classTypes) { final List list = new ArrayList<>(); for (String classType : classTypes) { for (L2NpcTemplate t : _npcs.values(new L2NpcTemplate[0])) { if (t.isType(classType)) { list.add(t); } } } return list; } /** * Id equals to zero or lesser means all. * @param id of the NPC to load. */ public void loadNpcs(int id) { Connection con = null; try { con = L2DatabaseFactory.getInstance().getConnection(); PreparedStatement statement; if (id > 0) { statement = con.prepareStatement("SELECT * FROM npc WHERE id = ?"); statement.setInt(1, id); } else { statement = con.prepareStatement("SELECT * FROM npc ORDER BY id"); } ResultSet rset = statement.executeQuery(); int cont = 0; int cCont = 0; while (rset.next()) { fillNpcTable(rset); cont++; } rset.close(); statement.close(); if (Config.CUSTOM_NPC_TABLE) { if (id > 0) { statement = con.prepareStatement("SELECT * FROM custom_npc WHERE id = ?"); statement.setInt(1, id); } else { statement = con.prepareStatement("SELECT * FROM custom_npc ORDER BY id"); } rset = statement.executeQuery(); while (rset.next()) { fillNpcTable(rset); cCont++; } rset.close(); statement.close(); } _log.info(getClass().getSimpleName() + ": Loaded " + cont + " (Custom: " + cCont + ") NPC template(s)."); } catch (Exception e) { _log.log(Level.SEVERE, getClass().getSimpleName() + ": Error creating NPC table.", e); } finally { L2DatabaseFactory.close(con); } } /** * Id equals to zero or lesser means all. * @param id of the NPC to load it's skills. */ public void loadNpcsSkills(int id) { Connection con = null; try { con = L2DatabaseFactory.getInstance().getConnection(); PreparedStatement statement; if (id > 0) { statement = con.prepareStatement("SELECT * FROM npcskills WHERE npcid = ?"); statement.setInt(1, id); } else { statement = con.prepareStatement("SELECT * FROM npcskills ORDER BY npcid"); } ResultSet rset = statement.executeQuery(); int cont = 0; int cCont = 0; L2NpcTemplate npcDat = null; L2Skill npcSkill = null; while (rset.next()) { int mobId = rset.getInt("npcid"); npcDat = _npcs.get(mobId); if (npcDat == null) { _log.warning(getClass().getSimpleName() + ": Skill data for undefined NPC. npcId: " + mobId); continue; } int skillId = rset.getInt("skillid"); int level = rset.getInt("level"); if (skillId == L2Skill.SKILL_NPC_RACE) { npcDat.setRace(level); continue; } npcSkill = SkillTable.getInstance().getInfo(skillId, level); if (npcSkill == null) { continue; } cont++; npcDat.addSkill(npcSkill); } rset.close(); statement.close(); if (Config.CUSTOM_NPC_SKILLS_TABLE) { if (id > 0) { statement = con.prepareStatement("SELECT * FROM custom_npcskills WHERE npcid = ?"); statement.setInt(1, id); } else { statement = con.prepareStatement("SELECT * FROM custom_npcskills ORDER BY npcid"); } rset = statement.executeQuery(); while (rset.next()) { int mobId = rset.getInt("npcid"); npcDat = _npcs.get(mobId); if (npcDat == null) { _log.warning("Custom " + getClass().getSimpleName() + ": Skill data for undefined NPC. npcId: " + mobId); continue; } int skillId = rset.getInt("skillid"); int level = rset.getInt("level"); if ((npcDat.getRace() == null) && (skillId == L2Skill.SKILL_NPC_RACE)) { npcDat.setRace(level); continue; } npcSkill = SkillTable.getInstance().getInfo(skillId, level); if (npcSkill == null) { continue; } cCont++; npcDat.addSkill(npcSkill); } rset.close(); statement.close(); } _log.info(getClass().getSimpleName() + ": Loaded " + cont + " (Custom: " + cCont + ") npc skills."); } catch (Exception e) { _log.log(Level.SEVERE, getClass().getSimpleName() + ": Error reading NPC skills table.", e); } finally { L2DatabaseFactory.close(con); } } /** * Id equals to zero or lesser means all. * @param id of the NPC to load it's drops. */ public void loadNpcsDrop(int id) { Connection con = null; try { con = L2DatabaseFactory.getInstance().getConnection(); PreparedStatement statement = null; if (id > 0) { statement = con.prepareStatement("SELECT * FROM droplist WHERE mobId = ? ORDER BY mobId, chance DESC"); statement.setInt(1, id); } else { statement = con.prepareStatement("SELECT * FROM droplist ORDER BY mobId, chance DESC"); } ResultSet rset = statement.executeQuery(); L2DropData dropDat = null; L2NpcTemplate npcDat = null; int cont = 0; int cCont = 0; while (rset.next()) { int mobId = rset.getInt("mobId"); npcDat = _npcs.get(mobId); if (npcDat == null) { _log.warning(getClass().getSimpleName() + ": Drop data for undefined NPC. npcId: " + mobId); continue; } dropDat = new L2DropData(); dropDat.setItemId(rset.getInt("itemId")); dropDat.setMinDrop(rset.getInt("min")); dropDat.setMaxDrop(rset.getInt("max")); dropDat.setChance(rset.getInt("chance")); int category = rset.getInt("category"); if (ItemTable.getInstance().getTemplate(dropDat.getItemId()) == null) { _log.warning(getClass().getSimpleName() + ": Drop data for undefined item template! NpcId: " + mobId + " itemId: " + dropDat.getItemId()); continue; } cont++; npcDat.addDropData(dropDat, category); } rset.close(); statement.close(); if (Config.CUSTOM_DROPLIST_TABLE) { if (id > 0) { statement = con.prepareStatement("SELECT * FROM custom_droplist WHERE mobId = ? ORDER BY mobId, chance DESC"); statement.setInt(1, id); } else { statement = con.prepareStatement("SELECT * FROM custom_droplist ORDER BY mobId, chance DESC"); } rset = statement.executeQuery(); int mobId; int category; while (rset.next()) { mobId = rset.getInt("mobId"); npcDat = _npcs.get(mobId); if (npcDat == null) { _log.warning(getClass().getSimpleName() + ": CUSTOM DROPLIST: Drop data for undefined NPC. npcId: " + mobId); continue; } dropDat = new L2DropData(); dropDat.setItemId(rset.getInt("itemId")); dropDat.setMinDrop(rset.getInt("min")); dropDat.setMaxDrop(rset.getInt("max")); dropDat.setChance(rset.getInt("chance")); category = rset.getInt("category"); if (ItemTable.getInstance().getTemplate(dropDat.getItemId()) == null) { _log.warning(getClass().getSimpleName() + ": Custom drop data for undefined item template! NpcId: " + mobId + " itemId: " + dropDat.getItemId()); continue; } npcDat.addDropData(dropDat, category); cCont++; } rset.close(); statement.close(); } _log.info(getClass().getSimpleName() + ": Loaded " + cont + " (Custom: " + cCont + ") drops."); } catch (Exception e) { _log.log(Level.SEVERE, getClass().getSimpleName() + ": Error reading NPC dropdata. ", e); } finally { L2DatabaseFactory.close(con); } } /** * Id equals to zero or lesser means all. * @param id of the NPC to load it's skill learn list. */ private void loadNpcsSkillLearn(int id) { Connection con = null; try { con = L2DatabaseFactory.getInstance().getConnection(); PreparedStatement statement; if (id > 0) { statement = con.prepareStatement("SELECT * FROM skill_learn WHERE npc_id = ?"); statement.setInt(1, id); } else { statement = con.prepareStatement("SELECT * FROM skill_learn"); } ResultSet rset = statement.executeQuery(); int cont = 0; int npcId; int classId; L2NpcTemplate npc; while (rset.next()) { npcId = rset.getInt("npc_id"); classId = rset.getInt("class_id"); npc = getTemplate(npcId); if (npc == null) { _log.warning(getClass().getSimpleName() + ": Error getting NPC template ID " + npcId + " while trying to load skill trainer data."); continue; } cont++; npc.addTeachInfo(ClassId.getClassId(classId)); } rset.close(); statement.close(); _log.info(getClass().getSimpleName() + ": Loaded " + cont + " Skill Learn."); } catch (Exception e) { _log.log(Level.SEVERE, getClass().getSimpleName() + ": Error reading NPC trainer data.", e); } finally { L2DatabaseFactory.close(con); } } /** * Id equals to zero or lesser means all. * @param id of the NPC to load it's minions. */ public void loadMinions(int id) { Connection con = null; try { con = L2DatabaseFactory.getInstance().getConnection(); PreparedStatement statement = null; if (id > 0) { statement = con.prepareStatement("SELECT * FROM minions WHERE boss_id = ?"); statement.setInt(1, id); } else { statement = con.prepareStatement("SELECT * FROM minions ORDER BY boss_id"); } ResultSet rset = statement.executeQuery(); L2MinionData minionDat = null; L2NpcTemplate npcDat = null; int cnt = 0; int raidId; while (rset.next()) { raidId = rset.getInt("boss_id"); npcDat = _npcs.get(raidId); if (npcDat == null) { _log.warning(getClass().getSimpleName() + ": Minion references undefined boss NPC. Boss NpcId: " + raidId); continue; } minionDat = new L2MinionData(); minionDat.setMinionId(rset.getInt("minion_id")); minionDat.setAmountMin(rset.getInt("amount_min")); minionDat.setAmountMax(rset.getInt("amount_max")); npcDat.addRaidData(minionDat); cnt++; } rset.close(); statement.close(); _log.info(getClass().getSimpleName() + ": Loaded " + cnt + " Minions."); } catch (Exception e) { _log.log(Level.SEVERE, getClass().getSimpleName() + ": Error loading minion data.", e); } finally { L2DatabaseFactory.close(con); } } /** * Id equals to zero or lesser means all. * @param id of the NPC to load it's AI data. */ public void loadNpcsAI(int id) { Connection con = null; try { con = L2DatabaseFactory.getInstance().getConnection(); PreparedStatement statement = null; if (id > 0) { statement = con.prepareStatement("SELECT * FROM npcaidata WHERE npcId = ?"); statement.setInt(1, id); } else { statement = con.prepareStatement("SELECT * FROM npcaidata ORDER BY npcId"); } ResultSet rset = statement.executeQuery(); L2NpcAIData npcAIDat = null; L2NpcTemplate npcDat = null; int cont = 0; int cCont = 0; int npcId; while (rset.next()) { npcId = rset.getInt("npcId"); npcDat = _npcs.get(npcId); if (npcDat == null) { _log.severe(getClass().getSimpleName() + ": AI Data Error with id : " + npcId); continue; } npcAIDat = new L2NpcAIData(); npcAIDat.setPrimarySkillId(rset.getInt("primarySkillId")); npcAIDat.setMinSkillChance(rset.getInt("minSkillChance")); npcAIDat.setMaxSkillChance(rset.getInt("maxSkillChance")); npcAIDat.setAggro(rset.getInt("aggro")); npcAIDat.setCanMove(rset.getInt("canMove")); npcAIDat.setShowName(rset.getBoolean("showName")); npcAIDat.setTargetable(rset.getBoolean("targetable")); npcAIDat.setSoulShot(rset.getInt("soulshot")); npcAIDat.setSpiritShot(rset.getInt("spiritshot")); npcAIDat.setSoulShotChance(rset.getInt("ssChance")); npcAIDat.setSpiritShotChance(rset.getInt("spsChance")); npcAIDat.setIsChaos(rset.getInt("isChaos")); npcAIDat.setShortRangeSkill(rset.getInt("minRangeSkill")); npcAIDat.setShortRangeChance(rset.getInt("minRangeChance")); npcAIDat.setLongRangeSkill(rset.getInt("maxRangeSkill")); npcAIDat.setLongRangeChance(rset.getInt("maxRangeChance")); npcAIDat.setClan(rset.getString("clan")); npcAIDat.setClanRange(rset.getInt("clanRange")); npcAIDat.setEnemyClan(rset.getString("enemyClan")); npcAIDat.setEnemyRange(rset.getInt("enemyRange")); npcAIDat.setDodge(rset.getInt("dodge")); npcAIDat.setAi(rset.getString("aiType")); npcDat.setAIData(npcAIDat); cont++; } rset.close(); statement.close(); if (Config.CUSTOM_NPC_TABLE) { if (id > 0) { statement = con.prepareStatement("SELECT * FROM custom_npcaidata WHERE npcId = ?"); statement.setInt(1, id); } else { statement = con.prepareStatement("SELECT * FROM custom_npcaidata ORDER BY npcId"); } rset = statement.executeQuery(); while (rset.next()) { npcId = rset.getInt("npcId"); npcDat = _npcs.get(npcId); if (npcDat == null) { _log.severe(getClass().getSimpleName() + ": Custom AI Data Error with id : " + npcId); continue; } npcAIDat = new L2NpcAIData(); npcAIDat.setPrimarySkillId(rset.getInt("primarySkillId")); npcAIDat.setMinSkillChance(rset.getInt("minSkillChance")); npcAIDat.setMaxSkillChance(rset.getInt("maxSkillChance")); npcAIDat.setAggro(rset.getInt("aggro")); npcAIDat.setCanMove(rset.getInt("canMove")); npcAIDat.setShowName(rset.getBoolean("showName")); npcAIDat.setTargetable(rset.getBoolean("targetable")); npcAIDat.setSoulShot(rset.getInt("soulshot")); npcAIDat.setSpiritShot(rset.getInt("spiritshot")); npcAIDat.setSoulShotChance(rset.getInt("ssChance")); npcAIDat.setSpiritShotChance(rset.getInt("spsChance")); npcAIDat.setIsChaos(rset.getInt("isChaos")); npcAIDat.setShortRangeSkill(rset.getInt("minRangeSkill")); npcAIDat.setShortRangeChance(rset.getInt("minRangeChance")); npcAIDat.setLongRangeSkill(rset.getInt("maxRangeSkill")); npcAIDat.setLongRangeChance(rset.getInt("maxRangeChance")); npcAIDat.setClan(rset.getString("clan")); npcAIDat.setClanRange(rset.getInt("clanRange")); npcAIDat.setEnemyClan(rset.getString("enemyClan")); npcAIDat.setEnemyRange(rset.getInt("enemyRange")); npcAIDat.setDodge(rset.getInt("dodge")); npcAIDat.setAi(rset.getString("aiType")); npcDat.setAIData(npcAIDat); cCont++; } rset.close(); statement.close(); } _log.info(getClass().getSimpleName() + ": Loaded " + cont + " (Custom: " + cCont + ") AI Data."); } catch (Exception e) { _log.log(Level.SEVERE, getClass().getSimpleName() + ": Error reading NPC AI Data: " + e.getMessage(), e); } finally { L2DatabaseFactory.close(con); } } /** * Id equals to zero or lesser means all. * @param id of the NPC to load it's element data. */ public void loadNpcsElement(int id) { Connection con = null; try { con = L2DatabaseFactory.getInstance().getConnection(); PreparedStatement statement = null; if (id > 0) { statement = con.prepareStatement("SELECT * FROM npc_elementals WHERE npc_id = ?"); statement.setInt(1, id); } else { statement = con.prepareStatement("SELECT * FROM npc_elementals ORDER BY npc_id"); } ResultSet rset = statement.executeQuery(); L2NpcTemplate npcDat = null; int cont = 0; int cCount = 0; int npcId; while (rset.next()) { npcId = rset.getInt("npc_id"); npcDat = _npcs.get(npcId); if (npcDat == null) { _log.severe("NPCElementals: Elementals Error with id : " + npcId); continue; } switch (rset.getByte("elemAtkType")) { case Elementals.FIRE: npcDat.setBaseFire(rset.getInt("elemAtkValue")); break; case Elementals.WATER: npcDat.setBaseWater(rset.getInt("elemAtkValue")); break; case Elementals.EARTH: npcDat.setBaseEarth(rset.getInt("elemAtkValue")); break; case Elementals.WIND: npcDat.setBaseWind(rset.getInt("elemAtkValue")); break; case Elementals.HOLY: npcDat.setBaseHoly(rset.getInt("elemAtkValue")); break; case Elementals.DARK: npcDat.setBaseDark(rset.getInt("elemAtkValue")); break; default: _log.severe("NPCElementals: Elementals Error with id : " + npcId + "; unknown elementType: " + rset.getByte("elemAtkType")); continue; } npcDat.setBaseFireRes(rset.getInt("fireDefValue")); npcDat.setBaseWaterRes(rset.getInt("waterDefValue")); npcDat.setBaseEarthRes(rset.getInt("earthDefValue")); npcDat.setBaseWindRes(rset.getInt("windDefValue")); npcDat.setBaseHolyRes(rset.getInt("holyDefValue")); npcDat.setBaseDarkRes(rset.getInt("darkDefValue")); cont++; } rset.close(); statement.close(); if (Config.CUSTOM_NPC_TABLE) { if (id > 0) { statement = con.prepareStatement("SELECT * FROM custom_npc_elementals WHERE npc_id = ?"); statement.setInt(1, id); } else { statement = con.prepareStatement("SELECT * FROM custom_npc_elementals ORDER BY npc_id"); } rset = statement.executeQuery(); while (rset.next()) { npcId = rset.getInt("npc_id"); npcDat = _npcs.get(npcId); if (npcDat == null) { _log.severe("NPCElementals: Custom Elementals Error with id : " + npcId); continue; } switch (rset.getByte("elemAtkType")) { case Elementals.FIRE: npcDat.setBaseFire(rset.getInt("elemAtkValue")); break; case Elementals.WATER: npcDat.setBaseWater(rset.getInt("elemAtkValue")); break; case Elementals.EARTH: npcDat.setBaseEarth(rset.getInt("elemAtkValue")); break; case Elementals.WIND: npcDat.setBaseWind(rset.getInt("elemAtkValue")); break; case Elementals.HOLY: npcDat.setBaseHoly(rset.getInt("elemAtkValue")); break; case Elementals.DARK: npcDat.setBaseDark(rset.getInt("elemAtkValue")); break; default: _log.severe("NPCElementals: Custom Elementals Error with id : " + npcId + "; unknown elementType: " + rset.getByte("elemAtkType")); continue; } npcDat.setBaseFireRes(rset.getInt("fireDefValue")); npcDat.setBaseWaterRes(rset.getInt("waterDefValue")); npcDat.setBaseEarthRes(rset.getInt("earthDefValue")); npcDat.setBaseWindRes(rset.getInt("windDefValue")); npcDat.setBaseHolyRes(rset.getInt("holyDefValue")); npcDat.setBaseDarkRes(rset.getInt("darkDefValue")); cont++; } rset.close(); statement.close(); } _log.info(getClass().getSimpleName() + ": Loaded " + cont + " (Custom: " + cCount + ") elementals Data."); } catch (Exception e) { _log.log(Level.SEVERE, getClass().getSimpleName() + ": Error reading NPC Elementals Data: " + e.getMessage(), e); } finally { L2DatabaseFactory.close(con); } } public static NpcTable getInstance() { return SingletonHolder._instance; } private static class SingletonHolder { protected static final NpcTable _instance = new NpcTable(); } }