/* * 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.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import javolution.util.FastList; import com.l2jserver.Config; import com.l2jserver.L2DatabaseFactory; import com.l2jserver.gameserver.model.Elementals; import com.l2jserver.gameserver.model.L2DropCategory; import com.l2jserver.gameserver.model.L2DropData; import com.l2jserver.gameserver.model.L2MinionData; import com.l2jserver.gameserver.model.L2NpcAIData; import com.l2jserver.gameserver.model.L2Skill; import com.l2jserver.gameserver.model.base.ClassId; import com.l2jserver.gameserver.skills.BaseStats; import com.l2jserver.gameserver.templates.StatsSet; import com.l2jserver.gameserver.templates.chars.L2NpcTemplate; /** * This class ... * * @version $Revision: 1.8.2.6.2.9 $ $Date: 2005/04/06 16:13:25 $ */ public class NpcTable { private static Logger _log = Logger.getLogger(NpcTable.class.getName()); private final TIntObjectHashMap _npcs; public static NpcTable getInstance() { return SingletonHolder._instance; } private NpcTable() { _npcs = new TIntObjectHashMap(); restoreNpcData(); } private void restoreNpcData() { Connection con = null; try { con = L2DatabaseFactory.getInstance().getConnection(); PreparedStatement statement; try { statement = con.prepareStatement("SELECT " + L2DatabaseFactory.getInstance().safetyString(new String[] { "id", "idTemplate", "name", "serverSideName", "title", "serverSideTitle", "class", "collision_radius", "collision_height", "level", "sex", "type", "attackrange", "hp", "mp", "hpreg", "mpreg", "str", "con", "dex", "int", "wit", "men", "exp", "sp", "patk", "pdef", "matk", "mdef", "atkspd", "critical", "aggro", "matkspd", "rhand", "lhand", "enchant", "walkspd", "runspd", "dropHerbGroup" }) + " FROM npc"); ResultSet npcdata = statement.executeQuery(); fillNpcTable(npcdata, false); npcdata.close(); statement.close(); } catch (Exception e) { _log.log(Level.SEVERE, "NPCTable: Error creating NPC table.", e); } if (Config.CUSTOM_NPC_TABLE) // reload certain NPCs { try { statement = con.prepareStatement("SELECT " + L2DatabaseFactory.getInstance().safetyString(new String[] { "id", "idTemplate", "name", "serverSideName", "title", "serverSideTitle", "class", "collision_radius", "collision_height", "level", "sex", "type", "attackrange", "hp", "mp", "hpreg", "mpreg", "str", "con", "dex", "int", "wit", "men", "exp", "sp", "patk", "pdef", "matk", "mdef", "atkspd", "critical", "aggro", "matkspd", "rhand", "lhand", "enchant", "walkspd", "runspd", "dropHerbGroup" }) + " FROM custom_npc"); ResultSet npcdata = statement.executeQuery(); fillNpcTable(npcdata, true); npcdata.close(); statement.close(); } catch (Exception e) { _log.log(Level.SEVERE, "NPCTable: Error creating custom NPC table.", e); } } try { statement = con.prepareStatement("SELECT npcid, skillid, level FROM npcskills"); ResultSet npcskills = statement.executeQuery(); L2NpcTemplate npcDat = null; L2Skill npcSkill = null; while (npcskills.next()) { int mobId = npcskills.getInt("npcid"); npcDat = _npcs.get(mobId); if (npcDat == null) { _log.warning("NPCTable: Skill data for undefined NPC. npcId: " + mobId); continue; } int skillId = npcskills.getInt("skillid"); int level = npcskills.getInt("level"); if (npcDat.race == null && skillId == 4416) { npcDat.setRace(level); continue; } npcSkill = SkillTable.getInstance().getInfo(skillId, level); if (npcSkill == null) continue; npcDat.addSkill(npcSkill); } npcskills.close(); statement.close(); } catch (Exception e) { _log.log(Level.SEVERE, "NPCTable: Error reading NPC skills table.", e); } if (Config.CUSTOM_NPC_SKILLS_TABLE) { try { statement = con.prepareStatement("SELECT npcid, skillid, level FROM custom_npcskills"); ResultSet npcskills = statement.executeQuery(); L2NpcTemplate npcDat = null; L2Skill npcSkill = null; while (npcskills.next()) { int mobId = npcskills.getInt("npcid"); npcDat = _npcs.get(mobId); if (npcDat == null) { _log.warning("Custom NPCTable: Skill data for undefined NPC. npcId: " + mobId); continue; } int skillId = npcskills.getInt("skillid"); int level = npcskills.getInt("level"); if (npcDat.race == null && skillId == 4416) { npcDat.setRace(level); continue; } npcSkill = SkillTable.getInstance().getInfo(skillId, level); if (npcSkill == null) continue; npcDat.addSkill(npcSkill); } npcskills.close(); statement.close(); } catch (Exception e) { _log.log(Level.SEVERE, "Custom NPCTable: Error reading NPC skills table.", e); } } try { statement = con.prepareStatement("SELECT " + L2DatabaseFactory.getInstance().safetyString(new String[] { "mobId", "itemId", "min", "max", "category", "chance" }) + " FROM droplist ORDER BY mobId, chance DESC"); ResultSet dropData = statement.executeQuery(); L2DropData dropDat = null; L2NpcTemplate npcDat = null; while (dropData.next()) { int mobId = dropData.getInt("mobId"); npcDat = _npcs.get(mobId); if (npcDat == null) { _log.warning("NPCTable: Drop data for undefined NPC. npcId: " + mobId); continue; } dropDat = new L2DropData(); dropDat.setItemId(dropData.getInt("itemId")); dropDat.setMinDrop(dropData.getInt("min")); dropDat.setMaxDrop(dropData.getInt("max")); dropDat.setChance(dropData.getDouble("chance")); int category = dropData.getInt("category"); if (ItemTable.getInstance().getTemplate(dropDat.getItemId()) == null) { _log.warning("Drop data for undefined item template! NpcId: " + mobId+" itemId: "+dropDat.getItemId()); continue; } npcDat.addDropData(dropDat, category); } dropData.close(); statement.close(); } catch (Exception e) { _log.log(Level.SEVERE, "NPCTable: Error reading NPC dropdata. ", e); } if (Config.CUSTOM_DROPLIST_TABLE) { try { statement = con.prepareStatement("SELECT " + L2DatabaseFactory.getInstance().safetyString(new String[] { "mobId", "itemId", "min", "max", "category", "chance" }) + " FROM custom_droplist ORDER BY mobId, chance DESC"); ResultSet dropData = statement.executeQuery(); L2DropData dropDat = null; L2NpcTemplate npcDat = null; int cCount = 0; while (dropData.next()) { int mobId = dropData.getInt("mobId"); npcDat = _npcs.get(mobId); if (npcDat == null) { _log.warning("NPCTable: CUSTOM DROPLIST: Drop data for undefined NPC. npcId: " + mobId); continue; } dropDat = new L2DropData(); dropDat.setItemId(dropData.getInt("itemId")); dropDat.setMinDrop(dropData.getInt("min")); dropDat.setMaxDrop(dropData.getInt("max")); dropDat.setChance(dropData.getInt("chance")); int category = dropData.getInt("category"); if (ItemTable.getInstance().getTemplate(dropDat.getItemId()) == null) { _log.warning("Custom drop data for undefined item template! NpcId: " + mobId+" itemId: "+dropDat.getItemId()); continue; } npcDat.addDropData(dropDat, category); cCount++; } dropData.close(); statement.close(); _log.info("CustomDropList: Added " + cCount + " custom droplist."); } catch (Exception e) { _log.log(Level.SEVERE, "NPCTable: Error reading NPC custom dropdata.", e); } } try { statement = con.prepareStatement("SELECT " + L2DatabaseFactory.getInstance().safetyString(new String[] { "npc_id", "class_id" }) + " FROM skill_learn"); ResultSet learndata = statement.executeQuery(); while (learndata.next()) { int npcId = learndata.getInt("npc_id"); int classId = learndata.getInt("class_id"); L2NpcTemplate npc = getTemplate(npcId); if (npc == null) { _log.warning("NPCTable: Error getting NPC template ID " + npcId + " while trying to load skill trainer data."); continue; } npc.addTeachInfo(ClassId.values()[classId]); } learndata.close(); statement.close(); } catch (Exception e) { _log.log(Level.SEVERE, "NPCTable: Error reading NPC trainer data.", e); } try { statement = con.prepareStatement("SELECT " + L2DatabaseFactory.getInstance().safetyString(new String[] { "boss_id", "minion_id", "amount_min", "amount_max" }) + " FROM minions"); ResultSet minionData = statement.executeQuery(); L2MinionData minionDat = null; L2NpcTemplate npcDat = null; int cnt = 0; while (minionData.next()) { int raidId = minionData.getInt("boss_id"); npcDat = _npcs.get(raidId); if (npcDat == null) { _log.warning("Minion references undefined boss NPC. Boss NpcId: " + raidId); continue; } minionDat = new L2MinionData(); minionDat.setMinionId(minionData.getInt("minion_id")); minionDat.setAmountMin(minionData.getInt("amount_min")); minionDat.setAmountMax(minionData.getInt("amount_max")); npcDat.addRaidData(minionDat); cnt++; } minionData.close(); statement.close(); _log.info("NpcTable: Loaded " + cnt + " Minions."); } catch (Exception e) { _log.log(Level.SEVERE, "NPCTable: Error loading minion data.", e); } //------------------------------------------------------------------- //NPC AI Attributes & Data ... try { statement = con.prepareStatement("SELECT * FROM npcaidata ORDER BY npcId"); ResultSet NpcAIDataTable = statement.executeQuery(); L2NpcAIData npcAIDat = null; L2NpcTemplate npcDat = null; int cont=0; while (NpcAIDataTable.next()) { int npc_id = NpcAIDataTable.getInt("npcId"); npcDat = _npcs.get(npc_id); if (npcDat == null) { _log.severe("NPCTable: AI Data Error with id : " + npc_id); continue; } npcAIDat = new L2NpcAIData(); npcAIDat.setMinSkillChance(NpcAIDataTable.getInt("minSkillChance")); npcAIDat.setMaxSkillChance(NpcAIDataTable.getInt("maxSkillChance")); npcAIDat.setPrimarySkillId(NpcAIDataTable.getInt("primarySkillId")); npcAIDat.setCanMove(NpcAIDataTable.getInt("canMove")); npcAIDat.setShortRangeSkill(NpcAIDataTable.getInt("minRangeSkill")); npcAIDat.setShortRangeChance(NpcAIDataTable.getInt("minRangeChance")); npcAIDat.setLongRangeSkill(NpcAIDataTable.getInt("maxRangeSkill")); npcAIDat.setLongRangeChance(NpcAIDataTable.getInt("maxRangeChance")); npcAIDat.setSoulShot(NpcAIDataTable.getInt("soulshot")); npcAIDat.setSpiritShot(NpcAIDataTable.getInt("spiritshot")); npcAIDat.setSpiritShotChance(NpcAIDataTable.getInt("spsChance")); npcAIDat.setSoulShotChance(NpcAIDataTable.getInt("ssChance")); npcAIDat.setIsChaos(NpcAIDataTable.getInt("isChaos")); npcAIDat.setClan(NpcAIDataTable.getString("clan")); npcAIDat.setClanRange(NpcAIDataTable.getInt("clanRange")); npcAIDat.setEnemyClan(NpcAIDataTable.getString("enemyClan")); npcAIDat.setEnemyRange(NpcAIDataTable.getInt("enemyRange")); npcAIDat.setDodge(NpcAIDataTable.getInt("dodge")); npcAIDat.setAi(NpcAIDataTable.getString("aiType")); //npcAIDat.setSwitchRangeChance(NpcAIDataTable.getInt("rangeswitchchance")); //npcAIDat.setBaseShldRate(NpcAIDataTable.getInt("baseShldRate")); //npcAIDat.setBaseShldDef(NpcAIDataTable.getInt("baseShldDef")); npcDat.setAIData(npcAIDat); cont++; } NpcAIDataTable.close(); statement.close(); _log.info("NPC AI Data Table: Loaded " + cont + " AI Data."); } catch (Exception e) { _log.log(Level.SEVERE, "NPCTable: Error reading NPC AI Data: " + e.getMessage(), e); } if (Config.CUSTOM_NPC_TABLE) { try { statement = con.prepareStatement("SELECT * FROM custom_npcaidata ORDER BY npcId"); ResultSet NpcAIDataTable = statement.executeQuery(); L2NpcAIData npcAIDat = null; L2NpcTemplate npcDat = null; int cont = 0; while (NpcAIDataTable.next()) { int npc_id = NpcAIDataTable.getInt("npcId"); npcDat = _npcs.get(npc_id); if (npcDat == null) { _log.severe("NPCTable: Custom AI Data Error with id : " + npc_id); continue; } npcAIDat = new L2NpcAIData(); npcAIDat.setPrimarySkillId(NpcAIDataTable.getInt("primarySkillId")); npcAIDat.setMinSkillChance(NpcAIDataTable.getInt("minSkillChance")); npcAIDat.setMaxSkillChance(NpcAIDataTable.getInt("maxSkillChance")); npcAIDat.setCanMove(NpcAIDataTable.getInt("canMove")); npcAIDat.setSoulShot(NpcAIDataTable.getInt("soulshot")); npcAIDat.setSpiritShot(NpcAIDataTable.getInt("spiritshot")); npcAIDat.setSoulShotChance(NpcAIDataTable.getInt("ssChance")); npcAIDat.setSpiritShotChance(NpcAIDataTable.getInt("spsChance")); npcAIDat.setIsChaos(NpcAIDataTable.getInt("isChaos")); npcAIDat.setShortRangeSkill(NpcAIDataTable.getInt("minRangeSkill")); npcAIDat.setShortRangeChance(NpcAIDataTable.getInt("minRangeChance")); npcAIDat.setLongRangeSkill(NpcAIDataTable.getInt("maxRangeSkill")); npcAIDat.setLongRangeChance(NpcAIDataTable.getInt("maxRangeChance")); npcAIDat.setClan(NpcAIDataTable.getString("clan")); npcAIDat.setClanRange(NpcAIDataTable.getInt("clanRange")); npcAIDat.setEnemyClan(NpcAIDataTable.getString("enemyClan")); npcAIDat.setEnemyRange(NpcAIDataTable.getInt("enemyRange")); npcAIDat.setDodge(NpcAIDataTable.getInt("dodge")); npcAIDat.setAi(NpcAIDataTable.getString("aiType")); //npcAIDat.setSwitchRangeChance(NpcAIDataTable.getInt("rangeswitchchance")); //npcAIDat.setBaseShldRate(NpcAIDataTable.getInt("baseShldRate")); //npcAIDat.setBaseShldDef(NpcAIDataTable.getInt("baseShldDef")); npcDat.setAIData(npcAIDat); cont++; } NpcAIDataTable.close(); statement.close(); _log.info("NPC AI Data Table: Loaded " + cont + " Custom AI Data."); } catch (Exception e) { _log.log(Level.SEVERE, "NPCTable: Error reading NPC Custom AI Data: " + e.getMessage(), e); } } try { statement = con.prepareStatement("SELECT " + L2DatabaseFactory.getInstance().safetyString(new String[] {"npc_id", "elemAtkType","elemAtkValue","fireDefValue","waterDefValue","earthDefValue","windDefValue","holyDefValue","darkDefValue"}) + " FROM npc_elementals ORDER BY npc_id"); ResultSet NpcElementals = statement.executeQuery(); L2NpcTemplate npcDat = null; int cont=0; while (NpcElementals.next()) { int npc_id = NpcElementals.getInt("npc_id"); npcDat = _npcs.get(npc_id); if (npcDat == null) { _log.severe("NPCElementals: Elementals Error with id : " + npc_id); continue; } switch(NpcElementals.getByte("elemAtkType")) { case Elementals.FIRE: npcDat.baseFire = NpcElementals.getInt("elemAtkValue"); break; case Elementals.WATER: npcDat.baseWater = NpcElementals.getInt("elemAtkValue"); break; case Elementals.EARTH: npcDat.baseEarth = NpcElementals.getInt("elemAtkValue"); break; case Elementals.WIND: npcDat.baseWind = NpcElementals.getInt("elemAtkValue"); break; case Elementals.HOLY: npcDat.baseHoly = NpcElementals.getInt("elemAtkValue"); break; case Elementals.DARK: npcDat.baseDark = NpcElementals.getInt("elemAtkValue"); break; default: _log.severe("NPCElementals: Elementals Error with id : " + npc_id + "; unknown elementType: " + NpcElementals.getByte("elemAtkType")); continue; } npcDat.baseFireRes = NpcElementals.getInt("fireDefValue"); npcDat.baseWaterRes = NpcElementals.getInt("waterDefValue"); npcDat.baseEarthRes = NpcElementals.getInt("earthDefValue"); npcDat.baseWindRes = NpcElementals.getInt("windDefValue"); npcDat.baseHolyRes = NpcElementals.getInt("holyDefValue"); npcDat.baseDarkRes = NpcElementals.getInt("darkDefValue"); cont++; } NpcElementals.close(); statement.close(); _log.info("NPC Elementals Data Table: Loaded " + cont + " elementals Data."); } catch (Exception e) { _log.log(Level.SEVERE, "NPCTable: Error reading NPC Elementals Data: " + e.getMessage(), e); } if (Config.CUSTOM_NPC_TABLE) { try { statement = con.prepareStatement("SELECT " + L2DatabaseFactory.getInstance().safetyString(new String[] {"npc_id", "elemAtkType","elemAtkValue","fireDefValue","waterDefValue","earthDefValue","windDefValue","holyDefValue","darkDefValue"}) + " FROM custom_npc_elementals ORDER BY npc_id"); ResultSet NpcElementals = statement.executeQuery(); L2NpcTemplate npcDat = null; int cont=0; while (NpcElementals.next()) { int npc_id = NpcElementals.getInt("npc_id"); npcDat = _npcs.get(npc_id); if (npcDat == null) { _log.severe("NPCElementals: custom Elementals Error with id : " + npc_id); continue; } switch(NpcElementals.getByte("elemAtkType")) { case Elementals.FIRE: npcDat.baseFire = NpcElementals.getInt("elemAtkValue"); break; case Elementals.WATER: npcDat.baseWater = NpcElementals.getInt("elemAtkValue"); break; case Elementals.EARTH: npcDat.baseEarth = NpcElementals.getInt("elemAtkValue"); break; case Elementals.WIND: npcDat.baseWind = NpcElementals.getInt("elemAtkValue"); break; case Elementals.HOLY: npcDat.baseHoly = NpcElementals.getInt("elemAtkValue"); break; case Elementals.DARK: npcDat.baseDark = NpcElementals.getInt("elemAtkValue"); break; default: _log.severe("NPCElementals: custom Elementals Error with id : " + npc_id + "; unknown elementType: " + NpcElementals.getByte("elemAtkType")); continue; } npcDat.baseFireRes = NpcElementals.getInt("fireDefValue"); npcDat.baseWaterRes = NpcElementals.getInt("waterDefValue"); npcDat.baseEarthRes = NpcElementals.getInt("earthDefValue"); npcDat.baseWindRes = NpcElementals.getInt("windDefValue"); npcDat.baseHolyRes = NpcElementals.getInt("holyDefValue"); npcDat.baseDarkRes = NpcElementals.getInt("darkDefValue"); cont++; } NpcElementals.close(); statement.close(); _log.info("NPC Elementals Data Table: Loaded " + cont + " custom elementals Data."); } catch (Exception e) { _log.log(Level.SEVERE, "NPCTable: Error reading NPC Custom Elementals Data: " + e.getMessage(), e); } } } catch (Exception e) { _log.log(Level.SEVERE, "NPCTable: Failed loading database connection: " + e.getMessage(), e); } finally { L2DatabaseFactory.close(con); } } private void fillNpcTable(ResultSet NpcData, boolean customData) throws Exception { int count = 0; while (NpcData.next()) { 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("jClass", 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("name", ""); 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("aggroRange", NpcData.getInt("aggro")); 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); L2NpcTemplate template = new L2NpcTemplate(npcDat); /*template.addVulnerability(Stats.BOW_WPN_VULN, 1); template.addVulnerability(Stats.CROSSBOW_WPN_VULN, 1); template.addVulnerability(Stats.BLUNT_WPN_VULN, 1); template.addVulnerability(Stats.DAGGER_WPN_VULN, 1);*/ _npcs.put(id, template); count++; } if (!customData) _log.info("NpcTable: (Re)Loaded " + count + " NPC template(s)."); else _log.info("NpcTable: (Re)Loaded " + count + " custom NPC template(s)."); } public void reloadNpc(int id) { Connection con = null; try { // save a copy of the old data L2NpcTemplate old = getTemplate(id); TIntObjectHashMap skills = new TIntObjectHashMap(); if (old.getSkills() != null) skills.putAll(old.getSkills()); FastList categories = new FastList(); if (old.getDropData() != null) categories.addAll(old.getDropData()); ClassId[] classIds = null; if (old.getTeachInfo() != null) classIds = old.getTeachInfo().clone(); List minions = new FastList(); if (old.getMinionData() != null) minions.addAll(old.getMinionData()); // reload the NPC base data con = L2DatabaseFactory.getInstance().getConnection(); PreparedStatement st = con.prepareStatement("SELECT " + L2DatabaseFactory.getInstance().safetyString(new String[] { "id", "idTemplate", "name", "serverSideName", "title", "serverSideTitle", "class", "collision_radius", "collision_height", "level", "sex", "type", "attackrange", "hp", "mp", "hpreg", "mpreg", "str", "con", "dex", "int", "wit", "men", "exp", "sp", "patk", "pdef", "matk", "mdef", "atkspd", "critical", "aggro", "matkspd", "rhand", "lhand", "enchant", "walkspd", "runspd", "dropHerbGroup" }) + " FROM npc WHERE id=?"); st.setInt(1, id); ResultSet rs = st.executeQuery(); fillNpcTable(rs, false); if (Config.CUSTOM_NPC_TABLE) // reload certain NPCs { st = con.prepareStatement("SELECT " + L2DatabaseFactory.getInstance().safetyString(new String[] { "id", "idTemplate", "name", "serverSideName", "title", "serverSideTitle", "class", "collision_radius", "collision_height", "level", "sex", "type", "attackrange", "hp", "mp", "hpreg", "mpreg", "str", "con", "dex", "int", "wit", "men", "exp", "sp", "patk", "pdef", "matk", "mdef", "atkspd", "critical", "aggro", "matkspd", "rhand", "lhand", "enchant", "walkspd", "runspd", "dropHerbGroup" }) + " FROM custom_npc WHERE id=?"); st.setInt(1, id); rs = st.executeQuery(); fillNpcTable(rs, true); } rs.close(); st.close(); // restore additional data from saved copy L2NpcTemplate created = getTemplate(id); for (L2Skill skill : skills.values(new L2Skill[skills.size()])) created.addSkill(skill); if (classIds != null) for (ClassId classId : classIds) created.addTeachInfo(classId); for (L2MinionData minion : minions) created.addRaidData(minion); } catch (Exception e) { _log.log(Level.WARNING, "NPCTable: Could not reload data for NPC " + id + ": " + e.getMessage(), e); } finally { L2DatabaseFactory.close(con); } } // just wrapper public void reloadAllNpc() { restoreNpcData(); } public void saveNpc(StatsSet npc) { 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 sbValues = new StringBuilder(length); for (Object obj : set.keySet()) { final String name = (String) obj; if (!name.equalsIgnoreCase("npcId")) { if (sbValues.length() > 0) { sbValues.append(", "); } sbValues.append(name); sbValues.append(" = '"); sbValues.append(set.get(name)); sbValues.append('\''); } } Connection con = null; try { con = L2DatabaseFactory.getInstance().getConnection(); int updated = 0; if (Config.CUSTOM_NPC_TABLE) { final StringBuilder sbQuery = new StringBuilder(sbValues.length() + 28); sbQuery.append("UPDATE custom_npc SET "); sbQuery.append(sbValues.toString()); sbQuery.append(" WHERE id = ?"); PreparedStatement statement = con.prepareStatement(sbQuery.toString()); statement.setInt(1, npc.getInteger("npcId")); updated = statement.executeUpdate(); statement.close(); } if (updated == 0) { final StringBuilder sbQuery = new StringBuilder(sbValues.length() + 28); sbQuery.append("UPDATE npc SET "); sbQuery.append(sbValues.toString()); sbQuery.append(" WHERE id = ?"); PreparedStatement statement = con.prepareStatement(sbQuery.toString()); statement.setInt(1, npc.getInteger("npcId")); statement.executeUpdate(); statement.close(); } } catch (Exception e) { _log.log(Level.WARNING, "NPCTable: Could not store new NPC data in database: " + e.getMessage(), e); } finally { L2DatabaseFactory.close(con); } } public void replaceTemplate(L2NpcTemplate npc) { _npcs.put(npc.npcId, npc); } public L2NpcTemplate getTemplate(int id) { return _npcs.get(id); } public L2NpcTemplate getTemplateByName(String name) { for (Object npcTemplate : _npcs.values()) if (((L2NpcTemplate)npcTemplate).name.equalsIgnoreCase(name)) return (L2NpcTemplate) npcTemplate; return null; } public L2NpcTemplate[] getAllOfLevel(int lvl) { List list = new FastList(); for (Object t : _npcs.values()) if (((L2NpcTemplate)t).level == lvl) list.add((L2NpcTemplate) t); return list.toArray(new L2NpcTemplate[list.size()]); } public L2NpcTemplate[] getAllMonstersOfLevel(int lvl) { List list = new FastList(); for (Object t : _npcs.values()) if (((L2NpcTemplate)t).level == lvl && "L2Monster".equals(((L2NpcTemplate)t).type)) list.add((L2NpcTemplate) t); return list.toArray(new L2NpcTemplate[list.size()]); } public L2NpcTemplate[] getAllNpcStartingWith(String letter) { List list = new FastList(); for (Object t : _npcs.values()) if (((L2NpcTemplate)t).name.startsWith(letter) && "L2Npc".equals(((L2NpcTemplate)t).type)) list.add((L2NpcTemplate) t); return list.toArray(new L2NpcTemplate[list.size()]); } /** * @param classType * @return */ public L2NpcTemplate[] getAllNpcOfClassType(String classType) { List list = new FastList(); for (Object t : _npcs.values()) if (classType.equals(((L2NpcTemplate)t).type)) list.add((L2NpcTemplate) t); return list.toArray(new L2NpcTemplate[list.size()]); } /** * @param clazz * @return */ public Set getAllNpcOfL2jClass(Class clazz) { return null; } /** * @param aiType * @return */ public Set getAllNpcOfAiType(String aiType) { return null; } @SuppressWarnings("synthetic-access") private static class SingletonHolder { protected static final NpcTable _instance = new NpcTable(); } }