diff --git a/build/built-jar.properties b/build/built-jar.properties
index 5e42a873ed..636854a414 100644
--- a/build/built-jar.properties
+++ b/build/built-jar.properties
@@ -1,4 +1,4 @@
-#Fri, 29 Sep 2017 17:49:16 -0300
+#Wed, 04 Oct 2017 01:18:34 -0300
C\:\\Nexon\\MapleSolaxia\\MapleSolaxiaV2=
diff --git a/build/classes/client/MapleCharacter$1.class b/build/classes/client/MapleCharacter$1.class
index b26efa68c3..87c0423bca 100644
Binary files a/build/classes/client/MapleCharacter$1.class and b/build/classes/client/MapleCharacter$1.class differ
diff --git a/build/classes/client/MapleCharacter$10.class b/build/classes/client/MapleCharacter$10.class
index db098ae8c2..408825533f 100644
Binary files a/build/classes/client/MapleCharacter$10.class and b/build/classes/client/MapleCharacter$10.class differ
diff --git a/build/classes/client/MapleCharacter$11.class b/build/classes/client/MapleCharacter$11.class
index 4f3667e5fe..3e208d85ff 100644
Binary files a/build/classes/client/MapleCharacter$11.class and b/build/classes/client/MapleCharacter$11.class differ
diff --git a/build/classes/client/MapleCharacter$12.class b/build/classes/client/MapleCharacter$12.class
index f9ba251f0f..8ff337fdfb 100644
Binary files a/build/classes/client/MapleCharacter$12.class and b/build/classes/client/MapleCharacter$12.class differ
diff --git a/build/classes/client/MapleCharacter$13.class b/build/classes/client/MapleCharacter$13.class
index 9d404e4ebe..9ab4c366a7 100644
Binary files a/build/classes/client/MapleCharacter$13.class and b/build/classes/client/MapleCharacter$13.class differ
diff --git a/build/classes/client/MapleCharacter$14.class b/build/classes/client/MapleCharacter$14.class
index be350f1f1e..80812804d5 100644
Binary files a/build/classes/client/MapleCharacter$14.class and b/build/classes/client/MapleCharacter$14.class differ
diff --git a/build/classes/client/MapleCharacter$15.class b/build/classes/client/MapleCharacter$15.class
index 257f322e92..e324653e57 100644
Binary files a/build/classes/client/MapleCharacter$15.class and b/build/classes/client/MapleCharacter$15.class differ
diff --git a/build/classes/client/MapleCharacter$16.class b/build/classes/client/MapleCharacter$16.class
index 006fafebcd..5b7fe85aeb 100644
Binary files a/build/classes/client/MapleCharacter$16.class and b/build/classes/client/MapleCharacter$16.class differ
diff --git a/build/classes/client/MapleCharacter$17.class b/build/classes/client/MapleCharacter$17.class
index aaef8453a4..dbf2eaa39d 100644
Binary files a/build/classes/client/MapleCharacter$17.class and b/build/classes/client/MapleCharacter$17.class differ
diff --git a/build/classes/client/MapleCharacter$18.class b/build/classes/client/MapleCharacter$18.class
index f87b4848e5..462a28dfb5 100644
Binary files a/build/classes/client/MapleCharacter$18.class and b/build/classes/client/MapleCharacter$18.class differ
diff --git a/build/classes/client/MapleCharacter$19.class b/build/classes/client/MapleCharacter$19.class
index 6f769f5371..7ac743104c 100644
Binary files a/build/classes/client/MapleCharacter$19.class and b/build/classes/client/MapleCharacter$19.class differ
diff --git a/build/classes/client/MapleCharacter$2.class b/build/classes/client/MapleCharacter$2.class
index 4429e2e258..4ca6c42c00 100644
Binary files a/build/classes/client/MapleCharacter$2.class and b/build/classes/client/MapleCharacter$2.class differ
diff --git a/build/classes/client/MapleCharacter$3.class b/build/classes/client/MapleCharacter$3.class
index c3c5666d8f..db78c174f2 100644
Binary files a/build/classes/client/MapleCharacter$3.class and b/build/classes/client/MapleCharacter$3.class differ
diff --git a/build/classes/client/MapleCharacter$4.class b/build/classes/client/MapleCharacter$4.class
index d3992c0b8c..0e98bcac15 100644
Binary files a/build/classes/client/MapleCharacter$4.class and b/build/classes/client/MapleCharacter$4.class differ
diff --git a/build/classes/client/MapleCharacter$5.class b/build/classes/client/MapleCharacter$5.class
index 7f59b82959..543b9cae3a 100644
Binary files a/build/classes/client/MapleCharacter$5.class and b/build/classes/client/MapleCharacter$5.class differ
diff --git a/build/classes/client/MapleCharacter$6.class b/build/classes/client/MapleCharacter$6.class
index c94e935a6a..d43741149b 100644
Binary files a/build/classes/client/MapleCharacter$6.class and b/build/classes/client/MapleCharacter$6.class differ
diff --git a/build/classes/client/MapleCharacter$7.class b/build/classes/client/MapleCharacter$7.class
index df470b6237..199dab081e 100644
Binary files a/build/classes/client/MapleCharacter$7.class and b/build/classes/client/MapleCharacter$7.class differ
diff --git a/build/classes/client/MapleCharacter$8.class b/build/classes/client/MapleCharacter$8.class
index 77092d280b..f8aafc7cc9 100644
Binary files a/build/classes/client/MapleCharacter$8.class and b/build/classes/client/MapleCharacter$8.class differ
diff --git a/build/classes/client/MapleCharacter$9.class b/build/classes/client/MapleCharacter$9.class
index 2ebee46129..d99b8e9a87 100644
Binary files a/build/classes/client/MapleCharacter$9.class and b/build/classes/client/MapleCharacter$9.class differ
diff --git a/build/classes/client/MapleCharacter$FameStatus.class b/build/classes/client/MapleCharacter$FameStatus.class
index 260e6e461a..e259067265 100644
Binary files a/build/classes/client/MapleCharacter$FameStatus.class and b/build/classes/client/MapleCharacter$FameStatus.class differ
diff --git a/build/classes/client/MapleCharacter$MapleBuffStatValueHolder.class b/build/classes/client/MapleCharacter$MapleBuffStatValueHolder.class
index 0c296f4973..fc0b0782a7 100644
Binary files a/build/classes/client/MapleCharacter$MapleBuffStatValueHolder.class and b/build/classes/client/MapleCharacter$MapleBuffStatValueHolder.class differ
diff --git a/build/classes/client/MapleCharacter$MapleCoolDownValueHolder.class b/build/classes/client/MapleCharacter$MapleCoolDownValueHolder.class
index 3d4a4254ef..2104ebccee 100644
Binary files a/build/classes/client/MapleCharacter$MapleCoolDownValueHolder.class and b/build/classes/client/MapleCharacter$MapleCoolDownValueHolder.class differ
diff --git a/build/classes/client/MapleCharacter$SkillEntry.class b/build/classes/client/MapleCharacter$SkillEntry.class
index a3fa9642f0..4778446029 100644
Binary files a/build/classes/client/MapleCharacter$SkillEntry.class and b/build/classes/client/MapleCharacter$SkillEntry.class differ
diff --git a/build/classes/client/MapleCharacter.class b/build/classes/client/MapleCharacter.class
index acdcd0f204..a7ec50c456 100644
Binary files a/build/classes/client/MapleCharacter.class and b/build/classes/client/MapleCharacter.class differ
diff --git a/build/classes/client/MapleClient$1.class b/build/classes/client/MapleClient$1.class
index 306f6e2420..14f584027f 100644
Binary files a/build/classes/client/MapleClient$1.class and b/build/classes/client/MapleClient$1.class differ
diff --git a/build/classes/client/MapleClient.class b/build/classes/client/MapleClient.class
index f6d0077b02..71dc907cf1 100644
Binary files a/build/classes/client/MapleClient.class and b/build/classes/client/MapleClient.class differ
diff --git a/build/classes/client/command/Commands.class b/build/classes/client/command/Commands.class
index 2aa0dfe49e..026abb3fdb 100644
Binary files a/build/classes/client/command/Commands.class and b/build/classes/client/command/Commands.class differ
diff --git a/build/classes/constants/ServerConstants.class b/build/classes/constants/ServerConstants.class
index ee42fd9fed..6b52815ae2 100644
Binary files a/build/classes/constants/ServerConstants.class and b/build/classes/constants/ServerConstants.class differ
diff --git a/build/classes/net/mina/MaplePacketDecoder.class b/build/classes/net/mina/MaplePacketDecoder.class
index 552028c078..c24236f2a0 100644
Binary files a/build/classes/net/mina/MaplePacketDecoder.class and b/build/classes/net/mina/MaplePacketDecoder.class differ
diff --git a/build/classes/net/mina/MaplePacketEncoder.class b/build/classes/net/mina/MaplePacketEncoder.class
index 7c7770456d..bb60a586b7 100644
Binary files a/build/classes/net/mina/MaplePacketEncoder.class and b/build/classes/net/mina/MaplePacketEncoder.class differ
diff --git a/build/classes/net/server/channel/handlers/EnterCashShopHandler.class b/build/classes/net/server/channel/handlers/EnterCashShopHandler.class
index 4596d166cc..aeb8da9dad 100644
Binary files a/build/classes/net/server/channel/handlers/EnterCashShopHandler.class and b/build/classes/net/server/channel/handlers/EnterCashShopHandler.class differ
diff --git a/build/classes/net/server/channel/handlers/EnterMTSHandler.class b/build/classes/net/server/channel/handlers/EnterMTSHandler.class
index a36be5dc2c..4e999fd1e4 100644
Binary files a/build/classes/net/server/channel/handlers/EnterMTSHandler.class and b/build/classes/net/server/channel/handlers/EnterMTSHandler.class differ
diff --git a/build/classes/net/server/channel/handlers/PartyOperationHandler.class b/build/classes/net/server/channel/handlers/PartyOperationHandler.class
index a4fdd26446..76444de686 100644
Binary files a/build/classes/net/server/channel/handlers/PartyOperationHandler.class and b/build/classes/net/server/channel/handlers/PartyOperationHandler.class differ
diff --git a/build/classes/net/server/channel/handlers/PlayerLoggedinHandler.class b/build/classes/net/server/channel/handlers/PlayerLoggedinHandler.class
index a66fe6e5f2..18b3a932ba 100644
Binary files a/build/classes/net/server/channel/handlers/PlayerLoggedinHandler.class and b/build/classes/net/server/channel/handlers/PlayerLoggedinHandler.class differ
diff --git a/build/classes/net/server/world/MapleParty$1.class b/build/classes/net/server/world/MapleParty$1.class
index 6a20d80984..fc9bc16440 100644
Binary files a/build/classes/net/server/world/MapleParty$1.class and b/build/classes/net/server/world/MapleParty$1.class differ
diff --git a/build/classes/net/server/world/MapleParty.class b/build/classes/net/server/world/MapleParty.class
index 91de42acd5..f6e35efcc6 100644
Binary files a/build/classes/net/server/world/MapleParty.class and b/build/classes/net/server/world/MapleParty.class differ
diff --git a/build/classes/net/server/world/World$1.class b/build/classes/net/server/world/World$1.class
index 994daaa622..04ce90d4a1 100644
Binary files a/build/classes/net/server/world/World$1.class and b/build/classes/net/server/world/World$1.class differ
diff --git a/build/classes/net/server/world/World.class b/build/classes/net/server/world/World.class
index 1c43e8c721..91d2968bf9 100644
Binary files a/build/classes/net/server/world/World.class and b/build/classes/net/server/world/World.class differ
diff --git a/build/classes/scripting/AbstractPlayerInteraction.class b/build/classes/scripting/AbstractPlayerInteraction.class
index a05872ab41..db93f32582 100644
Binary files a/build/classes/scripting/AbstractPlayerInteraction.class and b/build/classes/scripting/AbstractPlayerInteraction.class differ
diff --git a/build/classes/server/MapleItemInformationProvider$1.class b/build/classes/server/MapleItemInformationProvider$1.class
index 7d3a14d0fb..b933fe76d4 100644
Binary files a/build/classes/server/MapleItemInformationProvider$1.class and b/build/classes/server/MapleItemInformationProvider$1.class differ
diff --git a/build/classes/server/MapleItemInformationProvider$RewardItem.class b/build/classes/server/MapleItemInformationProvider$RewardItem.class
index c36cd1ad94..574fe92265 100644
Binary files a/build/classes/server/MapleItemInformationProvider$RewardItem.class and b/build/classes/server/MapleItemInformationProvider$RewardItem.class differ
diff --git a/build/classes/server/MapleItemInformationProvider$scriptedItem.class b/build/classes/server/MapleItemInformationProvider$scriptedItem.class
index b84ff88cc6..6de16c88cb 100644
Binary files a/build/classes/server/MapleItemInformationProvider$scriptedItem.class and b/build/classes/server/MapleItemInformationProvider$scriptedItem.class differ
diff --git a/build/classes/server/MapleItemInformationProvider.class b/build/classes/server/MapleItemInformationProvider.class
index 2cee15cbb8..5fe4e6fd01 100644
Binary files a/build/classes/server/MapleItemInformationProvider.class and b/build/classes/server/MapleItemInformationProvider.class differ
diff --git a/build/classes/server/life/MapleMonster$1.class b/build/classes/server/life/MapleMonster$1.class
index 5eba265f2e..0b90120e43 100644
Binary files a/build/classes/server/life/MapleMonster$1.class and b/build/classes/server/life/MapleMonster$1.class differ
diff --git a/build/classes/server/life/MapleMonster$2.class b/build/classes/server/life/MapleMonster$2.class
index 7490d5a677..947aba94f0 100644
Binary files a/build/classes/server/life/MapleMonster$2.class and b/build/classes/server/life/MapleMonster$2.class differ
diff --git a/build/classes/server/life/MapleMonster$3.class b/build/classes/server/life/MapleMonster$3.class
index 7d4d94292f..da2f603b71 100644
Binary files a/build/classes/server/life/MapleMonster$3.class and b/build/classes/server/life/MapleMonster$3.class differ
diff --git a/build/classes/server/life/MapleMonster$4.class b/build/classes/server/life/MapleMonster$4.class
index 0877f7700d..2e0760ef23 100644
Binary files a/build/classes/server/life/MapleMonster$4.class and b/build/classes/server/life/MapleMonster$4.class differ
diff --git a/build/classes/server/life/MapleMonster$5.class b/build/classes/server/life/MapleMonster$5.class
index 62f960585a..58f188cec9 100644
Binary files a/build/classes/server/life/MapleMonster$5.class and b/build/classes/server/life/MapleMonster$5.class differ
diff --git a/build/classes/server/life/MapleMonster$6.class b/build/classes/server/life/MapleMonster$6.class
index 42c2817f64..295643d0d0 100644
Binary files a/build/classes/server/life/MapleMonster$6.class and b/build/classes/server/life/MapleMonster$6.class differ
diff --git a/build/classes/server/life/MapleMonster$DamageTask.class b/build/classes/server/life/MapleMonster$DamageTask.class
index 8cb72a9590..f7fd11c750 100644
Binary files a/build/classes/server/life/MapleMonster$DamageTask.class and b/build/classes/server/life/MapleMonster$DamageTask.class differ
diff --git a/build/classes/server/life/MapleMonster.class b/build/classes/server/life/MapleMonster.class
index 90784264d8..6a7f1efef2 100644
Binary files a/build/classes/server/life/MapleMonster.class and b/build/classes/server/life/MapleMonster.class differ
diff --git a/build/classes/server/maps/MapleMap$1.class b/build/classes/server/maps/MapleMap$1.class
index 40a1810dc0..80658c3088 100644
Binary files a/build/classes/server/maps/MapleMap$1.class and b/build/classes/server/maps/MapleMap$1.class differ
diff --git a/build/classes/server/maps/MapleMap$10.class b/build/classes/server/maps/MapleMap$10.class
index 978c142bf6..1fa5f138b3 100644
Binary files a/build/classes/server/maps/MapleMap$10.class and b/build/classes/server/maps/MapleMap$10.class differ
diff --git a/build/classes/server/maps/MapleMap$11.class b/build/classes/server/maps/MapleMap$11.class
index 334fe659da..d317c29661 100644
Binary files a/build/classes/server/maps/MapleMap$11.class and b/build/classes/server/maps/MapleMap$11.class differ
diff --git a/build/classes/server/maps/MapleMap$12.class b/build/classes/server/maps/MapleMap$12.class
index 75ab674d8e..f6f1c55fba 100644
Binary files a/build/classes/server/maps/MapleMap$12.class and b/build/classes/server/maps/MapleMap$12.class differ
diff --git a/build/classes/server/maps/MapleMap$13.class b/build/classes/server/maps/MapleMap$13.class
index 4633113cec..d9174819c9 100644
Binary files a/build/classes/server/maps/MapleMap$13.class and b/build/classes/server/maps/MapleMap$13.class differ
diff --git a/build/classes/server/maps/MapleMap$14.class b/build/classes/server/maps/MapleMap$14.class
index e82823231e..3114ac5613 100644
Binary files a/build/classes/server/maps/MapleMap$14.class and b/build/classes/server/maps/MapleMap$14.class differ
diff --git a/build/classes/server/maps/MapleMap$15.class b/build/classes/server/maps/MapleMap$15.class
index 1273909d55..416d5f5615 100644
Binary files a/build/classes/server/maps/MapleMap$15.class and b/build/classes/server/maps/MapleMap$15.class differ
diff --git a/build/classes/server/maps/MapleMap$16.class b/build/classes/server/maps/MapleMap$16.class
index 0fb35420f3..cd76704b06 100644
Binary files a/build/classes/server/maps/MapleMap$16.class and b/build/classes/server/maps/MapleMap$16.class differ
diff --git a/build/classes/server/maps/MapleMap$17.class b/build/classes/server/maps/MapleMap$17.class
index 66922f4f7b..2509483fba 100644
Binary files a/build/classes/server/maps/MapleMap$17.class and b/build/classes/server/maps/MapleMap$17.class differ
diff --git a/build/classes/server/maps/MapleMap$18.class b/build/classes/server/maps/MapleMap$18.class
index df7e9c0c33..dc4637f64f 100644
Binary files a/build/classes/server/maps/MapleMap$18.class and b/build/classes/server/maps/MapleMap$18.class differ
diff --git a/build/classes/server/maps/MapleMap$19.class b/build/classes/server/maps/MapleMap$19.class
index b47e254fe6..1c77fd2f88 100644
Binary files a/build/classes/server/maps/MapleMap$19.class and b/build/classes/server/maps/MapleMap$19.class differ
diff --git a/build/classes/server/maps/MapleMap$2.class b/build/classes/server/maps/MapleMap$2.class
index ee1593f851..f384bcd8a8 100644
Binary files a/build/classes/server/maps/MapleMap$2.class and b/build/classes/server/maps/MapleMap$2.class differ
diff --git a/build/classes/server/maps/MapleMap$20.class b/build/classes/server/maps/MapleMap$20.class
index de685fc2ee..84c0f6e3e9 100644
Binary files a/build/classes/server/maps/MapleMap$20.class and b/build/classes/server/maps/MapleMap$20.class differ
diff --git a/build/classes/server/maps/MapleMap$21.class b/build/classes/server/maps/MapleMap$21.class
index 933606c589..ffd289db59 100644
Binary files a/build/classes/server/maps/MapleMap$21.class and b/build/classes/server/maps/MapleMap$21.class differ
diff --git a/build/classes/server/maps/MapleMap$22.class b/build/classes/server/maps/MapleMap$22.class
index 03b1c3a871..1523cfa102 100644
Binary files a/build/classes/server/maps/MapleMap$22.class and b/build/classes/server/maps/MapleMap$22.class differ
diff --git a/build/classes/server/maps/MapleMap$23.class b/build/classes/server/maps/MapleMap$23.class
index 7aeddfc257..6ac0109238 100644
Binary files a/build/classes/server/maps/MapleMap$23.class and b/build/classes/server/maps/MapleMap$23.class differ
diff --git a/build/classes/server/maps/MapleMap$24.class b/build/classes/server/maps/MapleMap$24.class
index 01f91ea1cc..8a5c6026de 100644
Binary files a/build/classes/server/maps/MapleMap$24.class and b/build/classes/server/maps/MapleMap$24.class differ
diff --git a/build/classes/server/maps/MapleMap$25.class b/build/classes/server/maps/MapleMap$25.class
index f4f278057a..e409dd8327 100644
Binary files a/build/classes/server/maps/MapleMap$25.class and b/build/classes/server/maps/MapleMap$25.class differ
diff --git a/build/classes/server/maps/MapleMap$26.class b/build/classes/server/maps/MapleMap$26.class
index c15d6b8442..2f5cea00d4 100644
Binary files a/build/classes/server/maps/MapleMap$26.class and b/build/classes/server/maps/MapleMap$26.class differ
diff --git a/build/classes/server/maps/MapleMap$27.class b/build/classes/server/maps/MapleMap$27.class
index 9db8188fdb..e59a680f42 100644
Binary files a/build/classes/server/maps/MapleMap$27.class and b/build/classes/server/maps/MapleMap$27.class differ
diff --git a/build/classes/server/maps/MapleMap$28.class b/build/classes/server/maps/MapleMap$28.class
index b86cca5db7..8349ecebd0 100644
Binary files a/build/classes/server/maps/MapleMap$28.class and b/build/classes/server/maps/MapleMap$28.class differ
diff --git a/build/classes/server/maps/MapleMap$29$1.class b/build/classes/server/maps/MapleMap$29$1.class
index a14b598c54..f166f7fff8 100644
Binary files a/build/classes/server/maps/MapleMap$29$1.class and b/build/classes/server/maps/MapleMap$29$1.class differ
diff --git a/build/classes/server/maps/MapleMap$29.class b/build/classes/server/maps/MapleMap$29.class
index eadd6bfb55..7374e8bff2 100644
Binary files a/build/classes/server/maps/MapleMap$29.class and b/build/classes/server/maps/MapleMap$29.class differ
diff --git a/build/classes/server/maps/MapleMap$3.class b/build/classes/server/maps/MapleMap$3.class
index 4d1c84a4c6..ceb2145abd 100644
Binary files a/build/classes/server/maps/MapleMap$3.class and b/build/classes/server/maps/MapleMap$3.class differ
diff --git a/build/classes/server/maps/MapleMap$30.class b/build/classes/server/maps/MapleMap$30.class
index 87862d5d50..027519c30a 100644
Binary files a/build/classes/server/maps/MapleMap$30.class and b/build/classes/server/maps/MapleMap$30.class differ
diff --git a/build/classes/server/maps/MapleMap$4.class b/build/classes/server/maps/MapleMap$4.class
index 4aa29578c9..85f0bb93b6 100644
Binary files a/build/classes/server/maps/MapleMap$4.class and b/build/classes/server/maps/MapleMap$4.class differ
diff --git a/build/classes/server/maps/MapleMap$5.class b/build/classes/server/maps/MapleMap$5.class
index bf69df5149..5921e9aa36 100644
Binary files a/build/classes/server/maps/MapleMap$5.class and b/build/classes/server/maps/MapleMap$5.class differ
diff --git a/build/classes/server/maps/MapleMap$6.class b/build/classes/server/maps/MapleMap$6.class
index 006c02fdd8..76b76e08e6 100644
Binary files a/build/classes/server/maps/MapleMap$6.class and b/build/classes/server/maps/MapleMap$6.class differ
diff --git a/build/classes/server/maps/MapleMap$7.class b/build/classes/server/maps/MapleMap$7.class
index fcadc5aa3d..3c75135efd 100644
Binary files a/build/classes/server/maps/MapleMap$7.class and b/build/classes/server/maps/MapleMap$7.class differ
diff --git a/build/classes/server/maps/MapleMap$8.class b/build/classes/server/maps/MapleMap$8.class
index 13a1508217..65652d9a72 100644
Binary files a/build/classes/server/maps/MapleMap$8.class and b/build/classes/server/maps/MapleMap$8.class differ
diff --git a/build/classes/server/maps/MapleMap$9.class b/build/classes/server/maps/MapleMap$9.class
index e5c60041c1..bc3acfc77f 100644
Binary files a/build/classes/server/maps/MapleMap$9.class and b/build/classes/server/maps/MapleMap$9.class differ
diff --git a/build/classes/server/maps/MapleMap$ActivateItemReactor$1.class b/build/classes/server/maps/MapleMap$ActivateItemReactor$1.class
index efba39b13e..552d48405c 100644
Binary files a/build/classes/server/maps/MapleMap$ActivateItemReactor$1.class and b/build/classes/server/maps/MapleMap$ActivateItemReactor$1.class differ
diff --git a/build/classes/server/maps/MapleMap$ActivateItemReactor.class b/build/classes/server/maps/MapleMap$ActivateItemReactor.class
index 0bece63c9f..5540d6b4ab 100644
Binary files a/build/classes/server/maps/MapleMap$ActivateItemReactor.class and b/build/classes/server/maps/MapleMap$ActivateItemReactor.class differ
diff --git a/build/classes/server/maps/MapleMap$ExpireMapItemJob.class b/build/classes/server/maps/MapleMap$ExpireMapItemJob.class
index 63445a468d..a9028052bd 100644
Binary files a/build/classes/server/maps/MapleMap$ExpireMapItemJob.class and b/build/classes/server/maps/MapleMap$ExpireMapItemJob.class differ
diff --git a/build/classes/server/maps/MapleMap.class b/build/classes/server/maps/MapleMap.class
index 3c91a89739..aaf146c8c9 100644
Binary files a/build/classes/server/maps/MapleMap.class and b/build/classes/server/maps/MapleMap.class differ
diff --git a/build/classes/tools/MaplePacketCreator$2.class b/build/classes/tools/MaplePacketCreator$2.class
index 766057277e..485e378320 100644
Binary files a/build/classes/tools/MaplePacketCreator$2.class and b/build/classes/tools/MaplePacketCreator$2.class differ
diff --git a/build/classes/tools/MaplePacketCreator.class b/build/classes/tools/MaplePacketCreator.class
index 80cc3a333b..1f6cabd445 100644
Binary files a/build/classes/tools/MaplePacketCreator.class and b/build/classes/tools/MaplePacketCreator.class differ
diff --git a/dist/MapleSolaxia.jar b/dist/MapleSolaxia.jar
index 5fccb629ef..c29d4b19e2 100644
Binary files a/dist/MapleSolaxia.jar and b/dist/MapleSolaxia.jar differ
diff --git a/docs/mychanges_ptbr.txt b/docs/mychanges_ptbr.txt
index f096866b4f..0a52870436 100644
--- a/docs/mychanges_ptbr.txt
+++ b/docs/mychanges_ptbr.txt
@@ -558,4 +558,11 @@ Adicionado Owl of Minerva.
Corrigido um bug no sistema de checagem de slots.
28 Setembro 2017,
-Adidionado wish tickets à AmoriaPQ.
\ No newline at end of file
+Adidionado wish tickets à AmoriaPQ.
+
+02 - 03 Outubro 2017,
+Adicionado proteção de acesso concorrente em MapleParty.
+Corrigido bug em sistema de distribuição de EXP para party.
+Corrigido bug de overflow em distribuição de EXP.
+Corrigido bug com scrolls não usando slots quando resultam em sucesso.
+Refatorado sistema de schedules para disease expiretimes.
\ No newline at end of file
diff --git a/nbproject/private/private.xml b/nbproject/private/private.xml
index 6bd1c4fef3..1037c26341 100644
--- a/nbproject/private/private.xml
+++ b/nbproject/private/private.xml
@@ -3,28 +3,15 @@
- file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/RecvOpcode.java
- file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/tools/data/input/GenericLittleEndianAccessor.java
- file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/maps/MapleHiredMerchant.java
- file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/PacketProcessor.java
+ file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/SendOpcode.java
+ file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/channel/handlers/TakeDamageHandler.java
+ file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/scripting/AbstractPlayerInteraction.java
file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/constants/ServerConstants.java
- file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/world/World.java
- file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/channel/handlers/FredrickHandler.java
- file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/channel/handlers/OwlWarpHandler.java
- file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/channel/handlers/RemoteStoreHandler.java
- file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/channel/handlers/PlayerInteractionHandler.java
- file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/client/inventory/MapleInventory.java
- file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/tools/MaplePacketCreator.java
- file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/channel/handlers/UseCashItemHandler.java
- file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/channel/handlers/UseOwlOfMinervaHandler.java
- file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/MapleTrade.java
- file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/MapleInventoryManipulator.java
- file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/MapleMiniGame.java
- file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/MaplePlayerShop.java
+ file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/tools/data/output/GenericLittleEndianWriter.java
file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/client/MapleCharacter.java
- file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/client/MapleClient.java
- file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/channel/Channel.java
- file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/tools/data/input/LittleEndianAccessor.java
+ file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/life/MobSkill.java
+ file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/MapleItemInformationProvider.java
+ file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/tools/MaplePacketCreator.java
diff --git a/scripts/event/KingPepeAndYetis.js b/scripts/event/KingPepeAndYetis.js
new file mode 100644
index 0000000000..cd2c2064e8
--- /dev/null
+++ b/scripts/event/KingPepeAndYetis.js
@@ -0,0 +1,110 @@
+var minPlayers = 1;
+var timeLimit = 20; //20 minutes
+var eventTimer = 1000 * 60 * timeLimit;
+var exitMap = 106021400;
+
+function init(){}
+
+function setup(difficulty, lobbyId){
+ var eim = em.newInstance("KingPepe_" +lobbyId);
+ eim.getInstanceMap(106021500).resetFully();
+ eim.getInstanceMap(106021500).allowSummonState(false);
+ respawn(eim);
+ eim.startEventTimer(eventTimer);
+ return eim;
+}
+
+function afterSetup(eim){}
+
+function respawn(eim){
+ var map = eim.getMapInstance(exitMap);
+ map.allowSummonState(true);
+ map.instanceMapRespawn();
+ eim.schedule("respawn", 10000);
+}
+
+function playerEntry(eim, player){
+ var yetiMap = eim.getMapInstance(106021500);
+ player.changeMap(yetiMap, yetiMap.getPortal(1));
+}
+
+function scheduledTimeout(eim){
+ var party = eim.getPlayers();
+
+ for(var i = 0; i < party.size(); i++)
+ playerExit(eim, party.get(i));
+
+ eim.dispose();
+}
+
+function playerRevive(eim, player){
+ player.setHp(50);
+ player.setStance(0);
+ eim.unregisterPlayer(player);
+ player.changeMap(exitMap);
+ return false;
+}
+
+function playerDead(eim, player){}
+
+function playerDisconnected(eim, player){
+ var party = eim.getPlayers();
+
+ for(var i = 0; i < party.size(); i++){
+ if(party.get(i).equals(player))
+ removePlayer(eim, player);
+ else
+ playerExit(eim, party.get(i));
+ }
+ eim.dispose();
+}
+
+function monsterValue(eim, mobId){
+ return -1;
+}
+
+function leftParty(eim, player){
+ var party = eim.getPlayers();
+
+ if(party.size() < minPlayers){
+ for(var i = 0; i < party.size(); i++){
+ playerExit(eim, party.get(i));
+ }
+ eim.dispose();
+ }
+ else{
+ playerExit(eim, player);
+ }
+}
+
+function disbandParty(eim){}
+
+function playerUnregistered(eim, player){}
+
+function playerExit(eim, player){
+ eim.unregisterPlayer(player);
+ player.changeMap(exitMap, 2);
+}
+
+function moveMap(eim, player){
+ if(player.getMap().getId() == exitMap){
+ removePlayer(eim, player);
+ eim.dispose();
+ }
+}
+
+function removePlayer(eim, player){
+ eim.unregisterPlayer(player);
+ player.getMap().removePlayer(player);
+ player.setMap(exitMap);
+}
+
+function cancelSchedule(){}
+
+function dispose(){}
+
+function clearPQ(eim){}
+
+function monsterKilled(mob, eim){}
+
+function allMonstersDead(eim){}
\ No newline at end of file
diff --git a/scripts/event/MK_PrimeMinister.js b/scripts/event/MK_PrimeMinister.js
new file mode 100644
index 0000000000..f987227b10
--- /dev/null
+++ b/scripts/event/MK_PrimeMinister.js
@@ -0,0 +1,108 @@
+var minPlayers = 1;
+var entryMap = 106021402;
+var exitMap = 106021600;
+
+function init(){}
+
+function setup(difficulty, lobbyId){
+ var eim = em.newInstance("MK_PrimeMinister_" +lobbyId);
+ eim.getInstanceMap(106021601).resetFully();
+ eim.getInstanceMap(106021601).allowSummonState(false);
+ respawn(eim);
+ return eim;
+}
+
+function afterSetup(eim){}
+
+function respawn(eim){
+ var map = eim.getMapInstance(entryMap);
+ map.allowSummonState(true);
+ map.instanceMapRespawn();
+ eim.schedule("respawn", 10000);
+}
+
+function playerEntry(eim, player){
+ var weddinghall = eim.getMapInstance(106021601);
+ player.changeMap(weddinghall, weddinghall.getPortal(1));
+}
+
+function scheduledTimeout(eim){
+ var party = eim.getPlayers();
+
+ for(var i = 0; i < party.size(); i++)
+ playerExit(eim, party.get(i));
+
+ eim.dispose();
+}
+
+function playerRevive(eim, player){
+ player.setHp(50);
+ player.setStance(0);
+ eim.unregisterPlayer(player);
+ player.changeMap(entryMap);
+ return false;
+}
+
+function playerDead(eim, player){}
+
+function playerDisconnected(eim, player){
+ var party = eim.getPlayers();
+
+ for(var i = 0; i < party.size(); i++){
+ if(party.get(i).equals(player))
+ removePlayer(eim, player);
+ else
+ playerExit(eim, party.get(i));
+ }
+ eim.dispose();
+}
+
+function monsterValue(eim, mobId){
+ return -1;
+}
+
+function leftParty(eim, player){
+ var party = eim.getPlayers();
+
+ if(party.size() < minPlayers){
+ for(var i = 0; i < party.size(); i++){
+ playerExit(eim, party.get(i));
+ }
+ eim.dispose();
+ }
+ else{
+ playerExit(eim, player);
+ }
+}
+
+function disbandParty(eim){}
+
+function playerUnregistered(eim, player){}
+
+function playerExit(eim, player){
+ eim.unregisterPlayer(player);
+ player.changeMap(entryMap, 2);
+}
+
+function moveMap(eim, player){
+ if(player.getMap().getId() == exitMap || player.getMap().getId() == entryMap){
+ removePlayer(eim, player);
+ eim.dispose();
+ }
+}
+
+function removePlayer(eim, player){
+ eim.unregisterPlayer(player);
+ player.getMap().removePlayer(player);
+ player.setMap(entryMap);
+}
+
+function cancelSchedule(){}
+
+function dispose(){}
+
+function clearPQ(eim){}
+
+function monsterKilled(mob, eim){}
+
+function allMonstersDead(eim){}
\ No newline at end of file
diff --git a/scripts/map/onUserEnter/pepeking_effect.js b/scripts/map/onUserEnter/pepeking_effect.js
new file mode 100644
index 0000000000..5fd8439196
--- /dev/null
+++ b/scripts/map/onUserEnter/pepeking_effect.js
@@ -0,0 +1,9 @@
+importPackage(Packages.server.life);
+
+function start(ms){
+ var mobId = 3300000 + (Math.floor(Math.random() * 3) + 5);
+ var player = ms.getPlayer();
+ var map = player.getMap();
+
+ map.spawnMonsterOnGroundBelow(MapleLifeFactory.getMonster(mobId), new java.awt.Point(-28, -67));
+}
\ No newline at end of file
diff --git a/scripts/npc/1052109.js b/scripts/npc/1052109.js
index 29f5c64340..826517af31 100644
--- a/scripts/npc/1052109.js
+++ b/scripts/npc/1052109.js
@@ -19,7 +19,7 @@
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
-/* Trash Can
+/* Trash Can 1
*/
diff --git a/scripts/npc/1052110.js b/scripts/npc/1052110.js
new file mode 100644
index 0000000000..0bba942db2
--- /dev/null
+++ b/scripts/npc/1052110.js
@@ -0,0 +1,31 @@
+/*
+ Trash Can 2
+ Kerning Subway
+*/
+
+var status;
+
+function start() {
+ status = -1;
+ action(1, 0, 0);
+}
+
+function action(mode, type, selection) {
+ if (mode == -1) {
+ cm.dispose();
+ } else {
+ if (mode == 0 && type > 0) {
+ cm.dispose();
+ return;
+ }
+ if (mode == 1)
+ status++;
+ else
+ status--;
+
+ if(status == 0) {
+ cm.sendOk("Just a trash can sitting there.");
+ cm.dispose();
+ }
+ }
+}
\ No newline at end of file
diff --git a/scripts/npc/1052111.js b/scripts/npc/1052111.js
new file mode 100644
index 0000000000..6183aa9d0e
--- /dev/null
+++ b/scripts/npc/1052111.js
@@ -0,0 +1,51 @@
+/*
+ Trash Can 3
+ Kerning Subway
+*/
+
+var status;
+
+function start(){
+ status = -1;
+ action(1, 0, 0);
+}
+
+function action(mode, type, selection){
+ if(mode == -1){
+ cm.dispose();
+ return;
+ }
+ else{
+ if(mode == 0 && status == 0){
+ cm.dispose();
+ return;
+ }
+ else if(mode == 0)
+ status--;
+ else
+ status++;
+
+
+ if(cm.isQuestStarted(20710)){
+ if(!cm.hasItem(4032136)){
+ cm.sendNext("You have found a #b#t4032136##k in the trash can! #i4032136#");
+
+ if(cm.canHold(4032136)){
+ cm.gainItem(4032136, 1);
+ }
+ else{
+ cm.sendOk("#i4032136# Not enough space in your ETC inventory.");
+ }
+ cm.dispose();
+ }
+ else{
+ cm.sendOk("Just a trash can sitting there.");
+ cm.dispose();
+ }
+ }
+ else{
+ cm.sendOk("Just a trash can sitting there.");
+ cm.dispose();
+ }
+ }
+}
\ No newline at end of file
diff --git a/scripts/npc/1052112.js b/scripts/npc/1052112.js
new file mode 100644
index 0000000000..58909d5be0
--- /dev/null
+++ b/scripts/npc/1052112.js
@@ -0,0 +1,31 @@
+/*
+ Trash Can 4
+ Kerning Subway
+*/
+
+var status;
+
+function start() {
+ status = -1;
+ action(1, 0, 0);
+}
+
+function action(mode, type, selection) {
+ if (mode == -1) {
+ cm.dispose();
+ } else {
+ if (mode == 0 && type > 0) {
+ cm.dispose();
+ return;
+ }
+ if (mode == 1)
+ status++;
+ else
+ status--;
+
+ if(status == 0) {
+ cm.sendOk("Just a trash can sitting there.");
+ cm.dispose();
+ }
+ }
+}
\ No newline at end of file
diff --git a/scripts/npc/1092000.js b/scripts/npc/1092000.js
index 74d6a2ae63..fcb55d97d8 100644
--- a/scripts/npc/1092000.js
+++ b/scripts/npc/1092000.js
@@ -3,19 +3,16 @@
Copyright (C) 2008 Patrick Huy
Matthias Butz
Jan Christian Meyer
-
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 .
*/
@@ -24,28 +21,37 @@
* @Author xXOsirisXx (BubblesDev)
*/
-status = -1;
+var status;
function start() {
- cm.sendNext("Okay, I'll now send you to the stable where my cows are. Watch out for the calves that drink all the milk. You don't want your effort to go to waste.");
+ status = -1;
+ action(1, 0, 0);
}
function action(mode, type, selection){
- if (mode == -1 || !cm.isQuestStarted(2180)){
- cm.dispose();
- return;
- } else if (mode == 0)
- status--;
- else
- status++;
- if (status == 1)
- cm.sendNextPrev("It won't be easy to tell at a glance between a calf and a cow. Those calves may only be a month or two old, but they have already grown to the size of their mother. They even look alike...even I get confused at times! Good luck!");
- else if (status == 2) {
- if (cm.canHold(4031847)) {
- cm.gainItem(4031847, 1);
- cm.warp(912000100);
- } else
- cm.sendNextPrev("I can't give you the empty bottle because your inventory is full. Please make some room in your Etc window.");
- cm.dispose();
- }
+ if (mode == -1 || !cm.isQuestStarted(2180)){
+ cm.dispose();
+ return;
+ }
+ else{
+ if (mode == 1) status++;
+ else status --;
+
+ if (status == 0){
+ cm.sendNext("Okay, I'll now send you to the stable where my cows are. Watch out for the calves that drink all the milk. You don't want your effort to go to waste.");
+ }
+ else if (status == 1){
+ cm.sendNextPrev("It won't be easy to tell at a glance between a calf and a cow. Those calves may only be a month or two old, but they have already grown to the size of their mother. They even look alike...even I get confused at times! Good luck!");
+ }
+ else if (status == 2){
+ if (cm.canHold(4031847)){
+ cm.gainItem(4031847, 1);
+ cm.warp(912000100);
+ }
+ else{
+ cm.sendOk("I can't give you the empty bottle because your inventory is full. Please make some room in your Etc window.");
+ }
+ cm.dispose();
+ }
+ }
}
\ No newline at end of file
diff --git a/scripts/npc/1300013.js b/scripts/npc/1300013.js
new file mode 100644
index 0000000000..22913c9967
--- /dev/null
+++ b/scripts/npc/1300013.js
@@ -0,0 +1,40 @@
+/*
+ NPC: Blocked Entrance (portal?)
+ MAP: Mushroom Castle - East Castle Tower (106021400)
+*/
+
+var status;
+
+function start(){
+ status = -1;
+ action(1, 0, 0);
+}
+
+function action(mode, type, selection){
+ if(mode == -1){
+ cm.dispose();
+ return;
+ }
+ else if(mode == 0 && status == 0){
+ cm.dispose();
+ return;
+ }
+ else if(mode == 0)
+ status--;
+ else
+ status++;
+
+
+ if(status == 0){
+ cm.sendSimple("#L1#Enter to fight #bKing Pepe#k and #bYeti Brothers#k.#l");
+ }
+ else if(status == 1){
+ if(selection == 1){
+ var pepe = cm.getEventManager("KingPepeAndYetis");
+ pepe.setProperty("player", cm.getPlayer().getName());
+ pepe.startInstance(cm.getPlayer());
+ cm.dispose();
+ return;
+ }
+ }
+}
\ No newline at end of file
diff --git a/scripts/npc/2060005.js b/scripts/npc/2060005.js
index 13937b4b4c..4ff99de789 100644
--- a/scripts/npc/2060005.js
+++ b/scripts/npc/2060005.js
@@ -46,7 +46,7 @@ function start() {
}
}
else {
- cm.sendSimple("Only few adventurers, from a selected public, are eligible to protect the Watch Hog.");
+ cm.sendOk("Only few adventurers, from a selected public, are eligible to protect the Watch Hog.");
}
cm.dispose();
diff --git a/scripts/npc/9000017.js b/scripts/npc/9000017.js
index f9ee0e2205..e074b84fbc 100644
--- a/scripts/npc/9000017.js
+++ b/scripts/npc/9000017.js
@@ -46,7 +46,7 @@ function action(mode, type, selection) {
var itemSet = new Array(2049100, 7777777);
var matSet = new Array(new Array(4031203,4001356,4000136,4000082,4001126,4080100,4000021,4003005));
- var matQtySet = new Array(new Array(10,6,4,8,8,1,20,12));
+ var matQtySet = new Array(new Array(100,60,40,80,80,8,200,120));
var costSet = new Array(1200000, 7777777);
item = itemSet[selectedItem];
mats = matSet[selectedItem];
diff --git a/scripts/portal/TD_MC_Egate.js b/scripts/portal/TD_MC_Egate.js
index 88a7ca6401..fe82c1f95c 100644
--- a/scripts/portal/TD_MC_Egate.js
+++ b/scripts/portal/TD_MC_Egate.js
@@ -1,5 +1,5 @@
function enter(pi) {
pi.playPortalSound();
- pi.warp(106021300, 0);
+ pi.warp(106021300, 1);
return true;
}
\ No newline at end of file
diff --git a/scripts/portal/TD_MC_enterboss1.js b/scripts/portal/TD_MC_enterboss1.js
index 9f2d7ad6a6..525c8e64f4 100644
--- a/scripts/portal/TD_MC_enterboss1.js
+++ b/scripts/portal/TD_MC_enterboss1.js
@@ -1,3 +1,23 @@
function enter(pi) {
- pi.openNpc(1300013);
+ var questProgress = pi.getQuestProgress(2330, 3300005) + pi.getQuestProgress(2330, 3300006) + pi.getQuestProgress(2330, 3300007); //3 Yetis
+
+ if(questProgress == 3 && !pi.hasItem(4032388) && !pi.isQuestCompleted(2332)){
+ if(pi.canHold(4032388)){
+ pi.getPlayer().message("You have aquired a key to the Wedding Hall. King Pepe must have dropped it.")
+ pi.gainItem(4032388, 1);
+ }
+ else{
+ pi.getPlayer().message("Please make room in your ETC inventory.");
+ }
+ }
+
+ if(pi.isQuestStarted(2330) && questProgress < 3){
+ pi.openNpc(1300013);
+ }
+ else{
+ pi.playPortalSound();
+ pi.warp(106021401, 1);
+ }
+
+ return true;
}
\ No newline at end of file
diff --git a/scripts/portal/TD_MC_enterboss2.js b/scripts/portal/TD_MC_enterboss2.js
index 41b63bcb0c..70994ceeb0 100644
--- a/scripts/portal/TD_MC_enterboss2.js
+++ b/scripts/portal/TD_MC_enterboss2.js
@@ -1,35 +1,48 @@
-/*
- This file is part of the ZeroFusion MapleStory Server
- Copyright (C) 2008 Patrick Huy
- Matthias Butz
- Jan Christian Meyer
- ZeroFusion organized by "RMZero213"
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License 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 .
-*/
-
-var dungeonid = 106021600;
-var dungeons = 10;
-
function enter(pi) {
- for(var i = 0; i < dungeons; i++) {
- if (pi.getMap(dungeonid + i).getCharactersSize() == 0) {
- pi.warp(dungeonid + i, 0);
- return true;
- }
+ if(pi.isQuestCompleted(2333) && pi.isQuestStarted(2331) && !pi.hasItem(4001318)){
+ pi.getPlayer().message("Lost the Royal Seal, eh? Worry not! Kevin's code here to save your hide.");
+ if(pi.canHold(4001318)){
+ pi.gainItem(4001318, 1);
+ }
+ else{
+ pi.getPlayer().message("Hey, how do you plan to hold this Seal when your inventory is full?");
+ }
}
- pi.playerMessage(5, "All of the Mini-Dungeons are in use right now, please try again later.");
- return false;
-}
+
+ if(pi.isQuestCompleted(2333)){
+ pi.playPortalSound();
+ pi.warp(106021600, 1);
+ return true;
+ }
+ else if(pi.isQuestStarted(2332) && pi.hasItem(4032388)){
+ if(pi.getPlayer().getParty() != null){
+ pi.getPlayer().showHint("The next part of the quest is solo only! Must leave party.");
+ return false;
+ }
+ else{
+ pi.forceCompleteQuest(2332, 1300002);
+ pi.getPlayer().message("You've found the princess!");
+ pi.giveCharacterExp(4400 * 1.5, pi.getPlayer());
+ var pm = pi.getEventManager("MK_PrimeMinister");
+ pm.setProperty("player", pi.getPlayer().getName());
+ pm.startInstance(pi.getPlayer());
+ return true;
+ }
+ }
+ else if(pi.isQuestStarted(2333) || (pi.isQuestCompleted(2332) && !pi.isQuestStarted(2333))){
+ if(pi.getPlayer.getParty() != null){
+ pi.getPlayer().showHint("The next part of the quest is solo only! Must leave party.");
+ return false;
+ }
+ else{
+ var pm = pi.getEventManager("MK_PrimeMinister");
+ pm.setProperty("player", pi.getPlayer().getName());
+ pm.startInstance(pi.getPlayer());
+ return true;
+ }
+ }
+ else{
+ pi.getPlayer().message("The door seems to be locked. Perhaps I can find a key to open it...");
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/scripts/portal/end_cow.js b/scripts/portal/end_cow.js
new file mode 100644
index 0000000000..5960392204
--- /dev/null
+++ b/scripts/portal/end_cow.js
@@ -0,0 +1,22 @@
+/*
+ By: Kevin
+ Map: Hidden Chamber - The Nautilus - Stable (912000100)
+ Quest: Find Fresh Milk (2180)
+*/
+
+function enter(pi){
+ if (pi.isQuestStarted(2180) && (pi.hasItem(4031847) || pi.hasItem(4031848) || pi.hasItem(4031849) || pi.hasItem(4031850))){
+ if (pi.hasItem(4031850)){
+ pi.warp(120000103);
+ return true;
+ }
+ else{
+ pi.getPlayer().dropMessage(5, "Your milk jug is not full...");
+ return false;
+ }
+ }
+ else{
+ pi.warp(120000103);
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/scripts/portal/go_secretroom.js b/scripts/portal/go_secretroom.js
new file mode 100644
index 0000000000..cd87306ea9
--- /dev/null
+++ b/scripts/portal/go_secretroom.js
@@ -0,0 +1,16 @@
+function enter(pi) {
+
+ if(!pi.isQuestStarted(2335) || (pi.isQuestStarted(2335) && !pi.hasItem(4032405))){
+ pi.getPlayer().message("The door is locked securely. I will need a key if I want to go in there.");
+ return false;
+ }
+
+ if(pi.isQuestStarted(2335) && pi.hasItem(4032405)){
+ pi.forceCompleteQuest(2335, 1300002);
+ pi.giveCharacterExp(5000 * 1.5, pi.getPlayer());
+ pi.gainItem(4032405, -1);
+ }
+ pi.playPortalSound();
+ pi.warp(106021001, 1);
+ return true;
+}
\ No newline at end of file
diff --git a/scripts/portal/out_pepeking.js b/scripts/portal/out_pepeking.js
new file mode 100644
index 0000000000..6be6f1059a
--- /dev/null
+++ b/scripts/portal/out_pepeking.js
@@ -0,0 +1,9 @@
+function enter(pi) {
+ var eim = pi.getEventInstance();
+ eim.stopEventTimer();
+ eim.dispose();
+
+ pi.playPortalSound();
+ pi.warp(106021400, 2);
+ return true;
+}
\ No newline at end of file
diff --git a/scripts/quest/20710.js b/scripts/quest/20710.js
new file mode 100644
index 0000000000..6e6bdd7486
--- /dev/null
+++ b/scripts/quest/20710.js
@@ -0,0 +1,35 @@
+/*
+ Author: DietStory dev team
+ NPC: Matthias
+ Quest: Hidden Inside the Trash Can
+*/
+
+
+var status = -1;
+
+function start(mode, type, selection){
+ if(mode == -1){
+ qm.dispose();
+ return;
+ }
+ else if(mode == 0 && status == 0){
+ qm.sendOk("What? Are you declining the mission? Fine, do it like that. I'll just report it straight to #p1101002#.");
+ qm.dispose();
+ return;
+ }
+ else if(mode == 0){
+ status--;
+ }
+ else{
+ status++;
+ }
+
+
+ if(status == 0){
+ qm.sendAcceptDecline("You don't really instill confidence in me, but since you're a Cygnus Knight and all... and since no one else can go on a search right now... Okay, let me explain to you what this mission is about.");
+ }
+ else if(status == 1){
+ qm.forceStartQuest();
+ qm.dispose();
+ }
+}
\ No newline at end of file
diff --git a/scripts/quest/2293.js b/scripts/quest/2293.js
new file mode 100644
index 0000000000..1119170795
--- /dev/null
+++ b/scripts/quest/2293.js
@@ -0,0 +1,110 @@
+/*
+ This file is part of the DietStory Maple Story Server
+ Copyright (C) 2017
+ 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: Benji
+ NPC Name: Maestro Rho
+ Map(s): Kerning Square Lobby
+ Description: The Last Song
+*/
+
+importPackage(Packages.client);
+
+var status = -1;
+
+function start(mode, type, selection) {
+ if(mode == -1 || (mode == 0 && status == 0)){
+ qm.dispose();
+ return;
+ }
+ else if(mode == 0)
+ status--;
+ else
+ status++;
+
+ if(status == 0)
+ {
+ qm.sendNext("Do you remember the last song that the Spirit of Rock played? I can think of a few songs that he may be imitating, so listen carefully and tell me which song it is. #bYou only get one chance,#k so please choose wisely.");
+ }
+ qm.forceStartQuest();
+ qm.dispose();
+}
+
+function end(mode, type, selection)
+{
+ if(mode == -1 || (mode == 0 && status == 0)){
+ qm.dispose();
+ return;
+ }
+ else if(mode == 0)
+ status--;
+ else
+ status++;
+
+ if (status == 0)
+ {
+ qm.sendSimple("Here, I'll give you some samples. Please listen to them and choose one. Please listen carefully before making your choide.\r\n\
+ \t#b#L1# Listen to song No. 1#l \r\n\
+ \t#L2# Listen to Song No. 2#l \r\n\
+ \t#L3# Listen to Song No. 3#l \r\n\
+ \r\n\
+ \t#e#L4# Enter the correct song.#l");
+ }
+ else if(status == 1)
+ {
+ if(selection == 1)
+ {
+ qm.playSound("Party1/Failed");
+ qm.sendOk("Awkwardly familiar...");
+ status = -1;
+ }
+ else if(selection == 2)
+ {
+ qm.playSound("Coconut/Failed");
+ qm.sendOk("Was it this?");
+ status = -1;
+ }
+ else if(selection == 3)
+ {
+ qm.playSound("quest2293/Die");
+ qm.sendOk("You heard that?");
+ status = -1;
+ }
+ else if(selection == 4)
+ {
+ qm.sendGetNumber("Now, please tell me the answer. You only get #bone chance#k, so please choose wisely. Please enter #b1, 2, or 3#k in the window below.\r\n",1,1,3);
+ }
+ }
+ else if(status == 2)
+ {
+ if(selection == 1)
+ {
+ qm.sendOk("Obviously you don't enjoy music.");
+ qm.dispose();
+ }
+ else if(selection == 2)
+ {
+ qm.sendOk("I suppose you could get #b#eone#n#k more chance.");
+ qm.dispose();
+ }
+ else if(selection == 3)
+ {
+ qm.sendOk("So that was the song he was playing... Well, it wasn't my song after all, but I'm glad I can know that now with certainty. Thank you so much.");
+ qm.gainExp(32500 * qm.getPlayer().getExpRate());
+ qm.forceCompleteQuest();
+ qm.dispose();
+ }
+ }
+}
\ No newline at end of file
diff --git a/scripts/quest/2325.js b/scripts/quest/2325.js
new file mode 100644
index 0000000000..2704bba250
--- /dev/null
+++ b/scripts/quest/2325.js
@@ -0,0 +1,30 @@
+/*
+ QUEST: Jame's Whereabouts (1)
+ NPC: James
+*/
+
+var status = -1;
+
+function end(mode, type, selection){
+ if(mode == -1){
+ qm.dispose();
+ return;
+ }
+ else if(mode == 0)
+ status--;
+ else
+ status++;
+
+ if(status == 0){
+ qm.sendNext("I... I am scared... Please... please help me...");
+ }
+ else if(status == 1){
+ qm.sendNextPrev("Don't be afriad, #b#p1300005##k sent me here.", 2);
+ }
+ else if(status == 2){
+ qm.sendOk("What? My brother sent you here? Ahhh... I am safe now. Thank you so much...");
+ qm.forceCompleteQuest();
+ qm.gainExp(6000 * qm.getPlayer().getExpRate());
+ qm.dispose();
+ }
+}
\ No newline at end of file
diff --git a/scripts/quest/2327.js b/scripts/quest/2327.js
new file mode 100644
index 0000000000..2299f14a8c
--- /dev/null
+++ b/scripts/quest/2327.js
@@ -0,0 +1,33 @@
+/*
+ QUEST: James's Whereabouts (3)
+ NPC: James
+ Why tf does this quest exist?!
+*/
+
+var status = -1;
+
+function start(mode, type, selection){
+ if(mode == -1){
+ qm.dispose();
+ return;
+ }
+ else if(mode == 0 && status == 0){
+ qm.dispose();
+ return;
+ }
+ else if(mode == 0)
+ status--;
+ else
+ status++;
+
+ if(status == 0){
+ qm.sendNext("Hey! Thank you for bringing me a #b#t4001317##k.");
+ }
+ else if(status == 1){
+ qm.sendNextPrev("I plan to escape from here wearing the #b#t4001317##k. Give me a minute to put it on. Talk to you soon...");
+ }
+ else if(status == 2){
+ qm.forceStartQuest();
+ qm.dispose();
+ }
+}
\ No newline at end of file
diff --git a/scripts/quest/2332.js b/scripts/quest/2332.js
new file mode 100644
index 0000000000..432a2f9858
--- /dev/null
+++ b/scripts/quest/2332.js
@@ -0,0 +1,17 @@
+/*
+ QUEST: Where's Violetta?
+ NPC: none
+*/
+
+var status = -1;
+
+function start(mode, type, selection){
+ if(qm.hasItem(4032388) && !qm.isQuestStarted(2332)){
+ qm.forceStartQuest();
+ qm.getPlayer().showHint("I must find Violetta. (quest started)");
+ }
+ qm.dispose();
+}
+
+function end(mode, type, selection){
+}
\ No newline at end of file
diff --git a/scripts/quest/2333.js b/scripts/quest/2333.js
new file mode 100644
index 0000000000..2eea658d7c
--- /dev/null
+++ b/scripts/quest/2333.js
@@ -0,0 +1,65 @@
+/*
+ QUEST: Where's Violetta?
+ NPC: none
+*/
+importPackage(Packages.server.life);
+
+var status = -1;
+var timeLimit = 10; //10 minutes
+var eventTimer = 1000 * 60 * timeLimit;
+var mobId = 3300008; //Prime Minister
+
+function start(mode, type, selection){
+ if(mode == -1 || (mode == 0 && status == 0)){
+ qm.dispose();
+ return;
+ }
+ else if(mode == 0)
+ status--;
+ else
+ status++;
+
+
+ if(status == 0){
+ qm.sendAcceptDecline("Please help me!");
+ }
+ else if(status == 1){
+ qm.sendNext("The #bPrime Minister#k is the one who plotted all this! Oh no! Here he comes...");
+ }
+ else if (status == 2){
+ qm.forceStartQuest();
+ var eim = qm.getEventInstance();
+ eim.startEventTimer(eventTimer);
+ qm.getPlayer().getMap().getPortal(1).setPortalState(false);
+ qm.getPlayer().getMap().spawnMonsterOnGroundBelow(MapleLifeFactory.getMonster(mobId), new java.awt.Point(292, 143));
+ qm.dispose();
+ }
+}
+
+function end(mode, type, selection){
+ if(mode == -1 || (mode == 0 && status == 0)){
+ qm.dispose();
+ return;
+ }
+ else if(mode == 0)
+ status--;
+ else
+ status++;
+
+
+ if(status == 0){
+ qm.sendNext("Hurray! #b#h ##k you defeated the #bPrime Minister#k.");
+ }
+ else if(status == 1){
+ qm.gainExp(15000 * qm.getPlayer().getExpRate());
+ qm.forceCompleteQuest();
+
+ var eim = qm.getEventInstance();
+ qm.getPlayer().getMap().getPortal(1).setPortalState(true);
+ eim.stopEventTimer();
+ eim.warpEventTeam(106021600);
+
+ eim.dispose();
+ qm.dispose();
+ }
+}
\ No newline at end of file
diff --git a/scripts/quest/2334.js b/scripts/quest/2334.js
new file mode 100644
index 0000000000..ac0e2aea87
--- /dev/null
+++ b/scripts/quest/2334.js
@@ -0,0 +1,46 @@
+/*
+ QUEST: The Identity of the Princess
+ NPC: Violetta
+*/
+
+var status = -1;
+
+function start(mode, type, selection){
+ if(mode == -1 || (mode == 0 && status == 0)){
+ qm.dispose();
+ return;
+ }
+ else if(mode == 0)
+ status--;
+ else
+ status++;
+
+
+ if(status == 0){
+ qm.forceStartQuest();
+ qm.sendNext("Thank you so much, #b#h ##k. You are the hero that has saved our empire from danger. I'm so grateful for what you've done. I dont know how to thank you. And please understand why I can't show you my face.");
+ }
+ else if(status == 1){
+ qm.sendNextPrev("It's humiliating to say this, but ever since I was a baby, my family has kept my face veiled from the world. They feared of men falling hopelessly in love with me. I've grown so accustomed to it that I even shy away from women. I know, it's rude of me to have my back turned against the hero, but I'll need some time to muster my courage before I can greet you face to face.");
+ }
+ else if(status == 2){
+ qm.sendNextPrev("I see...\r\n#b(Wow, how pretty could she be?)", 2);
+ }
+ else if(status == 3){
+ qm.sendNextPrev("#b(What the--)", 2);
+ }
+ else if(status == 4){
+ qm.sendNextPrev("#b(Is that what's considered pretty in the world of mushrooms?!)", 2);
+ }
+ else if(status == 5){
+ qm.sendNextPrev("I'm so shy, I'm blushing. Anyways, thank you, #b#h ##k.");
+ }
+ else if(status == 6){
+ qm.forceStartQuest();
+ qm.gainExp(1000 * qm.getPlayer().getExpRate());
+ qm.forceCompleteQuest();
+ qm.dispose();
+ }
+}
+
+function end(mode, type, selection){}
\ No newline at end of file
diff --git a/scripts/quest/2335.js b/scripts/quest/2335.js
new file mode 100644
index 0000000000..96117e0e4c
--- /dev/null
+++ b/scripts/quest/2335.js
@@ -0,0 +1,41 @@
+/*
+ QUEST: Eliminating the Rest
+ NPC: Violetta
+*/
+
+var status = -1;
+
+function start(mode, type, selection){
+ if(mode == -1 || (mode == 0 && status == 0)){
+ qm.dispose();
+ return;
+ }
+ else if(mode == 0)
+ status--;
+ else
+ status++;
+
+
+ if(status == 0){
+ qm.sendNext("This is not the end, #b#h ##k. Minions of the #bPrime Minister#k can still be found scattered throughout the castle.");
+ }
+ else if(status == 1){
+ qm.sendAcceptDecline("From what I've heard, there is a place near #bSkyscraper 3#k where a group of Prime Minister's minions can be found. I've picked up a key that the Prime Minister dropped the other day. Here, use this key.");
+ }
+ else if(status == 2){
+ if(qm.canHold(4032405)){
+ qm.gainItem(4032405, 1);
+ qm.sendNext("For one last time, good luck.");
+ }
+ else{
+ qm.sendOk("Please have a free space in your ETC inventory.");
+ qm.dispose();
+ }
+ }
+ else if(status == 3){
+ qm.forceStartQuest();
+ qm.dispose();
+ }
+}
+
+function end(mode, type, selection){}
\ No newline at end of file
diff --git a/scripts/quest/2342.js b/scripts/quest/2342.js
new file mode 100644
index 0000000000..6c8aed8d0d
--- /dev/null
+++ b/scripts/quest/2342.js
@@ -0,0 +1,28 @@
+/*
+ QUEST: Recovered Royal Seal.
+ NPC: Violetta
+*/
+
+var status = -1;
+
+function start(mode, type, selection){
+ if(!qm.hasItem(4001318) && qm.isQuestStarted(2331) && !qm.isQuestCompleted(2331)){
+ if(qm.canHold(4001318)){
+ qm.forceStartQuest();
+ qm.gainItem(4001318, 1);
+ qm.forceCompleteQuest();
+ qm.sendOk("Looks like you forgot to pick up the #b#t4001318##k when you fought with the #bPrime Minister#k. This is very important to our kingdom, so please deliver this to my father as soon as possible.");
+ qm.dispose();
+ }
+ else{
+ qm.sendOk("Please free up one spot in your ETC inventory");
+ qm.dispose();
+ }
+ }
+ else{
+ qm.dispose();
+ }
+}
+
+function end(mode, type, selection){
+}
\ No newline at end of file
diff --git a/sql/db_database.sql b/sql/db_database.sql
index 36024833ee..e089143276 100644
--- a/sql/db_database.sql
+++ b/sql/db_database.sql
@@ -21079,7 +21079,8 @@ INSERT INTO `shops` (`shopid`, `npcid`) VALUES
-- missing shops
INSERT INTO `shops` (`shopid`, `npcid`) VALUES
( 57, 2002001 ),
-(1052116, 1052116);
+(1052116, 1052116),
+(1301000, 1301000);
INSERT INTO `shopitems` ( `shopid`, `itemid`, `price`, `position`) VALUES
( 57, 3990000, 500, 1 ),
diff --git a/sql/db_drops.sql b/sql/db_drops.sql
index a7cced0499..f021bd77f7 100644
--- a/sql/db_drops.sql
+++ b/sql/db_drops.sql
@@ -19779,7 +19779,8 @@ USE `maplesolaxia`;
(2130100, 4001367, 1, 1, 28257, 10000),
(1110100, 4001369, 1, 1, 28259, 10000),
(1210101, 4001370, 1, 1, 28260, 10000),
-(1110101, 4001371, 1, 1, 28261, 10000);
+(1110101, 4001371, 1, 1, 28261, 10000),
+(3300003, 4001317, 1, 1, 2326, 20000);
# (dropperid, itemid, minqty, maxqty, questid, chance)
# delete item drops from other mobs named Freezer
@@ -19929,6 +19930,9 @@ USE `maplesolaxia`;
# remove belts dropping from mobs
DELETE FROM drop_data WHERE itemid>=1132000 AND itemid<=1132004;
+ # remove Liar Tree Sap (unusable)
+ DELETE FROM drop_data WHERE itemid=2049101;
+
# remove items being dropped from mobs in HPQ
DELETE FROM drop_data WHERE dropperid >= 9300061 AND dropperid <= 9300064;
DELETE FROM drop_data WHERE dropperid >= 9300081 AND dropperid <= 9300083;
@@ -20549,6 +20553,12 @@ USE `maplesolaxia`;
(9400533, 4031597, 1, 1, 0, 999999),
(9400534, 4031597, 1, 1, 0, 999999);
+ -- Thanks to DietStory dev team
+ -- There are two Jr. Boogies mob ids for some unknown reason. 3230301 had no drops, but 3230300 had all the correct drops.
+ -- Just copying the drops from the one with the correct drop data.
+ INSERT IGNORE INTO drop_data (`dropperid`, `itemid`, `minimum_quantity`, `maximum_quantity`, `questid`, `chance`)
+ SELECT 3230301, `itemid`, `minimum_quantity`, `maximum_quantity`, `questid`, `chance` FROM drop_data WHERE dropperid = 3230300;
+
# update quest reactor items
UPDATE reactordrops SET questid=2086 WHERE itemid=4031165;
UPDATE reactordrops SET questid=3407 WHERE itemid=4031141;
diff --git a/sql/db_shopupdate.sql b/sql/db_shopupdate.sql
index 14bc29e15e..06f45652bb 100644
--- a/sql/db_shopupdate.sql
+++ b/sql/db_shopupdate.sql
@@ -283,4 +283,21 @@ INSERT INTO `shopitems` ( `shopid`, `itemid`, `price`, `pitch`, `position`) VALU
(1203590, 2000003, 200, 0, 184),
(1203590, 2000002, 320, 0, 188),
(1203590, 2000001, 160, 0, 192),
- (1203590, 2000000, 50, 0, 196);
\ No newline at end of file
+ (1203590, 2000000, 50, 0, 196),
+ (1301000, 2330000, 600, 0, 1),
+ (1301000, 2070000, 500, 0, 2),
+ (1301000, 2061000, 1, 0, 3),
+ (1301000, 2060000, 1, 0, 4),
+ (1301000, 2030000, 400, 0, 5),
+ (1301000, 2022000, 1650, 0, 6),
+ (1301000, 2022003, 1100, 0, 7),
+ (1301000, 2002005, 500, 0, 8),
+ (1301000, 2002004, 500, 0, 9),
+ (1301000, 2002002, 500, 0, 10),
+ (1301000, 2002001, 400, 0, 11),
+ (1301000, 2002000, 500, 0, 12),
+ (1301000, 2000006, 620, 0, 13),
+ (1301000, 2000003, 200, 0, 14),
+ (1301000, 2000002, 320, 0, 15),
+ (1301000, 2000015, 160, 0, 16),
+ (1301000, 2000000, 50, 0, 17);
\ No newline at end of file
diff --git a/src/client/MapleCharacter.java b/src/client/MapleCharacter.java
index ec7b35e8bb..58a332a990 100644
--- a/src/client/MapleCharacter.java
+++ b/src/client/MapleCharacter.java
@@ -242,6 +242,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
private Map activeCouponRates = new LinkedHashMap<>();
private EnumMap effects = new EnumMap<>(MapleBuffStat.class);
private Map buffEffectsCount = new LinkedHashMap<>();
+ private Map diseaseExpires = new LinkedHashMap<>();
private Map> buffEffects = new LinkedHashMap<>();
private Map buffExpires = new LinkedHashMap<>();
private Map keymap = new LinkedHashMap<>();
@@ -255,6 +256,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
private ScheduledFuture> skillCooldownTask = null;
private ScheduledFuture> buffExpireTask = null;
private ScheduledFuture> itemExpireTask = null;
+ private ScheduledFuture> diseaseExpireTask = null;
private ScheduledFuture> recoveryTask = null;
private ScheduledFuture> extraRecoveryTask = null;
private ScheduledFuture> chairRecoveryTask = null;
@@ -263,6 +265,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
private Lock chrLock = new ReentrantLock();
private Lock effLock = new ReentrantLock();
private Lock petLock = new ReentrantLock();
+ private Lock prtLock = new ReentrantLock();
private Map> excluded = new LinkedHashMap<>();
private Set excludedItems = new LinkedHashSet<>();
private List crushRings = new ArrayList<>();
@@ -866,8 +869,9 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
public static boolean canCreateChar(String name) {
+ String lname = name.toLowerCase();
for (String nameTest : BLOCKED_NAMES) {
- if (name.toLowerCase().contains(nameTest)) {
+ if (lname.contains(nameTest)) {
return false;
}
}
@@ -1056,10 +1060,11 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
public MapleMap getWarpMap(int map) {
MapleMap target;
- if (getEventInstance() == null) {
+ EventInstanceManager eim = getEventInstance();
+ if (eim == null) {
target = client.getChannelServer().getMapFactory().getMap(map);
} else {
- target = getEventInstance().getMapInstance(map);
+ target = eim.getMapInstance(map);
}
return target;
}
@@ -1070,11 +1075,13 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
private void eventChangedMap(int map) {
- if (getEventInstance() != null) getEventInstance().changedMap(this, map);
+ EventInstanceManager eim = getEventInstance();
+ if (eim != null) eim.changedMap(this, map);
}
private void eventAfterChangedMap(int map) {
- if (getEventInstance() != null) getEventInstance().afterChangedMap(this, map);
+ EventInstanceManager eim = getEventInstance();
+ if (eim != null) eim.afterChangedMap(this, map);
}
public boolean canRecoverLastBanish() {
@@ -1117,8 +1124,10 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
public void changeMap(int map) {
MapleMap warpMap;
- if (getEventInstance() != null) {
- warpMap = getEventInstance().getMapInstance(map);
+ EventInstanceManager eim = getEventInstance();
+
+ if (eim != null) {
+ warpMap = eim.getMapInstance(map);
} else {
warpMap = client.getChannelServer().getMapFactory().getMap(map);
}
@@ -1128,8 +1137,10 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
public void changeMap(int map, int portal) {
MapleMap warpMap;
- if (getEventInstance() != null) {
- warpMap = getEventInstance().getMapInstance(map);
+ EventInstanceManager eim = getEventInstance();
+
+ if (eim != null) {
+ warpMap = eim.getMapInstance(map);
} else {
warpMap = client.getChannelServer().getMapFactory().getMap(map);
}
@@ -1139,8 +1150,10 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
public void changeMap(int map, String portal) {
MapleMap warpMap;
- if (getEventInstance() != null) {
- warpMap = getEventInstance().getMapInstance(map);
+ EventInstanceManager eim = getEventInstance();
+
+ if (eim != null) {
+ warpMap = eim.getMapInstance(map);
} else {
warpMap = client.getChannelServer().getMapFactory().getMap(map);
}
@@ -1150,8 +1163,10 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
public void changeMap(int map, MaplePortal portal) {
MapleMap warpMap;
- if (getEventInstance() != null) {
- warpMap = getEventInstance().getMapInstance(map);
+ EventInstanceManager eim = getEventInstance();
+
+ if (eim != null) {
+ warpMap = eim.getMapInstance(map);
} else {
warpMap = client.getChannelServer().getMapFactory().getMap(map);
}
@@ -1231,11 +1246,17 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
map = to;
setPosition(pos);
map.addPlayer(this);
- if (party != null) {
- mpc.setMapId(to.getId());
- silentPartyUpdate();
- client.announce(MaplePacketCreator.updateParty(client.getChannel(), party, PartyOperation.SILENT_UPDATE, null));
- updatePartyMemberHP();
+
+ prtLock.lock();
+ try {
+ if (party != null) {
+ mpc.setMapId(to.getId());
+ silentPartyUpdateInternal();
+ client.announce(MaplePacketCreator.updateParty(client.getChannel(), party, PartyOperation.SILENT_UPDATE, null));
+ updatePartyMemberHPInternal();
+ }
+ } finally {
+ prtLock.unlock();
}
if (getMap().getHPDec() > 0) resetHpDecreaseTask();
@@ -1254,8 +1275,9 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
// if this event map has a gate already opened, render it
- if(getEventInstance() != null) {
- getEventInstance().recoverOpenedGate(this, map.getId());
+ EventInstanceManager eim = getEventInstance();
+ if(eim != null) {
+ eim.recoverOpenedGate(this, map.getId());
}
// if this map has obstacle components moving, make it do so for this client
@@ -1446,27 +1468,32 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
return;
}
if (mapitem.getMeso() > 0) {
- if (this.getParty() != null) {
- int mesosamm = mapitem.getMeso();
- if (mesosamm > 50000 * this.getMesoRate()) {
- return;
- }
- int partynum = 0;
- for (MaplePartyCharacter partymem : this.getParty().getMembers()) {
- if (partymem.isOnline() && partymem.getMapId() == this.getMap().getId() && partymem.getChannel() == client.getChannel()) {
- partynum++;
+ prtLock.lock();
+ try {
+ if (this.party != null) {
+ int mesosamm = mapitem.getMeso();
+ if (mesosamm > 50000 * this.getMesoRate()) {
+ return;
}
- }
- for (MaplePartyCharacter partymem : this.getParty().getMembers()) {
- if (partymem.isOnline() && partymem.getMapId() == this.getMap().getId()) {
- MapleCharacter somecharacter = client.getChannelServer().getPlayerStorage().getCharacterById(partymem.getId());
- if (somecharacter != null) {
- somecharacter.gainMeso(mesosamm / partynum, true, true, false);
+ int partynum = 0;
+ for (MaplePartyCharacter partymem : this.party.getMembers()) {
+ if (partymem.isOnline() && partymem.getMapId() == this.getMap().getId() && partymem.getChannel() == client.getChannel()) {
+ partynum++;
}
}
+ for (MaplePartyCharacter partymem : this.party.getMembers()) {
+ if (partymem.isOnline() && partymem.getMapId() == this.getMap().getId()) {
+ MapleCharacter somecharacter = client.getChannelServer().getPlayerStorage().getCharacterById(partymem.getId());
+ if (somecharacter != null) {
+ somecharacter.gainMeso(mesosamm / partynum, true, true, false);
+ }
+ }
+ }
+ } else {
+ this.gainMeso(mapitem.getMeso(), true, true, false);
}
- } else {
- this.gainMeso(mapitem.getMeso(), true, true, false);
+ } finally {
+ prtLock.unlock();
}
} else if (mapitem.getItem().getItemId() / 10000 == 243) {
MapleItemInformationProvider.scriptedItem info = ii.getScriptedItemInfo(mapitem.getItem().getItemId());
@@ -1930,16 +1957,11 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
}
- TimerManager.getInstance().schedule(new Runnable() {
- @Override
- public void run() {
- dispelDebuff(disease);
- }
- }, skill.getDuration());
-
chrLock.lock();
try {
- diseases.put(disease, new MapleDiseaseValueHolder(System.currentTimeMillis(), skill.getDuration()));
+ long curTime = System.currentTimeMillis();
+ diseaseExpires.put(disease, curTime + skill.getDuration());
+ diseases.put(disease, new MapleDiseaseValueHolder(curTime, skill.getDuration()));
} finally {
chrLock.unlock();
}
@@ -1959,6 +1981,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
chrLock.lock();
try {
diseases.remove(debuff);
+ diseaseExpires.remove(debuff);
} finally {
chrLock.unlock();
}
@@ -2092,6 +2115,41 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
}
+ public void cancelDiseaseExpireTask() {
+ if (diseaseExpireTask != null) {
+ diseaseExpireTask.cancel(false);
+ diseaseExpireTask = null;
+ }
+ }
+
+ public void diseaseExpireTask() {
+ if (diseaseExpireTask == null) {
+ diseaseExpireTask = TimerManager.getInstance().register(new Runnable() {
+ @Override
+ public void run() {
+ Set toExpire = new LinkedHashSet<>();
+
+ chrLock.lock();
+ try {
+ long curTime = System.currentTimeMillis();
+
+ for(Entry d : diseaseExpires.entrySet()) {
+ if(d.getValue() < curTime) {
+ toExpire.add(d.getKey());
+ }
+ }
+ } finally {
+ chrLock.unlock();
+ }
+
+ for(MapleDisease d : toExpire) {
+ dispelDebuff(d);
+ }
+ }
+ }, 1500);
+ }
+ }
+
public void cancelBuffExpireTask() {
if (buffExpireTask != null) {
buffExpireTask.cancel(false);
@@ -2285,7 +2343,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
if(party < 0) party = Integer.MAX_VALUE; // integer overflow, heh.
int equip = (int)Math.min((long)((gain / 10) * pendantExp), Integer.MAX_VALUE);
- long total = gain + equip + party;
+ long total = (long)gain + equip + party;
gainExpInternal(total, equip, party, show, inChat, white);
}
@@ -2918,12 +2976,17 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
destroyDoor.getTownDoor().sendDestroyData(chr.getClient());
}
- if (party != null) {
- for (MaplePartyCharacter partyMembers : getParty().getMembers()) {
- partyMembers.getPlayer().removeDoor(this.getId());
- partyMembers.removeDoor(this.getId());
+ prtLock.lock();
+ try {
+ if (party != null) {
+ for (MaplePartyCharacter partyMembers : party.getMembers()) {
+ partyMembers.getPlayer().removeDoor(this.getId());
+ partyMembers.removeDoor(this.getId());
+ }
+ silentPartyUpdateInternal();
}
- silentPartyUpdate();
+ } finally {
+ prtLock.unlock();
}
}
}
@@ -3816,7 +3879,12 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
public int getDoorSlot() {
if(doorSlot == -1) {
- doorSlot = (party == null) ? 0 : party.getPartyDoor(this.getId());
+ prtLock.lock();
+ try {
+ doorSlot = (party == null) ? 0 : party.getPartyDoor(this.getId());
+ } finally {
+ prtLock.unlock();
+ }
}
return doorSlot;
@@ -3906,20 +3974,35 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
public MapleParty getParty() {
- return party;
+ prtLock.lock();
+ try {
+ return party;
+ } finally {
+ prtLock.unlock();
+ }
}
public int getPartyId() {
- return (party != null ? party.getId() : -1);
+ prtLock.lock();
+ try {
+ return (party != null ? party.getId() : -1);
+ } finally {
+ prtLock.unlock();
+ }
}
public List getPartyMembers() {
List list = new LinkedList<>();
- if(party != null) {
- for(MaplePartyCharacter partyMembers: party.getMembers()) {
- list.add(partyMembers.getPlayer());
+ prtLock.lock();
+ try {
+ if(party != null) {
+ for(MaplePartyCharacter partyMembers: party.getMembers()) {
+ list.add(partyMembers.getPlayer());
+ }
}
+ } finally {
+ prtLock.unlock();
}
return list;
@@ -3929,10 +4012,15 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
List list = new LinkedList<>();
int thisMapHash = this.getMap().hashCode();
- if(party != null) {
- for(MaplePartyCharacter partyMembers: party.getMembers()) {
- if(partyMembers.getPlayer().getMap().hashCode() == thisMapHash) list.add(partyMembers.getPlayer());
+ prtLock.lock();
+ try {
+ if(party != null) {
+ for(MaplePartyCharacter partyMembers: party.getMembers()) {
+ if(partyMembers.getPlayer().getMap().hashCode() == thisMapHash) list.add(partyMembers.getPlayer());
+ }
}
+ } finally {
+ prtLock.unlock();
}
return list;
@@ -4593,7 +4681,12 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
public boolean isPartyLeader() {
- return party.getLeaderId() == getId();
+ prtLock.lock();
+ try {
+ return party.getLeaderId() == getId();
+ } finally {
+ prtLock.unlock();
+ }
}
public boolean isGuildLeader() { // true on guild master or jr. master
@@ -5545,8 +5638,10 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
private void playerDead() {
cancelAllBuffs(false);
dispelDebuffs();
- if (getEventInstance() != null) {
- getEventInstance().playerKilled(this);
+
+ EventInstanceManager eim = getEventInstance();
+ if (eim != null) {
+ eim.playerKilled(this);
}
int[] charmID = {5130000, 4031283, 4140903};
int possesed = 0;
@@ -5741,16 +5836,21 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
public void receivePartyMemberHP() {
- if (party != null) {
- int channel = client.getChannel();
- for (MaplePartyCharacter partychar : party.getMembers()) {
- if (partychar.getMapId() == getMapId() && partychar.getChannel() == channel) {
- MapleCharacter other = Server.getInstance().getWorld(world).getChannel(channel).getPlayerStorage().getCharacterByName(partychar.getName());
- if (other != null) {
- client.announce(MaplePacketCreator.updatePartyMemberHP(other.getId(), other.getHp(), other.getCurrentMaxHp()));
+ prtLock.lock();
+ try {
+ if (party != null) {
+ int channel = client.getChannel();
+ for (MaplePartyCharacter partychar : party.getMembers()) {
+ if (partychar.getMapId() == getMapId() && partychar.getChannel() == channel) {
+ MapleCharacter other = Server.getInstance().getWorld(world).getChannel(channel).getPlayerStorage().getCharacterByName(partychar.getName());
+ if (other != null) {
+ client.announce(MaplePacketCreator.updatePartyMemberHP(other.getId(), other.getHp(), other.getCurrentMaxHp()));
+ }
}
}
}
+ } finally {
+ prtLock.unlock();
}
}
@@ -6128,11 +6228,18 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
ps.setInt(24, 0);
}
}
- if (party != null) {
- ps.setInt(25, party.getId());
- } else {
- ps.setInt(25, -1);
+
+ prtLock.lock();
+ try {
+ if (party != null) {
+ ps.setInt(25, party.getId());
+ } else {
+ ps.setInt(25, -1);
+ }
+ } finally {
+ prtLock.unlock();
}
+
ps.setInt(26, buddylist.getCapacity());
if (messenger != null) {
ps.setInt(27, messenger.getId());
@@ -6782,15 +6889,20 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
}
- public void setParty(MapleParty party) {
- if (party == null) {
- this.mpc = null;
- doorSlot = -1;
-
- this.party = null;
- //cancelMagicDoor(); // cancel magic doors if kicked out / quitted from party.
- } else {
- this.party = party;
+ public void setParty(MapleParty p) {
+ prtLock.lock();
+ try {
+ if (p == null) {
+ this.mpc = null;
+ doorSlot = -1;
+
+ party = null;
+ //cancelMagicDoor(); // cancel magic doors if kicked out / quitted from party.
+ } else {
+ party = p;
+ }
+ } finally {
+ prtLock.unlock();
}
}
@@ -6998,6 +7110,15 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
public void silentPartyUpdate() {
+ prtLock.lock();
+ try {
+ silentPartyUpdateInternal();
+ } finally {
+ prtLock.unlock();
+ }
+ }
+
+ private void silentPartyUpdateInternal() {
if (party != null) {
Server.getInstance().getWorld(world).updateParty(party.getId(), PartyOperation.SILENT_UPDATE, getMPC());
}
@@ -7118,6 +7239,15 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
public void updatePartyMemberHP() {
+ prtLock.lock();
+ try {
+ updatePartyMemberHPInternal();
+ } finally {
+ prtLock.unlock();
+ }
+ }
+
+ private void updatePartyMemberHPInternal() {
if (party != null) {
int channel = client.getChannel();
for (MaplePartyCharacter partychar : party.getMembers()) {
@@ -7628,8 +7758,10 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
cancelBuffExpireTask();
+ cancelDiseaseExpireTask();
cancelSkillCooldownTask();
cancelExpirationTask();
+
for (ScheduledFuture> sf : timers) {
sf.cancel(false);
}
diff --git a/src/client/MapleClient.java b/src/client/MapleClient.java
index 160995bfe5..d3a3e4ebd4 100644
--- a/src/client/MapleClient.java
+++ b/src/client/MapleClient.java
@@ -88,7 +88,7 @@ public class MapleClient {
public static final String CLIENT_KEY = "CLIENT";
private MapleAESOFB send;
private MapleAESOFB receive;
- private IoSession session;
+ private final IoSession session;
private MapleCharacter player;
private int channel = 1;
private int accId = 1;
@@ -123,15 +123,15 @@ public class MapleClient {
this.session = session;
}
- public synchronized MapleAESOFB getReceiveCrypto() {
+ public MapleAESOFB getReceiveCrypto() {
return receive;
}
- public synchronized MapleAESOFB getSendCrypto() {
+ public MapleAESOFB getSendCrypto() {
return send;
}
- public synchronized IoSession getSession() {
+ public IoSession getSession() {
return session;
}
@@ -459,7 +459,7 @@ public class MapleClient {
public boolean checkPin(String other) {
pinattempt++;
if (pinattempt > 5) {
- getSession().close(true);
+ session.close(false);
}
if (pin.equals(other)) {
pinattempt = 0;
@@ -493,7 +493,7 @@ public class MapleClient {
picattempt++;
if (picattempt > 5) {
- getSession().close(true);
+ session.close(false);
}
if (pic.equals(other)) {
picattempt = 0;
@@ -505,7 +505,7 @@ public class MapleClient {
public int login(String login, String pwd) {
loginattempt++;
if (loginattempt > 4) {
- getSession().close(true);
+ session.close(false);
}
int loginok = 5;
Connection con = null;
@@ -934,12 +934,12 @@ public class MapleClient {
if (!serverTransition && isLoggedIn()) {
updateLoginState(MapleClient.LOGIN_NOTLOGGEDIN);
session.removeAttribute(MapleClient.CLIENT_KEY); // prevents double dcing during login
- session.close();
+ session.close(false);
}
engines.clear();
}
- private void clear() {
+ private void clear() { //usable when defining client = null shortly after
this.accountName = null;
this.macs = null;
this.hwid = null;
@@ -1013,8 +1013,8 @@ public class MapleClient {
public void run() {
try {
if (lastPong < then) {
- if (getSession() != null && getSession().isConnected()) {
- getSession().close(true);
+ if (session != null && session.isConnected()) {
+ session.close(false);
}
}
} catch (NullPointerException e) {
@@ -1307,6 +1307,7 @@ public class MapleClient {
server.getPlayerBuffStorage().addBuffsToStorage(player.getId(), player.getAllBuffs());
player.cancelAllBuffs(true);
player.cancelBuffExpireTask();
+ player.cancelDiseaseExpireTask();
player.cancelSkillCooldownTask();
//Cancelling magicdoor? Nope
//Cancelling mounts? Noty
diff --git a/src/client/command/Commands.java b/src/client/command/Commands.java
index 145d4b1b23..76e119187e 100644
--- a/src/client/command/Commands.java
+++ b/src/client/command/Commands.java
@@ -1424,12 +1424,12 @@ public class Commands {
String sendStr = "";
if(sub[1].equalsIgnoreCase("on")) {
- sendStr += "GM Fly feature enabled. With fly active, GM's cannot attack.";
+ sendStr += "Enabled Fly feature (F1). With fly active, you cannot attack.";
if(!srv.canFly(accid)) sendStr += " Re-login to take effect.";
srv.changeFly(c.getAccID(), true);
} else {
- player.dropMessage(6, "GM Fly feature disabled. GM's can now attack.");
+ sendStr += "Disabled Fly feature. You can now attack.";
if(srv.canFly(accid)) sendStr += " Re-login to take effect.";
srv.changeFly(c.getAccID(), false);
diff --git a/src/constants/ServerConstants.java b/src/constants/ServerConstants.java
index 4f000c96d7..566fd6496c 100644
--- a/src/constants/ServerConstants.java
+++ b/src/constants/ServerConstants.java
@@ -53,6 +53,7 @@ public class ServerConstants {
public static final boolean USE_ERASE_UNTRADEABLE_DROP = true; //Forces flagged untradeable items to disappear when dropped.
public static final boolean USE_ERASE_PET_ON_EXPIRATION = false;//Forces pets to be removed from inventory when expire time comes, rather than converting it to a doll.
public static final boolean USE_BUFF_MOST_SIGNIFICANT = true; //When applying buffs, the player will stick with the highest stat boost among the listed, rather than overwriting stats.
+ public static final boolean USE_UNDERLEVELED_EXP_GAIN = false; //Players below the threshold level will gain no experience from defeating higher leveled mobs.
//Server Rates And Experience
public static final int EXP_RATE = 10;
@@ -77,10 +78,12 @@ public class ServerConstants {
//Some Gameplay Enhancing Configurations
//Scroll Configuration
- public static final boolean USE_PERFECT_GM_SCROLL = true; //Scrolls from GMs never uses up slots nor fails.
- public static final boolean USE_PERFECT_SCROLLING = true; //Scrolls doesn't use slots upon failure.
- public static final boolean USE_ENHANCED_CHSCROLL = true; //Equips even more powerful with chaos upgrade.
+ public static final boolean USE_PERFECT_GM_SCROLL = false; //Scrolls from GMs never uses up slots nor fails.
+ public static final boolean USE_PERFECT_SCROLLING = false; //Scrolls doesn't use slots upon failure.
+ public static final boolean USE_ENHANCED_CHSCROLL = false; //Equips even more powerful with chaos upgrade.
public static final boolean USE_ENHANCED_CRAFTING = true; //Applys chaos scroll on every equip crafted.
+ public static final int SCROLL_CHANCE_RATE = 0; //Number of rolls for success on a scroll, set 0 for default.
+ public static final int CHSCROLL_STAT_RANGE = 6; //Stat upgrade range (-N, N) on chaos scrolls.
//Beginner Skills Configuration
public static final boolean USE_ULTRA_NIMBLE_FEET = true; //Haste-like speed & jump upgrade.
@@ -93,7 +96,6 @@ public class ServerConstants {
public static final boolean USE_STACK_COUPON_RATES = true; //Multiple coupons effects builds up together.
public static final boolean USE_PERFECT_PITCH = true; //For lvl 30 or above, each lvlup grants player 1 perfect pitch.
public static final int FAME_GAIN_BY_QUEST = 4; //Fame gain each N quest completes, set 0 to disable.
- public static final int SCROLL_CHANCE_RATE = 10; //Number of rolls for success on a scroll, set 0 for default.
//Equipment Configuration
public static final boolean USE_EQUIPMNT_LVLUP_SLOTS = true;//Equips can upgrade slots at level up.
diff --git a/src/net/mina/MaplePacketDecoder.java b/src/net/mina/MaplePacketDecoder.java
index 3f1390f681..847c2d84e0 100644
--- a/src/net/mina/MaplePacketDecoder.java
+++ b/src/net/mina/MaplePacketDecoder.java
@@ -38,14 +38,21 @@ public class MaplePacketDecoder extends CumulativeProtocolDecoder {
@Override
protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
final MapleClient client = (MapleClient) session.getAttribute(MapleClient.CLIENT_KEY);
+ if(client == null) {
+ session.close(true);
+ return false;
+ }
+
DecoderState decoderState = (DecoderState) session.getAttribute(DECODER_STATE_KEY);
if (decoderState == null) {
decoderState = new DecoderState();
session.setAttribute(DECODER_STATE_KEY, decoderState);
}
+
+ MapleAESOFB rcvdCrypto = client.getReceiveCrypto();
if (in.remaining() >= 4 && decoderState.packetlength == -1) {
int packetHeader = in.getInt();
- if (!client.getReceiveCrypto().checkPacket(packetHeader)) {
+ if (!rcvdCrypto.checkPacket(packetHeader)) {
session.close(true);
return false;
}
@@ -57,7 +64,7 @@ public class MaplePacketDecoder extends CumulativeProtocolDecoder {
byte decryptedPacket[] = new byte[decoderState.packetlength];
in.get(decryptedPacket, 0, decoderState.packetlength);
decoderState.packetlength = -1;
- client.getReceiveCrypto().crypt(decryptedPacket);
+ rcvdCrypto.crypt(decryptedPacket);
MapleCustomEncryption.decryptData(decryptedPacket);
out.write(decryptedPacket);
return true;
diff --git a/src/net/mina/MaplePacketEncoder.java b/src/net/mina/MaplePacketEncoder.java
index f9cb0a30be..c14106b10c 100644
--- a/src/net/mina/MaplePacketEncoder.java
+++ b/src/net/mina/MaplePacketEncoder.java
@@ -62,6 +62,5 @@ public class MaplePacketEncoder implements ProtocolEncoder {
}
@Override
- public void dispose(IoSession session) throws Exception {
- }
+ public void dispose(IoSession session) throws Exception {}
}
\ No newline at end of file
diff --git a/src/net/server/channel/handlers/EnterCashShopHandler.java b/src/net/server/channel/handlers/EnterCashShopHandler.java
index 5af0f742a3..fac2f949c0 100644
--- a/src/net/server/channel/handlers/EnterCashShopHandler.java
+++ b/src/net/server/channel/handlers/EnterCashShopHandler.java
@@ -52,6 +52,7 @@ public class EnterCashShopHandler extends AbstractMaplePacketHandler {
Server.getInstance().getPlayerBuffStorage().addBuffsToStorage(mc.getId(), mc.getAllBuffs());
mc.cancelAllBuffs(true);
mc.cancelBuffExpireTask();
+ mc.cancelDiseaseExpireTask();
mc.cancelSkillCooldownTask();
mc.cancelExpirationTask();
diff --git a/src/net/server/channel/handlers/EnterMTSHandler.java b/src/net/server/channel/handlers/EnterMTSHandler.java
index ef2767e56e..ba448f6093 100644
--- a/src/net/server/channel/handlers/EnterMTSHandler.java
+++ b/src/net/server/channel/handlers/EnterMTSHandler.java
@@ -61,6 +61,7 @@ public final class EnterMTSHandler extends AbstractMaplePacketHandler {
Server.getInstance().getPlayerBuffStorage().addBuffsToStorage(chr.getId(), chr.getAllBuffs());
chr.cancelAllBuffs(true);
chr.cancelBuffExpireTask();
+ chr.cancelDiseaseExpireTask();
chr.cancelSkillCooldownTask();
chr.cancelExpirationTask();
chr.saveToDB();
diff --git a/src/net/server/channel/handlers/PartyOperationHandler.java b/src/net/server/channel/handlers/PartyOperationHandler.java
index 76c9a8d3b0..2b4f72af56 100644
--- a/src/net/server/channel/handlers/PartyOperationHandler.java
+++ b/src/net/server/channel/handlers/PartyOperationHandler.java
@@ -30,6 +30,8 @@ import tools.MaplePacketCreator;
import tools.data.input.SeekableLittleEndianAccessor;
import client.MapleCharacter;
import client.MapleClient;
+import scripting.event.EventInstanceManager;
+import server.maps.MapleMap;
public final class PartyOperationHandler extends AbstractMaplePacketHandler {
@@ -50,6 +52,7 @@ public final class PartyOperationHandler extends AbstractMaplePacketHandler {
party = world.createParty(partyplayer);
player.setParty(party);
player.setMPC(partyplayer);
+ player.getMap().addPartyMember(player);
player.silentPartyUpdate();
c.announce(MaplePacketCreator.partyCreated(partyplayer));
} else {
@@ -59,17 +62,22 @@ public final class PartyOperationHandler extends AbstractMaplePacketHandler {
}
case 2: {
if (party != null && partyplayer != null) {
- if (partyplayer.equals(party.getLeader())) {
- world.updateParty(party.getId(), PartyOperation.DISBAND, partyplayer);
- if (player.getEventInstance() != null) {
- player.getEventInstance().disbandParty();
- }
- } else {
- world.updateParty(party.getId(), PartyOperation.LEAVE, partyplayer);
- if (player.getEventInstance() != null) {
- player.getEventInstance().leftParty(player);
- }
+ if (partyplayer.getId() == party.getLeaderId()) {
+ c.getWorldServer().removeMapPartyMembers(party.getId());
+
+ world.updateParty(party.getId(), PartyOperation.DISBAND, partyplayer);
+ if (player.getEventInstance() != null) {
+ player.getEventInstance().disbandParty();
}
+ } else {
+ player.getMap().removePartyMember(player);
+
+ world.updateParty(party.getId(), PartyOperation.LEAVE, partyplayer);
+ if (player.getEventInstance() != null) {
+ player.getEventInstance().leftParty(player);
+ }
+ }
+
player.setParty(null);
}
break;
@@ -81,6 +89,8 @@ public final class PartyOperationHandler extends AbstractMaplePacketHandler {
if (party != null) {
if (party.getMembers().size() < 6) {
partyplayer = new MaplePartyCharacter(player);
+ player.getMap().addPartyMember(player);
+
world.updateParty(party.getId(), PartyOperation.JOIN, partyplayer);
player.receivePartyMemberHP();
player.updatePartyMemberHP();
@@ -109,6 +119,7 @@ public final class PartyOperationHandler extends AbstractMaplePacketHandler {
party = world.createParty(partyplayer);
player.setParty(party);
player.setMPC(partyplayer);
+ player.getMap().addPartyMember(player);
c.announce(MaplePacketCreator.partyCreated(partyplayer));
}
if (party.getMembers().size() < 6) {
@@ -129,12 +140,20 @@ public final class PartyOperationHandler extends AbstractMaplePacketHandler {
if (partyplayer.equals(party.getLeader())) {
MaplePartyCharacter expelled = party.getMemberById(cid);
if (expelled != null) {
- world.updateParty(party.getId(), PartyOperation.EXPEL, expelled);
- if (player.getEventInstance() != null) {
- if (expelled.isOnline()) {
- player.getEventInstance().disbandParty();
+ MapleCharacter emc = expelled.getPlayer();
+ if(emc != null) {
+ MapleMap map = emc.getMap();
+ if(map != null) map.removePartyMember(emc);
+
+ EventInstanceManager eim = emc.getEventInstance();
+ if(eim != null) {
+ eim.leftParty(emc);
}
+
+ emc.setParty(null);
}
+
+ world.updateParty(party.getId(), PartyOperation.EXPEL, expelled);
}
}
break;
diff --git a/src/net/server/channel/handlers/PlayerLoggedinHandler.java b/src/net/server/channel/handlers/PlayerLoggedinHandler.java
index 6573b99da1..40aac49275 100644
--- a/src/net/server/channel/handlers/PlayerLoggedinHandler.java
+++ b/src/net/server/channel/handlers/PlayerLoggedinHandler.java
@@ -263,6 +263,7 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
player.changeSkillLevel(SkillFactory.getSkill(10000000 * player.getJobType() + 12), (byte) (player.getLinkedLevel() / 10), 20, -1);
player.checkBerserk(player.isHidden());
player.buffExpireTask();
+ player.diseaseExpireTask();
player.skillCooldownTask();
player.expirationTask();
if (GameConstants.hasSPTable(player.getJob()) && player.getJob().getId() != 2001) {
diff --git a/src/net/server/world/MapleParty.java b/src/net/server/world/MapleParty.java
index 83a8707672..8eca3685ea 100644
--- a/src/net/server/world/MapleParty.java
+++ b/src/net/server/world/MapleParty.java
@@ -29,17 +29,21 @@ import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Map;
import java.util.Comparator;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.locks.Lock;
public class MapleParty {
+ private int id;
+
private int leaderId;
- private List members = new LinkedList();
+ private List members = new LinkedList<>();
private List pqMembers = null;
private Map histMembers = new HashMap<>();
private int nextEntry = 0;
- private int id;
-
+ private Lock lock = new ReentrantLock();
+
public MapleParty(int id, MaplePartyCharacter chrfor) {
this.leaderId = chrfor.getId();
this.members.add(chrfor);
@@ -47,20 +51,35 @@ public class MapleParty {
}
public boolean containsMembers(MaplePartyCharacter member) {
- return members.contains(member);
+ lock.lock();
+ try {
+ return members.contains(member);
+ } finally {
+ lock.unlock();
+ }
}
public void addMember(MaplePartyCharacter member) {
- histMembers.put(member.getId(), nextEntry);
- nextEntry++;
-
- members.add(member);
+ lock.lock();
+ try {
+ histMembers.put(member.getId(), nextEntry);
+ nextEntry++;
+
+ members.add(member);
+ } finally {
+ lock.unlock();
+ }
}
public void removeMember(MaplePartyCharacter member) {
- histMembers.remove(member.getId());
-
- members.remove(member);
+ lock.lock();
+ try {
+ histMembers.remove(member.getId());
+
+ members.remove(member);
+ } finally {
+ lock.unlock();
+ }
}
public void setLeader(MaplePartyCharacter victim) {
@@ -68,28 +87,48 @@ public class MapleParty {
}
public void updateMember(MaplePartyCharacter member) {
- for (int i = 0; i < members.size(); i++) {
- if (members.get(i).getId() == member.getId()) {
- members.set(i, member);
+ lock.lock();
+ try {
+ for (int i = 0; i < members.size(); i++) {
+ if (members.get(i).getId() == member.getId()) {
+ members.set(i, member);
+ }
}
+ } finally {
+ lock.unlock();
}
}
public MaplePartyCharacter getMemberById(int id) {
- for (MaplePartyCharacter chr : members) {
- if (chr.getId() == id) {
- return chr;
+ lock.lock();
+ try {
+ for (MaplePartyCharacter chr : members) {
+ if (chr.getId() == id) {
+ return chr;
+ }
}
+ return null;
+ } finally {
+ lock.unlock();
}
- return null;
}
public Collection getMembers() {
- return Collections.unmodifiableList(members);
+ lock.lock();
+ try {
+ return Collections.unmodifiableList(members);
+ } finally {
+ lock.unlock();
+ }
}
public List getPartyMembers() {
- return members;
+ lock.lock();
+ try {
+ return Collections.unmodifiableList(members);
+ } finally {
+ lock.unlock();
+ }
}
// used whenever entering PQs: will draw every party member that can attempt a target PQ while ingnoring those unfit.
@@ -114,17 +153,30 @@ public class MapleParty {
}
public MaplePartyCharacter getLeader() {
- for(MaplePartyCharacter mpc: members) {
- if(mpc.getId() == leaderId) {
- return mpc;
+ lock.lock();
+ try {
+ for(MaplePartyCharacter mpc: members) {
+ if(mpc.getId() == leaderId) {
+ return mpc;
+ }
}
+
+ return null;
+ } finally {
+ lock.unlock();
}
-
- return null;
}
public byte getPartyDoor(int cid) {
- List> histList = new LinkedList<>(histMembers.entrySet());
+ List> histList;
+
+ lock.lock();
+ try {
+ histList = new LinkedList<>(histMembers.entrySet());
+ } finally {
+ lock.unlock();
+ }
+
Collections.sort(histList, new Comparator>()
{
@Override
@@ -133,13 +185,13 @@ public class MapleParty {
return ( o1.getValue() ).compareTo( o2.getValue() );
}
});
-
+
byte slot = 0;
for(Entry e: histList) {
if(e.getKey() == cid) break;
slot++;
}
-
+
return slot;
}
diff --git a/src/net/server/world/World.java b/src/net/server/world/World.java
index 43eb976665..1dc1e45389 100644
--- a/src/net/server/world/World.java
+++ b/src/net/server/world/World.java
@@ -45,8 +45,10 @@ import java.util.Set;
import java.util.HashSet;
import java.util.concurrent.ScheduledFuture;
+import scripting.event.EventInstanceManager;
import server.TimerManager;
import server.maps.MapleHiredMerchant;
+import server.maps.MapleMap;
import server.MaplePlayerShop;
import net.server.worker.CharacterAutosaverWorker;
import net.server.worker.MountTirednessWorker;
@@ -357,16 +359,22 @@ public class World {
public MapleParty createParty(MaplePartyCharacter chrfor) {
int partyid = runningPartyId.getAndIncrement();
MapleParty party = new MapleParty(partyid, chrfor);
- parties.put(party.getId(), party);
+ synchronized(parties) {
+ parties.put(party.getId(), party);
+ }
return party;
}
public MapleParty getParty(int partyid) {
- return parties.get(partyid);
+ synchronized(parties) {
+ return parties.get(partyid);
+ }
}
public MapleParty disbandParty(int partyid) {
- return parties.remove(partyid);
+ synchronized(parties) {
+ return parties.remove(partyid);
+ }
}
public void updateParty(MapleParty party, PartyOperation operation, MaplePartyCharacter target) {
@@ -419,8 +427,10 @@ public class World {
break;
case CHANGE_LEADER:
MapleCharacter mc = party.getLeader().getPlayer();
- if(mc.getEventInstance() != null && mc.getEventInstance().isEventLeader(mc)) {
- mc.getEventInstance().changedLeader(target.getPlayer());
+ EventInstanceManager eim = mc.getEventInstance();
+
+ if(eim != null && eim.isEventLeader(mc)) {
+ eim.changedLeader(target.getPlayer());
}
party.setLeader(target);
break;
@@ -430,6 +440,21 @@ public class World {
updateParty(party, operation, target);
}
+ public void removeMapPartyMembers(int partyid) {
+ MapleParty party = getParty(partyid);
+ if(party == null) return;
+
+ for(MaplePartyCharacter mpc : party.getMembers()) {
+ MapleCharacter mc = mpc.getPlayer();
+ if(mc != null) {
+ MapleMap map = mc.getMap();
+ if(map != null) {
+ map.removeParty(partyid);
+ }
+ }
+ }
+ }
+
public int find(String name) {
int channel = -1;
MapleCharacter chr = getPlayerStorage().getCharacterByName(name);
diff --git a/src/scripting/AbstractPlayerInteraction.java b/src/scripting/AbstractPlayerInteraction.java
index 833994943b..4d09583236 100644
--- a/src/scripting/AbstractPlayerInteraction.java
+++ b/src/scripting/AbstractPlayerInteraction.java
@@ -449,10 +449,14 @@ public class AbstractPlayerInteraction {
if(item != null) {
Equip it = (Equip)item;
if(isAccessory(item.getItemId()) && it.getUpgradeSlots() <= 0) it.setUpgradeSlots(3);
- }
- if(ServerConstants.USE_ENHANCED_CRAFTING == true && c.getPlayer().getCS() == true)
- item = MapleItemInformationProvider.getInstance().scrollEquipWithId(item, 2049100, true, 0, c.getPlayer().isGM());
+ if(ServerConstants.USE_ENHANCED_CRAFTING == true && c.getPlayer().getCS() == true) {
+ Equip eqp = (Equip)item;
+ eqp.setUpgradeSlots((byte)(eqp.getUpgradeSlots() + 1));
+
+ item = MapleItemInformationProvider.getInstance().scrollEquipWithId(item, 2049100, true, 0, c.getPlayer().isGM());
+ }
+ }
} else {
item = new Item(id, (short) 0, quantity, petId);
}
diff --git a/src/server/MapleItemInformationProvider.java b/src/server/MapleItemInformationProvider.java
index 7b91c3cb43..05e6b7a0c3 100644
--- a/src/server/MapleItemInformationProvider.java
+++ b/src/server/MapleItemInformationProvider.java
@@ -568,6 +568,223 @@ public class MapleItemInformationProvider {
return (short)Math.min(Short.MAX_VALUE, value);
}
+ private static short chscrollRandomizedStat() {
+ return (short) Randomizer.rand(-ServerConstants.CHSCROLL_STAT_RANGE, ServerConstants.CHSCROLL_STAT_RANGE);
+ }
+
+ private void scrollEquipWithChaos(Equip nEquip) {
+ if(ServerConstants.SCROLL_CHANCE_RATE > 0) {
+ int temp;
+ short curStr, curDex, curInt, curLuk, curWatk, curWdef, curMatk, curMdef, curAcc, curAvoid, curSpeed, curJump, curHp, curMp;
+
+ if(ServerConstants.USE_ENHANCED_CHSCROLL) {
+ curStr = nEquip.getStr();
+ curDex = nEquip.getDex();
+ curInt = nEquip.getInt();
+ curLuk = nEquip.getLuk();
+ curWatk = nEquip.getWatk();
+ curWdef = nEquip.getWdef();
+ curMatk = nEquip.getMatk();
+ curMdef = nEquip.getMdef();
+ curAcc = nEquip.getAcc();
+ curAvoid = nEquip.getAvoid();
+ curSpeed = nEquip.getSpeed();
+ curJump = nEquip.getJump();
+ curHp = nEquip.getHp();
+ curMp = nEquip.getMp();
+ } else {
+ curStr = Short.MIN_VALUE;
+ curDex = Short.MIN_VALUE;
+ curInt = Short.MIN_VALUE;
+ curLuk = Short.MIN_VALUE;
+ curWatk = Short.MIN_VALUE;
+ curWdef = Short.MIN_VALUE;
+ curMatk = Short.MIN_VALUE;
+ curMdef = Short.MIN_VALUE;
+ curAcc = Short.MIN_VALUE;
+ curAvoid = Short.MIN_VALUE;
+ curSpeed = Short.MIN_VALUE;
+ curJump = Short.MIN_VALUE;
+ curHp = Short.MIN_VALUE;
+ curMp = Short.MIN_VALUE;
+ }
+
+ for(int i = 0; i < ServerConstants.SCROLL_CHANCE_RATE; i++) {
+ if (nEquip.getStr() > 0) {
+ if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curStr + chscrollRandomizedStat();
+ else temp = nEquip.getStr() + chscrollRandomizedStat();
+
+ curStr = getMaximumShortMaxIfOverflow(temp, curStr);
+ }
+
+ if (nEquip.getDex() > 0) {
+ if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curDex + chscrollRandomizedStat();
+ else temp = nEquip.getDex() + chscrollRandomizedStat();
+
+ curDex = getMaximumShortMaxIfOverflow(temp, curDex);
+ }
+
+ if (nEquip.getInt() > 0) {
+ if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curInt + chscrollRandomizedStat();
+ else temp = nEquip.getInt() + chscrollRandomizedStat();
+
+ curInt = getMaximumShortMaxIfOverflow(temp, curInt);
+ }
+
+ if (nEquip.getLuk() > 0) {
+ if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curLuk + chscrollRandomizedStat();
+ else temp = nEquip.getLuk() + chscrollRandomizedStat();
+
+ curLuk = getMaximumShortMaxIfOverflow(temp, curLuk);
+ }
+
+ if (nEquip.getWatk() > 0) {
+ if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curWatk + chscrollRandomizedStat();
+ else temp = nEquip.getWatk() + chscrollRandomizedStat();
+
+ curWatk = getMaximumShortMaxIfOverflow(temp, curWatk);
+ }
+
+ if (nEquip.getWdef() > 0) {
+ if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curWdef + chscrollRandomizedStat();
+ else temp = nEquip.getWdef() + chscrollRandomizedStat();
+
+ curWdef = getMaximumShortMaxIfOverflow(temp, curWdef);
+ }
+
+ if (nEquip.getMatk() > 0) {
+ if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curMatk + chscrollRandomizedStat();
+ else temp = nEquip.getMatk() + chscrollRandomizedStat();
+
+ curMatk = getMaximumShortMaxIfOverflow(temp, curMatk);
+ }
+
+ if (nEquip.getMdef() > 0) {
+ if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curMdef + chscrollRandomizedStat();
+ else temp = nEquip.getMdef() + chscrollRandomizedStat();
+
+ curMdef = getMaximumShortMaxIfOverflow(temp, curMdef);
+ }
+
+ if (nEquip.getAcc() > 0) {
+ if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curAcc + chscrollRandomizedStat();
+ else temp = nEquip.getAcc() + chscrollRandomizedStat();
+
+ curAcc = getMaximumShortMaxIfOverflow(temp, curAcc);
+ }
+
+ if (nEquip.getAvoid() > 0) {
+ if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curAvoid + chscrollRandomizedStat();
+ else temp = nEquip.getAvoid() + chscrollRandomizedStat();
+
+ curAvoid = getMaximumShortMaxIfOverflow(temp, curAvoid);
+ }
+
+ if (nEquip.getSpeed() > 0) {
+ if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curSpeed + chscrollRandomizedStat();
+ else temp = nEquip.getSpeed() + chscrollRandomizedStat();
+
+ curSpeed = getMaximumShortMaxIfOverflow(temp, curSpeed);
+ }
+
+ if (nEquip.getJump() > 0) {
+ if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curJump + chscrollRandomizedStat();
+ else temp = nEquip.getJump() + chscrollRandomizedStat();
+
+ curJump = getMaximumShortMaxIfOverflow(temp, curJump);
+ }
+
+ if (nEquip.getHp() > 0) {
+ if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curHp + chscrollRandomizedStat();
+ else temp = nEquip.getHp() + chscrollRandomizedStat();
+
+ curHp = getMaximumShortMaxIfOverflow(temp, curHp);
+ }
+
+ if (nEquip.getMp() > 0) {
+ if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curMp + chscrollRandomizedStat();
+ else temp = nEquip.getMp() + chscrollRandomizedStat();
+
+ curMp = getMaximumShortMaxIfOverflow(temp, curMp);
+ }
+ }
+
+ nEquip.setStr((short) Math.max(0, curStr));
+ nEquip.setDex((short) Math.max(0, curDex));
+ nEquip.setInt((short) Math.max(0, curInt));
+ nEquip.setLuk((short) Math.max(0, curLuk));
+ nEquip.setWatk((short) Math.max(0, curWatk));
+ nEquip.setWdef((short) Math.max(0, curWdef));
+ nEquip.setMatk((short) Math.max(0, curMatk));
+ nEquip.setMdef((short) Math.max(0, curMdef));
+ nEquip.setAcc((short) Math.max(0, curAcc));
+ nEquip.setAvoid((short) Math.max(0, curAvoid));
+ nEquip.setSpeed((short) Math.max(0, curSpeed));
+ nEquip.setJump((short) Math.max(0, curJump));
+ nEquip.setHp((short) Math.max(0, curHp));
+ nEquip.setMp((short) Math.max(0, curMp));
+ }
+
+ else {
+ if (nEquip.getStr() > 0) {
+ if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setStr(getMaximumShortMaxIfOverflow(nEquip.getStr(), (nEquip.getStr() + chscrollRandomizedStat())));
+ else nEquip.setStr(getMaximumShortMaxIfOverflow(0, (nEquip.getStr() + chscrollRandomizedStat())));
+ }
+ if (nEquip.getDex() > 0) {
+ if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setDex(getMaximumShortMaxIfOverflow(nEquip.getDex(), (nEquip.getDex() + chscrollRandomizedStat())));
+ else nEquip.setDex(getMaximumShortMaxIfOverflow(0, (nEquip.getDex() + chscrollRandomizedStat())));
+ }
+ if (nEquip.getInt() > 0) {
+ if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setInt(getMaximumShortMaxIfOverflow(nEquip.getInt(), (nEquip.getInt() + chscrollRandomizedStat())));
+ else nEquip.setInt(getMaximumShortMaxIfOverflow(0, (nEquip.getInt() + chscrollRandomizedStat())));
+ }
+ if (nEquip.getLuk() > 0) {
+ if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setLuk(getMaximumShortMaxIfOverflow(nEquip.getLuk(), (nEquip.getLuk() + chscrollRandomizedStat())));
+ else nEquip.setLuk(getMaximumShortMaxIfOverflow(0, (nEquip.getLuk() + chscrollRandomizedStat())));
+ }
+ if (nEquip.getWatk() > 0) {
+ if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setWatk(getMaximumShortMaxIfOverflow(nEquip.getWatk(), (nEquip.getWatk() + chscrollRandomizedStat())));
+ else nEquip.setWatk(getMaximumShortMaxIfOverflow(0, (nEquip.getWatk() + chscrollRandomizedStat())));
+ }
+ if (nEquip.getWdef() > 0) {
+ if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setWdef(getMaximumShortMaxIfOverflow(nEquip.getWdef(), (nEquip.getWdef() + chscrollRandomizedStat())));
+ else nEquip.setWdef(getMaximumShortMaxIfOverflow(0, (nEquip.getWdef() + chscrollRandomizedStat())));
+ }
+ if (nEquip.getMatk() > 0) {
+ if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setMatk(getMaximumShortMaxIfOverflow(nEquip.getMatk(), (nEquip.getMatk() + chscrollRandomizedStat())));
+ else nEquip.setMatk(getMaximumShortMaxIfOverflow(0, (nEquip.getMatk() + chscrollRandomizedStat())));
+ }
+ if (nEquip.getMdef() > 0) {
+ if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setMdef(getMaximumShortMaxIfOverflow(nEquip.getMdef(), (nEquip.getMdef() + chscrollRandomizedStat())));
+ else nEquip.setMdef(getMaximumShortMaxIfOverflow(0, (nEquip.getMdef() + chscrollRandomizedStat())));
+ }
+ if (nEquip.getAcc() > 0) {
+ if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setAcc(getMaximumShortMaxIfOverflow(nEquip.getAcc(), (nEquip.getAcc() + chscrollRandomizedStat())));
+ else nEquip.setAcc(getMaximumShortMaxIfOverflow(0, (nEquip.getAcc() + chscrollRandomizedStat())));
+ }
+ if (nEquip.getAvoid() > 0) {
+ if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setAvoid(getMaximumShortMaxIfOverflow(nEquip.getAvoid(), (nEquip.getAvoid() + chscrollRandomizedStat())));
+ else nEquip.setAvoid(getMaximumShortMaxIfOverflow(0, (nEquip.getAvoid() + chscrollRandomizedStat())));
+ }
+ if (nEquip.getSpeed() > 0) {
+ if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setSpeed(getMaximumShortMaxIfOverflow(nEquip.getSpeed(), (nEquip.getSpeed() + chscrollRandomizedStat())));
+ else nEquip.setSpeed(getMaximumShortMaxIfOverflow(0, (nEquip.getSpeed() + chscrollRandomizedStat())));
+ }
+ if (nEquip.getJump() > 0) {
+ if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setJump(getMaximumShortMaxIfOverflow(nEquip.getJump(), (nEquip.getJump() + chscrollRandomizedStat())));
+ else nEquip.setJump(getMaximumShortMaxIfOverflow(0, (nEquip.getJump() + chscrollRandomizedStat())));
+ }
+ if (nEquip.getHp() > 0) {
+ if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setHp(getMaximumShortMaxIfOverflow(nEquip.getHp(), (nEquip.getHp() + chscrollRandomizedStat())));
+ else nEquip.setHp(getMaximumShortMaxIfOverflow(0, (nEquip.getHp() + chscrollRandomizedStat())));
+ }
+ if (nEquip.getMp() > 0) {
+ if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setMp(getMaximumShortMaxIfOverflow(nEquip.getMp(), (nEquip.getMp() + chscrollRandomizedStat())));
+ else nEquip.setMp(getMaximumShortMaxIfOverflow(0, (nEquip.getMp() + chscrollRandomizedStat())));
+ }
+ }
+ }
+
public Item scrollEquipWithId(Item equip, int scrollId, boolean usingWhiteScroll, int vegaItemId, boolean isGM) {
boolean assertGM = (isGM && ServerConstants.USE_PERFECT_GM_SCROLL);
@@ -607,256 +824,7 @@ public class MapleItemInformationProvider {
case 2049100:
case 2049101:
case 2049102:
- int inc, i;
-
- if(ServerConstants.SCROLL_CHANCE_RATE > 0) {
- //int tempStr, tempDex, tempInt, tempLuk, tempWatk, tempWdef, tempMatk, tempMdef, tempAcc, tempAvoid, tempSpeed, tempJump, tempHp, tempMp;
- int temp;
- int mdStr = nEquip.getStr(), mdDex = nEquip.getDex(), mdInt = nEquip.getInt(), mdLuk = nEquip.getLuk(), mdWatk = nEquip.getWatk(), mdWdef = nEquip.getWdef(), mdMatk = nEquip.getMatk(), mdMdef = nEquip.getMdef(), mdAcc = nEquip.getAcc(), mdAvoid = nEquip.getAvoid(), mdSpeed = nEquip.getSpeed(), mdJump = nEquip.getJump(), mdHp = nEquip.getHp(), mdMp = nEquip.getMp();
-
- inc = 1;
- if (Randomizer.nextInt(2) == 0) {
- inc = -1;
- }
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) inc = 1;
-
- for(i = 0; i < ServerConstants.SCROLL_CHANCE_RATE; i++) {
- if (nEquip.getStr() > 0) {
- temp = (nEquip.getStr() + Randomizer.nextInt(6) * inc);
- nEquip.setStr(getMaximumShortMaxIfOverflow(mdStr, temp));
-
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) {
- mdStr = nEquip.getStr();
- }
- else {
- temp = (mdStr + temp) / 2;
- if(temp > mdStr) mdStr = temp;
- }
- }
- if (nEquip.getDex() > 0) {
- temp = (nEquip.getDex() + Randomizer.nextInt(6) * inc);
- nEquip.setDex(getMaximumShortMaxIfOverflow(mdDex, temp));
-
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) {
- mdDex = nEquip.getDex();
- }
- else {
- temp = (mdDex + temp) / 2;
- if(temp > mdDex) mdDex = temp;
- }
- }
- if (nEquip.getInt() > 0) {
- temp = (nEquip.getInt() + Randomizer.nextInt(6) * inc);
- nEquip.setInt(getMaximumShortMaxIfOverflow(mdInt, temp));
-
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) {
- mdInt = nEquip.getInt();
- }
- else {
- temp = (mdInt + temp) / 2;
- if(temp > mdInt) mdInt = temp;
- }
- }
- if (nEquip.getLuk() > 0) {
- temp = (nEquip.getLuk() + Randomizer.nextInt(6) * inc);
- nEquip.setLuk(getMaximumShortMaxIfOverflow(mdLuk, temp));
-
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) {
- mdLuk = nEquip.getLuk();
- }
- else {
- temp = (mdLuk + temp) / 2;
- if(temp > mdLuk) mdLuk = temp;
- }
- }
- if (nEquip.getWatk() > 0) {
- temp = (nEquip.getWatk() + Randomizer.nextInt(6) * inc);
- nEquip.setWatk(getMaximumShortMaxIfOverflow(mdWatk, temp));
-
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) {
- mdWatk = nEquip.getWatk();
- }
- else {
- temp = (mdWatk + temp) / 2;
- if(temp > mdWatk) mdWatk = temp;
- }
- }
- if (nEquip.getWdef() > 0) {
- temp = (nEquip.getWdef() + Randomizer.nextInt(6) * inc);
- nEquip.setWdef(getMaximumShortMaxIfOverflow(mdWdef, temp));
-
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) {
- mdWdef = nEquip.getWdef();
- }
- else {
- temp = (mdWdef + temp) / 2;
- if(temp > mdWdef) mdWdef = temp;
- }
- }
- if (nEquip.getMatk() > 0) {
- temp = (nEquip.getMatk() + Randomizer.nextInt(6) * inc);
- nEquip.setMatk(getMaximumShortMaxIfOverflow(mdMatk, temp));
-
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) {
- mdMatk = nEquip.getMatk();
- }
- else {
- temp = (mdMatk + temp) / 2;
- if(temp > mdMatk) mdMatk = temp;
- }
- }
- if (nEquip.getMdef() > 0) {
- temp = (nEquip.getMdef() + Randomizer.nextInt(6) * inc);
- nEquip.setMdef(getMaximumShortMaxIfOverflow(mdMdef, temp));
-
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) {
- mdMdef = nEquip.getMdef();
- }
- else {
- temp = (mdMdef + temp) / 2;
- if(temp > mdMdef) mdMdef = temp;
- }
- }
- if (nEquip.getAcc() > 0) {
- temp = (nEquip.getAcc() + Randomizer.nextInt(6) * inc);
- nEquip.setAcc(getMaximumShortMaxIfOverflow(mdAcc, temp));
-
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) {
- mdAcc = nEquip.getAcc();
- }
- else {
- temp = (mdAcc + temp) / 2;
- if(temp > mdAcc) mdAcc = temp;
- }
- }
- if (nEquip.getAvoid() > 0) {
- temp = (nEquip.getAvoid() + Randomizer.nextInt(6) * inc);
- nEquip.setAvoid(getMaximumShortMaxIfOverflow(mdAvoid, temp));
-
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) {
- mdAvoid = nEquip.getAvoid();
- }
- else {
- temp = (mdAvoid + temp) / 2;
- if(temp > mdAvoid) mdAvoid = temp;
- }
- }
- if (nEquip.getSpeed() > 0) {
- temp = (nEquip.getSpeed() + Randomizer.nextInt(6) * inc);
- nEquip.setSpeed(getMaximumShortMaxIfOverflow(mdSpeed, temp));
-
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) {
- mdSpeed = nEquip.getSpeed();
- }
- else {
- temp = (mdSpeed + temp) / 2;
- if(temp > mdSpeed) mdSpeed = temp;
- }
- }
- if (nEquip.getJump() > 0) {
- temp = (nEquip.getJump() + Randomizer.nextInt(6) * inc);
- nEquip.setJump(getMaximumShortMaxIfOverflow(mdJump, temp));
-
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) {
- mdJump = nEquip.getJump();
- }
- else {
- temp = (mdJump + temp) / 2;
- if(temp > mdJump) mdJump = temp;
- }
- }
- if (nEquip.getHp() > 0) {
- temp = (nEquip.getHp() + Randomizer.nextInt(6) * inc);
- nEquip.setHp(getMaximumShortMaxIfOverflow(mdHp, temp));
-
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) {
- mdHp = nEquip.getHp();
- }
- else {
- temp = (mdHp + temp) / 2;
- if(temp > mdHp) mdHp = temp;
- }
- }
- if (nEquip.getMp() > 0) {
- temp = (nEquip.getMp() + Randomizer.nextInt(6) * inc);
- nEquip.setMp(getMaximumShortMaxIfOverflow(mdMp, temp));
-
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) {
- mdMp = nEquip.getMp();
- }
- else {
- temp = (mdMp + temp) / 2;
- if(temp > mdMp) mdMp = temp;
- }
- }
- }
- }
-
- else {
- inc = 1;
-
- if (Randomizer.nextInt(2) == 0) {
- inc = -1;
- }
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) inc = 1;
-
- if (nEquip.getStr() > 0) {
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) nEquip.setStr(getMaximumShortMaxIfOverflow(nEquip.getStr(), (nEquip.getStr() + Randomizer.nextInt(6) * inc)));
- else nEquip.setStr(getMaximumShortMaxIfOverflow(0, (nEquip.getStr() + Randomizer.nextInt(6) * inc)));
- }
- if (nEquip.getDex() > 0) {
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) nEquip.setDex(getMaximumShortMaxIfOverflow(nEquip.getDex(), (nEquip.getDex() + Randomizer.nextInt(6) * inc)));
- else nEquip.setDex(getMaximumShortMaxIfOverflow(0, (nEquip.getDex() + Randomizer.nextInt(6) * inc)));
- }
- if (nEquip.getInt() > 0) {
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) nEquip.setInt(getMaximumShortMaxIfOverflow(nEquip.getInt(), (nEquip.getInt() + Randomizer.nextInt(6) * inc)));
- else nEquip.setInt(getMaximumShortMaxIfOverflow(0, (nEquip.getInt() + Randomizer.nextInt(6) * inc)));
- }
- if (nEquip.getLuk() > 0) {
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) nEquip.setLuk(getMaximumShortMaxIfOverflow(nEquip.getLuk(), (nEquip.getLuk() + Randomizer.nextInt(6) * inc)));
- else nEquip.setLuk(getMaximumShortMaxIfOverflow(0, (nEquip.getLuk() + Randomizer.nextInt(6) * inc)));
- }
- if (nEquip.getWatk() > 0) {
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) nEquip.setWatk(getMaximumShortMaxIfOverflow(nEquip.getWatk(), (nEquip.getWatk() + Randomizer.nextInt(6) * inc)));
- else nEquip.setWatk(getMaximumShortMaxIfOverflow(0, (nEquip.getWatk() + Randomizer.nextInt(6) * inc)));
- }
- if (nEquip.getWdef() > 0) {
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) nEquip.setWdef(getMaximumShortMaxIfOverflow(nEquip.getWdef(), (nEquip.getWdef() + Randomizer.nextInt(6) * inc)));
- else nEquip.setWdef(getMaximumShortMaxIfOverflow(0, (nEquip.getWdef() + Randomizer.nextInt(6) * inc)));
- }
- if (nEquip.getMatk() > 0) {
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) nEquip.setMatk(getMaximumShortMaxIfOverflow(nEquip.getMatk(), (nEquip.getMatk() + Randomizer.nextInt(6) * inc)));
- else nEquip.setMatk(getMaximumShortMaxIfOverflow(0, (nEquip.getMatk() + Randomizer.nextInt(6) * inc)));
- }
- if (nEquip.getMdef() > 0) {
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) nEquip.setMdef(getMaximumShortMaxIfOverflow(nEquip.getMdef(), (nEquip.getMdef() + Randomizer.nextInt(6) * inc)));
- else nEquip.setMdef(getMaximumShortMaxIfOverflow(0, (nEquip.getMdef() + Randomizer.nextInt(6) * inc)));
- }
- if (nEquip.getAcc() > 0) {
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) nEquip.setAcc(getMaximumShortMaxIfOverflow(nEquip.getAcc(), (nEquip.getAcc() + Randomizer.nextInt(6) * inc)));
- else nEquip.setAcc(getMaximumShortMaxIfOverflow(0, (nEquip.getAcc() + Randomizer.nextInt(6) * inc)));
- }
- if (nEquip.getAvoid() > 0) {
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) nEquip.setAvoid(getMaximumShortMaxIfOverflow(nEquip.getAvoid(), (nEquip.getAvoid() + Randomizer.nextInt(6) * inc)));
- else nEquip.setAvoid(getMaximumShortMaxIfOverflow(0, (nEquip.getAvoid() + Randomizer.nextInt(6) * inc)));
- }
- if (nEquip.getSpeed() > 0) {
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) nEquip.setSpeed(getMaximumShortMaxIfOverflow(nEquip.getSpeed(), (nEquip.getSpeed() + Randomizer.nextInt(6) * inc)));
- else nEquip.setSpeed(getMaximumShortMaxIfOverflow(0, (nEquip.getSpeed() + Randomizer.nextInt(6) * inc)));
- }
- if (nEquip.getJump() > 0) {
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) nEquip.setJump(getMaximumShortMaxIfOverflow(nEquip.getJump(), (nEquip.getJump() + Randomizer.nextInt(6) * inc)));
- else nEquip.setJump(getMaximumShortMaxIfOverflow(0, (nEquip.getJump() + Randomizer.nextInt(6) * inc)));
- }
- if (nEquip.getHp() > 0) {
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) nEquip.setHp(getMaximumShortMaxIfOverflow(nEquip.getHp(), (nEquip.getHp() + Randomizer.nextInt(6) * inc)));
- else nEquip.setHp(getMaximumShortMaxIfOverflow(0, (nEquip.getHp() + Randomizer.nextInt(6) * inc)));
- }
- if (nEquip.getMp() > 0) {
- if(ServerConstants.USE_ENHANCED_CHSCROLL == true) nEquip.setMp(getMaximumShortMaxIfOverflow(nEquip.getMp(), (nEquip.getMp() + Randomizer.nextInt(6) * inc)));
- else nEquip.setMp(getMaximumShortMaxIfOverflow(0, (nEquip.getMp() + Randomizer.nextInt(6) * inc)));
- }
- }
+ scrollEquipWithChaos(nEquip);
break;
default:
@@ -911,13 +879,13 @@ public class MapleItemInformationProvider {
break;
}
if (!ItemConstants.isCleanSlate(scrollId)) {
- if (ServerConstants.USE_PERFECT_SCROLLING == true && !assertGM && !usingWhiteScroll) {
+ if (!assertGM && !usingWhiteScroll) {
nEquip.setUpgradeSlots((byte) (nEquip.getUpgradeSlots() - 1));
}
nEquip.setLevel((byte) (nEquip.getLevel() + 1));
}
- } else {
- if (ServerConstants.USE_PERFECT_SCROLLING == false && !usingWhiteScroll && !ItemConstants.isCleanSlate(scrollId) && !assertGM) {
+ } else {
+ if (!ServerConstants.USE_PERFECT_SCROLLING && !usingWhiteScroll && !ItemConstants.isCleanSlate(scrollId) && !assertGM) {
nEquip.setUpgradeSlots((byte) (nEquip.getUpgradeSlots() - 1));
}
if (Randomizer.nextInt(101) < stats.get("cursed")) {
diff --git a/src/server/life/MapleMonster.java b/src/server/life/MapleMonster.java
index 990c59fcd3..14429dcbf1 100644
--- a/src/server/life/MapleMonster.java
+++ b/src/server/life/MapleMonster.java
@@ -48,6 +48,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
import net.server.world.MapleParty;
@@ -257,26 +258,33 @@ public class MapleMonster extends AbstractLoadedMapleLife {
}
private void distributeExperienceToParty(int pid, int exp, int killer, Map expDist) {
- LinkedList members = new LinkedList<>();
- Collection chrs = map.getCharacters();
-
- for (MapleCharacter mc : chrs) {
- if (mc.getPartyId() == pid) {
- members.add(mc);
- }
+ List members = new LinkedList<>();
+ MapleCharacter pchar = getMap().getAnyCharacterFromParty(pid);
+ if(pchar != null) {
+ for(MapleCharacter chr : pchar.getPartyMembersOnSameMap()) {
+ members.add(chr);
+ }
+ } else {
+ MapleCharacter chr = getMap().getCharacterById(killer);
+ if(chr == null) return;
+
+ members.add(chr);
}
-
+
final int minLevel = getLevel() - 5;
-
int partyLevel = 0;
int leechMinLevel = 0;
- for (MapleCharacter mc : members) {
- if (mc.getLevel() >= minLevel) {
- leechMinLevel = Math.min(mc.getLevel() - 5, minLevel);
+ if(!ServerConstants.USE_UNDERLEVELED_EXP_GAIN) { //NO EXP WILL BE GIVEN for those who are underleveled!
+ leechMinLevel = minLevel;
+
+ for (MapleCharacter mc : members) {
+ if (mc.getLevel() >= minLevel) {
+ leechMinLevel = Math.min(mc.getLevel() - 5, leechMinLevel);
+ }
}
}
-
+
int leechCount = 0;
for (MapleCharacter mc : members) {
if (mc.getLevel() >= leechMinLevel) {
@@ -290,13 +298,12 @@ public class MapleMonster extends AbstractLoadedMapleLife {
for (MapleCharacter mc : members) {
int id = mc.getId();
int level = mc.getLevel();
- if (expDist.containsKey(id)
- || level >= leechMinLevel) {
+ if (expDist.containsKey(id) || level >= leechMinLevel) {
boolean isKiller = killer == id;
boolean mostDamage = mostDamageCid == id;
- int xp = (int) (exp * 0.80f * level / partyLevel);
+ int xp = (int) ((0.80f * exp * level) / partyLevel);
if (mostDamage) {
- xp += (exp * 0.20f);
+ xp += (0.20f * exp);
}
giveExpToCharacter(mc, xp, isKiller, leechCount);
}
@@ -311,26 +318,32 @@ public class MapleMonster extends AbstractLoadedMapleLife {
int totalHealth = getMaxHp();
Map expDist = new HashMap<>();
Map partyExp = new HashMap<>();
- // 80% of pool is split amongst all the damagers
+
+ float exp8 = (0.8f * exp); // 80% of pool is split amongst all the damagers
+ float exp2 = (0.2f * exp); // 20% of pool goes to the killer or his/her party
+
for (Entry damage : takenDamage.entrySet()) {
- expDist.put(damage.getKey(), (int) (0.80f * exp * damage.getValue().get() / totalHealth));
+ expDist.put(damage.getKey(), (int) (Math.min((exp8 * damage.getValue().get()) / totalHealth, Integer.MAX_VALUE)));
}
Collection chrs = map.getCharacters();
for (MapleCharacter mc : chrs) {
if (expDist.containsKey(mc.getId())) {
- boolean isKiller = mc.getId() == killerId;
+ boolean isKiller = (mc.getId() == killerId);
int xp = expDist.get(mc.getId());
if (isKiller) {
- xp += exp / 5;
+ xp = (int)Math.min(exp2 + xp, Integer.MAX_VALUE);
}
MapleParty p = mc.getParty();
if (p != null) {
int pID = p.getId();
- int pXP = xp + (partyExp.containsKey(pID) ? partyExp.get(pID) : 0);
- partyExp.put(pID, pXP);
+ long pXP = (long)xp + (partyExp.containsKey(pID) ? partyExp.get(pID) : 0);
+ partyExp.put(pID, (int)Math.min(pXP, Integer.MAX_VALUE));
} else {
- giveExpToCharacter(mc, xp, isKiller, 1);
+ if(ServerConstants.USE_UNDERLEVELED_EXP_GAIN || mc.getLevel() >= this.getLevel() - 5) {
+ //NO EXP WILL BE GIVEN for those who are underleveled!
+ giveExpToCharacter(mc, xp, isKiller, 1);
+ }
}
}
}
diff --git a/src/server/maps/MapleMap.java b/src/server/maps/MapleMap.java
index 2c269fe0e3..bc2c4704dd 100644
--- a/src/server/maps/MapleMap.java
+++ b/src/server/maps/MapleMap.java
@@ -43,6 +43,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
+import java.util.Set;
import java.util.LinkedList;
import java.util.List;
import java.util.Iterator;
@@ -93,6 +94,7 @@ public class MapleMap {
private AtomicInteger spawnedMonstersOnMap = new AtomicInteger(0);
private AtomicInteger droppedItemCount = new AtomicInteger(0);
private Collection characters = new LinkedHashSet<>();
+ private Map> mapParty = new LinkedHashMap<>();
private Map portals = new HashMap<>();
private Map backgroundTypes = new HashMap<>();
private Map environment = new LinkedHashMap<>();
@@ -133,6 +135,7 @@ public class MapleMap {
private short mobInterval = 5000;
private boolean allowSummons = true; // All maps should have this true at the beginning
private int lastDoorOwner = -1;
+
// HPQ
private int riceCakes = 0;
private int bunnyDamage = 0;
@@ -1781,10 +1784,84 @@ public class MapleMap {
}, time);
}
+ public MapleCharacter getAnyCharacterFromParty(int partyid) {
+ chrRLock.lock();
+ try {
+ Set list = mapParty.get(partyid);
+ if(list == null) return null;
+
+ for(Integer cid : list) {
+ for (MapleCharacter c : this.characters) {
+ if (c.getId() == cid) {
+ return c;
+ }
+ }
+ }
+
+ return null;
+ } finally {
+ chrRLock.unlock();
+ }
+ }
+
+ private void addPartyMemberInternal(MapleCharacter chr) {
+ int partyid = chr.getPartyId();
+ if(partyid == -1) return;
+
+ Set partyEntry = mapParty.get(partyid);
+ if(partyEntry == null) {
+ partyEntry = new LinkedHashSet<>();
+ partyEntry.add(chr.getId());
+
+ mapParty.put(partyid, partyEntry);
+ } else {
+ partyEntry.add(chr.getId());
+ }
+ }
+
+ private void removePartyMemberInternal(MapleCharacter chr) {
+ int partyid = chr.getPartyId();
+ if(partyid == -1) return;
+
+ Set partyEntry = mapParty.get(partyid);
+ if(partyEntry != null) {
+ if(partyEntry.size() > 1) partyEntry.remove(chr.getId());
+ else mapParty.remove(partyid);
+ }
+ }
+
+ public void addPartyMember(MapleCharacter chr) {
+ chrWLock.lock();
+ try {
+ addPartyMemberInternal(chr);
+ } finally {
+ chrWLock.unlock();
+ }
+ }
+
+ public void removePartyMember(MapleCharacter chr) {
+ chrWLock.lock();
+ try {
+ removePartyMemberInternal(chr);
+ } finally {
+ chrWLock.unlock();
+ }
+ }
+
+ public void removeParty(int partyid) {
+ chrWLock.lock();
+ try {
+ mapParty.remove(partyid);
+ } finally {
+ chrWLock.unlock();
+ }
+ }
+
public void addPlayer(final MapleCharacter chr) {
chrWLock.lock();
try {
characters.add(chr);
+ addPartyMemberInternal(chr);
} finally {
chrWLock.unlock();
}
@@ -2047,6 +2124,7 @@ public class MapleMap {
public void removePlayer(MapleCharacter chr) {
chrWLock.lock();
try {
+ removePartyMemberInternal(chr);
characters.remove(chr);
} finally {
chrWLock.unlock();
diff --git a/src/tools/MaplePacketCreator.java b/src/tools/MaplePacketCreator.java
index ce5fee095c..7f91cb9c8a 100644
--- a/src/tools/MaplePacketCreator.java
+++ b/src/tools/MaplePacketCreator.java
@@ -2623,7 +2623,8 @@ public class MaplePacketCreator {
mplew.writeShort(SendOpcode.GIVE_FOREIGN_BUFF.getValue());
mplew.writeInt(cid);
writeLongMaskD(mplew, statups);
- for (int i = 0; i < statups.size(); i++) {
+ for (Pair statup : statups) {
+ mplew.writeShort(statup.getRight().shortValue());
mplew.writeShort(skill.getSkillId());
mplew.writeShort(skill.getSkillLevel());
}
diff --git a/wz/Quest.wz/Check.img.xml b/wz/Quest.wz/Check.img.xml
index 8d70d78244..182d87d4ec 100644
--- a/wz/Quest.wz/Check.img.xml
+++ b/wz/Quest.wz/Check.img.xml
@@ -25248,6 +25248,7 @@
+
@@ -25960,13 +25961,6 @@
-
-
-
-
-
-
-
diff --git a/wz/Quest.wz/Say.img.xml b/wz/Quest.wz/Say.img.xml
index 5451f266ce..5cbe91b8a5 100644
--- a/wz/Quest.wz/Say.img.xml
+++ b/wz/Quest.wz/Say.img.xml
@@ -12772,6 +12772,7 @@
+
diff --git a/wz/Sound.wz/Field.img.xml b/wz/Sound.wz/Field.img.xml
index a9bea020ef..ed8a2cdc37 100644
--- a/wz/Sound.wz/Field.img.xml
+++ b/wz/Sound.wz/Field.img.xml
@@ -76,4 +76,7 @@
+
+
+