diff --git a/.gitignore b/.gitignore
index 12bf4644a3..ea3a637b1d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -63,6 +63,10 @@
/tools/MapleQuestMesoFetcher/dist/
/tools/MapleQuestMesoFetcher/nbproject/
+/tools/MapleReactorDropFetcher/build/
+/tools/MapleReactorDropFetcher/dist/
+/tools/MapleReactorDropFetcher/nbproject/
+
/tools/MapleSkillMakerFetcher/build/
/tools/MapleSkillMakerFetcher/dist/
/tools/MapleSkillMakerFetcher/nbproject/
diff --git a/docs/feature_list.md b/docs/feature_list.md
index 2d008af778..7df541e9a1 100644
--- a/docs/feature_list.md
+++ b/docs/feature_list.md
@@ -50,6 +50,7 @@ Player Social Network:
* Guild and Alliance system fully functional.
* Beginners can create and join a "beginner-only" party (characters up to level 10).
* Enhanced synchronization on Player Shops and Hired Merchants. Transactions made are instantly informed to the owner.
+* Game minirooms such as match cards and omok now has semi-functional password system.
Cash & Items:
@@ -131,6 +132,7 @@ External tools:
* MapleQuestItemCountFetcher - Searches the quest WZ files and reports in all relevant data regarding missing "count" labels on item acts at "complete quest".
* MapleQuestItemFetcher - Searches the SQL tables and project files and reports in all relevant data regarding missing/erroneous quest items.
* MapleQuestMesoFetcher - Searches the quest WZ files and reports in all relevant data regarding missing/erroneous quest fee checks.
+* MapleReactorDropFetcher - Searches the DB for reactors with drop data and reports in reactorids that are not yet coded.
* MapleSkillMakerFetcher - Updates the DB Maker-related tables with the current info present on the WZs.
* MapleSkillMakerReagentIndexer - Generates a new maker table describing all stat-improvements from the Maker reagents (those empowering crystals and jewels).
diff --git a/docs/mychanges_ptbr.txt b/docs/mychanges_ptbr.txt
index 7c03a05e2a..740064462c 100644
--- a/docs/mychanges_ptbr.txt
+++ b/docs/mychanges_ptbr.txt
@@ -850,35 +850,35 @@ Adicionado sistema de bonus para expedição de Showa, atingível se nenhum joga
Nova ferramenta: MapleBossHpBarFetcher. Localiza no Mob.wz ids de mobs que possuem um boss hp bar mas não são labelados como "boss".
Incrementado quiz de 3rd job, agora utilizando um pool de 40 perguntas com escolha arbitrária.
-05 - 10 Março 2018,
+05 - 10 Abril 2018,
Corrigido diseases não sendo removidas corretamente no cliente quando tentando trocar de canal/entrar Cash Shop, permitindo-as ficar no jogador infinitamente.
Corrigido Holy Symbol atuando de forma inesperada no cenário com somente um jogador.
Corrigido Summon Sack lv. 9 lançando mob com id inexistente.
Corrigido NPC de guild tirando mesos do jogador sem efetuar a ação alguma caso o número máximo de jogadores tenha sido alcançado.
-11 - 12 Março 2018,
+11 - 12 Abril 2018,
Localhost melhorado: retirado caps de Matk, Mdef, Wdef, Acc e Avoid.
Balanceado Ninja Ambush, agora dando uma quantidade de dano justificável.
Implementado questline do Dyle.
Corrigido possível exploit com sistema de quests, onde jogador podia começar e completar quaisquer quests livremente.
Nova ferramenta: MapleCashDropFetcher. Aplicação busca por drop data de cash na DB e reporta.
-13 - 14 Março 2018,
+13 - 14 Abril 2018,
Adicionado feature de anúncio de mudança de classe.
Adicionado drops faltando da questline Puppeteer de Aran.
Movimentação de GM rank para alguns comandos.
Corrigido autoassigner inesperadamente desconectando jogadores, quando o autoassigner do cliente está sendo utilizado.
Adicionado scripts para a questline de Full Swing de Aran.
-19 Março 2018,
+19 Abril 2018,
Tentativa de correção em reactors desconectando jogadores que tentam ativá-los com ataque básico ao mesmo tempo.
Adicionado feature de AutoJCE (créditos aos Acernis devs).
-20 - 22 Março 2018,
+20 - 22 Abril 2018,
Resolvido exploit com login, onde qualquer um (via packet editing) podia logar livremente com personagem de outras contas.
Nova ferramenta: MapleQuestlineFetcher. Busca nos XMLs e registra questids que ainda não possuem quest scripts.
-24 - 25 Março 2018,
+24 - 25 Abril 2018,
Corrigido sistema de levelup de equips desbalanceado para o cenário low-level, distribuindo uma quantidade de EXP extremamente baixa.
Corrigido flag EQUIP_EXP_RATE atuando de forma errônea.
Modificado sistema do chaos scroll, agora utilizando uma flag nova ao invés de reusar flag SCROLL_CHANCE_RATE.
@@ -887,11 +887,24 @@ Corrigido alguns aspectos do BalrogPQ, tais como a cabeça sendo atingível ante
Corrigido barras da tela de seleção de canais na etapa de login não atuando corretamente.
Adicionado checks de world server lotado de diversos pontos das etapas de login.
-26 Março 2018,
+26 Abril 2018,
Corrigido sistema de levelup ainda desbalanceado para o cenário EXTREMAMENTE low-level.
Adicionado suporte para quests de Kerning Square e Mushroom Castle.
Adicionado script para várias quests ainda não-scriptadas.
Refatorado medal quests, agora adotando um sistema de script default para aquelas não-scriptadas.
Adicionado comando "debuff", debuffando em área próximo ao character que ativou o comando.
Corrigido vazamento de dados na DB referente às informações de quest status e medal maps dos jogadores.
-Adicionado checagem de proximidade aos NPCs para começar e terminar quests sem lightbulb.
\ No newline at end of file
+Adicionado checagem de proximidade aos NPCs para começar e terminar quests sem lightbulb.
+
+27 Abril 2018,
+Edição de localhost: Removido popup de "excesso de AP" e bloqueios de "Admin/MWLB", créditos ao kevintjuh93.
+Edição de localhost: Removido popup de "You've gained a level!", créditos ao PrinceReborn.
+Adicionado script para vários reactors com drop data na DB mas ainda não-scriptados.
+Melhorado updates de quest status, agora utilizando uma nova coluna "characterid" para facilitar retirada de antigos elementos da tabela.
+Corrigido vários status de diseases não aparecendo para outros jogadores.
+Corrigido item de MapleTV sendo retirado 2x ao usar.
+
+29 Abril 2018,
+Implementado sistema de senhas para minirooms de match cards/omok.
+Adicionado/documentado mensagens de erro apropriados ao criar/visitar minirooms.
+Implementado expel em minirooms de jogos.
\ No newline at end of file
diff --git a/docs/todo.txt b/docs/todo.txt
index 0430301e76..1a7c3eece5 100644
--- a/docs/todo.txt
+++ b/docs/todo.txt
@@ -7,10 +7,13 @@ Vcoc - Freelance Developer
Known issues:
- Everytime two people click on an npc at the same time, one of them dcs and the other needs to @dispose to talk to the npc.
- If multiple people hit boxes/reactors at the same time, they both dc with invalid pointer error.
+- Passwords on minirooms are not encoded for players entering/logging into the map.
---------------------------
---------------------------
-ToDo / Missing features list:
+Missing features list:
+- Miniroom tooltips (such as number of players in store/host awaiting game) not showing up properly.
+- Disease POISON appears MISSES to other players.
---------------------------
diff --git a/scripts/npc/commands.js b/scripts/npc/commands.js
index 31459e9c94..be6f6bcae0 100644
--- a/scripts/npc/commands.js
+++ b/scripts/npc/commands.js
@@ -74,6 +74,7 @@ function writeSolaxiaCommandsLv5() { //Developer
addCommand("debugcoupons", "");
addCommand("debugplayercoupons", "");
addCommand("debugtimer", "");
+ addCommand("set", "");
}
function writeSolaxiaCommandsLv4() { //SuperGM
diff --git a/scripts/reactor/1022001.js b/scripts/reactor/1022001.js
new file mode 100644
index 0000000000..9371dcfa5c
--- /dev/null
+++ b/scripts/reactor/1022001.js
@@ -0,0 +1,26 @@
+/*
+ This file is part of the HeavenMS (MapleSolaxiaV2) MapleStory Server
+ Copyleft (L) 2017 RonanLana
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as
+ published by the Free Software Foundation version 3 as published by
+ the Free Software Foundation. You may not use, modify or distribute
+ this program under any other version of the GNU Affero General Public
+ License.
+
+ 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+
+/* @Author Ronan
+*/
+
+function act() {
+ rm.dropItems();
+}
\ No newline at end of file
diff --git a/scripts/reactor/1032000.js b/scripts/reactor/1032000.js
new file mode 100644
index 0000000000..9371dcfa5c
--- /dev/null
+++ b/scripts/reactor/1032000.js
@@ -0,0 +1,26 @@
+/*
+ This file is part of the HeavenMS (MapleSolaxiaV2) MapleStory Server
+ Copyleft (L) 2017 RonanLana
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as
+ published by the Free Software Foundation version 3 as published by
+ the Free Software Foundation. You may not use, modify or distribute
+ this program under any other version of the GNU Affero General Public
+ License.
+
+ 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+
+/* @Author Ronan
+*/
+
+function act() {
+ rm.dropItems();
+}
\ No newline at end of file
diff --git a/scripts/reactor/200000.js b/scripts/reactor/200000.js
new file mode 100644
index 0000000000..9371dcfa5c
--- /dev/null
+++ b/scripts/reactor/200000.js
@@ -0,0 +1,26 @@
+/*
+ This file is part of the HeavenMS (MapleSolaxiaV2) MapleStory Server
+ Copyleft (L) 2017 RonanLana
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as
+ published by the Free Software Foundation version 3 as published by
+ the Free Software Foundation. You may not use, modify or distribute
+ this program under any other version of the GNU Affero General Public
+ License.
+
+ 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+
+/* @Author Ronan
+*/
+
+function act() {
+ rm.dropItems();
+}
\ No newline at end of file
diff --git a/scripts/reactor/200001.js b/scripts/reactor/200001.js
new file mode 100644
index 0000000000..9371dcfa5c
--- /dev/null
+++ b/scripts/reactor/200001.js
@@ -0,0 +1,26 @@
+/*
+ This file is part of the HeavenMS (MapleSolaxiaV2) MapleStory Server
+ Copyleft (L) 2017 RonanLana
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as
+ published by the Free Software Foundation version 3 as published by
+ the Free Software Foundation. You may not use, modify or distribute
+ this program under any other version of the GNU Affero General Public
+ License.
+
+ 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+
+/* @Author Ronan
+*/
+
+function act() {
+ rm.dropItems();
+}
\ No newline at end of file
diff --git a/scripts/reactor/200002.js b/scripts/reactor/200002.js
new file mode 100644
index 0000000000..9371dcfa5c
--- /dev/null
+++ b/scripts/reactor/200002.js
@@ -0,0 +1,26 @@
+/*
+ This file is part of the HeavenMS (MapleSolaxiaV2) MapleStory Server
+ Copyleft (L) 2017 RonanLana
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as
+ published by the Free Software Foundation version 3 as published by
+ the Free Software Foundation. You may not use, modify or distribute
+ this program under any other version of the GNU Affero General Public
+ License.
+
+ 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+
+/* @Author Ronan
+*/
+
+function act() {
+ rm.dropItems();
+}
\ No newline at end of file
diff --git a/scripts/reactor/200003.js b/scripts/reactor/200003.js
new file mode 100644
index 0000000000..9371dcfa5c
--- /dev/null
+++ b/scripts/reactor/200003.js
@@ -0,0 +1,26 @@
+/*
+ This file is part of the HeavenMS (MapleSolaxiaV2) MapleStory Server
+ Copyleft (L) 2017 RonanLana
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as
+ published by the Free Software Foundation version 3 as published by
+ the Free Software Foundation. You may not use, modify or distribute
+ this program under any other version of the GNU Affero General Public
+ License.
+
+ 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+
+/* @Author Ronan
+*/
+
+function act() {
+ rm.dropItems();
+}
\ No newline at end of file
diff --git a/scripts/reactor/200004.js b/scripts/reactor/200004.js
new file mode 100644
index 0000000000..9371dcfa5c
--- /dev/null
+++ b/scripts/reactor/200004.js
@@ -0,0 +1,26 @@
+/*
+ This file is part of the HeavenMS (MapleSolaxiaV2) MapleStory Server
+ Copyleft (L) 2017 RonanLana
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as
+ published by the Free Software Foundation version 3 as published by
+ the Free Software Foundation. You may not use, modify or distribute
+ this program under any other version of the GNU Affero General Public
+ License.
+
+ 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+
+/* @Author Ronan
+*/
+
+function act() {
+ rm.dropItems();
+}
\ No newline at end of file
diff --git a/scripts/reactor/200005.js b/scripts/reactor/200005.js
new file mode 100644
index 0000000000..9371dcfa5c
--- /dev/null
+++ b/scripts/reactor/200005.js
@@ -0,0 +1,26 @@
+/*
+ This file is part of the HeavenMS (MapleSolaxiaV2) MapleStory Server
+ Copyleft (L) 2017 RonanLana
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as
+ published by the Free Software Foundation version 3 as published by
+ the Free Software Foundation. You may not use, modify or distribute
+ this program under any other version of the GNU Affero General Public
+ License.
+
+ 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+
+/* @Author Ronan
+*/
+
+function act() {
+ rm.dropItems();
+}
\ No newline at end of file
diff --git a/scripts/reactor/200006.js b/scripts/reactor/200006.js
new file mode 100644
index 0000000000..9371dcfa5c
--- /dev/null
+++ b/scripts/reactor/200006.js
@@ -0,0 +1,26 @@
+/*
+ This file is part of the HeavenMS (MapleSolaxiaV2) MapleStory Server
+ Copyleft (L) 2017 RonanLana
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as
+ published by the Free Software Foundation version 3 as published by
+ the Free Software Foundation. You may not use, modify or distribute
+ this program under any other version of the GNU Affero General Public
+ License.
+
+ 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+
+/* @Author Ronan
+*/
+
+function act() {
+ rm.dropItems();
+}
\ No newline at end of file
diff --git a/scripts/reactor/200007.js b/scripts/reactor/200007.js
new file mode 100644
index 0000000000..9371dcfa5c
--- /dev/null
+++ b/scripts/reactor/200007.js
@@ -0,0 +1,26 @@
+/*
+ This file is part of the HeavenMS (MapleSolaxiaV2) MapleStory Server
+ Copyleft (L) 2017 RonanLana
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as
+ published by the Free Software Foundation version 3 as published by
+ the Free Software Foundation. You may not use, modify or distribute
+ this program under any other version of the GNU Affero General Public
+ License.
+
+ 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+
+/* @Author Ronan
+*/
+
+function act() {
+ rm.dropItems();
+}
\ No newline at end of file
diff --git a/scripts/reactor/200008.js b/scripts/reactor/200008.js
new file mode 100644
index 0000000000..9371dcfa5c
--- /dev/null
+++ b/scripts/reactor/200008.js
@@ -0,0 +1,26 @@
+/*
+ This file is part of the HeavenMS (MapleSolaxiaV2) MapleStory Server
+ Copyleft (L) 2017 RonanLana
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as
+ published by the Free Software Foundation version 3 as published by
+ the Free Software Foundation. You may not use, modify or distribute
+ this program under any other version of the GNU Affero General Public
+ License.
+
+ 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+
+/* @Author Ronan
+*/
+
+function act() {
+ rm.dropItems();
+}
\ No newline at end of file
diff --git a/scripts/reactor/200009.js b/scripts/reactor/200009.js
new file mode 100644
index 0000000000..9371dcfa5c
--- /dev/null
+++ b/scripts/reactor/200009.js
@@ -0,0 +1,26 @@
+/*
+ This file is part of the HeavenMS (MapleSolaxiaV2) MapleStory Server
+ Copyleft (L) 2017 RonanLana
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as
+ published by the Free Software Foundation version 3 as published by
+ the Free Software Foundation. You may not use, modify or distribute
+ this program under any other version of the GNU Affero General Public
+ License.
+
+ 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+
+/* @Author Ronan
+*/
+
+function act() {
+ rm.dropItems();
+}
\ No newline at end of file
diff --git a/scripts/reactor/2052001.js b/scripts/reactor/2052001.js
new file mode 100644
index 0000000000..9371dcfa5c
--- /dev/null
+++ b/scripts/reactor/2052001.js
@@ -0,0 +1,26 @@
+/*
+ This file is part of the HeavenMS (MapleSolaxiaV2) MapleStory Server
+ Copyleft (L) 2017 RonanLana
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as
+ published by the Free Software Foundation version 3 as published by
+ the Free Software Foundation. You may not use, modify or distribute
+ this program under any other version of the GNU Affero General Public
+ License.
+
+ 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+
+/* @Author Ronan
+*/
+
+function act() {
+ rm.dropItems();
+}
\ No newline at end of file
diff --git a/scripts/reactor/2112015.js b/scripts/reactor/2112015.js
new file mode 100644
index 0000000000..9371dcfa5c
--- /dev/null
+++ b/scripts/reactor/2112015.js
@@ -0,0 +1,26 @@
+/*
+ This file is part of the HeavenMS (MapleSolaxiaV2) MapleStory Server
+ Copyleft (L) 2017 RonanLana
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as
+ published by the Free Software Foundation version 3 as published by
+ the Free Software Foundation. You may not use, modify or distribute
+ this program under any other version of the GNU Affero General Public
+ License.
+
+ 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+
+/* @Author Ronan
+*/
+
+function act() {
+ rm.dropItems();
+}
\ No newline at end of file
diff --git a/sql/db_database.sql b/sql/db_database.sql
index 695670b3ab..04a209adf9 100644
--- a/sql/db_database.sql
+++ b/sql/db_database.sql
@@ -15990,6 +15990,7 @@ CREATE TABLE IF NOT EXISTS `marriages` (
CREATE TABLE IF NOT EXISTS `medalmaps` (
`id` int(11) NOT NULL AUTO_INCREMENT,
+ `characterid` int(11) NOT NULL,
`queststatusid` int(11) unsigned NOT NULL,
`mapid` int(11) NOT NULL,
PRIMARY KEY (`id`),
@@ -16508,6 +16509,7 @@ CREATE TABLE IF NOT EXISTS `questactions` (
CREATE TABLE IF NOT EXISTS `questprogress` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `characterid` int(11) NOT NULL,
`queststatusid` int(10) unsigned NOT NULL DEFAULT '0',
`progressid` int(11) NOT NULL DEFAULT '0',
`progress` varchar(15) CHARACTER SET latin1 COLLATE latin1_german1_ci NOT NULL DEFAULT '',
@@ -17240,8 +17242,8 @@ INSERT INTO `reactordrops` (`reactordropid`, `reactorid`, `itemid`, `chance`, `q
(693, 6702012, 3010011, 50, -1),
(694, 6702012, 3012000, 100, -1),
(695, 6702012, 3012005, 100, -1),
-(696, 1032000, 4001363, 1, -1),
-(697, 1032000, 4001362, 1, -1),
+(696, 1032000, 4001363, 1, 28252),
+(697, 1032000, 4001362, 1, 28252),
(698, 2512000, 2022131, 1, -1),
(699, 2512000, 2022132, 1, -1),
(700, 2612002, 4001134, 1, -1),
diff --git a/src/client/MapleCharacter.java b/src/client/MapleCharacter.java
index 6d240f7d86..b99400406a 100644
--- a/src/client/MapleCharacter.java
+++ b/src/client/MapleCharacter.java
@@ -1886,24 +1886,14 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
private static void deleteQuestProgressWhereCharacterId(Connection con, int cid) throws SQLException {
- try (PreparedStatement ps = con.prepareStatement("SELECT queststatusid FROM queststatus WHERE characterid = ?")) {
+ try (PreparedStatement ps = con.prepareStatement("DELETE FROM medalmaps WHERE characterid = ?")) {
ps.setInt(1, cid);
+ ps.executeUpdate();
+ }
- try (ResultSet rs = ps.executeQuery()) {
- while (rs.next()) {
- int queststatusid = rs.getInt("queststatusid");
-
- try (PreparedStatement ps2 = con.prepareStatement("DELETE FROM medalmaps WHERE queststatusid = ?")) {
- ps2.setInt(1, queststatusid);
- ps2.executeUpdate();
- }
-
- try (PreparedStatement ps2 = con.prepareStatement("DELETE FROM questprogress WHERE queststatusid = ?")) {
- ps2.setInt(1, queststatusid);
- ps2.executeUpdate();
- }
- }
- }
+ try (PreparedStatement ps = con.prepareStatement("DELETE FROM questprogress WHERE characterid = ?")) {
+ ps.setInt(1, cid);
+ ps.executeUpdate();
}
}
@@ -4309,7 +4299,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
this.setMiniGame(null);
if (game.isOwner(this)) {
this.getMap().broadcastMessage(MaplePacketCreator.removeCharBox(this));
- game.broadcastToVisitor(MaplePacketCreator.getMiniGameClose());
+ game.broadcastToVisitor(MaplePacketCreator.getMiniGameClose(3));
} else {
game.removeVisitor(this);
}
@@ -6663,8 +6653,8 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
deleteQuestProgressWhereCharacterId(con, id);
ps = con.prepareStatement("INSERT INTO queststatus (`queststatusid`, `characterid`, `quest`, `status`, `time`, `expires`, `forfeited`) VALUES (DEFAULT, ?, ?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS);
PreparedStatement psf;
- try (PreparedStatement pse = con.prepareStatement("INSERT INTO questprogress VALUES (DEFAULT, ?, ?, ?)")) {
- psf = con.prepareStatement("INSERT INTO medalmaps VALUES (DEFAULT, ?, ?)");
+ try (PreparedStatement pse = con.prepareStatement("INSERT INTO questprogress VALUES (DEFAULT, ?, ?, ?, ?)")) {
+ psf = con.prepareStatement("INSERT INTO medalmaps VALUES (DEFAULT, ?, ?, ?)");
ps.setInt(1, id);
synchronized (quests) {
@@ -6678,14 +6668,16 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
try (ResultSet rs = ps.getGeneratedKeys()) {
rs.next();
for (int mob : q.getProgress().keySet()) {
- pse.setInt(1, rs.getInt(1));
- pse.setInt(2, mob);
- pse.setString(3, q.getProgress(mob));
+ pse.setInt(1, id);
+ pse.setInt(2, rs.getInt(1));
+ pse.setInt(3, mob);
+ pse.setString(4, q.getProgress(mob));
pse.addBatch();
}
for (int i = 0; i < q.getMedalMaps().size(); i++) {
- psf.setInt(1, rs.getInt(1));
- psf.setInt(2, q.getMedalMaps().get(i));
+ psf.setInt(1, id);
+ psf.setInt(2, rs.getInt(1));
+ psf.setInt(3, q.getMedalMaps().get(i));
psf.addBatch();
}
pse.executeBatch();
diff --git a/src/client/command/Commands.java b/src/client/command/Commands.java
index 5ffa6687d4..45014bec10 100644
--- a/src/client/command/Commands.java
+++ b/src/client/command/Commands.java
@@ -1636,7 +1636,7 @@ public class Commands {
break;
}
- for (MapleMapObject mmo : player.getMap().getMapObjectsInRange(player.getPosition(), 1000.0, Arrays.asList(MapleMapObjectType.PLAYER))) {
+ for (MapleMapObject mmo : player.getMap().getMapObjectsInRange(player.getPosition(), 777777.7, Arrays.asList(MapleMapObjectType.PLAYER))) {
MapleCharacter chr = (MapleCharacter) mmo;
if(chr.getId() != player.getId()) {
@@ -2671,6 +2671,14 @@ public class Commands {
TimerManager tMan = TimerManager.getInstance();
player.dropMessage(6, "Total Task: " + tMan.getTaskCount() + " Current Task: " + tMan.getQueuedTasks() + " Active Task: " + tMan.getActiveCount() + " Completed Task: " + tMan.getCompletedTaskCount());
break;
+
+ case "set":
+ for(int i = 0; i < sub.length - 1; i++) {
+ ServerConstants.DEBUG_VALUES[i] = Integer.parseInt(sub[i + 1]);
+ }
+
+
+ break;
default:
return false;
diff --git a/src/constants/GameConstants.java b/src/constants/GameConstants.java
index fcb394d776..8eeb0c4708 100644
--- a/src/constants/GameConstants.java
+++ b/src/constants/GameConstants.java
@@ -4,6 +4,7 @@ import client.MapleJob;
import constants.skills.Aran;
import server.maps.MapleMap;
import server.maps.FieldLimit;
+import server.quest.MapleQuest;
/*
* @author kevintjuh93
@@ -211,7 +212,7 @@ public class GameConstants {
}
public static boolean isMedalQuest(short questid) {
- return questid / 100 == 299;
+ return MapleQuest.getInstance(questid).getMedalRequirement() != -1;
}
public static boolean hasSPTable(MapleJob job) {
diff --git a/src/constants/ServerConstants.java b/src/constants/ServerConstants.java
index b04fbee438..970ade8f67 100644
--- a/src/constants/ServerConstants.java
+++ b/src/constants/ServerConstants.java
@@ -166,7 +166,10 @@ public class ServerConstants {
//Event End Timestamp
public static final long EVENT_END_TIMESTAMP = 1428897600000L;
-
+
+ //Debug Variables
+ public static int DEBUG_VALUES[] = new int[10]; // Field designed for packet testing purposes
+
//Properties
static {
Properties p = new Properties();
diff --git a/src/net/server/channel/handlers/PlayerInteractionHandler.java b/src/net/server/channel/handlers/PlayerInteractionHandler.java
index 0e13420c7d..f8ebe4d2eb 100644
--- a/src/net/server/channel/handlers/PlayerInteractionHandler.java
+++ b/src/net/server/channel/handlers/PlayerInteractionHandler.java
@@ -93,6 +93,7 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
CANCEL_EXIT(0x39),
READY(0x3A),
UN_READY(0x3B),
+ EXPEL(0x3C),
START(0x3D),
GET_RESULT(0x3E),
SKIP(0x3F),
@@ -120,12 +121,15 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
MapleTrade.startTrade(chr);
} else if (createType == 1) { // omok mini game
if (chr.getChalkboard() != null || FieldLimit.CANNOTMINIGAME.check(chr.getMap().getFieldLimit())) {
+ chr.getClient().announce(MaplePacketCreator.getMiniRoomError(11));
return;
}
+
String desc = slea.readMapleAsciiString();
- slea.readByte(); // 20 6E 4E
- int type = slea.readByte(); // 20 6E 4E
- MapleMiniGame game = new MapleMiniGame(chr, desc);
+ int type = slea.readByte();
+ String pw = slea.available() > 1 ? slea.readMapleAsciiString() : "";
+
+ MapleMiniGame game = new MapleMiniGame(chr, desc, pw);
chr.setMiniGame(game);
game.setPieceType(type);
game.setGameType("omok");
@@ -133,13 +137,16 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
chr.getMap().broadcastMessage(MaplePacketCreator.addOmokBox(chr, 1, 0));
game.sendOmok(c, type);
} else if (createType == 2) { // matchcard
- if (chr.getChalkboard() != null) {
+ if (chr.getChalkboard() != null || FieldLimit.CANNOTMINIGAME.check(chr.getMap().getFieldLimit())) {
+ chr.getClient().announce(MaplePacketCreator.getMiniRoomError(11));
return;
}
+
String desc = slea.readMapleAsciiString();
- slea.readByte(); // 20 6E 4E
- int type = slea.readByte(); // 20 6E 4E
- MapleMiniGame game = new MapleMiniGame(chr, desc);
+ int type = slea.readByte();
+ String pw = slea.available() > 1 ? slea.readMapleAsciiString() : "";
+
+ MapleMiniGame game = new MapleMiniGame(chr, desc, pw);
game.setPieceType(type);
if (type == 0) {
game.setMatchesToWin(6);
@@ -155,12 +162,14 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
game.sendMatchCard(c, type);
} else if (createType == 4 || createType == 5) { // shop
if (!chr.getMap().getMapObjectsInRange(chr.getPosition(), 23000, Arrays.asList(MapleMapObjectType.SHOP, MapleMapObjectType.HIRED_MERCHANT)).isEmpty()) {
+ chr.getClient().announce(MaplePacketCreator.getMiniRoomError(14));
return;
}
String desc = slea.readMapleAsciiString();
slea.skip(3);
int itemId = slea.readInt();
if (chr.getInventory(MapleInventoryType.CASH).countById(itemId) < 1) {
+ chr.getClient().announce(MaplePacketCreator.getMiniRoomError(6));
return;
}
@@ -194,7 +203,7 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
if (!chr.getTrade().isFullTrade() && !chr.getTrade().getPartner().isFullTrade()) {
MapleTrade.visitTrade(chr, chr.getTrade().getPartner().getChr());
} else {
- c.announce(MaplePacketCreator.enableActions()); //Ill be nice and not dc u
+ chr.getClient().announce(MaplePacketCreator.getMiniRoomError(2));
return;
}
} else {
@@ -204,20 +213,27 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
MaplePlayerShop shop = (MaplePlayerShop) ob;
shop.visitShop(chr);
} else if (ob instanceof MapleMiniGame) {
+ slea.skip(1);
+ String pw = slea.available() > 1 ? slea.readMapleAsciiString() : "";
+
MapleMiniGame game = (MapleMiniGame) ob;
- if (game.hasFreeSlot() && !game.isVisitor(c.getPlayer())) {
- game.addVisitor(c.getPlayer());
- chr.setMiniGame(game);
- switch (game.getGameType()) {
- case "omok":
- game.sendOmok(c, game.getPieceType());
- break;
- case "matchcard":
- game.sendMatchCard(c, game.getPieceType());
- break;
+ if(game.checkPassword(pw) || game.checkPassword(c.getPlayer().getName())) {
+ if (game.hasFreeSlot() && !game.isVisitor(c.getPlayer())) {
+ game.addVisitor(c.getPlayer());
+ chr.setMiniGame(game);
+ switch (game.getGameType()) {
+ case "omok":
+ game.sendOmok(c, game.getPieceType());
+ break;
+ case "matchcard":
+ game.sendMatchCard(c, game.getPieceType());
+ break;
+ }
+ } else {
+ chr.getClient().announce(MaplePacketCreator.getMiniRoomError(2));
}
} else {
- chr.getClient().announce(MaplePacketCreator.getMiniGameFull());
+ chr.getClient().announce(MaplePacketCreator.getMiniRoomError(22));
}
} else if (ob instanceof MapleHiredMerchant && chr.getHiredMerchant() == null) {
MapleHiredMerchant merchant = (MapleHiredMerchant) ob;
@@ -227,10 +243,10 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
c.announce(MaplePacketCreator.getHiredMerchant(chr, merchant, false));
} else if (!merchant.isOpen()) {
- c.announce(MaplePacketCreator.hiredMerchantMaintenanceMessage());
+ chr.getClient().announce(MaplePacketCreator.getMiniRoomError(18));
return;
} else if (!merchant.addVisitor(c.getPlayer())) {
- chr.dropMessage(1, "This shop has reached it's maximum capacity, please come by later.");
+ chr.getClient().announce(MaplePacketCreator.getMiniRoomError(2));
return;
} else {
c.announce(MaplePacketCreator.getHiredMerchant(c.getPlayer(), merchant, false));
@@ -374,13 +390,13 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
} else if (mode == Action.SET_MESO.getCode()) {
chr.getTrade().setMeso(slea.readInt());
} else if (mode == Action.SET_ITEMS.getCode()) {
-
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
MapleInventoryType ivType = MapleInventoryType.getByType(slea.readByte());
Item item = chr.getInventory(ivType).getItem(slea.readShort());
short quantity = slea.readShort();
byte targetSlot = slea.readByte();
if (quantity < 1 || quantity > item.getQuantity()) {
+ c.announce(MaplePacketCreator.serverNotice(1, "You don't have enough quantity of the item."));
c.announce(MaplePacketCreator.enableActions());
return;
}
@@ -388,6 +404,7 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
if ((quantity <= item.getQuantity() && quantity >= 0) || ItemConstants.isRechargable(item.getItemId())) {
if (ii.isDropRestricted(item.getItemId())) { // ensure that undroppable items do not make it to the trade window
if (!((item.getFlag() & ItemConstants.KARMA) == ItemConstants.KARMA)) {
+ c.announce(MaplePacketCreator.serverNotice(1, "That item is untradeable."));
c.announce(MaplePacketCreator.enableActions());
return;
}
@@ -411,6 +428,8 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
short slot = slea.readShort();
short bundles = slea.readShort();
if (chr.getInventory(ivType).getItem(slot) == null || chr.getItemQuantity(chr.getInventory(ivType).getItem(slot).getItemId(), false) < bundles || chr.getInventory(ivType).getItem(slot).getFlag() == ItemConstants.UNTRADEABLE) {
+ c.announce(MaplePacketCreator.serverNotice(1, "Could not perform shop operation with that item."));
+ c.announce(MaplePacketCreator.enableActions());
return;
}
short perBundle = slea.readShort();
@@ -451,7 +470,7 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
if (shop != null && shop.isOwner(c.getPlayer())) {
int slot = slea.readShort();
if (slot >= shop.getItems().size() || slot < 0) {
- AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit with a player shop.");
+ AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit with a player shop.");
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to remove item at slot " + slot + "\r\n");
c.disconnect(true, false);
return;
@@ -479,7 +498,7 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
} else if (mode == Action.MERCHANT_ORGANIZE.getCode()) {
MapleHiredMerchant merchant = chr.getHiredMerchant();
if (!merchant.isOwner(chr)) return;
-
+
if (chr.getMerchantMeso() > 0) {
int possible = Integer.MAX_VALUE - chr.getMerchantMeso();
if (possible > 0) {
@@ -508,7 +527,7 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
int itemid = slea.readByte();
short quantity = slea.readShort();
if (quantity < 1) {
- AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit with a hired merchant and or player shop.");
+ AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit with a hired merchant and or player shop.");
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to buy item " + itemid + " with quantity " + quantity + "\r\n");
c.disconnect(true, false);
return;
@@ -528,6 +547,7 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
int slot = slea.readShort();
MaplePlayerShopItem shopItem = merchant.getItems().get(slot);
if (!MapleInventory.checkSpot(chr, shopItem.getItem())) {
+ c.announce(MaplePacketCreator.serverNotice(1, "Have a slot available on your inventory to claim back the item."));
c.announce(MaplePacketCreator.enableActions());
return;
}
@@ -568,6 +588,16 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
if (chr.getPlayerShop() != null && chr.getPlayerShop().isOwner(c.getPlayer())) {
chr.getPlayerShop().banPlayer(slea.readMapleAsciiString());
}
+ } else if (mode == Action.EXPEL.getCode()) {
+ MapleMiniGame miniGame = chr.getMiniGame();
+ if(miniGame != null && miniGame.isOwner(chr)) {
+ MapleCharacter visitor = miniGame.getVisitor();
+
+ if(visitor != null) {
+ visitor.closeMiniGame();
+ visitor.announce(MaplePacketCreator.getMiniGameClose(5));
+ }
+ }
}
}
}
diff --git a/src/net/server/channel/handlers/UseCashItemHandler.java b/src/net/server/channel/handlers/UseCashItemHandler.java
index fc286b62cf..92f8305881 100644
--- a/src/net/server/channel/handlers/UseCashItemHandler.java
+++ b/src/net/server/channel/handlers/UseCashItemHandler.java
@@ -331,7 +331,6 @@ public final class UseCashItemHandler extends AbstractMaplePacketHandler {
}
if (!MapleTVEffect.isActive()) {
new MapleTVEffect(player, victim, messages, tvType);
- remove(c, itemId);
} else {
player.dropMessage(1, "MapleTV is already in use.");
return;
diff --git a/src/net/server/world/World.java b/src/net/server/world/World.java
index bb0fd5f486..277c7e9939 100644
--- a/src/net/server/world/World.java
+++ b/src/net/server/world/World.java
@@ -1034,7 +1034,7 @@ public class World {
activeMerchantsLock.unlock();
}
}
-
+
public void setServerMessage(String msg) {
for (Channel ch : channels) {
ch.setServerMessage(msg);
diff --git a/src/server/maps/MapleMiniGame.java b/src/server/maps/MapleMiniGame.java
index cfa9598ae7..e45f4d415a 100644
--- a/src/server/maps/MapleMiniGame.java
+++ b/src/server/maps/MapleMiniGame.java
@@ -35,6 +35,7 @@ import tools.MaplePacketCreator;
public class MapleMiniGame extends AbstractMapleMapObject {
private MapleCharacter owner;
private MapleCharacter visitor;
+ private String password;
private String GameType = null;
private int[] piece = new int[250];
private List list4x3 = new ArrayList<>();
@@ -48,11 +49,20 @@ public class MapleMiniGame extends AbstractMapleMapObject {
private int ownerpoints = 0;
private int matchestowin = 0;
- public MapleMiniGame(MapleCharacter owner, String description) {
+ public MapleMiniGame(MapleCharacter owner, String description, String password) {
this.owner = owner;
this.description = description;
+ this.password = password;
}
+ public String getPassword() {
+ return this.password;
+ }
+
+ public boolean checkPassword(String sentPw) {
+ return this.password.length() == 0 || sentPw.toLowerCase().contentEquals(this.password.toLowerCase());
+ }
+
public boolean hasFreeSlot() {
return visitor == null;
}
diff --git a/src/tools/MaplePacketCreator.java b/src/tools/MaplePacketCreator.java
index d47a5c521a..dde1c65dc6 100644
--- a/src/tools/MaplePacketCreator.java
+++ b/src/tools/MaplePacketCreator.java
@@ -1898,15 +1898,19 @@ public class MaplePacketCreator {
} else {
addAnnounceBox(mplew, mps, 1);
}
- } else if (chr.getMiniGame() != null && chr.getMiniGame().isOwner(chr)) {
- if (chr.getMiniGame().hasFreeSlot()) {
- addAnnounceBox(mplew, chr.getMiniGame(), 1, 0, 1, 0);
- } else {
- addAnnounceBox(mplew, chr.getMiniGame(), 1, 0, 2, 1);
- }
} else {
- mplew.write(0);
+ MapleMiniGame miniGame = chr.getMiniGame();
+ if (miniGame != null && miniGame.isOwner(chr)) {
+ if (miniGame.hasFreeSlot()) {
+ spawnAnnounceBox(mplew, miniGame, 1, 0, 1, 0);
+ } else {
+ spawnAnnounceBox(mplew, miniGame, 1, 0, 2, 1);
+ }
+ } else {
+ mplew.write(0);
+ }
}
+
if (chr.getChalkboard() != null) {
mplew.write(1);
mplew.writeMapleAsciiString(chr.getChalkboard());
@@ -2073,6 +2077,17 @@ public class MaplePacketCreator {
}
private static void addAnnounceBox(final MaplePacketLittleEndianWriter mplew, MapleMiniGame game, int gametype, int type, int ammount, int joinable) {
+ mplew.write(gametype);
+ mplew.writeInt(game.getObjectId()); // gameid/shopid
+ mplew.writeMapleAsciiString(game.getDescription()); // desc
+ mplew.writeMapleAsciiString(game.getPassword());
+ mplew.write(type);
+ mplew.write(ammount);
+ mplew.write(2);
+ mplew.write(joinable);
+ }
+
+ private static void spawnAnnounceBox(final MaplePacketLittleEndianWriter mplew, MapleMiniGame game, int gametype, int type, int ammount, int joinable) {
mplew.write(gametype);
mplew.writeInt(game.getObjectId()); // gameid/shopid
mplew.writeMapleAsciiString(game.getDescription()); // desc
@@ -2082,7 +2097,7 @@ public class MaplePacketCreator {
mplew.write(2);
mplew.write(joinable);
}
-
+
public static byte[] facialExpression(MapleCharacter from, int expression) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(10);
mplew.writeShort(SendOpcode.FACIAL_EXPRESSION.getValue());
@@ -2768,7 +2783,7 @@ public class MaplePacketCreator {
mplew.writeInt(cid);
writeLongMaskD(mplew, statups);
for (Pair statup : statups) {
- mplew.writeShort(statup.getRight().shortValue());
+ if(statup.getLeft() == MapleDisease.POISON) mplew.writeShort(statup.getRight().shortValue());
mplew.writeShort(skill.getSkillId());
mplew.writeShort(skill.getSkillLevel());
}
@@ -4823,15 +4838,27 @@ public class MaplePacketCreator {
return mplew.getPacket();
}
- public static byte[] getMiniGameFull() {
+ /**
+ * 1 = Room already closed 2 = Can't enter due full cappacity 3 = Other requests at this minute
+ * 4 = Can't do while dead 5 = Can't do while middle event 6 = This character unable to do it
+ * 7, 20 = Not allowed to trade anymore 9 = Can only trade on same map 10 = May not open store near portal
+ * 11, 14 = Can't start game here 12 = Can't open store at this channel 13 = Can't estabilish miniroom
+ * 15 = Stores only an the free market 16 = Lists the rooms at FM (?) 17 = You may not enter this store
+ * 18 = Owner undergoing store maintenance 19 = Unable to enter tournament room 21 = Not enough mesos to enter
+ * 22 = Incorrect password
+ *
+ * @param status
+ * @return
+ */
+ public static byte[] getMiniRoomError(int status) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(5);
mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue());
mplew.write(PlayerInteractionHandler.Action.ROOM.getCode());
mplew.write(0);
- mplew.write(2);
+ mplew.write(status);
return mplew.getPacket();
}
-
+
public static byte[] getMiniGameSkipVisitor(MapleMiniGame game) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(4);
mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue());
@@ -4918,12 +4945,12 @@ public class MaplePacketCreator {
return getMiniGameResult(game, 1, 0, 0, 1, 1, true);
}
- public static byte[] getMiniGameClose() {
+ public static byte[] getMiniGameClose(int type) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(5);
mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue());
mplew.write(PlayerInteractionHandler.Action.EXIT.getCode());
mplew.write(1);
- mplew.write(3);
+ mplew.write(type); /* 2 : CRASH 3 : The room has been closed 4 : You have left the room 5 : You have been expelled */
return mplew.getPacket();
}
@@ -5072,7 +5099,7 @@ public class MaplePacketCreator {
mplew.skip(3);
return mplew.getPacket();
}
-
+
public static byte[] addOmokBox(MapleCharacter c, int ammount, int type) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.UPDATE_CHAR_BOX.getValue());
diff --git a/tools/MapleReactorDropFetcher/build.xml b/tools/MapleReactorDropFetcher/build.xml
new file mode 100644
index 0000000000..24bf91c390
--- /dev/null
+++ b/tools/MapleReactorDropFetcher/build.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+ Builds, tests, and runs the project MapleReactorDropFetcher.
+
+
+
diff --git a/tools/MapleReactorDropFetcher/lib/ReactorDropReport.txt b/tools/MapleReactorDropFetcher/lib/ReactorDropReport.txt
new file mode 100644
index 0000000000..b011a3466e
--- /dev/null
+++ b/tools/MapleReactorDropFetcher/lib/ReactorDropReport.txt
@@ -0,0 +1,20 @@
+ # Report File autogenerated from the MapleReactorDropFetcher feature by Ronan Lana.
+ # Generated data takes into account several data info from the underlying DB and the server-side files.
+
+MISSING REACTOR DROP SCRIPTS
+ 200000
+ 200001
+ 200002
+ 200003
+ 200004
+ 200005
+ 200006
+ 200007
+ 200008
+ 200009
+ 1022001
+ 1032000
+ 2052001
+ 2112015
+
+
diff --git a/tools/MapleReactorDropFetcher/manifest.mf b/tools/MapleReactorDropFetcher/manifest.mf
new file mode 100644
index 0000000000..328e8e5bc3
--- /dev/null
+++ b/tools/MapleReactorDropFetcher/manifest.mf
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+X-COMMENT: Main-Class will be added automatically by build
+
diff --git a/tools/MapleReactorDropFetcher/src/maplereactordropfetcher/MapleReactorDropFetcher.java b/tools/MapleReactorDropFetcher/src/maplereactordropfetcher/MapleReactorDropFetcher.java
new file mode 100644
index 0000000000..8a317fee3f
--- /dev/null
+++ b/tools/MapleReactorDropFetcher/src/maplereactordropfetcher/MapleReactorDropFetcher.java
@@ -0,0 +1,170 @@
+/*
+ This file is part of the HeavenMS (MapleSolaxiaV2) MapleStory Server
+ Copyleft (L) 2017 RonanLana
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as
+ published by the Free Software Foundation version 3 as published by
+ the Free Software Foundation. You may not use, modify or distribute
+ this program under any other version of the GNU Affero General Public
+ License.
+
+ 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+package maplereactordropfetcher;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.HashSet;
+import java.util.Set;
+
+import java.io.File;
+
+/**
+ *
+ * @author RonanLana
+
+ This application reports in reactor ids that have drops on the SQL table but are
+ not yet coded.
+
+ */
+public class MapleReactorDropFetcher {
+ static String host = "jdbc:mysql://localhost:3306/heavenms";
+ static String driver = "com.mysql.jdbc.Driver";
+ static String username = "root";
+ static String password = "";
+
+ static String reactorScriptPath = "../../scripts/reactor";
+
+ static String directoryName = "../..";
+ static String newFile = "lib/ReactorDropReport.txt";
+
+ static Connection con = null;
+ static PrintWriter printWriter = null;
+ static InputStreamReader fileReader = null;
+ static BufferedReader bufferedReader = null;
+
+ static Set reactors = new HashSet<>();
+
+ private static void printReportFileHeader() {
+ printWriter.println(" # Report File autogenerated from the MapleReactorDropFetcher feature by Ronan Lana.");
+ printWriter.println(" # Generated data takes into account several data info from the underlying DB and the server-side files.");
+ printWriter.println();
+ }
+
+ private static int getReactorIdFromFilename(String name) {
+ try {
+ return Integer.valueOf(name.substring(0, name.indexOf('.')));
+ } catch(Exception e) {
+ return -1;
+ }
+ }
+
+ private static void removeScriptedReactorids(String directoryName) {
+ File directory = new File(directoryName);
+
+ // get all the files from a directory
+ File[] fList = directory.listFiles();
+ for (File file : fList) {
+ if (file.isFile()) {
+ reactors.remove(getReactorIdFromFilename(file.getName()));
+ }
+ }
+ }
+
+ private static void loadReactoridsOnDB() throws SQLException {
+ PreparedStatement ps = con.prepareStatement("SELECT DISTINCT reactorid FROM reactordrops;");
+ ResultSet rs = ps.executeQuery();
+
+ while(rs.next()) {
+ reactors.add(rs.getInt("reactorid"));
+ }
+
+ rs.close();
+ ps.close();
+ }
+
+ private static List getSortedReactorids() {
+ List sortedReactors = new ArrayList<>(reactors);
+ Collections.sort(sortedReactors);
+
+ return sortedReactors;
+ }
+
+ private static void fetchMissingReactorDrops() throws SQLException {
+ loadReactoridsOnDB();
+ removeScriptedReactorids(reactorScriptPath);
+ }
+
+ private static void reportMissingReactorDrops() throws SQLException {
+ if(!reactors.isEmpty()) {
+ printWriter.println("MISSING REACTOR DROP SCRIPTS");
+ for(Integer reactorid : getSortedReactorids()) {
+ printWriter.println(" " + reactorid);
+ }
+ printWriter.println("\n");
+ }
+ }
+
+ private static void ReportMissingReactors() {
+ try {
+ Class.forName(driver).newInstance();
+
+ // filter reactorids on DB
+ con = DriverManager.getConnection(host, username, password);
+
+ System.out.println("Fetching reactors from DB...");
+ fetchMissingReactorDrops();
+
+ con.close();
+ printWriter = new PrintWriter(newFile, "UTF-8");
+
+ // report suspects of missing quest drop data, as well as those drop data that may have incorrect questids.
+ System.out.println("Reporting results...");
+ printReportFileHeader();
+ reportMissingReactorDrops();
+
+ printWriter.close();
+ System.out.println("Done!");
+ }
+
+ catch(SQLException e) {
+ System.out.println("Warning: Could not establish connection to database to report quest data.");
+ System.out.println(e.getMessage());
+ }
+
+ catch(ClassNotFoundException e) {
+ System.out.println("Error: could not find class");
+ System.out.println(e.getMessage());
+ }
+
+ catch(InstantiationException e) {
+ System.out.println("Error: instantiation failure");
+ System.out.println(e.getMessage());
+ }
+
+ catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static void main(String[] args) {
+ ReportMissingReactors();
+ }
+
+}