Support for Balthus Event.

Contributed by Index.
This commit is contained in:
MobiusDevelopment
2022-03-23 11:23:11 +00:00
parent 7e327f1402
commit 5dd8637495
81 changed files with 3714 additions and 36 deletions

View File

@@ -0,0 +1,407 @@
/*
* 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.instancemanager.events;
import java.io.File;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.l2jmobius.commons.threads.ThreadPool;
import org.l2jmobius.commons.util.Chronos;
import org.l2jmobius.commons.util.IXmlReader;
import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.enums.MailType;
import org.l2jmobius.gameserver.instancemanager.MailManager;
import org.l2jmobius.gameserver.model.Message;
import org.l2jmobius.gameserver.model.StatSet;
import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.model.holders.ItemChanceHolder;
import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.item.instance.Item;
import org.l2jmobius.gameserver.model.itemcontainer.Mail;
import org.l2jmobius.gameserver.model.variables.PlayerVariables;
import org.l2jmobius.gameserver.network.SystemMessageId;
import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import org.l2jmobius.gameserver.network.serverpackets.balthusevent.ExBalthusEvent;
import org.l2jmobius.gameserver.network.serverpackets.balthusevent.ExBalthusEventJackpotUser;
import org.l2jmobius.gameserver.util.Broadcast;
/**
* @author Index
*/
public class BalthusEventManager implements IXmlReader
{
protected static final Logger LOGGER = Logger.getLogger(BalthusEventManager.class.getName());
private final Set<Player> _players = ConcurrentHashMap.newKeySet();
private final Map<Integer, BalthusEventHolder> _templates = new HashMap<>();
private boolean _isEasyMode;
private ItemHolder _consolation;
private int _minimalLevel = 0;
private String _mailSubject = null;
private String _mailContent = null;
private boolean _isRunning = false;
private int _currProgress;
private int _currState;
private int _avoidMinutesIssue;
private Player _winner = null;
private ItemChanceHolder _rewardItem;
public void addPlayer(Player player)
{
_players.add(player);
}
public void removePlayer(Player player)
{
_players.remove(player);
}
public Set<Player> getPlayers()
{
return _players;
}
public void removeParticipant(Player player)
{
_players.remove(player);
}
public boolean isPlayerParticipant(Player player)
{
return _players.contains(player);
}
public int getMinimalLevel()
{
return _minimalLevel;
}
public int getCurrentProgress()
{
return _currProgress;
}
public int getCurrentState()
{
return _currState;
}
public ItemHolder getConsolation()
{
return _consolation;
}
public int getCurrRewardItem()
{
return _rewardItem.getId();
}
public boolean isRunning()
{
return _isRunning;
}
public int getTime()
{
return Calendar.getInstance().get(Calendar.MINUTE) * 60; // client makes 3600 - time
}
protected BalthusEventManager()
{
load();
final long currentTime = Chronos.currentTimeMillis();
final Calendar calendar = Calendar.getInstance();
final long hours = calendar.get(Calendar.HOUR_OF_DAY);
final long mins = calendar.get(Calendar.MINUTE);
long startDelay;
if (mins <= 11)
{
calendar.set(Calendar.MINUTE, 12);
calendar.set(Calendar.SECOND, 0);
startDelay = calendar.getTimeInMillis() - currentTime;
_currProgress = 20;
_avoidMinutesIssue = 1;
}
else if (mins <= 23)
{
calendar.set(Calendar.MINUTE, 24);
calendar.set(Calendar.SECOND, 0);
startDelay = calendar.getTimeInMillis() - currentTime;
_currProgress = 40;
_avoidMinutesIssue = 2;
}
else if (mins <= 35)
{
calendar.set(Calendar.MINUTE, 36);
calendar.set(Calendar.SECOND, 0);
startDelay = calendar.getTimeInMillis() - currentTime;
_currProgress = 60;
_avoidMinutesIssue = 3;
}
else if (mins <= 47)
{
calendar.set(Calendar.MINUTE, 48);
calendar.set(Calendar.SECOND, 0);
startDelay = calendar.getTimeInMillis() - currentTime;
_currProgress = 80;
_avoidMinutesIssue = 4;
}
else
{
calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) + 1);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
startDelay = calendar.getTimeInMillis() - currentTime;
_currProgress = 100;
_avoidMinutesIssue = 5;
}
if (((hours > 11) && (hours < 23)) || (hours == 23))
{
_currState = (int) hours - 11;
}
else
{
_currState = (int) hours + 13;
}
getNewRewardItem();
ThreadPool.scheduleAtFixedRate(this::tryToGetWinner, startDelay, 720000);
}
@Override
public synchronized void load()
{
_templates.clear();
parseDatapackFile("data/scripts/events/BalthusFestival/rewards.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _templates.size() + " rewards.");
}
@Override
public void parseDocument(Document doc, File f)
{
final AtomicInteger i = new AtomicInteger();
forEach(doc, "list", listNode ->
{
final StatSet set = new StatSet(parseAttributes(listNode));
if (_minimalLevel == 0)
{
_isEasyMode = set.getBoolean("easyMode", false);
_minimalLevel = set.getInt("minLevel", 85);
_consolation = new ItemHolder(set.getInt("id", 49783), set.getInt("count", 100));
_mailSubject = set.getString("mailSubject", "Balthus Knight Lottery");
_mailContent = set.getString("mailContent", "You win reward in Balthus Event!");
}
forEach(listNode, "reward", reward ->
{
final AtomicInteger j = new AtomicInteger();
final Map<Integer, Map<ItemChanceHolder, Double>> tempRewardList = new HashMap<>();
final Map<Integer, Integer> rewardTime = new HashMap<>();
final StatSet rewardSet = new StatSet(parseAttributes(reward));
rewardTime.put(rewardSet.getInt("from"), rewardSet.getInt("to", rewardSet.getInt("from")));
forEach(reward, "items", itemNode ->
{
forEach(itemNode, "item", item ->
{
final Map<ItemChanceHolder, Double> tempChanceRewardList = new HashMap<>();
j.getAndIncrement();
final StatSet itemSet = new StatSet(parseAttributes(item));
ItemChanceHolder itemChanceHolder = new ItemChanceHolder(itemSet.getInt("id", 57), itemSet.getDouble("chance", 100), itemSet.getInt("count", 100));
tempChanceRewardList.put(itemChanceHolder, itemSet.getDouble("lotteryChance", 0.0));
tempRewardList.put(j.intValue(), tempChanceRewardList);
});
i.getAndIncrement();
_templates.put(i.intValue(), new BalthusEventHolder(rewardTime, tempRewardList));
});
});
});
}
private void tryToGetWinner()
{
_avoidMinutesIssue++;
if (_isRunning && (_avoidMinutesIssue != 6))
{
return;
}
final int random = Rnd.get(100);
if (!_isRunning && (random >= _rewardItem.getChance()) && !_players.isEmpty())
{
final List<Player> playerList = new ArrayList<>(_players);
Collections.shuffle(playerList);
for (Player player : playerList)
{
if (player.getLevel() >= getMinimalLevel())
{
_winner = player;
}
}
if (_winner != null)
{
LOGGER.info(getClass().getSimpleName() + ": New winner for " + _currState + " of Balthus Event is " + _winner.getName() + " - " + _winner.getObjectId() + ". Player win " + new Item(_rewardItem.getId()).getItemName() + " - " + _rewardItem.getId() + " count: " + _rewardItem.getCount() + ".");
Broadcast.toAllOnlinePlayers(new ExBalthusEventJackpotUser());
Broadcast.toAllOnlinePlayers(new SystemMessage(SystemMessageId.S1_HAS_OBTAINED_S2_FROM_THE_FESTIVAL_FAIRY).addPcName(_winner).addItemName(_rewardItem.getId()));
_isRunning = true;
sendConsolationItemsToAll();
sendRewardToPlayer(_winner);
}
else
{
_currProgress += 20;
}
}
else
{
_currProgress += 20;
}
if (_avoidMinutesIssue == 6)
{
resetCurrentStage();
}
for (Player player : World.getInstance().getPlayers())
{
player.sendPacket(new ExBalthusEvent(player));
}
}
private void resetCurrentStage()
{
_currState += 1;
_winner = null;
if (_currState == 25)
{
_currState = 1;
}
_currProgress = 20;
if (!_isRunning && _isEasyMode)
{
sendConsolationItemsToAll();
}
_isRunning = false;
_rewardItem = null;
_avoidMinutesIssue = 1;
getNewRewardItem();
}
private void sendConsolationItemsToAll()
{
for (Player player : _players)
{
if (player == _winner)
{
continue;
}
player.getVariables().set(PlayerVariables.BALTHUS_REWARD, player.getVariables().getInt(PlayerVariables.BALTHUS_REWARD, 0) + _consolation.getCount());
player.sendPacket(new SystemMessage(SystemMessageId.YOU_VE_OBTAINED_S1_FAIRY_S_LUCKY_COINS).addInt((int) _consolation.getCount()));
}
}
private void getNewRewardItem()
{
while (_rewardItem == null)
{
for (BalthusEventHolder holder : _templates.values())
{
if (holder.getRewardTime() == null)
{
continue;
}
final Map<Integer, Integer> rewardTime = holder.getRewardTime();
final int firstParam = rewardTime.keySet().iterator().hasNext() ? rewardTime.keySet().iterator().next() : 0;
final Calendar calendar = Calendar.getInstance();
if ((firstParam <= calendar.get(Calendar.HOUR_OF_DAY)) && (calendar.get(Calendar.HOUR_OF_DAY) <= rewardTime.get(firstParam)))
{
final double random = Rnd.get(100d);
double chance = 0;
for (Map<ItemChanceHolder, Double> map : holder.getRewardList().values())
{
for (Entry<ItemChanceHolder, Double> entry : map.entrySet())
{
chance += entry.getValue();
if (chance >= random)
{
_rewardItem = entry.getKey();
LOGGER.info(getClass().getSimpleName() + ": Reward for " + _currState + " stage set. Next reward item is " + new Item(_rewardItem.getId()).getItemName() + " - " + _rewardItem.getId() + " count: " + _rewardItem.getCount() + ".");
break;
}
}
if (_rewardItem != null)
{
break;
}
}
}
}
}
}
private void sendRewardToPlayer(Player player)
{
final Message msg = new Message(player.getObjectId(), _mailSubject, _mailContent, MailType.NEWS_INFORMER);
final Mail attachments = msg.createAttachments();
attachments.addItem("Balthus Knight Lottery", _rewardItem.getId(), _rewardItem.getCount(), null, null);
MailManager.getInstance().sendMessage(msg);
}
public static class BalthusEventHolder
{
// From hour to hour.
private final Map<Integer, Integer> _rewardTime;
// Time reward - Reward item, chance to put in lottery.
private final Map<Integer, Map<ItemChanceHolder, Double>> _rewardList;
public BalthusEventHolder(Map<Integer, Integer> rewardTime, Map<Integer, Map<ItemChanceHolder, Double>> rewardList)
{
_rewardTime = rewardTime;
_rewardList = rewardList;
}
public Map<Integer, Integer> getRewardTime()
{
return _rewardTime;
}
public Map<Integer, Map<ItemChanceHolder, Double>> getRewardList()
{
return _rewardList;
}
}
public static BalthusEventManager getInstance()
{
return SingletonHolder.INSTANCE;
}
private static class SingletonHolder
{
protected static final BalthusEventManager INSTANCE = new BalthusEventManager();
}
}

