-JRGames-

New VIP Manager

Sep 22nd, 2025
617
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 39.42 KB | Source Code | 0 0
  1. diff --git a/game/data/xml/Custom/VipManager.xml b/game/data/xml/Custom/VipManager.xml
  2. new file mode 100644
  3. index 0000000..7d7e373
  4. --- /dev/null
  5. +++ b/game/data/xml/Custom/VipManager.xml
  6. @@ -0,0 +1,88 @@
  7. +<?xml version="1.0" encoding="UTF-8"?>
  8. +<VipData enabled="true">
  9. +
  10. +  <!-- BRONZE -->
  11. +  <Tier name="bronze" titleColor="#a97142" useTitleColor="true" xpRate="1.15" spRate="1.10" useXpSp="true">
  12. +    <!-- Drops -->
  13. +    <DropBonus itemId="57" addPercent="0.2"/>
  14. +    <DropBonus itemId="9300" countMul="2.0"/>
  15. +
  16. +    <!-- Enchant (global do tier) -->
  17. +    <EnchantBonus addPercent="3.0"/>
  18. +    <!-- Exemplo por scroll: +2 pp no 947 -->
  19. +    <EnchantBonus scrollId="947" addPercent="2.0"/>
  20. +  </Tier>
  21. +
  22. +  <!-- PRATA -->
  23. +  <Tier name="prata" titleColor="#c0c0c0" useTitleColor="true" xpRate="1.25" spRate="1.15" useXpSp="true">
  24. +    <!-- Drops -->
  25. +    <DropBonus itemId="57" addPercent="0.6"/>
  26. +
  27. +    <!-- Enchant: +5 pp no 947 e +10% multiplicativo no 948 -->
  28. +    <EnchantBonus scrollId="947" addPercent="5.0"/>
  29. +    <EnchantBonus scrollId="948" mulRate="1.10"/>
  30. +  </Tier>
  31. +
  32. +  <!-- OURO -->
  33. +  <Tier name="ouro" titleColor="#ffd700" useTitleColor="true" xpRate="1.35" spRate="1.20" useXpSp="true">
  34. +    <!-- Drops -->
  35. +    <DropBonus itemId="57" addPercent="1.0"/>
  36. +
  37. +    <!-- Enchant (global): +2 pp e +10% -->
  38. +    <EnchantBonus addPercent="2.0" mulRate="1.10"/>
  39. +  </Tier>
  40. +
  41. +  <!-- MASTER -->
  42. +  <Tier name="master" titleColor="#9b59b6" useTitleColor="true" xpRate="1.50" spRate="1.30" useXpSp="true">
  43. +    <!-- Drops -->
  44. +    <DropBonus itemId="57" addPercent="1.8"/>
  45. +    <DropBonus itemId="9300" countMul="2.0"/>
  46. +
  47. +    <!-- Enchant (global mais forte) -->
  48. +    <EnchantBonus addPercent="5.0" mulRate="1.15"/>
  49. +    <!-- Exemplo ainda mais forte para um scroll específico -->
  50. +    <EnchantBonus scrollId="949" addPercent="7.0" mulRate="1.20"/>
  51. +  </Tier>
  52. +
  53. +  <!-- ===== Tokens ===== -->
  54. +  <Token itemId="9301"  tier="bronze" days="3"/>
  55. +  <Token itemId="99001" tier="prata"  days="7"/>
  56. +  <Token itemId="99002" tier="ouro"   days="15"/>
  57. +  <Token itemId="99003" tier="master" days="30"/>
  58. +
  59. +</VipData>
  60. diff --git a/game/data/xml/items/custom/VipItens.xml b/game/data/xml/items/custom/VipItens.xml
  61. new file mode 100644
  62. index 0000000..071021b
  63. --- /dev/null
  64. +++ b/game/data/xml/items/custom/VipItens.xml
  65. @@ -0,0 +1,24 @@
  66. +<?xml version="1.0" encoding="UTF-8"?>
  67. +<list>
  68. +   <item id="99000" type="EtcItem" name="VIP Bronze (3 dias)">
  69. +       <set name="material" val="STEEL" />
  70. +       <set name="is_stackable" val="true" />
  71. +       <set name="handler" val="VipToken" />
  72. +   </item>
  73. +   <item id="99001" type="EtcItem" name="VIP Prata (7 dias)">
  74. +       <set name="material" val="STEEL" />
  75. +       <set name="is_stackable" val="true" />
  76. +       <set name="handler" val="VipToken" />
  77. +   </item>
  78. +   <item id="99002" type="EtcItem" name="VIP Ouro (15 dias)">
  79. +       <set name="material" val="STEEL" />
  80. +       <set name="is_stackable" val="true" />
  81. +       <set name="handler" val="VipToken" />
  82. +   </item>
  83. +   <item id="99003" type="EtcItem" name="VIP Master (30 dias)">
  84. +       <set name="material" val="STEEL" />
  85. +       <set name="is_stackable" val="true" />
  86. +       <set name="handler" val="VipToken" />
  87. +   </item>
  88. +
  89. +</list>
  90. diff --git a/java/TioPatinhas/Vip/VipDAO.java b/java/TioPatinhas/Vip/VipDAO.java
  91. new file mode 100644
  92. index 0000000..a7e99e4
  93. --- /dev/null
  94. +++ b/java/TioPatinhas/Vip/VipDAO.java
  95. @@ -0,0 +1,72 @@
  96. +package TioPatinhas.Vip;
  97. +
  98. +import java.sql.Connection;
  99. +import java.sql.PreparedStatement;
  100. +import java.sql.ResultSet;
  101. +import java.sql.Timestamp;
  102. +import java.time.LocalDateTime;
  103. +
  104. +import net.sf.l2j.L2DatabaseFactory;
  105. +
  106. +/*
  107. + * @author -= TioPatinhas =-
  108. + */
  109. +public final class VipDAO
  110. +{
  111. +   private static final String SELECT = "SELECT tier, expire_at FROM character_vip_player WHERE charId=?";
  112. +   private static final String UPSERT = "REPLACE INTO character_vip_player (charId, tier, expire_at) VALUES (?,?,?)";
  113. +   private static final String DELETE = "DELETE FROM character_vip_player WHERE charId=?";
  114. +  
  115. +   public static VipStatus load(int charId)
  116. +   {
  117. +       try (Connection con = L2DatabaseFactory.getInstance().getConnection();
  118. +           PreparedStatement ps = con.prepareStatement(SELECT))
  119. +       {
  120. +           ps.setInt(1, charId);
  121. +           try (ResultSet rs = ps.executeQuery())
  122. +           {
  123. +               if (rs.next())
  124. +               {
  125. +                   final String tier = rs.getString("tier");
  126. +                   final LocalDateTime exp = rs.getTimestamp("expire_at").toLocalDateTime();
  127. +                   return new VipStatus(tier, exp);
  128. +               }
  129. +           }
  130. +       }
  131. +       catch (Exception e)
  132. +       {
  133. +           e.printStackTrace();
  134. +       }
  135. +       return null;
  136. +   }
  137. +  
  138. +   public static void save(int charId, String tier, LocalDateTime expireAt)
  139. +   {
  140. +       try (Connection con = L2DatabaseFactory.getInstance().getConnection();
  141. +           PreparedStatement ps = con.prepareStatement(UPSERT))
  142. +       {
  143. +           ps.setInt(1, charId);
  144. +           ps.setString(2, tier);
  145. +           ps.setTimestamp(3, Timestamp.valueOf(expireAt));
  146. +           ps.executeUpdate();
  147. +       }
  148. +       catch (Exception e)
  149. +       {
  150. +           e.printStackTrace();
  151. +       }
  152. +   }
  153. +  
  154. +   public static void delete(int charId)
  155. +   {
  156. +       try (Connection con = L2DatabaseFactory.getInstance().getConnection();
  157. +           PreparedStatement ps = con.prepareStatement(DELETE))
  158. +       {
  159. +           ps.setInt(1, charId);
  160. +           ps.executeUpdate();
  161. +       }
  162. +       catch (Exception e)
  163. +       {
  164. +           e.printStackTrace();
  165. +       }
  166. +   }
  167. +}
  168. diff --git a/java/TioPatinhas/Vip/VipData.java b/java/TioPatinhas/Vip/VipData.java
  169. new file mode 100644
  170. index 0000000..cf6937c
  171. --- /dev/null
  172. +++ b/java/TioPatinhas/Vip/VipData.java
  173. @@ -0,0 +1,326 @@
  174. +package TioPatinhas.Vip;
  175. +
  176. +import java.io.File;
  177. +import java.util.Collections;
  178. +import java.util.HashMap;
  179. +import java.util.Map;
  180. +import java.util.logging.Logger;
  181. +
  182. +import javax.xml.parsers.DocumentBuilderFactory;
  183. +
  184. +import org.w3c.dom.Document;
  185. +import org.w3c.dom.NamedNodeMap;
  186. +import org.w3c.dom.Node;
  187. +
  188. +/*
  189. + * @author -= TioPatinhas =-
  190. + */
  191. +public final class VipData
  192. +{
  193. +   private static final Logger _log = Logger.getLogger(VipData.class.getName());
  194. +   private static final VipData INSTANCE = new VipData();
  195. +  
  196. +   public static VipData getInstance()
  197. +   {
  198. +       return INSTANCE;
  199. +   }
  200. +  
  201. +   private boolean _enabled = false;
  202. +  
  203. +   private final Map<String, Map<Integer, Double>> _tierChanceAdd = new HashMap<>();
  204. +   private final Map<String, Map<Integer, Double>> _tierCountMul = new HashMap<>();
  205. +   private final Map<String, String> _tierTitleColors = new HashMap<>();
  206. +   private final Map<String, Boolean> _tierUseTitleColor = new HashMap<>();
  207. +   private final Map<String, Double> _tierXpRate = new HashMap<>();
  208. +   private final Map<String, Double> _tierSpRate = new HashMap<>();
  209. +   private final Map<String, Boolean> _tierUseXpSp = new HashMap<>();
  210. +  
  211. +   private final Map<String, Double> _tierEnchantAddGlobal = new HashMap<>();
  212. +   private final Map<String, Double> _tierEnchantMulGlobal = new HashMap<>();
  213. +  
  214. +   private final Map<String, Map<Integer, Double>> _tierEnchantAddByScroll = new HashMap<>();
  215. +   private final Map<String, Map<Integer, Double>> _tierEnchantMulByScroll = new HashMap<>();
  216. +  
  217. +   public static final class TokenEntry
  218. +   {
  219. +       public final String tier;
  220. +       public final int days;
  221. +      
  222. +       public TokenEntry(String t, int d)
  223. +       {
  224. +           tier = t;
  225. +           days = d;
  226. +       }
  227. +   }
  228. +  
  229. +   private final Map<Integer, TokenEntry> _tokenByItem = new HashMap<>();
  230. +  
  231. +   private VipData()
  232. +   {
  233. +       reload();
  234. +   }
  235. +  
  236. +   public void reload()
  237. +   {
  238. +       _enabled = false;
  239. +       _tierChanceAdd.clear();
  240. +       _tierCountMul.clear();
  241. +       _tierTitleColors.clear();
  242. +       _tierUseTitleColor.clear();
  243. +       _tierXpRate.clear();
  244. +       _tierSpRate.clear();
  245. +       _tierUseXpSp.clear();
  246. +      
  247. +       _tierEnchantAddGlobal.clear();
  248. +       _tierEnchantMulGlobal.clear();
  249. +       _tierEnchantAddByScroll.clear();
  250. +       _tierEnchantMulByScroll.clear();
  251. +      
  252. +       _tokenByItem.clear();
  253. +      
  254. +       try
  255. +       {
  256. +           final File f = new File("./data/xml/Custom/VipManager.xml");
  257. +           final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
  258. +           dbf.setIgnoringComments(true);
  259. +           dbf.setExpandEntityReferences(false);
  260. +           final Document doc = dbf.newDocumentBuilder().parse(f);
  261. +           doc.getDocumentElement().normalize();
  262. +          
  263. +           final NamedNodeMap rootAttrs = doc.getDocumentElement().getAttributes();
  264. +           final Node enabledAttr = rootAttrs.getNamedItem("enabled");
  265. +           _enabled = (enabledAttr != null && Boolean.parseBoolean(enabledAttr.getNodeValue()));
  266. +          
  267. +           for (Node n = doc.getDocumentElement().getFirstChild(); n != null; n = n.getNextSibling())
  268. +           {
  269. +               if (n.getNodeType() != Node.ELEMENT_NODE)
  270. +                   continue;
  271. +              
  272. +               if ("Tier".equalsIgnoreCase(n.getNodeName()))
  273. +               {
  274. +                   final NamedNodeMap a = n.getAttributes();
  275. +                   final String name = a.getNamedItem("name").getNodeValue().toLowerCase();
  276. +                  
  277. +                   // titleColor / useTitleColor
  278. +                   Node tc = a.getNamedItem("titleColor");
  279. +                   if (tc != null)
  280. +                       _tierTitleColors.put(name, tc.getNodeValue());
  281. +                  
  282. +                   Node utc = a.getNamedItem("useTitleColor");
  283. +                   final boolean useTitle = (utc != null && Boolean.parseBoolean(utc.getNodeValue()));
  284. +                   _tierUseTitleColor.put(name, useTitle);
  285. +                  
  286. +                   // xpRate / spRate / useXpSp
  287. +                   double xpRate = 1.0, spRate = 1.0;
  288. +                   Node xr = a.getNamedItem("xpRate");
  289. +                   Node sr = a.getNamedItem("spRate");
  290. +                   if (xr != null)
  291. +                       xpRate = Double.parseDouble(xr.getNodeValue());
  292. +                   if (sr != null)
  293. +                       spRate = Double.parseDouble(sr.getNodeValue());
  294. +                   _tierXpRate.put(name, xpRate);
  295. +                   _tierSpRate.put(name, spRate);
  296. +                  
  297. +                   Node ux = a.getNamedItem("useXpSp");
  298. +                   boolean useXpSp = (ux != null && Boolean.parseBoolean(ux.getNodeValue()));
  299. +                   _tierUseXpSp.put(name, useXpSp);
  300. +                  
  301. +                   final Map<Integer, Double> chanceAdd = new HashMap<>();
  302. +                   final Map<Integer, Double> countMul = new HashMap<>();
  303. +                  
  304. +                   // ENCHANT maps locais do tier
  305. +                   final Map<Integer, Double> enchAddByScroll = new HashMap<>();
  306. +                   final Map<Integer, Double> enchMulByScroll = new HashMap<>();
  307. +                   Double enchAddGlobal = null;
  308. +                   Double enchMulGlobal = null;
  309. +                  
  310. +                   for (Node c = n.getFirstChild(); c != null; c = c.getNextSibling())
  311. +                   {
  312. +                       if (c.getNodeType() != Node.ELEMENT_NODE)
  313. +                           continue;
  314. +                      
  315. +                       final String nodeName = c.getNodeName();
  316. +                      
  317. +                       // Drops
  318. +                       if ("DropBonus".equalsIgnoreCase(nodeName))
  319. +                       {
  320. +                           final NamedNodeMap ca = c.getAttributes();
  321. +                           final int itemId = Integer.parseInt(ca.getNamedItem("itemId").getNodeValue());
  322. +                          
  323. +                           double addPercent = 0.0;
  324. +                           Node ap = ca.getNamedItem("addPercent");
  325. +                           if (ap != null)
  326. +                               addPercent = Double.parseDouble(ap.getNodeValue());
  327. +                           if (addPercent != 0.0)
  328. +                               chanceAdd.put(itemId, addPercent);
  329. +                          
  330. +                           double mul = 1.0;
  331. +                           Node cm = ca.getNamedItem("countMul");
  332. +                           if (cm != null)
  333. +                               mul = Double.parseDouble(cm.getNodeValue());
  334. +                           if (mul != 1.0)
  335. +                               countMul.put(itemId, mul);
  336. +                          
  337. +                           continue;
  338. +                       }
  339. +                      
  340. +                       // Enchant
  341. +                       if ("EnchantBonus".equalsIgnoreCase(nodeName))
  342. +                       {
  343. +                           final NamedNodeMap ca = c.getAttributes();
  344. +                           Node addN = ca.getNamedItem("addPercent");
  345. +                           Node mulN = ca.getNamedItem("mulRate");
  346. +                           Node sidN = ca.getNamedItem("scrollId");
  347. +                          
  348. +                           final Double add = (addN != null) ? Double.parseDouble(addN.getNodeValue()) : null;
  349. +                           final Double mul = (mulN != null) ? Double.parseDouble(mulN.getNodeValue()) : null;
  350. +                          
  351. +                           if (sidN != null)
  352. +                           {
  353. +                               final int scrollId = Integer.parseInt(sidN.getNodeValue());
  354. +                               if (add != null)
  355. +                                   enchAddByScroll.put(scrollId, add);
  356. +                               if (mul != null)
  357. +                                   enchMulByScroll.put(scrollId, mul);
  358. +                           }
  359. +                           else
  360. +                           {
  361. +                               if (add != null)
  362. +                                   enchAddGlobal = add;
  363. +                               if (mul != null)
  364. +                                   enchMulGlobal = mul;
  365. +                           }
  366. +                       }
  367. +                   }
  368. +                  
  369. +                   _tierChanceAdd.put(name, Collections.unmodifiableMap(chanceAdd));
  370. +                   _tierCountMul.put(name, Collections.unmodifiableMap(countMul));
  371. +                  
  372. +                   // salva enchant por-tier
  373. +                   _tierEnchantAddByScroll.put(name, Collections.unmodifiableMap(enchAddByScroll));
  374. +                   _tierEnchantMulByScroll.put(name, Collections.unmodifiableMap(enchMulByScroll));
  375. +                   if (enchAddGlobal != null)
  376. +                       _tierEnchantAddGlobal.put(name, enchAddGlobal);
  377. +                   if (enchMulGlobal != null)
  378. +                       _tierEnchantMulGlobal.put(name, enchMulGlobal);
  379. +                  
  380. +                   continue;
  381. +               }
  382. +              
  383. +               if ("Token".equalsIgnoreCase(n.getNodeName()))
  384. +               {
  385. +                   final NamedNodeMap a = n.getAttributes();
  386. +                   final int itemId = Integer.parseInt(a.getNamedItem("itemId").getNodeValue());
  387. +                   final String tier = a.getNamedItem("tier").getNodeValue().toLowerCase();
  388. +                   final int days = Integer.parseInt(a.getNamedItem("days").getNodeValue());
  389. +                   _tokenByItem.put(itemId, new TokenEntry(tier, days));
  390. +               }
  391. +           }
  392. +       }
  393. +       catch (Exception e)
  394. +       {
  395. +           e.printStackTrace();
  396. +       }
  397. +      
  398. +       _log.info("VipData: carregado " + _tierChanceAdd.size() + " tiers, " + _tokenByItem.size() + " tokens.");
  399. +   }
  400. +  
  401. +   public boolean isEnabled()
  402. +   {
  403. +       return _enabled;
  404. +   }
  405. +  
  406. +   public double getAddPercent(String tierName, int itemId)
  407. +   {
  408. +       if (!_enabled || tierName == null)
  409. +           return 0.0;
  410. +       final Map<Integer, Double> m = _tierChanceAdd.get(tierName.toLowerCase());
  411. +       return (m == null) ? 0.0 : m.getOrDefault(itemId, 0.0);
  412. +   }
  413. +  
  414. +   public double getCountMul(String tierName, int itemId)
  415. +   {
  416. +       if (!_enabled || tierName == null)
  417. +           return 1.0;
  418. +       final Map<Integer, Double> m = _tierCountMul.get(tierName.toLowerCase());
  419. +       return (m == null) ? 1.0 : m.getOrDefault(itemId, 1.0);
  420. +   }
  421. +  
  422. +   public String getTitleColor(String tierName)
  423. +   {
  424. +       if (!_enabled || tierName == null)
  425. +           return null;
  426. +       return _tierTitleColors.get(tierName.toLowerCase());
  427. +   }
  428. +  
  429. +   public boolean isUseTitleColor(String tierName)
  430. +   {
  431. +       if (!_enabled || tierName == null)
  432. +           return false;
  433. +       return _tierUseTitleColor.getOrDefault(tierName.toLowerCase(), false);
  434. +   }
  435. +  
  436. +   public boolean isUseXpSp(String tierName)
  437. +   {
  438. +       if (!_enabled || tierName == null)
  439. +           return false;
  440. +       return _tierUseXpSp.getOrDefault(tierName.toLowerCase(), false);
  441. +   }
  442. +  
  443. +   public double getXpRate(String tierName)
  444. +   {
  445. +       if (!_enabled || tierName == null)
  446. +           return 1.0;
  447. +       return _tierXpRate.getOrDefault(tierName.toLowerCase(), 1.0);
  448. +   }
  449. +  
  450. +   public double getSpRate(String tierName)
  451. +   {
  452. +       if (!_enabled || tierName == null)
  453. +           return 1.0;
  454. +       return _tierSpRate.getOrDefault(tierName.toLowerCase(), 1.0);
  455. +   }
  456. +  
  457. +   public double getEnchantAddPercent(String tierName, int scrollId)
  458. +   {
  459. +       if (!_enabled || tierName == null)
  460. +           return 0.0;
  461. +       final String t = tierName.toLowerCase();
  462. +       final Map<Integer, Double> byScroll = _tierEnchantAddByScroll.get(t);
  463. +       if (byScroll != null)
  464. +       {
  465. +           final Double v = byScroll.get(scrollId);
  466. +           if (v != null)
  467. +               return v;
  468. +       }
  469. +       return _tierEnchantAddGlobal.getOrDefault(t, 0.0);
  470. +   }
  471. +  
  472. +   public double getEnchantMulRate(String tierName, int scrollId)
  473. +   {
  474. +       if (!_enabled || tierName == null)
  475. +           return 1.0;
  476. +       final String t = tierName.toLowerCase();
  477. +       final Map<Integer, Double> byScroll = _tierEnchantMulByScroll.get(t);
  478. +       if (byScroll != null)
  479. +       {
  480. +           final Double v = byScroll.get(scrollId);
  481. +           if (v != null)
  482. +               return v;
  483. +       }
  484. +       return _tierEnchantMulGlobal.getOrDefault(t, 1.0);
  485. +   }
  486. +  
  487. +   public static int parseColor(String hex)
  488. +   {
  489. +       if (hex == null)
  490. +           return 0xFFFFFF;
  491. +       String clean = hex.replace("#", "");
  492. +       return (int) Long.parseLong(clean, 16);
  493. +   }
  494. +  
  495. +   public TokenEntry getToken(int itemId)
  496. +   {
  497. +       return _tokenByItem.get(itemId);
  498. +   }
  499. +}
  500. diff --git a/java/TioPatinhas/Vip/VipManager.java b/java/TioPatinhas/Vip/VipManager.java
  501. new file mode 100644
  502. index 0000000..19ac606
  503. --- /dev/null
  504. +++ b/java/TioPatinhas/Vip/VipManager.java
  505. @@ -0,0 +1,205 @@
  506. +package TioPatinhas.Vip;
  507. +
  508. +import java.time.Duration;
  509. +import java.time.LocalDateTime;
  510. +
  511. +import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
  512. +import net.sf.l2j.gameserver.network.clientpackets.Say2;
  513. +import net.sf.l2j.gameserver.network.serverpackets.CreatureSay;
  514. +
  515. +/*
  516. + * @author -= TioPatinhas =-
  517. + */
  518. +public final class VipManager
  519. +{
  520. +   private static final VipManager INSTANCE = new VipManager();
  521. +  
  522. +   public static VipManager getInstance()
  523. +   {
  524. +       return INSTANCE;
  525. +   }
  526. +  
  527. +   private VipManager()
  528. +   {
  529. +   }
  530. +  
  531. +   public void onLogin(L2PcInstance player)
  532. +   {
  533. +       final VipStatus stage = VipDAO.load(player.getObjectId());
  534. +       if (stage != null && stage.isActive())
  535. +       {
  536. +           player.setNewVipTier(stage.tier);
  537. +           player.setNewVipExpire(stage.expire);
  538. +           applyTitleColorFromTier(player, stage.tier);
  539. +          
  540. +           final String left = formatRemaining(LocalDateTime.now(), stage.expire);
  541. +           player.sendPacket(new CreatureSay(0, Say2.CRITICAL_ANNOUNCE, "", "Seu VIP " + stage.tier + " expira em " + left + "."));
  542. +           warnIfLessThanOneDay(player, stage.expire);
  543. +       }
  544. +       else
  545. +       {
  546. +           player.setNewVipTier(null);
  547. +           player.setNewVipExpire(null);
  548. +           if (stage != null)
  549. +               VipDAO.delete(player.getObjectId());
  550. +           resetTitleColorToDefault(player);
  551. +       }
  552. +   }
  553. +  
  554. +   public void setVip(L2PcInstance player, String tier, int days)
  555. +   {
  556. +       LocalDateTime base = LocalDateTime.now();
  557. +       if (player.getNewVipExpire() != null && base.isBefore(player.getNewVipExpire()))
  558. +           base = player.getNewVipExpire();
  559. +      
  560. +       final LocalDateTime exp = base.plusDays(Math.max(1, days));
  561. +       final String normTier = tier.toLowerCase();
  562. +      
  563. +       VipDAO.save(player.getObjectId(), normTier, exp);
  564. +       player.setNewVipTier(normTier);
  565. +       player.setNewVipExpire(exp);
  566. +      
  567. +       applyTitleColorFromTier(player, normTier);
  568. +      
  569. +       final String left = formatRemaining(LocalDateTime.now(), exp);
  570. +       player.sendMessage("VIP " + normTier + " renovado. Expira em " + left + ".");
  571. +       player.sendPacket(new CreatureSay(0, Say2.CRITICAL_ANNOUNCE, "", "VIP " + normTier + " renovado. Expira em " + left + "."));
  572. +       warnIfLessThanOneDay(player, exp);
  573. +   }
  574. +  
  575. +   public void clearVip(L2PcInstance player)
  576. +   {
  577. +       VipDAO.delete(player.getObjectId());
  578. +       player.setNewVipTier(null);
  579. +       player.setNewVipExpire(null);
  580. +       resetTitleColorToDefault(player);
  581. +       player.sendMessage("Seu VIP foi removido.");
  582. +       player.sendPacket(new CreatureSay(0, Say2.CRITICAL_ANNOUNCE, "", "Seu VIP foi removido."));
  583. +   }
  584. +  
  585. +   public double getDropAddPercent(L2PcInstance player, int itemId)
  586. +   {
  587. +       if (player == null || player.getNewVipTier() == null)
  588. +           return 0.0;
  589. +       return VipData.getInstance().getAddPercent(player.getNewVipTier(), itemId);
  590. +   }
  591. +  
  592. +   public double getCountMultiplier(L2PcInstance player, int itemId)
  593. +   {
  594. +       if (player == null || player.getNewVipTier() == null)
  595. +           return 1.0;
  596. +       return VipData.getInstance().getCountMul(player.getNewVipTier(), itemId);
  597. +   }
  598. +  
  599. +   // XP / SP
  600. +   public double getXpRateMultiplier(L2PcInstance player)
  601. +   {
  602. +       if (player == null)
  603. +           return 1.0;
  604. +       final String tier = player.getNewVipTier();
  605. +       if (tier == null)
  606. +           return 1.0;
  607. +       if (!VipData.getInstance().isUseXpSp(tier))
  608. +           return 1.0;
  609. +       return VipData.getInstance().getXpRate(tier);
  610. +   }
  611. +  
  612. +   public double getSpRateMultiplier(L2PcInstance player)
  613. +   {
  614. +       if (player == null)
  615. +           return 1.0;
  616. +       final String tier = player.getNewVipTier();
  617. +       if (tier == null)
  618. +           return 1.0;
  619. +       if (!VipData.getInstance().isUseXpSp(tier))
  620. +           return 1.0;
  621. +       return VipData.getInstance().getSpRate(tier);
  622. +   }
  623. +  
  624. +   public double getEnchantAddPercent(L2PcInstance player, int scrollId)
  625. +   {
  626. +       if (player == null)
  627. +           return 0.0;
  628. +       final String tier = player.getNewVipTier();
  629. +       if (tier == null)
  630. +           return 0.0;
  631. +       return VipData.getInstance().getEnchantAddPercent(tier, scrollId);
  632. +   }
  633. +  
  634. +   public double getEnchantMulRate(L2PcInstance player, int scrollId)
  635. +   {
  636. +       if (player == null)
  637. +           return 1.0;
  638. +       final String tier = player.getNewVipTier();
  639. +       if (tier == null)
  640. +           return 1.0;
  641. +       return VipData.getInstance().getEnchantMulRate(tier, scrollId);
  642. +   }
  643. +  
  644. +   private void applyTitleColorFromTier(L2PcInstance player, String tier)
  645. +   {
  646. +       if (player == null || tier == null)
  647. +           return;
  648. +       if (!VipData.getInstance().isUseTitleColor(tier))
  649. +           return;
  650. +      
  651. +       final String hex = VipData.getInstance().getTitleColor(tier);
  652. +       if (hex == null)
  653. +           return;
  654. +      
  655. +       try
  656. +       {
  657. +           final int rgb = VipData.parseColor(hex); // "#rrggbb" -> 0xRRGGBB
  658. +           player.getAppearance().setTitleColor(rgb);
  659. +           player.broadcastUserInfo();
  660. +       }
  661. +       catch (Exception e)
  662. +       {
  663. +           e.printStackTrace();
  664. +       }
  665. +   }
  666. +  
  667. +   private void resetTitleColorToDefault(L2PcInstance player)
  668. +   {
  669. +       if (player == null)
  670. +           return;
  671. +      
  672. +       final int DEFAULT_TITLE_COLOR = 0xFFFF77;
  673. +       try
  674. +       {
  675. +           player.getAppearance().setTitleColor(DEFAULT_TITLE_COLOR);
  676. +           player.broadcastUserInfo();
  677. +       }
  678. +       catch (Exception e)
  679. +       {
  680. +           e.printStackTrace();
  681. +       }
  682. +   }
  683. +  
  684. +   private static String formatRemaining(LocalDateTime now, LocalDateTime expire)
  685. +   {
  686. +       if (expire == null || !expire.isAfter(now))
  687. +           return "0d 00h 00m";
  688. +      
  689. +       Duration day = Duration.between(now, expire);
  690. +       long totalMin = day.toMinutes();
  691. +       long days = totalMin / (24 * 60);
  692. +       long hours = (totalMin % (24 * 60)) / 60;
  693. +       long mins = totalMin % 60;
  694. +       return String.format("%ddias %02dhoras %02dminutos", days, hours, mins);
  695. +   }
  696. +  
  697. +   private static void warnIfLessThanOneDay(L2PcInstance player, LocalDateTime expire)
  698. +   {
  699. +       if (expire == null)
  700. +           return;
  701. +      
  702. +       Duration days = Duration.between(LocalDateTime.now(), expire);
  703. +       if (!days.isNegative() && days.compareTo(Duration.ofHours(24)) <= 0)
  704. +       {
  705. +           long hours = Math.max(0, days.toHours());
  706. +           player.sendMessage("Aviso: seu VIP expira em menos de 24h (" + hours + "h).");
  707. +           player.sendPacket(new CreatureSay(0, Say2.CRITICAL_ANNOUNCE, "Aviso: ", "seu VIP expira em menos de 24h (" + hours + "h)."));
  708. +       }
  709. +   }
  710. +}
  711. diff --git a/java/TioPatinhas/Vip/VipStatus.java b/java/TioPatinhas/Vip/VipStatus.java
  712. new file mode 100644
  713. index 0000000..53dfd7a
  714. --- /dev/null
  715. +++ b/java/TioPatinhas/Vip/VipStatus.java
  716. @@ -0,0 +1,23 @@
  717. +package TioPatinhas.Vip;
  718. +
  719. +import java.time.LocalDateTime;
  720. +
  721. +/*
  722. + * @author -= TioPatinhas =-
  723. + */
  724. +public final class VipStatus
  725. +{
  726. +   public final String tier;
  727. +   public final LocalDateTime expire;
  728. +  
  729. +   public VipStatus(String tier, LocalDateTime expire)
  730. +   {
  731. +       this.tier = tier;
  732. +       this.expire = expire;
  733. +   }
  734. +  
  735. +   public boolean isActive()
  736. +   {
  737. +       return tier != null && expire != null && LocalDateTime.now().isBefore(expire);
  738. +   }
  739. +}
  740. diff --git a/java/net/sf/l2j/gameserver/GameServer.java b/java/net/sf/l2j/gameserver/GameServer.java
  741. index 88af6d2..41024a0 100644
  742. --- a/java/net/sf/l2j/gameserver/GameServer.java
  743. +++ b/java/net/sf/l2j/gameserver/GameServer.java
  744. @@ -211,6 +211,7 @@
  745.  import TioPatinhas.Dungeon.DungeonManager;
  746.  import TioPatinhas.Fusion.data.ItemFusionData;
  747.  import TioPatinhas.TerritoryWar.TerritoryWarInit;
  748. +import TioPatinhas.Vip.VipData;
  749.  import TioPatinhas.WhatsApp.WhatsappBridge;
  750.  import hwid.Hwid;
  751.  import phantom.FakePlayerConfig;
  752. @@ -576,6 +577,7 @@
  753.             _log.info("Battle Farm Event is disabled");
  754.        
  755.         ItemFusionData.getInstance();
  756. +       VipData.getInstance();
  757.            
  758.         Util.printSection("Lotus Dev: Interface");
  759.         TeleportLocationDataLotus.getInstance();
  760. diff --git a/java/net/sf/l2j/gameserver/handler/AdminCommandHandler.java b/java/net/sf/l2j/gameserver/handler/AdminCommandHandler.java
  761. index 646ec73..4fc3ad5 100644
  762. --- a/java/net/sf/l2j/gameserver/handler/AdminCommandHandler.java
  763. +++ b/java/net/sf/l2j/gameserver/handler/AdminCommandHandler.java
  764. @@ -66,6 +66,7 @@
  765.  import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminMonsterRace;
  766.  import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminMovieMaker;
  767.  import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminMultiTvT;
  768. +import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminNewVip;
  769.  import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminOlympiad;
  770.  import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminPCBPoint;
  771.  import net.sf.l2j.gameserver.handler.admincommandhandlers.AdminPForge;
  772. @@ -184,6 +185,7 @@
  773.         registerAdminCommandHandler(new AdminSearch());
  774.         registerAdminCommandHandler(new AdminScanPlayers());
  775.         registerAdminCommandHandler(new AdminWhatsapp());
  776. +       registerAdminCommandHandler(new AdminNewVip());
  777.     }
  778.    
  779.     public void registerAdminCommandHandler(IAdminCommandHandler handler)
  780. diff --git a/java/net/sf/l2j/gameserver/handler/ItemHandler.java b/java/net/sf/l2j/gameserver/handler/ItemHandler.java
  781. index 7ecd306..edef874 100644
  782. --- a/java/net/sf/l2j/gameserver/handler/ItemHandler.java
  783. +++ b/java/net/sf/l2j/gameserver/handler/ItemHandler.java
  784. @@ -50,6 +50,7 @@
  785.  import net.sf.l2j.gameserver.handler.itemhandlers.SpecialXMas;
  786.  import net.sf.l2j.gameserver.handler.itemhandlers.SpiritShot;
  787.  import net.sf.l2j.gameserver.handler.itemhandlers.SummonItems;
  788. +import net.sf.l2j.gameserver.handler.itemhandlers.VipToken;
  789.  import net.sf.l2j.gameserver.handler.itemhandlers.clan.ClanLevel;
  790.  import net.sf.l2j.gameserver.handler.itemhandlers.clan.ClanReputation;
  791.  import net.sf.l2j.gameserver.handler.itemhandlers.clan.skills.SkillAegis;
  792. @@ -144,6 +145,7 @@
  793.         registerItemHandler(new RouletteItem());
  794.         registerItemHandler(new AgationItems());
  795.         registerItemHandler(new CapsuleBox());
  796. +       registerItemHandler(new VipToken());
  797.        
  798.        
  799.         if (Config.ALLOW_ITEM_RECOVER)
  800. diff --git a/java/net/sf/l2j/gameserver/handler/admincommandhandlers/AdminNewVip.java b/java/net/sf/l2j/gameserver/handler/admincommandhandlers/AdminNewVip.java
  801. new file mode 100644
  802. index 0000000..dca9a8c
  803. --- /dev/null
  804. +++ b/java/net/sf/l2j/gameserver/handler/admincommandhandlers/AdminNewVip.java
  805. @@ -0,0 +1,93 @@
  806. +package net.sf.l2j.gameserver.handler.admincommandhandlers;
  807. +
  808. +import java.util.StringTokenizer;
  809. +
  810. +import net.sf.l2j.gameserver.handler.IAdminCommandHandler;
  811. +import net.sf.l2j.gameserver.model.L2World;
  812. +import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
  813. +
  814. +import TioPatinhas.Vip.VipData;
  815. +import TioPatinhas.Vip.VipManager;
  816. +
  817. +/*
  818. + * @author -= TioPatinhas =-
  819. + */
  820. +public class AdminNewVip implements IAdminCommandHandler
  821. +{
  822. +  
  823. +   private static final String[] ADMIN_COMMANDS =
  824. +   {
  825. +       "admin_newvip",
  826. +       "admin_clearvip",
  827. +       "admin_reloadvip"
  828. +   };
  829. +  
  830. +   private L2PcInstance resolvePlayer(L2PcInstance admin, String nameOrDot)
  831. +   {
  832. +       if (nameOrDot.equals(".") && admin.getTarget() instanceof L2PcInstance)
  833. +           return (L2PcInstance) admin.getTarget();
  834. +       return L2World.getInstance().getPlayer(nameOrDot);
  835. +   }
  836. +  
  837. +   @Override
  838. +   public boolean useAdminCommand(String command, L2PcInstance activeChar)
  839. +   {
  840. +       final StringTokenizer st = new StringTokenizer(command, " ");
  841. +       final String cmd = st.nextToken();
  842. +      
  843. +       if ("admin_newvip".equalsIgnoreCase(cmd))
  844. +       {
  845. +           if (st.countTokens() < 3)
  846. +           {
  847. +               activeChar.sendMessage("Uso: //newvip <player> <tier> <dias>");
  848. +               return true;
  849. +           }
  850. +           final String playerName = st.nextToken();
  851. +           final String tier = st.nextToken().toLowerCase();
  852. +           final int days = Integer.parseInt(st.nextToken());
  853. +          
  854. +           final L2PcInstance target = resolvePlayer(activeChar, playerName);
  855. +           if (target == null)
  856. +           {
  857. +               activeChar.sendMessage("Player offline.");
  858. +               return true;
  859. +           }
  860. +          
  861. +           VipManager.getInstance().setVip(target, tier, days);
  862. +           activeChar.sendMessage("VIP setado: " + target.getName() + " -> " + tier + " (" + days + "Dia(s))");
  863. +           target.sendMessage("Seu VIP foi ativado: " + tier + " por " + days + " dia(s).");
  864. +           return true;
  865. +       }
  866. +       else if ("admin_clearvip".equalsIgnoreCase(cmd))
  867. +       {
  868. +           if (!st.hasMoreTokens())
  869. +           {
  870. +               activeChar.sendMessage("Uso: //clearvip <player>");
  871. +               return true;
  872. +           }
  873. +           final L2PcInstance target = resolvePlayer(activeChar, st.nextToken());
  874. +           if (target == null)
  875. +           {
  876. +               activeChar.sendMessage("Player offline.");
  877. +               return true;
  878. +           }
  879. +           VipManager.getInstance().clearVip(target);
  880. +           activeChar.sendMessage("VIP removido de " + target.getName());
  881. +           target.sendMessage("Seu VIP foi removido.");
  882. +           return true;
  883. +       }
  884. +       else if ("admin_reloadvip".equalsIgnoreCase(cmd))
  885. +       {
  886. +           VipData.getInstance().reload();
  887. +           activeChar.sendMessage("O VipData e VipItems Foram recarregado.");
  888. +           return true;
  889. +       }
  890. +       return false;
  891. +   }
  892. +  
  893. +   @Override
  894. +   public String[] getAdminCommandList()
  895. +   {
  896. +       return ADMIN_COMMANDS;
  897. +   }
  898. +}
  899. diff --git a/java/net/sf/l2j/gameserver/handler/itemhandlers/VipToken.java b/java/net/sf/l2j/gameserver/handler/itemhandlers/VipToken.java
  900. new file mode 100644
  901. index 0000000..b962cad
  902. --- /dev/null
  903. +++ b/java/net/sf/l2j/gameserver/handler/itemhandlers/VipToken.java
  904. @@ -0,0 +1,48 @@
  905. +package net.sf.l2j.gameserver.handler.itemhandlers;
  906. +
  907. +import net.sf.l2j.gameserver.handler.IItemHandler;
  908. +import net.sf.l2j.gameserver.model.actor.L2Playable;
  909. +import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
  910. +import net.sf.l2j.gameserver.model.item.instance.ItemInstance;
  911. +import net.sf.l2j.gameserver.network.SystemMessageId;
  912. +import net.sf.l2j.gameserver.network.clientpackets.Say2;
  913. +import net.sf.l2j.gameserver.network.serverpackets.CreatureSay;
  914. +import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
  915. +
  916. +import TioPatinhas.Vip.VipData;
  917. +import TioPatinhas.Vip.VipManager;
  918. +
  919. +/*
  920. + * @author -= TioPatinhas =-
  921. + */
  922. +public final class VipToken implements IItemHandler
  923. +{
  924. +  
  925. +   @Override
  926. +   public void useItem(L2Playable playable, ItemInstance item, boolean forceUse)
  927. +   {
  928. +       if (!(playable instanceof L2PcInstance))
  929. +           return;
  930. +      
  931. +       final L2PcInstance player = (L2PcInstance) playable;
  932. +      
  933. +       final VipData.TokenEntry token = VipData.getInstance().getToken(item.getItemId());
  934. +       if (token == null)
  935. +       {
  936. +           player.sendMessage("Token VIP inválido ou não configurado no VipManager.xml.");
  937. +           return;
  938. +       }
  939. +      
  940. +       if (!player.destroyItemByItemId("VipToken", item.getItemId(), 1, player, true))
  941. +       {
  942. +           player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.NOT_ENOUGH_ITEMS));
  943. +           return;
  944. +       }
  945. +      
  946. +       final int days = Math.max(1, token.days);
  947. +       VipManager.getInstance().setVip(player, token.tier, days);
  948. +      
  949. +       player.sendMessage("VIP " + token.tier + " aplicado/renovado por " + days + " dia(s).");
  950. +       player.sendPacket(new CreatureSay(0, Say2.CRITICAL_ANNOUNCE, "", "VIP " + token.tier + " aplicado/renovado por " + days + " dia(s)."));
  951. +   }
  952. +}
  953. diff --git a/java/net/sf/l2j/gameserver/model/actor/L2Attackable.java b/java/net/sf/l2j/gameserver/model/actor/L2Attackable.java
  954. index 02fc312..ff3a8a9 100644
  955. --- a/java/net/sf/l2j/gameserver/model/actor/L2Attackable.java
  956. +++ b/java/net/sf/l2j/gameserver/model/actor/L2Attackable.java
  957. @@ -76,6 +76,8 @@
  958.  import TioPatinhas.BattleFarm.event.AbstractBattleFarm;
  959.  import TioPatinhas.BattleFarm.event.RewardMobRegistry;
  960.  import TioPatinhas.BossEngine.CustomBossManager;
  961. +import TioPatinhas.Vip.VipData;
  962. +import TioPatinhas.Vip.VipManager;
  963.  
  964.  /**
  965.   * This class manages all NPC that can be attacked, such as :
  966. @@ -643,6 +645,16 @@
  967.                         sp *= Config.VIP_XP_SP_RATE;
  968.                     }
  969.                    
  970. +                   if (attacker != null && attacker.isNewVip() && VipData.getInstance().isUseXpSp(attacker.getNewVipTier()))
  971. +                   {
  972. +                       final double xpMul = VipManager.getInstance().getXpRateMultiplier(attacker);
  973. +                       final double spMul = VipManager.getInstance().getSpRateMultiplier(attacker);
  974. +                      
  975. +                       exp = Math.round(exp * xpMul);
  976. +                       sp = (int) Math.round(sp * spMul);
  977. +                   }
  978. +                  
  979.                     exp *= 1 - penalty;
  980.                    
  981.                     if (isOverhit() && _overhitAttacker != null && _overhitAttacker.getActingPlayer() != null && attacker == _overhitAttacker.getActingPlayer())
  982. @@ -734,6 +746,17 @@
  983.                         exp *= Config.VIP_XP_SP_RATE;
  984.                         sp *= Config.VIP_XP_SP_RATE;
  985.                     }
  986. +                  
  987. +                   if (attacker != null && attacker.isNewVip() && VipData.getInstance().isUseXpSp(attacker.getNewVipTier()))
  988. +                   {
  989. +                       final double xpMul = VipManager.getInstance().getXpRateMultiplier(attacker);
  990. +                       final double spMul = VipManager.getInstance().getSpRateMultiplier(attacker);
  991. +                      
  992. +                       exp = Math.round(exp * xpMul);
  993. +                       sp = (int) Math.round(sp * spMul);
  994. +                   }
  995. +                  
  996.                 }
  997.                
  998.                 if (isChampion())
  999. @@ -751,6 +774,15 @@
  1000.                         exp *= Config.VIP_XP_SP_RATE;
  1001.                         sp *= Config.VIP_XP_SP_RATE;
  1002.                     }
  1003.  
  1004. +                   if (attacker != null && attacker.isNewVip() && VipData.getInstance().isUseXpSp(attacker.getNewVipTier()))
  1005. +                   {
  1006. +                       final double xpMul = VipManager.getInstance().getXpRateMultiplier(attacker);
  1007. +                       final double spMul = VipManager.getInstance().getSpRateMultiplier(attacker);
  1008. +                      
  1009. +                       exp = Math.round(exp * xpMul);
  1010. +                       sp = (int) Math.round(sp * spMul);
  1011. +                   }
  1012.                 }
  1013.                
  1014.                 exp *= partyMul;
  1015. @@ -1069,6 +1101,18 @@
  1016.         if (isChampion())
  1017.             dropChance *= Config.CHAMPION_REWARDS;
  1018.        
  1019. +       if (lastAttacker != null && VipData.getInstance().isEnabled() && lastAttacker.isNewVip())
  1020. +       {
  1021. +           final double addPercent = VipManager.getInstance().getDropAddPercent(lastAttacker, drop.getItemId());
  1022. +          
  1023. +           if (addPercent > 0.0)
  1024. +           {
  1025. +               final double addInChanceUnits = addPercent * (DropData.MAX_CHANCE / 100.0); // MAX_CHANCE = 100%
  1026. +               dropChance += addInChanceUnits;
  1027. +           }
  1028. +       }
  1029. +      
  1030.         // Set our limits for chance of drop
  1031.         if (dropChance < 1)
  1032.             dropChance = 1;
  1033. @@ -1104,6 +1148,27 @@
  1034.             if (drop.getItemId() >= 6360 && drop.getItemId() <= 6362)
  1035.                 itemCount *= Config.RATE_DROP_SEAL_STONES;
  1036.            
  1037. +       if (itemCount > 0 && lastAttacker != null && VipData.getInstance().isEnabled() && lastAttacker.isNewVip())
  1038. +       {
  1039. +           final double mul = VipManager.getInstance().getCountMultiplier(lastAttacker, drop.getItemId());
  1040. +          
  1041. +           if (mul > 1.0)
  1042. +           {
  1043. +               final int base = itemCount;
  1044. +               final int whole = (int) Math.floor(mul);
  1045. +               final double frac = mul - whole;
  1046. +              
  1047. +               long newCount = (long) base * (long) whole;
  1048. +               if (frac > 0d && Rnd.nextDouble() < frac)
  1049. +                   newCount += base;
  1050. +              
  1051. +               if (newCount < 1 && itemCount > 0)
  1052. +                   newCount = 1;
  1053. +               itemCount = (int) Math.min(Integer.MAX_VALUE, newCount);
  1054. +           }
  1055. +       }
  1056. +      
  1057.         if (lastAttacker.isVip())
  1058.         {
  1059.             if (drop.getItemId() == Config.VIP_DROP_RATE)
  1060. @@ -1187,6 +1252,14 @@
  1061.             if (isChampion())
  1062.                 dropChance *= Config.CHAMPION_REWARDS;
  1063.            
  1064. +           if (lastAttacker != null && VipData.getInstance().isEnabled() && lastAttacker.isNewVip())
  1065. +           {
  1066. +               final double addPercent = VipManager.getInstance().getDropAddPercent(lastAttacker, drop.getItemId());
  1067. +               if (addPercent > 0.0)
  1068. +                   dropChance += (addPercent * (DropData.MAX_CHANCE / 100.0));
  1069. +           }
  1070. +          
  1071.             if (dropChance < DropData.MAX_CHANCE)
  1072.                 dropChance = DropData.MAX_CHANCE;
  1073.            
  1074. @@ -1232,6 +1305,26 @@
  1075.                 }
  1076.             }
  1077.            
  1078. +           if (itemCount > 0 && lastAttacker != null && VipData.getInstance().isEnabled() && lastAttacker.isNewVip())
  1079. +           {
  1080. +               final double mul = VipManager.getInstance().getCountMultiplier(lastAttacker, drop.getItemId());
  1081. +               if (mul > 1.0)
  1082. +               {
  1083. +                   final int base = itemCount;
  1084. +                   final int whole = (int) Math.floor(mul);
  1085. +                   final double frac = mul - whole;
  1086. +                  
  1087. +                   long newCount = (long) base * (long) whole;
  1088. +                   if (frac > 0d && Rnd.nextDouble() < frac)
  1089. +                       newCount += base;
  1090. +                  
  1091. +                   if (newCount < 1 && itemCount > 0)
  1092. +                       newCount = 1;
  1093. +                   itemCount = (int) Math.min(Integer.MAX_VALUE, newCount);
  1094. +               }
  1095. +           }
  1096. +          
  1097.             if (itemCount > 0)
  1098.                 return new ItemHolder(drop.getItemId(), itemCount, drop.getMinEnchant(), drop.getMaxEnchant(), drop.getEnchantSucess());
  1099.         }
  1100. diff --git a/java/net/sf/l2j/gameserver/model/actor/instance/L2PcInstance.java b/java/net/sf/l2j/gameserver/model/actor/instance/L2PcInstance.java
  1101. index ae7ddc0..cf38913 100644
  1102. --- a/java/net/sf/l2j/gameserver/model/actor/instance/L2PcInstance.java
  1103. +++ b/java/net/sf/l2j/gameserver/model/actor/instance/L2PcInstance.java
  1104. @@ -17,6 +17,7 @@
  1105.  import java.sql.Connection;
  1106.  import java.sql.PreparedStatement;
  1107.  import java.sql.ResultSet;
  1108. +import java.time.LocalDateTime;
  1109.  import java.util.ArrayList;
  1110.  import java.util.Arrays;
  1111.  import java.util.Calendar;
  1112. @@ -14613,4 +14614,34 @@
  1113.     {
  1114.         _originalBatlleTitleColor = color;
  1115.     }
  1116. +  
  1117. +   // NewVIP
  1118. +   private String _vipTier = null;
  1119. +   private LocalDateTime _vipExpire = null;
  1120. +  
  1121. +   public void setNewVipTier(String t)
  1122. +   {
  1123. +       _vipTier = t;
  1124. +   }
  1125. +  
  1126. +   public String getNewVipTier()
  1127. +   {
  1128. +       return _vipTier;
  1129. +   }
  1130. +  
  1131. +   public void setNewVipExpire(LocalDateTime e)
  1132. +   {
  1133. +       _vipExpire = e;
  1134. +   }
  1135. +  
  1136. +   public LocalDateTime getNewVipExpire()
  1137. +   {
  1138. +       return _vipExpire;
  1139. +   }
  1140. +  
  1141. +   public boolean isNewVip()
  1142. +   {
  1143. +       return _vipTier != null && _vipExpire != null && LocalDateTime.now().isBefore(_vipExpire);
  1144. +   }
  1145. +  
  1146.  }
  1147. \ No newline at end of file
  1148. diff --git a/java/net/sf/l2j/gameserver/network/clientpackets/EnterWorld.java b/java/net/sf/l2j/gameserver/network/clientpackets/EnterWorld.java
  1149. index 2ce2d4a..07635f1 100644
  1150. --- a/java/net/sf/l2j/gameserver/network/clientpackets/EnterWorld.java
  1151. +++ b/java/net/sf/l2j/gameserver/network/clientpackets/EnterWorld.java
  1152. @@ -106,6 +106,7 @@
  1153.  
  1154.  import TioPatinhas.BotPrevention.BotsPreventionManager;
  1155.  import TioPatinhas.DollSystem.DollsData;
  1156. +import TioPatinhas.Vip.VipManager;
  1157.  import hwid.Hwid;
  1158.  import phantom.FakePlayer;
  1159.  
  1160. @@ -487,6 +488,8 @@
  1161.        
  1162.         L2ClassMasterInstance.showQuestionMark(activeChar);
  1163.        
  1164. +       VipManager.getInstance().onLogin(activeChar);
  1165. +      
  1166.         // VIP Delete
  1167.         if (activeChar.isVip())
  1168.         {
  1169. diff --git a/java/net/sf/l2j/gameserver/network/clientpackets/RequestEnchantItem.java b/java/net/sf/l2j/gameserver/network/clientpackets/RequestEnchantItem.java
  1170. index a1c9d5c..2e836f8 100644
  1171. --- a/java/net/sf/l2j/gameserver/network/clientpackets/RequestEnchantItem.java
  1172. +++ b/java/net/sf/l2j/gameserver/network/clientpackets/RequestEnchantItem.java
  1173. @@ -29,6 +29,8 @@
  1174.  import net.sf.l2j.gameserver.util.Broadcast;
  1175.  import net.sf.l2j.util.Rnd;
  1176.  
  1177. +import TioPatinhas.Vip.VipManager;
  1178. +
  1179.  public final class RequestEnchantItem extends L2GameClientPacket
  1180.  {
  1181.     private int _objectId;
  1182. @@ -104,6 +106,28 @@
  1183.        
  1184.         synchronized (item)
  1185.         {
  1186. +          
  1187. +           double chance = enchant.getChance(item);
  1188. +          
  1189. +           // if (player != null && player.isNewVip())
  1190. +           if (player.isNewVip())
  1191. +           {
  1192. +               final int scrollId = scroll.getItemId();
  1193. +               final double mul = VipManager.getInstance().getEnchantMulRate(player, scrollId);
  1194. +               final double add = VipManager.getInstance().getEnchantAddPercent(player, scrollId);
  1195. +              
  1196. +               if (mul != 1.0)
  1197. +                   chance *= mul;
  1198. +               if (add != 0.0)
  1199. +                   chance += add;
  1200. +              
  1201. +               if (chance < 0.0)
  1202. +                   chance = 0.0;
  1203. +               if (chance > 100.0)
  1204. +                   chance = 100.0;
  1205. +           }
  1206. +          
  1207.             if (Rnd.get(100) < enchant.getChance(item)) // success
  1208.             {
  1209.                 // announce the success
  1210.  
  1211.  
  1212. //================================== SQL ===========
  1213.  
  1214. SET NAMES utf8mb4;
  1215. SET FOREIGN_KEY_CHECKS = 0;
  1216.  
  1217. -- ----------------------------
  1218. -- Table structure for character_vip_player
  1219. -- ----------------------------
  1220. DROP TABLE IF EXISTS `character_vip_player`;
  1221. CREATE TABLE `character_vip_player`  (
  1222.   `charId` int(11) NOT NULL,
  1223.   `tier` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  1224.   `expire_at` datetime NOT NULL,
  1225.   `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE CURRENT_TIMESTAMP,
  1226.   PRIMARY KEY (`charId`) USING BTREE,
  1227.   INDEX `idx_character_vip_expire`(`expire_at` ASC) USING BTREE
  1228. ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
  1229.  
  1230. -- ----------------------------
  1231. -- Records of character_vip_player
  1232. -- ----------------------------
  1233.  
  1234. SET FOREIGN_KEY_CHECKS = 1;
  1235.  
  1236.  
Advertisement
Add Comment
Please, Sign In to add comment