/* * 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.List; import javolution.text.TextBuilder; import silentium.gameserver.configs.EventsConfig; import silentium.gameserver.model.L2ItemInstance; import silentium.gameserver.model.L2Party; import silentium.gameserver.model.entity.sevensigns.SevenSigns; import silentium.gameserver.model.entity.sevensigns.SevenSignsFestival; import silentium.gameserver.network.SystemMessageId; import silentium.gameserver.network.serverpackets.ActionFailed; import silentium.gameserver.network.serverpackets.NpcHtmlMessage; import silentium.gameserver.network.serverpackets.SystemMessage; import silentium.gameserver.templates.StatsSet; import silentium.gameserver.templates.chars.L2NpcTemplate; /** * Festival of Darkness Guide (Seven Signs) * * @author Tempy */ public final class L2FestivalGuideInstance extends L2NpcInstance { protected int _festivalType; protected int _festivalOracle; protected int _blueStonesNeeded; protected int _greenStonesNeeded; protected int _redStonesNeeded; public L2FestivalGuideInstance(int objectId, L2NpcTemplate template) { super(objectId, template); switch (getNpcId()) { case 31127: case 31132: _festivalType = SevenSignsFestival.FESTIVAL_LEVEL_MAX_31; _festivalOracle = SevenSigns.CABAL_DAWN; _blueStonesNeeded = 900; _greenStonesNeeded = 540; _redStonesNeeded = 270; break; case 31128: case 31133: _festivalType = SevenSignsFestival.FESTIVAL_LEVEL_MAX_42; _festivalOracle = SevenSigns.CABAL_DAWN; _blueStonesNeeded = 1500; _greenStonesNeeded = 900; _redStonesNeeded = 450; break; case 31129: case 31134: _festivalType = SevenSignsFestival.FESTIVAL_LEVEL_MAX_53; _festivalOracle = SevenSigns.CABAL_DAWN; _blueStonesNeeded = 3000; _greenStonesNeeded = 1800; _redStonesNeeded = 900; break; case 31130: case 31135: _festivalType = SevenSignsFestival.FESTIVAL_LEVEL_MAX_64; _festivalOracle = SevenSigns.CABAL_DAWN; _blueStonesNeeded = 4500; _greenStonesNeeded = 2700; _redStonesNeeded = 1350; break; case 31131: case 31136: _festivalType = SevenSignsFestival.FESTIVAL_LEVEL_MAX_NONE; _festivalOracle = SevenSigns.CABAL_DAWN; _blueStonesNeeded = 6000; _greenStonesNeeded = 3600; _redStonesNeeded = 1800; break; case 31137: case 31142: _festivalType = SevenSignsFestival.FESTIVAL_LEVEL_MAX_31; _festivalOracle = SevenSigns.CABAL_DUSK; _blueStonesNeeded = 900; _greenStonesNeeded = 540; _redStonesNeeded = 270; break; case 31138: case 31143: _festivalType = SevenSignsFestival.FESTIVAL_LEVEL_MAX_42; _festivalOracle = SevenSigns.CABAL_DUSK; _blueStonesNeeded = 1500; _greenStonesNeeded = 900; _redStonesNeeded = 450; break; case 31139: case 31144: _festivalType = SevenSignsFestival.FESTIVAL_LEVEL_MAX_53; _festivalOracle = SevenSigns.CABAL_DUSK; _blueStonesNeeded = 3000; _greenStonesNeeded = 1800; _redStonesNeeded = 900; break; case 31140: case 31145: _festivalType = SevenSignsFestival.FESTIVAL_LEVEL_MAX_64; _festivalOracle = SevenSigns.CABAL_DUSK; _blueStonesNeeded = 4500; _greenStonesNeeded = 2700; _redStonesNeeded = 1350; break; case 31141: case 31146: _festivalType = SevenSignsFestival.FESTIVAL_LEVEL_MAX_NONE; _festivalOracle = SevenSigns.CABAL_DUSK; _blueStonesNeeded = 6000; _greenStonesNeeded = 3600; _redStonesNeeded = 1800; break; } } @Override public void onBypassFeedback(L2PcInstance player, String command) { if (command.startsWith("FestivalDesc")) { int val = Integer.parseInt(command.substring(13)); showChatWindow(player, val, null, true); } else if (command.startsWith("Festival")) { L2Party playerParty = player.getParty(); int val = Integer.parseInt(command.substring(9, 10)); switch (val) { case 1: // Become a Participant // Check if the festival period is active, if not then don't allow registration. if (SevenSigns.getInstance().isSealValidationPeriod()) { showChatWindow(player, 2, "a", false); return; } // Check if a festival is in progress, then don't allow registration yet. if (SevenSignsFestival.getInstance().isFestivalInitialized()) { player.sendMessage("You cannot sign up while a festival is in progress."); return; } // Check if the player is in a formed party already. if (playerParty == null) { showChatWindow(player, 2, "b", false); return; } // Check if the player is the party leader. if (!playerParty.isLeader(player)) { showChatWindow(player, 2, "c", false); return; } // Check to see if the party has at least 5 members. if (playerParty.getMemberCount() < EventsConfig.ALT_FESTIVAL_MIN_PLAYER) { showChatWindow(player, 2, "b", false); return; } // Check if all the party members are in the required level range. if (playerParty.getLevel() > SevenSignsFestival.getMaxLevelForFestival(_festivalType)) { showChatWindow(player, 2, "d", false); return; } // TODO: Check if the player has delevelled by comparing their skill levels. /* * Check to see if the player has already signed up, if they are then update the participant list providing all the required * criteria has been met. */ if (player.isFestivalParticipant()) { SevenSignsFestival.getInstance().setParticipants(_festivalOracle, _festivalType, playerParty); showChatWindow(player, 2, "f", false); return; } showChatWindow(player, 1, null, false); break; case 2: // Festival 2 xxxx int stoneType = Integer.parseInt(command.substring(11)); int stonesNeeded = 0; switch (stoneType) { case SevenSigns.SEAL_STONE_BLUE_ID: stonesNeeded = _blueStonesNeeded; break; case SevenSigns.SEAL_STONE_GREEN_ID: stonesNeeded = _greenStonesNeeded; break; case SevenSigns.SEAL_STONE_RED_ID: stonesNeeded = _redStonesNeeded; break; } if (!player.destroyItemByItemId("SevenSigns", stoneType, stonesNeeded, this, true)) return; SevenSignsFestival.getInstance().setParticipants(_festivalOracle, _festivalType, playerParty); SevenSignsFestival.getInstance().addAccumulatedBonus(_festivalType, stoneType, stonesNeeded); showChatWindow(player, 2, "e", false); break; case 3: // Score Registration // Check if the festival period is active, if not then don't register the score. if (SevenSigns.getInstance().isSealValidationPeriod()) { showChatWindow(player, 3, "a", false); return; } // Check if a festival is in progress, if it is don't register the score. if (SevenSignsFestival.getInstance().isFestivalInProgress()) { player.sendMessage("You cannot register a score while a festival is in progress."); return; } // Check if the player is in a party. if (playerParty == null) { showChatWindow(player, 3, "b", false); return; } final List<Integer> prevParticipants = SevenSignsFestival.getInstance().getPreviousParticipants(_festivalOracle, _festivalType); // Check if there are any past participants. if ((prevParticipants == null) || prevParticipants.isEmpty() || !prevParticipants.contains(player.getObjectId())) { showChatWindow(player, 3, "b", false); return; } // Check if this player was the party leader in the festival. if (player.getObjectId() != prevParticipants.get(0)) { showChatWindow(player, 3, "b", false); return; } final L2ItemInstance bloodOfferings = player.getInventory().getItemByItemId(SevenSignsFestival.FESTIVAL_OFFERING_ID); // Check if the player collected any blood offerings during the festival. if (bloodOfferings == null) { player.sendMessage("You do not have any blood offerings to contribute."); return; } final int offeringScore = bloodOfferings.getCount() * SevenSignsFestival.FESTIVAL_OFFERING_VALUE; if (!player.destroyItem("SevenSigns", bloodOfferings, this, false)) return; final boolean isHighestScore = SevenSignsFestival.getInstance().setFinalScore(player, _festivalOracle, _festivalType, offeringScore); // Send message that the contribution score has increased. player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.CONTRIB_SCORE_INCREASED_S1).addNumber(offeringScore)); if (isHighestScore) showChatWindow(player, 3, "c", false); else showChatWindow(player, 3, "d", false); break; case 4: // Current High Scores TextBuilder strBuffer = new TextBuilder("<html><body>Festival Guide:<br>These are the top scores of the week, for the "); final StatsSet dawnData = SevenSignsFestival.getInstance().getHighestScoreData(SevenSigns.CABAL_DAWN, _festivalType); final StatsSet duskData = SevenSignsFestival.getInstance().getHighestScoreData(SevenSigns.CABAL_DUSK, _festivalType); final StatsSet overallData = SevenSignsFestival.getInstance().getOverallHighestScoreData(_festivalType); final int dawnScore = dawnData.getInteger("score"); final int duskScore = duskData.getInteger("score"); int overallScore = 0; // If no data is returned, assume there is no record, or all scores are 0. if (overallData != null) overallScore = overallData.getInteger("score"); strBuffer.append(SevenSignsFestival.getFestivalName(_festivalType)).append(" festival.<br>"); if (dawnScore > 0) strBuffer.append("Dawn: ").append(calculateDate(dawnData.getString("date"))).append(". Score ").append(dawnScore).append("<br>").append(dawnData.getString("members")).append("<br>"); else strBuffer.append("Dawn: No record exists. Score 0<br>"); if (duskScore > 0) strBuffer.append("Dusk: ").append(calculateDate(duskData.getString("date"))).append(". Score ").append(duskScore).append("<br>").append(duskData.getString("members")).append("<br>"); else strBuffer.append("Dusk: No record exists. Score 0<br>"); if (overallScore > 0) { String cabalStr = "Children of Dusk"; if (overallData.getString("cabal").equals("dawn")) cabalStr = "Children of Dawn"; strBuffer.append("Consecutive top scores: ").append(calculateDate(overallData.getString("date"))).append(". Score ").append(overallScore).append("<br>Affilated side: ").append(cabalStr).append("<br>").append(overallData.getString("members")).append("<br>"); } else strBuffer.append("Consecutive top scores: No record exists. Score 0<br>"); strBuffer.append("<a action=\"bypass -h npc_").append(getObjectId()).append("_Chat 0\">Go back.</a></body></html>"); NpcHtmlMessage html = new NpcHtmlMessage(getObjectId()); html.setHtml(strBuffer.toString()); player.sendPacket(html); break; case 8: // Increase the Festival Challenge if (playerParty == null) return; if (!SevenSignsFestival.getInstance().isFestivalInProgress()) return; if (!playerParty.isLeader(player)) { showChatWindow(player, 8, "a", false); break; } if (SevenSignsFestival.getInstance().increaseChallenge(_festivalOracle, _festivalType)) showChatWindow(player, 8, "b", false); else showChatWindow(player, 8, "c", false); break; case 9: // Leave the Festival if (playerParty == null) return; /** * If the player is the party leader, remove all participants from the festival (i.e. set the party to null, when updating * the participant list) otherwise just remove this player from the "arena", and also remove them from the party. */ boolean isLeader = playerParty.isLeader(player); if (isLeader) { SevenSignsFestival.getInstance().updateParticipants(player, null); } else { SevenSignsFestival.getInstance().updateParticipants(player, playerParty); playerParty.removePartyMember(player); } break; case 0: // Distribute Accumulated Bonus if (!SevenSigns.getInstance().isSealValidationPeriod()) { player.sendMessage("Bonuses cannot be paid during the competition period."); return; } if (SevenSignsFestival.getInstance().distribAccumulatedBonus(player) > 0) showChatWindow(player, 0, "a", false); else showChatWindow(player, 0, "b", false); break; default: showChatWindow(player, val, null, false); } } else { // this class dont know any other commands, let forward // the command to the parent class super.onBypassFeedback(player, command); } } @Override public void showChatWindow(L2PcInstance player, int val) { String filename = SevenSigns.SEVEN_SIGNS_HTML_PATH; switch (getTemplate().getNpcId()) { case 31127: // case 31128: // case 31129: // Dawn Festival Guides case 31130: // case 31131: // filename += "festival/dawn_guide.htm"; break; case 31137: // case 31138: // case 31139: // Dusk Festival Guides case 31140: // case 31141: // filename += "festival/dusk_guide.htm"; break; case 31132: // case 31133: // case 31134: // case 31135: // case 31136: // Festival Witches case 31142: // case 31143: // case 31144: // case 31145: // case 31146: // filename += "festival/festival_witch.htm"; break; } // Send a Server->Client NpcHtmlMessage containing the text of the L2Npc to the L2PcInstance NpcHtmlMessage html = new NpcHtmlMessage(getObjectId()); html.setFile(filename, player); html.replace("%objectId%", String.valueOf(getObjectId())); html.replace("%festivalMins%", SevenSignsFestival.getInstance().getTimeToNextFestivalStr()); player.sendPacket(html); // Send ActionFailed to the player in order to avoid he stucks player.sendPacket(ActionFailed.STATIC_PACKET); } private void showChatWindow(L2PcInstance player, int val, String suffix, boolean isDescription) { String filename = SevenSigns.SEVEN_SIGNS_HTML_PATH + "festival/"; filename += (isDescription) ? "desc_" : "festival_"; filename += (suffix != null) ? val + suffix + ".htm" : val + ".htm"; // Send a Server->Client NpcHtmlMessage containing the text of the L2Npc to the L2PcInstance NpcHtmlMessage html = new NpcHtmlMessage(getObjectId()); html.setFile(filename, player); html.replace("%objectId%", String.valueOf(getObjectId())); html.replace("%festivalType%", SevenSignsFestival.getFestivalName(_festivalType)); html.replace("%cycleMins%", String.valueOf(SevenSignsFestival.getInstance().getMinsToNextCycle())); if (!isDescription && "2b".equals(val + suffix)) html.replace("%minFestivalPartyMembers%", String.valueOf(EventsConfig.ALT_FESTIVAL_MIN_PLAYER)); // Festival's fee if (val == 1) { html.replace("%blueStoneNeeded%", String.valueOf(_blueStonesNeeded)); html.replace("%greenStoneNeeded%", String.valueOf(_greenStonesNeeded)); html.replace("%redStoneNeeded%", String.valueOf(_redStonesNeeded)); } // If the stats or bonus table is required, construct them. else if (val == 5) html.replace("%statsTable%", getStatsTable()); else if (val == 6) html.replace("%bonusTable%", getBonusTable()); player.sendPacket(html); // Send ActionFailed to the player in order to avoid he stucks player.sendPacket(ActionFailed.STATIC_PACKET); } private final static String getStatsTable() { TextBuilder tableHtml = new TextBuilder(); // Get the scores for each of the festival level ranges (types). for (int i = 0; i < 5; i++) { int dawnScore = SevenSignsFestival.getInstance().getHighestScore(SevenSigns.CABAL_DAWN, i); int duskScore = SevenSignsFestival.getInstance().getHighestScore(SevenSigns.CABAL_DUSK, i); String festivalName = SevenSignsFestival.getFestivalName(i); String winningCabal = "Children of Dusk"; if (dawnScore > duskScore) winningCabal = "Children of Dawn"; else if (dawnScore == duskScore) winningCabal = "None"; tableHtml.append("<tr><td width=\"100\" align=\"center\">").append(festivalName).append("</td><td align=\"center\" width=\"35\">").append(duskScore).append("</td><td align=\"center\" width=\"35\">").append(dawnScore).append("</td><td align=\"center\" width=\"130\">").append(winningCabal).append("</td></tr>"); } return tableHtml.toString(); } private final static String getBonusTable() { TextBuilder tableHtml = new TextBuilder(); // Get the accumulated scores for each of the festival level ranges (types). for (int i = 0; i < 5; i++) { int accumScore = SevenSignsFestival.getInstance().getAccumulatedBonus(i); String festivalName = SevenSignsFestival.getFestivalName(i); tableHtml.append("<tr><td align=\"center\" width=\"150\">").append(festivalName).append("</td><td align=\"center\" width=\"150\">").append(accumScore).append("</td></tr>"); } return tableHtml.toString(); } private final static String calculateDate(String milliFromEpoch) { long numMillis = Long.valueOf(milliFromEpoch); Calendar calCalc = Calendar.getInstance(); calCalc.setTimeInMillis(numMillis); return calCalc.get(Calendar.YEAR) + "/" + calCalc.get(Calendar.MONTH) + "/" + calCalc.get(Calendar.DAY_OF_MONTH); } }