123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488 |
- /*
- * 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 <http://www.gnu.org/licenses/>.
- */
- package com.l2jserver.gameserver.instancemanager;
- import java.io.File;
- import java.sql.Connection;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.util.Collection;
- import java.util.Map;
- import java.util.Set;
- import java.util.logging.Level;
- import java.util.logging.Logger;
- import javax.xml.parsers.DocumentBuilderFactory;
- import javolution.util.FastMap;
- import org.w3c.dom.Document;
- import org.w3c.dom.NamedNodeMap;
- import org.w3c.dom.Node;
- import com.l2jserver.Config;
- import com.l2jserver.L2DatabaseFactory;
- import com.l2jserver.gameserver.model.CursedWeapon;
- import com.l2jserver.gameserver.model.actor.L2Attackable;
- import com.l2jserver.gameserver.model.actor.L2Character;
- import com.l2jserver.gameserver.model.actor.instance.L2DefenderInstance;
- import com.l2jserver.gameserver.model.actor.instance.L2FeedableBeastInstance;
- import com.l2jserver.gameserver.model.actor.instance.L2FestivalMonsterInstance;
- import com.l2jserver.gameserver.model.actor.instance.L2FortCommanderInstance;
- import com.l2jserver.gameserver.model.actor.instance.L2GrandBossInstance;
- import com.l2jserver.gameserver.model.actor.instance.L2GuardInstance;
- import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
- import com.l2jserver.gameserver.model.actor.instance.L2RiftInvaderInstance;
- import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
- import com.l2jserver.gameserver.network.SystemMessageId;
- import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
- import com.l2jserver.gameserver.util.Broadcast;
- /**
- * @author Micht
- */
- public class CursedWeaponsManager
- {
- private static final Logger _log = Logger.getLogger(CursedWeaponsManager.class.getName());
-
- public static final CursedWeaponsManager getInstance()
- {
- return SingletonHolder._instance;
- }
-
- private Map<Integer, CursedWeapon> _cursedWeapons;
-
- private CursedWeaponsManager()
- {
- init();
- }
-
- private void init()
- {
- _log.info("Initializing CursedWeaponsManager");
- _cursedWeapons = new FastMap<Integer, CursedWeapon>();
-
- if (!Config.ALLOW_CURSED_WEAPONS)
- return;
-
- load();
- restore();
- controlPlayers();
- _log.info("Loaded : " + _cursedWeapons.size() + " cursed weapon(s).");
- }
-
- public final void reload()
- {
- init();
- }
-
- private final void load()
- {
- if (Config.DEBUG)
- _log.info(" Parsing ... ");
- try
- {
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- factory.setValidating(false);
- factory.setIgnoringComments(true);
-
- File file = new File(Config.DATAPACK_ROOT + "/data/cursedWeapons.xml");
- if (!file.exists())
- {
- if (Config.DEBUG)
- _log.info("NO FILE");
- return;
- }
-
- Document doc = factory.newDocumentBuilder().parse(file);
-
- for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
- {
- if ("list".equalsIgnoreCase(n.getNodeName()))
- {
- for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
- {
- if ("item".equalsIgnoreCase(d.getNodeName()))
- {
- NamedNodeMap attrs = d.getAttributes();
- int id = Integer.parseInt(attrs.getNamedItem("id").getNodeValue());
- int skillId = Integer.parseInt(attrs.getNamedItem("skillId").getNodeValue());
- String name = attrs.getNamedItem("name").getNodeValue();
-
- CursedWeapon cw = new CursedWeapon(id, skillId, name);
-
- int val;
- for (Node cd = d.getFirstChild(); cd != null; cd = cd.getNextSibling())
- {
- if ("dropRate".equalsIgnoreCase(cd.getNodeName()))
- {
- attrs = cd.getAttributes();
- val = Integer.parseInt(attrs.getNamedItem("val").getNodeValue());
- cw.setDropRate(val);
- }
- else if ("duration".equalsIgnoreCase(cd.getNodeName()))
- {
- attrs = cd.getAttributes();
- val = Integer.parseInt(attrs.getNamedItem("val").getNodeValue());
- cw.setDuration(val);
- }
- else if ("durationLost".equalsIgnoreCase(cd.getNodeName()))
- {
- attrs = cd.getAttributes();
- val = Integer.parseInt(attrs.getNamedItem("val").getNodeValue());
- cw.setDurationLost(val);
- }
- else if ("disapearChance".equalsIgnoreCase(cd.getNodeName()))
- {
- attrs = cd.getAttributes();
- val = Integer.parseInt(attrs.getNamedItem("val").getNodeValue());
- cw.setDisapearChance(val);
- }
- else if ("stageKills".equalsIgnoreCase(cd.getNodeName()))
- {
- attrs = cd.getAttributes();
- val = Integer.parseInt(attrs.getNamedItem("val").getNodeValue());
- cw.setStageKills(val);
- }
- }
-
- // Store cursed weapon
- _cursedWeapons.put(id, cw);
- }
- }
- }
- }
-
- if (Config.DEBUG)
- _log.info("OK");
- }
- catch (Exception e)
- {
- _log.log(Level.SEVERE, "Error parsing cursed weapons file.", e);
-
- return;
- }
- }
-
- private final void restore()
- {
- if (Config.DEBUG)
- _log.info(" Restoring ... ");
- Connection con = null;
- try
- {
- // Retrieve the L2PcInstance from the characters table of the database
- con = L2DatabaseFactory.getInstance().getConnection();
-
- PreparedStatement statement = con.prepareStatement("SELECT itemId, charId, playerKarma, playerPkKills, nbKills, endTime FROM cursed_weapons");
- ResultSet rset = statement.executeQuery();
- while (rset.next())
- {
- int itemId = rset.getInt("itemId");
- int playerId = rset.getInt("charId");
- int playerKarma = rset.getInt("playerKarma");
- int playerPkKills = rset.getInt("playerPkKills");
- int nbKills = rset.getInt("nbKills");
- long endTime = rset.getLong("endTime");
-
- CursedWeapon cw = _cursedWeapons.get(itemId);
- cw.setPlayerId(playerId);
- cw.setPlayerKarma(playerKarma);
- cw.setPlayerPkKills(playerPkKills);
- cw.setNbKills(nbKills);
- cw.setEndTime(endTime);
- cw.reActivate();
- }
-
- rset.close();
- statement.close();
-
- if (Config.DEBUG)
- _log.info("OK");
- }
- catch (Exception e)
- {
- _log.log(Level.WARNING, "Could not restore CursedWeapons data: " + e.getMessage(), e);
- }
- finally
- {
- L2DatabaseFactory.close(con);
- }
- }
-
- private final void controlPlayers()
- {
- if (Config.DEBUG)
- _log.info(" Checking players ... ");
-
- Connection con = null;
- try
- {
- // Retrieve the L2PcInstance from the characters table of the database
- con = L2DatabaseFactory.getInstance().getConnection();
- PreparedStatement statement = null;
- ResultSet rset = null;
-
- // TODO: See comments below...
- // This entire for loop should NOT be necessary, since it is already handled by
- // CursedWeapon.endOfLife(). However, if we indeed *need* to duplicate it for safety,
- // then we'd better make sure that it FULLY cleans up inactive cursed weapons!
- // Undesired effects result otherwise, such as player with no zariche but with karma
- // or a lost-child entry in the cursedweapons table, without a corresponding one in items...
- for (CursedWeapon cw : _cursedWeapons.values())
- {
- if (cw.isActivated())
- continue;
-
- // Do an item check to be sure that the cursed weapon isn't hold by someone
- int itemId = cw.getItemId();
- try
- {
- statement = con.prepareStatement("SELECT owner_id FROM items WHERE item_id=?");
- statement.setInt(1, itemId);
- rset = statement.executeQuery();
-
- if (rset.next())
- {
- // A player has the cursed weapon in his inventory ...
- int playerId = rset.getInt("owner_id");
- _log.info("PROBLEM : Player " + playerId + " owns the cursed weapon " + itemId + " but he shouldn't.");
-
- // Delete the item
- statement.close();
- statement = con.prepareStatement("DELETE FROM items WHERE owner_id=? AND item_id=?");
- statement.setInt(1, playerId);
- statement.setInt(2, itemId);
- if (statement.executeUpdate() != 1)
- {
- _log.warning("Error while deleting cursed weapon " + itemId + " from userId " + playerId);
- }
- statement.close();
-
- // Delete the skill
- /*
- statement = con.prepareStatement("DELETE FROM character_skills WHERE charId=? AND skill_id=");
- statement.setInt(1, playerId);
- statement.setInt(2, cw.getSkillId());
- if (statement.executeUpdate() != 1)
- {
- _log.warning("Error while deleting cursed weapon "+itemId+" skill from userId "+playerId);
- }
- */
- // Restore the player's old karma and pk count
- statement = con.prepareStatement("UPDATE characters SET karma=?, pkkills=? WHERE charId=?");
- statement.setInt(1, cw.getPlayerKarma());
- statement.setInt(2, cw.getPlayerPkKills());
- statement.setInt(3, playerId);
- if (statement.executeUpdate() != 1)
- {
- _log.warning("Error while updating karma & pkkills for userId " + cw.getPlayerId());
- }
- // clean up the cursedweapons table.
- removeFromDb(itemId);
- }
- rset.close();
- statement.close();
- }
- catch (SQLException sqlE)
- {
- }
- }
- }
- catch (Exception e)
- {
- if (Config.DEBUG)
- _log.log(Level.WARNING, "Could not check CursedWeapons data: " + e.getMessage(), e);
- return;
- }
- finally
- {
- L2DatabaseFactory.close(con);
- }
- if (Config.DEBUG)
- _log.info("DONE");
- }
-
- public synchronized void checkDrop(L2Attackable attackable, L2PcInstance player)
- {
- if (attackable instanceof L2DefenderInstance || attackable instanceof L2RiftInvaderInstance
- || attackable instanceof L2FestivalMonsterInstance || attackable instanceof L2GuardInstance
- || attackable instanceof L2GrandBossInstance || attackable instanceof L2FeedableBeastInstance
- || attackable instanceof L2FortCommanderInstance)
- return;
-
- for (CursedWeapon cw : _cursedWeapons.values())
- {
- if (cw.isActive())
- continue;
-
- if (cw.checkDrop(attackable, player))
- break;
- }
- }
-
- public void activate(L2PcInstance player, L2ItemInstance item)
- {
- CursedWeapon cw = _cursedWeapons.get(item.getItemId());
- if (player.isCursedWeaponEquipped()) // cannot own 2 cursed swords
- {
- CursedWeapon cw2 = _cursedWeapons.get(player.getCursedWeaponEquippedId());
- /* TODO: give the bonus level in a more appropriate manner.
- * The following code adds "_stageKills" levels. This will also show in the char status.
- * I do not have enough info to know if the bonus should be shown in the pk count, or if it
- * should be a full "_stageKills" bonus or just the remaining from the current count till the
- * of the current stage...
- * This code is a TEMP fix, so that the cursed weapon's bonus level can be observed with as
- * little change in the code as possible, until proper info arises.
- */
- cw2.setNbKills(cw2.getStageKills() - 1);
- cw2.increaseKills();
-
- // erase the newly obtained cursed weapon
- cw.setPlayer(player); // NECESSARY in order to find which inventory the weapon is in!
- cw.endOfLife(); // expire the weapon and clean up.
- }
- else
- cw.activate(player, item);
- }
-
- public void drop(int itemId, L2Character killer)
- {
- CursedWeapon cw = _cursedWeapons.get(itemId);
-
- cw.dropIt(killer);
- }
-
- public void increaseKills(int itemId)
- {
- CursedWeapon cw = _cursedWeapons.get(itemId);
-
- cw.increaseKills();
- }
-
- public int getLevel(int itemId)
- {
- CursedWeapon cw = _cursedWeapons.get(itemId);
-
- return cw.getLevel();
- }
-
- public static void announce(SystemMessage sm)
- {
- Broadcast.toAllOnlinePlayers(sm);
- }
-
- public void checkPlayer(L2PcInstance player)
- {
- if (player == null)
- return;
-
- for (CursedWeapon cw : _cursedWeapons.values())
- {
- if (cw.isActivated() && player.getObjectId() == cw.getPlayerId())
- {
- cw.setPlayer(player);
- cw.setItem(player.getInventory().getItemByItemId(cw.getItemId()));
- cw.giveSkill();
- player.setCursedWeaponEquippedId(cw.getItemId());
-
- SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.S2_MINUTE_OF_USAGE_TIME_ARE_LEFT_FOR_S1);
- sm.addString(cw.getName());
- //sm.addItemName(cw.getItemId());
- sm.addNumber((int) ((cw.getEndTime() - System.currentTimeMillis()) / 60000));
- player.sendPacket(sm);
- }
- }
- }
-
- public int checkOwnsWeaponId(int ownerId)
- {
- for (CursedWeapon cw : _cursedWeapons.values())
- if (cw.isActivated() && ownerId == cw.getPlayerId())
- return cw.getItemId();
- return -1;
- }
-
- public static void removeFromDb(int itemId)
- {
- Connection con = null;
- try
- {
- con = L2DatabaseFactory.getInstance().getConnection();
-
- // Delete datas
- PreparedStatement statement = con.prepareStatement("DELETE FROM cursed_weapons WHERE itemId = ?");
- statement.setInt(1, itemId);
- statement.executeUpdate();
-
- statement.close();
- }
- catch (SQLException e)
- {
- _log.log(Level.SEVERE, "CursedWeaponsManager: Failed to remove data: " + e.getMessage(), e);
- }
- finally
- {
- L2DatabaseFactory.close(con);
- }
- }
-
- public void saveData()
- {
- for (CursedWeapon cw : _cursedWeapons.values())
- {
- cw.saveData();
- }
- }
-
- public boolean isCursed(int itemId)
- {
- return _cursedWeapons.containsKey(itemId);
- }
-
- public Collection<CursedWeapon> getCursedWeapons()
- {
- return _cursedWeapons.values();
- }
-
- public Set<Integer> getCursedWeaponsIds()
- {
- return _cursedWeapons.keySet();
- }
-
- public CursedWeapon getCursedWeapon(int itemId)
- {
- return _cursedWeapons.get(itemId);
- }
-
- public void givePassive(int itemId)
- {
- try
- {
- _cursedWeapons.get(itemId).giveSkill();
- }
- catch (Exception e)
- {
- /***/
- }
- }
-
- @SuppressWarnings("synthetic-access")
- private static class SingletonHolder
- {
- protected static final CursedWeaponsManager _instance = new CursedWeaponsManager();
- }
- }
|