Addition of Monster Race with reward system.
Adapted from aCis free version.
This commit is contained in:
15
L2J_Mobius_C6_Interlude/dist/db_installer/sql/game/mdt_bets.sql
vendored
Normal file
15
L2J_Mobius_C6_Interlude/dist/db_installer/sql/game/mdt_bets.sql
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
CREATE TABLE IF NOT EXISTS `mdt_bets` (
|
||||
`lane_id` INT(1) DEFAULT 0,
|
||||
`bet` INT DEFAULT 0,
|
||||
PRIMARY KEY (`lane_id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
|
||||
|
||||
INSERT INTO `mdt_bets` VALUES
|
||||
('1','0'),
|
||||
('2','0'),
|
||||
('3','0'),
|
||||
('4','0'),
|
||||
('5','0'),
|
||||
('6','0'),
|
||||
('7','0'),
|
||||
('8','0');
|
7
L2J_Mobius_C6_Interlude/dist/db_installer/sql/game/mdt_history.sql
vendored
Normal file
7
L2J_Mobius_C6_Interlude/dist/db_installer/sql/game/mdt_history.sql
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
CREATE TABLE IF NOT EXISTS `mdt_history` (
|
||||
`race_id` MEDIUMINT DEFAULT 0,
|
||||
`first` INT(1) DEFAULT 0,
|
||||
`second` INT(1) DEFAULT 0,
|
||||
`odd_rate` DOUBLE(10,2) DEFAULT 0,
|
||||
PRIMARY KEY (`race_id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
|
@@ -412,9 +412,6 @@
|
||||
<admin command="admin_mobgroup_invul" accessLevel="90" />
|
||||
<admin command="admin_mobinst" accessLevel="90" />
|
||||
|
||||
<!-- Section: MonsterRace -->
|
||||
<admin command="admin_mons" accessLevel="90" />
|
||||
|
||||
<!-- Section: Noble -->
|
||||
<admin command="admin_setnoble" accessLevel="90" />
|
||||
|
||||
|
@@ -4,7 +4,7 @@
|
||||
<br>
|
||||
In a monster race eight monsters race at the same time. If you guess which monster is expected to finish first and buy that monster's race ticket, based upon the odds to win you will receive an appropriate amount of adena.<br>
|
||||
<font color="LEVEL">Racing Schedule</font><br>
|
||||
Monster races every 20 minutes in real time.
|
||||
Monster races every 20 minutes in real time.<br>
|
||||
<font color="LEVEL">Method of Race Participation</font><br>
|
||||
You can purchase a monster race ticket through a race manager NPC. Only between 18 minutes before the start of a race until 3 minutes before the race begins you can buy a ticket for the applicable race. When you purchase a ticket through a conversation with a race manager, you can find out the names of participating monsters in the race and their current statistics. Five minutes before a race starts, the race manager will stop ticket sales and announce monsters' individual odds rate for the current race.<br>
|
||||
<font color="LEVEL">Types of Race</font><br>
|
||||
|
@@ -15,49 +15,49 @@
|
||||
<tr>
|
||||
<td fixwidth=40>No.1</td>
|
||||
<td fixwidth=130 align=left><font color="LEVEL">Mob1</font></td>
|
||||
<td fixwidth=100 align=right><font color="00ffff">&$804;</font> </td>
|
||||
<td fixwidth=100 align=right><font color="00ffff">Odd1</font> </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td fixwidth=40>No.2</td>
|
||||
<td fixwidth=130 align=left><font color="LEVEL">Mob2</font></td>
|
||||
<td fixwidth=100 align=right><font color="00ffff">&$804;</font> </td>
|
||||
<td fixwidth=100 align=right><font color="00ffff">Odd2</font> </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td fixwidth=40>No.3</td>
|
||||
<td fixwidth=130 align=left><font color="LEVEL">Mob3</font></td>
|
||||
<td fixwidth=100 align=right><font color="00ffff">&$804;</font> </td>
|
||||
<td fixwidth=100 align=right><font color="00ffff">Odd3</font> </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td fixwidth=40>No.4</td>
|
||||
<td fixwidth=130 align=left><font color="LEVEL">Mob4</font></td>
|
||||
<td fixwidth=100 align=right><font color="00ffff">&$804;</font> </td>
|
||||
<td fixwidth=100 align=right><font color="00ffff">Odd4</font> </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td fixwidth=40>No.5</td>
|
||||
<td fixwidth=130 align=left><font color="LEVEL">Mob5</font></td>
|
||||
<td fixwidth=100 align=right><font color="00ffff">&$804;</font> </td>
|
||||
<td fixwidth=100 align=right><font color="00ffff">Odd5</font> </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td fixwidth=40>No.6</td>
|
||||
<td fixwidth=130 align=left><font color="LEVEL">Mob6</font></td>
|
||||
<td fixwidth=100 align=right><font color="00ffff">&$804;</font> </td>
|
||||
<td fixwidth=100 align=right><font color="00ffff">Odd6</font> </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td fixwidth=40>No.7</td>
|
||||
<td fixwidth=130 align=left><font color="LEVEL">Mob7</font></td>
|
||||
<td fixwidth=100 align=right><font color="00ffff">&$804;</font> </td>
|
||||
<td fixwidth=100 align=right><font color="00ffff">Odd7</font> </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td fixwidth=40>No.8</td>
|
||||
<td fixwidth=130 align=left><font color="LEVEL">Mob8</font></td>
|
||||
<td fixwidth=100 align=right><font color="00ffff">&$804;</font> </td>
|
||||
<td fixwidth=100 align=right><font color="00ffff">Odd8</font> </td>
|
||||
</tr>
|
||||
</table>
|
||||
<img src="L2UI.SquareBlank" width=270 height=10>
|
||||
|
@@ -3,22 +3,12 @@
|
||||
<img src="L2UI.SquareWhite" width=270 height=1>
|
||||
<img src="L2UI.SquareBlank" width=1 height=3>
|
||||
<table width=270 border=0 bgcolor=111111>
|
||||
<tr><td fixwidth=60>Winnings for a Race.</td><td fixwidth=60 align=right>Lane</td><td fixwidth=160 align=right>Bet Amount</td></tr>
|
||||
<tr><td fixwidth=60 fixheight=1></td><td fixwidth=60></td><td fixwidth=160></td></tr>
|
||||
<tr><td fixwidth=70>Winnings for a Race.</td><td fixwidth=70 align=right>Lane</td><td fixwidth=130 align=right>Bet Amount</td></tr>
|
||||
<tr><td fixwidth=70 fixheight=1></td><td fixwidth=70></td><td fixwidth=130></td></tr>
|
||||
</table>
|
||||
<table width=270 border=0>
|
||||
<tr>
|
||||
<td><a action="bypass -h npc_%objectId%_Chat 8">1 Race Number</a></td>
|
||||
<td align=right><font color="LEVEL">1</font> Number</td>
|
||||
<td align=right><font color="LEVEL">100</font> Adena</td>
|
||||
</tr>
|
||||
%tickets%
|
||||
</table>
|
||||
<img src="L2UI.SquareWhite" width=270 height=1>
|
||||
|
||||
<table width=270 border=0>
|
||||
<tr><td width=90><a action="bypass _mrsl01_1">Previous List</a></td><td width=90 align=center>1 Page </td><td width=90 align=right><a action="bypass _mrsl01_2"> Next List</a></td></tr>
|
||||
</table>
|
||||
|
||||
<img src="L2UI.SquareWhite" width=270 height=1>
|
||||
<img src="L2UI.SquareBlank" width=270 height=5>
|
||||
<table width=270 border=0 cellpadding=0 cellspacing=0>
|
||||
|
@@ -4,11 +4,11 @@
|
||||
<img src="L2UI.SquareBlank" width=1 height=3>
|
||||
<table width=270 border=0>
|
||||
<tr>
|
||||
<td width=230>Race #19090<br>
|
||||
Lane 1<br>
|
||||
Bet: 100 adena<br>
|
||||
1st place: Lane [4]<br>
|
||||
Odds:[0.01]
|
||||
<td width=230>Race #%raceId%<br>
|
||||
Lane: %lane%<br>
|
||||
Bet: %bet% Adena<br>
|
||||
1st place: Lane [%firstLane%]<br>
|
||||
Odds: [%odd%]
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -18,8 +18,8 @@ Odds:[0.01]
|
||||
|
||||
<table width=270 border=0 cellpadding=0 cellspacing=0>
|
||||
<tr>
|
||||
<td width=90 height=20><button value="Previous" action="bypass -h npc_%objectId%_Chat 7" back="L2UI.DefaultButton_click" fore="L2UI.DefaultButton" width=67 height=19></td>
|
||||
<td width=90 height=20><button value="Previous" action="bypass -h npc_%objectId%_ShowTickets" back="L2UI.DefaultButton_click" fore="L2UI.DefaultButton" width=67 height=19></td>
|
||||
<td width=90></td>
|
||||
<td width=90 align=right><button value="Calculate" action="bypass _mrsl03_30635184" back="L2UI.DefaultButton_click" fore="L2UI.DefaultButton" width=67 height=19></td>
|
||||
<td width=90 align=right><button value="Calculate" action="bypass -h npc_%objectId%_CalculateWin %ticketObjectId%" back="L2UI.DefaultButton_click" fore="L2UI.DefaultButton" width=67 height=19></td>
|
||||
</tr></table>
|
||||
</body></html>
|
@@ -7,41 +7,7 @@
|
||||
</table>
|
||||
<table width=270 border=0>
|
||||
<tr><td fixwidth=60 fixheight=1></td><td fixwidth=70></td><td fixwidth=70></td><td fixwidth=70></td></tr>
|
||||
<tr>
|
||||
<td><font color="LEVEL">7</font> th</td>
|
||||
<td><font color="LEVEL">8</font> Lane </td><td><font color="LEVEL">1</font> Lane</td>
|
||||
<td align=right><font color="00ffff">0.00</font> Times</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="LEVEL">6</font> th</td>
|
||||
<td><font color="LEVEL">4</font> Lane </td><td><font color="LEVEL">8</font> Lane</td>
|
||||
<td align=right><font color="00ffff">0.00</font> Times</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="LEVEL">5</font> th</td>
|
||||
<td><font color="LEVEL">7</font> Lane </td><td><font color="LEVEL">2</font> Lane</td>
|
||||
<td align=right><font color="00ffff">0.00</font> Times</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="LEVEL">4</font> th</td>
|
||||
<td><font color="LEVEL">6</font> Lane </td><td><font color="LEVEL">8</font> Lane</td>
|
||||
<td align=right><font color="00ffff">0.00</font> Times</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="LEVEL">3</font> th</td>
|
||||
<td><font color="LEVEL">4</font> Lane </td><td><font color="LEVEL">1</font> Lane</td>
|
||||
<td align=right><font color="00ffff">0.00</font> Times</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="LEVEL">2</font> th</td>
|
||||
<td><font color="LEVEL">1</font> Lane </td><td><font color="LEVEL">8</font> Lane</td>
|
||||
<td align=right><font color="00ffff">0.00</font> Times</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="LEVEL">1</font> th</td>
|
||||
<td><font color="LEVEL">7</font> Lane </td><td><font color="LEVEL">6</font> Lane</td>
|
||||
<td align=right><font color="00ffff">0.00</font> Times</td>
|
||||
</tr>
|
||||
%infos%
|
||||
</table>
|
||||
<img src="L2UI.SquareBlank" width=270 height=10>
|
||||
<img src="L2UI.SquareWhite" width=270 height=1>
|
||||
|
@@ -7,8 +7,8 @@
|
||||
<tr><td width=270><a action="bypass -h npc_%objectId%_ShowOdds">View Odds</a></td></tr>
|
||||
<tr><td width=270><a action="bypass -h npc_%objectId%_ShowInfo">View Monster Information</a></td></tr>
|
||||
<tr><td width=270><a action="bypass -h npc_%objectId%_BuyTicket 0">Purchase Ticket</a></td></tr>
|
||||
<tr><td width=270><a action="bypass -h npc_%objectId%_Chat 7">Calculate Winnings</a></td></tr>
|
||||
<tr><td width=270><a action="bypass -h npc_%objectId%_Chat 9">View Past Results</a></td></tr>
|
||||
<tr><td width=270><a action="bypass -h npc_%objectId%_ShowTickets">Calculate Winnings</a></td></tr>
|
||||
<tr><td width=270><a action="bypass -h npc_%objectId%_ViewHistory">View Past Results</a></td></tr>
|
||||
<tr><td width=270><a action="bypass -h npc_%objectId%_Quest RaceTrack" msg="1298;Monster Race Track">Exit the monster race track.</a></td></tr>
|
||||
</table>
|
||||
|
||||
|
@@ -111,8 +111,8 @@ import org.l2jmobius.gameserver.instancemanager.SiegeManager;
|
||||
import org.l2jmobius.gameserver.model.World;
|
||||
import org.l2jmobius.gameserver.model.entity.Announcements;
|
||||
import org.l2jmobius.gameserver.model.entity.Hero;
|
||||
import org.l2jmobius.gameserver.model.entity.MonsterRace;
|
||||
import org.l2jmobius.gameserver.model.entity.event.Lottery;
|
||||
import org.l2jmobius.gameserver.model.entity.event.MonsterRace;
|
||||
import org.l2jmobius.gameserver.model.entity.event.PcPoint;
|
||||
import org.l2jmobius.gameserver.model.entity.event.manager.EventManager;
|
||||
import org.l2jmobius.gameserver.model.entity.olympiad.Olympiad;
|
||||
|
@@ -63,7 +63,6 @@ import org.l2jmobius.gameserver.handler.admincommandhandlers.AdminMassControl;
|
||||
import org.l2jmobius.gameserver.handler.admincommandhandlers.AdminMassRecall;
|
||||
import org.l2jmobius.gameserver.handler.admincommandhandlers.AdminMenu;
|
||||
import org.l2jmobius.gameserver.handler.admincommandhandlers.AdminMobGroup;
|
||||
import org.l2jmobius.gameserver.handler.admincommandhandlers.AdminMonsterRace;
|
||||
import org.l2jmobius.gameserver.handler.admincommandhandlers.AdminNoble;
|
||||
import org.l2jmobius.gameserver.handler.admincommandhandlers.AdminOnline;
|
||||
import org.l2jmobius.gameserver.handler.admincommandhandlers.AdminPForge;
|
||||
@@ -146,7 +145,6 @@ public class AdminCommandHandler
|
||||
registerAdminCommandHandler(new AdminMassRecall());
|
||||
registerAdminCommandHandler(new AdminMenu());
|
||||
registerAdminCommandHandler(new AdminMobGroup());
|
||||
registerAdminCommandHandler(new AdminMonsterRace());
|
||||
registerAdminCommandHandler(new AdminNoble());
|
||||
registerAdminCommandHandler(new AdminOnline());
|
||||
registerAdminCommandHandler(new AdminPetition());
|
||||
|
@@ -1,163 +0,0 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.l2jmobius.gameserver.handler.admincommandhandlers;
|
||||
|
||||
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||
import org.l2jmobius.gameserver.handler.IAdminCommandHandler;
|
||||
import org.l2jmobius.gameserver.model.Location;
|
||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||
import org.l2jmobius.gameserver.model.entity.MonsterRace;
|
||||
import org.l2jmobius.gameserver.network.SystemMessageId;
|
||||
import org.l2jmobius.gameserver.network.serverpackets.DeleteObject;
|
||||
import org.l2jmobius.gameserver.network.serverpackets.MonRaceInfo;
|
||||
import org.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
||||
import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
|
||||
|
||||
/**
|
||||
* This class handles following admin commands: - invul = turns invulnerability on/off
|
||||
* @version $Revision: 1.1.6.4 $ $Date: 2007/07/31 10:06:00 $
|
||||
*/
|
||||
public class AdminMonsterRace implements IAdminCommandHandler
|
||||
{
|
||||
private static final String[] ADMIN_COMMANDS =
|
||||
{
|
||||
"admin_mons"
|
||||
};
|
||||
|
||||
protected static int state = -1;
|
||||
|
||||
@Override
|
||||
public boolean useAdminCommand(String command, PlayerInstance activeChar)
|
||||
{
|
||||
if (command.equalsIgnoreCase("admin_mons"))
|
||||
{
|
||||
handleSendPacket(activeChar);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAdminCommandList()
|
||||
{
|
||||
return ADMIN_COMMANDS;
|
||||
}
|
||||
|
||||
private void handleSendPacket(PlayerInstance activeChar)
|
||||
{
|
||||
/*
|
||||
* -1 0 to initialize the race 0 15322 to start race 13765 -1 in middle of race -1 0 to end the race 8003 to 8027
|
||||
*/
|
||||
final int[][] codes =
|
||||
{
|
||||
{
|
||||
-1,
|
||||
0
|
||||
},
|
||||
{
|
||||
0,
|
||||
15322
|
||||
},
|
||||
{
|
||||
13765,
|
||||
-1
|
||||
},
|
||||
{
|
||||
-1,
|
||||
0
|
||||
}
|
||||
};
|
||||
final MonsterRace race = MonsterRace.getInstance();
|
||||
|
||||
if (state == -1)
|
||||
{
|
||||
state++;
|
||||
race.newRace();
|
||||
race.newSpeeds();
|
||||
final MonRaceInfo spk = new MonRaceInfo(codes[state][0], codes[state][1], race.getMonsters(), race.getSpeeds());
|
||||
activeChar.sendPacket(spk);
|
||||
activeChar.broadcastPacket(spk);
|
||||
}
|
||||
else if (state == 0)
|
||||
{
|
||||
state++;
|
||||
|
||||
final SystemMessage sm = new SystemMessage(SystemMessageId.MONSRACE_RACE_START);
|
||||
sm.addNumber(0);
|
||||
activeChar.sendPacket(sm);
|
||||
|
||||
final PlaySound sRace = new PlaySound(1, "S_Race");
|
||||
activeChar.sendPacket(sRace);
|
||||
activeChar.broadcastPacket(sRace);
|
||||
|
||||
final PlaySound sRace2 = new PlaySound(0, "ItemSound2.race_start", true, 121209259, new Location(12125, 182487, -3559), 0);
|
||||
activeChar.sendPacket(sRace2);
|
||||
activeChar.broadcastPacket(sRace2);
|
||||
|
||||
final MonRaceInfo spk = new MonRaceInfo(codes[state][0], codes[state][1], race.getMonsters(), race.getSpeeds());
|
||||
activeChar.sendPacket(spk);
|
||||
activeChar.broadcastPacket(spk);
|
||||
|
||||
ThreadPool.schedule(new RunRace(codes, activeChar), 5000);
|
||||
}
|
||||
}
|
||||
|
||||
class RunRace implements Runnable
|
||||
{
|
||||
private final int[][] codes;
|
||||
private final PlayerInstance activeChar;
|
||||
|
||||
public RunRace(int[][] pCodes, PlayerInstance pActiveChar)
|
||||
{
|
||||
codes = pCodes;
|
||||
activeChar = pActiveChar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
final MonRaceInfo spk = new MonRaceInfo(codes[2][0], codes[2][1], MonsterRace.getInstance().getMonsters(), MonsterRace.getInstance().getSpeeds());
|
||||
activeChar.sendPacket(spk);
|
||||
activeChar.broadcastPacket(spk);
|
||||
ThreadPool.schedule(new RunEnd(activeChar), 30000);
|
||||
}
|
||||
}
|
||||
|
||||
class RunEnd implements Runnable
|
||||
{
|
||||
private final PlayerInstance activeChar;
|
||||
|
||||
public RunEnd(PlayerInstance pActiveChar)
|
||||
{
|
||||
activeChar = pActiveChar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
DeleteObject obj = null;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
obj = new DeleteObject(MonsterRace.getInstance().getMonsters()[i]);
|
||||
activeChar.sendPacket(obj);
|
||||
activeChar.broadcastPacket(obj);
|
||||
}
|
||||
state = -1;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,530 +1,374 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.l2jmobius.gameserver.model.actor.instance;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||
import org.l2jmobius.gameserver.idfactory.IdFactory;
|
||||
import org.l2jmobius.gameserver.model.Location;
|
||||
import org.l2jmobius.gameserver.model.actor.knownlist.RaceManagerKnownList;
|
||||
import org.l2jmobius.gameserver.model.actor.templates.NpcTemplate;
|
||||
import org.l2jmobius.gameserver.model.entity.MonsterRace;
|
||||
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
|
||||
import org.l2jmobius.gameserver.network.SystemMessageId;
|
||||
import org.l2jmobius.gameserver.network.serverpackets.ActionFailed;
|
||||
import org.l2jmobius.gameserver.network.serverpackets.DeleteObject;
|
||||
import org.l2jmobius.gameserver.network.serverpackets.GameServerPacket;
|
||||
import org.l2jmobius.gameserver.network.serverpackets.InventoryUpdate;
|
||||
import org.l2jmobius.gameserver.network.serverpackets.MonRaceInfo;
|
||||
import org.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage;
|
||||
import org.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
||||
import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
|
||||
import org.l2jmobius.gameserver.util.Broadcast;
|
||||
|
||||
public class RaceManagerInstance extends NpcInstance
|
||||
{
|
||||
public static final int LANES = 8;
|
||||
public static final int WINDOW_START = 0;
|
||||
|
||||
private static List<RaceManagerInstance> _managers;
|
||||
protected static int _raceNumber = 4;
|
||||
|
||||
// Time Constants
|
||||
private static final long SECOND = 1000;
|
||||
private static final long MINUTE = 60 * SECOND;
|
||||
|
||||
private static int _minutes = 5;
|
||||
|
||||
// States
|
||||
private static final int ACCEPTING_BETS = 0;
|
||||
private static final int WAITING = 1;
|
||||
private static final int STARTING_RACE = 2;
|
||||
private static final int RACE_END = 3;
|
||||
private static int _state = RACE_END;
|
||||
|
||||
protected static final int[][] _codes =
|
||||
{
|
||||
{
|
||||
-1,
|
||||
0
|
||||
},
|
||||
{
|
||||
0,
|
||||
15322
|
||||
},
|
||||
{
|
||||
13765,
|
||||
-1
|
||||
}
|
||||
};
|
||||
private static boolean _notInitialized = true;
|
||||
protected static MonRaceInfo _packet;
|
||||
protected static final int[] _cost =
|
||||
{
|
||||
100,
|
||||
500,
|
||||
1000,
|
||||
5000,
|
||||
10000,
|
||||
20000,
|
||||
50000,
|
||||
100000
|
||||
};
|
||||
|
||||
public RaceManagerInstance(int objectId, NpcTemplate template)
|
||||
{
|
||||
super(objectId, template);
|
||||
getKnownList(); // init knownlist
|
||||
if (_notInitialized)
|
||||
{
|
||||
_notInitialized = false;
|
||||
_managers = new ArrayList<>();
|
||||
|
||||
ThreadPool.scheduleAtFixedRate(new Announcement(SystemMessageId.MONSRACE_TICKETS_AVAILABLE_FOR_S1_RACE), 0, 10 * MINUTE);
|
||||
ThreadPool.scheduleAtFixedRate(new Announcement(SystemMessageId.MONSRACE_TICKETS_NOW_AVAILABLE_FOR_S1_RACE), 30 * SECOND, 10 * MINUTE);
|
||||
ThreadPool.scheduleAtFixedRate(new Announcement(SystemMessageId.MONSRACE_TICKETS_AVAILABLE_FOR_S1_RACE), MINUTE, 10 * MINUTE);
|
||||
ThreadPool.scheduleAtFixedRate(new Announcement(SystemMessageId.MONSRACE_TICKETS_NOW_AVAILABLE_FOR_S1_RACE), MINUTE + (30 * SECOND), 10 * MINUTE);
|
||||
ThreadPool.scheduleAtFixedRate(new Announcement(SystemMessageId.MONSRACE_TICKETS_STOP_IN_S1_MINUTES), 2 * MINUTE, 10 * MINUTE);
|
||||
ThreadPool.scheduleAtFixedRate(new Announcement(SystemMessageId.MONSRACE_TICKETS_STOP_IN_S1_MINUTES), 3 * MINUTE, 10 * MINUTE);
|
||||
ThreadPool.scheduleAtFixedRate(new Announcement(SystemMessageId.MONSRACE_TICKETS_STOP_IN_S1_MINUTES), 4 * MINUTE, 10 * MINUTE);
|
||||
ThreadPool.scheduleAtFixedRate(new Announcement(SystemMessageId.MONSRACE_TICKETS_STOP_IN_S1_MINUTES), 5 * MINUTE, 10 * MINUTE);
|
||||
ThreadPool.scheduleAtFixedRate(new Announcement(SystemMessageId.MONSRACE_TICKETS_STOP_IN_S1_MINUTES), 6 * MINUTE, 10 * MINUTE);
|
||||
ThreadPool.scheduleAtFixedRate(new Announcement(SystemMessageId.MONSRACE_TICKET_SALES_CLOSED), 7 * MINUTE, 10 * MINUTE);
|
||||
ThreadPool.scheduleAtFixedRate(new Announcement(SystemMessageId.MONSRACE_BEGINS_IN_S1_MINUTES), 7 * MINUTE, 10 * MINUTE);
|
||||
ThreadPool.scheduleAtFixedRate(new Announcement(SystemMessageId.MONSRACE_BEGINS_IN_S1_MINUTES), 8 * MINUTE, 10 * MINUTE);
|
||||
ThreadPool.scheduleAtFixedRate(new Announcement(SystemMessageId.MONSRACE_BEGINS_IN_30_SECONDS), (8 * MINUTE) + (30 * SECOND), 10 * MINUTE);
|
||||
ThreadPool.scheduleAtFixedRate(new Announcement(SystemMessageId.MONSRACE_COUNTDOWN_IN_FIVE_SECONDS), (8 * MINUTE) + (50 * SECOND), 10 * MINUTE);
|
||||
ThreadPool.scheduleAtFixedRate(new Announcement(SystemMessageId.MONSRACE_BEGINS_IN_S1_SECONDS), (8 * MINUTE) + (55 * SECOND), 10 * MINUTE);
|
||||
ThreadPool.scheduleAtFixedRate(new Announcement(SystemMessageId.MONSRACE_BEGINS_IN_S1_SECONDS), (8 * MINUTE) + (56 * SECOND), 10 * MINUTE);
|
||||
ThreadPool.scheduleAtFixedRate(new Announcement(SystemMessageId.MONSRACE_BEGINS_IN_S1_SECONDS), (8 * MINUTE) + (57 * SECOND), 10 * MINUTE);
|
||||
ThreadPool.scheduleAtFixedRate(new Announcement(SystemMessageId.MONSRACE_BEGINS_IN_S1_SECONDS), (8 * MINUTE) + (58 * SECOND), 10 * MINUTE);
|
||||
ThreadPool.scheduleAtFixedRate(new Announcement(SystemMessageId.MONSRACE_BEGINS_IN_S1_SECONDS), (8 * MINUTE) + (59 * SECOND), 10 * MINUTE);
|
||||
ThreadPool.scheduleAtFixedRate(new Announcement(SystemMessageId.MONSRACE_RACE_START), 9 * MINUTE, 10 * MINUTE);
|
||||
}
|
||||
_managers.add(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RaceManagerKnownList getKnownList()
|
||||
{
|
||||
if (!(super.getKnownList() instanceof RaceManagerKnownList))
|
||||
{
|
||||
setKnownList(new RaceManagerKnownList(this));
|
||||
}
|
||||
return (RaceManagerKnownList) super.getKnownList();
|
||||
}
|
||||
|
||||
class Announcement implements Runnable
|
||||
{
|
||||
private final SystemMessageId _type;
|
||||
|
||||
public Announcement(SystemMessageId pType)
|
||||
{
|
||||
_type = pType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
makeAnnouncement(_type);
|
||||
}
|
||||
}
|
||||
|
||||
public void makeAnnouncement(SystemMessageId type)
|
||||
{
|
||||
final SystemMessage sm = new SystemMessage(type);
|
||||
switch (type.getId())
|
||||
{
|
||||
case 816: // SystemMessageId.MONSRACE_TICKETS_AVAILABLE_FOR_S1_RACE
|
||||
case 817: // SystemMessageId.MONSRACE_TICKETS_NOW_AVAILABLE_FOR_S1_RACE
|
||||
{
|
||||
if (_state != ACCEPTING_BETS)
|
||||
{
|
||||
_state = ACCEPTING_BETS;
|
||||
startRace();
|
||||
}
|
||||
sm.addNumber(_raceNumber);
|
||||
break;
|
||||
}
|
||||
case 818: // SystemMessageId.MONSRACE_TICKETS_STOP_IN_S1_MINUTES
|
||||
case 820: // SystemMessageId.MONSRACE_BEGINS_IN_S1_MINUTES
|
||||
case 823: // SystemMessageId.MONSRACE_BEGINS_IN_S1_SECONDS
|
||||
{
|
||||
sm.addNumber(_minutes);
|
||||
sm.addNumber(_raceNumber);
|
||||
_minutes--;
|
||||
break;
|
||||
}
|
||||
case 819: // SystemMessageId.MONSRACE_TICKET_SALES_CLOSED
|
||||
{
|
||||
sm.addNumber(_raceNumber);
|
||||
_state = WAITING;
|
||||
_minutes = 2;
|
||||
break;
|
||||
}
|
||||
case 822: // SystemMessageId.MONSRACE_COUNTDOWN_IN_FIVE_SECONDS
|
||||
case 825: // SystemMessageId.MONSRACE_RACE_END
|
||||
{
|
||||
sm.addNumber(_raceNumber);
|
||||
_minutes = 5;
|
||||
break;
|
||||
}
|
||||
case 826: // SystemMessageId.MONSRACE_FIRST_PLACE_S1_SECOND_S2
|
||||
{
|
||||
_state = RACE_END;
|
||||
sm.addNumber(MonsterRace.getInstance().getFirstPlace());
|
||||
sm.addNumber(MonsterRace.getInstance().getSecondPlace());
|
||||
break;
|
||||
}
|
||||
}
|
||||
broadcast(sm);
|
||||
|
||||
if (type == SystemMessageId.MONSRACE_RACE_START)
|
||||
{
|
||||
_state = STARTING_RACE;
|
||||
startRace();
|
||||
_minutes = 5;
|
||||
}
|
||||
}
|
||||
|
||||
protected void broadcast(GameServerPacket pkt)
|
||||
{
|
||||
for (RaceManagerInstance manager : _managers)
|
||||
{
|
||||
if (!manager.isDead())
|
||||
{
|
||||
Broadcast.toKnownPlayers(manager, pkt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void sendMonsterInfo()
|
||||
{
|
||||
broadcast(_packet);
|
||||
}
|
||||
|
||||
private void startRace()
|
||||
{
|
||||
final MonsterRace race = MonsterRace.getInstance();
|
||||
if (_state == STARTING_RACE)
|
||||
{
|
||||
broadcast(new PlaySound(1, "S_Race"));
|
||||
broadcast(new PlaySound(0, "ItemSound2.race_start", true, 121209259, new Location(12125, 182487, -3559), 0));
|
||||
_packet = new MonRaceInfo(_codes[1][0], _codes[1][1], race.getMonsters(), race.getSpeeds());
|
||||
sendMonsterInfo();
|
||||
|
||||
ThreadPool.schedule(new RunRace(), 5000);
|
||||
}
|
||||
else
|
||||
{
|
||||
race.newRace();
|
||||
race.newSpeeds();
|
||||
_packet = new MonRaceInfo(_codes[0][0], _codes[0][1], race.getMonsters(), race.getSpeeds());
|
||||
sendMonsterInfo();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBypassFeedback(PlayerInstance player, String command)
|
||||
{
|
||||
if (command.startsWith("BuyTicket") && (_state != ACCEPTING_BETS))
|
||||
{
|
||||
player.sendPacket(SystemMessageId.MONSRACE_TICKETS_NOT_AVAILABLE);
|
||||
command = "Chat 0";
|
||||
}
|
||||
if (command.startsWith("ShowOdds") && (_state == ACCEPTING_BETS))
|
||||
{
|
||||
player.sendPacket(SystemMessageId.MONSRACE_NO_PAYOUT_INFO);
|
||||
command = "Chat 0";
|
||||
}
|
||||
|
||||
if (command.startsWith("BuyTicket"))
|
||||
{
|
||||
int val = Integer.parseInt(command.substring(10));
|
||||
if (val == 0)
|
||||
{
|
||||
player.setRace(0, 0);
|
||||
player.setRace(1, 0);
|
||||
}
|
||||
if (((val == 10) && (player.getRace(0) == 0)) || ((val == 20) && (player.getRace(0) == 0) && (player.getRace(1) == 0)))
|
||||
{
|
||||
val = 0;
|
||||
}
|
||||
showBuyTicket(player, val);
|
||||
}
|
||||
else if (command.equals("ShowOdds"))
|
||||
{
|
||||
showOdds(player);
|
||||
}
|
||||
else if (command.equals("ShowInfo"))
|
||||
{
|
||||
showMonsterInfo(player);
|
||||
}
|
||||
else if (command.equals("calculateWin"))
|
||||
{
|
||||
// displayCalculateWinnings(player);
|
||||
}
|
||||
else if (command.equals("viewHistory"))
|
||||
{
|
||||
// displayHistory(player);
|
||||
}
|
||||
else
|
||||
{
|
||||
super.onBypassFeedback(player, command);
|
||||
}
|
||||
}
|
||||
|
||||
public void showOdds(PlayerInstance player)
|
||||
{
|
||||
if (_state == ACCEPTING_BETS)
|
||||
{
|
||||
return;
|
||||
}
|
||||
final int npcId = getTemplate().getNpcId();
|
||||
String filename;
|
||||
String search;
|
||||
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
|
||||
filename = getHtmlPath(npcId, 5);
|
||||
html.setFile(filename);
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
final int n = i + 1;
|
||||
search = "Mob" + n;
|
||||
html.replace(search, MonsterRace.getInstance().getMonsters()[i].getTemplate().getName());
|
||||
}
|
||||
html.replace("1race", String.valueOf(_raceNumber));
|
||||
html.replace("%objectId%", String.valueOf(getObjectId()));
|
||||
player.sendPacket(html);
|
||||
player.sendPacket(ActionFailed.STATIC_PACKET);
|
||||
}
|
||||
|
||||
public void showMonsterInfo(PlayerInstance player)
|
||||
{
|
||||
final int npcId = getTemplate().getNpcId();
|
||||
String filename;
|
||||
String search;
|
||||
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
|
||||
filename = getHtmlPath(npcId, 6);
|
||||
html.setFile(filename);
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
final int n = i + 1;
|
||||
search = "Mob" + n;
|
||||
html.replace(search, MonsterRace.getInstance().getMonsters()[i].getTemplate().getName());
|
||||
}
|
||||
html.replace("%objectId%", String.valueOf(getObjectId()));
|
||||
player.sendPacket(html);
|
||||
player.sendPacket(ActionFailed.STATIC_PACKET);
|
||||
}
|
||||
|
||||
public void showBuyTicket(PlayerInstance player, int value)
|
||||
{
|
||||
if (_state != ACCEPTING_BETS)
|
||||
{
|
||||
return;
|
||||
}
|
||||
final int npcId = getTemplate().getNpcId();
|
||||
SystemMessage sm;
|
||||
String filename;
|
||||
String search;
|
||||
String replace;
|
||||
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
|
||||
if (value < 10)
|
||||
{
|
||||
filename = getHtmlPath(npcId, 2);
|
||||
html.setFile(filename);
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
final int n = i + 1;
|
||||
search = "Mob" + n;
|
||||
html.replace(search, MonsterRace.getInstance().getMonsters()[i].getTemplate().getName());
|
||||
}
|
||||
search = "No1";
|
||||
if (value == 0)
|
||||
{
|
||||
html.replace(search, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
html.replace(search, "" + value);
|
||||
player.setRace(0, value);
|
||||
}
|
||||
}
|
||||
else if (value < 20)
|
||||
{
|
||||
if (player.getRace(0) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
filename = getHtmlPath(npcId, 3);
|
||||
html.setFile(filename);
|
||||
html.replace("0place", "" + player.getRace(0));
|
||||
search = "Mob1";
|
||||
replace = MonsterRace.getInstance().getMonsters()[player.getRace(0) - 1].getTemplate().getName();
|
||||
html.replace(search, replace);
|
||||
search = "0adena";
|
||||
if (value == 10)
|
||||
{
|
||||
html.replace(search, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
html.replace(search, "" + _cost[value - 11]);
|
||||
player.setRace(1, value - 10);
|
||||
}
|
||||
}
|
||||
else if (value == 20)
|
||||
{
|
||||
if ((player.getRace(0) == 0) || (player.getRace(1) == 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
filename = getHtmlPath(npcId, 4);
|
||||
html.setFile(filename);
|
||||
html.replace("0place", "" + player.getRace(0));
|
||||
search = "Mob1";
|
||||
replace = MonsterRace.getInstance().getMonsters()[player.getRace(0) - 1].getTemplate().getName();
|
||||
html.replace(search, replace);
|
||||
search = "0adena";
|
||||
final int price = _cost[player.getRace(1) - 1];
|
||||
html.replace(search, "" + price);
|
||||
search = "0tax";
|
||||
final int tax = 0;
|
||||
html.replace(search, "" + tax);
|
||||
search = "0total";
|
||||
final int total = price + tax;
|
||||
html.replace(search, "" + total);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((player.getRace(0) == 0) || (player.getRace(1) == 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
final int ticket = player.getRace(0);
|
||||
final int priceId = player.getRace(1);
|
||||
if (!player.reduceAdena("Race", _cost[priceId - 1], this, true))
|
||||
{
|
||||
return;
|
||||
}
|
||||
player.setRace(0, 0);
|
||||
player.setRace(1, 0);
|
||||
sm = new SystemMessage(SystemMessageId.ACQUIRED);
|
||||
sm.addNumber(_raceNumber);
|
||||
sm.addItemName(4443);
|
||||
player.sendPacket(sm);
|
||||
final ItemInstance item = new ItemInstance(IdFactory.getInstance().getNextId(), 4443);
|
||||
item.setCount(1);
|
||||
item.setEnchantLevel(_raceNumber);
|
||||
item.setCustomType1(ticket);
|
||||
item.setCustomType2(_cost[priceId - 1] / 100);
|
||||
player.getInventory().addItem("Race", item, player, this);
|
||||
final InventoryUpdate iu = new InventoryUpdate();
|
||||
iu.addItem(item);
|
||||
final ItemInstance adenaupdate = player.getInventory().getItemByItemId(57);
|
||||
iu.addModifiedItem(adenaupdate);
|
||||
player.sendPacket(iu);
|
||||
return;
|
||||
}
|
||||
html.replace("1race", String.valueOf(_raceNumber));
|
||||
html.replace("%objectId%", String.valueOf(getObjectId()));
|
||||
player.sendPacket(html);
|
||||
player.sendPacket(ActionFailed.STATIC_PACKET);
|
||||
}
|
||||
|
||||
public class Race
|
||||
{
|
||||
private final Info[] _info;
|
||||
|
||||
public Race(Info[] pInfo)
|
||||
{
|
||||
_info = pInfo;
|
||||
}
|
||||
|
||||
public Info getLaneInfo(int lane)
|
||||
{
|
||||
return _info[lane];
|
||||
}
|
||||
|
||||
public class Info
|
||||
{
|
||||
private final int _id;
|
||||
private final int _place;
|
||||
private final int _odds;
|
||||
private final int _payout;
|
||||
|
||||
public Info(int pId, int pPlace, int pOdds, int pPayout)
|
||||
{
|
||||
_id = pId;
|
||||
_place = pPlace;
|
||||
_odds = pOdds;
|
||||
_payout = pPayout;
|
||||
}
|
||||
|
||||
public int getId()
|
||||
{
|
||||
return _id;
|
||||
}
|
||||
|
||||
public int getOdds()
|
||||
{
|
||||
return _odds;
|
||||
}
|
||||
|
||||
public int getPayout()
|
||||
{
|
||||
return _payout;
|
||||
}
|
||||
|
||||
public int getPlace()
|
||||
{
|
||||
return _place;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RunRace implements Runnable
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
_packet = new MonRaceInfo(_codes[2][0], _codes[2][1], MonsterRace.getInstance().getMonsters(), MonsterRace.getInstance().getSpeeds());
|
||||
sendMonsterInfo();
|
||||
ThreadPool.schedule(new RunEnd(), 30000);
|
||||
}
|
||||
}
|
||||
|
||||
class RunEnd implements Runnable
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
makeAnnouncement(SystemMessageId.MONSRACE_FIRST_PLACE_S1_SECOND_S2);
|
||||
makeAnnouncement(SystemMessageId.MONSRACE_RACE_END);
|
||||
_raceNumber++;
|
||||
|
||||
DeleteObject obj = null;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
obj = new DeleteObject(MonsterRace.getInstance().getMonsters()[i]);
|
||||
broadcast(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.l2jmobius.gameserver.model.actor.instance;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.l2jmobius.Config;
|
||||
import org.l2jmobius.commons.util.StringUtil;
|
||||
import org.l2jmobius.gameserver.idfactory.IdFactory;
|
||||
import org.l2jmobius.gameserver.model.actor.templates.NpcTemplate;
|
||||
import org.l2jmobius.gameserver.model.entity.event.MonsterRace;
|
||||
import org.l2jmobius.gameserver.model.entity.event.MonsterRace.HistoryInfo;
|
||||
import org.l2jmobius.gameserver.model.entity.event.MonsterRace.RaceState;
|
||||
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
|
||||
import org.l2jmobius.gameserver.network.SystemMessageId;
|
||||
import org.l2jmobius.gameserver.network.serverpackets.ActionFailed;
|
||||
import org.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage;
|
||||
import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
|
||||
|
||||
public class RaceManagerInstance extends FolkInstance
|
||||
{
|
||||
protected static final int TICKET_PRICES[] =
|
||||
{
|
||||
100,
|
||||
500,
|
||||
1000,
|
||||
5000,
|
||||
10000,
|
||||
20000,
|
||||
50000,
|
||||
100000
|
||||
};
|
||||
|
||||
public RaceManagerInstance(int objectId, NpcTemplate template)
|
||||
{
|
||||
super(objectId, template);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBypassFeedback(PlayerInstance player, String command)
|
||||
{
|
||||
if (command.startsWith("BuyTicket"))
|
||||
{
|
||||
if (!Config.ALLOW_RACE || (MonsterRace.getInstance().getCurrentRaceState() != RaceState.ACCEPTING_BETS))
|
||||
{
|
||||
player.sendPacket(SystemMessageId.MONSRACE_TICKETS_NOT_AVAILABLE);
|
||||
super.onBypassFeedback(player, "Chat 0");
|
||||
return;
|
||||
}
|
||||
|
||||
int val = Integer.parseInt(command.substring(10));
|
||||
if (val == 0)
|
||||
{
|
||||
player.setRace(0, 0);
|
||||
player.setRace(1, 0);
|
||||
}
|
||||
|
||||
if (((val == 10) && (player.getRace(0) == 0)) || ((val == 20) && (player.getRace(0) == 0) && (player.getRace(1) == 0)))
|
||||
{
|
||||
val = 0;
|
||||
}
|
||||
|
||||
int npcId = getTemplate().getNpcId();
|
||||
String search, replace;
|
||||
|
||||
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
|
||||
|
||||
if (val < 10)
|
||||
{
|
||||
html.setFile(getHtmlPath(npcId, 2));
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
int n = i + 1;
|
||||
search = "Mob" + n;
|
||||
html.replace(search, MonsterRace.getInstance().getMonsters()[i].getTemplate().getName());
|
||||
}
|
||||
search = "No1";
|
||||
if (val == 0)
|
||||
{
|
||||
html.replace(search, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
html.replace(search, val);
|
||||
player.setRace(0, val);
|
||||
}
|
||||
}
|
||||
else if (val < 20)
|
||||
{
|
||||
if (player.getRace(0) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
html.setFile(getHtmlPath(npcId, 3));
|
||||
html.replace("0place", player.getRace(0));
|
||||
search = "Mob1";
|
||||
replace = MonsterRace.getInstance().getMonsters()[player.getRace(0) - 1].getTemplate().getName();
|
||||
html.replace(search, replace);
|
||||
search = "0adena";
|
||||
|
||||
if (val == 10)
|
||||
{
|
||||
html.replace(search, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
html.replace(search, TICKET_PRICES[val - 11]);
|
||||
player.setRace(1, val - 10);
|
||||
}
|
||||
}
|
||||
else if (val == 20)
|
||||
{
|
||||
if ((player.getRace(0) == 0) || (player.getRace(1) == 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
html.setFile(getHtmlPath(npcId, 4));
|
||||
html.replace("0place", player.getRace(0));
|
||||
search = "Mob1";
|
||||
replace = MonsterRace.getInstance().getMonsters()[player.getRace(0) - 1].getTemplate().getName();
|
||||
html.replace(search, replace);
|
||||
search = "0adena";
|
||||
int price = TICKET_PRICES[player.getRace(1) - 1];
|
||||
html.replace(search, price);
|
||||
search = "0tax";
|
||||
int tax = 0;
|
||||
html.replace(search, tax);
|
||||
search = "0total";
|
||||
int total = price + tax;
|
||||
html.replace(search, total);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((player.getRace(0) == 0) || (player.getRace(1) == 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int ticket = player.getRace(0);
|
||||
int priceId = player.getRace(1);
|
||||
|
||||
if (!player.reduceAdena("Race", TICKET_PRICES[priceId - 1], this, true))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
player.setRace(0, 0);
|
||||
player.setRace(1, 0);
|
||||
|
||||
ItemInstance item = new ItemInstance(IdFactory.getInstance().getNextId(), 4443);
|
||||
item.setCount(1);
|
||||
item.setEnchantLevel(MonsterRace.getInstance().getRaceNumber());
|
||||
item.setCustomType1(ticket);
|
||||
item.setCustomType2(TICKET_PRICES[priceId - 1] / 100);
|
||||
|
||||
player.addItem("Race", item, player, false);
|
||||
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.ACQUIRED).addNumber(MonsterRace.getInstance().getRaceNumber()).addItemName(4443));
|
||||
|
||||
// Refresh lane bet.
|
||||
MonsterRace.getInstance().setBetOnLane(ticket, TICKET_PRICES[priceId - 1], true);
|
||||
super.onBypassFeedback(player, "Chat 0");
|
||||
return;
|
||||
}
|
||||
html.replace("1race", MonsterRace.getInstance().getRaceNumber());
|
||||
html.replace("%objectId%", getObjectId());
|
||||
player.sendPacket(html);
|
||||
player.sendPacket(ActionFailed.STATIC_PACKET);
|
||||
}
|
||||
else if (command.equals("ShowOdds"))
|
||||
{
|
||||
if (!Config.ALLOW_RACE || (MonsterRace.getInstance().getCurrentRaceState() == RaceState.ACCEPTING_BETS))
|
||||
{
|
||||
player.sendPacket(SystemMessageId.MONSRACE_NO_PAYOUT_INFO);
|
||||
super.onBypassFeedback(player, "Chat 0");
|
||||
return;
|
||||
}
|
||||
|
||||
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
|
||||
html.setFile(getHtmlPath(getTemplate().getNpcId(), 5));
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
final int n = i + 1;
|
||||
|
||||
html.replace("Mob" + n, MonsterRace.getInstance().getMonsters()[i].getTemplate().getName());
|
||||
|
||||
// Odd
|
||||
final double odd = MonsterRace.getInstance().getOdds().get(i);
|
||||
html.replace("Odd" + n, (odd > 0D) ? String.format(Locale.ENGLISH, "%.1f", odd) : "&$804;");
|
||||
}
|
||||
html.replace("1race", MonsterRace.getInstance().getRaceNumber());
|
||||
html.replace("%objectId%", getObjectId());
|
||||
player.sendPacket(html);
|
||||
player.sendPacket(ActionFailed.STATIC_PACKET);
|
||||
}
|
||||
else if (command.equals("ShowInfo"))
|
||||
{
|
||||
if (!Config.ALLOW_RACE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
|
||||
html.setFile(getHtmlPath(getTemplate().getNpcId(), 6));
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
int n = i + 1;
|
||||
String search = "Mob" + n;
|
||||
html.replace(search, MonsterRace.getInstance().getMonsters()[i].getTemplate().getName());
|
||||
}
|
||||
html.replace("%objectId%", getObjectId());
|
||||
player.sendPacket(html);
|
||||
player.sendPacket(ActionFailed.STATIC_PACKET);
|
||||
}
|
||||
else if (command.equals("ShowTickets"))
|
||||
{
|
||||
if (!Config.ALLOW_RACE)
|
||||
{
|
||||
super.onBypassFeedback(player, "Chat 0");
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate data.
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
|
||||
// Retrieve player's tickets.
|
||||
for (ItemInstance ticket : player.getInventory().getAllItemsByItemId(4443))
|
||||
{
|
||||
// Don't list current race tickets.
|
||||
if (ticket.getEnchantLevel() == MonsterRace.getInstance().getRaceNumber())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
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>");
|
||||
}
|
||||
|
||||
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
|
||||
html.setFile(getHtmlPath(getTemplate().getNpcId(), 7));
|
||||
html.replace("%tickets%", sb.toString());
|
||||
html.replace("%objectId%", getObjectId());
|
||||
player.sendPacket(html);
|
||||
player.sendPacket(ActionFailed.STATIC_PACKET);
|
||||
}
|
||||
else if (command.startsWith("ShowTicket"))
|
||||
{
|
||||
// Retrieve ticket objectId.
|
||||
final int val = Integer.parseInt(command.substring(11));
|
||||
if (!Config.ALLOW_RACE || (val == 0))
|
||||
{
|
||||
super.onBypassFeedback(player, "Chat 0");
|
||||
return;
|
||||
}
|
||||
|
||||
// Retrieve ticket on player's inventory.
|
||||
final ItemInstance ticket = player.getInventory().getItemByObjectId(val);
|
||||
if (ticket == null)
|
||||
{
|
||||
super.onBypassFeedback(player, "Chat 0");
|
||||
return;
|
||||
}
|
||||
|
||||
final int raceId = ticket.getEnchantLevel();
|
||||
final int lane = ticket.getCustomType1();
|
||||
final int bet = ticket.getCustomType2() * 100;
|
||||
|
||||
// Retrieve HistoryInfo for that race.
|
||||
final HistoryInfo info = MonsterRace.getInstance().getHistory().get(raceId - 1);
|
||||
if (info == null)
|
||||
{
|
||||
super.onBypassFeedback(player, "Chat 0");
|
||||
return;
|
||||
}
|
||||
|
||||
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
|
||||
html.setFile(getHtmlPath(getTemplate().getNpcId(), 8));
|
||||
html.replace("%raceId%", raceId);
|
||||
html.replace("%lane%", lane);
|
||||
html.replace("%bet%", bet);
|
||||
html.replace("%firstLane%", info.getFirst());
|
||||
html.replace("%odd%", (lane == info.getFirst()) ? String.format(Locale.ENGLISH, "%.2f", info.getOddRate()) : "0.01");
|
||||
html.replace("%objectId%", getObjectId());
|
||||
html.replace("%ticketObjectId%", val);
|
||||
player.sendPacket(html);
|
||||
player.sendPacket(ActionFailed.STATIC_PACKET);
|
||||
}
|
||||
else if (command.startsWith("CalculateWin"))
|
||||
{
|
||||
// Retrieve ticket objectId.
|
||||
final int val = Integer.parseInt(command.substring(13));
|
||||
if (!Config.ALLOW_RACE || (val == 0))
|
||||
{
|
||||
super.onBypassFeedback(player, "Chat 0");
|
||||
return;
|
||||
}
|
||||
|
||||
// Delete ticket on player's inventory.
|
||||
final ItemInstance ticket = player.getInventory().getItemByObjectId(val);
|
||||
if (ticket == null)
|
||||
{
|
||||
super.onBypassFeedback(player, "Chat 0");
|
||||
return;
|
||||
}
|
||||
|
||||
final int raceId = ticket.getEnchantLevel();
|
||||
final int lane = ticket.getCustomType1();
|
||||
final int bet = ticket.getCustomType2() * 100;
|
||||
|
||||
// Retrieve HistoryInfo for that race.
|
||||
final HistoryInfo info = MonsterRace.getInstance().getHistory().get(raceId - 1);
|
||||
if (info == null)
|
||||
{
|
||||
super.onBypassFeedback(player, "Chat 0");
|
||||
return;
|
||||
}
|
||||
|
||||
// Destroy the ticket.
|
||||
if (player.destroyItem("MonsterTrack", ticket, this, true))
|
||||
{
|
||||
player.addAdena("MonsterTrack", (int) (bet * ((lane == info.getFirst()) ? info.getOddRate() : 0.01)), this, true);
|
||||
}
|
||||
|
||||
super.onBypassFeedback(player, "Chat 0");
|
||||
return;
|
||||
}
|
||||
else if (command.equals("ViewHistory"))
|
||||
{
|
||||
if (!Config.ALLOW_RACE)
|
||||
{
|
||||
super.onBypassFeedback(player, "Chat 0");
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate data.
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
|
||||
// Use whole history, pickup from 'last element' and stop at 'latest element - 7'.
|
||||
final List<HistoryInfo> history = MonsterRace.getInstance().getHistory();
|
||||
for (int i = history.size() - 1; i >= Math.max(0, history.size() - 7); i--)
|
||||
{
|
||||
final HistoryInfo info = history.get(i);
|
||||
StringUtil.append(sb, "<tr><td><font color=\"LEVEL\">", info.getRaceId(), "</font> th</td><td><font color=\"LEVEL\">", info.getFirst(), "</font> Lane </td><td><font color=\"LEVEL\">", info.getSecond(), "</font> Lane</td><td align=right><font color=00ffff>", String.format(Locale.ENGLISH, "%.2f", info.getOddRate()), "</font> Times</td></tr>");
|
||||
}
|
||||
|
||||
final NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
|
||||
html.setFile(getHtmlPath(getTemplate().getNpcId(), 9));
|
||||
html.replace("%infos%", sb.toString());
|
||||
html.replace("%objectId%", getObjectId());
|
||||
player.sendPacket(html);
|
||||
player.sendPacket(ActionFailed.STATIC_PACKET);
|
||||
}
|
||||
else
|
||||
{
|
||||
super.onBypassFeedback(player, command);
|
||||
}
|
||||
}
|
||||
}
|
@@ -19,7 +19,7 @@ package org.l2jmobius.gameserver.model.actor.knownlist;
|
||||
import org.l2jmobius.gameserver.model.WorldObject;
|
||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||
import org.l2jmobius.gameserver.model.actor.instance.RaceManagerInstance;
|
||||
import org.l2jmobius.gameserver.model.entity.MonsterRace;
|
||||
import org.l2jmobius.gameserver.model.entity.event.MonsterRace;
|
||||
import org.l2jmobius.gameserver.network.serverpackets.DeleteObject;
|
||||
|
||||
public class RaceManagerKnownList extends NpcKnownList
|
||||
|
@@ -1,148 +0,0 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.l2jmobius.gameserver.model.entity;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import org.l2jmobius.commons.util.Rnd;
|
||||
import org.l2jmobius.gameserver.datatables.sql.NpcTable;
|
||||
import org.l2jmobius.gameserver.idfactory.IdFactory;
|
||||
import org.l2jmobius.gameserver.model.actor.instance.NpcInstance;
|
||||
import org.l2jmobius.gameserver.model.actor.templates.NpcTemplate;
|
||||
|
||||
public class MonsterRace
|
||||
{
|
||||
private final NpcInstance[] _monsters;
|
||||
private int[][] _speeds;
|
||||
private final int[] _first;
|
||||
private final int[] _second;
|
||||
|
||||
private MonsterRace()
|
||||
{
|
||||
_monsters = new NpcInstance[8];
|
||||
_speeds = new int[8][20];
|
||||
_first = new int[2];
|
||||
_second = new int[2];
|
||||
}
|
||||
|
||||
public void newRace()
|
||||
{
|
||||
int random = 0;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
final int id = 31003;
|
||||
random = Rnd.get(24);
|
||||
while (true)
|
||||
{
|
||||
for (int j = i - 1; j >= 0; j--)
|
||||
{
|
||||
if (_monsters[j].getTemplate().getNpcId() == (id + random))
|
||||
{
|
||||
random = Rnd.get(24);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
try
|
||||
{
|
||||
final NpcTemplate template = NpcTable.getInstance().getTemplate(id + random);
|
||||
final Constructor<?> constructor = Class.forName("org.l2jmobius.gameserver.model.actor.instance." + template.getType() + "Instance").getConstructors()[0];
|
||||
final int objectId = IdFactory.getInstance().getNextId();
|
||||
_monsters[i] = (NpcInstance) constructor.newInstance(objectId, template);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
newSpeeds();
|
||||
}
|
||||
|
||||
public void newSpeeds()
|
||||
{
|
||||
_speeds = new int[8][20];
|
||||
int total = 0;
|
||||
_first[1] = 0;
|
||||
_second[1] = 0;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
total = 0;
|
||||
for (int j = 0; j < 20; j++)
|
||||
{
|
||||
if (j == 19)
|
||||
{
|
||||
_speeds[i][j] = 100;
|
||||
}
|
||||
else
|
||||
{
|
||||
_speeds[i][j] = Rnd.get(60) + 65;
|
||||
}
|
||||
total += _speeds[i][j];
|
||||
}
|
||||
|
||||
if (total >= _first[1])
|
||||
{
|
||||
_second[0] = _first[0];
|
||||
_second[1] = _first[1];
|
||||
_first[0] = 8 - i;
|
||||
_first[1] = total;
|
||||
}
|
||||
else if (total >= _second[1])
|
||||
{
|
||||
_second[0] = 8 - i;
|
||||
_second[1] = total;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the monsters.
|
||||
*/
|
||||
public NpcInstance[] getMonsters()
|
||||
{
|
||||
return _monsters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the speeds.
|
||||
*/
|
||||
public int[][] getSpeeds()
|
||||
{
|
||||
return _speeds;
|
||||
}
|
||||
|
||||
public int getFirstPlace()
|
||||
{
|
||||
return _first[0];
|
||||
}
|
||||
|
||||
public int getSecondPlace()
|
||||
{
|
||||
return _second[0];
|
||||
}
|
||||
|
||||
public static MonsterRace getInstance()
|
||||
{
|
||||
return SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
private static class SingletonHolder
|
||||
{
|
||||
protected static final MonsterRace INSTANCE = new MonsterRace();
|
||||
}
|
||||
}
|
@@ -0,0 +1,595 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.l2jmobius.gameserver.model.entity.event;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.l2jmobius.Config;
|
||||
import org.l2jmobius.commons.concurrent.ThreadPool;
|
||||
import org.l2jmobius.commons.database.DatabaseFactory;
|
||||
import org.l2jmobius.commons.util.Rnd;
|
||||
import org.l2jmobius.gameserver.datatables.sql.NpcTable;
|
||||
import org.l2jmobius.gameserver.idfactory.IdFactory;
|
||||
import org.l2jmobius.gameserver.model.actor.instance.NpcInstance;
|
||||
import org.l2jmobius.gameserver.model.actor.templates.NpcTemplate;
|
||||
import org.l2jmobius.gameserver.model.zone.type.DerbyTrackZone;
|
||||
import org.l2jmobius.gameserver.network.SystemMessageId;
|
||||
import org.l2jmobius.gameserver.network.serverpackets.DeleteObject;
|
||||
import org.l2jmobius.gameserver.network.serverpackets.MonRaceInfo;
|
||||
import org.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
||||
import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
|
||||
import org.l2jmobius.gameserver.util.Broadcast;
|
||||
|
||||
public class MonsterRace
|
||||
{
|
||||
protected static final Logger LOGGER = Logger.getLogger(MonsterRace.class.getName());
|
||||
|
||||
public static enum RaceState
|
||||
{
|
||||
ACCEPTING_BETS,
|
||||
WAITING,
|
||||
STARTING_RACE,
|
||||
RACE_END
|
||||
}
|
||||
|
||||
protected static final PlaySound SOUND_1 = new PlaySound(1, "S_Race");
|
||||
protected static final PlaySound SOUND_2 = new PlaySound("ItemSound2.race_start");
|
||||
|
||||
protected static final int[][] CODES =
|
||||
{
|
||||
{
|
||||
-1,
|
||||
0
|
||||
},
|
||||
{
|
||||
0,
|
||||
15322
|
||||
},
|
||||
{
|
||||
13765,
|
||||
-1
|
||||
}
|
||||
};
|
||||
|
||||
protected final List<Integer> _npcTemplates = new ArrayList<>(); // List holding npc templates, shuffled on a new race.
|
||||
protected final List<HistoryInfo> _history = new ArrayList<>(); // List holding old race records.
|
||||
protected final Map<Integer, Long> _betsPerLane = new ConcurrentHashMap<>(); // Map holding all bets for each lane ; values setted to 0 after every race.
|
||||
protected final List<Double> _odds = new ArrayList<>(); // List holding sorted odds per lane ; cleared at new odds calculation.
|
||||
|
||||
protected int _raceNumber = 1;
|
||||
protected int _finalCountdown = 0;
|
||||
protected RaceState _state = RaceState.RACE_END;
|
||||
|
||||
protected MonRaceInfo _packet;
|
||||
|
||||
private Constructor<?> _constructor;
|
||||
private final NpcInstance[] _monsters = new NpcInstance[8];
|
||||
private int[][] _speeds = new int[8][20];
|
||||
private final int[] _first = new int[2];
|
||||
private final int[] _second = new int[2];
|
||||
|
||||
protected MonsterRace()
|
||||
{
|
||||
if (!Config.ALLOW_RACE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Feed _history with previous race results.
|
||||
loadHistory();
|
||||
|
||||
// Feed _betsPerLane with stored informations on bets.
|
||||
loadBets();
|
||||
|
||||
// Feed _npcTemplates, we will only have to shuffle it when needed.
|
||||
for (int i = 31003; i < 31027; i++)
|
||||
{
|
||||
_npcTemplates.add(i);
|
||||
}
|
||||
|
||||
ThreadPool.scheduleAtFixedRate(new Announcement(), 0, 1000);
|
||||
}
|
||||
|
||||
public static class HistoryInfo
|
||||
{
|
||||
private final int _raceId;
|
||||
private int _first;
|
||||
private int _second;
|
||||
private double _oddRate;
|
||||
|
||||
public HistoryInfo(int raceId, int first, int second, double oddRate)
|
||||
{
|
||||
_raceId = raceId;
|
||||
_first = first;
|
||||
_second = second;
|
||||
_oddRate = oddRate;
|
||||
}
|
||||
|
||||
public int getRaceId()
|
||||
{
|
||||
return _raceId;
|
||||
}
|
||||
|
||||
public int getFirst()
|
||||
{
|
||||
return _first;
|
||||
}
|
||||
|
||||
public int getSecond()
|
||||
{
|
||||
return _second;
|
||||
}
|
||||
|
||||
public double getOddRate()
|
||||
{
|
||||
return _oddRate;
|
||||
}
|
||||
|
||||
public void setFirst(int first)
|
||||
{
|
||||
_first = first;
|
||||
}
|
||||
|
||||
public void setSecond(int second)
|
||||
{
|
||||
_second = second;
|
||||
}
|
||||
|
||||
public void setOddRate(double oddRate)
|
||||
{
|
||||
_oddRate = oddRate;
|
||||
}
|
||||
}
|
||||
|
||||
private class Announcement implements Runnable
|
||||
{
|
||||
public Announcement()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if (_finalCountdown > 1200)
|
||||
{
|
||||
_finalCountdown = 0;
|
||||
}
|
||||
|
||||
switch (_finalCountdown)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
newRace();
|
||||
newSpeeds();
|
||||
|
||||
_state = RaceState.ACCEPTING_BETS;
|
||||
_packet = new MonRaceInfo(CODES[0][0], CODES[0][1], getMonsters(), getSpeeds());
|
||||
|
||||
Broadcast.toAllPlayersInZoneType(DerbyTrackZone.class, _packet, SystemMessage.getSystemMessage(SystemMessageId.MONSRACE_TICKETS_AVAILABLE_FOR_S1_RACE).addNumber(_raceNumber));
|
||||
break;
|
||||
}
|
||||
case 30: // 30 sec
|
||||
case 60: // 1 min
|
||||
case 90: // 1 min 30 sec
|
||||
case 120: // 2 min
|
||||
case 150: // 2 min 30
|
||||
case 180: // 3 min
|
||||
case 210: // 3 min 30
|
||||
case 240: // 4 min
|
||||
case 270: // 4 min 30 sec
|
||||
case 330: // 5 min 30 sec
|
||||
case 360: // 6 min
|
||||
case 390: // 6 min 30 sec
|
||||
case 420: // 7 min
|
||||
case 450: // 7 min 30
|
||||
case 480: // 8 min
|
||||
case 510: // 8 min 30
|
||||
case 540: // 9 min
|
||||
case 570: // 9 min 30 sec
|
||||
case 630: // 10 min 30 sec
|
||||
case 660: // 11 min
|
||||
case 690: // 11 min 30 sec
|
||||
case 720: // 12 min
|
||||
case 750: // 12 min 30
|
||||
case 780: // 13 min
|
||||
case 810: // 13 min 30
|
||||
case 870: // 14 min 30 sec
|
||||
{
|
||||
Broadcast.toAllPlayersInZoneType(DerbyTrackZone.class, SystemMessage.getSystemMessage(SystemMessageId.MONSRACE_TICKETS_NOW_AVAILABLE_FOR_S1_RACE).addNumber(_raceNumber));
|
||||
break;
|
||||
}
|
||||
case 300: // 5 min
|
||||
{
|
||||
Broadcast.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));
|
||||
break;
|
||||
}
|
||||
case 600: // 10 min
|
||||
{
|
||||
Broadcast.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));
|
||||
break;
|
||||
}
|
||||
case 840: // 14 min
|
||||
{
|
||||
Broadcast.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));
|
||||
break;
|
||||
}
|
||||
case 900: // 15 min
|
||||
{
|
||||
_state = RaceState.WAITING;
|
||||
|
||||
calculateOdds();
|
||||
|
||||
Broadcast.toAllPlayersInZoneType(DerbyTrackZone.class, SystemMessage.getSystemMessage(SystemMessageId.MONSRACE_TICKETS_NOW_AVAILABLE_FOR_S1_RACE).addNumber(_raceNumber), SystemMessage.getSystemMessage(SystemMessageId.MONSRACE_S1_TICKET_SALES_CLOSED).addNumber(_raceNumber));
|
||||
break;
|
||||
}
|
||||
case 960: // 16 min
|
||||
case 1020: // 17 min
|
||||
{
|
||||
final int minutes = (_finalCountdown == 960) ? 2 : 1;
|
||||
Broadcast.toAllPlayersInZoneType(DerbyTrackZone.class, SystemMessage.getSystemMessage(SystemMessageId.MONSRACE_S2_BEGINS_IN_S1_MINUTES).addNumber(minutes).addNumber(_raceNumber));
|
||||
break;
|
||||
}
|
||||
case 1050: // 17 min 30 sec
|
||||
{
|
||||
Broadcast.toAllPlayersInZoneType(DerbyTrackZone.class, SystemMessage.getSystemMessage(SystemMessageId.MONSRACE_S1_BEGINS_IN_30_SECONDS));
|
||||
break;
|
||||
}
|
||||
case 1070: // 17 min 50 sec
|
||||
{
|
||||
Broadcast.toAllPlayersInZoneType(DerbyTrackZone.class, SystemMessage.getSystemMessage(SystemMessageId.MONSRACE_S1_COUNTDOWN_IN_FIVE_SECONDS));
|
||||
break;
|
||||
}
|
||||
case 1075: // 17 min 55 sec
|
||||
case 1076: // 17 min 56 sec
|
||||
case 1077: // 17 min 57 sec
|
||||
case 1078: // 17 min 58 sec
|
||||
case 1079: // 17 min 59 sec
|
||||
{
|
||||
final int seconds = 1080 - _finalCountdown;
|
||||
Broadcast.toAllPlayersInZoneType(DerbyTrackZone.class, SystemMessage.getSystemMessage(SystemMessageId.MONSRACE_BEGINS_IN_S1_SECONDS).addNumber(seconds));
|
||||
break;
|
||||
}
|
||||
case 1080: // 18 min
|
||||
{
|
||||
_state = RaceState.STARTING_RACE;
|
||||
_packet = new MonRaceInfo(CODES[1][0], CODES[1][1], getMonsters(), getSpeeds());
|
||||
|
||||
Broadcast.toAllPlayersInZoneType(DerbyTrackZone.class, SystemMessage.getSystemMessage(SystemMessageId.MONSRACE_RACE_START), SOUND_1, SOUND_2, _packet);
|
||||
break;
|
||||
}
|
||||
case 1085: // 18 min 5 sec
|
||||
{
|
||||
_packet = new MonRaceInfo(CODES[2][0], CODES[2][1], getMonsters(), getSpeeds());
|
||||
|
||||
Broadcast.toAllPlayersInZoneType(DerbyTrackZone.class, _packet);
|
||||
break;
|
||||
}
|
||||
case 1115: // 18 min 35 sec
|
||||
{
|
||||
_state = RaceState.RACE_END;
|
||||
|
||||
// Populate history info with data, stores it in database.
|
||||
final HistoryInfo info = _history.get(_history.size() - 1);
|
||||
info.setFirst(getFirstPlace());
|
||||
info.setSecond(getSecondPlace());
|
||||
info.setOddRate(_odds.get(getFirstPlace() - 1));
|
||||
|
||||
saveHistory(info);
|
||||
clearBets();
|
||||
|
||||
Broadcast.toAllPlayersInZoneType(DerbyTrackZone.class, SystemMessage.getSystemMessage(SystemMessageId.MONSRACE_FIRST_PLACE_S1_SECOND_S2).addNumber(getFirstPlace()).addNumber(getSecondPlace()), SystemMessage.getSystemMessage(SystemMessageId.MONSRACE_S1_RACE_END).addNumber(_raceNumber));
|
||||
_raceNumber++;
|
||||
break;
|
||||
}
|
||||
case 1140: // 19 min
|
||||
{
|
||||
Broadcast.toAllPlayersInZoneType(DerbyTrackZone.class, new DeleteObject(getMonsters()[0]), new DeleteObject(getMonsters()[1]), new DeleteObject(getMonsters()[2]), new DeleteObject(getMonsters()[3]), new DeleteObject(getMonsters()[4]), new DeleteObject(getMonsters()[5]), new DeleteObject(getMonsters()[6]), new DeleteObject(getMonsters()[7]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
_finalCountdown += 1;
|
||||
}
|
||||
}
|
||||
|
||||
public void newRace()
|
||||
{
|
||||
// Edit _history.
|
||||
_history.add(new HistoryInfo(_raceNumber, 0, 0, 0));
|
||||
|
||||
// Randomize _npcTemplates.
|
||||
Collections.shuffle(_npcTemplates);
|
||||
|
||||
// Setup 8 new creatures ; pickup the first 8 from _npcTemplates.
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
final NpcTemplate template = NpcTable.getInstance().getTemplate(_npcTemplates.get(i));
|
||||
_constructor = Class.forName("org.l2jmobius.gameserver.model.actor.instance." + template.getType() + "Instance").getConstructors()[0];
|
||||
final int objectId = IdFactory.getInstance().getNextId();
|
||||
_monsters[i] = (NpcInstance) _constructor.newInstance(objectId, template);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.log(Level.WARNING, "", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void newSpeeds()
|
||||
{
|
||||
_speeds = new int[8][20];
|
||||
int total = 0;
|
||||
_first[1] = 0;
|
||||
_second[1] = 0;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
total = 0;
|
||||
for (int j = 0; j < 20; j++)
|
||||
{
|
||||
if (j == 19)
|
||||
{
|
||||
_speeds[i][j] = 100;
|
||||
}
|
||||
else
|
||||
{
|
||||
_speeds[i][j] = Rnd.get(60) + 65;
|
||||
}
|
||||
total += _speeds[i][j];
|
||||
}
|
||||
|
||||
if (total >= _first[1])
|
||||
{
|
||||
_second[0] = _first[0];
|
||||
_second[1] = _first[1];
|
||||
_first[0] = 8 - i;
|
||||
_first[1] = total;
|
||||
}
|
||||
else if (total >= _second[1])
|
||||
{
|
||||
_second[0] = 8 - i;
|
||||
_second[1] = total;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load past races informations, feeding _history arrayList.<br>
|
||||
* Also sets _raceNumber, based on latest HistoryInfo loaded.
|
||||
*/
|
||||
protected void loadHistory()
|
||||
{
|
||||
try (Connection con = DatabaseFactory.getConnection())
|
||||
{
|
||||
PreparedStatement statement = con.prepareStatement("SELECT * FROM mdt_history");
|
||||
ResultSet rset = statement.executeQuery();
|
||||
|
||||
while (rset.next())
|
||||
{
|
||||
_history.add(new HistoryInfo(rset.getInt("race_id"), rset.getInt("first"), rset.getInt("second"), rset.getDouble("odd_rate")));
|
||||
_raceNumber++;
|
||||
}
|
||||
rset.close();
|
||||
statement.close();
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
LOGGER.log(Level.WARNING, "MonsterRace: Can't load history: " + e.getMessage(), e);
|
||||
}
|
||||
LOGGER.info("MonsterRace: loaded " + _history.size() + " records, currently on race #" + _raceNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save an history record into database.
|
||||
* @param history The infos to store.
|
||||
*/
|
||||
protected void saveHistory(HistoryInfo history)
|
||||
{
|
||||
try (Connection con = DatabaseFactory.getConnection())
|
||||
{
|
||||
PreparedStatement statement = con.prepareStatement("INSERT INTO mdt_history (race_id, first, second, odd_rate) VALUES (?,?,?,?)");
|
||||
statement.setInt(1, history.getRaceId());
|
||||
statement.setInt(2, history.getFirst());
|
||||
statement.setInt(3, history.getSecond());
|
||||
statement.setDouble(4, history.getOddRate());
|
||||
statement.execute();
|
||||
statement.close();
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
LOGGER.log(Level.WARNING, "MonsterRace: Can't save history: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load current bets per lane ; initialize the map keys.
|
||||
*/
|
||||
protected void loadBets()
|
||||
{
|
||||
try (Connection con = DatabaseFactory.getConnection())
|
||||
{
|
||||
PreparedStatement statement = con.prepareStatement("SELECT * FROM mdt_bets");
|
||||
ResultSet rset = statement.executeQuery();
|
||||
|
||||
while (rset.next())
|
||||
{
|
||||
setBetOnLane(rset.getInt("lane_id"), rset.getLong("bet"), false);
|
||||
}
|
||||
|
||||
rset.close();
|
||||
statement.close();
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
LOGGER.log(Level.WARNING, "MonsterRace: Can't load bets: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the current lane bet into database.
|
||||
* @param lane : The lane to affect.
|
||||
* @param sum : The sum to set.
|
||||
*/
|
||||
protected void saveBet(int lane, long sum)
|
||||
{
|
||||
try (Connection con = DatabaseFactory.getConnection())
|
||||
{
|
||||
PreparedStatement statement = con.prepareStatement("REPLACE INTO mdt_bets (lane_id, bet) VALUES (?,?)");
|
||||
statement.setInt(1, lane);
|
||||
statement.setLong(2, sum);
|
||||
statement.execute();
|
||||
statement.close();
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
LOGGER.log(Level.WARNING, "MonsterRace: Can't save bet: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all lanes bets, either on database or Map.
|
||||
*/
|
||||
protected void clearBets()
|
||||
{
|
||||
for (int key : _betsPerLane.keySet())
|
||||
{
|
||||
_betsPerLane.put(key, 0L);
|
||||
}
|
||||
|
||||
try (Connection con = DatabaseFactory.getConnection())
|
||||
{
|
||||
PreparedStatement statement = con.prepareStatement("UPDATE mdt_bets SET bet = 0");
|
||||
statement.execute();
|
||||
statement.close();
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
LOGGER.log(Level.WARNING, "MonsterRace: Can't clear bets: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup lane bet, based on previous value (if any).
|
||||
* @param lane : The lane to edit.
|
||||
* @param amount : The amount to add.
|
||||
* @param saveOnDb : Should it be saved on db or not.
|
||||
*/
|
||||
public void setBetOnLane(int lane, long amount, boolean saveOnDb)
|
||||
{
|
||||
final long sum = (_betsPerLane.containsKey(lane)) ? _betsPerLane.get(lane) + amount : amount;
|
||||
|
||||
_betsPerLane.put(lane, sum);
|
||||
|
||||
if (saveOnDb)
|
||||
{
|
||||
saveBet(lane, sum);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate odds for every lane, based on others lanes.
|
||||
*/
|
||||
protected void calculateOdds()
|
||||
{
|
||||
// Clear previous List holding old odds.
|
||||
_odds.clear();
|
||||
|
||||
// Sort bets lanes per lane.
|
||||
final Map<Integer, Long> sortedLanes = new TreeMap<>(_betsPerLane);
|
||||
|
||||
// Pass a first loop in order to calculate total sum of all lanes.
|
||||
long sumOfAllLanes = 0;
|
||||
for (long amount : sortedLanes.values())
|
||||
{
|
||||
sumOfAllLanes += amount;
|
||||
}
|
||||
|
||||
// As we get the sum, we can now calculate the odd rate of each lane.
|
||||
for (long amount : sortedLanes.values())
|
||||
{
|
||||
_odds.add((amount == 0) ? 0D : Math.max(1.25, (sumOfAllLanes * 0.7) / amount));
|
||||
}
|
||||
}
|
||||
|
||||
public NpcInstance[] getMonsters()
|
||||
{
|
||||
return _monsters;
|
||||
}
|
||||
|
||||
public int[][] getSpeeds()
|
||||
{
|
||||
return _speeds;
|
||||
}
|
||||
|
||||
public int getFirstPlace()
|
||||
{
|
||||
return _first[0];
|
||||
}
|
||||
|
||||
public int getSecondPlace()
|
||||
{
|
||||
return _second[0];
|
||||
}
|
||||
|
||||
public MonRaceInfo getRacePacket()
|
||||
{
|
||||
return _packet;
|
||||
}
|
||||
|
||||
public RaceState getCurrentRaceState()
|
||||
{
|
||||
return _state;
|
||||
}
|
||||
|
||||
public int getRaceNumber()
|
||||
{
|
||||
return _raceNumber;
|
||||
}
|
||||
|
||||
public List<HistoryInfo> getHistory()
|
||||
{
|
||||
return _history;
|
||||
}
|
||||
|
||||
public List<Double> getOdds()
|
||||
{
|
||||
return _odds;
|
||||
}
|
||||
|
||||
public static MonsterRace getInstance()
|
||||
{
|
||||
return SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
private static class SingletonHolder
|
||||
{
|
||||
protected static final MonsterRace INSTANCE = new MonsterRace();
|
||||
}
|
||||
}
|
@@ -2177,25 +2177,25 @@ public enum SystemMessageId
|
||||
* ID: 819<br>
|
||||
* Message: Tickets sales are closed for Monster Race $s1. Odds are posted.
|
||||
*/
|
||||
MONSRACE_TICKET_SALES_CLOSED(819),
|
||||
MONSRACE_S1_TICKET_SALES_CLOSED(819),
|
||||
|
||||
/**
|
||||
* ID: 820<br>
|
||||
* Message: Monster Race $s2 will begin in $s1 minute(s)!
|
||||
*/
|
||||
MONSRACE_BEGINS_IN_S1_MINUTES(820),
|
||||
MONSRACE_S2_BEGINS_IN_S1_MINUTES(820),
|
||||
|
||||
/**
|
||||
* ID: 821<br>
|
||||
* Message: Monster Race $s1 will begin in 30 seconds!
|
||||
*/
|
||||
MONSRACE_BEGINS_IN_30_SECONDS(821),
|
||||
MONSRACE_S1_BEGINS_IN_30_SECONDS(821),
|
||||
|
||||
/**
|
||||
* ID: 822<br>
|
||||
* Message: Monster Race $s1 is about to begin! Countdown in five seconds!
|
||||
*/
|
||||
MONSRACE_COUNTDOWN_IN_FIVE_SECONDS(822),
|
||||
MONSRACE_S1_COUNTDOWN_IN_FIVE_SECONDS(822),
|
||||
|
||||
/**
|
||||
* ID: 823<br>
|
||||
@@ -2213,7 +2213,7 @@ public enum SystemMessageId
|
||||
* ID: 825<br>
|
||||
* Message: Monster Race $s1 is finished!
|
||||
*/
|
||||
MONSRACE_RACE_END(825),
|
||||
MONSRACE_S1_RACE_END(825),
|
||||
|
||||
/**
|
||||
* ID: 826<br>
|
||||
|
@@ -16,9 +16,11 @@
|
||||
*/
|
||||
package org.l2jmobius.gameserver.util;
|
||||
|
||||
import org.l2jmobius.gameserver.datatables.xml.ZoneData;
|
||||
import org.l2jmobius.gameserver.model.World;
|
||||
import org.l2jmobius.gameserver.model.actor.Creature;
|
||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||
import org.l2jmobius.gameserver.model.zone.ZoneType;
|
||||
import org.l2jmobius.gameserver.network.serverpackets.CharInfo;
|
||||
import org.l2jmobius.gameserver.network.serverpackets.GameServerPacket;
|
||||
import org.l2jmobius.gameserver.network.serverpackets.RelationChanged;
|
||||
@@ -180,4 +182,29 @@ public class Broadcast
|
||||
onlinePlayer.sendPacket(packet);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a packet to all players in a specific zone type.
|
||||
* @param <T> ZoneType.
|
||||
* @param zoneType : The zone type to send packets.
|
||||
* @param packets : The packets to send.
|
||||
*/
|
||||
public static <T extends ZoneType> void toAllPlayersInZoneType(Class<T> zoneType, GameServerPacket... packets)
|
||||
{
|
||||
for (ZoneType zone : ZoneData.getInstance().getAllZones(zoneType))
|
||||
{
|
||||
for (Creature creature : zone.getCharactersInside().values())
|
||||
{
|
||||
if (creature == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (GameServerPacket packet : packets)
|
||||
{
|
||||
creature.sendPacket(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user