View File

@@ -63,6 +63,7 @@ public class PlayerVariables extends AbstractVariables
public static final String CLAN_CONTRIBUTION = "CLAN_CONTRIBUTION";
public static final String CLAN_CONTRIBUTION_TOTAL = "CLAN_CONTRIBUTION_TOTAL";
public static final String CLAN_CONTRIBUTION_REWARDED = "CLAN_CONTRIBUTION_REWARDED";
public static final String BALTHUS_REWARD = "BALTHUS_REWARD";
public static final String AUTO_USE_SETTINGS = "AUTO_USE_SETTINGS";
public static final String AUTO_USE_SHORTCUTS = "AUTO_USE_SHORTCUTS";
public static final String HUNTING_ZONE_ENTRY = "HUNTING_ZONE_ENTRY_";

View File

@@ -48,6 +48,7 @@ import org.l2jmobius.gameserver.network.clientpackets.attributechange.SendChange
import org.l2jmobius.gameserver.network.clientpackets.autoplay.ExAutoPlaySetting;
import org.l2jmobius.gameserver.network.clientpackets.autoplay.ExRequestActivateAutoShortcut;
import org.l2jmobius.gameserver.network.clientpackets.awakening.RequestCallToChangeClass;
import org.l2jmobius.gameserver.network.clientpackets.balthusevent.RequestEventBalthusToken;
import org.l2jmobius.gameserver.network.clientpackets.ceremonyofchaos.RequestCancelCuriousHouse;
import org.l2jmobius.gameserver.network.clientpackets.ceremonyofchaos.RequestCuriousHouseHtml;
import org.l2jmobius.gameserver.network.clientpackets.ceremonyofchaos.RequestJoinCuriousHouse;
@@ -455,7 +456,7 @@ public enum ExIncomingPackets implements IIncomingPackets<GameClient>
REQUEST_CHECK_AGIT_DECO_AVAILABILITY(0x117, null, ConnectionState.IN_GAME),
REQUEST_USER_FACTION_INFO(0x118, RequestUserFactionInfo::new, ConnectionState.IN_GAME),
EX_EXIT_ARENA(0x119, null, ConnectionState.IN_GAME),
REQUEST_EVENT_BALTHUS_TOKEN(0x11A, null, ConnectionState.IN_GAME),
REQUEST_EVENT_BALTHUS_TOKEN(0x11A, RequestEventBalthusToken::new, ConnectionState.IN_GAME),
REQUEST_PARTY_MATCHING_HISTORY(0x11B, null, ConnectionState.IN_GAME),
EX_ARENA_CUSTOM_NOTIFICATION(0x11C, null, ConnectionState.IN_GAME),
REQUEST_TODO_LIST(0x11D, null, ConnectionState.IN_GAME),

