Advertisement
Guest User

Monster race event

a guest
Apr 27th, 2023
265
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 51.54 KB | Gaming | 0 0
  1. \ No newline at end of file
  2. diff --git a/aCis_gameserver/java/net/sf/l2j/Config.java b/aCis_gameserver/java/net/sf/l2j/Config.java
  3. index 65daaa6..3cd7841 100644
  4. --- a/aCis_gameserver/java/net/sf/l2j/Config.java
  5. +++ b/aCis_gameserver/java/net/sf/l2j/Config.java
  6. @@ -201,6 +201,12 @@
  7.     public static int FISH_CHAMPIONSHIP_REWARD_4;
  8.     public static int FISH_CHAMPIONSHIP_REWARD_5;
  9.    
  10. +   /** Derby Race system */
  11. +   public static int _itemID;
  12. +   public static int _price1;
  13. +   public static int _price2;
  14. +   public static int _price3;
  15. +  
  16.     // --------------------------------------------------
  17.     // GeoEngine
  18.     // --------------------------------------------------
  19. @@ -803,6 +809,11 @@
  20.         FISH_CHAMPIONSHIP_REWARD_3 = events.getProperty("FishChampionshipReward3", 300000);
  21.         FISH_CHAMPIONSHIP_REWARD_4 = events.getProperty("FishChampionshipReward4", 200000);
  22.         FISH_CHAMPIONSHIP_REWARD_5 = events.getProperty("FishChampionshipReward5", 100000);
  23. +      
  24. +       _itemID = events.getProperty("ItemID", 6673);
  25. +       _price1 = events.getProperty("Price1", 10);
  26. +       _price2 = events.getProperty("Price2", 20);
  27. +       _price3 = events.getProperty("Price3", 30);
  28.     }
  29.    
  30.     /**
  31. diff --git a/aCis_gameserver/java/net/sf/l2j/gameserver/data/manager/DerbyTrackManager.java b/aCis_gameserver/java/net/sf/l2j/gameserver/data/manager/DerbyTrackManager.java
  32. index e8efc06..8122d4a 100644
  33. --- a/aCis_gameserver/java/net/sf/l2j/gameserver/data/manager/DerbyTrackManager.java
  34. +++ b/aCis_gameserver/java/net/sf/l2j/gameserver/data/manager/DerbyTrackManager.java
  35. @@ -1,13 +1,14 @@
  36.  package net.sf.l2j.gameserver.data.manager;
  37.  
  38. -import java.lang.reflect.Constructor;
  39. -import java.sql.Connection;
  40. -import java.sql.PreparedStatement;
  41. -import java.sql.ResultSet;
  42. +import java.sql.SQLException;
  43.  import java.util.ArrayList;
  44. +import java.util.Arrays;
  45.  import java.util.Collections;
  46.  import java.util.List;
  47.  import java.util.Map;
  48. +import java.util.Random;
  49. +import java.util.Timer;
  50. +import java.util.TimerTask;
  51.  import java.util.TreeMap;
  52.  import java.util.concurrent.ConcurrentHashMap;
  53.  import java.util.stream.Collectors;
  54. @@ -18,14 +19,17 @@
  55.  import net.sf.l2j.commons.random.Rnd;
  56.  
  57.  import net.sf.l2j.gameserver.data.xml.NpcData;
  58. +import net.sf.l2j.gameserver.enums.RaceState;
  59. +import net.sf.l2j.gameserver.enums.SayType;
  60.  import net.sf.l2j.gameserver.idfactory.IdFactory;
  61.  import net.sf.l2j.gameserver.model.HistoryInfo;
  62. +import net.sf.l2j.gameserver.model.World;
  63.  import net.sf.l2j.gameserver.model.actor.Npc;
  64. -import net.sf.l2j.gameserver.model.actor.template.NpcTemplate;
  65.  import net.sf.l2j.gameserver.model.zone.type.DerbyTrackZone;
  66.  import net.sf.l2j.gameserver.network.SystemMessageId;
  67.  import net.sf.l2j.gameserver.network.serverpackets.DeleteObject;
  68.  import net.sf.l2j.gameserver.network.serverpackets.MonRaceInfo;
  69. +import net.sf.l2j.gameserver.network.serverpackets.NpcSay;
  70.  import net.sf.l2j.gameserver.network.serverpackets.PlaySound;
  71.  import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
  72.  
  73. @@ -33,54 +37,35 @@
  74.  {
  75.     protected static final CLogger LOGGER = new CLogger(DerbyTrackManager.class.getName());
  76.    
  77. -   private static final String SAVE_HISTORY = "INSERT INTO mdt_history (race_id, first, second, odd_rate) VALUES (?,?,?,?)";
  78. +   private static final String SAVE_HISTORY = "INSERT INTO mdt_history (race_id, first, second, odd_rate, winner) VALUES (?,?,?,?,?)";
  79.     private static final String LOAD_HISTORY = "SELECT * FROM mdt_history";
  80.     private static final String LOAD_BETS = "SELECT * FROM mdt_bets";
  81.     private static final String SAVE_BETS = "REPLACE INTO mdt_bets (lane_id, bet) VALUES (?,?)";
  82.     private static final String CLEAR_BETS = "UPDATE mdt_bets SET bet = 0";
  83.    
  84. -   public enum RaceState
  85. -   {
  86. -       ACCEPTING_BETS,
  87. -       WAITING,
  88. -       STARTING_RACE,
  89. -       RACE_END
  90. -   }
  91. +   private static final PlaySound SOUND_1 = new PlaySound(1, "S_Race");
  92. +   private static final PlaySound SOUND_2 = new PlaySound("ItemSound2.race_start");
  93. +   private static final List<List<Integer>> CODES = Arrays.asList(Arrays.asList(-1, 0), Arrays.asList(0, 15322), Arrays.asList(13765, -1));
  94. +   private static final int RACE_MANAGER = 30995;
  95.    
  96. -   protected static final PlaySound SOUND_1 = new PlaySound(1, "S_Race");
  97. -   protected static final PlaySound SOUND_2 = new PlaySound("ItemSound2.race_start");
  98. +   private final List<Npc> _runners = new ArrayList<>(); // List holding initial npcs, shuffled on a new race.
  99. +   private final TreeMap<Integer, HistoryInfo> _history = new TreeMap<>(); // List holding old race records.
  100. +   public final Map<Integer, Long> _betsPerLane = new ConcurrentHashMap<>(); // Map holding all bets for each lane ; values are set to 0 after every race.
  101. +   private final List<Double> _odds = new ArrayList<>(); // List holding sorted odds per lane ; cleared at new odds calculation.
  102. +   private final List<Integer> _runnerIndices = new ArrayList<>(); // Create a list of indices for all the runners
  103.    
  104. -   protected static final int[][] CODES =
  105. -   {
  106. -       {
  107. -           -1,
  108. -           0
  109. -       },
  110. -       {
  111. -           0,
  112. -           15322
  113. -       },
  114. -       {
  115. -           13765,
  116. -           -1
  117. -       }
  118. -   };
  119. +   private int _raceNumber = 1;
  120. +   private int _finalCountdown = 0;
  121. +   private RaceState _state = RaceState.FINISHED;
  122.    
  123. -   protected final List<Npc> _runners = new ArrayList<>(); // List holding initial npcs, shuffled on a new race.
  124. -   protected final TreeMap<Integer, HistoryInfo> _history = new TreeMap<>(); // List holding old race records.
  125. -   protected final Map<Integer, Long> _betsPerLane = new ConcurrentHashMap<>(); // Map holding all bets for each lane ; values are set to 0 after every race.
  126. -   protected final List<Double> _odds = new ArrayList<>(); // List holding sorted odds per lane ; cleared at new odds calculation.
  127. +   private MonRaceInfo _packet;
  128.    
  129. -   protected int _raceNumber = 1;
  130. -   protected int _finalCountdown = 0;
  131. -   protected RaceState _state = RaceState.RACE_END;
  132. -  
  133. -   protected MonRaceInfo _packet;
  134. -  
  135. -   private List<Npc> _chosenRunners; // Holds the actual list of 8 runners.
  136. +   public List<Npc> _chosenRunners; // Holds the actual list of 8 runners.
  137.     private int[][] _speeds;
  138. -   private int _firstIndex; // Index going from 0-7.
  139. -   private int _secondIndex; // Index going from 0-7.
  140. +   private int _firstPlaceIndex; // Index going from 0-7.
  141. +   private int _secondPlaceIndex; // Index going from 0-7.
  142. +   private String _message;
  143. +   private Timer _timer = new Timer();
  144.    
  145.     protected DerbyTrackManager()
  146.     {
  147. @@ -90,58 +75,71 @@
  148.         // Feed _betsPerLane with stored informations on bets.
  149.         loadBets();
  150.        
  151. -       // Feed _runners, we will only have to shuffle it when needed.
  152. +       // Initialize _runners list with NPC templates and their constructors
  153.         try
  154.         {
  155. -           for (int i = 31003; i < 31027; i++)
  156. +           for (var i = 31003; i < 31027; i++)
  157.             {
  158. -               final NpcTemplate template = NpcData.getInstance().getTemplate(i);
  159. -               if (template == null)
  160. -                   continue;
  161. -              
  162. -               final Constructor<?> constructor = Class.forName("net.sf.l2j.gameserver.model.actor.instance." + template.getType()).getConstructors()[0];
  163. -              
  164. -               _runners.add((Npc) constructor.newInstance(IdFactory.getInstance().getNextId(), template));
  165. +               var template = NpcData.getInstance().getTemplate(i);
  166. +               if (template != null)
  167. +               {
  168. +                   var constructor = Class.forName("net.sf.l2j.gameserver.model.actor.instance." + template.getType()).getConstructors()[0];
  169. +                   var npc = (Npc) constructor.newInstance(IdFactory.getInstance().getNextId(), template);
  170. +                   _runners.add(npc);
  171. +               }
  172.             }
  173.         }
  174.         catch (Exception e)
  175.         {
  176. -           LOGGER.error("Couldn't initialize runners.", e);
  177. +           LOGGER.error("Failed to initialize runners", e);
  178.         }
  179.        
  180. +       // Initialize _speeds array
  181.         _speeds = new int[8][20];
  182.        
  183. +       // Schedule announcement task to run every second
  184.         ThreadPool.scheduleAtFixedRate(new Announcement(), 0, 1000);
  185.     }
  186.    
  187. -   public List<Npc> getRunners()
  188. +   /**
  189. +    * @return the list of selected runners.
  190. +    */
  191. +   public List<Npc> getChosenRunners()
  192.     {
  193.         return _chosenRunners;
  194.     }
  195.    
  196.     /**
  197. -    * @param index : The actual index of List to check on.
  198. -    * @return the name of the Npc.
  199. +    * Returns the name of the runner at the given index in the selected runners list.
  200. +    * @param index of the runner.
  201. +    * @return the name of the runner.
  202.      */
  203.     public String getRunnerName(int index)
  204.     {
  205. -       final Npc npc = _chosenRunners.get(index);
  206. -       return (npc == null) ? "" : npc.getName();
  207. +       if (index >= 0 && index < _chosenRunners.size())
  208. +       {
  209. +           Npc runner = _chosenRunners.get(index);
  210. +           return runner.getName();
  211. +       }
  212. +       return "";
  213.     }
  214.    
  215. +   /**
  216. +    * @return the speeds of the runners.
  217. +    */
  218.     public int[][] getSpeeds()
  219.     {
  220.         return _speeds;
  221.     }
  222.    
  223. -   public int getFirst()
  224. +   public int getFirstPlace()
  225.     {
  226. -       return _firstIndex;
  227. +       return _firstPlaceIndex;
  228.     }
  229.    
  230. -   public int getSecond()
  231. +   public int getSecondPlace()
  232.     {
  233. -       return _secondIndex;
  234. +       return _secondPlaceIndex;
  235.     }
  236.    
  237.     public MonRaceInfo getRacePacket()
  238. @@ -161,187 +159,189 @@
  239.    
  240.     public List<HistoryInfo> getLastHistoryEntries()
  241.     {
  242. -       return _history.descendingMap().values().stream().limit(8).collect(Collectors.toList());
  243. +       return new ArrayList<>(_history.descendingMap().values()).subList(0, Math.min(8, _history.size()));
  244.     }
  245.    
  246.     public HistoryInfo getHistoryInfo(int raceNumber)
  247.     {
  248. -       return _history.get(raceNumber);
  249. +       return _history.getOrDefault(raceNumber, null);
  250.     }
  251.    
  252.     public List<Double> getOdds()
  253.     {
  254. -       return _odds;
  255. +       return new ArrayList<>(_odds);
  256.     }
  257.    
  258.     public void newRace()
  259.     {
  260. -       // Edit _history.
  261. -       _history.put(_raceNumber, new HistoryInfo(_raceNumber, 0, 0, 0));
  262. +       // Add a new history entry.
  263. +       _history.put(_raceNumber, new HistoryInfo(_raceNumber, 0, 0, 0, ""));
  264.        
  265. -       // Randomize _runners.
  266. +       // Randomize runners.
  267.         Collections.shuffle(_runners);
  268.        
  269. -       // Setup 8 new creatures ; pickup the first 8 from _runners.
  270. -       _chosenRunners = _runners.subList(0, 8);
  271. +       // Choose 8 runners from the shuffled list.
  272. +       _chosenRunners = new ArrayList<>(_runners.subList(0, 8));
  273.     }
  274.    
  275. -   public void newSpeeds()
  276. +   public void CalculateLaneSpeeds()
  277.     {
  278. -       _speeds = new int[8][20];
  279. -      
  280. -       int total = 0;
  281. -       int winnerDistance = 0;
  282. -       int secondDistance = 0;
  283. +       var speeds = new int[8][];
  284. +       var firstPlaceIndex = -1;
  285. +       var secondPlaceIndex = -1;
  286. +       var currentWinnerTotal = 0;
  287. +       var currentRunnerUpTotal = 0;
  288.        
  289.         // For each lane.
  290. -       for (int i = 0; i < 8; i++)
  291. +       for (var laneIndex = 0; laneIndex < 8; laneIndex++)
  292.         {
  293. -           // Reset value upon new lane.
  294. -           total = 0;
  295. +           var totalSpeed = 0;
  296. +           var segmentSpeeds = new int[20];
  297.            
  298. -           // Test the 20 segments.
  299. -           for (int j = 0; j < 20; j++)
  300. +           // Calculate the speed for each of the 20 segments in the lane.
  301. +           for (var segmentIndex = 0; segmentIndex < 20; segmentIndex++)
  302.             {
  303. -               if (j == 19)
  304. -                   _speeds[i][j] = 100;
  305. +               if (segmentIndex == 19)
  306. +                   // Set the final segment speed to 100.
  307. +                   segmentSpeeds[segmentIndex] = 100;
  308.                 else
  309. -                   _speeds[i][j] = Rnd.get(60) + 65;
  310. +                   // Generate a random speed.
  311. +                   segmentSpeeds[segmentIndex] = Rnd.get(50) + 55;
  312.                
  313. -               // feed actual total to current lane total.
  314. -               total += _speeds[i][j];
  315. +               // Calculate the total speed for this lane.
  316. +               totalSpeed += segmentSpeeds[segmentIndex];
  317.             }
  318.            
  319. -           // The current total for this line is superior or equals to previous winner ; it means we got a new winner, and the old winner becomes second.
  320. -           if (total >= winnerDistance)
  321. +           // Check if this lane is the new winner or runner-up.
  322. +           if (totalSpeed >= currentWinnerTotal)
  323.             {
  324. -               // Old winner becomes second.
  325. -               _secondIndex = _firstIndex;
  326. +               // The previous winner becomes the runner-up.
  327. +               secondPlaceIndex = firstPlaceIndex;
  328. +               currentRunnerUpTotal = currentWinnerTotal;
  329.                
  330. -               // Old winner distance is the second.
  331. -               secondDistance = winnerDistance;
  332. -              
  333. -               // Find the good index.
  334. -               _firstIndex = i;
  335. -              
  336. -               // Set the new limit to bypass winner position.
  337. -               winnerDistance = total;
  338. +               // Set this lane as the new winner.
  339. +               firstPlaceIndex = laneIndex;
  340. +               currentWinnerTotal = totalSpeed;
  341.             }
  342. -           // The total wasn't enough to
  343. -           else if (total >= secondDistance)
  344. +           else if (totalSpeed >= currentRunnerUpTotal)
  345.             {
  346. -               // Find the good index.
  347. -               _secondIndex = i;
  348. -              
  349. -               // Set the new limit to bypass second position.
  350. -               secondDistance = total;
  351. +               // Set this lane as the new runner-up.
  352. +               secondPlaceIndex = laneIndex;
  353. +               currentRunnerUpTotal = totalSpeed;
  354.             }
  355. +          
  356. +           // Store the speeds for this lane.
  357. +           speeds[laneIndex] = segmentSpeeds;
  358.         }
  359. +      
  360. +       // Store the results.
  361. +       _speeds = speeds;
  362. +       _firstPlaceIndex = firstPlaceIndex;
  363. +       _secondPlaceIndex = secondPlaceIndex;
  364.     }
  365.    
  366.     /**
  367. -    * Load past races informations, feeding _history arrayList.<br>
  368. -    * Also sets _raceNumber, based on latest HistoryInfo loaded.
  369. +    * Loads information on past races and adds it to the _history arrayList. Also sets _raceNumber based on the latest HistoryInfo loaded.
  370.      */
  371.     protected void loadHistory()
  372.     {
  373. -       try (Connection con = ConnectionPool.getConnection();
  374. -           PreparedStatement ps = con.prepareStatement(LOAD_HISTORY);
  375. -           ResultSet rs = ps.executeQuery())
  376. +       try (var connection = ConnectionPool.getConnection();
  377. +           var preparedStatement = connection.prepareStatement(LOAD_HISTORY);
  378. +           var resultSet = preparedStatement.executeQuery())
  379.         {
  380. -           while (rs.next())
  381. +           while (resultSet.next())
  382.             {
  383. -               final int savedRaceNumber = rs.getInt("race_id");
  384. -              
  385. -               _history.put(savedRaceNumber, new HistoryInfo(savedRaceNumber, rs.getInt("first"), rs.getInt("second"), rs.getDouble("odd_rate")));
  386. -              
  387. -               // Calculate the current race number.
  388. +               var savedRaceNumber = resultSet.getInt("race_id");
  389. +               var historyInfo = new HistoryInfo(savedRaceNumber, resultSet.getInt("first"), resultSet.getInt("second"), resultSet.getDouble("odd_rate"), resultSet.getString("winner"));
  390. +               _history.put(savedRaceNumber, historyInfo);
  391.                 if (_raceNumber <= savedRaceNumber)
  392.                     _raceNumber = savedRaceNumber + 1;
  393.             }
  394.         }
  395. -       catch (Exception e)
  396. +       catch (SQLException e)
  397.         {
  398. -           LOGGER.error("Can't load Derby Track history.", e);
  399. +           LOGGER.error("Failed to load Derby Track history", e);
  400.         }
  401.         LOGGER.info("Loaded {} Derby Track records, currently on race #{}.", _history.size(), _raceNumber);
  402.     }
  403.    
  404.     /**
  405. -    * Save an {@link HistoryInfo} record into database.
  406. -    * @param history The HistoryInfo to store.
  407. +    * Saves a {@link HistoryInfo} record into the database.
  408. +    * @param history The HistoryInfo object to be stored.
  409.      */
  410.     protected void saveHistory(HistoryInfo history)
  411.     {
  412. -       try (Connection con = ConnectionPool.getConnection();
  413. -           PreparedStatement ps = con.prepareStatement(SAVE_HISTORY))
  414. +       try (var con = ConnectionPool.getConnection();
  415. +           var ps = con.prepareStatement(SAVE_HISTORY))
  416.         {
  417.             ps.setInt(1, history.getRaceId());
  418. -           ps.setInt(2, history.getFirst());
  419. -           ps.setInt(3, history.getSecond());
  420. +           ps.setInt(2, history.getFirstPlace());
  421. +           ps.setInt(3, history.getSecondPlace());
  422.             ps.setDouble(4, history.getOddRate());
  423. -           ps.execute();
  424. +           ps.setString(5, history.getWinnerName());
  425. +           ps.executeUpdate();
  426.         }
  427. -       catch (Exception e)
  428. +       catch (SQLException e)
  429.         {
  430. -           LOGGER.error("Can't save Derby Track history.", e);
  431. +           LOGGER.error("Failed to save Derby Track history.", e);
  432.         }
  433.     }
  434.    
  435.     /**
  436. -    * Load current bets per lane ; initialize the map keys.
  437. +    * Load current bets per lane and initialize the map keys.
  438.      */
  439.     protected void loadBets()
  440.     {
  441. -       try (Connection con = ConnectionPool.getConnection();
  442. -           PreparedStatement ps = con.prepareStatement(LOAD_BETS);
  443. -           ResultSet rs = ps.executeQuery())
  444. +       try (var con = ConnectionPool.getConnection();
  445. +           var ps = con.prepareStatement(LOAD_BETS);
  446. +           var rs = ps.executeQuery())
  447.         {
  448.             while (rs.next())
  449.                 setBetOnLane(rs.getInt("lane_id"), rs.getLong("bet"), false);
  450.         }
  451. -       catch (Exception e)
  452. +       catch (SQLException e)
  453.         {
  454. -           LOGGER.error("Can't load Derby Track bets.", e);
  455. +           LOGGER.error("Failed to load Derby Track bets.", e);
  456.         }
  457.     }
  458.    
  459.     /**
  460. -    * Save the current lane bet into database.
  461. -    * @param lane : The lane to affect.
  462. -    * @param sum : The sum to set.
  463. +    * Save the current lane bet into the database.
  464. +    * @param lane The lane to affect.
  465. +    * @param sum The sum to set.
  466.      */
  467.     protected void saveBet(int lane, long sum)
  468.     {
  469. -       try (Connection con = ConnectionPool.getConnection();
  470. -           PreparedStatement ps = con.prepareStatement(SAVE_BETS))
  471. +       try (var con = ConnectionPool.getConnection();
  472. +           var ps = con.prepareStatement(SAVE_BETS))
  473.         {
  474.             ps.setInt(1, lane);
  475.             ps.setLong(2, sum);
  476.             ps.execute();
  477.         }
  478. -       catch (Exception e)
  479. +       catch (SQLException e)
  480.         {
  481. -           LOGGER.error("Can't save Derby Track bet.", e);
  482. +           LOGGER.error("Failed to save Derby Track bet.", e);
  483.         }
  484.     }
  485.    
  486.     /**
  487. -    * Clear all lanes bets, either on database or Map.
  488. +    * Clear all lane bets, either in the database or the Map.
  489.      */
  490.     protected void clearBets()
  491.     {
  492. -       for (int key : _betsPerLane.keySet())
  493. +       for (var key : _betsPerLane.keySet())
  494. +       {
  495.             _betsPerLane.put(key, 0L);
  496. -      
  497. -       try (Connection con = ConnectionPool.getConnection();
  498. -           PreparedStatement ps = con.prepareStatement(CLEAR_BETS))
  499. +       }
  500. +       try (var con = ConnectionPool.getConnection();
  501. +           var ps = con.prepareStatement(CLEAR_BETS))
  502.         {
  503.             ps.execute();
  504.         }
  505. -       catch (Exception e)
  506. +       catch (SQLException e)
  507.         {
  508. -           LOGGER.error("Can't clear Derby Track bets.", e);
  509. +           LOGGER.error("Failed to clear Derby Track bets.", e);
  510.         }
  511.     }
  512.    
  513. @@ -353,7 +353,7 @@
  514.      */
  515.     public void setBetOnLane(int lane, long amount, boolean saveOnDb)
  516.     {
  517. -       final long sum = _betsPerLane.getOrDefault(lane, 0L) + amount;
  518. +       var sum = _betsPerLane.getOrDefault(lane, 0L) + amount;
  519.        
  520.         _betsPerLane.put(lane, sum);
  521.        
  522. @@ -362,161 +362,221 @@
  523.     }
  524.    
  525.     /**
  526. -    * Calculate odds for every lane, based on others lanes.
  527. +    * Calculates odds for each lane based on other lanes.
  528.      */
  529. -   protected void calculateOdds()
  530. +   protected void calculateOddsForLanes()
  531.     {
  532. -       // Clear previous List holding old odds.
  533. +       // Clear the previous odds.
  534.         _odds.clear();
  535.        
  536. -       // Sort bets lanes per lane.
  537. -       final Map<Integer, Long> sortedLanes = new TreeMap<>(_betsPerLane);
  538. +       // Sort the bets per lane.
  539. +       Map<Integer, Long> sortedLanes = new TreeMap<>(_betsPerLane);
  540.        
  541. -       // Pass a first loop in order to calculate total sum of all lanes.
  542. -       long sumOfAllLanes = 0;
  543. -       for (long amount : sortedLanes.values())
  544. -           sumOfAllLanes += amount;
  545. +       // Calculate the total sum of all lanes.
  546. +       var sumOfAllLanes = sortedLanes.values().stream().mapToLong(Long::valueOf).sum();
  547.        
  548. -       // As we get the sum, we can now calculate the odd rate of each lane.
  549. -       for (long amount : sortedLanes.values())
  550. -           _odds.add((amount == 0) ? 0D : Math.max(1.25, sumOfAllLanes * 0.7 / amount));
  551. +       // Calculate the odd rate of each lane based on the sum of the lane amounts.
  552. +       for (var amount : sortedLanes.values())
  553. +       {
  554. +           var randomValue = getRandomOddValue();
  555. +           var odd = (amount == 0) ? 0D : Math.max(1.25, sumOfAllLanes * randomValue / amount);
  556. +           _odds.add(odd);
  557. +       }
  558. +   }
  559. +  
  560. +   // Generate a random odd value.
  561. +   private static final double[] oddValues =
  562. +   {
  563. +       0.4,
  564. +       0.5
  565. +   };
  566. +  
  567. +   private static double getRandomOddValue()
  568. +   {
  569. +       Random rand = new Random();
  570. +       return oddValues[rand.nextInt(oddValues.length)];
  571. +   }
  572. +  
  573. +   // New method to get runner odd by runner number
  574. +   public double getRunnerOdd(int runnerNumber)
  575. +   {
  576. +       if (runnerNumber > 0 && runnerNumber <= _odds.size())
  577. +           return _odds.get(runnerNumber - 1);
  578. +       return 0.0;
  579.     }
  580.    
  581.     private class Announcement implements Runnable
  582.     {
  583. -       public Announcement()
  584. -       {
  585. -       }
  586. -      
  587.         @Override
  588.         public void run()
  589.         {
  590. -           if (_finalCountdown > 1200)
  591. +           if (_finalCountdown > 900)
  592.                 _finalCountdown = 0;
  593.            
  594.             switch (_finalCountdown)
  595.             {
  596.                 case 0:
  597.                     newRace();
  598. -                   newSpeeds();
  599. -                  
  600. -                   _state = RaceState.ACCEPTING_BETS;
  601. -                   _packet = new MonRaceInfo(CODES[0][0], CODES[0][1], getRunners(), getSpeeds());
  602. -                  
  603. -                   ZoneManager.toAllPlayersInZoneType(DerbyTrackZone.class, _packet, SystemMessage.getSystemMessage(SystemMessageId.MONSRACE_TICKETS_AVAILABLE_FOR_S1_RACE).addNumber(_raceNumber));
  604. +                   CalculateLaneSpeeds();
  605. +                   _state = RaceState.BETTING;
  606. +                   _packet = new MonRaceInfo(CODES.get(0).get(0), CODES.get(0).get(1), getChosenRunners(), getSpeeds());
  607. +                   World.toAllOnlinePlayers(new NpcSay(RACE_MANAGER, SayType.TRADE, "Monster Race: Tickets are now available. Next announcements inside of race zone."));
  608.                     break;
  609. -              
  610. -               case 30: // 30 sec
  611. -               case 60: // 1 min
  612. -               case 90: // 1 min 30 sec
  613. -               case 120: // 2 min
  614. -               case 150: // 2 min 30
  615. -               case 180: // 3 min
  616. -               case 210: // 3 min 30
  617. -               case 240: // 4 min
  618. -               case 270: // 4 min 30 sec
  619. -               case 330: // 5 min 30 sec
  620. -               case 360: // 6 min
  621. -               case 390: // 6 min 30 sec
  622. -               case 420: // 7 min
  623. -               case 450: // 7 min 30
  624. -               case 480: // 8 min
  625. -               case 510: // 8 min 30
  626. -               case 540: // 9 min
  627. -               case 570: // 9 min 30 sec
  628. -               case 630: // 10 min 30 sec
  629. -               case 660: // 11 min
  630. -               case 690: // 11 min 30 sec
  631. -               case 720: // 12 min
  632. -               case 750: // 12 min 30
  633. -               case 780: // 13 min
  634. -               case 810: // 13 min 30
  635. -               case 870: // 14 min 30 sec
  636. -                   ZoneManager.toAllPlayersInZoneType(DerbyTrackZone.class, SystemMessage.getSystemMessage(SystemMessageId.MONSRACE_TICKETS_NOW_AVAILABLE_FOR_S1_RACE).addNumber(_raceNumber));
  637. +               case 180: // 3 minutes
  638. +                   ZoneManager.toAllPlayersInZoneType(DerbyTrackZone.class, _packet, new NpcSay(RACE_MANAGER, SayType.TRADE, "7 minutes left to begin the race."));
  639.                     break;
  640. -              
  641. -               case 300: // 5 min
  642. -                   ZoneManager.toAllPlayersInZoneType(DerbyTrackZone.class, SystemMessage.getSystemMessage(SystemMessageId.MONSRACE_TICKETS_NOW_AVAILABLE_FOR_S1_RACE).addNumber(_raceNumber), SystemMessage.getSystemMessage(SystemMessageId.MONSRACE_TICKETS_STOP_IN_S1_MINUTES).addNumber(10));
  643. +               case 240: // 4 minutes
  644. +                   talk();
  645.                     break;
  646. -              
  647. -               case 600: // 10 min
  648. -                   ZoneManager.toAllPlayersInZoneType(DerbyTrackZone.class, SystemMessage.getSystemMessage(SystemMessageId.MONSRACE_TICKETS_NOW_AVAILABLE_FOR_S1_RACE).addNumber(_raceNumber), SystemMessage.getSystemMessage(SystemMessageId.MONSRACE_TICKETS_STOP_IN_S1_MINUTES).addNumber(5));
  649. +               case 420: // 7 minutes
  650. +                   ZoneManager.toAllPlayersInZoneType(DerbyTrackZone.class, _packet, new NpcSay(RACE_MANAGER, SayType.TRADE, "Bets are about to close in 3 minutes. Good luck everyone!"));
  651.                     break;
  652. -              
  653. -               case 840: // 14 min
  654. -                   ZoneManager.toAllPlayersInZoneType(DerbyTrackZone.class, SystemMessage.getSystemMessage(SystemMessageId.MONSRACE_TICKETS_NOW_AVAILABLE_FOR_S1_RACE).addNumber(_raceNumber), SystemMessage.getSystemMessage(SystemMessageId.MONSRACE_TICKETS_STOP_IN_S1_MINUTES).addNumber(1));
  655. -                   break;
  656. -              
  657. -               case 900: // 15 min
  658. +               case 600: // 10 minutes
  659.                     _state = RaceState.WAITING;
  660. +                   calculateOddsForLanes();
  661. +                   ZoneManager.toAllPlayersInZoneType(DerbyTrackZone.class, _packet, new NpcSay(RACE_MANAGER, SayType.TRADE, "The race is about to begin in 1 minute. Get ready!"));
  662. +                   break;
  663. +               case 630: // 10 min 30 sec
  664. +                   ZoneManager.toAllPlayersInZoneType(DerbyTrackZone.class, _packet, SystemMessage.sendString("Monster Race: The race begins in 30 seconds."));
  665.                    
  666. -                   calculateOdds();
  667. -                  
  668. -                   ZoneManager.toAllPlayersInZoneType(DerbyTrackZone.class, SystemMessage.getSystemMessage(SystemMessageId.MONSRACE_TICKETS_NOW_AVAILABLE_FOR_S1_RACE).addNumber(_raceNumber), SystemMessage.getSystemMessage(SystemMessageId.MONSRACE_S1_TICKET_SALES_CLOSED));
  669.                     break;
  670. -              
  671. -               case 960: // 16 min
  672. -               case 1020: // 17 min
  673. -                   final int minutes = (_finalCountdown == 960) ? 2 : 1;
  674. -                   ZoneManager.toAllPlayersInZoneType(DerbyTrackZone.class, SystemMessage.getSystemMessage(SystemMessageId.MONSRACE_S2_BEGINS_IN_S1_MINUTES).addNumber(minutes));
  675. +               case 650: // 10 min 50 sec
  676. +                   ZoneManager.toAllPlayersInZoneType(DerbyTrackZone.class, _packet, SystemMessage.sendString("Monster Race: Race is about to begin! Countdown in five seconds."));
  677.                     break;
  678. -              
  679. -               case 1050: // 17 min 30 sec
  680. -                   ZoneManager.toAllPlayersInZoneType(DerbyTrackZone.class, SystemMessage.getSystemMessage(SystemMessageId.MONSRACE_S1_BEGINS_IN_30_SECONDS));
  681. -                   break;
  682. -              
  683. -               case 1070: // 17 min 50 sec
  684. -                   ZoneManager.toAllPlayersInZoneType(DerbyTrackZone.class, SystemMessage.getSystemMessage(SystemMessageId.MONSRACE_S1_COUNTDOWN_IN_FIVE_SECONDS));
  685. -                   break;
  686. -              
  687. -               case 1075: // 17 min 55 sec
  688. -               case 1076: // 17 min 56 sec
  689. -               case 1077: // 17 min 57 sec
  690. -               case 1078: // 17 min 58 sec
  691. -               case 1079: // 17 min 59 sec
  692. -                   final int seconds = 1080 - _finalCountdown;
  693. +               case 655: // 10 min 55 sec
  694. +               case 656: // 10 min 56 sec
  695. +               case 657: // 10 min 57 sec
  696. +               case 658: // 10 min 58 sec
  697. +               case 659: // 10 min 59 sec
  698. +                   var seconds = 660 - _finalCountdown;
  699.                     ZoneManager.toAllPlayersInZoneType(DerbyTrackZone.class, SystemMessage.getSystemMessage(SystemMessageId.MONSRACE_BEGINS_IN_S1_SECONDS).addNumber(seconds));
  700.                     break;
  701. -              
  702. -               case 1080: // 18 min
  703. -                   _state = RaceState.STARTING_RACE;
  704. -                   _packet = new MonRaceInfo(CODES[1][0], CODES[1][1], getRunners(), getSpeeds());
  705. -                  
  706. +               case 660: // 11 min
  707. +                   _state = RaceState.STARTING;
  708. +                   _packet = new MonRaceInfo(CODES.get(1).get(0), CODES.get(1).get(1), getChosenRunners(), getSpeeds());
  709.                     ZoneManager.toAllPlayersInZoneType(DerbyTrackZone.class, SystemMessage.getSystemMessage(SystemMessageId.MONSRACE_RACE_START), SOUND_1, SOUND_2, _packet);
  710.                     break;
  711. -              
  712. -               case 1085: // 18 min 5 sec
  713. -                   _packet = new MonRaceInfo(CODES[2][0], CODES[2][1], getRunners(), getSpeeds());
  714. +               case 665: // 11 min 5 sec
  715. +                   // Shuffle the indices to get a random order of runners
  716. +                   Collections.shuffle(_runnerIndices);
  717.                    
  718. +                   for (int i = 0; i < 4; i++)
  719. +                   {
  720. +                       var runnerIndex = _runnerIndices.get(i);
  721. +                       var delay = 0;
  722. +                       switch (i)
  723. +                       {
  724. +                           case 0:
  725. +                               _message = "I will win!";
  726. +                               delay = 4000;
  727. +                               break;
  728. +                           case 1:
  729. +                               _message = "No! I will be the winner!";
  730. +                               delay = 7000;
  731. +                               break;
  732. +                           case 2:
  733. +                               _message = "Oh my legs! But I will try more..";
  734. +                               delay = 10000;
  735. +                               break;
  736. +                           case 3:
  737. +                               _message = "I'll need an ice cream after this.";
  738. +                               delay = 12000;
  739. +                               break;
  740. +                       }
  741. +                       _timer.schedule(new SayTask(new NpcSay(getChosenRunners().get(runnerIndex), SayType.ALL, _message)), delay);
  742. +                   }
  743. +                   _packet = new MonRaceInfo(CODES.get(2).get(0), CODES.get(2).get(1), getChosenRunners(), getSpeeds());
  744.                     ZoneManager.toAllPlayersInZoneType(DerbyTrackZone.class, _packet);
  745.                     break;
  746. -              
  747. -               case 1115: // 18 min 35 sec
  748. -                   _state = RaceState.RACE_END;
  749. -                  
  750. -                   // Retrieve current HistoryInfo and populate it with data, then stores it in database.
  751. -                   final HistoryInfo info = getHistoryInfo(_raceNumber);
  752. +               case 690: // 11 min 30 sec
  753. +                   _state = RaceState.FINISHED;
  754. +                   var info = getHistoryInfo(_raceNumber);
  755.                     if (info != null)
  756.                     {
  757. -                       info.setFirst(getFirst());
  758. -                       info.setSecond(getSecond());
  759. -                       info.setOddRate(_odds.get(getFirst()));
  760. -                      
  761. +                       info.setFirst(getFirstPlace());
  762. +                       info.setSecond(getSecondPlace());
  763. +                       info.setOddRate(_odds.get(getFirstPlace()));
  764. +                       info.setWinnerName(getRunnerName(getFirstPlace()));
  765.                         saveHistory(info);
  766.                     }
  767. -                  
  768. -                   // Clear bets.
  769.                     clearBets();
  770. +                   var firstPlace = getFirstPlace() + 1;
  771. +                   var secondPlace = getSecondPlace() + 1;
  772. +                   var firstPlaceOdd = _odds.get(getFirstPlace());
  773. +                   var secondPlaceOdd = _odds.get(getSecondPlace());
  774. +                   var first = _chosenRunners.get(getFirstPlace());
  775. +                   var second = _chosenRunners.get(getSecondPlace());
  776.                    
  777. -                   ZoneManager.toAllPlayersInZoneType(DerbyTrackZone.class, SystemMessage.getSystemMessage(SystemMessageId.MONSRACE_FIRST_PLACE_S1_SECOND_S2).addNumber(getFirst() + 1).addNumber(getSecond() + 1), SystemMessage.getSystemMessage(SystemMessageId.MONSRACE_S1_RACE_END).addNumber(_raceNumber));
  778. +                   ZoneManager.toAllPlayersInZoneType(DerbyTrackZone.class, _packet, new NpcSay(first, SayType.SHOUT, "I win! I win.. Yea!!!"));
  779. +                   ZoneManager.toAllPlayersInZoneType(DerbyTrackZone.class, _packet, new NpcSay(second, SayType.SHOUT, "I came second! I'm so happy!"));
  780. +                   ZoneManager.toAllPlayersInZoneType(DerbyTrackZone.class, _packet, SystemMessage.sendString("First place goes to lane " + firstPlace + ". Prize Odds: " + firstPlaceOdd));
  781. +                   ZoneManager.toAllPlayersInZoneType(DerbyTrackZone.class, _packet, SystemMessage.sendString("Second place goes to lane " + secondPlace + ". Prize Odds: " + secondPlaceOdd * 0.70));
  782.                     _raceNumber++;
  783.                     break;
  784. -              
  785. -               case 1140: // 19 min
  786. -                   ZoneManager.toAllPlayersInZoneType(DerbyTrackZone.class, new DeleteObject(getRunners().get(0)), new DeleteObject(getRunners().get(1)), new DeleteObject(getRunners().get(2)), new DeleteObject(getRunners().get(3)), new DeleteObject(getRunners().get(4)), new DeleteObject(getRunners().get(5)), new DeleteObject(getRunners().get(6)), new DeleteObject(getRunners().get(7)));
  787. +               case 720: // 12 minutes. End of event!
  788. +                   var deleteObjects = getChosenRunners().stream().map(DeleteObject::new).collect(Collectors.toList());
  789. +                   ZoneManager.toAllPlayersInZoneType(DerbyTrackZone.class, deleteObjects.toArray(new DeleteObject[0]));
  790. +                   ZoneManager.toAllPlayersInZoneType(DerbyTrackZone.class, _packet, SystemMessage.sendString("Next Race will take place in 3 minutes."));
  791. +
  792.                     break;
  793.             }
  794. -           _finalCountdown += 1;
  795. +           _finalCountdown++;
  796. +       }
  797. +   }
  798. +  
  799. +   /**
  800. +    * Talks to runners to convince players to bet on them for a race. Displays five messages at different intervals from different runners.
  801. +    */
  802. +   private void talk()
  803. +   {
  804. +       for (int i = 0; i < getChosenRunners().size(); i++)
  805. +           _runnerIndices.add(i);
  806. +      
  807. +       // Shuffle the indices to get a random order of runners
  808. +       Collections.shuffle(_runnerIndices);
  809. +      
  810. +       for (int i = 0; i < 4; i++)
  811. +       {
  812. +           // Create a timer to schedule messages
  813. +           Timer timer = new Timer();
  814. +           int runnerIndex = _runnerIndices.get(i);
  815. +           String message = "";
  816. +           int delay = 0;
  817. +           switch (i)
  818. +           {
  819. +               case 0:
  820. +                   message = "I am runner " + (runnerIndex + 1) + ". Choose me! I will win.";
  821. +                   break;
  822. +               case 1:
  823. +                   message = "No! Runner " + (_runnerIndices.get(0) + 1) + " is not as fast as me! Choose me instead! I'm runner " + (runnerIndex + 1);
  824. +                   delay = 30000;
  825. +                   break;
  826. +               case 2:
  827. +                   message = "I am runner " + (runnerIndex + 1) + ". I'm not the fastest, but I'll try my best!";
  828. +                   delay = 240000;
  829. +                   break;
  830. +               case 3:
  831. +                   message = "Good luck to all of us! May the fastest one win!";
  832. +                   delay = 420000;
  833. +                   break;
  834. +           }
  835. +           timer.schedule(new SayTask(new NpcSay(getChosenRunners().get(runnerIndex), SayType.SHOUT, message)), delay);
  836. +       }
  837. +   }
  838. +  
  839. +   private class SayTask extends TimerTask
  840. +   {
  841. +       private NpcSay say;
  842. +      
  843. +       public SayTask(NpcSay say)
  844. +       {
  845. +           this.say = say;
  846. +       }
  847. +      
  848. +       @Override
  849. +       public void run()
  850. +       {
  851. +           ZoneManager.toAllPlayersInZoneType(DerbyTrackZone.class, say);
  852.         }
  853.     }
  854.    
  855. diff --git a/aCis_gameserver/java/net/sf/l2j/gameserver/enums/RaceState.java b/aCis_gameserver/java/net/sf/l2j/gameserver/enums/RaceState.java
  856. new file mode 100644
  857. index 0000000..b2fcd09
  858. --- /dev/null
  859. +++ b/aCis_gameserver/java/net/sf/l2j/gameserver/enums/RaceState.java
  860. @@ -0,0 +1,12 @@
  861. +package net.sf.l2j.gameserver.enums;
  862. +
  863. +/**
  864. + * Enumeration representing the state of the race.
  865. + */
  866. +public enum RaceState
  867. +{
  868. +   BETTING, // Currently in progress for betting
  869. +   WAITING, // Currently waiting to begin
  870. +   STARTING, // About to start
  871. +   FINISHED // Just finished
  872. +}
  873. diff --git a/aCis_gameserver/java/net/sf/l2j/gameserver/model/HistoryInfo.java b/aCis_gameserver/java/net/sf/l2j/gameserver/model/HistoryInfo.java
  874. index f3822d2..9911f34 100644
  875. --- a/aCis_gameserver/java/net/sf/l2j/gameserver/model/HistoryInfo.java
  876. +++ b/aCis_gameserver/java/net/sf/l2j/gameserver/model/HistoryInfo.java
  877. @@ -3,16 +3,18 @@
  878.  public class HistoryInfo
  879.  {
  880.     private final int _raceId;
  881. -   private int _first;
  882. -   private int _second;
  883. +   private int _firstPlace;
  884. +   private int _secondPlace;
  885.     private double _oddRate;
  886. +   private String _winner;
  887.    
  888. -   public HistoryInfo(int raceId, int first, int second, double oddRate)
  889. +   public HistoryInfo(int raceId, int first, int second, double oddRate, String winner)
  890.     {
  891.         _raceId = raceId;
  892. -       _first = first;
  893. -       _second = second;
  894. +       _firstPlace = first;
  895. +       _secondPlace = second;
  896.         _oddRate = oddRate;
  897. +       _winner = winner;
  898.     }
  899.    
  900.     public int getRaceId()
  901. @@ -20,14 +22,14 @@
  902.         return _raceId;
  903.     }
  904.    
  905. -   public int getFirst()
  906. +   public int getFirstPlace()
  907.     {
  908. -       return _first;
  909. +       return _firstPlace;
  910.     }
  911.    
  912. -   public int getSecond()
  913. +   public int getSecondPlace()
  914.     {
  915. -       return _second;
  916. +       return _secondPlace;
  917.     }
  918.    
  919.     public double getOddRate()
  920. @@ -35,18 +37,28 @@
  921.         return _oddRate;
  922.     }
  923.    
  924. +   public String getWinnerName()
  925. +   {
  926. +       return _winner;
  927. +   }
  928. +  
  929.     public void setFirst(int first)
  930.     {
  931. -       _first = first;
  932. +       _firstPlace = first;
  933.     }
  934.    
  935.     public void setSecond(int second)
  936.     {
  937. -       _second = second;
  938. +       _secondPlace = second;
  939.     }
  940.    
  941.     public void setOddRate(double oddRate)
  942.     {
  943.         _oddRate = oddRate;
  944.     }
  945. +  
  946. +   public void setWinnerName(String winner)
  947. +   {
  948. +       _winner = winner;
  949. +   }
  950.  }
  951. \ No newline at end of file
  952. diff --git a/aCis_gameserver/java/net/sf/l2j/gameserver/model/actor/instance/DerbyTrackManagerNpc.java b/aCis_gameserver/java/net/sf/l2j/gameserver/model/actor/instance/DerbyTrackManagerNpc.java
  953. index 46c5d68..61143f2 100644
  954. --- a/aCis_gameserver/java/net/sf/l2j/gameserver/model/actor/instance/DerbyTrackManagerNpc.java
  955. +++ b/aCis_gameserver/java/net/sf/l2j/gameserver/model/actor/instance/DerbyTrackManagerNpc.java
  956. @@ -4,15 +4,16 @@
  957.  
  958.  import net.sf.l2j.commons.lang.StringUtil;
  959.  
  960. +import net.sf.l2j.Config;
  961.  import net.sf.l2j.gameserver.data.manager.DerbyTrackManager;
  962. -import net.sf.l2j.gameserver.data.manager.DerbyTrackManager.RaceState;
  963. +import net.sf.l2j.gameserver.data.xml.ItemData;
  964. +import net.sf.l2j.gameserver.enums.RaceState;
  965.  import net.sf.l2j.gameserver.idfactory.IdFactory;
  966. -import net.sf.l2j.gameserver.model.HistoryInfo;
  967.  import net.sf.l2j.gameserver.model.WorldObject;
  968. -import net.sf.l2j.gameserver.model.actor.Npc;
  969.  import net.sf.l2j.gameserver.model.actor.Player;
  970.  import net.sf.l2j.gameserver.model.actor.template.NpcTemplate;
  971.  import net.sf.l2j.gameserver.model.item.instance.ItemInstance;
  972. +import net.sf.l2j.gameserver.model.item.kind.Item;
  973.  import net.sf.l2j.gameserver.network.SystemMessageId;
  974.  import net.sf.l2j.gameserver.network.serverpackets.ActionFailed;
  975.  import net.sf.l2j.gameserver.network.serverpackets.DeleteObject;
  976. @@ -21,16 +22,11 @@
  977.  
  978.  public class DerbyTrackManagerNpc extends Folk
  979.  {
  980. -   protected static final int[] TICKET_PRICES =
  981. +   protected static final int TICKET_PRICES[] =
  982.     {
  983. -       100,
  984. -       500,
  985. -       1000,
  986. -       5000,
  987. -       10000,
  988. -       20000,
  989. -       50000,
  990. -       100000
  991. +       Config._price1,
  992. +       Config._price2,
  993. +       Config._price3
  994.     };
  995.    
  996.     public DerbyTrackManagerNpc(int objectId, NpcTemplate template)
  997. @@ -41,49 +37,47 @@
  998.     @Override
  999.     public void onBypassFeedback(Player player, String command)
  1000.     {
  1001. +       Item ItemName = ItemData.getInstance().getTemplate(Config._itemID);
  1002. +       String itemName = ItemName.getName();
  1003. +      
  1004.         if (command.startsWith("BuyTicket"))
  1005.         {
  1006. -           if (DerbyTrackManager.getInstance().getCurrentRaceState() != RaceState.ACCEPTING_BETS)
  1007. +           var currentRaceState = DerbyTrackManager.getInstance().getCurrentRaceState();
  1008. +          
  1009. +           if (currentRaceState != RaceState.BETTING)
  1010.             {
  1011.                 player.sendPacket(SystemMessageId.MONSRACE_TICKETS_NOT_AVAILABLE);
  1012.                 super.onBypassFeedback(player, "Chat 0");
  1013.                 return;
  1014.             }
  1015. -          
  1016. -           int val = Integer.parseInt(command.substring(10));
  1017. +           var val = Integer.parseInt(command.substring(10));
  1018.             if (val == 0)
  1019.             {
  1020.                 player.setRace(0, 0);
  1021.                 player.setRace(1, 0);
  1022.             }
  1023. -          
  1024. -           if ((val == 10 && player.getRace(0) == 0) || (val == 20 && player.getRace(0) == 0 && player.getRace(1) == 0))
  1025. +           else if ((val == 10 && player.getRace(0) == 0) || (val == 20 && player.getRace(0) == 0 && player.getRace(1) == 0))
  1026.                 val = 0;
  1027.            
  1028. -           int npcId = getTemplate().getNpcId();
  1029. -          
  1030. -           String search;
  1031. -           String replace;
  1032. -          
  1033. -           final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
  1034. -          
  1035. +           var npcId = getTemplate().getNpcId();
  1036. +           var html = new NpcHtmlMessage(getObjectId());
  1037.             if (val < 10)
  1038.             {
  1039.                 html.setFile(getHtmlPath(npcId, 2));
  1040. -               for (int i = 0; i < 8; i++)
  1041. +               for (var i = 0; i < 8; i++)
  1042.                 {
  1043. -                   int n = i + 1;
  1044. -                   search = "Mob" + n;
  1045. +                   var n = i + 1;
  1046. +                   var search = "Mob" + n;
  1047.                     html.replace(search, DerbyTrackManager.getInstance().getRunnerName(i));
  1048.                 }
  1049. -               search = "No1";
  1050. -               if (val == 0)
  1051. -                   html.replace(search, "");
  1052. -               else
  1053. +               var search = "No1";
  1054. +               if (val != 0)
  1055.                 {
  1056.                     html.replace(search, val);
  1057.                     player.setRace(0, val);
  1058.                 }
  1059. +               else
  1060. +                   html.replace(search, "");
  1061.             }
  1062.             else if (val < 20)
  1063.             {
  1064. @@ -92,226 +86,244 @@
  1065.                
  1066.                 html.setFile(getHtmlPath(npcId, 3));
  1067.                 html.replace("0place", player.getRace(0));
  1068. -               search = "Mob1";
  1069. -               replace = DerbyTrackManager.getInstance().getRunnerName(player.getRace(0) - 1);
  1070. +               var search = "Mob1";
  1071. +               var replace = DerbyTrackManager.getInstance().getRunnerName(player.getRace(0) - 1);
  1072.                 html.replace(search, replace);
  1073. +               search = "itemname";
  1074. +               html.replace(search, itemName);
  1075. +               for (var i = 0; i < TICKET_PRICES.length; i++)
  1076. +               {
  1077. +                   search = "price" + (i + 1);
  1078. +                   html.replace(search, String.valueOf(TICKET_PRICES[i]));
  1079. +               }
  1080.                 search = "0adena";
  1081. -              
  1082. -               if (val == 10)
  1083. -                   html.replace(search, "");
  1084. -               else
  1085. +               if (val != 10)
  1086.                 {
  1087.                     html.replace(search, TICKET_PRICES[val - 11]);
  1088.                     player.setRace(1, val - 10);
  1089.                 }
  1090. +               else
  1091. +                   html.replace(search, "");
  1092.             }
  1093.             else if (val == 20)
  1094.             {
  1095.                 if (player.getRace(0) == 0 || player.getRace(1) == 0)
  1096.                     return;
  1097.                
  1098. +               var raceId = player.getRace(0);
  1099. +               var priceId = player.getRace(1);
  1100. +               var ticketPrice = TICKET_PRICES[priceId - 1];
  1101. +              
  1102.                 html.setFile(getHtmlPath(npcId, 4));
  1103. -               html.replace("0place", player.getRace(0));
  1104. -               search = "Mob1";
  1105. -               replace = DerbyTrackManager.getInstance().getRunnerName(player.getRace(0) - 1);
  1106. -               html.replace(search, replace);
  1107. -               search = "0adena";
  1108. -               int price = TICKET_PRICES[player.getRace(1) - 1];
  1109. -               html.replace(search, price);
  1110. -               search = "0tax";
  1111. -               int tax = 0;
  1112. -               html.replace(search, tax);
  1113. -               search = "0total";
  1114. -               int total = price + tax;
  1115. -               html.replace(search, total);
  1116. +               html.replace("0place", raceId);
  1117. +               html.replace("Mob1", DerbyTrackManager.getInstance().getRunnerName(raceId - 1));
  1118. +               html.replace("0adena", ticketPrice);
  1119. +               html.replace("0tax", 0);
  1120. +               html.replace("0total", ticketPrice);
  1121. +               html.replace("itemname", itemName);
  1122. +              
  1123.             }
  1124.             else
  1125.             {
  1126.                 if (player.getRace(0) == 0 || player.getRace(1) == 0)
  1127.                     return;
  1128.                
  1129. -               int ticket = player.getRace(0);
  1130. +               int raceId = player.getRace(0);
  1131.                 int priceId = player.getRace(1);
  1132. -              
  1133. -               if (!player.reduceAdena("Race", TICKET_PRICES[priceId - 1], this, true))
  1134. -                   return;
  1135. +               int ticketPrice = TICKET_PRICES[priceId - 1];
  1136. +
  1137. +               if (!player.destroyItemByItemId("Race", Config._itemID, ticketPrice, this, true))
  1138. +               {
  1139. +                   player.sendMessage("Not enough " + itemName + " to purchase ticket.");
  1140. +                   return;
  1141. +               }
  1142.                
  1143.                 player.setRace(0, 0);
  1144.                 player.setRace(1, 0);
  1145.                
  1146. -               ItemInstance item = new ItemInstance(IdFactory.getInstance().getNextId(), 4443);
  1147. +               var item = new ItemInstance(IdFactory.getInstance().getNextId(), 4443);
  1148.                 item.setCount(1);
  1149.                 item.setEnchantLevel(DerbyTrackManager.getInstance().getRaceNumber());
  1150. -               item.setCustomType1(ticket);
  1151. -               item.setCustomType2(TICKET_PRICES[priceId - 1] / 100);
  1152. +               item.setCustomType1(raceId);
  1153. +               item.setCustomType2(ticketPrice / 10);
  1154.                
  1155.                 player.addItem("Race", item, player, false);
  1156.                 player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.ACQUIRED_S1_S2).addNumber(DerbyTrackManager.getInstance().getRaceNumber()).addItemName(4443));
  1157.                
  1158. -               // Refresh lane bet.
  1159. -               DerbyTrackManager.getInstance().setBetOnLane(ticket, TICKET_PRICES[priceId - 1], true);
  1160. +               DerbyTrackManager.getInstance().setBetOnLane(raceId, ticketPrice, true);
  1161.                 super.onBypassFeedback(player, "Chat 0");
  1162.                 return;
  1163.             }
  1164. +          
  1165.             html.replace("1race", DerbyTrackManager.getInstance().getRaceNumber());
  1166.             html.replace("%objectId%", getObjectId());
  1167.             player.sendPacket(html);
  1168.             player.sendPacket(ActionFailed.STATIC_PACKET);
  1169.         }
  1170. -       else if (command.equals("ShowOdds"))
  1171. +       else if (command.equalsIgnoreCase("ShowOdds"))
  1172.         {
  1173. -           if (DerbyTrackManager.getInstance().getCurrentRaceState() == RaceState.ACCEPTING_BETS)
  1174. +           var currentRaceState = DerbyTrackManager.getInstance().getCurrentRaceState();
  1175. +           if (currentRaceState == RaceState.BETTING)
  1176.             {
  1177.                 player.sendPacket(SystemMessageId.MONSRACE_NO_PAYOUT_INFO);
  1178.                 super.onBypassFeedback(player, "Chat 0");
  1179.                 return;
  1180.             }
  1181.            
  1182. -           final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
  1183. +           var html = new NpcHtmlMessage(getObjectId());
  1184.             html.setFile(getHtmlPath(getTemplate().getNpcId(), 5));
  1185. -           for (int i = 0; i < 8; i++)
  1186. +          
  1187. +           for (var i = 0; i < 8; i++)
  1188.             {
  1189. -               final int n = i + 1;
  1190. +               var n = i + 1;
  1191. +               var mobName = DerbyTrackManager.getInstance().getRunnerName(i);
  1192. +               html.replace("Mob" + n, mobName);
  1193.                
  1194. -               html.replace("Mob" + n, DerbyTrackManager.getInstance().getRunnerName(i));
  1195. -              
  1196. -               // Odd
  1197. -               final double odd = DerbyTrackManager.getInstance().getOdds().get(i);
  1198. +               var odd = DerbyTrackManager.getInstance().getOdds().get(i);
  1199.                 html.replace("Odd" + n, (odd > 0D) ? String.format(Locale.ENGLISH, "%.1f", odd) : "&$804;");
  1200.             }
  1201. +          
  1202.             html.replace("1race", DerbyTrackManager.getInstance().getRaceNumber());
  1203.             html.replace("%objectId%", getObjectId());
  1204. +          
  1205.             player.sendPacket(html);
  1206.             player.sendPacket(ActionFailed.STATIC_PACKET);
  1207.         }
  1208. -       else if (command.equals("ShowInfo"))
  1209. +       else if (command.equalsIgnoreCase("ShowInfo"))
  1210.         {
  1211. -           final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
  1212. +           var html = new NpcHtmlMessage(getObjectId());
  1213.             html.setFile(getHtmlPath(getTemplate().getNpcId(), 6));
  1214.            
  1215. -           for (int i = 0; i < 8; i++)
  1216. +           for (var i = 1; i <= 8; i++)
  1217.             {
  1218. -               int n = i + 1;
  1219. -               String search = "Mob" + n;
  1220. -               html.replace(search, DerbyTrackManager.getInstance().getRunnerName(i));
  1221. +               var search = "Mob" + i;
  1222. +               html.replace(search, DerbyTrackManager.getInstance().getRunnerName(i - 1));
  1223.             }
  1224. -           html.replace("%objectId%", getObjectId());
  1225. +          
  1226. +           html.replace("%objectId%", String.valueOf(getObjectId()));
  1227.             player.sendPacket(html);
  1228.             player.sendPacket(ActionFailed.STATIC_PACKET);
  1229.         }
  1230.         else if (command.equals("ShowTickets"))
  1231.         {
  1232. -           // Generate data.
  1233. -           final StringBuilder sb = new StringBuilder();
  1234. +           var sb = new StringBuilder();
  1235.            
  1236. -           // Retrieve player's tickets.
  1237. -           for (ItemInstance ticket : player.getInventory().getAllItemsByItemId(4443))
  1238. +           for (var ticket : player.getInventory().getAllItemsByItemId(4443))
  1239.             {
  1240. -               // Don't list current race tickets.
  1241. +               // Skip tickets for the current race.
  1242.                 if (ticket.getEnchantLevel() == DerbyTrackManager.getInstance().getRaceNumber())
  1243.                     continue;
  1244.                
  1245. -               StringUtil.append(sb, "<tr><td><a action=\"bypass -h npc_%objectId%_ShowTicket ", ticket.getObjectId(), "\">", ticket.getEnchantLevel(), " Race Number</a></td><td align=right><font color=\"LEVEL\">", ticket.getCustomType1(), "</font> Number</td><td align=right><font color=\"LEVEL\">", ticket.getCustomType2() * 100, "</font> Adena</td></tr>");
  1246. +               StringUtil.append(sb, "<tr><td><a action=\"bypass -h npc_%objectId%_ShowTicket ", ticket.getObjectId(), "\">", ticket.getEnchantLevel(), " Race Number</a></td><td align=right><font color=\"LEVEL\">", ticket.getCustomType1(), "</font> Number</td><td align=right><font color=\"LEVEL\">Your Bet: ", ticket.getCustomType2() * 10, "</font></td></tr>");
  1247.             }
  1248. -          
  1249. -           final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
  1250. +           var html = new NpcHtmlMessage(getObjectId());
  1251.             html.setFile(getHtmlPath(getTemplate().getNpcId(), 7));
  1252.             html.replace("%tickets%", sb.toString());
  1253.             html.replace("%objectId%", getObjectId());
  1254.             player.sendPacket(html);
  1255.             player.sendPacket(ActionFailed.STATIC_PACKET);
  1256.         }
  1257. +      
  1258.         else if (command.startsWith("ShowTicket"))
  1259.         {
  1260. -           // Retrieve ticket objectId.
  1261. -           final int val = Integer.parseInt(command.substring(11));
  1262. +           var val = Integer.parseInt(command.substring(11));
  1263.             if (val == 0)
  1264.             {
  1265.                 super.onBypassFeedback(player, "Chat 0");
  1266.                 return;
  1267.             }
  1268.            
  1269. -           // Retrieve ticket on player's inventory.
  1270. -           final ItemInstance ticket = player.getInventory().getItemByObjectId(val);
  1271. +           // Find ticket in player's inventory.
  1272. +           var ticket = player.getInventory().getItemByObjectId(val);
  1273.             if (ticket == null)
  1274.             {
  1275.                 super.onBypassFeedback(player, "Chat 0");
  1276.                 return;
  1277.             }
  1278.            
  1279. -           final int raceId = ticket.getEnchantLevel();
  1280. -           final int lane = ticket.getCustomType1();
  1281. -           final int bet = ticket.getCustomType2() * 100;
  1282. +           var raceId = ticket.getEnchantLevel();
  1283. +           var lane = ticket.getCustomType1();
  1284. +           var bet = ticket.getCustomType2() * 10;
  1285.            
  1286.             // Retrieve HistoryInfo for that race.
  1287. -           final HistoryInfo info = DerbyTrackManager.getInstance().getHistoryInfo(raceId);
  1288. +           var info = DerbyTrackManager.getInstance().getHistoryInfo(raceId);
  1289.             if (info == null)
  1290.             {
  1291.                 super.onBypassFeedback(player, "Chat 0");
  1292.                 return;
  1293.             }
  1294.            
  1295. -           final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
  1296. +           var html = new NpcHtmlMessage(getObjectId());
  1297.             html.setFile(getHtmlPath(getTemplate().getNpcId(), 8));
  1298.             html.replace("%raceId%", raceId);
  1299.             html.replace("%lane%", lane);
  1300.             html.replace("%bet%", bet);
  1301. -           html.replace("%firstLane%", info.getFirst() + 1);
  1302. -           html.replace("%odd%", (lane == info.getFirst() + 1) ? String.format(Locale.ENGLISH, "%.2f", info.getOddRate()) : "0.01");
  1303. +           html.replace("%firstLane%", info.getFirstPlace() + 1);
  1304. +           html.replace("%secondLane%", info.getSecondPlace() + 1);
  1305. +           html.replace("%odd%", lane == info.getFirstPlace() + 1 ? String.format(Locale.ENGLISH, "%.2f", info.getOddRate()) : lane == info.getSecondPlace() + 1 ? String.format(Locale.ENGLISH, "%.2f", info.getOddRate() * 0.6) : "0.01");
  1306.             html.replace("%objectId%", getObjectId());
  1307.             html.replace("%ticketObjectId%", val);
  1308. +          
  1309.             player.sendPacket(html);
  1310.             player.sendPacket(ActionFailed.STATIC_PACKET);
  1311.         }
  1312.         else if (command.startsWith("CalculateWin"))
  1313.         {
  1314. -           // Retrieve ticket objectId.
  1315. -           final int val = Integer.parseInt(command.substring(13));
  1316. -           if (val == 0)
  1317. +           // Extract ticket objectId.
  1318. +           var ticketId = Integer.parseInt(command.substring(13));
  1319. +           if (ticketId == 0)
  1320.             {
  1321.                 super.onBypassFeedback(player, "Chat 0");
  1322.                 return;
  1323.             }
  1324.            
  1325. -           // Delete ticket on player's inventory.
  1326. -           final ItemInstance ticket = player.getInventory().getItemByObjectId(val);
  1327. +           // Check if player has the ticket.
  1328. +           var ticket = player.getInventory().getItemByObjectId(ticketId);
  1329.             if (ticket == null)
  1330.             {
  1331.                 super.onBypassFeedback(player, "Chat 0");
  1332.                 return;
  1333.             }
  1334.            
  1335. -           final int raceId = ticket.getEnchantLevel();
  1336. -           final int lane = ticket.getCustomType1();
  1337. -           final int bet = ticket.getCustomType2() * 100;
  1338. +           // Extract ticket info.
  1339. +           var raceId = ticket.getEnchantLevel();
  1340. +           var lane = ticket.getCustomType1();
  1341. +           var bet = ticket.getCustomType2() * 10;
  1342.            
  1343. -           // Retrieve HistoryInfo for that race.
  1344. -           final HistoryInfo info = DerbyTrackManager.getInstance().getHistoryInfo(raceId);
  1345. -           if (info == null)
  1346. +           // Get race history.
  1347. +           var raceHistory = DerbyTrackManager.getInstance().getHistoryInfo(raceId);
  1348. +           if (raceHistory == null)
  1349.             {
  1350.                 super.onBypassFeedback(player, "Chat 0");
  1351.                 return;
  1352.             }
  1353.            
  1354. -           // Destroy the ticket.
  1355. -           if (player.destroyItem("MonsterTrack", ticket, this, true))
  1356. -               player.addAdena("MonsterTrack", (int) (bet * ((lane == info.getFirst() + 1) ? info.getOddRate() : 0.01)), this, true);
  1357. +           // Calculate and reward winnings.
  1358. +           var firstPlace = raceHistory.getFirstPlace() + 1;
  1359. +           var secondPlace = raceHistory.getSecondPlace() + 1;
  1360. +           var oddRate = (lane == firstPlace) ? raceHistory.getOddRate() : (lane == secondPlace) ? raceHistory.getOddRate() * 0.6 : 0.10;
  1361. +           var winnings = (int) (bet * oddRate);
  1362.            
  1363. +           if (player.destroyItem("MonsterTrack", ticket, this, true))
  1364. +               player.addItem("MonsterTrack", Config._itemID, winnings, this, true);
  1365. +          
  1366. +           // Notify player and exit bypass.
  1367.             super.onBypassFeedback(player, "Chat 0");
  1368. +           return;
  1369.         }
  1370. -       else if (command.equals("ViewHistory"))
  1371. +       else if (command.equalsIgnoreCase("ViewHistory"))
  1372.         {
  1373.             // Generate data.
  1374. -           final StringBuilder sb = new StringBuilder();
  1375. +           var sb = new StringBuilder();
  1376.            
  1377.             // Retrieve current race number.
  1378. -           final int raceNumber = DerbyTrackManager.getInstance().getRaceNumber();
  1379. +           var raceNumber = DerbyTrackManager.getInstance().getRaceNumber();
  1380.            
  1381.             // Retrieve the few latest entries.
  1382. -           for (HistoryInfo info : DerbyTrackManager.getInstance().getLastHistoryEntries())
  1383. -               StringUtil.append(sb, "<tr><td><font color=\"LEVEL\">", info.getRaceId(), "</font> th</td><td><font color=\"LEVEL\">", (raceNumber == info.getRaceId()) ? 0 : info.getFirst() + 1, "</font> Lane </td><td><font color=\"LEVEL\">", (raceNumber == info.getRaceId()) ? 0 : info.getSecond() + 1, "</font> Lane</td><td align=right><font color=00ffff>", String.format(Locale.ENGLISH, "%.2f", info.getOddRate()), "</font> Times</td></tr>");
  1384. +           for (var info : DerbyTrackManager.getInstance().getLastHistoryEntries())
  1385. +               StringUtil.append(sb, "<tr><td><font color=\"LEVEL\">", info.getRaceId(), "</font> th</td><td><font color=\"LEVEL\"><div style=\"text-align:center;\">", (raceNumber == info.getRaceId()) ? "Race in progress.." : info.getWinnerName(), "</div></font> </td><td align=right><font color=00ffff>", String.format(Locale.ENGLISH, "%.2f", info.getOddRate()), "</font></td></tr>");
  1386.            
  1387. -           final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
  1388. +           var html = new NpcHtmlMessage(getObjectId());
  1389.             html.setFile(getHtmlPath(getTemplate().getNpcId(), 9));
  1390.             html.replace("%infos%", sb.toString());
  1391.             html.replace("%objectId%", getObjectId());
  1392. @@ -326,19 +338,21 @@
  1393.     public void addKnownObject(WorldObject object)
  1394.     {
  1395.         if (object instanceof Player)
  1396. -           ((Player) object).sendPacket(DerbyTrackManager.getInstance().getRacePacket());
  1397. +       {
  1398. +           var player = (Player) object;
  1399. +           player.sendPacket(DerbyTrackManager.getInstance().getRacePacket());
  1400. +       }
  1401.     }
  1402.    
  1403.     @Override
  1404.     public void removeKnownObject(WorldObject object)
  1405.     {
  1406.         super.removeKnownObject(object);
  1407. -      
  1408.         if (object instanceof Player)
  1409.         {
  1410. -           final Player player = ((Player) object);
  1411. -          
  1412. -           for (Npc npc : DerbyTrackManager.getInstance().getRunners())
  1413. +           var player = (Player) object;
  1414. +           var derbyTrackManager = DerbyTrackManager.getInstance();
  1415. +           for (var npc : derbyTrackManager.getChosenRunners())
  1416.                 player.sendPacket(new DeleteObject(npc));
  1417.         }
  1418.     }
  1419.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement