SHOW:
|
|
- or go back to the newest paste.
1 | diff --git a/config/CustomMods/BossSettings.ini b/config/CustomMods/BossSettings.ini | |
2 | index 1190422..729b563 100644 | |
3 | --- a/config/CustomMods/BossSettings.ini | |
4 | +++ b/config/CustomMods/BossSettings.ini | |
5 | @@ -1,4 +1,23 @@ | |
6 | +#============================================================= | |
7 | +# Custom settings | |
8 | +#============================================================= | |
9 | +# Limit of displayed raid boss per page | |
10 | +# Default: 15 | |
11 | +RaidBossInfoPageLimit = 15 | |
12 | + | |
13 | +# Limit of displayed drop per page | |
14 | +# Default: 15, Max 18 | |
15 | +RaidBossDropPageLimit = 18 | |
16 | + | |
17 | +# Displayed date format for dead raid boss | |
18 | +# Default: (MMM dd, HH:mm) | |
19 | +RaidBossDateFormat = (MMM dd, HH:mm) | |
20 | + | |
21 | +# Displayed raid boss | |
22 | +# Syntax: bossId,bossId, ... | |
23 | +RaidBossIds = 25325,29001 | |
24 | + | |
25 | #============================================================= | |
26 | # Bosses | |
27 | #============================================================= | |
28 | ||
29 | diff --git a/java/net/sf/l2j/Config.java b/java/net/sf/l2j/Config.java | |
30 | index 61cacdf..53f4314 100644 | |
31 | --- a/java/net/sf/l2j/Config.java | |
32 | +++ b/java/net/sf/l2j/Config.java | |
33 | @@ -85,6 +85,12 @@ | |
34 | public static boolean ALLOW_DUALBOX; | |
35 | public static int ALLOWED_BOXES; | |
36 | public static boolean ALLOW_DUALBOX_OLY; | |
37 | + /** Raid info*/ | |
38 | + public static int RAID_BOSS_INFO_PAGE_LIMIT; | |
39 | + public static int RAID_BOSS_DROP_PAGE_LIMIT; | |
40 | + public static String RAID_BOSS_DATE_FORMAT; | |
41 | + public static String RAID_BOSS_IDS; | |
42 | + public static List<Integer> LIST_RAID_BOSS_IDS; | |
43 | /** Clan Hall function */ | |
44 | public static boolean PVP_SAME_IP; | |
45 | public static boolean PVP_SUMON; | |
46 | @@ -1084,6 +1090,16 @@ | |
47 | private static final void loadBoss() | |
48 | { | |
49 | final ExProperties Boss = initProperties(BOSSESETTIGNS); | |
50 | + RAID_BOSS_INFO_PAGE_LIMIT = Integer.parseInt(Boss.getProperty("RaidBossInfoPageLimit", "15")); | |
51 | + RAID_BOSS_DROP_PAGE_LIMIT = Integer.parseInt(Boss.getProperty("RaidBossDropPageLimit", "15")); | |
52 | + RAID_BOSS_DATE_FORMAT = Boss.getProperty("RaidBossDateFormat", "MMM dd, HH:mm"); | |
53 | + RAID_BOSS_IDS = Boss.getProperty("RaidBossIds", "0,0"); | |
54 | + LIST_RAID_BOSS_IDS = new ArrayList<>(); | |
55 | + for (String val : RAID_BOSS_IDS.split(",")) | |
56 | + { | |
57 | + int npcId = Integer.parseInt(val); | |
58 | + LIST_RAID_BOSS_IDS.add(npcId); | |
59 | + } | |
60 | RAID_HP_REGEN_MULTIPLIER = Boss.getProperty("RaidHpRegenMultiplier", 1.); | |
61 | RAID_MP_REGEN_MULTIPLIER = Boss.getProperty("RaidMpRegenMultiplier", 1.); | |
62 | RAID_DEFENCE_MULTIPLIER = Boss.getProperty("RaidDefenceMultiplier", 1.); | |
63 | diff --git a/java/net/sf/l2j/gameserver/GameServer.java b/java/net/sf/l2j/gameserver/GameServer.java | |
64 | index 33aa989..fb95657 100644 | |
65 | --- a/java/net/sf/l2j/gameserver/GameServer.java | |
66 | +++ b/java/net/sf/l2j/gameserver/GameServer.java | |
67 | @@ -39,6 +39,7 @@ | |
68 | import net.sf.l2j.gameserver.data.manager.LotteryManager; | |
69 | import net.sf.l2j.gameserver.data.manager.PartyMatchRoomManager; | |
70 | import net.sf.l2j.gameserver.data.manager.PetitionManager; | |
71 | +import net.sf.l2j.gameserver.data.manager.RaidBossInfoManager; | |
72 | import net.sf.l2j.gameserver.data.manager.RaidBossManager; | |
73 | import net.sf.l2j.gameserver.data.manager.RaidPointManager; | |
74 | import net.sf.l2j.gameserver.data.manager.SevenSignsManager; | |
75 | @@ -57,6 +58,7 @@ | |
76 | import net.sf.l2j.gameserver.data.xml.FishData; | |
77 | import net.sf.l2j.gameserver.data.xml.HennaData; | |
78 | import net.sf.l2j.gameserver.data.xml.HerbDropData; | |
79 | +import net.sf.l2j.gameserver.data.xml.IconTable; | |
80 | import net.sf.l2j.gameserver.data.xml.InstantTeleportData; | |
81 | import net.sf.l2j.gameserver.data.xml.ItemData; | |
82 | import net.sf.l2j.gameserver.data.xml.MapRegionData; | |
83 | @@ -218,6 +220,8 @@ | |
84 | RandomAnimationTaskManager.getInstance(); | |
85 | ShadowItemTaskManager.getInstance(); | |
86 | WaterTaskManager.getInstance(); | |
87 | + RaidBossInfoManager.getInstance(); | |
88 | + IconTable.getInstance(); | |
89 | ||
90 | StringUtil.printSection("Auto Spawns"); | |
91 | AutoSpawnTable.getInstance(); | |
92 | diff --git a/java/net/sf/l2j/gameserver/data/manager/GrandBossManager.java b/java/net/sf/l2j/gameserver/data/manager/GrandBossManager.java | |
93 | index 8055a66..64f5c5a 100644 | |
94 | --- a/java/net/sf/l2j/gameserver/data/manager/GrandBossManager.java | |
95 | +++ b/java/net/sf/l2j/gameserver/data/manager/GrandBossManager.java | |
96 | @@ -10,6 +10,7 @@ | |
97 | import net.sf.l2j.commons.logging.CLogger; | |
98 | import net.sf.l2j.commons.pool.ConnectionPool; | |
99 | ||
100 | +import net.sf.l2j.Config; | |
101 | import net.sf.l2j.gameserver.data.xml.NpcData; | |
102 | import net.sf.l2j.gameserver.model.actor.instance.GrandBoss; | |
103 | ||
104 | @@ -106,6 +107,8 @@ | |
105 | public void setStatSet(int bossId, StatSet info) | |
106 | { | |
107 | _sets.put(bossId, info); | |
108 | + if (Config.LIST_RAID_BOSS_IDS.contains(bossId)) | |
109 | + RaidBossInfoManager.getInstance().updateRaidBossInfo(bossId, info.getLong("respawn_time")); | |
110 | ||
111 | updateDb(bossId, false); | |
112 | } | |
113 | diff --git a/java/net/sf/l2j/gameserver/data/manager/RaidBossInfoManager.java b/java/net/sf/l2j/gameserver/data/manager/RaidBossInfoManager.java | |
114 | new file mode 100644 | |
115 | index 0000000..79f77ea | |
116 | --- /dev/null | |
117 | +++ b/java/net/sf/l2j/gameserver/data/manager/RaidBossInfoManager.java | |
118 | @@ -0,0 +1,71 @@ | |
119 | +package net.sf.l2j.gameserver.data.manager; | |
120 | + | |
121 | +import java.sql.Connection; | |
122 | +import java.sql.PreparedStatement; | |
123 | +import java.sql.ResultSet; | |
124 | +import java.util.Map; | |
125 | +import java.util.concurrent.ConcurrentHashMap; | |
126 | +import java.util.logging.Logger; | |
127 | + | |
128 | +import net.sf.l2j.commons.pool.ConnectionPool; | |
129 | + | |
130 | +import net.sf.l2j.Config; | |
131 | + | |
132 | +public class RaidBossInfoManager | |
133 | +{ | |
134 | + private static final Logger _log = Logger.getLogger(RaidBossInfoManager.class.getName()); | |
135 | + private final Map<Integer, Long> _raidBosses; | |
136 | + | |
137 | + protected RaidBossInfoManager() | |
138 | + { | |
139 | + _raidBosses = new ConcurrentHashMap<>(); | |
140 | + load(); | |
141 | + } | |
142 | + | |
143 | + public void load() | |
144 | + { | |
145 | + try (Connection con = ConnectionPool.getConnection(); | |
146 | + PreparedStatement statement = con.prepareStatement("SELECT boss_id, respawn_time FROM grandboss_data UNION SELECT boss_id, respawn_time FROM raidboss_spawnlist ORDER BY boss_id")) | |
147 | + { | |
148 | + try (ResultSet rs = statement.executeQuery()) | |
149 | + { | |
150 | + while (rs.next()) | |
151 | + { | |
152 | + int bossId = rs.getInt("boss_id"); | |
153 | + if (Config.LIST_RAID_BOSS_IDS.contains(bossId)) | |
154 | + _raidBosses.put(bossId, rs.getLong("respawn_time")); | |
155 | + | |
156 | + /*if (Config.LIST_RAID_BOSS_IDS2.contains(bossId)) | |
157 | + _raidBosses.put(bossId, rs.getLong("respawn_time")); | |
158 | + if (Config.LIST_RAID_BOSS_IDS3.contains(bossId)) | |
159 | + _raidBosses.put(bossId, rs.getLong("respawn_time"));*/ | |
160 | + } | |
161 | + } | |
162 | + } | |
163 | + catch (Exception e) | |
164 | + { | |
165 | + _log.warning("Exception: RaidBossInfoManager load: " + e); | |
166 | + } | |
167 | + _log.info("RaidBossInfoManager: Loaded " + _raidBosses.size() + " instances."); | |
168 | + } | |
169 | + | |
170 | + public void updateRaidBossInfo(int bossId, long respawnTime) | |
171 | + { | |
172 | + _raidBosses.put(bossId, respawnTime); | |
173 | + } | |
174 | + | |
175 | + public long getRaidBossRespawnTime(int bossId) | |
176 | + { | |
177 | + return _raidBosses.get(bossId); | |
178 | + } | |
179 | + | |
180 | + public static RaidBossInfoManager getInstance() | |
181 | + { | |
182 | + return SingletonHolder._instance; | |
183 | + } | |
184 | + | |
185 | + private static class SingletonHolder | |
186 | + { | |
187 | + protected static final RaidBossInfoManager _instance = new RaidBossInfoManager(); | |
188 | + } | |
189 | +} | |
190 | \ No newline at end of file | |
191 | diff --git a/java/net/sf/l2j/gameserver/data/xml/IconTable.java b/java/net/sf/l2j/gameserver/data/xml/IconTable.java | |
192 | new file mode 100644 | |
193 | index 0000000..08bbfec | |
194 | --- /dev/null | |
195 | +++ b/java/net/sf/l2j/gameserver/data/xml/IconTable.java | |
196 | @@ -0,0 +1,96 @@ | |
197 | +/* | |
198 | + * This program is free software: you can redistribute it and/or modify it under | |
199 | + * the terms of the GNU General Public License as published by the Free Software | |
200 | + * Foundation, either version 3 of the License, or (at your option) any later | |
201 | + * version. | |
202 | + * | |
203 | + * This program is distributed in the hope that it will be useful, but WITHOUT | |
204 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
205 | + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more | |
206 | + * details. | |
207 | + * | |
208 | + * You should have received a copy of the GNU General Public License along with | |
209 | + * this program. If not, see <http://www.gnu.org/licenses/>. | |
210 | + */ | |
211 | +package net.sf.l2j.gameserver.data.xml; | |
212 | + | |
213 | +import java.io.File; | |
214 | +import java.util.Map; | |
215 | +import java.util.concurrent.ConcurrentHashMap; | |
216 | +import java.util.logging.Level; | |
217 | +import java.util.logging.Logger; | |
218 | + | |
219 | +import net.sf.l2j.gameserver.xmlfactory.XMLDocumentFactory; | |
220 | + | |
221 | +import org.w3c.dom.Document; | |
222 | +import org.w3c.dom.NamedNodeMap; | |
223 | +import org.w3c.dom.Node; | |
224 | +/** | |
225 | + * | |
226 | + * @author Sarada | |
227 | + * | |
228 | + */ | |
229 | +public class IconTable | |
230 | +{ | |
231 | + private static final Logger _log = Logger.getLogger(IconTable.class.getName()); | |
232 | + | |
233 | + private static Map<Integer, String> _icons = new ConcurrentHashMap<>(); | |
234 | + | |
235 | + public static final IconTable getInstance() | |
236 | + { | |
237 | + return SingletonHolder._instance; | |
238 | + } | |
239 | + | |
240 | + protected IconTable() | |
241 | + { | |
242 | + | |
243 | + load(); | |
244 | + } | |
245 | + | |
246 | + private static void load() | |
247 | + { | |
248 | + try | |
249 | + { | |
250 | + File f = new File("./data/xml/icons.xml"); | |
251 | + Document doc = XMLDocumentFactory.getInstance().loadDocument(f); | |
252 | + | |
253 | + Node n = doc.getFirstChild(); | |
254 | + for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling()) | |
255 | + { | |
256 | + if (d.getNodeName().equalsIgnoreCase("icon")) | |
257 | + { | |
258 | + NamedNodeMap attrs = d.getAttributes(); | |
259 | + | |
260 | + int itemId = Integer.valueOf(attrs.getNamedItem("itemId").getNodeValue()); | |
261 | + String iconName = attrs.getNamedItem("iconName").getNodeValue(); | |
262 | + | |
263 | + if (itemId == 0 && itemId < 0) | |
264 | + { | |
265 | + _log.log(Level.WARNING, "Icon Table: itemId=\"" + itemId + "\" is not item ID, Ignoring it!"); | |
266 | + continue; | |
267 | + } | |
268 | + _icons.put(itemId, iconName); | |
269 | + } | |
270 | + } | |
271 | + } | |
272 | + catch (Exception e) | |
273 | + { | |
274 | + _log.log(Level.WARNING, "Icon Table: Error loading from database: " + e.getMessage(), e); | |
275 | + } | |
276 | + | |
277 | + _log.info("Icon Table: Loaded " + _icons.size() + " icons."); | |
278 | + } | |
279 | + | |
280 | + public static String getIcon(int id) | |
281 | + { | |
282 | + if (_icons.get(id) == null) | |
283 | + return "icon.NOIMAGE"; | |
284 | + | |
285 | + return _icons.get(id); | |
286 | + } | |
287 | + | |
288 | + private static class SingletonHolder | |
289 | + { | |
290 | + protected static final IconTable _instance = new IconTable(); | |
291 | + } | |
292 | +} | |
293 | \ No newline at end of file | |
294 | diff --git a/java/net/sf/l2j/gameserver/model/actor/Npc.java b/java/net/sf/l2j/gameserver/model/actor/Npc.java | |
295 | index 9b5c4fb..17a0088 100644 | |
296 | --- a/java/net/sf/l2j/gameserver/model/actor/Npc.java | |
297 | +++ b/java/net/sf/l2j/gameserver/model/actor/Npc.java | |
298 | @@ -3,7 +3,9 @@ | |
299 | import java.text.DateFormat; | |
300 | import java.util.ArrayList; | |
301 | import java.util.List; | |
302 | +import java.util.Map; | |
303 | import java.util.StringTokenizer; | |
304 | +import java.util.concurrent.ConcurrentHashMap; | |
305 | ||
306 | import net.sf.l2j.commons.lang.StringUtil; | |
307 | import net.sf.l2j.commons.pool.ThreadPool; | |
308 | @@ -94,7 +96,19 @@ | |
309 | private final SiegableHall _siegableHall; | |
310 | ||
311 | private boolean _isCoreAiDisabled; | |
312 | - | |
313 | + protected static final int PAGE_LIMIT = Config.RAID_BOSS_DROP_PAGE_LIMIT; | |
314 | + protected static final Map<Integer, Integer> LAST_PAGE = new ConcurrentHashMap<>(); | |
315 | + protected static final String[][] MESSAGE = | |
316 | + { | |
317 | + { | |
318 | + "<font color=\"LEVEL\">%player%</font>, are you not afraid?", | |
319 | + "Be careful <font color=\"LEVEL\">%player%</font>!" | |
320 | + }, | |
321 | + { | |
322 | + "Here is the drop list of <font color=\"LEVEL\">%boss%</font>!", | |
323 | + "Seems that <font color=\"LEVEL\">%boss%</font> has good drops." | |
324 | + }, | |
325 | + }; | |
326 | public Npc(int objectId, NpcTemplate template) | |
327 | { | |
328 | super(objectId, template); | |
329 | diff --git a/java/net/sf/l2j/gameserver/model/actor/instance/RaidBossInfo.java b/java/net/sf/l2j/gameserver/model/actor/instance/RaidBossInfo.java | |
330 | new file mode 100644 | |
331 | index 0000000..4a17556 | |
332 | --- /dev/null | |
333 | +++ b/java/net/sf/l2j/gameserver/model/actor/instance/RaidBossInfo.java | |
334 | @@ -0,0 +1,328 @@ | |
335 | +/* | |
336 | +* This program is free software: you can redistribute it and/or modify it under | |
337 | +* the terms of the GNU General Public License as published by the Free Software | |
338 | +* Foundation, either version 3 of the License, or (at your option) any later | |
339 | +* version. | |
340 | +* | |
341 | +* This program is distributed in the hope that it will be useful, but WITHOUT | |
342 | +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
343 | +* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more | |
344 | +* details. | |
345 | +* | |
346 | +* You should have received a copy of the GNU General Public License along with | |
347 | +* this program. If not, see <http://www.gnu.org/licenses/>. | |
348 | +*/ | |
349 | +package net.sf.l2j.gameserver.model.actor.instance; | |
350 | + | |
351 | +import java.text.DecimalFormat; | |
352 | +import java.text.SimpleDateFormat; | |
353 | +import java.util.ArrayList; | |
354 | +import java.util.Collections; | |
355 | +import java.util.Date; | |
356 | +import java.util.List; | |
357 | +import java.util.Map; | |
358 | +import java.util.StringTokenizer; | |
359 | +import java.util.concurrent.ConcurrentHashMap; | |
360 | + | |
361 | +import net.sf.l2j.commons.lang.StringUtil; | |
362 | +import net.sf.l2j.commons.random.Rnd; | |
363 | + | |
364 | +import net.sf.l2j.Config; | |
365 | +import net.sf.l2j.gameserver.data.manager.RaidBossInfoManager; | |
366 | +import net.sf.l2j.gameserver.data.xml.IconTable; | |
367 | +import net.sf.l2j.gameserver.data.xml.ItemData; | |
368 | +import net.sf.l2j.gameserver.data.xml.NpcData; | |
369 | +import net.sf.l2j.gameserver.model.actor.Player; | |
370 | +import net.sf.l2j.gameserver.model.actor.template.NpcTemplate; | |
371 | +import net.sf.l2j.gameserver.model.item.DropCategory; | |
372 | +import net.sf.l2j.gameserver.model.item.DropData; | |
373 | +import net.sf.l2j.gameserver.model.item.kind.Item; | |
374 | +import net.sf.l2j.gameserver.network.serverpackets.ActionFailed; | |
375 | +import net.sf.l2j.gameserver.network.serverpackets.NpcHtmlMessage; | |
376 | + | |
377 | +public class RaidBossInfo extends Folk | |
378 | +{ | |
379 | +private final Map<Integer, Integer> _lastPage = new ConcurrentHashMap<>(); | |
380 | + | |
381 | +private final String[][] _messages = | |
382 | +{ | |
383 | +{ | |
384 | +"<font color=\"LEVEL\">%player%</font>, are you not afraid?", | |
385 | +"Be careful <font color=\"LEVEL\">%player%</font>!" | |
386 | +}, | |
387 | +{ | |
388 | +"Here is the drop list of <font color=\"LEVEL\">%boss%</font>!", | |
389 | +"Seems that <font color=\"LEVEL\">%boss%</font> has good drops." | |
390 | +}, | |
391 | +}; | |
392 | + | |
393 | +public RaidBossInfo(int objectId, NpcTemplate template) | |
394 | +{ | |
395 | +super(objectId, template); | |
396 | +} | |
397 | + | |
398 | +@Override | |
399 | +public void showChatWindow(Player player, int val) | |
400 | +{ | |
401 | +String name = "data/html/mods/raidbossinfo/" + getNpcId() + ".htm"; | |
402 | +if (val != 0) | |
403 | +name = "data/html/mods/raidbossinfo/" + getNpcId() + "-" + val + ".htm"; | |
404 | + | |
405 | +NpcHtmlMessage html = new NpcHtmlMessage(getObjectId()); | |
406 | +html.setFile(name); | |
407 | +html.replace("%objectId%", getObjectId()); | |
408 | +player.sendPacket(html); | |
409 | +player.sendPacket(ActionFailed.STATIC_PACKET); | |
410 | +} | |
411 | + | |
412 | +@Override | |
413 | +public void onBypassFeedback(Player player, String command) | |
414 | +{ | |
415 | +StringTokenizer st = new StringTokenizer(command, " "); | |
416 | +String currentCommand = st.nextToken(); | |
417 | + | |
418 | +if (currentCommand.startsWith("RaidBossInfo")) | |
419 | +{ | |
420 | +int pageId = Integer.parseInt(st.nextToken()); | |
421 | +_lastPage.put(player.getObjectId(), pageId); | |
422 | +showRaidBossInfo(player, pageId); | |
423 | +} | |
424 | +else if (currentCommand.startsWith("RaidBossDrop")) | |
425 | +{ | |
426 | +int bossId = Integer.parseInt(st.nextToken()); | |
427 | +int pageId = st.hasMoreTokens() ? Integer.parseInt(st.nextToken()) : 1; | |
428 | +showRaidBossDrop(player, bossId, pageId); | |
429 | +} | |
430 | + | |
431 | +super.onBypassFeedback(player, command); | |
432 | +} | |
433 | + | |
434 | +private void showRaidBossInfo(Player player, int pageId) | |
435 | +{ | |
436 | +List<Integer> infos = new ArrayList<>(); | |
437 | +infos.addAll(Config.LIST_RAID_BOSS_IDS); | |
438 | + | |
439 | +final int limit = Config.RAID_BOSS_INFO_PAGE_LIMIT; | |
440 | +final int max = infos.size() / limit + (infos.size() % limit == 0 ? 0 : 1); | |
441 | +infos = infos.subList((pageId - 1) * limit, Math.min(pageId * limit, infos.size())); | |
442 | + | |
443 | +final StringBuilder sb = new StringBuilder(); | |
444 | +sb.append("<html>"); | |
445 | +sb.append("<center>"); | |
446 | +sb.append("<body>"); | |
447 | +sb.append("<table><tr>"); | |
448 | +sb.append("<td width=32><img src=Icon.etc_alphabet_b_i00 height=32 width=32></td>"); | |
449 | +sb.append("<td width=32><img src=Icon.etc_alphabet_i_i00 height=32 width=32></td>"); | |
450 | +sb.append("<td width=32><img src=Icon.etc_alphabet_g_i00 height=32 width=32></td>"); | |
451 | +sb.append("<td width=32><img src=Icon.etc_alphabet_b_i00 height=32 width=32></td>"); | |
452 | +sb.append("<td width=32><img src=Icon.etc_alphabet_o_i00 height=32 width=32></td>"); | |
453 | +sb.append("<td width=32><img src=Icon.etc_alphabet_s_i00 height=32 width=32></td>"); | |
454 | +sb.append("<td width=32><img src=Icon.etc_alphabet_s_i00 height=32 width=32></td>"); | |
455 | +sb.append("</tr></table><br>"); | |
456 | + | |
457 | +sb.append("<img src=\"L2UI.SquareGray\" width=300 height=1>"); | |
458 | +sb.append("<table bgcolor=\"000000\" width=\"318\">"); | |
459 | +sb.append("<tr><td><center>" + _messages[0][Rnd.get(_messages.length)].replace("%player%", player.getName()) + "</center></td></tr>"); | |
460 | +sb.append("<tr><td><center><font color=\"FF8C00\">Raid Boss Infos</font></center></td></tr>"); | |
461 | +sb.append("</table>"); | |
462 | +sb.append("<img src=\"L2UI.SquareGray\" width=300 height=1>"); | |
463 | + | |
464 | +sb.append("<table bgcolor=\"000000\" width=\"318\">"); | |
465 | + | |
466 | +for (int bossId : infos) | |
467 | +{ | |
468 | +final NpcTemplate template = NpcData.getInstance().getTemplate(bossId); | |
469 | +if (template == null) | |
470 | +continue; | |
471 | + | |
472 | +String bossName = template.getName(); | |
473 | +if (bossName.length() > 23) | |
474 | +bossName = bossName.substring(0, 23) + "..."; | |
475 | + | |
476 | +final long respawnTime = RaidBossInfoManager.getInstance().getRaidBossRespawnTime(bossId); | |
477 | +if (respawnTime <= System.currentTimeMillis()) | |
478 | +{ | |
479 | +sb.append("<tr>"); | |
480 | +sb.append("<td><a action=\"bypass -h npc_%objectId%_RaidBossDrop " + bossId + "\">" + bossName + "</a></td>"); | |
481 | +sb.append("<td><font color=\"9CC300\">Alive</font></td>"); | |
482 | +sb.append("</tr>"); | |
483 | +} | |
484 | +else | |
485 | +{ | |
486 | +sb.append("<tr>"); | |
487 | +sb.append("<td width=\"159\" align=\"left\"><a action=\"bypass -h npc_%objectId%_RaidBossDrop " + bossId + "\">" + bossName + "</a></td>"); | |
488 | +sb.append("<td width=\"159\" align=\"left\"><font color=\"FB5858\">Dead</font> " + new SimpleDateFormat(Config.RAID_BOSS_DATE_FORMAT).format(new Date(respawnTime)) + "</td>"); | |
489 | +sb.append("</tr>"); | |
490 | +} | |
491 | +} | |
492 | +sb.append("</table>"); | |
493 | + | |
494 | +sb.append("<img src=\"L2UI.SquareGray\" width=300 height=1>"); | |
495 | + | |
496 | +sb.append("<table width=\"300\" cellspacing=\"2\">"); | |
497 | +sb.append("<tr>"); | |
498 | +for (int x = 0; x < max; x++) | |
499 | +{ | |
500 | + final int pageNr = x + 1; | |
501 | + if (pageId == pageNr) | |
502 | + sb.append("<td align=\"center\">" + pageNr + "</td>"); | |
503 | + else | |
504 | + sb.append("<td align=\"center\"><a action=\"bypass -h npc_%objectId%_RaidBossInfo " + pageNr + "\">" + pageNr + "</a></td>"); | |
505 | +} | |
506 | +sb.append("</tr>"); | |
507 | +sb.append("</table>"); | |
508 | + | |
509 | +sb.append("<img src=\"L2UI.SquareGray\" width=300 height=1>"); | |
510 | + | |
511 | +sb.append("<table bgcolor=\"000000\" width=\"350\">"); | |
512 | +sb.append("<tr><td><center><a action=\"bypass -h npc_%objectId%_Chat 0\">Return</a></center></td></tr>"); | |
513 | +sb.append("</table>"); | |
514 | +sb.append("<img src=\"L2UI.SquareGray\" width=300 height=1>"); | |
515 | + | |
516 | + | |
517 | +sb.append("</center>"); | |
518 | +sb.append("</body>"); | |
519 | +sb.append("</html>"); | |
520 | + | |
521 | +final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId()); | |
522 | +html.setHtml(sb.toString()); | |
523 | +html.replace("%name%", getName()); | |
524 | +html.replace("%objectId%", getObjectId()); | |
525 | +player.sendPacket(html); | |
526 | +} | |
527 | + | |
528 | +private void showRaidBossDrop(Player player, int npcId, int page) | |
529 | +{ | |
530 | + final NpcTemplate template = NpcData.getInstance().getTemplate(npcId); | |
531 | + if (template == null) | |
532 | + return; | |
533 | + | |
534 | + if (template.getDropData().isEmpty()) | |
535 | + { | |
536 | + player.sendMessage("This target have not drop info."); | |
537 | + return; | |
538 | + } | |
539 | + | |
540 | + final List<DropCategory> list = new ArrayList<>(); | |
541 | + template.getDropData().forEach(c -> list.add(c)); | |
542 | + Collections.reverse(list); | |
543 | + | |
544 | + int myPage = 1; | |
545 | + int i = 0; | |
546 | + int shown = 0; | |
547 | + boolean hasMore = false; | |
548 | + | |
549 | + final StringBuilder sb = new StringBuilder(); | |
550 | + sb.append("<html>"); | |
551 | + sb.append("<center>"); | |
552 | + sb.append("<body>"); | |
553 | + sb.append("<table width=\"256\">"); | |
554 | + sb.append("<tr><td width=\"256\" align=\"center\">%name%</td></tr>"); | |
555 | + sb.append("</table>"); | |
556 | + sb.append("<br>"); | |
557 | + sb.append("<table width=\"256\">"); | |
558 | + sb.append("<tr><td width=\"256\" align=\"left\">" + MESSAGE[1][Rnd.get(MESSAGE.length)].replace("%boss%", template.getName()) + "</td></tr>"); | |
559 | + sb.append("</table>"); | |
560 | + sb.append("<br>"); | |
561 | + sb.append("<table width=\"224\" bgcolor=\"000000\">"); | |
562 | + sb.append("<tr><td width=\"224\" align=\"center\">Raid Boss Drops</td></tr>"); | |
563 | + sb.append("</table>"); | |
564 | + sb.append("<br>"); | |
565 | + | |
566 | + for (DropCategory cat : list) | |
567 | + { | |
568 | + if (shown == PAGE_LIMIT) | |
569 | + { | |
570 | + hasMore = true; | |
571 | + break; | |
572 | + } | |
573 | + | |
574 | + for (DropData drop : cat.getAllDrops()) | |
575 | + { | |
576 | + final double chance = Math.min(100, (((drop.getItemId() == 57) ? drop.getChance() * Config.RATE_DROP_ADENA : drop.getChance() * Config.RATE_DROP_ITEMS) / 10000)); | |
577 | + final Item item = ItemData.getInstance().getTemplate(drop.getItemId()); | |
578 | + | |
579 | + String name = item.getName(); | |
580 | + if (name.startsWith("Recipe: ")) | |
581 | + name = "R: " + name.substring(8); | |
582 | + | |
583 | + if (name.length() >= 45) | |
584 | + name = name.substring(0, 42) + "..."; | |
585 | + | |
586 | + String percent = null; | |
587 | + if (chance <= 0.001) | |
588 | + { | |
589 | + DecimalFormat df = new DecimalFormat("#.####"); | |
590 | + percent = df.format(chance); | |
591 | + } | |
592 | + else if (chance <= 0.01) | |
593 | + { | |
594 | + DecimalFormat df = new DecimalFormat("#.###"); | |
595 | + percent = df.format(chance); | |
596 | + } | |
597 | + else | |
598 | + { | |
599 | + DecimalFormat df = new DecimalFormat("##.##"); | |
600 | + percent = df.format(chance); | |
601 | + } | |
602 | + | |
603 | + if (myPage != page) | |
604 | + { | |
605 | + i++; | |
606 | + if (i == PAGE_LIMIT) | |
607 | + { | |
608 | + myPage++; | |
609 | + i = 0; | |
610 | + } | |
611 | + continue; | |
612 | + } | |
613 | + | |
614 | + if (shown == PAGE_LIMIT) | |
615 | + { | |
616 | + hasMore = true; | |
617 | + break; | |
618 | + } | |
619 | + | |
620 | + sb.append(((shown % 2) == 0 ? "<table width=\"280\" bgcolor=\"000000\"><tr>" : "<table width=\"280\"><tr>")); | |
621 | + sb.append("<td width=44 height=41 align=center><table bgcolor=" + (cat.isSweep() ? "FF00FF" : "FFFFFF") + " cellpadding=6 cellspacing=\"-5\"><tr><td><button width=32 height=32 back=" + IconTable.getIcon(item.getItemId()) + " fore=" + IconTable.getIcon(item.getItemId()) + "></td></tr></table></td>"); | |
622 | + sb.append("<td width=240>" + (cat.isSweep() ? ("<font color=ff00ff>" + name + "</font>") : name) + "<br1><font color=B09878>" + (cat.isSweep() ? "Spoil" : "Drop") + " Chance : " + percent + "%</font></td>"); | |
623 | + sb.append("</tr></table><img src=L2UI.SquareGray width=280 height=1>"); | |
624 | + shown++; | |
625 | + } | |
626 | + } | |
627 | + | |
628 | + // Build page footer. | |
629 | + sb.append("<br><img src=\"L2UI.SquareGray\" width=277 height=1><table width=\"100%\" bgcolor=000000><tr>"); | |
630 | + | |
631 | + if (page > 1) | |
632 | + StringUtil.append(sb, "<td align=left width=70><a action=\"bypass -h npc_%objectId%_RaidBossDrop "+ npcId + " ", (page - 1), "\">Previous</a></td>"); | |
633 | + else | |
634 | + StringUtil.append(sb, "<td align=left width=70>Previous</td>"); | |
635 | + | |
636 | + StringUtil.append(sb, "<td align=center width=100>Page ", page, "</td>"); | |
637 | + | |
638 | + if (page < shown) | |
639 | + StringUtil.append(sb, "<td align=right width=70>" + (hasMore ? "<a action=\"bypass -h npc_%objectId%_RaidBossDrop " + npcId + " " + (page + 1) + "\">Next</a>" : "") + "</td>"); | |
640 | + else | |
641 | + StringUtil.append(sb, "<td align=right width=70>Next</td>"); | |
642 | + | |
643 | + sb.append("</tr></table><img src=\"L2UI.SquareGray\" width=277 height=1>"); | |
644 | + sb.append("<br>"); | |
645 | + sb.append("<center>"); | |
646 | + sb.append("<table width=\"160\" cellspacing=\"2\">"); | |
647 | + sb.append("<tr>"); | |
648 | + sb.append("<td width=\"160\" align=\"center\"><a action=\"bypass -h npc_%objectId%_RaidBossInfo " + _lastPage.get(player.getObjectId()) + "\">Return</a></td>"); | |
649 | + sb.append("</tr>"); | |
650 | + sb.append("</table>"); | |
651 | + sb.append("</center>"); | |
652 | + sb.append("</body>"); | |
653 | + sb.append("</html>"); | |
654 | + | |
655 | + final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId()); | |
656 | + html.setHtml(sb.toString()); | |
657 | + html.replace("%name%", getName()); | |
658 | + html.replace("%objectId%", getObjectId()); | |
659 | + player.sendPacket(html); | |
660 | +} | |
661 | + | |
662 | +} | |
663 | \ No newline at end of file | |
664 | diff --git a/java/net/sf/l2j/gameserver/model/spawn/BossSpawn.java b/java/net/sf/l2j/gameserver/model/spawn/BossSpawn.java | |
665 | index c7c5a19..0507249 100644 | |
666 | --- a/java/net/sf/l2j/gameserver/model/spawn/BossSpawn.java | |
667 | +++ b/java/net/sf/l2j/gameserver/model/spawn/BossSpawn.java | |
668 | @@ -11,6 +11,7 @@ | |
669 | import net.sf.l2j.commons.random.Rnd; | |
670 | ||
671 | import net.sf.l2j.Config; | |
672 | +import net.sf.l2j.gameserver.data.manager.RaidBossInfoManager; | |
673 | import net.sf.l2j.gameserver.enums.BossStatus; | |
674 | import net.sf.l2j.gameserver.model.World; | |
675 | import net.sf.l2j.gameserver.model.actor.Npc; | |
676 | @@ -147,6 +148,8 @@ | |
677 | ||
678 | // Refresh the database for this particular boss entry. | |
679 | updateOnDb(); | |
680 | + if (Config.LIST_RAID_BOSS_IDS.contains(_spawn.getNpcId())) | |
681 | + RaidBossInfoManager.getInstance().updateRaidBossInfo(_spawn.getNpcId(), respawnTime); | |
682 | ||
683 | LOGGER.info("Raid boss: {} - {} ({}h).", _spawn.getNpc().getName(), new SimpleDateFormat("dd-MM-yyyy HH:mm").format(respawnTime), respawnDelay); | |
684 | } | |
685 | @@ -175,6 +178,10 @@ | |
686 | ||
687 | // Refresh the database for this particular boss entry. | |
688 | updateOnDb(); | |
689 | + | |
690 | + if (Config.LIST_RAID_BOSS_IDS.contains(npc.getNpcId())) | |
691 | + RaidBossInfoManager.getInstance().updateRaidBossInfo(npc.getNpcId(), 0); | |
692 | + | |
693 | if (Config.ANNOUNCE_BOSS_ALIVE) | |
694 | World.gameAnnounceToOnlinePlayers("Boss: " + npc.getName() + " has spawned in the world!"); | |
695 | LOGGER.info("{} raid boss has spawned.", npc.getName()); | |
696 |