/* * 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 silentium.gameserver.model.actor.instance; import java.util.Calendar; import java.util.NoSuchElementException; import java.util.StringTokenizer; import silentium.commons.utils.StringUtil; import silentium.gameserver.data.html.StaticHtmPath; import silentium.gameserver.instancemanager.CastleManager; import silentium.gameserver.instancemanager.CastleManorManager; import silentium.gameserver.model.L2Clan; import silentium.gameserver.model.entity.sevensigns.SevenSigns; import silentium.gameserver.network.SystemMessageId; import silentium.gameserver.network.serverpackets.ActionFailed; import silentium.gameserver.network.serverpackets.ExShowCropInfo; import silentium.gameserver.network.serverpackets.ExShowCropSetting; import silentium.gameserver.network.serverpackets.ExShowManorDefaultInfo; import silentium.gameserver.network.serverpackets.ExShowSeedInfo; import silentium.gameserver.network.serverpackets.ExShowSeedSetting; import silentium.gameserver.network.serverpackets.NpcHtmlMessage; import silentium.gameserver.network.serverpackets.SystemMessage; import silentium.gameserver.tables.ClanTable; import silentium.gameserver.templates.chars.L2NpcTemplate; import silentium.gameserver.utils.Util; /** * Castle Chamberlains implementation, used for: - tax rate control - regional manor system control - castle treasure control - ... */ public class L2CastleChamberlainInstance extends L2MerchantInstance { protected static final int COND_ALL_FALSE = 0; protected static final int COND_BUSY_BECAUSE_OF_SIEGE = 1; protected static final int COND_OWNER = 2; protected static final int COND_CLAN_MEMBER = 3; private int _preHour = 6; public L2CastleChamberlainInstance(int objectId, L2NpcTemplate template) { super(objectId, template); } @Override public void onBypassFeedback(L2PcInstance player, String command) { // BypassValidation Exploit plug. if (player.getCurrentFolkNPC().getObjectId() != getObjectId()) return; int condition = validateCondition(player); if (condition <= COND_ALL_FALSE) return; else if (condition == COND_BUSY_BECAUSE_OF_SIEGE) return; else if (condition == COND_OWNER) { StringTokenizer st = new StringTokenizer(command, " "); String actualCommand = st.nextToken(); // Get actual command String val = ""; if (st.countTokens() >= 1) val = st.nextToken(); if (actualCommand.equalsIgnoreCase("banish_foreigner")) { if (!validatePrivileges(player, L2Clan.CP_CS_DISMISS)) return; if (siegeBlocksFunction(player)) return; // Move non-clan members off castle area, and send html getCastle().banishForeigners(); sendFileMessage(player, StaticHtmPath.ChamberlainHtmPath + "chamberlain-banishafter.htm"); return; } else if (actualCommand.equalsIgnoreCase("banish_foreigner_show")) { if (!validatePrivileges(player, L2Clan.CP_CS_DISMISS)) return; if (siegeBlocksFunction(player)) return; sendFileMessage(player, StaticHtmPath.ChamberlainHtmPath + "chamberlain-banishfore.htm"); return; } else if (actualCommand.equalsIgnoreCase("manage_functions")) { sendFileMessage(player, StaticHtmPath.ChamberlainHtmPath + "chamberlain-manage.htm"); return; } else if (actualCommand.equalsIgnoreCase("products")) { sendFileMessage(player, StaticHtmPath.ChamberlainHtmPath + "chamberlain-products.htm"); return; } else if (actualCommand.equalsIgnoreCase("list_siege_clans")) { if ((player.getClanPrivileges() & L2Clan.CP_CS_MANAGE_SIEGE) == L2Clan.CP_CS_MANAGE_SIEGE) { getCastle().getSiege().listRegisterClan(player); // List current register clan return; } sendFileMessage(player, StaticHtmPath.ChamberlainHtmPath + "chamberlain-noprivs.htm"); return; } else if (actualCommand.equalsIgnoreCase("receive_report")) { if (player.isClanLeader()) { NpcHtmlMessage html = new NpcHtmlMessage(getObjectId()); html.setFile(StaticHtmPath.ChamberlainHtmPath + "chamberlain-report.htm", player); html.replace("%objectId%", String.valueOf(getObjectId())); L2Clan clan = ClanTable.getInstance().getClan(getCastle().getOwnerId()); html.replace("%clanname%", clan.getName()); html.replace("%clanleadername%", clan.getLeaderName()); html.replace("%castlename%", getCastle().getName()); int currentPeriod = SevenSigns.getInstance().getCurrentPeriod(); switch (currentPeriod) { case SevenSigns.PERIOD_COMP_RECRUITING: html.replace("%ss_event%", "Quest Event Initialization"); break; case SevenSigns.PERIOD_COMPETITION: html.replace("%ss_event%", "Competition (Quest Event)"); break; case SevenSigns.PERIOD_COMP_RESULTS: html.replace("%ss_event%", "Quest Event Results"); break; case SevenSigns.PERIOD_SEAL_VALIDATION: html.replace("%ss_event%", "Seal Validation"); break; } int sealOwner1 = SevenSigns.getInstance().getSealOwner(1); switch (sealOwner1) { case SevenSigns.CABAL_NULL: html.replace("%ss_avarice%", "Not in Possession"); break; case SevenSigns.CABAL_DAWN: html.replace("%ss_avarice%", "Lords of Dawn"); break; case SevenSigns.CABAL_DUSK: html.replace("%ss_avarice%", "Revolutionaries of Dusk"); break; } int sealOwner2 = SevenSigns.getInstance().getSealOwner(2); switch (sealOwner2) { case SevenSigns.CABAL_NULL: html.replace("%ss_gnosis%", "Not in Possession"); break; case SevenSigns.CABAL_DAWN: html.replace("%ss_gnosis%", "Lords of Dawn"); break; case SevenSigns.CABAL_DUSK: html.replace("%ss_gnosis%", "Revolutionaries of Dusk"); break; } int sealOwner3 = SevenSigns.getInstance().getSealOwner(3); switch (sealOwner3) { case SevenSigns.CABAL_NULL: html.replace("%ss_strife%", "Not in Possession"); break; case SevenSigns.CABAL_DAWN: html.replace("%ss_strife%", "Lords of Dawn"); break; case SevenSigns.CABAL_DUSK: html.replace("%ss_strife%", "Revolutionaries of Dusk"); break; } player.sendPacket(html); return; } sendFileMessage(player, StaticHtmPath.ChamberlainHtmPath + "chamberlain-noprivs.htm"); return; } else if (actualCommand.equalsIgnoreCase("items")) { if ((player.getClanPrivileges() & L2Clan.CP_CS_USE_FUNCTIONS) == L2Clan.CP_CS_USE_FUNCTIONS) { if (val.isEmpty()) return; player.tempInventoryDisable(); _log.trace("Showing chamberlain buylist"); showBuyWindow(player, Integer.parseInt(val + "1")); return; } sendFileMessage(player, StaticHtmPath.ChamberlainHtmPath + "chamberlain-noprivs.htm"); return; } else if (actualCommand.equalsIgnoreCase("manage_siege_defender")) { if ((player.getClanPrivileges() & L2Clan.CP_CS_MANAGE_SIEGE) == L2Clan.CP_CS_MANAGE_SIEGE) { getCastle().getSiege().listRegisterClan(player); return; } sendFileMessage(player, StaticHtmPath.ChamberlainHtmPath + "chamberlain-noprivs.htm"); return; } else if (actualCommand.equalsIgnoreCase("manage_vault")) { if ((player.getClanPrivileges() & L2Clan.CP_CS_TAXES) == L2Clan.CP_CS_TAXES) { String filename = StaticHtmPath.ChamberlainHtmPath + "chamberlain-vault.htm"; int amount = 0; if (val.equalsIgnoreCase("deposit")) { try { amount = Integer.parseInt(st.nextToken()); } catch (NoSuchElementException e) { } if (amount > 0 && getCastle().getTreasury() + amount < Integer.MAX_VALUE) { if (player.reduceAdena("Castle", amount, this, true)) getCastle().addToTreasuryNoTax(amount); else sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOU_NOT_ENOUGH_ADENA)); } } else if (val.equalsIgnoreCase("withdraw")) { try { amount = Integer.parseInt(st.nextToken()); } catch (NoSuchElementException e) { } if (amount > 0) { if (getCastle().getTreasury() < amount) filename = StaticHtmPath.ChamberlainHtmPath + "chamberlain-vault-no.htm"; else { if (getCastle().addToTreasuryNoTax((-1) * amount)) player.addAdena("Castle", amount, this, true); } } } NpcHtmlMessage html = new NpcHtmlMessage(getObjectId()); html.setFile(filename, player); html.replace("%objectId%", String.valueOf(getObjectId())); html.replace("%npcname%", getName()); html.replace("%tax_income%", Util.formatAdena(getCastle().getTreasury())); html.replace("%withdraw_amount%", Util.formatAdena(amount)); player.sendPacket(html); return; } sendFileMessage(player, StaticHtmPath.ChamberlainHtmPath + "chamberlain-noprivs.htm"); return; } else if (actualCommand.equalsIgnoreCase("operate_door")) // door control { if ((player.getClanPrivileges() & L2Clan.CP_CS_OPEN_DOOR) == L2Clan.CP_CS_OPEN_DOOR) { if (!val.isEmpty()) { boolean open = (Integer.parseInt(val) == 1); while (st.hasMoreTokens()) getCastle().openCloseDoor(player, Integer.parseInt(st.nextToken()), open); NpcHtmlMessage html = new NpcHtmlMessage(getObjectId()); String file = StaticHtmPath.ChamberlainHtmPath + "doors-close.htm"; if (open) file = StaticHtmPath.ChamberlainHtmPath + "doors-open.htm"; html.setFile(file, player); html.replace("%objectId%", String.valueOf(getObjectId())); player.sendPacket(html); return; } NpcHtmlMessage html = new NpcHtmlMessage(getObjectId()); html.setFile(StaticHtmPath.ChamberlainHtmPath + getTemplate().getNpcId() + "-d.htm", player); html.replace("%objectId%", String.valueOf(getObjectId())); html.replace("%npcname%", getName()); player.sendPacket(html); return; } sendFileMessage(player, StaticHtmPath.ChamberlainHtmPath + "chamberlain-noprivs.htm"); return; } else if (actualCommand.equalsIgnoreCase("tax_set")) // tax rates control { if ((player.getClanPrivileges() & L2Clan.CP_CS_TAXES) == L2Clan.CP_CS_TAXES) { if (!val.isEmpty()) getCastle().setTaxPercent(player, Integer.parseInt(val)); final String msg = StringUtil.concat("<html><body>", getName(), ":<br>" + "Current tax rate: ", String.valueOf(getCastle().getTaxPercent()), "%<br>" + "<table>" + "<tr>" + "<td width=120>Change tax rate to:</td>" + "<td><edit var=\"value\" width=40></td>" + "</tr>" + "</table><br>" + "<center><button value=\"Adjust\" action=\"bypass -h npc_%objectId%_tax_set $value\" width=74 height=21 back=\"L2UI_CH3.Btn1_normalOn\" fore=\"L2UI_CH3.Btn1_normal\">" + "<button value=\"Cancel\" action=\"bypass -h npc_%objectId%_Link chamberlain/chamberlain.htm\" width=74 height=21 back=\"L2UI_CH3.Btn1_normalOn\" fore=\"L2UI_CH3.Btn1_normal\"></center>" + "</body></html>"); sendHtmlMessage(player, msg); return; } NpcHtmlMessage html = new NpcHtmlMessage(getObjectId()); html.setFile(StaticHtmPath.ChamberlainHtmPath + "chamberlain-tax.htm", player); html.replace("%objectId%", String.valueOf(getObjectId())); html.replace("%tax%", String.valueOf(getCastle().getTaxPercent())); player.sendPacket(html); return; } else if (actualCommand.equalsIgnoreCase("manor")) { String filename = ""; if (CastleManorManager.getInstance().isDisabled()) filename = StaticHtmPath.NpcHtmPath + "npcdefault.htm"; else { int cmd = Integer.parseInt(val); switch (cmd) { case 0: filename = StaticHtmPath.ChamberlainHtmPath + "manor/manor.htm"; break; // TODO: correct in html's to 1 case 4: filename = StaticHtmPath.ChamberlainHtmPath + "manor/manor_help00" + st.nextToken() + ".htm"; break; default: filename = StaticHtmPath.ChamberlainHtmPath + "chamberlain-no.htm"; break; } } if (filename.length() != 0) { NpcHtmlMessage html = new NpcHtmlMessage(getObjectId()); html.setFile(filename, player); html.replace("%objectId%", String.valueOf(getObjectId())); html.replace("%npcname%", getName()); player.sendPacket(html); } return; } else if (command.startsWith("manor_menu_select")) { if (CastleManorManager.getInstance().isUnderMaintenance()) { player.sendPacket(ActionFailed.STATIC_PACKET); player.sendPacket(SystemMessageId.THE_MANOR_SYSTEM_IS_CURRENTLY_UNDER_MAINTENANCE); return; } String params = command.substring(command.indexOf("?") + 1); StringTokenizer str = new StringTokenizer(params, "&"); int ask = Integer.parseInt(str.nextToken().split("=")[1]); int state = Integer.parseInt(str.nextToken().split("=")[1]); int time = Integer.parseInt(str.nextToken().split("=")[1]); int castleId; if (state == -1) // info for current manor castleId = getCastle().getCastleId(); else // info for requested manor castleId = state; switch (ask) { case 3: // Current seeds (Manor info) if (time == 1 && !CastleManager.getInstance().getCastleById(castleId).isNextPeriodApproved()) player.sendPacket(new ExShowSeedInfo(castleId, null)); else player.sendPacket(new ExShowSeedInfo(castleId, CastleManager.getInstance().getCastleById(castleId).getSeedProduction(time))); break; case 4: // Current crops (Manor info) if (time == 1 && !CastleManager.getInstance().getCastleById(castleId).isNextPeriodApproved()) player.sendPacket(new ExShowCropInfo(castleId, null)); else player.sendPacket(new ExShowCropInfo(castleId, CastleManager.getInstance().getCastleById(castleId).getCropProcure(time))); break; case 5: // Basic info (Manor info) player.sendPacket(new ExShowManorDefaultInfo()); break; case 7: // Edit seed setup if (getCastle().isNextPeriodApproved()) player.sendPacket(SystemMessageId.A_MANOR_CANNOT_BE_SET_UP_BETWEEN_6_AM_AND_8_PM); else player.sendPacket(new ExShowSeedSetting(getCastle().getCastleId())); break; case 8: // Edit crop setup if (getCastle().isNextPeriodApproved()) player.sendPacket(SystemMessageId.A_MANOR_CANNOT_BE_SET_UP_BETWEEN_6_AM_AND_8_PM); else player.sendPacket(new ExShowCropSetting(getCastle().getCastleId())); break; } } else if (actualCommand.equalsIgnoreCase("siege_change")) // set siege time { if (player.isClanLeader()) { if (getCastle().getSiege().getTimeRegistrationOverDate().getTimeInMillis() < Calendar.getInstance().getTimeInMillis()) sendFileMessage(player, StaticHtmPath.ChamberlainHtmPath + "siegetime1.htm"); else if (getCastle().getSiege().getIsTimeRegistrationOver()) sendFileMessage(player, StaticHtmPath.ChamberlainHtmPath + "siegetime2.htm"); else sendFileMessage(player, StaticHtmPath.ChamberlainHtmPath + "siegetime3.htm"); } else sendFileMessage(player, StaticHtmPath.ChamberlainHtmPath + "chamberlain-noprivs.htm"); return; } else if (actualCommand.equalsIgnoreCase("siege_time_set")) // set preDay { switch (Integer.parseInt(val)) { case 1: _preHour = Integer.parseInt(st.nextToken()); break; default: break; } if (_preHour != 6) { getCastle().getSiegeDate().set(Calendar.HOUR_OF_DAY, _preHour + 12); // now store the changed time and finished next Siege Time registration getCastle().getSiege().endTimeRegistration(false); sendFileMessage(player, StaticHtmPath.ChamberlainHtmPath + "siegetime8.htm"); return; } sendFileMessage(player, StaticHtmPath.ChamberlainHtmPath + "siegetime6.htm"); return; } else if (actualCommand.equals("give_crown")) { if (siegeBlocksFunction(player)) return; NpcHtmlMessage html = new NpcHtmlMessage(getObjectId()); if (player.isClanLeader()) { if (player.getInventory().getItemByItemId(6841) == null) { player.getInventory().addItem("Castle Crown", 6841, 1, player, this); SystemMessage ms = SystemMessage.getSystemMessage(SystemMessageId.EARNED_ITEM_S1); ms.addItemName(6841); player.sendPacket(ms); html.setFile(StaticHtmPath.ChamberlainHtmPath + "chamberlain-gavecrown.htm", player); html.replace("%CharName%", String.valueOf(player.getName())); html.replace("%FeudName%", String.valueOf(getCastle().getName())); } else html.setFile(StaticHtmPath.ChamberlainHtmPath + "chamberlain-hascrown.htm", player); } else html.setFile(StaticHtmPath.ChamberlainHtmPath + "chamberlain-noprivs.htm", player); player.sendPacket(html); return; } } super.onBypassFeedback(player, command); } @Override public void showChatWindow(L2PcInstance player) { player.sendPacket(ActionFailed.STATIC_PACKET); String filename = StaticHtmPath.ChamberlainHtmPath + "chamberlain-no.htm"; int condition = validateCondition(player); if (condition > COND_ALL_FALSE) { if (condition == COND_BUSY_BECAUSE_OF_SIEGE) filename = StaticHtmPath.ChamberlainHtmPath + "chamberlain-busy.htm"; else if (condition == COND_OWNER) filename = StaticHtmPath.ChamberlainHtmPath + "chamberlain.htm"; } NpcHtmlMessage html = new NpcHtmlMessage(getObjectId()); html.setFile(filename, player); html.replace("%objectId%", String.valueOf(getObjectId())); html.replace("%npcname%", getName()); player.sendPacket(html); } protected int validateCondition(L2PcInstance player) { if (getCastle() != null && getCastle().getCastleId() > 0) { if (player.getClan() != null) { if (getCastle().getSiege().getIsInProgress()) return COND_BUSY_BECAUSE_OF_SIEGE; else if (getCastle().getOwnerId() == player.getClanId()) { if (player.isClanLeader()) return COND_OWNER; return COND_CLAN_MEMBER; } } } return COND_ALL_FALSE; } private boolean validatePrivileges(L2PcInstance player, int privilege) { if ((player.getClanPrivileges() & privilege) != privilege) { NpcHtmlMessage html = new NpcHtmlMessage(getObjectId()); html.setFile(StaticHtmPath.ChamberlainHtmPath + "chamberlain-noprivs.htm", player); player.sendPacket(html); return false; } return true; } private boolean siegeBlocksFunction(L2PcInstance player) { if (getCastle().getSiege().getIsInProgress()) { NpcHtmlMessage html = new NpcHtmlMessage(getObjectId()); html.setFile(StaticHtmPath.ChamberlainHtmPath + "chamberlain-busy.htm", player); html.replace("%npcname%", String.valueOf(getName())); player.sendPacket(html); return true; } return false; } private void sendFileMessage(L2PcInstance player, String htmlMessage) { NpcHtmlMessage html = new NpcHtmlMessage(getObjectId()); html.setFile(htmlMessage, player); html.replace("%objectId%", String.valueOf(getObjectId())); html.replace("%npcname%", getName()); html.replace("%npcId%", String.valueOf(getNpcId())); html.replace("%time%", String.valueOf(getCastle().getSiegeDate().getTime())); player.sendPacket(html); } private void sendHtmlMessage(L2PcInstance player, String htmlMessage) { NpcHtmlMessage html = new NpcHtmlMessage(getObjectId()); html.setHtml(htmlMessage); html.replace("%objectId%", String.valueOf(getObjectId())); html.replace("%npcname%", getName()); player.sendPacket(html); } }