View File

@@ -0,0 +1,63 @@
/*
* 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.network.clientpackets.balthusevent;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.instancemanager.events.BalthusEventManager;
import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.model.variables.PlayerVariables;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.SystemMessageId;
import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import org.l2jmobius.gameserver.network.serverpackets.balthusevent.ExBalthusEvent;
/**
* @author Index
*/
public class RequestEventBalthusToken implements IClientIncomingPacket
{
@Override
public boolean read(GameClient client, PacketReader packet)
{
return true;
}
@Override
public void run(GameClient client)
{
final Player player = client.getPlayer();
if (player == null)
{
return;
}
final int count = player.getVariables().getInt(PlayerVariables.BALTHUS_REWARD, 0);
if (count != 0)
{
if (player.addItem("Balthus Consolation Item", BalthusEventManager.getInstance().getConsolation().getId(), count, player, true) != null)
{
player.getVariables().set(PlayerVariables.BALTHUS_REWARD, 0);
player.sendPacket(new ExBalthusEvent(player));
}
}
else
{
player.sendPacket(new SystemMessage(SystemMessageId.NO_FAIRY_S_LUCKY_COINS_AVAILABLE));
}
}
}

View File

@@ -0,0 +1,54 @@
/*
* 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.network.serverpackets.balthusevent;
import org.l2jmobius.commons.network.PacketWriter;
import org.l2jmobius.gameserver.instancemanager.events.BalthusEventManager;
import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.model.variables.PlayerVariables;
import org.l2jmobius.gameserver.network.OutgoingPackets;
import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
/**
* Consolation prize changing in SysTextures/ui6.ugx file "RewardClip.as" -> configUI -> this.tokenItemID = 49783;
* @author Index
*/
public class ExBalthusEvent implements IClientOutgoingPacket
{
private final Player _player;
public ExBalthusEvent(Player player)
{
_player = player;
}
@Override
public boolean write(PacketWriter packet)
{
OutgoingPackets.EX_BALTHUS_EVENT.writeId(packet);
packet.writeD(BalthusEventManager.getInstance().getCurrentState()); // CurrentState (max 24, because 1 state going 1 hour)
packet.writeD(BalthusEventManager.getInstance().getCurrentProgress()); // Progress
packet.writeD(BalthusEventManager.getInstance().getCurrRewardItem()); // CurrentRewardItem (current event item, what can be rewarded)
packet.writeD(_player.getVariables().getInt(PlayerVariables.BALTHUS_REWARD, 0)); // RewardTokenCount (current items for withdraw (available rewards))
packet.writeD((int) BalthusEventManager.getInstance().getConsolation().getCount()); // CurrentTokenCount (current count of "consolation prize")
packet.writeD(BalthusEventManager.getInstance().isPlayerParticipant(_player) ? 1 : 0); // Participated (player in event?)
packet.writeC(BalthusEventManager.getInstance().isRunning() ? 0 : 1); // Running (0 - already someone get this reward ? / 1 - item can be rewarded)
packet.writeD(BalthusEventManager.getInstance().getTime()); // Time (in seconds)
return true;
}
}

View File

@@ -0,0 +1,36 @@
/*
* 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.network.serverpackets.balthusevent;
import org.l2jmobius.commons.network.PacketWriter;
import org.l2jmobius.gameserver.network.OutgoingPackets;
import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
/**
* @author Index
*/
public class ExBalthusEventJackpotUser implements IClientOutgoingPacket
{
public static final ExBalthusEventJackpotUser STATIC_PACKET = new ExBalthusEventJackpotUser();
@Override
public boolean write(PacketWriter packet)
{
OutgoingPackets.EX_BALTHUS_EVENT_JACKPOT_USER.writeId(packet);
return true;
}
}