From fd9a116f811f7b3e55089e4d6ac4642b20779f73 Mon Sep 17 00:00:00 2001
From: MobiusDevelopment <8391001+MobiusDevelopment@users.noreply.github.com>
Date: Wed, 14 Dec 2022 22:25:24 +0000
Subject: [PATCH] Addition of Achievement box. Contributed by Serenitty.
---
.../db_installer/sql/game/achievement_box.sql | 18 +
.../dist/game/config/AchievementBox.ini | 19 +
.../java/org/l2jmobius/Config.java | 14 +
.../gameserver/enums/AchievementBoxState.java | 29 +
.../gameserver/enums/AchievementBoxType.java | 28 +
.../gameserver/model/AchievementBox.java | 539 ++++++++++++++++++
.../org/l2jmobius/gameserver/model/Party.java | 6 +
.../gameserver/model/actor/Attackable.java | 7 +
.../gameserver/model/actor/Player.java | 15 +
.../model/holders/AchievementBoxHolder.java | 62 ++
.../gameserver/network/ExClientPackets.java | 12 +-
.../network/clientpackets/EnterWorld.java | 6 +
.../steadybox/RequestSteadyBoxLoad.java | 41 ++
.../steadybox/RequestSteadyGetReward.java | 48 ++
.../steadybox/RequestSteadyOpenBox.java | 57 ++
.../steadybox/RequestSteadyOpenSlot.java | 49 ++
.../steadybox/ExSteadyAllBoxUpdate.java | 57 ++
.../steadybox/ExSteadyBoxReward.java | 47 ++
.../steadybox/ExSteadyBoxUiInit.java | 97 ++++
.../steadybox/ExSteadyOneBoxUpdate.java | 52 ++
L2J_Mobius_Essence_5.2_FrostLord/readme.txt | 2 +
.../db_installer/sql/game/achievement_box.sql | 18 +
.../dist/game/config/AchievementBox.ini | 19 +
.../java/org/l2jmobius/Config.java | 14 +
.../gameserver/enums/AchievementBoxState.java | 29 +
.../gameserver/enums/AchievementBoxType.java | 28 +
.../gameserver/model/AchievementBox.java | 539 ++++++++++++++++++
.../org/l2jmobius/gameserver/model/Party.java | 6 +
.../gameserver/model/actor/Attackable.java | 7 +
.../gameserver/model/actor/Player.java | 19 +-
.../model/holders/AchievementBoxHolder.java | 62 ++
.../gameserver/network/ExClientPackets.java | 12 +-
.../network/clientpackets/EnterWorld.java | 6 +
.../steadybox/RequestSteadyBoxLoad.java | 41 ++
.../steadybox/RequestSteadyGetReward.java | 48 ++
.../steadybox/RequestSteadyOpenBox.java | 57 ++
.../steadybox/RequestSteadyOpenSlot.java | 49 ++
.../steadybox/ExSteadyAllBoxUpdate.java | 57 ++
.../steadybox/ExSteadyBoxReward.java | 47 ++
.../steadybox/ExSteadyBoxUiInit.java | 97 ++++
.../steadybox/ExSteadyOneBoxUpdate.java | 52 ++
L2J_Mobius_Essence_6.2_Vanguard/readme.txt | 1 +
.../db_installer/sql/game/achievement_box.sql | 18 +
.../dist/game/config/AchievementBox.ini | 19 +
.../java/org/l2jmobius/Config.java | 14 +
.../gameserver/enums/AchievementBoxState.java | 29 +
.../gameserver/enums/AchievementBoxType.java | 28 +
.../gameserver/model/AchievementBox.java | 539 ++++++++++++++++++
.../org/l2jmobius/gameserver/model/Party.java | 6 +
.../gameserver/model/actor/Attackable.java | 7 +
.../gameserver/model/actor/Player.java | 19 +-
.../model/holders/AchievementBoxHolder.java | 62 ++
.../gameserver/network/ExClientPackets.java | 12 +-
.../network/clientpackets/EnterWorld.java | 6 +
.../steadybox/RequestSteadyBoxLoad.java | 41 ++
.../steadybox/RequestSteadyGetReward.java | 48 ++
.../steadybox/RequestSteadyOpenBox.java | 57 ++
.../steadybox/RequestSteadyOpenSlot.java | 49 ++
.../steadybox/ExSteadyAllBoxUpdate.java | 57 ++
.../steadybox/ExSteadyBoxReward.java | 47 ++
.../steadybox/ExSteadyBoxUiInit.java | 97 ++++
.../steadybox/ExSteadyOneBoxUpdate.java | 52 ++
L2J_Mobius_Essence_6.3_Crusader/readme.txt | 1 +
63 files changed, 3607 insertions(+), 14 deletions(-)
create mode 100644 L2J_Mobius_Essence_5.2_FrostLord/dist/db_installer/sql/game/achievement_box.sql
create mode 100644 L2J_Mobius_Essence_5.2_FrostLord/dist/game/config/AchievementBox.ini
create mode 100644 L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/enums/AchievementBoxState.java
create mode 100644 L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/enums/AchievementBoxType.java
create mode 100644 L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/AchievementBox.java
create mode 100644 L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/holders/AchievementBoxHolder.java
create mode 100644 L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyBoxLoad.java
create mode 100644 L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyGetReward.java
create mode 100644 L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyOpenBox.java
create mode 100644 L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyOpenSlot.java
create mode 100644 L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyAllBoxUpdate.java
create mode 100644 L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyBoxReward.java
create mode 100644 L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyBoxUiInit.java
create mode 100644 L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyOneBoxUpdate.java
create mode 100644 L2J_Mobius_Essence_6.2_Vanguard/dist/db_installer/sql/game/achievement_box.sql
create mode 100644 L2J_Mobius_Essence_6.2_Vanguard/dist/game/config/AchievementBox.ini
create mode 100644 L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/enums/AchievementBoxState.java
create mode 100644 L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/enums/AchievementBoxType.java
create mode 100644 L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/AchievementBox.java
create mode 100644 L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/holders/AchievementBoxHolder.java
create mode 100644 L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyBoxLoad.java
create mode 100644 L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyGetReward.java
create mode 100644 L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyOpenBox.java
create mode 100644 L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyOpenSlot.java
create mode 100644 L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyAllBoxUpdate.java
create mode 100644 L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyBoxReward.java
create mode 100644 L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyBoxUiInit.java
create mode 100644 L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyOneBoxUpdate.java
create mode 100644 L2J_Mobius_Essence_6.3_Crusader/dist/db_installer/sql/game/achievement_box.sql
create mode 100644 L2J_Mobius_Essence_6.3_Crusader/dist/game/config/AchievementBox.ini
create mode 100644 L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/enums/AchievementBoxState.java
create mode 100644 L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/enums/AchievementBoxType.java
create mode 100644 L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/model/AchievementBox.java
create mode 100644 L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/model/holders/AchievementBoxHolder.java
create mode 100644 L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyBoxLoad.java
create mode 100644 L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyGetReward.java
create mode 100644 L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyOpenBox.java
create mode 100644 L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyOpenSlot.java
create mode 100644 L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyAllBoxUpdate.java
create mode 100644 L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyBoxReward.java
create mode 100644 L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyBoxUiInit.java
create mode 100644 L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyOneBoxUpdate.java
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/dist/db_installer/sql/game/achievement_box.sql b/L2J_Mobius_Essence_5.2_FrostLord/dist/db_installer/sql/game/achievement_box.sql
new file mode 100644
index 0000000000..a6750eef4c
--- /dev/null
+++ b/L2J_Mobius_Essence_5.2_FrostLord/dist/db_installer/sql/game/achievement_box.sql
@@ -0,0 +1,18 @@
+DROP TABLE IF EXISTS `achievement_box`;
+CREATE TABLE IF NOT EXISTS `achievement_box` (
+`charId` INT,
+`box_owned` INT NOT NULL DEFAULT 1,
+`monster_point` INT NOT NULL DEFAULT 0,
+`pvp_point` INT NOT NULL DEFAULT 0,
+`pending_box` INT NOT NULL DEFAULT 0,
+`open_time` BIGINT UNSIGNED NOT NULL DEFAULT 0,
+`box_state_slot_1` INT NOT NULL DEFAULT 1,
+`boxtype_slot_1` INT NOT NULL DEFAULT 0,
+`box_state_slot_2` INT NOT NULL DEFAULT 0,
+`boxtype_slot_2` INT NOT NULL DEFAULT 0,
+`box_state_slot_3` INT NOT NULL DEFAULT 0,
+`boxtype_slot_3` INT NOT NULL DEFAULT 0,
+`box_state_slot_4` INT NOT NULL DEFAULT 0,
+`boxtype_slot_4` INT NOT NULL DEFAULT 0,
+PRIMARY KEY (`charId`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/dist/game/config/AchievementBox.ini b/L2J_Mobius_Essence_5.2_FrostLord/dist/game/config/AchievementBox.ini
new file mode 100644
index 0000000000..fadac51262
--- /dev/null
+++ b/L2J_Mobius_Essence_5.2_FrostLord/dist/game/config/AchievementBox.ini
@@ -0,0 +1,19 @@
+# --------------------------------------------------------------------------
+# Achievement Box Settings
+# --------------------------------------------------------------------------
+
+EnabledAchievementBox = False
+
+# Amount of mobs killed.
+# Retail is 1000.
+PointsForReward = 1000
+
+# --------------------------------------------------------------------------
+# Achievement Box PVP Settings
+# --------------------------------------------------------------------------
+
+EnabledAchievementPvP = False
+
+# Amount of Players killed.
+# Retail is 5.
+PointsForPvpReward = 5
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/Config.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/Config.java
index 5b15fec15d..2477c594ce 100644
--- a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/Config.java
+++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/Config.java
@@ -103,6 +103,7 @@ public class Config
private static final String GENERAL_CONFIG_FILE = "./config/General.ini";
private static final String GRACIASEEDS_CONFIG_FILE = "./config/GraciaSeeds.ini";
private static final String GRANDBOSS_CONFIG_FILE = "./config/GrandBoss.ini";
+ private static final String ACHIEVEMENT_BOX_CONFIG_FILE = "./config/AchievementBox.ini";
private static final String LOGIN_CONFIG_FILE = "./config/LoginServer.ini";
private static final String NPC_CONFIG_FILE = "./config/NPC.ini";
private static final String PVP_CONFIG_FILE = "./config/PVP.ini";
@@ -935,6 +936,12 @@ public class Config
public static int RANDOM_CRAFT_CREATE_FEE;
public static boolean DROP_RANDOM_CRAFT_MATERIALS;
+ // Achivement Box
+ public static boolean ENABLE_ACHIEVEMENT_BOX;
+ public static int ACHIEVEMENT_BOX_POINTS_FOR_REWARD;
+ public static boolean ENABLE_ACHIEVEMENT_PVP;
+ public static int ACHIEVEMENT_BOX_PVP_POINTS_FOR_REWARD;
+
// GrandBoss Settings
// Antharas
@@ -2653,6 +2660,13 @@ public class Config
ZAKEN_SPAWN_INTERVAL = grandBossConfig.getInt("IntervalOfZakenSpawn", 168);
ZAKEN_SPAWN_RANDOM = grandBossConfig.getInt("RandomOfZakenSpawn", 48);
+ // Load ArchivementBox (if exists)
+ final PropertiesParser achievementBoxConfig = new PropertiesParser(ACHIEVEMENT_BOX_CONFIG_FILE);
+ ENABLE_ACHIEVEMENT_BOX = achievementBoxConfig.getBoolean("EnabledAchievementBox", true);
+ ACHIEVEMENT_BOX_POINTS_FOR_REWARD = achievementBoxConfig.getInt("PointsForReward", 1000);
+ ENABLE_ACHIEVEMENT_PVP = achievementBoxConfig.getBoolean("EnabledAchievementPvP", true);
+ ACHIEVEMENT_BOX_PVP_POINTS_FOR_REWARD = achievementBoxConfig.getInt("PointsForPvpReward", 5);
+
// Gracia Seeds
final PropertiesParser graciaSeedsConfig = new PropertiesParser(GRACIASEEDS_CONFIG_FILE);
SOD_TIAT_KILL_COUNT = graciaSeedsConfig.getInt("TiatKillCountForNextState", 10);
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/enums/AchievementBoxState.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/enums/AchievementBoxState.java
new file mode 100644
index 0000000000..671455dfb8
--- /dev/null
+++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/enums/AchievementBoxState.java
@@ -0,0 +1,29 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.enums;
+
+/**
+ * @author Serenitty
+ */
+public enum AchievementBoxState
+{
+ LOCKED,
+ AVAILABLE,
+ OPEN,
+ UNLOCK_IN_PROGRESS,
+ RECEIVE_REWARD
+}
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/enums/AchievementBoxType.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/enums/AchievementBoxType.java
new file mode 100644
index 0000000000..aabe5ce5b9
--- /dev/null
+++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/enums/AchievementBoxType.java
@@ -0,0 +1,28 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.enums;
+
+/**
+ * @author Serenitty
+ */
+public enum AchievementBoxType
+{
+ LOCKED,
+ BOX_2H,
+ BOX_6H,
+ BOX_12H;
+}
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/AchievementBox.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/AchievementBox.java
new file mode 100644
index 0000000000..9f7d29d0e4
--- /dev/null
+++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/AchievementBox.java
@@ -0,0 +1,539 @@
+package org.l2jmobius.gameserver.model;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+import java.util.concurrent.ScheduledFuture;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.database.DatabaseFactory;
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.commons.util.Rnd;
+import org.l2jmobius.gameserver.enums.AchievementBoxState;
+import org.l2jmobius.gameserver.enums.AchievementBoxType;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.holders.AchievementBoxHolder;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import org.l2jmobius.gameserver.network.serverpackets.steadybox.ExSteadyAllBoxUpdate;
+import org.l2jmobius.gameserver.network.serverpackets.steadybox.ExSteadyBoxReward;
+
+/**
+ * @author Serenitty, nlyyn, MacuK, Rudelitobr
+ */
+public class AchievementBox
+{
+ private static final Logger LOGGER = Logger.getLogger(AchievementBox.class.getName());
+
+ private static final int ACHIEVEMENT_BOX_2H = 7200000;
+ private static final int ACHIEVEMENT_BOX_6H = 21600000;
+ private static final int ACHIEVEMENT_BOX_12H = 43200000;
+
+ private final Player _owner;
+ private int _boxOwned = 1;
+ private int _monsterPoints = 0;
+ private int _pvpPoints = 0;
+ private int _pendingBoxSlotId = 0;
+ private int _pvpEndDate;
+ private long _boxTimeForOpen;
+ private final List _achievementBox = new ArrayList<>();
+ private ScheduledFuture> _boxOpenTask;
+
+ public AchievementBox(Player owner)
+ {
+ _owner = owner;
+ }
+
+ public int pvpEndDate()
+ {
+ return _pvpEndDate;
+ }
+
+ public void addPoints(int value)
+ {
+ final int newPoints = Math.min(Config.ACHIEVEMENT_BOX_POINTS_FOR_REWARD, _monsterPoints + value);
+ if (newPoints >= Config.ACHIEVEMENT_BOX_POINTS_FOR_REWARD)
+ {
+ if (addNewBox())
+ {
+ _monsterPoints = 0;
+ }
+ else
+ {
+ _monsterPoints = Config.ACHIEVEMENT_BOX_POINTS_FOR_REWARD;
+ }
+ return;
+ }
+ _monsterPoints += value;
+ }
+
+ public void addPvpPoints(int value)
+ {
+ final int newPoints = Math.min(Config.ACHIEVEMENT_BOX_PVP_POINTS_FOR_REWARD, _pvpPoints);
+ while (newPoints >= Config.ACHIEVEMENT_BOX_PVP_POINTS_FOR_REWARD)
+ {
+ if (addNewBox())
+ {
+ _pvpPoints = 0;
+ }
+ else
+ {
+ _pvpPoints = Config.ACHIEVEMENT_BOX_PVP_POINTS_FOR_REWARD;
+ }
+ return;
+ }
+ _pvpPoints += value;
+ }
+
+ public void restore()
+ {
+ tryFinishBox();
+ refreshPvpEndDate();
+ try (Connection con = DatabaseFactory.getConnection();
+ PreparedStatement ps = con.prepareStatement("SELECT * FROM achievement_box WHERE charId=?"))
+ {
+ ps.setInt(1, _owner.getObjectId());
+ try (ResultSet rs = ps.executeQuery())
+ {
+ if (rs.next())
+ {
+ try
+ {
+ _boxOwned = rs.getInt("box_owned");
+ _monsterPoints = rs.getInt("monster_point");
+ _pvpPoints = rs.getInt("pvp_point");
+ _pendingBoxSlotId = rs.getInt("pending_box");
+ _boxTimeForOpen = rs.getLong("open_time");
+ for (int i = 1; i <= 4; i++)
+ {
+ int state = rs.getInt("box_state_slot_" + i);
+ int type = rs.getInt("boxtype_slot_" + i);
+ if ((i == 1) && (state == 0))
+ {
+ state = 1;
+ }
+ final AchievementBoxHolder holder = new AchievementBoxHolder(i, state, type);
+ _achievementBox.add(i - 1, holder);
+ }
+ }
+ catch (Exception e)
+ {
+ LOGGER.warning("Could not restore Achievement box for " + _owner);
+ }
+ }
+ else
+ {
+ storeNew();
+ _achievementBox.add(0, new AchievementBoxHolder(1, 1, 0));
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ LOGGER.log(Level.WARNING, "Could not restore achievement box for " + _owner, e);
+ }
+ }
+
+ public void storeNew()
+ {
+ try (Connection con = DatabaseFactory.getConnection();
+ PreparedStatement ps = con.prepareStatement("INSERT INTO achievement_box VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?)"))
+ {
+ ps.setInt(1, _owner.getObjectId());
+ ps.setInt(2, _boxOwned);
+ ps.setInt(3, _monsterPoints);
+ ps.setInt(4, _pvpPoints);
+ ps.setInt(5, _pendingBoxSlotId);
+ ps.setLong(6, _boxTimeForOpen);
+ for (int i = 0; i < 4; i++)
+ {
+ ps.setInt(7 + (i * 2), 0);
+ ps.setInt(8 + (i * 2), 0);
+ }
+ ps.executeUpdate();
+ }
+ catch (SQLException e)
+ {
+ LOGGER.warning("Could not store new Archivement Box for: " + _owner);
+ LOGGER.warning(CommonUtil.getStackTrace(e));
+ }
+ }
+
+ public void store()
+ {
+ try (Connection con = DatabaseFactory.getConnection();
+ PreparedStatement ps = con.prepareStatement("UPDATE achievement_box SET box_owned=?,monster_point=?,pvp_point=?,pending_box=?,open_time=?,box_state_slot_1=?,boxtype_slot_1=?,box_state_slot_2=?,boxtype_slot_2=?,box_state_slot_3=?,boxtype_slot_3=?,box_state_slot_4=?,boxtype_slot_4=? WHERE charId=?"))
+ {
+ ps.setInt(1, getBoxOwned());
+ ps.setInt(2, getMonsterPoints());
+ ps.setInt(3, getPvpPoints());
+ ps.setInt(4, getPendingBoxSlotId());
+ ps.setLong(5, getBoxOpenTime());
+ for (int i = 0; i < 4; i++)
+ {
+ if (_achievementBox.size() >= (i + 1))
+ {
+ AchievementBoxHolder holder = _achievementBox.get(i);
+ ps.setInt(6 + (i * 2), holder == null ? 0 : holder.getState().ordinal());
+ ps.setInt(7 + (i * 2), holder == null ? 0 : holder.getType().ordinal());
+ }
+ else
+ {
+ ps.setInt(6 + (i * 2), 0);
+ ps.setInt(7 + (i * 2), 0);
+ }
+ }
+ ps.setInt(14, _owner.getObjectId());
+ ps.execute();
+ }
+ catch (SQLException e)
+ {
+ LOGGER.log(Level.SEVERE, "Could not store Achievement Box for: " + _owner, e);
+ }
+ }
+
+ public List getAchievementBox()
+ {
+ return _achievementBox;
+ }
+
+ public boolean addNewBox()
+ {
+ AchievementBoxHolder free = null;
+ int id = -1;
+ for (int i = 1; i <= getBoxOwned(); i++)
+ {
+ final AchievementBoxHolder holder = getAchievementBox().get(i - 1);
+ if (holder.getState() == AchievementBoxState.AVAILABLE)
+ {
+ free = holder;
+ id = i;
+ break;
+ }
+ }
+ if (free != null)
+ {
+ int rnd = Rnd.get(0, 100);
+ free.setType(rnd < 12 ? AchievementBoxType.BOX_12H : rnd < 40 ? AchievementBoxType.BOX_6H : AchievementBoxType.BOX_2H);
+ switch (free.getType())
+ {
+ case BOX_2H:
+ case BOX_6H:
+ case BOX_12H:
+ {
+ free.setState(AchievementBoxState.OPEN);
+ getAchievementBox().remove(id - 1);
+ getAchievementBox().add(id - 1, free);
+ sendBoxUpdate();
+ break;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public void openBox(int slotId)
+ {
+ if (slotId > getBoxOwned())
+ {
+ return;
+ }
+
+ final AchievementBoxHolder holder = getAchievementBox().get(slotId - 1);
+ if ((holder == null) || (_boxTimeForOpen != 0))
+ {
+ return;
+ }
+
+ _pendingBoxSlotId = slotId;
+
+ switch (holder.getType())
+ {
+ case BOX_2H:
+ {
+ setBoxTimeForOpen(ACHIEVEMENT_BOX_2H);
+ holder.setState(AchievementBoxState.UNLOCK_IN_PROGRESS);
+ getAchievementBox().remove(slotId - 1);
+ getAchievementBox().add(slotId - 1, holder);
+ sendBoxUpdate();
+ break;
+ }
+ case BOX_6H:
+ {
+ setBoxTimeForOpen(ACHIEVEMENT_BOX_6H);
+ holder.setState(AchievementBoxState.UNLOCK_IN_PROGRESS);
+ getAchievementBox().remove(slotId - 1);
+ getAchievementBox().add(slotId - 1, holder);
+ sendBoxUpdate();
+ break;
+ }
+ case BOX_12H:
+ {
+ setBoxTimeForOpen(ACHIEVEMENT_BOX_12H);
+ holder.setState(AchievementBoxState.UNLOCK_IN_PROGRESS);
+ getAchievementBox().remove(slotId - 1);
+ getAchievementBox().add(slotId - 1, holder);
+ sendBoxUpdate();
+ break;
+ }
+ }
+ }
+
+ public void skipBoxOpenTime(int slotId, long fee)
+ {
+ if (slotId > getBoxOwned())
+ {
+ return;
+ }
+
+ final AchievementBoxHolder holder = getAchievementBox().get(slotId - 1);
+ if ((holder != null) && _owner.destroyItemByItemId("Take Achievement Box", Inventory.LCOIN_ID, fee, _owner, true))
+ {
+ if (_pendingBoxSlotId == slotId)
+ {
+ cancelTask();
+ }
+ finishAndUnlockChest(slotId);
+ }
+ }
+
+ public boolean setBoxTimeForOpen(long time)
+ {
+ if ((_boxOpenTask != null) && !(_boxOpenTask.isDone() || _boxOpenTask.isCancelled()))
+ {
+ return false;
+ }
+
+ _boxTimeForOpen = System.currentTimeMillis() + time;
+ return true;
+ }
+
+ public void tryFinishBox()
+ {
+ if ((_boxTimeForOpen == 0) || (_boxTimeForOpen >= System.currentTimeMillis()))
+ {
+ return;
+ }
+
+ if ((_owner == null) || !_owner.isOnline())
+ {
+ return;
+ }
+
+ final AchievementBoxHolder holder = getAchievementBox().get(_pendingBoxSlotId - 1);
+ if (holder != null)
+ {
+ finishAndUnlockChest(_pendingBoxSlotId);
+ }
+ }
+
+ public int getBoxOwned()
+ {
+ return _boxOwned;
+ }
+
+ public int getMonsterPoints()
+ {
+ return _monsterPoints;
+ }
+
+ public int getPvpPoints()
+ {
+ return _pvpPoints;
+ }
+
+ public int getPendingBoxSlotId()
+ {
+ return _pendingBoxSlotId;
+ }
+
+ public long getBoxOpenTime()
+ {
+ return _boxTimeForOpen;
+ }
+
+ public void finishAndUnlockChest(int id)
+ {
+ if (id > getBoxOwned())
+ {
+ return;
+ }
+
+ if (_pendingBoxSlotId == id)
+ {
+ _boxTimeForOpen = 0;
+ _pendingBoxSlotId = 0;
+ }
+
+ getAchievementBox().get(id - 1).setState(AchievementBoxState.RECEIVE_REWARD);
+ sendBoxUpdate();
+ }
+
+ public void sendBoxUpdate()
+ {
+ _owner.sendPacket(new ExSteadyAllBoxUpdate(_owner));
+ }
+
+ public void cancelTask()
+ {
+ if (_boxOpenTask == null)
+ {
+ return;
+ }
+
+ _boxOpenTask.cancel(false);
+ _boxOpenTask = null;
+ }
+
+ public void unlockSlot(int slotId)
+ {
+ if (((slotId - 1) != getBoxOwned()) || (slotId > 4))
+ {
+ return;
+ }
+
+ boolean paidSlot = false;
+ switch (slotId)
+ {
+ case 2:
+ {
+ if (_owner.reduceAdena("Adena " + slotId, 100000000, _owner, true))
+ {
+ paidSlot = true;
+ }
+ break;
+ }
+ case 3:
+ {
+ if (_owner.destroyItemByItemId("L coin " + slotId, Inventory.LCOIN_ID, 2000, _owner, true))
+ {
+ paidSlot = true;
+ }
+ break;
+ }
+ case 4:
+ {
+ if (_owner.destroyItemByItemId("L coin " + slotId, Inventory.LCOIN_ID, 8000, _owner, true))
+ {
+ paidSlot = true;
+ }
+ break;
+ }
+ }
+
+ if (paidSlot)
+ {
+ _boxOwned = slotId;
+ final AchievementBoxHolder holder = new AchievementBoxHolder(slotId, 1, 0);
+ holder.setState(AchievementBoxState.AVAILABLE);
+ holder.setType(AchievementBoxType.LOCKED);
+ getAchievementBox().add(slotId - 1, holder);
+ sendBoxUpdate();
+ }
+ }
+
+ public void getReward(int slotId)
+ {
+ final AchievementBoxHolder holder = getAchievementBox().get(slotId - 1);
+ if (holder.getState() != AchievementBoxState.RECEIVE_REWARD)
+ {
+ return;
+ }
+
+ final int rnd = Rnd.get(100);
+ ItemHolder reward = null;
+ switch (holder.getType())
+ {
+ case BOX_2H:
+ {
+ if (rnd < 3)
+ {
+ reward = new ItemHolder(Rnd.get(72084, 72102), 1);
+ }
+ else if (rnd < 30)
+ {
+ reward = new ItemHolder(93274, 5); // Sayha Cookie
+ }
+ else if (rnd < 70)
+ {
+ reward = new ItemHolder(90907, 250); // Soulshot Ticket
+ }
+ else
+ {
+ reward = new ItemHolder(3031, 50); // Spirit Ore
+ }
+ break;
+ }
+ case BOX_6H:
+ {
+ if (rnd < 10)
+ {
+ reward = new ItemHolder(Rnd.get(72084, 72102), 1);
+ }
+ else if (rnd < 30)
+ {
+ reward = new ItemHolder(93274, 10); // Sayha Cookie
+ }
+ else if (rnd < 70)
+ {
+ reward = new ItemHolder(90907, 500); // Soulshot Ticket
+ }
+ else
+ {
+ reward = new ItemHolder(3031, 100); // Spirit Ore
+ }
+ break;
+ }
+ case BOX_12H:
+ {
+ if (rnd < 20)
+ {
+ reward = new ItemHolder(Rnd.get(72084, 72102), 1);
+ }
+ else if (rnd < 30)
+ {
+ reward = new ItemHolder(93274, 20); // Sayha Cookie
+ }
+ else if (rnd < 70)
+ {
+ reward = new ItemHolder(90907, 1000); // Soulshot Ticket
+ }
+ else
+ {
+ reward = new ItemHolder(3031, 200); // Spirit Ore
+ }
+ break;
+ }
+ }
+
+ holder.setState(AchievementBoxState.AVAILABLE);
+ holder.setType(AchievementBoxType.LOCKED);
+ sendBoxUpdate();
+ if (reward != null)
+ {
+ _owner.addItem("Chest unlock", reward, _owner, true);
+ _owner.sendPacket(new ExSteadyBoxReward(slotId, reward.getId(), reward.getCount()));
+ }
+ }
+
+ public void refreshPvpEndDate()
+ {
+ final long currentTime = System.currentTimeMillis();
+ final Calendar calendar = Calendar.getInstance();
+ calendar.setTimeInMillis(currentTime);
+ calendar.set(Calendar.DAY_OF_MONTH, 1);
+ calendar.set(Calendar.HOUR_OF_DAY, 6);
+ if (calendar.getTimeInMillis() < currentTime)
+ {
+ calendar.add(Calendar.MONTH, 1);
+ }
+ _pvpEndDate = (int) (calendar.getTimeInMillis() / 1000);
+ }
+}
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/Party.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/Party.java
index d887f4f20d..96c9dc24ed 100644
--- a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/Party.java
+++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/Party.java
@@ -887,6 +887,12 @@ public class Party extends AbstractPlayerGroup
member.updateVitalityPoints(target.getVitalityPoints(member.getLevel(), exp, target.isRaid()), true, false);
PcCafePointsManager.getInstance().givePcCafePoint(member, exp);
MagicLampData.getInstance().addLampExp(member, exp, true);
+
+ final AchievementBox box = member.getAchievementBox();
+ if (box != null)
+ {
+ member.getAchievementBox().addPoints(1);
+ }
}
}
else
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/actor/Attackable.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/actor/Attackable.java
index 2fc231663d..501eae8d0e 100644
--- a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/actor/Attackable.java
+++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/actor/Attackable.java
@@ -46,6 +46,7 @@ import org.l2jmobius.gameserver.instancemanager.CursedWeaponsManager;
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
import org.l2jmobius.gameserver.instancemanager.WalkingManager;
import org.l2jmobius.gameserver.instancemanager.events.EventDropManager;
+import org.l2jmobius.gameserver.model.AchievementBox;
import org.l2jmobius.gameserver.model.AggroInfo;
import org.l2jmobius.gameserver.model.CommandChannel;
import org.l2jmobius.gameserver.model.DamageDoneInfo;
@@ -606,6 +607,12 @@ public class Attackable extends Npc
}
PcCafePointsManager.getInstance().givePcCafePoint(attacker, exp);
MagicLampData.getInstance().addLampExp(attacker, exp, true);
+
+ final AchievementBox box = attacker.getAchievementBox();
+ if (box != null)
+ {
+ attacker.getAchievementBox().addPoints(1);
+ }
}
}
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/actor/Player.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/actor/Player.java
index b364ee9cc7..f5ce988dab 100644
--- a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/actor/Player.java
+++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/actor/Player.java
@@ -141,6 +141,7 @@ import org.l2jmobius.gameserver.instancemanager.SellBuffsManager;
import org.l2jmobius.gameserver.instancemanager.SiegeManager;
import org.l2jmobius.gameserver.instancemanager.ZoneManager;
import org.l2jmobius.gameserver.model.AccessLevel;
+import org.l2jmobius.gameserver.model.AchievementBox;
import org.l2jmobius.gameserver.model.ArenaParticipantsHolder;
import org.l2jmobius.gameserver.model.BlockList;
import org.l2jmobius.gameserver.model.ClientSettings;
@@ -945,6 +946,8 @@ public class Player extends Playable
private final Map _purgePoints = new HashMap<>();
+ private final AchievementBox _achivemenetBox;
+
private final Map _petEvolves = new HashMap<>();
private final List _questTimers = new ArrayList<>();
@@ -1237,6 +1240,8 @@ public class Player extends Playable
app.setOwner(this);
_appearance = app;
+ _achivemenetBox = Config.ENABLE_ACHIEVEMENT_BOX ? new AchievementBox(this) : null;
+
// Create an AI
getAI();
@@ -1327,6 +1332,11 @@ public class Player extends Playable
return PlayerTemplateData.getInstance().getTemplate(_baseClass);
}
+ public AchievementBox getAchievementBox()
+ {
+ return _achivemenetBox;
+ }
+
/**
* @return the PlayerTemplate link to the Player.
*/
@@ -7296,6 +7306,11 @@ public class Player extends Playable
{
_randomCraft.store();
}
+
+ if (_achivemenetBox != null)
+ {
+ _achivemenetBox.store();
+ }
}
@Override
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/holders/AchievementBoxHolder.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/holders/AchievementBoxHolder.java
new file mode 100644
index 0000000000..639b3082a8
--- /dev/null
+++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/model/holders/AchievementBoxHolder.java
@@ -0,0 +1,62 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.model.holders;
+
+import org.l2jmobius.gameserver.enums.AchievementBoxState;
+import org.l2jmobius.gameserver.enums.AchievementBoxType;
+
+/**
+ * @author Serenitty
+ */
+public class AchievementBoxHolder
+{
+ private final int _slotId;
+ private AchievementBoxState _boxState;
+ private AchievementBoxType _boxType;
+
+ public AchievementBoxHolder(int slotId, int boxState, int boxType)
+ {
+ _slotId = slotId;
+ _boxState = AchievementBoxState.values()[boxState];
+ _boxType = AchievementBoxType.values()[boxType];
+ }
+
+ public void setState(AchievementBoxState value)
+ {
+ _boxState = value;
+ }
+
+ public AchievementBoxState getState()
+ {
+ return _boxState;
+ }
+
+ public AchievementBoxType getType()
+ {
+ return _boxType;
+ }
+
+ public void setType(AchievementBoxType value)
+ {
+ _boxType = value;
+ }
+
+ public int getSlotId()
+ {
+ return _slotId;
+ }
+}
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/ExClientPackets.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/ExClientPackets.java
index a7f59eec55..95e9d04736 100644
--- a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/ExClientPackets.java
+++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/ExClientPackets.java
@@ -155,6 +155,10 @@ import org.l2jmobius.gameserver.network.clientpackets.shuttle.RequestShuttleGetO
import org.l2jmobius.gameserver.network.clientpackets.shuttle.RequestShuttleGetOn;
import org.l2jmobius.gameserver.network.clientpackets.stats.ExResetStatusBonus;
import org.l2jmobius.gameserver.network.clientpackets.stats.ExSetStatusBonus;
+import org.l2jmobius.gameserver.network.clientpackets.steadybox.RequestSteadyBoxLoad;
+import org.l2jmobius.gameserver.network.clientpackets.steadybox.RequestSteadyGetReward;
+import org.l2jmobius.gameserver.network.clientpackets.steadybox.RequestSteadyOpenBox;
+import org.l2jmobius.gameserver.network.clientpackets.steadybox.RequestSteadyOpenSlot;
import org.l2jmobius.gameserver.network.clientpackets.subjugation.RequestSubjugationGacha;
import org.l2jmobius.gameserver.network.clientpackets.subjugation.RequestSubjugationGachaUI;
import org.l2jmobius.gameserver.network.clientpackets.subjugation.RequestSubjugationList;
@@ -648,10 +652,10 @@ public enum ExClientPackets
EX_RANKING_FESTIVAL_MY_RECEIVED_BONUS(0x1D1, null, ConnectionState.IN_GAME),
EX_RANKING_FESTIVAL_REWARD(0x1D2, null, ConnectionState.IN_GAME),
EX_TIMER_CHECK(0x1D3, null, ConnectionState.IN_GAME),
- EX_STEADY_BOX_LOAD(0x1D4, null, ConnectionState.IN_GAME),
- EX_STEADY_OPEN_SLOT(0x1D5, null, ConnectionState.IN_GAME),
- EX_STEADY_OPEN_BOX(0x1D6, null, ConnectionState.IN_GAME),
- EX_STEADY_GET_REWARD(0x1D7, null, ConnectionState.IN_GAME),
+ EX_STEADY_BOX_LOAD(0x1D4, RequestSteadyBoxLoad::new, ConnectionState.IN_GAME),
+ EX_STEADY_OPEN_SLOT(0x1D5, RequestSteadyOpenSlot::new, ConnectionState.IN_GAME),
+ EX_STEADY_OPEN_BOX(0x1D6, RequestSteadyOpenBox::new, ConnectionState.IN_GAME),
+ EX_STEADY_GET_REWARD(0x1D7, RequestSteadyGetReward::new, ConnectionState.IN_GAME),
EX_PET_RANKING_MY_INFO(0x1D8, RequestPetRankingMyInfo::new, ConnectionState.IN_GAME),
EX_PET_RANKING_LIST(0x1D9, RequestPetRankingList::new, ConnectionState.IN_GAME),
EX_COLLECTION_OPEN_UI(0x1DA, RequestExCollectionOpenUI::new, ConnectionState.IN_GAME),
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java
index 9ecdf052d5..18bdc33c6f 100644
--- a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java
+++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java
@@ -121,6 +121,7 @@ import org.l2jmobius.gameserver.network.serverpackets.magiclamp.ExMagicLampExpIn
import org.l2jmobius.gameserver.network.serverpackets.pledgedonation.ExPledgeContributionList;
import org.l2jmobius.gameserver.network.serverpackets.randomcraft.ExCraftInfo;
import org.l2jmobius.gameserver.network.serverpackets.settings.ExItemAnnounceSetting;
+import org.l2jmobius.gameserver.network.serverpackets.steadybox.ExSteadyBoxUiInit;
import org.l2jmobius.gameserver.network.serverpackets.subjugation.ExSubjugationSidebar;
import org.l2jmobius.gameserver.util.BuilderUtil;
@@ -672,6 +673,11 @@ public class EnterWorld implements ClientPacket
player.sendPacket(new ExCraftInfo(player));
}
+ if (Config.ENABLE_ACHIEVEMENT_BOX)
+ {
+ player.sendPacket(new ExSteadyBoxUiInit(player));
+ }
+
for (int category = 1; category <= 7; category++)
{
player.sendPacket(new ExCollectionInfo(player, category));
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyBoxLoad.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyBoxLoad.java
new file mode 100644
index 0000000000..857e566c55
--- /dev/null
+++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyBoxLoad.java
@@ -0,0 +1,41 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.steadybox;
+
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.ClientPacket;
+import org.l2jmobius.gameserver.network.serverpackets.steadybox.ExSteadyAllBoxUpdate;
+
+/**
+ * @author Serenitty
+ */
+public class RequestSteadyBoxLoad implements ClientPacket
+{
+ @Override
+ public void run(GameClient client)
+ {
+ final Player player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ player.getAchievementBox().tryFinishBox();
+ player.sendPacket(new ExSteadyAllBoxUpdate(player));
+ }
+}
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyGetReward.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyGetReward.java
new file mode 100644
index 0000000000..d15ab61f00
--- /dev/null
+++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyGetReward.java
@@ -0,0 +1,48 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.steadybox;
+
+import org.l2jmobius.commons.network.ReadablePacket;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.ClientPacket;
+
+/**
+ * @author Serenitty
+ */
+public class RequestSteadyGetReward implements ClientPacket
+{
+ private int _slotId;
+
+ @Override
+ public void read(ReadablePacket packet)
+ {
+ _slotId = packet.readInt();
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final Player player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ player.getAchievementBox().getReward(_slotId);
+ }
+}
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyOpenBox.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyOpenBox.java
new file mode 100644
index 0000000000..550efa0e79
--- /dev/null
+++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyOpenBox.java
@@ -0,0 +1,57 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.steadybox;
+
+import org.l2jmobius.commons.network.ReadablePacket;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.ClientPacket;
+
+/**
+ * @author Serenitty
+ */
+public class RequestSteadyOpenBox implements ClientPacket
+{
+ private int _slotId;
+ private long _feeBoxPrice;
+
+ @Override
+ public void read(ReadablePacket packet)
+ {
+ _slotId = packet.readInt();
+ _feeBoxPrice = packet.readLong();
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final Player player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ if (_feeBoxPrice > 0)
+ {
+ player.getAchievementBox().skipBoxOpenTime(_slotId, _feeBoxPrice);
+ }
+ else
+ {
+ player.getAchievementBox().openBox(_slotId);
+ }
+ }
+}
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyOpenSlot.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyOpenSlot.java
new file mode 100644
index 0000000000..049ed91873
--- /dev/null
+++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyOpenSlot.java
@@ -0,0 +1,49 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.steadybox;
+
+import org.l2jmobius.commons.network.ReadablePacket;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.ClientPacket;
+
+/**
+ * @author Serenitty
+ */
+public class RequestSteadyOpenSlot implements ClientPacket
+{
+ private int _slotId;
+
+ @Override
+ public void read(ReadablePacket packet)
+ {
+ _slotId = packet.readInt();
+
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final Player player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ player.getAchievementBox().unlockSlot(_slotId);
+ }
+}
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyAllBoxUpdate.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyAllBoxUpdate.java
new file mode 100644
index 0000000000..88ab530ce2
--- /dev/null
+++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyAllBoxUpdate.java
@@ -0,0 +1,57 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.steadybox;
+
+import org.l2jmobius.gameserver.model.AchievementBox;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.holders.AchievementBoxHolder;
+import org.l2jmobius.gameserver.network.ServerPackets;
+import org.l2jmobius.gameserver.network.serverpackets.ServerPacket;
+
+/**
+ * @author Serenitty
+ */
+public class ExSteadyAllBoxUpdate extends ServerPacket
+{
+ private final AchievementBox _achievementBox;
+
+ public ExSteadyAllBoxUpdate(Player player)
+ {
+ _achievementBox = player.getAchievementBox();
+ }
+
+ @Override
+ public void write()
+ {
+ ServerPackets.EX_STEADY_ALL_BOX_UPDATE.writeId(this);
+
+ writeInt(_achievementBox.getMonsterPoints());
+ writeInt(_achievementBox.getPvpPoints());
+ writeInt(_achievementBox.getBoxOwned());
+
+ for (int i = 1; i <= _achievementBox.getBoxOwned(); i++)
+ {
+ final AchievementBoxHolder boxholder = _achievementBox.getAchievementBox().get(i - 1);
+ writeInt(i); //
+ writeInt(boxholder.getState().ordinal());
+ writeInt(boxholder.getType().ordinal());
+ }
+
+ final int rewardTimeStage = (int) ((_achievementBox.getBoxOpenTime() - System.currentTimeMillis()) / 1000);
+ writeInt(rewardTimeStage > 0 ? rewardTimeStage : 0);
+ }
+}
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyBoxReward.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyBoxReward.java
new file mode 100644
index 0000000000..43f55025b6
--- /dev/null
+++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyBoxReward.java
@@ -0,0 +1,47 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.steadybox;
+
+import org.l2jmobius.gameserver.network.ServerPackets;
+import org.l2jmobius.gameserver.network.serverpackets.ServerPacket;
+
+/**
+ * @author Serenitty
+ */
+public class ExSteadyBoxReward extends ServerPacket
+{
+ private final int _slotId;
+ private final int _itemId;
+ private final long _itemCount;
+
+ public ExSteadyBoxReward(int slotId, int itemId, long itemCount)
+ {
+ _slotId = slotId;
+ _itemId = itemId;
+ _itemCount = itemCount;
+ }
+
+ @Override
+ public void write()
+ {
+ ServerPackets.EX_STEADY_BOX_REWARD.writeId(this);
+ writeInt(_slotId);
+ writeInt(_itemId);
+ writeLong(_itemCount);
+ writeInt(0);
+ }
+}
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyBoxUiInit.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyBoxUiInit.java
new file mode 100644
index 0000000000..03daa26a57
--- /dev/null
+++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyBoxUiInit.java
@@ -0,0 +1,97 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.steadybox;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import org.l2jmobius.gameserver.network.ServerPackets;
+import org.l2jmobius.gameserver.network.serverpackets.ServerPacket;
+
+/**
+ * @author Serenitty
+ */
+public class ExSteadyBoxUiInit extends ServerPacket
+{
+ private static final int[] OPEN_PRICE =
+ {
+ 500,
+ 1000,
+ 1500
+ };
+ private static final int[] WAIT_TIME =
+ {
+ 0,
+ 60,
+ 180,
+ 360,
+ 540
+ };
+ private static final int[] TIME_PRICE =
+ {
+ 100,
+ 500,
+ 1000,
+ 1500,
+ 2000
+ };
+
+ private final Player _player;
+
+ public ExSteadyBoxUiInit(Player player)
+ {
+ _player = player;
+ }
+
+ @Override
+ public void write()
+ {
+ ServerPackets.EX_STEADY_BOX_UI_INIT.writeId(this);
+
+ writeInt(Config.ACHIEVEMENT_BOX_POINTS_FOR_REWARD);
+ writeInt(Config.ACHIEVEMENT_BOX_PVP_POINTS_FOR_REWARD);
+ if (Config.ENABLE_ACHIEVEMENT_PVP)
+ {
+ writeInt(2); // EventID Normal Point + Pvp Point Bar
+ }
+ else
+ {
+ writeInt(0); // EventID Normal Point + Pvp Point Bar
+ }
+ writeInt(0); // nEventStartTime time for limitkill
+ writeInt(_player.getAchievementBox().pvpEndDate());
+
+ writeInt(OPEN_PRICE.length);
+ for (int i = 0; i < OPEN_PRICE.length; i++)
+ {
+ writeInt(i + 1);
+ writeInt(Inventory.LCOIN_ID);
+ writeLong(OPEN_PRICE[i]);
+ }
+
+ writeInt(TIME_PRICE.length);
+ for (int i = 0; i < TIME_PRICE.length; i++)
+ {
+ writeInt(WAIT_TIME[i]);
+ writeInt(Inventory.LCOIN_ID);
+ writeLong(TIME_PRICE[i]);
+ }
+
+ final int rewardTimeStage = (int) (_player.getAchievementBox().getBoxOpenTime() - System.currentTimeMillis()) / 1000;
+ writeInt(rewardTimeStage > 0 ? rewardTimeStage : 0);
+ }
+}
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyOneBoxUpdate.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyOneBoxUpdate.java
new file mode 100644
index 0000000000..71ecfaced1
--- /dev/null
+++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyOneBoxUpdate.java
@@ -0,0 +1,52 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.steadybox;
+
+import org.l2jmobius.gameserver.model.AchievementBox;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.holders.AchievementBoxHolder;
+import org.l2jmobius.gameserver.network.ServerPackets;
+import org.l2jmobius.gameserver.network.serverpackets.ServerPacket;
+
+/**
+ * @author Serenitty
+ */
+public class ExSteadyOneBoxUpdate extends ServerPacket
+{
+ private final AchievementBox _achievementBox;
+ private final int _slotId;
+
+ public ExSteadyOneBoxUpdate(Player player, int slotId)
+ {
+ _achievementBox = player.getAchievementBox();
+ _slotId = slotId;
+ }
+
+ @Override
+ public void write()
+ {
+ ServerPackets.EX_STEADY_ONE_BOX_UPDATE.writeId(this);
+ writeInt(_achievementBox.getMonsterPoints());
+ writeInt(_achievementBox.getPvpPoints());
+ final AchievementBoxHolder boxholder = _achievementBox.getAchievementBox().get(_slotId - 1);
+ writeInt(_slotId);
+ writeInt(boxholder.getState().ordinal());
+ writeInt(boxholder.getType().ordinal());
+ final int rewardTimeStage = ((int) ((_achievementBox.getBoxOpenTime() - System.currentTimeMillis()) / 1000));
+ writeInt(rewardTimeStage > 0 ? rewardTimeStage : 0);
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_5.2_FrostLord/readme.txt b/L2J_Mobius_Essence_5.2_FrostLord/readme.txt
index d62bc0da4b..a51d6a3ef9 100644
--- a/L2J_Mobius_Essence_5.2_FrostLord/readme.txt
+++ b/L2J_Mobius_Essence_5.2_FrostLord/readme.txt
@@ -132,6 +132,8 @@ Sylph: https://eu.4game.com/patchnotes/lineage2essence/281/
-Collection system
-Purge system
-Pledge donation system
+-Hellbound spawns
+-Achievement box
Frost Lord: https://eu.4game.com/patchnotes/lineage2essence/329/
-Resurrection with payment
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/dist/db_installer/sql/game/achievement_box.sql b/L2J_Mobius_Essence_6.2_Vanguard/dist/db_installer/sql/game/achievement_box.sql
new file mode 100644
index 0000000000..a6750eef4c
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/dist/db_installer/sql/game/achievement_box.sql
@@ -0,0 +1,18 @@
+DROP TABLE IF EXISTS `achievement_box`;
+CREATE TABLE IF NOT EXISTS `achievement_box` (
+`charId` INT,
+`box_owned` INT NOT NULL DEFAULT 1,
+`monster_point` INT NOT NULL DEFAULT 0,
+`pvp_point` INT NOT NULL DEFAULT 0,
+`pending_box` INT NOT NULL DEFAULT 0,
+`open_time` BIGINT UNSIGNED NOT NULL DEFAULT 0,
+`box_state_slot_1` INT NOT NULL DEFAULT 1,
+`boxtype_slot_1` INT NOT NULL DEFAULT 0,
+`box_state_slot_2` INT NOT NULL DEFAULT 0,
+`boxtype_slot_2` INT NOT NULL DEFAULT 0,
+`box_state_slot_3` INT NOT NULL DEFAULT 0,
+`boxtype_slot_3` INT NOT NULL DEFAULT 0,
+`box_state_slot_4` INT NOT NULL DEFAULT 0,
+`boxtype_slot_4` INT NOT NULL DEFAULT 0,
+PRIMARY KEY (`charId`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/dist/game/config/AchievementBox.ini b/L2J_Mobius_Essence_6.2_Vanguard/dist/game/config/AchievementBox.ini
new file mode 100644
index 0000000000..3d91d7b746
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/dist/game/config/AchievementBox.ini
@@ -0,0 +1,19 @@
+# --------------------------------------------------------------------------
+# Achievement Box Settings
+# --------------------------------------------------------------------------
+
+EnabledAchievementBox = True
+
+# Amount of mobs killed.
+# Retail is 1000.
+PointsForReward = 1000
+
+# --------------------------------------------------------------------------
+# Achievement Box PVP Settings
+# --------------------------------------------------------------------------
+
+EnabledAchievementPvP = True
+
+# Amount of Players killed.
+# Retail is 5.
+PointsForPvpReward = 5
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/Config.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/Config.java
index d1d566e8d7..374c9ad12c 100644
--- a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/Config.java
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/Config.java
@@ -104,6 +104,7 @@ public class Config
private static final String GRACIASEEDS_CONFIG_FILE = "./config/GraciaSeeds.ini";
private static final String GRANDBOSS_CONFIG_FILE = "./config/GrandBoss.ini";
private static final String HUNT_PASS_CONFIG_FILE = "./config/HuntPass.ini";
+ private static final String ACHIEVEMENT_BOX_CONFIG_FILE = "./config/AchievementBox.ini";
private static final String LOGIN_CONFIG_FILE = "./config/LoginServer.ini";
private static final String NPC_CONFIG_FILE = "./config/NPC.ini";
private static final String PVP_CONFIG_FILE = "./config/PVP.ini";
@@ -956,6 +957,12 @@ public class Config
public static int HUNT_PASS_PREMIUM_COST;
public static int HUNT_PASS_POINTS_FOR_STEP;
+ // Achivement Box
+ public static boolean ENABLE_ACHIEVEMENT_BOX;
+ public static int ACHIEVEMENT_BOX_POINTS_FOR_REWARD;
+ public static boolean ENABLE_ACHIEVEMENT_PVP;
+ public static int ACHIEVEMENT_BOX_PVP_POINTS_FOR_REWARD;
+
// GrandBoss Settings
// Antharas
@@ -2696,6 +2703,13 @@ public class Config
HUNT_PASS_POINTS_FOR_STEP = huntPassConfig.getInt("PointsForstep", 2400);
HUNT_PASS_PERIOD = huntPassConfig.getInt("DayOfMonth", 1);
+ // Load ArchivementBox (if exists)
+ final PropertiesParser achievementBoxConfig = new PropertiesParser(ACHIEVEMENT_BOX_CONFIG_FILE);
+ ENABLE_ACHIEVEMENT_BOX = achievementBoxConfig.getBoolean("EnabledAchievementBox", true);
+ ACHIEVEMENT_BOX_POINTS_FOR_REWARD = achievementBoxConfig.getInt("PointsForReward", 1000);
+ ENABLE_ACHIEVEMENT_PVP = achievementBoxConfig.getBoolean("EnabledAchievementPvP", true);
+ ACHIEVEMENT_BOX_PVP_POINTS_FOR_REWARD = achievementBoxConfig.getInt("PointsForPvpReward", 5);
+
// Gracia Seeds
final PropertiesParser graciaSeedsConfig = new PropertiesParser(GRACIASEEDS_CONFIG_FILE);
SOD_TIAT_KILL_COUNT = graciaSeedsConfig.getInt("TiatKillCountForNextState", 10);
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/enums/AchievementBoxState.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/enums/AchievementBoxState.java
new file mode 100644
index 0000000000..671455dfb8
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/enums/AchievementBoxState.java
@@ -0,0 +1,29 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.enums;
+
+/**
+ * @author Serenitty
+ */
+public enum AchievementBoxState
+{
+ LOCKED,
+ AVAILABLE,
+ OPEN,
+ UNLOCK_IN_PROGRESS,
+ RECEIVE_REWARD
+}
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/enums/AchievementBoxType.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/enums/AchievementBoxType.java
new file mode 100644
index 0000000000..aabe5ce5b9
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/enums/AchievementBoxType.java
@@ -0,0 +1,28 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.enums;
+
+/**
+ * @author Serenitty
+ */
+public enum AchievementBoxType
+{
+ LOCKED,
+ BOX_2H,
+ BOX_6H,
+ BOX_12H;
+}
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/AchievementBox.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/AchievementBox.java
new file mode 100644
index 0000000000..9f7d29d0e4
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/AchievementBox.java
@@ -0,0 +1,539 @@
+package org.l2jmobius.gameserver.model;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+import java.util.concurrent.ScheduledFuture;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.database.DatabaseFactory;
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.commons.util.Rnd;
+import org.l2jmobius.gameserver.enums.AchievementBoxState;
+import org.l2jmobius.gameserver.enums.AchievementBoxType;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.holders.AchievementBoxHolder;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import org.l2jmobius.gameserver.network.serverpackets.steadybox.ExSteadyAllBoxUpdate;
+import org.l2jmobius.gameserver.network.serverpackets.steadybox.ExSteadyBoxReward;
+
+/**
+ * @author Serenitty, nlyyn, MacuK, Rudelitobr
+ */
+public class AchievementBox
+{
+ private static final Logger LOGGER = Logger.getLogger(AchievementBox.class.getName());
+
+ private static final int ACHIEVEMENT_BOX_2H = 7200000;
+ private static final int ACHIEVEMENT_BOX_6H = 21600000;
+ private static final int ACHIEVEMENT_BOX_12H = 43200000;
+
+ private final Player _owner;
+ private int _boxOwned = 1;
+ private int _monsterPoints = 0;
+ private int _pvpPoints = 0;
+ private int _pendingBoxSlotId = 0;
+ private int _pvpEndDate;
+ private long _boxTimeForOpen;
+ private final List _achievementBox = new ArrayList<>();
+ private ScheduledFuture> _boxOpenTask;
+
+ public AchievementBox(Player owner)
+ {
+ _owner = owner;
+ }
+
+ public int pvpEndDate()
+ {
+ return _pvpEndDate;
+ }
+
+ public void addPoints(int value)
+ {
+ final int newPoints = Math.min(Config.ACHIEVEMENT_BOX_POINTS_FOR_REWARD, _monsterPoints + value);
+ if (newPoints >= Config.ACHIEVEMENT_BOX_POINTS_FOR_REWARD)
+ {
+ if (addNewBox())
+ {
+ _monsterPoints = 0;
+ }
+ else
+ {
+ _monsterPoints = Config.ACHIEVEMENT_BOX_POINTS_FOR_REWARD;
+ }
+ return;
+ }
+ _monsterPoints += value;
+ }
+
+ public void addPvpPoints(int value)
+ {
+ final int newPoints = Math.min(Config.ACHIEVEMENT_BOX_PVP_POINTS_FOR_REWARD, _pvpPoints);
+ while (newPoints >= Config.ACHIEVEMENT_BOX_PVP_POINTS_FOR_REWARD)
+ {
+ if (addNewBox())
+ {
+ _pvpPoints = 0;
+ }
+ else
+ {
+ _pvpPoints = Config.ACHIEVEMENT_BOX_PVP_POINTS_FOR_REWARD;
+ }
+ return;
+ }
+ _pvpPoints += value;
+ }
+
+ public void restore()
+ {
+ tryFinishBox();
+ refreshPvpEndDate();
+ try (Connection con = DatabaseFactory.getConnection();
+ PreparedStatement ps = con.prepareStatement("SELECT * FROM achievement_box WHERE charId=?"))
+ {
+ ps.setInt(1, _owner.getObjectId());
+ try (ResultSet rs = ps.executeQuery())
+ {
+ if (rs.next())
+ {
+ try
+ {
+ _boxOwned = rs.getInt("box_owned");
+ _monsterPoints = rs.getInt("monster_point");
+ _pvpPoints = rs.getInt("pvp_point");
+ _pendingBoxSlotId = rs.getInt("pending_box");
+ _boxTimeForOpen = rs.getLong("open_time");
+ for (int i = 1; i <= 4; i++)
+ {
+ int state = rs.getInt("box_state_slot_" + i);
+ int type = rs.getInt("boxtype_slot_" + i);
+ if ((i == 1) && (state == 0))
+ {
+ state = 1;
+ }
+ final AchievementBoxHolder holder = new AchievementBoxHolder(i, state, type);
+ _achievementBox.add(i - 1, holder);
+ }
+ }
+ catch (Exception e)
+ {
+ LOGGER.warning("Could not restore Achievement box for " + _owner);
+ }
+ }
+ else
+ {
+ storeNew();
+ _achievementBox.add(0, new AchievementBoxHolder(1, 1, 0));
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ LOGGER.log(Level.WARNING, "Could not restore achievement box for " + _owner, e);
+ }
+ }
+
+ public void storeNew()
+ {
+ try (Connection con = DatabaseFactory.getConnection();
+ PreparedStatement ps = con.prepareStatement("INSERT INTO achievement_box VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?)"))
+ {
+ ps.setInt(1, _owner.getObjectId());
+ ps.setInt(2, _boxOwned);
+ ps.setInt(3, _monsterPoints);
+ ps.setInt(4, _pvpPoints);
+ ps.setInt(5, _pendingBoxSlotId);
+ ps.setLong(6, _boxTimeForOpen);
+ for (int i = 0; i < 4; i++)
+ {
+ ps.setInt(7 + (i * 2), 0);
+ ps.setInt(8 + (i * 2), 0);
+ }
+ ps.executeUpdate();
+ }
+ catch (SQLException e)
+ {
+ LOGGER.warning("Could not store new Archivement Box for: " + _owner);
+ LOGGER.warning(CommonUtil.getStackTrace(e));
+ }
+ }
+
+ public void store()
+ {
+ try (Connection con = DatabaseFactory.getConnection();
+ PreparedStatement ps = con.prepareStatement("UPDATE achievement_box SET box_owned=?,monster_point=?,pvp_point=?,pending_box=?,open_time=?,box_state_slot_1=?,boxtype_slot_1=?,box_state_slot_2=?,boxtype_slot_2=?,box_state_slot_3=?,boxtype_slot_3=?,box_state_slot_4=?,boxtype_slot_4=? WHERE charId=?"))
+ {
+ ps.setInt(1, getBoxOwned());
+ ps.setInt(2, getMonsterPoints());
+ ps.setInt(3, getPvpPoints());
+ ps.setInt(4, getPendingBoxSlotId());
+ ps.setLong(5, getBoxOpenTime());
+ for (int i = 0; i < 4; i++)
+ {
+ if (_achievementBox.size() >= (i + 1))
+ {
+ AchievementBoxHolder holder = _achievementBox.get(i);
+ ps.setInt(6 + (i * 2), holder == null ? 0 : holder.getState().ordinal());
+ ps.setInt(7 + (i * 2), holder == null ? 0 : holder.getType().ordinal());
+ }
+ else
+ {
+ ps.setInt(6 + (i * 2), 0);
+ ps.setInt(7 + (i * 2), 0);
+ }
+ }
+ ps.setInt(14, _owner.getObjectId());
+ ps.execute();
+ }
+ catch (SQLException e)
+ {
+ LOGGER.log(Level.SEVERE, "Could not store Achievement Box for: " + _owner, e);
+ }
+ }
+
+ public List getAchievementBox()
+ {
+ return _achievementBox;
+ }
+
+ public boolean addNewBox()
+ {
+ AchievementBoxHolder free = null;
+ int id = -1;
+ for (int i = 1; i <= getBoxOwned(); i++)
+ {
+ final AchievementBoxHolder holder = getAchievementBox().get(i - 1);
+ if (holder.getState() == AchievementBoxState.AVAILABLE)
+ {
+ free = holder;
+ id = i;
+ break;
+ }
+ }
+ if (free != null)
+ {
+ int rnd = Rnd.get(0, 100);
+ free.setType(rnd < 12 ? AchievementBoxType.BOX_12H : rnd < 40 ? AchievementBoxType.BOX_6H : AchievementBoxType.BOX_2H);
+ switch (free.getType())
+ {
+ case BOX_2H:
+ case BOX_6H:
+ case BOX_12H:
+ {
+ free.setState(AchievementBoxState.OPEN);
+ getAchievementBox().remove(id - 1);
+ getAchievementBox().add(id - 1, free);
+ sendBoxUpdate();
+ break;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public void openBox(int slotId)
+ {
+ if (slotId > getBoxOwned())
+ {
+ return;
+ }
+
+ final AchievementBoxHolder holder = getAchievementBox().get(slotId - 1);
+ if ((holder == null) || (_boxTimeForOpen != 0))
+ {
+ return;
+ }
+
+ _pendingBoxSlotId = slotId;
+
+ switch (holder.getType())
+ {
+ case BOX_2H:
+ {
+ setBoxTimeForOpen(ACHIEVEMENT_BOX_2H);
+ holder.setState(AchievementBoxState.UNLOCK_IN_PROGRESS);
+ getAchievementBox().remove(slotId - 1);
+ getAchievementBox().add(slotId - 1, holder);
+ sendBoxUpdate();
+ break;
+ }
+ case BOX_6H:
+ {
+ setBoxTimeForOpen(ACHIEVEMENT_BOX_6H);
+ holder.setState(AchievementBoxState.UNLOCK_IN_PROGRESS);
+ getAchievementBox().remove(slotId - 1);
+ getAchievementBox().add(slotId - 1, holder);
+ sendBoxUpdate();
+ break;
+ }
+ case BOX_12H:
+ {
+ setBoxTimeForOpen(ACHIEVEMENT_BOX_12H);
+ holder.setState(AchievementBoxState.UNLOCK_IN_PROGRESS);
+ getAchievementBox().remove(slotId - 1);
+ getAchievementBox().add(slotId - 1, holder);
+ sendBoxUpdate();
+ break;
+ }
+ }
+ }
+
+ public void skipBoxOpenTime(int slotId, long fee)
+ {
+ if (slotId > getBoxOwned())
+ {
+ return;
+ }
+
+ final AchievementBoxHolder holder = getAchievementBox().get(slotId - 1);
+ if ((holder != null) && _owner.destroyItemByItemId("Take Achievement Box", Inventory.LCOIN_ID, fee, _owner, true))
+ {
+ if (_pendingBoxSlotId == slotId)
+ {
+ cancelTask();
+ }
+ finishAndUnlockChest(slotId);
+ }
+ }
+
+ public boolean setBoxTimeForOpen(long time)
+ {
+ if ((_boxOpenTask != null) && !(_boxOpenTask.isDone() || _boxOpenTask.isCancelled()))
+ {
+ return false;
+ }
+
+ _boxTimeForOpen = System.currentTimeMillis() + time;
+ return true;
+ }
+
+ public void tryFinishBox()
+ {
+ if ((_boxTimeForOpen == 0) || (_boxTimeForOpen >= System.currentTimeMillis()))
+ {
+ return;
+ }
+
+ if ((_owner == null) || !_owner.isOnline())
+ {
+ return;
+ }
+
+ final AchievementBoxHolder holder = getAchievementBox().get(_pendingBoxSlotId - 1);
+ if (holder != null)
+ {
+ finishAndUnlockChest(_pendingBoxSlotId);
+ }
+ }
+
+ public int getBoxOwned()
+ {
+ return _boxOwned;
+ }
+
+ public int getMonsterPoints()
+ {
+ return _monsterPoints;
+ }
+
+ public int getPvpPoints()
+ {
+ return _pvpPoints;
+ }
+
+ public int getPendingBoxSlotId()
+ {
+ return _pendingBoxSlotId;
+ }
+
+ public long getBoxOpenTime()
+ {
+ return _boxTimeForOpen;
+ }
+
+ public void finishAndUnlockChest(int id)
+ {
+ if (id > getBoxOwned())
+ {
+ return;
+ }
+
+ if (_pendingBoxSlotId == id)
+ {
+ _boxTimeForOpen = 0;
+ _pendingBoxSlotId = 0;
+ }
+
+ getAchievementBox().get(id - 1).setState(AchievementBoxState.RECEIVE_REWARD);
+ sendBoxUpdate();
+ }
+
+ public void sendBoxUpdate()
+ {
+ _owner.sendPacket(new ExSteadyAllBoxUpdate(_owner));
+ }
+
+ public void cancelTask()
+ {
+ if (_boxOpenTask == null)
+ {
+ return;
+ }
+
+ _boxOpenTask.cancel(false);
+ _boxOpenTask = null;
+ }
+
+ public void unlockSlot(int slotId)
+ {
+ if (((slotId - 1) != getBoxOwned()) || (slotId > 4))
+ {
+ return;
+ }
+
+ boolean paidSlot = false;
+ switch (slotId)
+ {
+ case 2:
+ {
+ if (_owner.reduceAdena("Adena " + slotId, 100000000, _owner, true))
+ {
+ paidSlot = true;
+ }
+ break;
+ }
+ case 3:
+ {
+ if (_owner.destroyItemByItemId("L coin " + slotId, Inventory.LCOIN_ID, 2000, _owner, true))
+ {
+ paidSlot = true;
+ }
+ break;
+ }
+ case 4:
+ {
+ if (_owner.destroyItemByItemId("L coin " + slotId, Inventory.LCOIN_ID, 8000, _owner, true))
+ {
+ paidSlot = true;
+ }
+ break;
+ }
+ }
+
+ if (paidSlot)
+ {
+ _boxOwned = slotId;
+ final AchievementBoxHolder holder = new AchievementBoxHolder(slotId, 1, 0);
+ holder.setState(AchievementBoxState.AVAILABLE);
+ holder.setType(AchievementBoxType.LOCKED);
+ getAchievementBox().add(slotId - 1, holder);
+ sendBoxUpdate();
+ }
+ }
+
+ public void getReward(int slotId)
+ {
+ final AchievementBoxHolder holder = getAchievementBox().get(slotId - 1);
+ if (holder.getState() != AchievementBoxState.RECEIVE_REWARD)
+ {
+ return;
+ }
+
+ final int rnd = Rnd.get(100);
+ ItemHolder reward = null;
+ switch (holder.getType())
+ {
+ case BOX_2H:
+ {
+ if (rnd < 3)
+ {
+ reward = new ItemHolder(Rnd.get(72084, 72102), 1);
+ }
+ else if (rnd < 30)
+ {
+ reward = new ItemHolder(93274, 5); // Sayha Cookie
+ }
+ else if (rnd < 70)
+ {
+ reward = new ItemHolder(90907, 250); // Soulshot Ticket
+ }
+ else
+ {
+ reward = new ItemHolder(3031, 50); // Spirit Ore
+ }
+ break;
+ }
+ case BOX_6H:
+ {
+ if (rnd < 10)
+ {
+ reward = new ItemHolder(Rnd.get(72084, 72102), 1);
+ }
+ else if (rnd < 30)
+ {
+ reward = new ItemHolder(93274, 10); // Sayha Cookie
+ }
+ else if (rnd < 70)
+ {
+ reward = new ItemHolder(90907, 500); // Soulshot Ticket
+ }
+ else
+ {
+ reward = new ItemHolder(3031, 100); // Spirit Ore
+ }
+ break;
+ }
+ case BOX_12H:
+ {
+ if (rnd < 20)
+ {
+ reward = new ItemHolder(Rnd.get(72084, 72102), 1);
+ }
+ else if (rnd < 30)
+ {
+ reward = new ItemHolder(93274, 20); // Sayha Cookie
+ }
+ else if (rnd < 70)
+ {
+ reward = new ItemHolder(90907, 1000); // Soulshot Ticket
+ }
+ else
+ {
+ reward = new ItemHolder(3031, 200); // Spirit Ore
+ }
+ break;
+ }
+ }
+
+ holder.setState(AchievementBoxState.AVAILABLE);
+ holder.setType(AchievementBoxType.LOCKED);
+ sendBoxUpdate();
+ if (reward != null)
+ {
+ _owner.addItem("Chest unlock", reward, _owner, true);
+ _owner.sendPacket(new ExSteadyBoxReward(slotId, reward.getId(), reward.getCount()));
+ }
+ }
+
+ public void refreshPvpEndDate()
+ {
+ final long currentTime = System.currentTimeMillis();
+ final Calendar calendar = Calendar.getInstance();
+ calendar.setTimeInMillis(currentTime);
+ calendar.set(Calendar.DAY_OF_MONTH, 1);
+ calendar.set(Calendar.HOUR_OF_DAY, 6);
+ if (calendar.getTimeInMillis() < currentTime)
+ {
+ calendar.add(Calendar.MONTH, 1);
+ }
+ _pvpEndDate = (int) (calendar.getTimeInMillis() / 1000);
+ }
+}
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/Party.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/Party.java
index 0f0c401de4..2d72c27fcb 100644
--- a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/Party.java
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/Party.java
@@ -895,6 +895,12 @@ public class Party extends AbstractPlayerGroup
{
huntpass.addPassPoint(exp);
}
+
+ final AchievementBox box = member.getAchievementBox();
+ if (box != null)
+ {
+ member.getAchievementBox().addPoints(1);
+ }
}
}
else
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/actor/Attackable.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/actor/Attackable.java
index 379acd8294..3480884ddd 100644
--- a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/actor/Attackable.java
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/actor/Attackable.java
@@ -46,6 +46,7 @@ import org.l2jmobius.gameserver.instancemanager.CursedWeaponsManager;
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
import org.l2jmobius.gameserver.instancemanager.WalkingManager;
import org.l2jmobius.gameserver.instancemanager.events.EventDropManager;
+import org.l2jmobius.gameserver.model.AchievementBox;
import org.l2jmobius.gameserver.model.AggroInfo;
import org.l2jmobius.gameserver.model.CommandChannel;
import org.l2jmobius.gameserver.model.DamageDoneInfo;
@@ -613,6 +614,12 @@ public class Attackable extends Npc
{
attacker.getHuntPass().addPassPoint(exp);
}
+
+ final AchievementBox box = attacker.getAchievementBox();
+ if (box != null)
+ {
+ attacker.getAchievementBox().addPoints(1);
+ }
}
}
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/actor/Player.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/actor/Player.java
index 841ade3ceb..ad01b9161f 100644
--- a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/actor/Player.java
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/actor/Player.java
@@ -143,6 +143,7 @@ import org.l2jmobius.gameserver.instancemanager.SellBuffsManager;
import org.l2jmobius.gameserver.instancemanager.SiegeManager;
import org.l2jmobius.gameserver.instancemanager.ZoneManager;
import org.l2jmobius.gameserver.model.AccessLevel;
+import org.l2jmobius.gameserver.model.AchievementBox;
import org.l2jmobius.gameserver.model.ArenaParticipantsHolder;
import org.l2jmobius.gameserver.model.BlockList;
import org.l2jmobius.gameserver.model.ClientSettings;
@@ -963,6 +964,7 @@ public class Player extends Playable
private final Map _purgePoints = new HashMap<>();
private final HuntPass _huntPass;
+ private final AchievementBox _achivemenetBox;
private final Map _petEvolves = new HashMap<>();
@@ -1259,6 +1261,7 @@ public class Player extends Playable
_appearance = app;
_huntPass = Config.ENABLE_HUNT_PASS ? new HuntPass(this) : null;
+ _achivemenetBox = Config.ENABLE_ACHIEVEMENT_BOX ? new AchievementBox(this) : null;
// Create an AI
getAI();
@@ -1355,6 +1358,11 @@ public class Player extends Playable
return _huntPass;
}
+ public AchievementBox getAchievementBox()
+ {
+ return _achivemenetBox;
+ }
+
/**
* @return the PlayerTemplate link to the Player.
*/
@@ -5414,6 +5422,10 @@ public class Player extends Playable
setPvpKills(_pvpKills + 1);
setTotalKills(getTotalKills() + 1);
updatePvpTitleAndColor(true);
+ if (Config.ENABLE_ACHIEVEMENT_PVP)
+ {
+ getAchievementBox().addPvpPoints(1);
+ }
}
else if ((getReputation() > 0) && (_pkKills == 0))
{
@@ -7072,7 +7084,7 @@ public class Player extends Playable
player.setOnlineStatus(true, false);
PlayerAutoSaveTaskManager.getInstance().add(player);
-
+ player.getAchievementBox().restore();
}
catch (Exception e)
{
@@ -7396,6 +7408,11 @@ public class Player extends Playable
{
_huntPass.store();
}
+
+ if (_achivemenetBox != null)
+ {
+ _achivemenetBox.store();
+ }
}
@Override
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/holders/AchievementBoxHolder.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/holders/AchievementBoxHolder.java
new file mode 100644
index 0000000000..639b3082a8
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/model/holders/AchievementBoxHolder.java
@@ -0,0 +1,62 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.model.holders;
+
+import org.l2jmobius.gameserver.enums.AchievementBoxState;
+import org.l2jmobius.gameserver.enums.AchievementBoxType;
+
+/**
+ * @author Serenitty
+ */
+public class AchievementBoxHolder
+{
+ private final int _slotId;
+ private AchievementBoxState _boxState;
+ private AchievementBoxType _boxType;
+
+ public AchievementBoxHolder(int slotId, int boxState, int boxType)
+ {
+ _slotId = slotId;
+ _boxState = AchievementBoxState.values()[boxState];
+ _boxType = AchievementBoxType.values()[boxType];
+ }
+
+ public void setState(AchievementBoxState value)
+ {
+ _boxState = value;
+ }
+
+ public AchievementBoxState getState()
+ {
+ return _boxState;
+ }
+
+ public AchievementBoxType getType()
+ {
+ return _boxType;
+ }
+
+ public void setType(AchievementBoxType value)
+ {
+ _boxType = value;
+ }
+
+ public int getSlotId()
+ {
+ return _slotId;
+ }
+}
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/ExClientPackets.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/ExClientPackets.java
index 9f6fbc37a1..b84515516f 100644
--- a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/ExClientPackets.java
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/ExClientPackets.java
@@ -185,6 +185,10 @@ import org.l2jmobius.gameserver.network.clientpackets.shuttle.RequestShuttleGetO
import org.l2jmobius.gameserver.network.clientpackets.shuttle.RequestShuttleGetOn;
import org.l2jmobius.gameserver.network.clientpackets.stats.ExResetStatusBonus;
import org.l2jmobius.gameserver.network.clientpackets.stats.ExSetStatusBonus;
+import org.l2jmobius.gameserver.network.clientpackets.steadybox.RequestSteadyBoxLoad;
+import org.l2jmobius.gameserver.network.clientpackets.steadybox.RequestSteadyGetReward;
+import org.l2jmobius.gameserver.network.clientpackets.steadybox.RequestSteadyOpenBox;
+import org.l2jmobius.gameserver.network.clientpackets.steadybox.RequestSteadyOpenSlot;
import org.l2jmobius.gameserver.network.clientpackets.subjugation.RequestSubjugationGacha;
import org.l2jmobius.gameserver.network.clientpackets.subjugation.RequestSubjugationGachaUI;
import org.l2jmobius.gameserver.network.clientpackets.subjugation.RequestSubjugationList;
@@ -688,10 +692,10 @@ public enum ExClientPackets
EX_RANKING_FESTIVAL_MY_RECEIVED_BONUS(0x1D1, null, ConnectionState.IN_GAME),
EX_RANKING_FESTIVAL_REWARD(0x1D2, null, ConnectionState.IN_GAME),
EX_TIMER_CHECK(0x1D3, null, ConnectionState.IN_GAME),
- EX_STEADY_BOX_LOAD(0x1D4, null, ConnectionState.IN_GAME),
- EX_STEADY_OPEN_SLOT(0x1D5, null, ConnectionState.IN_GAME),
- EX_STEADY_OPEN_BOX(0x1D6, null, ConnectionState.IN_GAME),
- EX_STEADY_GET_REWARD(0x1D7, null, ConnectionState.IN_GAME),
+ EX_STEADY_BOX_LOAD(0x1D4, RequestSteadyBoxLoad::new, ConnectionState.IN_GAME),
+ EX_STEADY_OPEN_SLOT(0x1D5, RequestSteadyOpenSlot::new, ConnectionState.IN_GAME),
+ EX_STEADY_OPEN_BOX(0x1D6, RequestSteadyOpenBox::new, ConnectionState.IN_GAME),
+ EX_STEADY_GET_REWARD(0x1D7, RequestSteadyGetReward::new, ConnectionState.IN_GAME),
EX_PET_RANKING_MY_INFO(0x1D8, RequestPetRankingMyInfo::new, ConnectionState.IN_GAME),
EX_PET_RANKING_LIST(0x1D9, RequestPetRankingList::new, ConnectionState.IN_GAME),
EX_COLLECTION_OPEN_UI(0x1DA, RequestExCollectionOpenUI::new, ConnectionState.IN_GAME),
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java
index 28725b2176..4d3af75cf4 100644
--- a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java
@@ -123,6 +123,7 @@ import org.l2jmobius.gameserver.network.serverpackets.magiclamp.ExMagicLampExpIn
import org.l2jmobius.gameserver.network.serverpackets.pledgedonation.ExPledgeContributionList;
import org.l2jmobius.gameserver.network.serverpackets.randomcraft.ExCraftInfo;
import org.l2jmobius.gameserver.network.serverpackets.settings.ExItemAnnounceSetting;
+import org.l2jmobius.gameserver.network.serverpackets.steadybox.ExSteadyBoxUiInit;
import org.l2jmobius.gameserver.network.serverpackets.subjugation.ExSubjugationSidebar;
import org.l2jmobius.gameserver.util.BuilderUtil;
@@ -688,6 +689,11 @@ public class EnterWorld implements ClientPacket
player.sendPacket(new HuntPassSimpleInfo(player));
}
+ if (Config.ENABLE_ACHIEVEMENT_BOX)
+ {
+ player.sendPacket(new ExSteadyBoxUiInit(player));
+ }
+
for (int category = 1; category <= 7; category++)
{
player.sendPacket(new ExCollectionInfo(player, category));
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyBoxLoad.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyBoxLoad.java
new file mode 100644
index 0000000000..857e566c55
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyBoxLoad.java
@@ -0,0 +1,41 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.steadybox;
+
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.ClientPacket;
+import org.l2jmobius.gameserver.network.serverpackets.steadybox.ExSteadyAllBoxUpdate;
+
+/**
+ * @author Serenitty
+ */
+public class RequestSteadyBoxLoad implements ClientPacket
+{
+ @Override
+ public void run(GameClient client)
+ {
+ final Player player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ player.getAchievementBox().tryFinishBox();
+ player.sendPacket(new ExSteadyAllBoxUpdate(player));
+ }
+}
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyGetReward.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyGetReward.java
new file mode 100644
index 0000000000..d15ab61f00
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyGetReward.java
@@ -0,0 +1,48 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.steadybox;
+
+import org.l2jmobius.commons.network.ReadablePacket;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.ClientPacket;
+
+/**
+ * @author Serenitty
+ */
+public class RequestSteadyGetReward implements ClientPacket
+{
+ private int _slotId;
+
+ @Override
+ public void read(ReadablePacket packet)
+ {
+ _slotId = packet.readInt();
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final Player player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ player.getAchievementBox().getReward(_slotId);
+ }
+}
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyOpenBox.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyOpenBox.java
new file mode 100644
index 0000000000..550efa0e79
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyOpenBox.java
@@ -0,0 +1,57 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.steadybox;
+
+import org.l2jmobius.commons.network.ReadablePacket;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.ClientPacket;
+
+/**
+ * @author Serenitty
+ */
+public class RequestSteadyOpenBox implements ClientPacket
+{
+ private int _slotId;
+ private long _feeBoxPrice;
+
+ @Override
+ public void read(ReadablePacket packet)
+ {
+ _slotId = packet.readInt();
+ _feeBoxPrice = packet.readLong();
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final Player player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ if (_feeBoxPrice > 0)
+ {
+ player.getAchievementBox().skipBoxOpenTime(_slotId, _feeBoxPrice);
+ }
+ else
+ {
+ player.getAchievementBox().openBox(_slotId);
+ }
+ }
+}
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyOpenSlot.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyOpenSlot.java
new file mode 100644
index 0000000000..049ed91873
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyOpenSlot.java
@@ -0,0 +1,49 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.steadybox;
+
+import org.l2jmobius.commons.network.ReadablePacket;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.ClientPacket;
+
+/**
+ * @author Serenitty
+ */
+public class RequestSteadyOpenSlot implements ClientPacket
+{
+ private int _slotId;
+
+ @Override
+ public void read(ReadablePacket packet)
+ {
+ _slotId = packet.readInt();
+
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final Player player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ player.getAchievementBox().unlockSlot(_slotId);
+ }
+}
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyAllBoxUpdate.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyAllBoxUpdate.java
new file mode 100644
index 0000000000..88ab530ce2
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyAllBoxUpdate.java
@@ -0,0 +1,57 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.steadybox;
+
+import org.l2jmobius.gameserver.model.AchievementBox;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.holders.AchievementBoxHolder;
+import org.l2jmobius.gameserver.network.ServerPackets;
+import org.l2jmobius.gameserver.network.serverpackets.ServerPacket;
+
+/**
+ * @author Serenitty
+ */
+public class ExSteadyAllBoxUpdate extends ServerPacket
+{
+ private final AchievementBox _achievementBox;
+
+ public ExSteadyAllBoxUpdate(Player player)
+ {
+ _achievementBox = player.getAchievementBox();
+ }
+
+ @Override
+ public void write()
+ {
+ ServerPackets.EX_STEADY_ALL_BOX_UPDATE.writeId(this);
+
+ writeInt(_achievementBox.getMonsterPoints());
+ writeInt(_achievementBox.getPvpPoints());
+ writeInt(_achievementBox.getBoxOwned());
+
+ for (int i = 1; i <= _achievementBox.getBoxOwned(); i++)
+ {
+ final AchievementBoxHolder boxholder = _achievementBox.getAchievementBox().get(i - 1);
+ writeInt(i); //
+ writeInt(boxholder.getState().ordinal());
+ writeInt(boxholder.getType().ordinal());
+ }
+
+ final int rewardTimeStage = (int) ((_achievementBox.getBoxOpenTime() - System.currentTimeMillis()) / 1000);
+ writeInt(rewardTimeStage > 0 ? rewardTimeStage : 0);
+ }
+}
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyBoxReward.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyBoxReward.java
new file mode 100644
index 0000000000..43f55025b6
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyBoxReward.java
@@ -0,0 +1,47 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.steadybox;
+
+import org.l2jmobius.gameserver.network.ServerPackets;
+import org.l2jmobius.gameserver.network.serverpackets.ServerPacket;
+
+/**
+ * @author Serenitty
+ */
+public class ExSteadyBoxReward extends ServerPacket
+{
+ private final int _slotId;
+ private final int _itemId;
+ private final long _itemCount;
+
+ public ExSteadyBoxReward(int slotId, int itemId, long itemCount)
+ {
+ _slotId = slotId;
+ _itemId = itemId;
+ _itemCount = itemCount;
+ }
+
+ @Override
+ public void write()
+ {
+ ServerPackets.EX_STEADY_BOX_REWARD.writeId(this);
+ writeInt(_slotId);
+ writeInt(_itemId);
+ writeLong(_itemCount);
+ writeInt(0);
+ }
+}
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyBoxUiInit.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyBoxUiInit.java
new file mode 100644
index 0000000000..03daa26a57
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyBoxUiInit.java
@@ -0,0 +1,97 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.steadybox;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import org.l2jmobius.gameserver.network.ServerPackets;
+import org.l2jmobius.gameserver.network.serverpackets.ServerPacket;
+
+/**
+ * @author Serenitty
+ */
+public class ExSteadyBoxUiInit extends ServerPacket
+{
+ private static final int[] OPEN_PRICE =
+ {
+ 500,
+ 1000,
+ 1500
+ };
+ private static final int[] WAIT_TIME =
+ {
+ 0,
+ 60,
+ 180,
+ 360,
+ 540
+ };
+ private static final int[] TIME_PRICE =
+ {
+ 100,
+ 500,
+ 1000,
+ 1500,
+ 2000
+ };
+
+ private final Player _player;
+
+ public ExSteadyBoxUiInit(Player player)
+ {
+ _player = player;
+ }
+
+ @Override
+ public void write()
+ {
+ ServerPackets.EX_STEADY_BOX_UI_INIT.writeId(this);
+
+ writeInt(Config.ACHIEVEMENT_BOX_POINTS_FOR_REWARD);
+ writeInt(Config.ACHIEVEMENT_BOX_PVP_POINTS_FOR_REWARD);
+ if (Config.ENABLE_ACHIEVEMENT_PVP)
+ {
+ writeInt(2); // EventID Normal Point + Pvp Point Bar
+ }
+ else
+ {
+ writeInt(0); // EventID Normal Point + Pvp Point Bar
+ }
+ writeInt(0); // nEventStartTime time for limitkill
+ writeInt(_player.getAchievementBox().pvpEndDate());
+
+ writeInt(OPEN_PRICE.length);
+ for (int i = 0; i < OPEN_PRICE.length; i++)
+ {
+ writeInt(i + 1);
+ writeInt(Inventory.LCOIN_ID);
+ writeLong(OPEN_PRICE[i]);
+ }
+
+ writeInt(TIME_PRICE.length);
+ for (int i = 0; i < TIME_PRICE.length; i++)
+ {
+ writeInt(WAIT_TIME[i]);
+ writeInt(Inventory.LCOIN_ID);
+ writeLong(TIME_PRICE[i]);
+ }
+
+ final int rewardTimeStage = (int) (_player.getAchievementBox().getBoxOpenTime() - System.currentTimeMillis()) / 1000;
+ writeInt(rewardTimeStage > 0 ? rewardTimeStage : 0);
+ }
+}
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyOneBoxUpdate.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyOneBoxUpdate.java
new file mode 100644
index 0000000000..71ecfaced1
--- /dev/null
+++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyOneBoxUpdate.java
@@ -0,0 +1,52 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.steadybox;
+
+import org.l2jmobius.gameserver.model.AchievementBox;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.holders.AchievementBoxHolder;
+import org.l2jmobius.gameserver.network.ServerPackets;
+import org.l2jmobius.gameserver.network.serverpackets.ServerPacket;
+
+/**
+ * @author Serenitty
+ */
+public class ExSteadyOneBoxUpdate extends ServerPacket
+{
+ private final AchievementBox _achievementBox;
+ private final int _slotId;
+
+ public ExSteadyOneBoxUpdate(Player player, int slotId)
+ {
+ _achievementBox = player.getAchievementBox();
+ _slotId = slotId;
+ }
+
+ @Override
+ public void write()
+ {
+ ServerPackets.EX_STEADY_ONE_BOX_UPDATE.writeId(this);
+ writeInt(_achievementBox.getMonsterPoints());
+ writeInt(_achievementBox.getPvpPoints());
+ final AchievementBoxHolder boxholder = _achievementBox.getAchievementBox().get(_slotId - 1);
+ writeInt(_slotId);
+ writeInt(boxholder.getState().ordinal());
+ writeInt(boxholder.getType().ordinal());
+ final int rewardTimeStage = ((int) ((_achievementBox.getBoxOpenTime() - System.currentTimeMillis()) / 1000));
+ writeInt(rewardTimeStage > 0 ? rewardTimeStage : 0);
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_6.2_Vanguard/readme.txt b/L2J_Mobius_Essence_6.2_Vanguard/readme.txt
index f11f6da222..08467382b1 100644
--- a/L2J_Mobius_Essence_6.2_Vanguard/readme.txt
+++ b/L2J_Mobius_Essence_6.2_Vanguard/readme.txt
@@ -133,6 +133,7 @@ Sylph: https://eu.4game.com/patchnotes/lineage2essence/281/
-Purge system
-Pledge donation system
-Hellbound spawns
+-Achievement box
Frost Lord: https://eu.4game.com/patchnotes/lineage2essence/329/
-Resurrection with payment
diff --git a/L2J_Mobius_Essence_6.3_Crusader/dist/db_installer/sql/game/achievement_box.sql b/L2J_Mobius_Essence_6.3_Crusader/dist/db_installer/sql/game/achievement_box.sql
new file mode 100644
index 0000000000..a6750eef4c
--- /dev/null
+++ b/L2J_Mobius_Essence_6.3_Crusader/dist/db_installer/sql/game/achievement_box.sql
@@ -0,0 +1,18 @@
+DROP TABLE IF EXISTS `achievement_box`;
+CREATE TABLE IF NOT EXISTS `achievement_box` (
+`charId` INT,
+`box_owned` INT NOT NULL DEFAULT 1,
+`monster_point` INT NOT NULL DEFAULT 0,
+`pvp_point` INT NOT NULL DEFAULT 0,
+`pending_box` INT NOT NULL DEFAULT 0,
+`open_time` BIGINT UNSIGNED NOT NULL DEFAULT 0,
+`box_state_slot_1` INT NOT NULL DEFAULT 1,
+`boxtype_slot_1` INT NOT NULL DEFAULT 0,
+`box_state_slot_2` INT NOT NULL DEFAULT 0,
+`boxtype_slot_2` INT NOT NULL DEFAULT 0,
+`box_state_slot_3` INT NOT NULL DEFAULT 0,
+`boxtype_slot_3` INT NOT NULL DEFAULT 0,
+`box_state_slot_4` INT NOT NULL DEFAULT 0,
+`boxtype_slot_4` INT NOT NULL DEFAULT 0,
+PRIMARY KEY (`charId`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_6.3_Crusader/dist/game/config/AchievementBox.ini b/L2J_Mobius_Essence_6.3_Crusader/dist/game/config/AchievementBox.ini
new file mode 100644
index 0000000000..3d91d7b746
--- /dev/null
+++ b/L2J_Mobius_Essence_6.3_Crusader/dist/game/config/AchievementBox.ini
@@ -0,0 +1,19 @@
+# --------------------------------------------------------------------------
+# Achievement Box Settings
+# --------------------------------------------------------------------------
+
+EnabledAchievementBox = True
+
+# Amount of mobs killed.
+# Retail is 1000.
+PointsForReward = 1000
+
+# --------------------------------------------------------------------------
+# Achievement Box PVP Settings
+# --------------------------------------------------------------------------
+
+EnabledAchievementPvP = True
+
+# Amount of Players killed.
+# Retail is 5.
+PointsForPvpReward = 5
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/Config.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/Config.java
index d1d566e8d7..374c9ad12c 100644
--- a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/Config.java
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/Config.java
@@ -104,6 +104,7 @@ public class Config
private static final String GRACIASEEDS_CONFIG_FILE = "./config/GraciaSeeds.ini";
private static final String GRANDBOSS_CONFIG_FILE = "./config/GrandBoss.ini";
private static final String HUNT_PASS_CONFIG_FILE = "./config/HuntPass.ini";
+ private static final String ACHIEVEMENT_BOX_CONFIG_FILE = "./config/AchievementBox.ini";
private static final String LOGIN_CONFIG_FILE = "./config/LoginServer.ini";
private static final String NPC_CONFIG_FILE = "./config/NPC.ini";
private static final String PVP_CONFIG_FILE = "./config/PVP.ini";
@@ -956,6 +957,12 @@ public class Config
public static int HUNT_PASS_PREMIUM_COST;
public static int HUNT_PASS_POINTS_FOR_STEP;
+ // Achivement Box
+ public static boolean ENABLE_ACHIEVEMENT_BOX;
+ public static int ACHIEVEMENT_BOX_POINTS_FOR_REWARD;
+ public static boolean ENABLE_ACHIEVEMENT_PVP;
+ public static int ACHIEVEMENT_BOX_PVP_POINTS_FOR_REWARD;
+
// GrandBoss Settings
// Antharas
@@ -2696,6 +2703,13 @@ public class Config
HUNT_PASS_POINTS_FOR_STEP = huntPassConfig.getInt("PointsForstep", 2400);
HUNT_PASS_PERIOD = huntPassConfig.getInt("DayOfMonth", 1);
+ // Load ArchivementBox (if exists)
+ final PropertiesParser achievementBoxConfig = new PropertiesParser(ACHIEVEMENT_BOX_CONFIG_FILE);
+ ENABLE_ACHIEVEMENT_BOX = achievementBoxConfig.getBoolean("EnabledAchievementBox", true);
+ ACHIEVEMENT_BOX_POINTS_FOR_REWARD = achievementBoxConfig.getInt("PointsForReward", 1000);
+ ENABLE_ACHIEVEMENT_PVP = achievementBoxConfig.getBoolean("EnabledAchievementPvP", true);
+ ACHIEVEMENT_BOX_PVP_POINTS_FOR_REWARD = achievementBoxConfig.getInt("PointsForPvpReward", 5);
+
// Gracia Seeds
final PropertiesParser graciaSeedsConfig = new PropertiesParser(GRACIASEEDS_CONFIG_FILE);
SOD_TIAT_KILL_COUNT = graciaSeedsConfig.getInt("TiatKillCountForNextState", 10);
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/enums/AchievementBoxState.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/enums/AchievementBoxState.java
new file mode 100644
index 0000000000..671455dfb8
--- /dev/null
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/enums/AchievementBoxState.java
@@ -0,0 +1,29 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.enums;
+
+/**
+ * @author Serenitty
+ */
+public enum AchievementBoxState
+{
+ LOCKED,
+ AVAILABLE,
+ OPEN,
+ UNLOCK_IN_PROGRESS,
+ RECEIVE_REWARD
+}
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/enums/AchievementBoxType.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/enums/AchievementBoxType.java
new file mode 100644
index 0000000000..aabe5ce5b9
--- /dev/null
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/enums/AchievementBoxType.java
@@ -0,0 +1,28 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.enums;
+
+/**
+ * @author Serenitty
+ */
+public enum AchievementBoxType
+{
+ LOCKED,
+ BOX_2H,
+ BOX_6H,
+ BOX_12H;
+}
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/model/AchievementBox.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/model/AchievementBox.java
new file mode 100644
index 0000000000..9f7d29d0e4
--- /dev/null
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/model/AchievementBox.java
@@ -0,0 +1,539 @@
+package org.l2jmobius.gameserver.model;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+import java.util.concurrent.ScheduledFuture;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.database.DatabaseFactory;
+import org.l2jmobius.commons.util.CommonUtil;
+import org.l2jmobius.commons.util.Rnd;
+import org.l2jmobius.gameserver.enums.AchievementBoxState;
+import org.l2jmobius.gameserver.enums.AchievementBoxType;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.holders.AchievementBoxHolder;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
+import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import org.l2jmobius.gameserver.network.serverpackets.steadybox.ExSteadyAllBoxUpdate;
+import org.l2jmobius.gameserver.network.serverpackets.steadybox.ExSteadyBoxReward;
+
+/**
+ * @author Serenitty, nlyyn, MacuK, Rudelitobr
+ */
+public class AchievementBox
+{
+ private static final Logger LOGGER = Logger.getLogger(AchievementBox.class.getName());
+
+ private static final int ACHIEVEMENT_BOX_2H = 7200000;
+ private static final int ACHIEVEMENT_BOX_6H = 21600000;
+ private static final int ACHIEVEMENT_BOX_12H = 43200000;
+
+ private final Player _owner;
+ private int _boxOwned = 1;
+ private int _monsterPoints = 0;
+ private int _pvpPoints = 0;
+ private int _pendingBoxSlotId = 0;
+ private int _pvpEndDate;
+ private long _boxTimeForOpen;
+ private final List _achievementBox = new ArrayList<>();
+ private ScheduledFuture> _boxOpenTask;
+
+ public AchievementBox(Player owner)
+ {
+ _owner = owner;
+ }
+
+ public int pvpEndDate()
+ {
+ return _pvpEndDate;
+ }
+
+ public void addPoints(int value)
+ {
+ final int newPoints = Math.min(Config.ACHIEVEMENT_BOX_POINTS_FOR_REWARD, _monsterPoints + value);
+ if (newPoints >= Config.ACHIEVEMENT_BOX_POINTS_FOR_REWARD)
+ {
+ if (addNewBox())
+ {
+ _monsterPoints = 0;
+ }
+ else
+ {
+ _monsterPoints = Config.ACHIEVEMENT_BOX_POINTS_FOR_REWARD;
+ }
+ return;
+ }
+ _monsterPoints += value;
+ }
+
+ public void addPvpPoints(int value)
+ {
+ final int newPoints = Math.min(Config.ACHIEVEMENT_BOX_PVP_POINTS_FOR_REWARD, _pvpPoints);
+ while (newPoints >= Config.ACHIEVEMENT_BOX_PVP_POINTS_FOR_REWARD)
+ {
+ if (addNewBox())
+ {
+ _pvpPoints = 0;
+ }
+ else
+ {
+ _pvpPoints = Config.ACHIEVEMENT_BOX_PVP_POINTS_FOR_REWARD;
+ }
+ return;
+ }
+ _pvpPoints += value;
+ }
+
+ public void restore()
+ {
+ tryFinishBox();
+ refreshPvpEndDate();
+ try (Connection con = DatabaseFactory.getConnection();
+ PreparedStatement ps = con.prepareStatement("SELECT * FROM achievement_box WHERE charId=?"))
+ {
+ ps.setInt(1, _owner.getObjectId());
+ try (ResultSet rs = ps.executeQuery())
+ {
+ if (rs.next())
+ {
+ try
+ {
+ _boxOwned = rs.getInt("box_owned");
+ _monsterPoints = rs.getInt("monster_point");
+ _pvpPoints = rs.getInt("pvp_point");
+ _pendingBoxSlotId = rs.getInt("pending_box");
+ _boxTimeForOpen = rs.getLong("open_time");
+ for (int i = 1; i <= 4; i++)
+ {
+ int state = rs.getInt("box_state_slot_" + i);
+ int type = rs.getInt("boxtype_slot_" + i);
+ if ((i == 1) && (state == 0))
+ {
+ state = 1;
+ }
+ final AchievementBoxHolder holder = new AchievementBoxHolder(i, state, type);
+ _achievementBox.add(i - 1, holder);
+ }
+ }
+ catch (Exception e)
+ {
+ LOGGER.warning("Could not restore Achievement box for " + _owner);
+ }
+ }
+ else
+ {
+ storeNew();
+ _achievementBox.add(0, new AchievementBoxHolder(1, 1, 0));
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ LOGGER.log(Level.WARNING, "Could not restore achievement box for " + _owner, e);
+ }
+ }
+
+ public void storeNew()
+ {
+ try (Connection con = DatabaseFactory.getConnection();
+ PreparedStatement ps = con.prepareStatement("INSERT INTO achievement_box VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?)"))
+ {
+ ps.setInt(1, _owner.getObjectId());
+ ps.setInt(2, _boxOwned);
+ ps.setInt(3, _monsterPoints);
+ ps.setInt(4, _pvpPoints);
+ ps.setInt(5, _pendingBoxSlotId);
+ ps.setLong(6, _boxTimeForOpen);
+ for (int i = 0; i < 4; i++)
+ {
+ ps.setInt(7 + (i * 2), 0);
+ ps.setInt(8 + (i * 2), 0);
+ }
+ ps.executeUpdate();
+ }
+ catch (SQLException e)
+ {
+ LOGGER.warning("Could not store new Archivement Box for: " + _owner);
+ LOGGER.warning(CommonUtil.getStackTrace(e));
+ }
+ }
+
+ public void store()
+ {
+ try (Connection con = DatabaseFactory.getConnection();
+ PreparedStatement ps = con.prepareStatement("UPDATE achievement_box SET box_owned=?,monster_point=?,pvp_point=?,pending_box=?,open_time=?,box_state_slot_1=?,boxtype_slot_1=?,box_state_slot_2=?,boxtype_slot_2=?,box_state_slot_3=?,boxtype_slot_3=?,box_state_slot_4=?,boxtype_slot_4=? WHERE charId=?"))
+ {
+ ps.setInt(1, getBoxOwned());
+ ps.setInt(2, getMonsterPoints());
+ ps.setInt(3, getPvpPoints());
+ ps.setInt(4, getPendingBoxSlotId());
+ ps.setLong(5, getBoxOpenTime());
+ for (int i = 0; i < 4; i++)
+ {
+ if (_achievementBox.size() >= (i + 1))
+ {
+ AchievementBoxHolder holder = _achievementBox.get(i);
+ ps.setInt(6 + (i * 2), holder == null ? 0 : holder.getState().ordinal());
+ ps.setInt(7 + (i * 2), holder == null ? 0 : holder.getType().ordinal());
+ }
+ else
+ {
+ ps.setInt(6 + (i * 2), 0);
+ ps.setInt(7 + (i * 2), 0);
+ }
+ }
+ ps.setInt(14, _owner.getObjectId());
+ ps.execute();
+ }
+ catch (SQLException e)
+ {
+ LOGGER.log(Level.SEVERE, "Could not store Achievement Box for: " + _owner, e);
+ }
+ }
+
+ public List getAchievementBox()
+ {
+ return _achievementBox;
+ }
+
+ public boolean addNewBox()
+ {
+ AchievementBoxHolder free = null;
+ int id = -1;
+ for (int i = 1; i <= getBoxOwned(); i++)
+ {
+ final AchievementBoxHolder holder = getAchievementBox().get(i - 1);
+ if (holder.getState() == AchievementBoxState.AVAILABLE)
+ {
+ free = holder;
+ id = i;
+ break;
+ }
+ }
+ if (free != null)
+ {
+ int rnd = Rnd.get(0, 100);
+ free.setType(rnd < 12 ? AchievementBoxType.BOX_12H : rnd < 40 ? AchievementBoxType.BOX_6H : AchievementBoxType.BOX_2H);
+ switch (free.getType())
+ {
+ case BOX_2H:
+ case BOX_6H:
+ case BOX_12H:
+ {
+ free.setState(AchievementBoxState.OPEN);
+ getAchievementBox().remove(id - 1);
+ getAchievementBox().add(id - 1, free);
+ sendBoxUpdate();
+ break;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public void openBox(int slotId)
+ {
+ if (slotId > getBoxOwned())
+ {
+ return;
+ }
+
+ final AchievementBoxHolder holder = getAchievementBox().get(slotId - 1);
+ if ((holder == null) || (_boxTimeForOpen != 0))
+ {
+ return;
+ }
+
+ _pendingBoxSlotId = slotId;
+
+ switch (holder.getType())
+ {
+ case BOX_2H:
+ {
+ setBoxTimeForOpen(ACHIEVEMENT_BOX_2H);
+ holder.setState(AchievementBoxState.UNLOCK_IN_PROGRESS);
+ getAchievementBox().remove(slotId - 1);
+ getAchievementBox().add(slotId - 1, holder);
+ sendBoxUpdate();
+ break;
+ }
+ case BOX_6H:
+ {
+ setBoxTimeForOpen(ACHIEVEMENT_BOX_6H);
+ holder.setState(AchievementBoxState.UNLOCK_IN_PROGRESS);
+ getAchievementBox().remove(slotId - 1);
+ getAchievementBox().add(slotId - 1, holder);
+ sendBoxUpdate();
+ break;
+ }
+ case BOX_12H:
+ {
+ setBoxTimeForOpen(ACHIEVEMENT_BOX_12H);
+ holder.setState(AchievementBoxState.UNLOCK_IN_PROGRESS);
+ getAchievementBox().remove(slotId - 1);
+ getAchievementBox().add(slotId - 1, holder);
+ sendBoxUpdate();
+ break;
+ }
+ }
+ }
+
+ public void skipBoxOpenTime(int slotId, long fee)
+ {
+ if (slotId > getBoxOwned())
+ {
+ return;
+ }
+
+ final AchievementBoxHolder holder = getAchievementBox().get(slotId - 1);
+ if ((holder != null) && _owner.destroyItemByItemId("Take Achievement Box", Inventory.LCOIN_ID, fee, _owner, true))
+ {
+ if (_pendingBoxSlotId == slotId)
+ {
+ cancelTask();
+ }
+ finishAndUnlockChest(slotId);
+ }
+ }
+
+ public boolean setBoxTimeForOpen(long time)
+ {
+ if ((_boxOpenTask != null) && !(_boxOpenTask.isDone() || _boxOpenTask.isCancelled()))
+ {
+ return false;
+ }
+
+ _boxTimeForOpen = System.currentTimeMillis() + time;
+ return true;
+ }
+
+ public void tryFinishBox()
+ {
+ if ((_boxTimeForOpen == 0) || (_boxTimeForOpen >= System.currentTimeMillis()))
+ {
+ return;
+ }
+
+ if ((_owner == null) || !_owner.isOnline())
+ {
+ return;
+ }
+
+ final AchievementBoxHolder holder = getAchievementBox().get(_pendingBoxSlotId - 1);
+ if (holder != null)
+ {
+ finishAndUnlockChest(_pendingBoxSlotId);
+ }
+ }
+
+ public int getBoxOwned()
+ {
+ return _boxOwned;
+ }
+
+ public int getMonsterPoints()
+ {
+ return _monsterPoints;
+ }
+
+ public int getPvpPoints()
+ {
+ return _pvpPoints;
+ }
+
+ public int getPendingBoxSlotId()
+ {
+ return _pendingBoxSlotId;
+ }
+
+ public long getBoxOpenTime()
+ {
+ return _boxTimeForOpen;
+ }
+
+ public void finishAndUnlockChest(int id)
+ {
+ if (id > getBoxOwned())
+ {
+ return;
+ }
+
+ if (_pendingBoxSlotId == id)
+ {
+ _boxTimeForOpen = 0;
+ _pendingBoxSlotId = 0;
+ }
+
+ getAchievementBox().get(id - 1).setState(AchievementBoxState.RECEIVE_REWARD);
+ sendBoxUpdate();
+ }
+
+ public void sendBoxUpdate()
+ {
+ _owner.sendPacket(new ExSteadyAllBoxUpdate(_owner));
+ }
+
+ public void cancelTask()
+ {
+ if (_boxOpenTask == null)
+ {
+ return;
+ }
+
+ _boxOpenTask.cancel(false);
+ _boxOpenTask = null;
+ }
+
+ public void unlockSlot(int slotId)
+ {
+ if (((slotId - 1) != getBoxOwned()) || (slotId > 4))
+ {
+ return;
+ }
+
+ boolean paidSlot = false;
+ switch (slotId)
+ {
+ case 2:
+ {
+ if (_owner.reduceAdena("Adena " + slotId, 100000000, _owner, true))
+ {
+ paidSlot = true;
+ }
+ break;
+ }
+ case 3:
+ {
+ if (_owner.destroyItemByItemId("L coin " + slotId, Inventory.LCOIN_ID, 2000, _owner, true))
+ {
+ paidSlot = true;
+ }
+ break;
+ }
+ case 4:
+ {
+ if (_owner.destroyItemByItemId("L coin " + slotId, Inventory.LCOIN_ID, 8000, _owner, true))
+ {
+ paidSlot = true;
+ }
+ break;
+ }
+ }
+
+ if (paidSlot)
+ {
+ _boxOwned = slotId;
+ final AchievementBoxHolder holder = new AchievementBoxHolder(slotId, 1, 0);
+ holder.setState(AchievementBoxState.AVAILABLE);
+ holder.setType(AchievementBoxType.LOCKED);
+ getAchievementBox().add(slotId - 1, holder);
+ sendBoxUpdate();
+ }
+ }
+
+ public void getReward(int slotId)
+ {
+ final AchievementBoxHolder holder = getAchievementBox().get(slotId - 1);
+ if (holder.getState() != AchievementBoxState.RECEIVE_REWARD)
+ {
+ return;
+ }
+
+ final int rnd = Rnd.get(100);
+ ItemHolder reward = null;
+ switch (holder.getType())
+ {
+ case BOX_2H:
+ {
+ if (rnd < 3)
+ {
+ reward = new ItemHolder(Rnd.get(72084, 72102), 1);
+ }
+ else if (rnd < 30)
+ {
+ reward = new ItemHolder(93274, 5); // Sayha Cookie
+ }
+ else if (rnd < 70)
+ {
+ reward = new ItemHolder(90907, 250); // Soulshot Ticket
+ }
+ else
+ {
+ reward = new ItemHolder(3031, 50); // Spirit Ore
+ }
+ break;
+ }
+ case BOX_6H:
+ {
+ if (rnd < 10)
+ {
+ reward = new ItemHolder(Rnd.get(72084, 72102), 1);
+ }
+ else if (rnd < 30)
+ {
+ reward = new ItemHolder(93274, 10); // Sayha Cookie
+ }
+ else if (rnd < 70)
+ {
+ reward = new ItemHolder(90907, 500); // Soulshot Ticket
+ }
+ else
+ {
+ reward = new ItemHolder(3031, 100); // Spirit Ore
+ }
+ break;
+ }
+ case BOX_12H:
+ {
+ if (rnd < 20)
+ {
+ reward = new ItemHolder(Rnd.get(72084, 72102), 1);
+ }
+ else if (rnd < 30)
+ {
+ reward = new ItemHolder(93274, 20); // Sayha Cookie
+ }
+ else if (rnd < 70)
+ {
+ reward = new ItemHolder(90907, 1000); // Soulshot Ticket
+ }
+ else
+ {
+ reward = new ItemHolder(3031, 200); // Spirit Ore
+ }
+ break;
+ }
+ }
+
+ holder.setState(AchievementBoxState.AVAILABLE);
+ holder.setType(AchievementBoxType.LOCKED);
+ sendBoxUpdate();
+ if (reward != null)
+ {
+ _owner.addItem("Chest unlock", reward, _owner, true);
+ _owner.sendPacket(new ExSteadyBoxReward(slotId, reward.getId(), reward.getCount()));
+ }
+ }
+
+ public void refreshPvpEndDate()
+ {
+ final long currentTime = System.currentTimeMillis();
+ final Calendar calendar = Calendar.getInstance();
+ calendar.setTimeInMillis(currentTime);
+ calendar.set(Calendar.DAY_OF_MONTH, 1);
+ calendar.set(Calendar.HOUR_OF_DAY, 6);
+ if (calendar.getTimeInMillis() < currentTime)
+ {
+ calendar.add(Calendar.MONTH, 1);
+ }
+ _pvpEndDate = (int) (calendar.getTimeInMillis() / 1000);
+ }
+}
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/model/Party.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/model/Party.java
index 0f0c401de4..2d72c27fcb 100644
--- a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/model/Party.java
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/model/Party.java
@@ -895,6 +895,12 @@ public class Party extends AbstractPlayerGroup
{
huntpass.addPassPoint(exp);
}
+
+ final AchievementBox box = member.getAchievementBox();
+ if (box != null)
+ {
+ member.getAchievementBox().addPoints(1);
+ }
}
}
else
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/model/actor/Attackable.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/model/actor/Attackable.java
index 379acd8294..3480884ddd 100644
--- a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/model/actor/Attackable.java
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/model/actor/Attackable.java
@@ -46,6 +46,7 @@ import org.l2jmobius.gameserver.instancemanager.CursedWeaponsManager;
import org.l2jmobius.gameserver.instancemanager.PcCafePointsManager;
import org.l2jmobius.gameserver.instancemanager.WalkingManager;
import org.l2jmobius.gameserver.instancemanager.events.EventDropManager;
+import org.l2jmobius.gameserver.model.AchievementBox;
import org.l2jmobius.gameserver.model.AggroInfo;
import org.l2jmobius.gameserver.model.CommandChannel;
import org.l2jmobius.gameserver.model.DamageDoneInfo;
@@ -613,6 +614,12 @@ public class Attackable extends Npc
{
attacker.getHuntPass().addPassPoint(exp);
}
+
+ final AchievementBox box = attacker.getAchievementBox();
+ if (box != null)
+ {
+ attacker.getAchievementBox().addPoints(1);
+ }
}
}
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/model/actor/Player.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/model/actor/Player.java
index 4303144b35..2998e23357 100644
--- a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/model/actor/Player.java
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/model/actor/Player.java
@@ -143,6 +143,7 @@ import org.l2jmobius.gameserver.instancemanager.SellBuffsManager;
import org.l2jmobius.gameserver.instancemanager.SiegeManager;
import org.l2jmobius.gameserver.instancemanager.ZoneManager;
import org.l2jmobius.gameserver.model.AccessLevel;
+import org.l2jmobius.gameserver.model.AchievementBox;
import org.l2jmobius.gameserver.model.ArenaParticipantsHolder;
import org.l2jmobius.gameserver.model.BlockList;
import org.l2jmobius.gameserver.model.ClientSettings;
@@ -963,6 +964,7 @@ public class Player extends Playable
private final Map _purgePoints = new HashMap<>();
private final HuntPass _huntPass;
+ private final AchievementBox _achivemenetBox;
private final Map _petEvolves = new HashMap<>();
@@ -1259,6 +1261,7 @@ public class Player extends Playable
_appearance = app;
_huntPass = Config.ENABLE_HUNT_PASS ? new HuntPass(this) : null;
+ _achivemenetBox = Config.ENABLE_ACHIEVEMENT_BOX ? new AchievementBox(this) : null;
// Create an AI
getAI();
@@ -1355,6 +1358,11 @@ public class Player extends Playable
return _huntPass;
}
+ public AchievementBox getAchievementBox()
+ {
+ return _achivemenetBox;
+ }
+
/**
* @return the PlayerTemplate link to the Player.
*/
@@ -5414,6 +5422,10 @@ public class Player extends Playable
setPvpKills(_pvpKills + 1);
setTotalKills(getTotalKills() + 1);
updatePvpTitleAndColor(true);
+ if (Config.ENABLE_ACHIEVEMENT_PVP)
+ {
+ getAchievementBox().addPvpPoints(1);
+ }
}
else if ((getReputation() > 0) && (_pkKills == 0))
{
@@ -7072,7 +7084,7 @@ public class Player extends Playable
player.setOnlineStatus(true, false);
PlayerAutoSaveTaskManager.getInstance().add(player);
-
+ player.getAchievementBox().restore();
}
catch (Exception e)
{
@@ -7396,6 +7408,11 @@ public class Player extends Playable
{
_huntPass.store();
}
+
+ if (_achivemenetBox != null)
+ {
+ _achivemenetBox.store();
+ }
}
@Override
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/model/holders/AchievementBoxHolder.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/model/holders/AchievementBoxHolder.java
new file mode 100644
index 0000000000..639b3082a8
--- /dev/null
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/model/holders/AchievementBoxHolder.java
@@ -0,0 +1,62 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.model.holders;
+
+import org.l2jmobius.gameserver.enums.AchievementBoxState;
+import org.l2jmobius.gameserver.enums.AchievementBoxType;
+
+/**
+ * @author Serenitty
+ */
+public class AchievementBoxHolder
+{
+ private final int _slotId;
+ private AchievementBoxState _boxState;
+ private AchievementBoxType _boxType;
+
+ public AchievementBoxHolder(int slotId, int boxState, int boxType)
+ {
+ _slotId = slotId;
+ _boxState = AchievementBoxState.values()[boxState];
+ _boxType = AchievementBoxType.values()[boxType];
+ }
+
+ public void setState(AchievementBoxState value)
+ {
+ _boxState = value;
+ }
+
+ public AchievementBoxState getState()
+ {
+ return _boxState;
+ }
+
+ public AchievementBoxType getType()
+ {
+ return _boxType;
+ }
+
+ public void setType(AchievementBoxType value)
+ {
+ _boxType = value;
+ }
+
+ public int getSlotId()
+ {
+ return _slotId;
+ }
+}
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/ExClientPackets.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/ExClientPackets.java
index 588dbda592..bb66728a4b 100644
--- a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/ExClientPackets.java
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/ExClientPackets.java
@@ -185,6 +185,10 @@ import org.l2jmobius.gameserver.network.clientpackets.shuttle.RequestShuttleGetO
import org.l2jmobius.gameserver.network.clientpackets.shuttle.RequestShuttleGetOn;
import org.l2jmobius.gameserver.network.clientpackets.stats.ExResetStatusBonus;
import org.l2jmobius.gameserver.network.clientpackets.stats.ExSetStatusBonus;
+import org.l2jmobius.gameserver.network.clientpackets.steadybox.RequestSteadyBoxLoad;
+import org.l2jmobius.gameserver.network.clientpackets.steadybox.RequestSteadyGetReward;
+import org.l2jmobius.gameserver.network.clientpackets.steadybox.RequestSteadyOpenBox;
+import org.l2jmobius.gameserver.network.clientpackets.steadybox.RequestSteadyOpenSlot;
import org.l2jmobius.gameserver.network.clientpackets.subjugation.RequestSubjugationGacha;
import org.l2jmobius.gameserver.network.clientpackets.subjugation.RequestSubjugationGachaUI;
import org.l2jmobius.gameserver.network.clientpackets.subjugation.RequestSubjugationList;
@@ -689,10 +693,10 @@ public enum ExClientPackets
EX_RANKING_FESTIVAL_MY_RECEIVED_BONUS(0x1D2, null, ConnectionState.IN_GAME),
EX_RANKING_FESTIVAL_REWARD(0x1D3, null, ConnectionState.IN_GAME),
EX_TIMER_CHECK(0x1D4, null, ConnectionState.IN_GAME),
- EX_STEADY_BOX_LOAD(0x1D5, null, ConnectionState.IN_GAME),
- EX_STEADY_OPEN_SLOT(0x1D6, null, ConnectionState.IN_GAME),
- EX_STEADY_OPEN_BOX(0x1D7, null, ConnectionState.IN_GAME),
- EX_STEADY_GET_REWARD(0x1D8, null, ConnectionState.IN_GAME),
+ EX_STEADY_BOX_LOAD(0x1D5, RequestSteadyBoxLoad::new, ConnectionState.IN_GAME),
+ EX_STEADY_OPEN_SLOT(0x1D6, RequestSteadyOpenSlot::new, ConnectionState.IN_GAME),
+ EX_STEADY_OPEN_BOX(0x1D7, RequestSteadyOpenBox::new, ConnectionState.IN_GAME),
+ EX_STEADY_GET_REWARD(0x1D8, RequestSteadyGetReward::new, ConnectionState.IN_GAME),
EX_PET_RANKING_MY_INFO(0x1D9, RequestPetRankingMyInfo::new, ConnectionState.IN_GAME),
EX_PET_RANKING_LIST(0x1DA, RequestPetRankingList::new, ConnectionState.IN_GAME),
EX_COLLECTION_OPEN_UI(0x1DB, RequestExCollectionOpenUI::new, ConnectionState.IN_GAME),
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java
index 28725b2176..4d3af75cf4 100644
--- a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/EnterWorld.java
@@ -123,6 +123,7 @@ import org.l2jmobius.gameserver.network.serverpackets.magiclamp.ExMagicLampExpIn
import org.l2jmobius.gameserver.network.serverpackets.pledgedonation.ExPledgeContributionList;
import org.l2jmobius.gameserver.network.serverpackets.randomcraft.ExCraftInfo;
import org.l2jmobius.gameserver.network.serverpackets.settings.ExItemAnnounceSetting;
+import org.l2jmobius.gameserver.network.serverpackets.steadybox.ExSteadyBoxUiInit;
import org.l2jmobius.gameserver.network.serverpackets.subjugation.ExSubjugationSidebar;
import org.l2jmobius.gameserver.util.BuilderUtil;
@@ -688,6 +689,11 @@ public class EnterWorld implements ClientPacket
player.sendPacket(new HuntPassSimpleInfo(player));
}
+ if (Config.ENABLE_ACHIEVEMENT_BOX)
+ {
+ player.sendPacket(new ExSteadyBoxUiInit(player));
+ }
+
for (int category = 1; category <= 7; category++)
{
player.sendPacket(new ExCollectionInfo(player, category));
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyBoxLoad.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyBoxLoad.java
new file mode 100644
index 0000000000..857e566c55
--- /dev/null
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyBoxLoad.java
@@ -0,0 +1,41 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.steadybox;
+
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.ClientPacket;
+import org.l2jmobius.gameserver.network.serverpackets.steadybox.ExSteadyAllBoxUpdate;
+
+/**
+ * @author Serenitty
+ */
+public class RequestSteadyBoxLoad implements ClientPacket
+{
+ @Override
+ public void run(GameClient client)
+ {
+ final Player player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ player.getAchievementBox().tryFinishBox();
+ player.sendPacket(new ExSteadyAllBoxUpdate(player));
+ }
+}
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyGetReward.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyGetReward.java
new file mode 100644
index 0000000000..d15ab61f00
--- /dev/null
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyGetReward.java
@@ -0,0 +1,48 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.steadybox;
+
+import org.l2jmobius.commons.network.ReadablePacket;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.ClientPacket;
+
+/**
+ * @author Serenitty
+ */
+public class RequestSteadyGetReward implements ClientPacket
+{
+ private int _slotId;
+
+ @Override
+ public void read(ReadablePacket packet)
+ {
+ _slotId = packet.readInt();
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final Player player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ player.getAchievementBox().getReward(_slotId);
+ }
+}
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyOpenBox.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyOpenBox.java
new file mode 100644
index 0000000000..550efa0e79
--- /dev/null
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyOpenBox.java
@@ -0,0 +1,57 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.steadybox;
+
+import org.l2jmobius.commons.network.ReadablePacket;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.ClientPacket;
+
+/**
+ * @author Serenitty
+ */
+public class RequestSteadyOpenBox implements ClientPacket
+{
+ private int _slotId;
+ private long _feeBoxPrice;
+
+ @Override
+ public void read(ReadablePacket packet)
+ {
+ _slotId = packet.readInt();
+ _feeBoxPrice = packet.readLong();
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final Player player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ if (_feeBoxPrice > 0)
+ {
+ player.getAchievementBox().skipBoxOpenTime(_slotId, _feeBoxPrice);
+ }
+ else
+ {
+ player.getAchievementBox().openBox(_slotId);
+ }
+ }
+}
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyOpenSlot.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyOpenSlot.java
new file mode 100644
index 0000000000..049ed91873
--- /dev/null
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/clientpackets/steadybox/RequestSteadyOpenSlot.java
@@ -0,0 +1,49 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.steadybox;
+
+import org.l2jmobius.commons.network.ReadablePacket;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.ClientPacket;
+
+/**
+ * @author Serenitty
+ */
+public class RequestSteadyOpenSlot implements ClientPacket
+{
+ private int _slotId;
+
+ @Override
+ public void read(ReadablePacket packet)
+ {
+ _slotId = packet.readInt();
+
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ final Player player = client.getPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ player.getAchievementBox().unlockSlot(_slotId);
+ }
+}
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyAllBoxUpdate.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyAllBoxUpdate.java
new file mode 100644
index 0000000000..88ab530ce2
--- /dev/null
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyAllBoxUpdate.java
@@ -0,0 +1,57 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.steadybox;
+
+import org.l2jmobius.gameserver.model.AchievementBox;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.holders.AchievementBoxHolder;
+import org.l2jmobius.gameserver.network.ServerPackets;
+import org.l2jmobius.gameserver.network.serverpackets.ServerPacket;
+
+/**
+ * @author Serenitty
+ */
+public class ExSteadyAllBoxUpdate extends ServerPacket
+{
+ private final AchievementBox _achievementBox;
+
+ public ExSteadyAllBoxUpdate(Player player)
+ {
+ _achievementBox = player.getAchievementBox();
+ }
+
+ @Override
+ public void write()
+ {
+ ServerPackets.EX_STEADY_ALL_BOX_UPDATE.writeId(this);
+
+ writeInt(_achievementBox.getMonsterPoints());
+ writeInt(_achievementBox.getPvpPoints());
+ writeInt(_achievementBox.getBoxOwned());
+
+ for (int i = 1; i <= _achievementBox.getBoxOwned(); i++)
+ {
+ final AchievementBoxHolder boxholder = _achievementBox.getAchievementBox().get(i - 1);
+ writeInt(i); //
+ writeInt(boxholder.getState().ordinal());
+ writeInt(boxholder.getType().ordinal());
+ }
+
+ final int rewardTimeStage = (int) ((_achievementBox.getBoxOpenTime() - System.currentTimeMillis()) / 1000);
+ writeInt(rewardTimeStage > 0 ? rewardTimeStage : 0);
+ }
+}
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyBoxReward.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyBoxReward.java
new file mode 100644
index 0000000000..43f55025b6
--- /dev/null
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyBoxReward.java
@@ -0,0 +1,47 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.steadybox;
+
+import org.l2jmobius.gameserver.network.ServerPackets;
+import org.l2jmobius.gameserver.network.serverpackets.ServerPacket;
+
+/**
+ * @author Serenitty
+ */
+public class ExSteadyBoxReward extends ServerPacket
+{
+ private final int _slotId;
+ private final int _itemId;
+ private final long _itemCount;
+
+ public ExSteadyBoxReward(int slotId, int itemId, long itemCount)
+ {
+ _slotId = slotId;
+ _itemId = itemId;
+ _itemCount = itemCount;
+ }
+
+ @Override
+ public void write()
+ {
+ ServerPackets.EX_STEADY_BOX_REWARD.writeId(this);
+ writeInt(_slotId);
+ writeInt(_itemId);
+ writeLong(_itemCount);
+ writeInt(0);
+ }
+}
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyBoxUiInit.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyBoxUiInit.java
new file mode 100644
index 0000000000..03daa26a57
--- /dev/null
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyBoxUiInit.java
@@ -0,0 +1,97 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.steadybox;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import org.l2jmobius.gameserver.network.ServerPackets;
+import org.l2jmobius.gameserver.network.serverpackets.ServerPacket;
+
+/**
+ * @author Serenitty
+ */
+public class ExSteadyBoxUiInit extends ServerPacket
+{
+ private static final int[] OPEN_PRICE =
+ {
+ 500,
+ 1000,
+ 1500
+ };
+ private static final int[] WAIT_TIME =
+ {
+ 0,
+ 60,
+ 180,
+ 360,
+ 540
+ };
+ private static final int[] TIME_PRICE =
+ {
+ 100,
+ 500,
+ 1000,
+ 1500,
+ 2000
+ };
+
+ private final Player _player;
+
+ public ExSteadyBoxUiInit(Player player)
+ {
+ _player = player;
+ }
+
+ @Override
+ public void write()
+ {
+ ServerPackets.EX_STEADY_BOX_UI_INIT.writeId(this);
+
+ writeInt(Config.ACHIEVEMENT_BOX_POINTS_FOR_REWARD);
+ writeInt(Config.ACHIEVEMENT_BOX_PVP_POINTS_FOR_REWARD);
+ if (Config.ENABLE_ACHIEVEMENT_PVP)
+ {
+ writeInt(2); // EventID Normal Point + Pvp Point Bar
+ }
+ else
+ {
+ writeInt(0); // EventID Normal Point + Pvp Point Bar
+ }
+ writeInt(0); // nEventStartTime time for limitkill
+ writeInt(_player.getAchievementBox().pvpEndDate());
+
+ writeInt(OPEN_PRICE.length);
+ for (int i = 0; i < OPEN_PRICE.length; i++)
+ {
+ writeInt(i + 1);
+ writeInt(Inventory.LCOIN_ID);
+ writeLong(OPEN_PRICE[i]);
+ }
+
+ writeInt(TIME_PRICE.length);
+ for (int i = 0; i < TIME_PRICE.length; i++)
+ {
+ writeInt(WAIT_TIME[i]);
+ writeInt(Inventory.LCOIN_ID);
+ writeLong(TIME_PRICE[i]);
+ }
+
+ final int rewardTimeStage = (int) (_player.getAchievementBox().getBoxOpenTime() - System.currentTimeMillis()) / 1000;
+ writeInt(rewardTimeStage > 0 ? rewardTimeStage : 0);
+ }
+}
diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyOneBoxUpdate.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyOneBoxUpdate.java
new file mode 100644
index 0000000000..71ecfaced1
--- /dev/null
+++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/gameserver/network/serverpackets/steadybox/ExSteadyOneBoxUpdate.java
@@ -0,0 +1,52 @@
+/*
+ * 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 .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.steadybox;
+
+import org.l2jmobius.gameserver.model.AchievementBox;
+import org.l2jmobius.gameserver.model.actor.Player;
+import org.l2jmobius.gameserver.model.holders.AchievementBoxHolder;
+import org.l2jmobius.gameserver.network.ServerPackets;
+import org.l2jmobius.gameserver.network.serverpackets.ServerPacket;
+
+/**
+ * @author Serenitty
+ */
+public class ExSteadyOneBoxUpdate extends ServerPacket
+{
+ private final AchievementBox _achievementBox;
+ private final int _slotId;
+
+ public ExSteadyOneBoxUpdate(Player player, int slotId)
+ {
+ _achievementBox = player.getAchievementBox();
+ _slotId = slotId;
+ }
+
+ @Override
+ public void write()
+ {
+ ServerPackets.EX_STEADY_ONE_BOX_UPDATE.writeId(this);
+ writeInt(_achievementBox.getMonsterPoints());
+ writeInt(_achievementBox.getPvpPoints());
+ final AchievementBoxHolder boxholder = _achievementBox.getAchievementBox().get(_slotId - 1);
+ writeInt(_slotId);
+ writeInt(boxholder.getState().ordinal());
+ writeInt(boxholder.getType().ordinal());
+ final int rewardTimeStage = ((int) ((_achievementBox.getBoxOpenTime() - System.currentTimeMillis()) / 1000));
+ writeInt(rewardTimeStage > 0 ? rewardTimeStage : 0);
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_6.3_Crusader/readme.txt b/L2J_Mobius_Essence_6.3_Crusader/readme.txt
index 068bcfac1d..c208ab8607 100644
--- a/L2J_Mobius_Essence_6.3_Crusader/readme.txt
+++ b/L2J_Mobius_Essence_6.3_Crusader/readme.txt
@@ -133,6 +133,7 @@ Sylph: https://eu.4game.com/patchnotes/lineage2essence/281/
-Purge system
-Pledge donation system
-Hellbound spawns
+-Achievement box
Frost Lord: https://eu.4game.com/patchnotes/lineage2essence/329/
-Resurrection with payment