NpcViewMod.java 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. /*
  2. * Copyright (C) 2004-2014 L2J DataPack
  3. *
  4. * This file is part of L2J DataPack.
  5. *
  6. * L2J DataPack is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * L2J DataPack is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. package handlers.bypasshandlers;
  20. import java.text.DecimalFormat;
  21. import java.util.List;
  22. import java.util.Map;
  23. import java.util.StringTokenizer;
  24. import java.util.concurrent.TimeUnit;
  25. import com.l2jserver.gameserver.cache.HtmCache;
  26. import com.l2jserver.gameserver.datatables.ItemTable;
  27. import com.l2jserver.gameserver.handler.IBypassHandler;
  28. import com.l2jserver.gameserver.model.Elementals;
  29. import com.l2jserver.gameserver.model.L2Object;
  30. import com.l2jserver.gameserver.model.L2Spawn;
  31. import com.l2jserver.gameserver.model.L2World;
  32. import com.l2jserver.gameserver.model.actor.L2Character;
  33. import com.l2jserver.gameserver.model.actor.L2Npc;
  34. import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
  35. import com.l2jserver.gameserver.model.drops.DropListScope;
  36. import com.l2jserver.gameserver.model.drops.GeneralDropItem;
  37. import com.l2jserver.gameserver.model.drops.GroupedGeneralDropItem;
  38. import com.l2jserver.gameserver.model.drops.IDropItem;
  39. import com.l2jserver.gameserver.model.items.L2Item;
  40. import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
  41. import com.l2jserver.gameserver.util.HtmlUtil;
  42. import com.l2jserver.gameserver.util.Util;
  43. /**
  44. * @author NosBit
  45. */
  46. public class NpcViewMod implements IBypassHandler
  47. {
  48. private static final String[] COMMANDS =
  49. {
  50. "NpcViewMod"
  51. };
  52. private static final int DROP_LIST_ITEMS_PER_PAGE = 10;
  53. @Override
  54. public boolean useBypass(String command, L2PcInstance activeChar, L2Character bypassOrigin)
  55. {
  56. final StringTokenizer st = new StringTokenizer(command);
  57. st.nextToken();
  58. if (!st.hasMoreTokens())
  59. {
  60. _log.warning("Bypass[NpcViewMod] used without enough parameters.");
  61. return false;
  62. }
  63. final String actualCommand = st.nextToken();
  64. switch (actualCommand.toLowerCase())
  65. {
  66. case "view":
  67. {
  68. final L2Object target;
  69. if (st.hasMoreElements())
  70. {
  71. try
  72. {
  73. target = L2World.getInstance().findObject(Integer.parseInt(st.nextToken()));
  74. }
  75. catch (NumberFormatException e)
  76. {
  77. return false;
  78. }
  79. }
  80. else
  81. {
  82. target = activeChar.getTarget();
  83. }
  84. final L2Npc npc = target instanceof L2Npc ? (L2Npc) target : null;
  85. if (npc == null)
  86. {
  87. return false;
  88. }
  89. NpcViewMod.sendNpcView(activeChar, npc);
  90. break;
  91. }
  92. case "droplist":
  93. {
  94. if (st.countTokens() < 2)
  95. {
  96. _log.warning("Bypass[NpcViewMod] used without enough parameters.");
  97. return false;
  98. }
  99. final String dropListScopeString = st.nextToken();
  100. try
  101. {
  102. final DropListScope dropListScope = Enum.valueOf(DropListScope.class, dropListScopeString);
  103. final L2Object target = L2World.getInstance().findObject(Integer.parseInt(st.nextToken()));
  104. final L2Npc npc = target instanceof L2Npc ? (L2Npc) target : null;
  105. if (npc == null)
  106. {
  107. return false;
  108. }
  109. final int page = st.hasMoreElements() ? Integer.parseInt(st.nextToken()) : 0;
  110. sendNpcDropList(activeChar, npc, dropListScope, page);
  111. }
  112. catch (NumberFormatException e)
  113. {
  114. return false;
  115. }
  116. catch (IllegalArgumentException e)
  117. {
  118. _log.warning("Bypass[NpcViewMod] unknown drop list scope: " + dropListScopeString);
  119. return false;
  120. }
  121. break;
  122. }
  123. }
  124. return true;
  125. }
  126. @Override
  127. public String[] getBypassList()
  128. {
  129. return COMMANDS;
  130. }
  131. public static void sendNpcView(L2PcInstance activeChar, L2Npc npc)
  132. {
  133. final NpcHtmlMessage html = new NpcHtmlMessage();
  134. html.setFile(activeChar.getHtmlPrefix(), "data/html/mods/NpcView/Info.htm");
  135. html.replace("%name%", npc.getName());
  136. html.replace("%hpGauge%", HtmlUtil.getHpGauge(250, (long) npc.getCurrentHp(), npc.getMaxHp(), false));
  137. html.replace("%mpGauge%", HtmlUtil.getMpGauge(250, (long) npc.getCurrentMp(), npc.getMaxMp(), false));
  138. final L2Spawn npcSpawn = npc.getSpawn();
  139. if ((npcSpawn == null) || (npcSpawn.getRespawnMinDelay() == 0))
  140. {
  141. html.replace("%respawn%", "None");
  142. }
  143. else
  144. {
  145. TimeUnit timeUnit = TimeUnit.MILLISECONDS;
  146. long min = Long.MAX_VALUE;
  147. for (TimeUnit tu : TimeUnit.values())
  148. {
  149. final long minTimeFromMillis = tu.convert(npcSpawn.getRespawnMinDelay(), TimeUnit.MILLISECONDS);
  150. final long maxTimeFromMillis = tu.convert(npcSpawn.getRespawnMaxDelay(), TimeUnit.MILLISECONDS);
  151. if ((TimeUnit.MILLISECONDS.convert(minTimeFromMillis, tu) == npcSpawn.getRespawnMinDelay()) && (TimeUnit.MILLISECONDS.convert(maxTimeFromMillis, tu) == npcSpawn.getRespawnMaxDelay()))
  152. {
  153. if (min > minTimeFromMillis)
  154. {
  155. min = minTimeFromMillis;
  156. timeUnit = tu;
  157. }
  158. }
  159. }
  160. final long minRespawnDelay = timeUnit.convert(npcSpawn.getRespawnMinDelay(), TimeUnit.MILLISECONDS);
  161. final long maxRespawnDelay = timeUnit.convert(npcSpawn.getRespawnMaxDelay(), TimeUnit.MILLISECONDS);
  162. final String timeUnitName = timeUnit.name().charAt(0) + timeUnit.name().toLowerCase().substring(1);
  163. if (npcSpawn.hasRespawnRandom())
  164. {
  165. html.replace("%respawn%", minRespawnDelay + "-" + maxRespawnDelay + " " + timeUnitName);
  166. }
  167. else
  168. {
  169. html.replace("%respawn%", minRespawnDelay + " " + timeUnitName);
  170. }
  171. }
  172. html.replace("%atktype%", Util.capitalizeFirst(npc.getAttackType().name().toLowerCase()));
  173. html.replace("%atkrange%", npc.getStat().getPhysicalAttackRange());
  174. html.replace("%patk%", npc.getPAtk(activeChar));
  175. html.replace("%pdef%", npc.getPDef(activeChar));
  176. html.replace("%matk%", npc.getMAtk(activeChar, null));
  177. html.replace("%mdef%", npc.getMDef(activeChar, null));
  178. html.replace("%atkspd%", npc.getPAtkSpd());
  179. html.replace("%castspd%", npc.getMAtkSpd());
  180. html.replace("%critrate%", npc.getStat().getCriticalHit(activeChar, null));
  181. html.replace("%evasion%", npc.getEvasionRate(activeChar));
  182. html.replace("%accuracy%", npc.getStat().getAccuracy());
  183. html.replace("%speed%", (int) npc.getStat().getMoveSpeed());
  184. html.replace("%attributeatktype%", Elementals.getElementName(npc.getStat().getAttackElement()));
  185. html.replace("%attributeatkvalue%", npc.getStat().getAttackElementValue(npc.getStat().getAttackElement()));
  186. html.replace("%attributefire%", npc.getStat().getDefenseElementValue(Elementals.FIRE));
  187. html.replace("%attributewater%", npc.getStat().getDefenseElementValue(Elementals.WATER));
  188. html.replace("%attributewind%", npc.getStat().getDefenseElementValue(Elementals.WIND));
  189. html.replace("%attributeearth%", npc.getStat().getDefenseElementValue(Elementals.EARTH));
  190. html.replace("%attributedark%", npc.getStat().getDefenseElementValue(Elementals.DARK));
  191. html.replace("%attributeholy%", npc.getStat().getDefenseElementValue(Elementals.HOLY));
  192. html.replace("%dropListButtons%", getDropListButtons(npc));
  193. activeChar.sendPacket(html);
  194. }
  195. public static String getDropListButtons(L2Npc npc)
  196. {
  197. final StringBuilder sb = new StringBuilder();
  198. final Map<DropListScope, List<IDropItem>> dropLists = npc.getTemplate().getDropLists();
  199. if ((dropLists != null) && !dropLists.isEmpty() && (dropLists.containsKey(DropListScope.DEATH) || dropLists.containsKey(DropListScope.CORPSE)))
  200. {
  201. sb.append("<table width=275 cellpadding=0 cellspacing=0><tr>");
  202. if (dropLists.containsKey(DropListScope.DEATH))
  203. {
  204. sb.append("<td align=center><button value=\"Show Drop\" width=100 height=25 action=\"bypass NpcViewMod dropList DEATH " + npc.getObjectId() + "\" back=\"L2UI_CT1.Button_DF_Calculator_Down\" fore=\"L2UI_CT1.Button_DF_Calculator\"></td>");
  205. }
  206. if (dropLists.containsKey(DropListScope.CORPSE))
  207. {
  208. sb.append("<td align=center><button value=\"Show Spoil\" width=100 height=25 action=\"bypass NpcViewMod dropList CORPSE " + npc.getObjectId() + "\" back=\"L2UI_CT1.Button_DF_Calculator_Down\" fore=\"L2UI_CT1.Button_DF_Calculator\"></td>");
  209. }
  210. sb.append("</tr></table>");
  211. }
  212. return sb.toString();
  213. }
  214. public static void sendNpcDropList(L2PcInstance activeChar, L2Npc npc, DropListScope dropListScope, int page)
  215. {
  216. final List<IDropItem> dropList = npc.getTemplate().getDropList(dropListScope);
  217. if ((dropList == null) || dropList.isEmpty())
  218. {
  219. return;
  220. }
  221. int pages = dropList.size() / DROP_LIST_ITEMS_PER_PAGE;
  222. if ((DROP_LIST_ITEMS_PER_PAGE * pages) < dropList.size())
  223. {
  224. pages++;
  225. }
  226. final StringBuilder pagesSb = new StringBuilder();
  227. if (pages > 1)
  228. {
  229. pagesSb.append("<table><tr>");
  230. for (int i = 0; i < pages; i++)
  231. {
  232. pagesSb.append("<td align=center><button value=\"" + (i + 1) + "\" width=20 height=20 action=\"bypass NpcViewMod dropList " + dropListScope + " " + npc.getObjectId() + " " + i + "\" back=\"L2UI_CT1.Button_DF_Calculator_Down\" fore=\"L2UI_CT1.Button_DF_Calculator\"></td>");
  233. }
  234. pagesSb.append("</tr></table>");
  235. }
  236. if (page >= pages)
  237. {
  238. page = pages - 1;
  239. }
  240. final int start = page > 0 ? page * DROP_LIST_ITEMS_PER_PAGE : 0;
  241. int end = (page * DROP_LIST_ITEMS_PER_PAGE) + DROP_LIST_ITEMS_PER_PAGE;
  242. if (end > dropList.size())
  243. {
  244. end = dropList.size();
  245. }
  246. final DecimalFormat amountFormat = new DecimalFormat("#,###");
  247. final DecimalFormat chanceFormat = new DecimalFormat("0.00##");
  248. int leftHeight = 0;
  249. int rightHeight = 0;
  250. final StringBuilder leftSb = new StringBuilder();
  251. final StringBuilder rightSb = new StringBuilder();
  252. for (int i = start; i < end; i++)
  253. {
  254. final StringBuilder sb = new StringBuilder();
  255. int height = 64;
  256. final IDropItem dropItem = dropList.get(i);
  257. if (dropItem instanceof GeneralDropItem)
  258. {
  259. final GeneralDropItem generalDropItem = (GeneralDropItem) dropItem;
  260. final L2Item item = ItemTable.getInstance().getTemplate(generalDropItem.getItemId());
  261. sb.append("<table width=332 cellpadding=2 cellspacing=0 background=\"L2UI_CT1.Windows.Windows_DF_TooltipBG\">");
  262. sb.append("<tr><td width=32 valign=top>");
  263. sb.append("<img src=\"" + item.getIcon() + "\" width=32 height=32>");
  264. sb.append("</td><td fixwidth=300 align=center><font name=\"hs9\" color=\"CD9000\">");
  265. sb.append(item.getName());
  266. sb.append("</font></td></tr><tr><td width=32></td><td width=300><table width=295 cellpadding=0 cellspacing=0>");
  267. sb.append("<tr><td width=48 align=right valign=top><font color=\"LEVEL\">Amount:</font></td>");
  268. sb.append("<td width=247 align=center>");
  269. final long min = generalDropItem.getMin(npc, activeChar);
  270. final long max = generalDropItem.getMax(npc, activeChar);
  271. if (min == max)
  272. {
  273. sb.append(amountFormat.format(min));
  274. }
  275. else
  276. {
  277. sb.append(amountFormat.format(min));
  278. sb.append(" - ");
  279. sb.append(amountFormat.format(max));
  280. }
  281. sb.append("</td></tr><tr><td width=48 align=right valign=top><font color=\"LEVEL\">Chance:</font></td>");
  282. sb.append("<td width=247 align=center>");
  283. sb.append(chanceFormat.format(Math.min(generalDropItem.getChance(npc, activeChar), 100)));
  284. sb.append("%</td></tr></table></td></tr><tr><td width=32></td><td width=300>&nbsp;</td></tr></table>");
  285. }
  286. else if (dropItem instanceof GroupedGeneralDropItem)
  287. {
  288. final GroupedGeneralDropItem generalGroupedDropItem = (GroupedGeneralDropItem) dropItem;
  289. if (generalGroupedDropItem.getItems().size() == 1)
  290. {
  291. final GeneralDropItem generalDropItem = generalGroupedDropItem.getItems().get(0);
  292. final L2Item item = ItemTable.getInstance().getTemplate(generalDropItem.getItemId());
  293. sb.append("<table width=332 cellpadding=2 cellspacing=0 background=\"L2UI_CT1.Windows.Windows_DF_TooltipBG\">");
  294. sb.append("<tr><td width=32 valign=top>");
  295. sb.append("<img src=\"" + item.getIcon() + "\" width=32 height=32>");
  296. sb.append("</td><td fixwidth=300 align=center><font name=\"hs9\" color=\"CD9000\">");
  297. sb.append(item.getName());
  298. sb.append("</font></td></tr><tr><td width=32></td><td width=300><table width=295 cellpadding=0 cellspacing=0>");
  299. sb.append("<tr><td width=48 align=right valign=top><font color=\"LEVEL\">Amount:</font></td>");
  300. sb.append("<td width=247 align=center>");
  301. final long min = generalDropItem.getMin(npc, activeChar);
  302. final long max = generalDropItem.getMax(npc, activeChar);
  303. if (min == max)
  304. {
  305. sb.append(amountFormat.format(min));
  306. }
  307. else
  308. {
  309. sb.append(amountFormat.format(min));
  310. sb.append(" - ");
  311. sb.append(amountFormat.format(max));
  312. }
  313. sb.append("</td></tr><tr><td width=48 align=right valign=top><font color=\"LEVEL\">Chance:</font></td>");
  314. sb.append("<td width=247 align=center>");
  315. sb.append(chanceFormat.format(Math.min(generalGroupedDropItem.getChance(npc, activeChar), 100)));
  316. sb.append("%</td></tr></table></td></tr><tr><td width=32></td><td width=300>&nbsp;</td></tr></table>");
  317. }
  318. else
  319. {
  320. sb.append("<table width=332 cellpadding=2 cellspacing=0 background=\"L2UI_CT1.Windows.Windows_DF_TooltipBG\">");
  321. sb.append("<tr><td width=32 valign=top><img src=\"L2UI_CT1.ICON_DF_premiumItem\" width=32 height=32></td>");
  322. sb.append("<td fixwidth=300 align=center><font name=\"ScreenMessageSmall\" color=\"CD9000\">One from group</font>");
  323. sb.append("</td></tr><tr><td width=32></td><td width=300><table width=295 cellpadding=0 cellspacing=0><tr>");
  324. sb.append("<td width=48 align=right valign=top><font color=\"LEVEL\">Chance:</font></td>");
  325. sb.append("<td width=247 align=center>");
  326. sb.append(chanceFormat.format(Math.min(generalGroupedDropItem.getChance(npc, activeChar), 100)));
  327. sb.append("%</td></tr></table><br>");
  328. for (GeneralDropItem generalDropItem : generalGroupedDropItem.getItems())
  329. {
  330. final L2Item item = ItemTable.getInstance().getTemplate(generalDropItem.getItemId());
  331. sb.append("<table width=291 cellpadding=2 cellspacing=0 background=\"L2UI_CT1.Windows.Windows_DF_TooltipBG\">");
  332. sb.append("<tr><td width=32 valign=top>");
  333. sb.append("<img src=\"" + item.getIcon() + "\" width=32 height=32>");
  334. sb.append("</td><td fixwidth=259 align=center><font name=\"hs9\" color=\"CD9000\">");
  335. sb.append(item.getName());
  336. sb.append("</font></td></tr><tr><td width=32></td><td width=259><table width=253 cellpadding=0 cellspacing=0>");
  337. sb.append("<tr><td width=48 align=right valign=top><font color=\"LEVEL\">Amount:</font></td><td width=205 align=center>");
  338. final long min = generalDropItem.getMin(npc, activeChar);
  339. final long max = generalDropItem.getMax(npc, activeChar);
  340. if (min == max)
  341. {
  342. sb.append(amountFormat.format(min));
  343. }
  344. else
  345. {
  346. sb.append(amountFormat.format(min));
  347. sb.append(" - ");
  348. sb.append(amountFormat.format(max));
  349. }
  350. sb.append("</td></tr><tr><td width=48 align=right valign=top><font color=\"LEVEL\">Chance:</font></td>");
  351. sb.append("<td width=205 align=center>");
  352. sb.append(chanceFormat.format(Math.min(generalDropItem.getChance(), 100)));
  353. sb.append("%</td></tr></table></td></tr><tr><td width=32></td><td width=259>&nbsp;</td></tr></table>");
  354. height += 64;
  355. }
  356. sb.append("</td></tr><tr><td width=32></td><td width=300>&nbsp;</td></tr></table>");
  357. }
  358. }
  359. if (leftHeight >= (rightHeight + height))
  360. {
  361. rightSb.append(sb);
  362. rightHeight += height;
  363. }
  364. else
  365. {
  366. leftSb.append(sb);
  367. leftHeight += height;
  368. }
  369. }
  370. final StringBuilder bodySb = new StringBuilder();
  371. bodySb.append("<table><tr>");
  372. bodySb.append("<td>");
  373. bodySb.append(leftSb.toString());
  374. bodySb.append("</td><td>");
  375. bodySb.append(rightSb.toString());
  376. bodySb.append("</td>");
  377. bodySb.append("</tr></table>");
  378. String html = HtmCache.getInstance().getHtm(activeChar.getHtmlPrefix(), "data/html/mods/NpcView/DropList.htm");
  379. if (html == null)
  380. {
  381. _log.warning(NpcViewMod.class.getSimpleName() + ": The html file data/html/mods/NpcView/DropList.htm could not be found.");
  382. return;
  383. }
  384. html = html.replaceAll("%name%", npc.getName());
  385. html = html.replaceAll("%dropListButtons%", getDropListButtons(npc));
  386. html = html.replaceAll("%pages%", pagesSb.toString());
  387. html = html.replaceAll("%items%", bodySb.toString());
  388. Util.sendCBHtml(activeChar, html);
  389. }
  390. }