Merge branch 'master' into credits_update
This commit is contained in:
@@ -55,6 +55,10 @@
|
|||||||
/tools/MapleEventMethodFiller/dist/
|
/tools/MapleEventMethodFiller/dist/
|
||||||
/tools/MapleEventMethodFiller/nbproject/
|
/tools/MapleEventMethodFiller/nbproject/
|
||||||
|
|
||||||
|
/tools/MapleGachaponItemidRetriever/build/
|
||||||
|
/tools/MapleGachaponItemidRetriever/dist/
|
||||||
|
/tools/MapleGachaponItemidRetriever/nbproject/
|
||||||
|
|
||||||
/tools/MapleIdRetriever/build/
|
/tools/MapleIdRetriever/build/
|
||||||
/tools/MapleIdRetriever/dist/
|
/tools/MapleIdRetriever/dist/
|
||||||
/tools/MapleIdRetriever/nbproject/
|
/tools/MapleIdRetriever/nbproject/
|
||||||
|
|||||||
@@ -23,13 +23,15 @@ Java7 SDK: https://www.oracle.com/technetwork/java/javase/downloads/java-archive
|
|||||||
|
|
||||||
**Important note about localhosts**: these executables are red-flagged by antivirus tools as __potentially malicious softwares__, this happens due to the reverse engineering methods that were applied onto these software artifacts. Those depicted here have been put to use for years already and posed no harm so far, so they are soundly assumed to be safe.
|
**Important note about localhosts**: these executables are red-flagged by antivirus tools as __potentially malicious softwares__, this happens due to the reverse engineering methods that were applied onto these software artifacts. Those depicted here have been put to use for years already and posed no harm so far, so they are soundly assumed to be safe.
|
||||||
|
|
||||||
Latest localhost: https://hostr.co/tsYsQzzV6xT0
|
Latest localhost: https://hostr.co/itrvrHapvtEg
|
||||||
|
|
||||||
The following list, in bottom-up chronological order, holds information regarding all changes that were applied from the starting localhost used in this development. Some lines have a link attached, that will lead you to a snapshot of the localhost at that version of the artifact. Naturally, later versions holds all previous changes along with the proposed changes.
|
The following list, in bottom-up chronological order, holds information regarding all changes that were applied from the starting localhost used in this development. Some lines have a link attached, that will lead you to a snapshot of the localhost at that version of the artifact. Naturally, later versions holds all previous changes along with the proposed changes.
|
||||||
|
|
||||||
**Change log:**
|
**Change log:**
|
||||||
|
|
||||||
* Fixed some 'rn' problems with quest icons & removed "tab" from party leader changed message.
|
* Fixed Monster Magnet crashing the caster when trying to pull-in bosses.
|
||||||
|
|
||||||
|
* Fixed some 'rn' problems with quest icons & removed "tab" from party leader changed message. https://hostr.co/tsYsQzzV6xT0
|
||||||
|
|
||||||
* Removed block on applying attack-based strengthening gems on non-weapon equipments. https://hostr.co/m2bVtnizCtmD
|
* Removed block on applying attack-based strengthening gems on non-weapon equipments. https://hostr.co/m2bVtnizCtmD
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ Known issues:
|
|||||||
- On low-end connections, things such as command summoning a player that is currently logging in (already visible to other players) may cause the player to freeze, consequently freezing the account as well since the server-side disconnection doesn't happen.
|
- On low-end connections, things such as command summoning a player that is currently logging in (already visible to other players) may cause the player to freeze, consequently freezing the account as well since the server-side disconnection doesn't happen.
|
||||||
- Reportedly, there are cases where mob positions fail to sync between player's client-view.
|
- Reportedly, there are cases where mob positions fail to sync between player's client-view.
|
||||||
- Visual equip EXP watch value will present stuttering for early levels requirement (EXP needed less than 100), and requirement at level 200 will not progress at all due to the level cap in client.
|
- Visual equip EXP watch value will present stuttering for early levels requirement (EXP needed less than 100), and requirement at level 200 will not progress at all due to the level cap in client.
|
||||||
|
- Monster Magnet will crash the player when trying to pull fixed monsters.
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
-- Thanks MikeyJacobs for prompting out minimum specs search for pre-BB MapleStory.
|
||||||
|
-- Minimum specs gathered thanks to AkatsukiLog, source: https://www.clubedohardware.com.br/forums/topic/1081421-maplestory-reinicia-meu-pc-direto-ajuda/
|
||||||
|
|
||||||
|
MapleStory pre-BB specs:
|
||||||
|
|
||||||
|
Minimum Requirement | Recommended Setting
|
||||||
|
|
||||||
|
OS: Windows XP or later | Windows XP or later
|
||||||
|
Processor: Pentium 4 or equivalent | Pentium Dual Core or equivalent
|
||||||
|
Memory: 1GB RAM | 1GB RAM
|
||||||
|
Hard Drive: At least 7GB of free space | At least 7GB of free space
|
||||||
|
Graphics: Video Card with 128MB or higher | GeForce FX5000 / ATI Radeon 9600 or higher (any video card with Shader model 2.0 or higher)
|
||||||
|
Sound: DirectX compatible sound card | DirectX compatible sound card
|
||||||
|
Network: Broadband internet connection | Broadband internet connection
|
||||||
+77
-2
@@ -7,8 +7,8 @@
|
|||||||
Abdula -> 9209000 *
|
Abdula -> 9209000 *
|
||||||
|
|
||||||
CUSTOM NPC SHOPS (db_shopupdate.sql):
|
CUSTOM NPC SHOPS (db_shopupdate.sql):
|
||||||
Asia -> 2082014 *
|
Asia -> 2082014
|
||||||
T-1337 -> 9201101 *
|
T-1337 -> 9201101
|
||||||
|
|
||||||
* : those won't get disabled when USE_ENABLE_CUSTOM_NPC_SCRIPTS = false
|
* : those won't get disabled when USE_ENABLE_CUSTOM_NPC_SCRIPTS = false
|
||||||
|
|
||||||
@@ -1873,5 +1873,80 @@ Corrigido pets sendo indevidamente removido da DB ao realizar operações de ret
|
|||||||
15 Maio 2019,
|
15 Maio 2019,
|
||||||
Revisado, via testes unitários, robustez dos registros/buscas de jogadores e fluidez do sistema de Party Search.
|
Revisado, via testes unitários, robustez dos registros/buscas de jogadores e fluidez do sistema de Party Search.
|
||||||
|
|
||||||
|
18 - 19 Maio 2019,
|
||||||
|
Corrigido glitch de inventário ao colocar itens no storage, problema que foi introduzido recentemente.
|
||||||
|
Finalmente aprendido como funciona a mecânica por trás dos nodos "infoEx/infoNumber" amplamente usado pelas quests! :D
|
||||||
|
Implementado sistema de "crescimento de itens" na fonte.
|
||||||
|
|
||||||
|
20 - 24 Maio 2019,
|
||||||
|
Ajustado "Party Search". Ao invés de expirar sessões de busca após N tentativas, líderes são colocados em espera por alguns minutos e podem voltar a buscar automaticamente mais tarde.
|
||||||
|
Corrigido itens armazenados no Fredrick não sendo deletados ao deletar personagem, acarretando em inconsistências com cid inexistente.
|
||||||
|
Corrigido livros de upgrade de skills stackados em quantidade maior que 1 não podendo ser utilizados.
|
||||||
|
Nova ferramenta: MapleGachaponItemidRetriever. A ferramenta lê o arquivo-receita com nomes de itens designados para os diversos gachapons do jogo e, analisando a tabela da DB "handbook" (descrito pela ferramenta MapleIdRetriever), gera diversos arquivos (um para cada gachapon) contendo os ids dos itens especificados (ou próprio nome do item, se não encontrado).
|
||||||
|
Revisado script itens da região de Mushroom Empire. Ao invés dos efeitos dos itens atuarem ao acessar portais, agora ao utilizar os próprios itens pelo inventário as regiões anteriormente inacessíveis se tornam exploráveis, seguindo a descrição dos mesmos.
|
||||||
|
Revisado transições em 2 mapas da região de Mushroom Empire (um deles agora podendo ser atravessado ao utilizar um ETC, como previsto). Ambas transições projetadas para atuar após uso dos itens designados.
|
||||||
|
Corrigido script "secretroom" sempre requerendo o ETC adquirido via questline, algo que tornava a área interna inacessível ao tentar fazê-la múltiplas vezes.
|
||||||
|
Reelaborado completamente sistema de loots dos gachapons. Nova lista de loots de cada cidade disponível tenta seguir conteúdos encontrados na Web, supostamente legítimos (vide fontes mencionadas no fonte).
|
||||||
|
Adicionado gachapons para El Nath e Ludibrium.
|
||||||
|
Corrigido presença de PIN e PIC nulos (modificado para strings vazias).
|
||||||
|
Corrigido skill "Monster Magnet" desconectando jogadores ao utilizá-la. Isso ocorria devido a um problema no lado-cliente ao "falhar" em capturar o mob. Nova skill foi remodelada para solucionar isso (além de MP e range, árvore de atributos varia por quantidade máxima de mobs).
|
||||||
|
|
||||||
26 Maio 2019,
|
26 Maio 2019,
|
||||||
|
Ajustado portal que acessa área do NPC Nein Spirit's Baby Dragon, para permitir acesso aos jogadores que concluem a rachadura do ovo, ao invés de somente após completar quest.
|
||||||
Normalizado comentários de créditos.
|
Normalizado comentários de créditos.
|
||||||
|
|
||||||
|
31 Maio 2019,
|
||||||
|
Implementado método/comando que permite visualizar itens que podem ser ganhos pelo gachapons.
|
||||||
|
Corrigido Mystic Doors crashando jogadores ao tentar cancelar o buff da skill excessivamente cedo.
|
||||||
|
Corrigido tentativa de acessar boss Prime Minister acarretando em exceções de nulos ao tentar entrar em party.
|
||||||
|
Corrigido evento de acesso ao boss Prime Minister não realizando disposes corretamente (assim que evento fica sem jogadores, após mudar de mapa, reviver, desconectar, etc).
|
||||||
|
Refatorado estruturas de "ignored" e "monitored" dos comandos, agora utilizando conjuntos e checagem de inteiros ao invés de nomes.
|
||||||
|
Refatorado referências aos métodos da família "startQuest" e "completeQuest", com funcionalidade repetida para diversas subclasses de AbstractPlayerInteraction.
|
||||||
|
|
||||||
|
01 Junho 2019,
|
||||||
|
Corrigido métodos de chegagem por espaço de inventários não avaliando corretamente quantidade de slots necessário para acomodar itens recarregáveis.
|
||||||
|
Corrigido minigames não retirando referências dos jogadores devidamente, problema que veio a ocorrer após atualizações recentes.
|
||||||
|
Implementado requisição de saída de minigames após fim de partida.
|
||||||
|
Corrigido possibilidade de minigames entregando mais de um resultado cada partida (jogadores podem decidir desistir em conjunto, somando pontos).
|
||||||
|
Corrigido negação de empate em minigame pelo outro jogador não permitindo o mesmo lançar um pedido de empate em sequência.
|
||||||
|
|
||||||
|
02 - 03 Junho 2019,
|
||||||
|
Tentativa de correção de mais casos de skill "Monster Magnet" desconectando jogadores ao utilizá-la (tentativa não foi bem-sucedida, mas apresenta resultados para bosses ou mobs fixos, mutuamente exclusivos).
|
||||||
|
|
||||||
|
04 Junho 2019,
|
||||||
|
Aprimorado sistema de update de buffs condicionais, não mais atualizando todos os buffs ao mudar de mapas.
|
||||||
|
|
||||||
|
05 Junho 2019,
|
||||||
|
Refatorado uso da DB pelo Duey. Itens registrados pelo Duey agora compartilham da mesma tabela de itens e equipamentos que os demais.
|
||||||
|
Revisado levemente transação de itens pelas diversas interações disponíveis (trades, shops, Duey, até checagem de item ao anunciar pelo megafone), adotando uso das server flags.
|
||||||
|
Corrigido caso de unlock não-encapsulado no hitLock de reatores.
|
||||||
|
|
||||||
|
07 - 08 Junho 2019,
|
||||||
|
Corrigido NPCs de cosméticos desconectando jogadores ao tentar mostrar ao jogador uma lista sem opções.
|
||||||
|
Corrigido caso de deadlock ao realizar update de buffs durante transição de mapas.
|
||||||
|
|
||||||
|
09 Junho 2019,
|
||||||
|
Corrigido falhas na detecção de objetos dentro do alcançe de mob skills, código anterior levava em conta atributo "facingLeft" desnecessário para cálculo da área de efeito.
|
||||||
|
Revisado sistema de aggro não mais retirando perseguição de boss sobre jogadores após expirar contagem de aggro.
|
||||||
|
Refatorado checagem desnecessária por mapas onde itens não expiram (não havia efeito na checagem, itens expiráveis são determinados mais à frente com tempo de expiração máximo).
|
||||||
|
Corrigido chalkboard removendo unidade do inventário ao usar (usa-se à vontade, por um curto período).
|
||||||
|
Corrigido detecção de "mob virado para um lado" atuando incorretamente para mobs fixos não-viráveis (resultado deveria ser sempre a mesma orientação para esse caso).
|
||||||
|
|
||||||
|
10 Junho 2019,
|
||||||
|
Refatorado MapleMapFactory, buscando normalizar o padrão de design "Factory" que fora implementado inicialmente. Com a adição de novas funcionalidades o padrão implementado perdeu um pouco de sua coesão, agora revisado.
|
||||||
|
Adicionado sistema de recuperação de MP para mobs, evitando assim possibilidade de mobs faltarem com MP em lutas muito longas.
|
||||||
|
Adicionado no sistema de buff condicionais suporte para condicional de "caçando em grupo" (dois ou mais membros de grupo no mesmo mapa).
|
||||||
|
Corrigido indisponibilidade de certos loots de mobs para jogadores que poderiam obter o mesmo mas que não fazem parte do grupo que lidou o golpe final (somente o grupo citado era levado em consideração).
|
||||||
|
Corrigido loots one-of-a-kind se tornando indisponível uma vez que o jogador possui o mesmo em seu inventário.
|
||||||
|
|
||||||
|
11 - 12 Junho 2019,
|
||||||
|
Refatorado objeto construtor de intervalos para fora da classe encarregada com "Party Search", agora servindo como objeto de propósito-geral.
|
||||||
|
Revisado sistema de distribuição de EXP, agora seguindo cálculos mais chegados ao GMS-like.
|
||||||
|
|
||||||
|
13 Junho 2019,
|
||||||
|
Ajustado novamente portal que acessa área do NPC Nein Spirit's Baby Dragon. Somente acessa a área quem completou a quest inicial do NPC.
|
||||||
|
Ajustado interação com mapa do NPC Nein Spirit's Baby Dragon. Acesso à área é restrita para um jogador por vez, tempo limitado, e somente se o mesmo pode/já interagiu com o NPC.
|
||||||
|
Normalizado uso de lobbyids em início de eventos nos scripts.
|
||||||
|
|
||||||
|
15 Junho 2019,
|
||||||
|
Corrigido limites de requisitos de nível para acessar expedições nos scripts de NPCs que as gerenciam.
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
Source: http://metropi.forumotion.net/t32-npc-scripting-guide-from-ragezone
|
Source: http://forum.ragezone.com/f428/add-npc-scripting-605225/
|
||||||
|
|
||||||
NPC Markups:
|
NPC Markups:
|
||||||
#b = Blue text.
|
#b = Blue text.
|
||||||
|
|||||||
+8
-8
@@ -446,10 +446,10 @@
|
|||||||
2040303 - Scroll for Earring for INT - Improves INT on ear accessory.\nSuccess rate:30%, magic attack +5, INT+3, magic def. +1
|
2040303 - Scroll for Earring for INT - Improves INT on ear accessory.\nSuccess rate:30%, magic attack +5, INT+3, magic def. +1
|
||||||
2040304 - Dark scroll for Earring for INT - Improves INT on ear accessory.\nSuccess rate:70%, magic attack +2, INT+1nIf failed, the item will be destroyed at a 50% rate.
|
2040304 - Dark scroll for Earring for INT - Improves INT on ear accessory.\nSuccess rate:70%, magic attack +2, INT+1nIf failed, the item will be destroyed at a 50% rate.
|
||||||
2040305 - Dark scroll for Earring for INT - Improves INT on ear accessory.\nSuccess rate:30%, magic attack +5, INT+3, magic def. +1nIf failed, the item will be destroyed at a 50% rate.
|
2040305 - Dark scroll for Earring for INT - Improves INT on ear accessory.\nSuccess rate:30%, magic attack +5, INT+3, magic def. +1nIf failed, the item will be destroyed at a 50% rate.
|
||||||
2040306 - Dark scroll for Earring for DEX - Improves DEX on ear accesrroy.\nSuccess rate: 70%. DEX + 2nIf failed, the item will be destroyed at a 50% rate.
|
2040306 - Dark scroll for Earring for DEX - Improves DEX on ear accessory.\nSuccess rate: 70%. DEX + 2nIf failed, the item will be destroyed at a 50% rate.
|
||||||
2040307 - Dark scroll for Earring for DEX - Improves DEX on ear accessorynSuccess rate: 30%. DEX + 3nIf failed, the item will be destroyed at a 50% rate.
|
2040307 - Dark scroll for Earring for DEX - Improves DEX on ear accessorynSuccess rate: 30%. DEX + 3nIf failed, the item will be destroyed at a 50% rate.
|
||||||
2040308 - Dark Scroll for Earrings for DEF - Improves DEF on earringsnSuccess Rate 70%, weapon defense+1, magic defense+1nIf failed, the item will be destroyed at a 50% rate.
|
2040308 - Dark Scroll for Earring for DEF - Improves DEF on earringsnSuccess Rate 70%, weapon defense+1, magic defense+1nIf failed, the item will be destroyed at a 50% rate.
|
||||||
2040309 - Dark Scroll for Earrings for DEF - Improves DEF on earringsnSuccess Rate 30%, weapon defense+3, magic defense+3, accuracy+1nIf failed, the item will be destroyed at a 50% rate.
|
2040309 - Dark Scroll for Earring for DEF - Improves DEF on earringsnSuccess Rate 30%, weapon defense+3, magic defense+3, accuracy+1nIf failed, the item will be destroyed at a 50% rate.
|
||||||
2040310 - Scroll for Earring for DEF - Improves DEF on earrings.\nSuccess Rate 10%, weapon defense+3, magic defense+3, Accuracy+1. The success rate of this scroll can be enhanced by Vega's Spell.
|
2040310 - Scroll for Earring for DEF - Improves DEF on earrings.\nSuccess Rate 10%, weapon defense+3, magic defense+3, Accuracy+1. The success rate of this scroll can be enhanced by Vega's Spell.
|
||||||
2040311 - Scroll for Earring for DEF - Improves DEF on earrings.\nSuccess Rate 60%, weapon defense+1, magic defense+1. The success rate of this scroll can be enhanced by Vega's Spell.
|
2040311 - Scroll for Earring for DEF - Improves DEF on earrings.\nSuccess Rate 60%, weapon defense+1, magic defense+1. The success rate of this scroll can be enhanced by Vega's Spell.
|
||||||
2040312 - Scroll for Earring for DEF - Improves DEF on earringsnSuccess Rate 100%, weapon defense+1
|
2040312 - Scroll for Earring for DEF - Improves DEF on earringsnSuccess Rate 100%, weapon defense+1
|
||||||
@@ -952,8 +952,8 @@
|
|||||||
2070009 - Wooden Top - When thrown, it spins fast and flies at great speed. Once they are all used up, they need to be recharged.\nLevel Limit : 10, Attack + 19
|
2070009 - Wooden Top - When thrown, it spins fast and flies at great speed. Once they are all used up, they need to be recharged.\nLevel Limit : 10, Attack + 19
|
||||||
2070010 - Icicle - Sharp icicles. Once they run out, they need to be recharged.rnLevel Limit : 10, Attack + 21
|
2070010 - Icicle - Sharp icicles. Once they run out, they need to be recharged.rnLevel Limit : 10, Attack + 21
|
||||||
2070011 - Maple Throwing-Stars - Maple-shaped steel throwing-stars. Once they run out, they need to be recharged.rnLevel Limit : 10, Attack + 21
|
2070011 - Maple Throwing-Stars - Maple-shaped steel throwing-stars. Once they run out, they need to be recharged.rnLevel Limit : 10, Attack + 21
|
||||||
2070012 - Paper Fighter Plane - A paper plane that can be thrown at things. Once they run out, they need to be recharged. Attack +20
|
2070012 - Paper Fighter Plane - A paper plane that can be thrown at things. Once they run out, they need to be recharged.\nAttack +20
|
||||||
2070013 - Orange - A tasty orange that can be thrown at things. Attack + 20
|
2070013 - Orange - A tasty orange that can be thrown at things.\nAttack + 20
|
||||||
2070014 - Devil Rain Throwing Star - Throwing Star
|
2070014 - Devil Rain Throwing Star - Throwing Star
|
||||||
2070015 - A Beginner Thief's Throwing Stars - These are steel throwing stars given by Dark Lord for Beginner Thieves. Unlike normal throwing stars, you can't recharge it. \nAttack + 15
|
2070015 - A Beginner Thief's Throwing Stars - These are steel throwing stars given by Dark Lord for Beginner Thieves. Unlike normal throwing stars, you can't recharge it. \nAttack + 15
|
||||||
2070016 - Crystal Ilbi Throwing-Stars - A throwing-star made of crystal. Once they run out, they need to be recharged. rnAttack + 29
|
2070016 - Crystal Ilbi Throwing-Stars - A throwing-star made of crystal. Once they run out, they need to be recharged. rnAttack + 29
|
||||||
@@ -1810,8 +1810,8 @@
|
|||||||
2044812 - Scroll for Knuckles for ATT 15% - Improves ATT on Knuckles.\nSuccess Rate:15%, Weapon Att+5, STR+3, Weapon DEF+1
|
2044812 - Scroll for Knuckles for ATT 15% - Improves ATT on Knuckles.\nSuccess Rate:15%, Weapon Att+5, STR+3, Weapon DEF+1
|
||||||
2044813 - Scroll for Knuckles for Accuracy 65% - Improves Accuracy on Knuckles.\nSuccess Rate:65%, Accuracy+3, DEX+2, Weapon Att+1
|
2044813 - Scroll for Knuckles for Accuracy 65% - Improves Accuracy on Knuckles.\nSuccess Rate:65%, Accuracy+3, DEX+2, Weapon Att+1
|
||||||
2044814 - Scroll for Knuckles for Accuracy 15% - Improves Accuracy on Knuckles.\nSuccess Rate:15%, Accuracy+5, DEX+3, Weapon Att+3
|
2044814 - Scroll for Knuckles for Accuracy 15% - Improves Accuracy on Knuckles.\nSuccess Rate:15%, Accuracy+5, DEX+3, Weapon Att+3
|
||||||
2044906 - Gun ATT Scroll 65% - Improves ATT on guns.\nSuccess Rate:65%, Weapon Att.+2, Accuracy+1
|
2044906 - Scroll for Gun for ATT 65% - Improves ATT on guns.\nSuccess Rate:65%, Weapon Att.+2, Accuracy+1
|
||||||
2044907 - Gun ATT Scroll 15% - Improves ATT on guns.\nSuccess Rate:15%, Weapon Att.+5, Accuracy+3, DEX+1
|
2044907 - Scroll for Gun for ATT 15% - Improves ATT on guns.\nSuccess Rate:15%, Weapon Att.+5, Accuracy+3, DEX+1
|
||||||
2049103 - Beach Sandals Scroll 100% - Used on limited-edition beach sandals, with the options of improving/decreasing the stats.\nSuccess rate:100%
|
2049103 - Beach Sandals Scroll 100% - Used on limited-edition beach sandals, with the options of improving/decreasing the stats.\nSuccess rate:100%
|
||||||
2100073 - Mu Lung Dojo Summon Package3_Deo - Summon Deo
|
2100073 - Mu Lung Dojo Summon Package3_Deo - Summon Deo
|
||||||
2100074 - Mu Lung Dojo Summon Package4_King Slime - Summon King Slime
|
2100074 - Mu Lung Dojo Summon Package4_King Slime - Summon King Slime
|
||||||
@@ -2017,7 +2017,7 @@
|
|||||||
2044015 - Scroll for Two-Handed Swords for ATT 10% - Improves ATT on Two-Handed Swords. nSuccess rate: 10%, Weapons ATT +5, STR +3, Weapons Defense +1
|
2044015 - Scroll for Two-Handed Swords for ATT 10% - Improves ATT on Two-Handed Swords. nSuccess rate: 10%, Weapons ATT +5, STR +3, Weapons Defense +1
|
||||||
2049105 - [6th Anniversary] Dark Scroll for Gloves for ATT 70% - Improves ATT on Gloves. nSuccess rate: 70%, Weapons ATT +1nIf unsuccessful, item has a 50% chance of being destroyed.
|
2049105 - [6th Anniversary] Dark Scroll for Gloves for ATT 70% - Improves ATT on Gloves. nSuccess rate: 70%, Weapons ATT +1nIf unsuccessful, item has a 50% chance of being destroyed.
|
||||||
2049106 - [6th Anniversary] Dark Scroll for Gloves for ATT 30% - Improves ATT on Gloves. nSucces rate: 30%, Weapons ATT +2nIf unsuccessful, item has an 80% chance of being destroyed.
|
2049106 - [6th Anniversary] Dark Scroll for Gloves for ATT 30% - Improves ATT on Gloves. nSucces rate: 30%, Weapons ATT +2nIf unsuccessful, item has an 80% chance of being destroyed.
|
||||||
2049107 - [6th Anniversary] Dark Scroll for Gloves for STR 70% [ - Improves STR on Gloves. nSuccess rate: 70%, Accuracy +2, STR +1nIf unsuccessful, item has a 50% chance of being destroyed.
|
2049107 - [6th Anniversary] Dark Scroll for Gloves for STR 70% - Improves STR on Gloves. nSuccess rate: 70%, Accuracy +2, STR +1nIf unsuccessful, item has a 50% chance of being destroyed.
|
||||||
2049108 - [6th Anniversary] Dark Scroll for Gloves for LUK 70% - Improves LUK on Gloves. nSuccess rate: 70%, Accuracy +2, LUK +1nIf unsuccessful, item has a 50% chance of being destroyed.
|
2049108 - [6th Anniversary] Dark Scroll for Gloves for LUK 70% - Improves LUK on Gloves. nSuccess rate: 70%, Accuracy +2, LUK +1nIf unsuccessful, item has a 50% chance of being destroyed.
|
||||||
2049109 - [6th Anniversary] Dark Scroll for Gloves for INT 70% - Improves INT on Gloves. nSuccess rate: 70%, Accuracy +2, INT +1nIf unsuccessful, item has a 50% chance of being destroyed.
|
2049109 - [6th Anniversary] Dark Scroll for Gloves for INT 70% - Improves INT on Gloves. nSuccess rate: 70%, Accuracy +2, INT +1nIf unsuccessful, item has a 50% chance of being destroyed.
|
||||||
2049110 - [6th Anniversary] Dark Scroll for Gloves for DEX 70% - Improves DEX on Gloves. nSuccess rate: 70%, Accuracy +2, DEX +1nIf unsuccessful, item has a 50% chance of being destroyed.
|
2049110 - [6th Anniversary] Dark Scroll for Gloves for DEX 70% - Improves DEX on Gloves. nSuccess rate: 70%, Accuracy +2, DEX +1nIf unsuccessful, item has a 50% chance of being destroyed.
|
||||||
|
|||||||
@@ -86,29 +86,38 @@ function scheduledTimeout(eim){
|
|||||||
eim.dispose();
|
eim.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
function playerRevive(eim, player){
|
function playerRevive(eim, player) { // player presses ok on the death pop up.
|
||||||
player.respawn(eim, entryMap);
|
if (eim.isEventTeamLackingNow(true, minPlayers, player)) {
|
||||||
return false;
|
eim.unregisterPlayer(player);
|
||||||
|
end(eim);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
eim.unregisterPlayer(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
function playerDead(eim, player){}
|
function playerDead(eim, player){}
|
||||||
|
|
||||||
function playerDisconnected(eim, player){
|
function playerDisconnected(eim, player){
|
||||||
var party = eim.getPlayers();
|
if (eim.isEventTeamLackingNow(true, minPlayers, player)) {
|
||||||
|
eim.unregisterPlayer(player);
|
||||||
for(var i = 0; i < party.size(); i++){
|
end(eim);
|
||||||
if(party.get(i).equals(player))
|
|
||||||
removePlayer(eim, player);
|
|
||||||
else
|
|
||||||
playerExit(eim, party.get(i));
|
|
||||||
}
|
}
|
||||||
eim.dispose();
|
else
|
||||||
|
eim.unregisterPlayer(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
function monsterValue(eim, mobId){
|
function monsterValue(eim, mobId){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function end(eim) {
|
||||||
|
var party = eim.getPlayers();
|
||||||
|
for (var i = 0; i < party.size(); i++) {
|
||||||
|
playerExit(eim, party.get(i));
|
||||||
|
}
|
||||||
|
eim.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
function leftParty(eim, player){}
|
function leftParty(eim, player){}
|
||||||
|
|
||||||
function disbandParty(eim){}
|
function disbandParty(eim){}
|
||||||
@@ -120,8 +129,15 @@ function playerExit(eim, player){
|
|||||||
player.changeMap(exitMap, 2);
|
player.changeMap(exitMap, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
function changedMap(eim, chr, mapid) {
|
function changedMap(eim, player, mapid) {
|
||||||
if(mapid < minMapId || mapid > maxMapId) playerExit(eim, chr);
|
if (mapid < minMapId || mapid > maxMapId) {
|
||||||
|
if (eim.isEventTeamLackingNow(true, minPlayers, player)) {
|
||||||
|
eim.unregisterPlayer(player);
|
||||||
|
end(eim);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
eim.unregisterPlayer(player);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function removePlayer(eim, player){
|
function removePlayer(eim, player){
|
||||||
|
|||||||
@@ -77,29 +77,38 @@ function scheduledTimeout(eim){
|
|||||||
eim.dispose();
|
eim.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
function playerRevive(eim, player){
|
function playerRevive(eim, player) { // player presses ok on the death pop up.
|
||||||
player.respawn(eim, entryMap);
|
if (eim.isEventTeamLackingNow(true, minPlayers, player)) {
|
||||||
return false;
|
eim.unregisterPlayer(player);
|
||||||
|
end(eim);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
eim.unregisterPlayer(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
function playerDead(eim, player){}
|
function playerDead(eim, player){}
|
||||||
|
|
||||||
function playerDisconnected(eim, player){
|
function playerDisconnected(eim, player){
|
||||||
var party = eim.getPlayers();
|
if (eim.isEventTeamLackingNow(true, minPlayers, player)) {
|
||||||
|
eim.unregisterPlayer(player);
|
||||||
for(var i = 0; i < party.size(); i++){
|
end(eim);
|
||||||
if(party.get(i).equals(player))
|
|
||||||
removePlayer(eim, player);
|
|
||||||
else
|
|
||||||
playerExit(eim, party.get(i));
|
|
||||||
}
|
}
|
||||||
eim.dispose();
|
else
|
||||||
|
eim.unregisterPlayer(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
function monsterValue(eim, mobId){
|
function monsterValue(eim, mobId){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function end(eim) {
|
||||||
|
var party = eim.getPlayers();
|
||||||
|
for (var i = 0; i < party.size(); i++) {
|
||||||
|
playerExit(eim, party.get(i));
|
||||||
|
}
|
||||||
|
eim.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
function leftParty(eim, player){}
|
function leftParty(eim, player){}
|
||||||
|
|
||||||
function disbandParty(eim){}
|
function disbandParty(eim){}
|
||||||
@@ -112,7 +121,14 @@ function playerExit(eim, player){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function changedMap(eim, chr, mapid) {
|
function changedMap(eim, chr, mapid) {
|
||||||
if(mapid < minMapId || mapid > maxMapId) playerExit(eim, chr);
|
if (mapid < minMapId || mapid > maxMapId) {
|
||||||
|
if (eim.isEventTeamLackingNow(true, minPlayers, player)) {
|
||||||
|
eim.unregisterPlayer(player);
|
||||||
|
end(eim);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
eim.unregisterPlayer(player);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function removePlayer(eim, player){
|
function removePlayer(eim, player){
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
var minPlayers = 1;
|
||||||
|
var timeLimit = 5; //5 minutes
|
||||||
|
var eventTimer = 1000 * 60 * timeLimit;
|
||||||
|
var exitMap = 240040610;
|
||||||
|
var eventMap = 240040611;
|
||||||
|
|
||||||
|
var minMapId = 240040611;
|
||||||
|
var maxMapId = 240040611;
|
||||||
|
|
||||||
|
function init(){}
|
||||||
|
|
||||||
|
function setup(difficulty, lobbyId){
|
||||||
|
var eim = em.newInstance("NineSpirit_" +lobbyId);
|
||||||
|
eim.getInstanceMap(eventMap).resetFully();
|
||||||
|
eim.getInstanceMap(eventMap).allowSummonState(false);
|
||||||
|
respawn(eim);
|
||||||
|
eim.startEventTimer(eventTimer);
|
||||||
|
return eim;
|
||||||
|
}
|
||||||
|
|
||||||
|
function afterSetup(eim){}
|
||||||
|
|
||||||
|
function respawn(eim){}
|
||||||
|
|
||||||
|
function playerEntry(eim, player){
|
||||||
|
var nest = eim.getMapInstance(eventMap);
|
||||||
|
if (!player.haveItem(4001094)) {
|
||||||
|
eim.spawnNpc(2081008, nest.getReactorById(2406000).getPosition(), nest);
|
||||||
|
}
|
||||||
|
|
||||||
|
player.changeMap(nest, 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.respawn(eim, 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){}
|
||||||
|
|
||||||
|
function disbandParty(eim){}
|
||||||
|
|
||||||
|
function playerUnregistered(eim, player){}
|
||||||
|
|
||||||
|
function playerExit(eim, player){
|
||||||
|
eim.unregisterPlayer(player);
|
||||||
|
player.changeMap(exitMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
function changedMap(eim, chr, mapid){
|
||||||
|
if(mapid < minMapId || mapid > maxMapId){
|
||||||
|
removePlayer(eim, chr);
|
||||||
|
eim.stopEventTimer();
|
||||||
|
eim.setEventCleared();
|
||||||
|
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){}
|
||||||
|
|
||||||
|
// ---------- FILLER FUNCTIONS ----------
|
||||||
|
|
||||||
|
function changedLeader(eim, leader) {}
|
||||||
|
|
||||||
@@ -4,6 +4,9 @@ var eventTimer = 1000 * 60 * timeLimit;
|
|||||||
var exitMap = 105070300;
|
var exitMap = 105070300;
|
||||||
var eventMap = 910510000;
|
var eventMap = 910510000;
|
||||||
|
|
||||||
|
var minMapId = 910510000;
|
||||||
|
var maxMapId = 910510000;
|
||||||
|
|
||||||
function init(){}
|
function init(){}
|
||||||
|
|
||||||
function setup(difficulty, lobbyId){
|
function setup(difficulty, lobbyId){
|
||||||
@@ -67,9 +70,9 @@ function playerExit(eim, player){
|
|||||||
player.changeMap(exitMap);
|
player.changeMap(exitMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
function changedMap(eim, player){
|
function changedMap(eim, chr, mapid){
|
||||||
if(player.getMap().getId() < eventMap || player.getMap().getId() > next){
|
if(mapid < minMapId || mapid > maxMapId){
|
||||||
removePlayer(eim, player);
|
removePlayer(eim, chr);
|
||||||
eim.stopEventTimer();
|
eim.stopEventTimer();
|
||||||
eim.setEventCleared();
|
eim.setEventCleared();
|
||||||
eim.dispose();
|
eim.dispose();
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the HeavenMS MapleStory Server
|
||||||
|
Copyleft (L) 2016 - 2018 RonanLana
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as
|
||||||
|
published by the Free Software Foundation version 3 as published by
|
||||||
|
the Free Software Foundation. You may not use, modify or distribute
|
||||||
|
this program under any other version of the GNU Affero General Public
|
||||||
|
License.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var status;
|
||||||
|
|
||||||
|
function start() {
|
||||||
|
status = -1;
|
||||||
|
action(1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function action(mode, type, selection) {
|
||||||
|
if (mode == -1) {
|
||||||
|
im.dispose();
|
||||||
|
} else {
|
||||||
|
if (mode == 0 && type > 0) {
|
||||||
|
im.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mode == 1)
|
||||||
|
status++;
|
||||||
|
else
|
||||||
|
status--;
|
||||||
|
|
||||||
|
if(status == 0) {
|
||||||
|
if (im.getMapId() == 106020300) {
|
||||||
|
var portal = im.getMap().getPortal("obstacle");
|
||||||
|
if (portal != null && portal.getPosition().distance(im.getPlayer().getPosition()) < 210) {
|
||||||
|
if(!(im.isQuestStarted(100202) || im.isQuestCompleted(100202))) im.startQuest(100202);
|
||||||
|
im.removeAll(2430014);
|
||||||
|
|
||||||
|
im.message("You have used the Killer Mushroom Spore to open the way.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
im.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the HeavenMS MapleStory Server
|
||||||
|
Copyleft (L) 2016 - 2018 RonanLana
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as
|
||||||
|
published by the Free Software Foundation version 3 as published by
|
||||||
|
the Free Software Foundation. You may not use, modify or distribute
|
||||||
|
this program under any other version of the GNU Affero General Public
|
||||||
|
License.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var status;
|
||||||
|
|
||||||
|
function start() {
|
||||||
|
status = -1;
|
||||||
|
action(1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function action(mode, type, selection) {
|
||||||
|
if (mode == -1) {
|
||||||
|
im.dispose();
|
||||||
|
} else {
|
||||||
|
if (mode == 0 && type > 0) {
|
||||||
|
im.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mode == 1)
|
||||||
|
status++;
|
||||||
|
else
|
||||||
|
status--;
|
||||||
|
|
||||||
|
if(status == 0) {
|
||||||
|
if (im.getMapId() == 106020400 && im.isQuestActive(2324)) {
|
||||||
|
var player = im.getPlayer();
|
||||||
|
|
||||||
|
var portal = im.getMap().getPortal("right00");
|
||||||
|
if (portal != null && portal.getPosition().distance(player.getPosition()) < 210) {
|
||||||
|
player.gainExp(3300 * player.getExpRate());
|
||||||
|
|
||||||
|
im.forceCompleteQuest(2324);
|
||||||
|
im.removeAll(2430015);
|
||||||
|
im.playerMessage(5, "You have used the Thorn Remover to clear the path.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
im.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -58,7 +58,7 @@ function action(mode, type, selection) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
if (player.getLevel() < exped.getMinLevel() && player.getLevel() > exped.getMaxLevel()) { //Don't fit requirement
|
if (player.getLevel() < exped.getMinLevel() || player.getLevel() > exped.getMaxLevel()) { //Don't fit requirement, thanks Conrad
|
||||||
cm.sendOk("You do not meet the criteria to battle " + expedBoss + "!");
|
cm.sendOk("You do not meet the criteria to battle " + expedBoss + "!");
|
||||||
cm.dispose();
|
cm.dispose();
|
||||||
} else if (expedition == null) { //Start an expedition
|
} else if (expedition == null) { //Start an expedition
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ function action(mode, type, selection){
|
|||||||
|
|
||||||
var party = cm.getPlayer().getParty();
|
var party = cm.getPlayer().getParty();
|
||||||
if (party != null) {
|
if (party != null) {
|
||||||
if (!em.startInstance(party, cm.getMap())) {
|
if (!em.startInstance(party, cm.getMap(), 1)) {
|
||||||
cm.sendOk("Another party is already challenging the boss in this channel.");
|
cm.sendOk("Another party is already challenging the boss in this channel.");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -59,7 +59,12 @@ function action(mode, type, selection) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!(cm.isQuestStarted(100200) || cm.isQuestCompleted(100200))) { // thanks Vcoc for finding out a need of reapproval from the masters for Zakum expeditions
|
if(!(cm.isQuestStarted(100200) || cm.isQuestCompleted(100200))) { // thanks Vcoc for finding out a need of reapproval from the masters for Zakum expeditions
|
||||||
|
if (cm.getPlayer().getLevel() >= 50) { // thanks Z1peR for noticing not-so-clear unmet requirements message here.
|
||||||
|
cm.sendOk("Beware, for the power of olde has not been forgotten... If you seek to defeat #rZakum#k someday, earn the #bChief's Residence Council#k approval foremost and then #bface the trials#k, only then you will become eligible to fight.");
|
||||||
|
} else {
|
||||||
cm.sendOk("Beware, for the power of olde has not been forgotten...");
|
cm.sendOk("Beware, for the power of olde has not been forgotten...");
|
||||||
|
}
|
||||||
|
|
||||||
cm.dispose();
|
cm.dispose();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ function action(mode, type, selection) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
if (player.getLevel() < exped.getMinLevel() && player.getLevel() > exped.getMaxLevel()) { //Don't fit requirement
|
if (player.getLevel() < exped.getMinLevel() || player.getLevel() > exped.getMaxLevel()) { //Don't fit requirement, thanks Conrad
|
||||||
cm.sendOk("You do not meet the criteria to battle " + expedBoss + "!");
|
cm.sendOk("You do not meet the criteria to battle " + expedBoss + "!");
|
||||||
cm.dispose();
|
cm.dispose();
|
||||||
} else if (expedition == null) { //Start an expedition
|
} else if (expedition == null) { //Start an expedition
|
||||||
|
|||||||
@@ -39,7 +39,14 @@ function action(mode, type, selection) {
|
|||||||
status--;
|
status--;
|
||||||
|
|
||||||
if(status == 0) {
|
if(status == 0) {
|
||||||
|
if (Packages.constants.ServerConstants.USE_ENABLE_CUSTOM_NPC_SCRIPT) {
|
||||||
|
cm.openShopNPC(2082014);
|
||||||
|
} else if (cm.isQuestStarted(3749)) {
|
||||||
cm.sendOk("We've already located the enemy's ultimate weapon! Follow along the ship's bow area ahead and you will find my sister #b#p2082013##k. Report to her for futher instructions on the mission.");
|
cm.sendOk("We've already located the enemy's ultimate weapon! Follow along the ship's bow area ahead and you will find my sister #b#p2082013##k. Report to her for futher instructions on the mission.");
|
||||||
|
} else {
|
||||||
|
cm.sendDefault();
|
||||||
|
}
|
||||||
|
|
||||||
cm.dispose();
|
cm.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,7 +57,7 @@ function action(mode, type, selection) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
if (player.getLevel() < exped.getMinLevel() && player.getLevel() > exped.getMaxLevel()) { //Don't fit requirement
|
if (player.getLevel() < exped.getMinLevel() || player.getLevel() > exped.getMaxLevel()) { //Don't fit requirement, thanks Conrad
|
||||||
cm.sendOk("You do not meet the criteria to battle " + expedBoss + "!");
|
cm.sendOk("You do not meet the criteria to battle " + expedBoss + "!");
|
||||||
cm.dispose();
|
cm.dispose();
|
||||||
} else if (expedition == null) { //Start an expedition
|
} else if (expedition == null) { //Start an expedition
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ function action(mode, type, selection) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
if (player.getLevel() < exped.getMinLevel() && player.getLevel() > exped.getMaxLevel()) { //Don't fit requirement
|
if (player.getLevel() < exped.getMinLevel() || player.getLevel() > exped.getMaxLevel()) { //Don't fit requirement, thanks Conrad
|
||||||
cm.sendOk("You do not meet the criteria to battle " + expedBoss + "!");
|
cm.sendOk("You do not meet the criteria to battle " + expedBoss + "!");
|
||||||
cm.dispose();
|
cm.dispose();
|
||||||
} else if (expedition == null) { //Start an expedition
|
} else if (expedition == null) { //Start an expedition
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ function action(mode, type, selection) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
if (player.getLevel() < exped.getMinLevel() && player.getLevel() > exped.getMaxLevel()) { //Don't fit requirement
|
if (player.getLevel() < exped.getMinLevel() || player.getLevel() > exped.getMaxLevel()) { //Don't fit requirement, thanks Conrad
|
||||||
cm.sendOk("You do not meet the criteria to battle " + expedBoss + "!");
|
cm.sendOk("You do not meet the criteria to battle " + expedBoss + "!");
|
||||||
cm.dispose();
|
cm.dispose();
|
||||||
} else if (expedition == null) { //Start an expedition
|
} else if (expedition == null) { //Start an expedition
|
||||||
|
|||||||
@@ -4,10 +4,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function start() {
|
function start() {
|
||||||
if(Packages.server.MapleShopFactory.getInstance().getShop(9201101) != null) {
|
if (Packages.constants.ServerConstants.USE_ENABLE_CUSTOM_NPC_SCRIPT) {
|
||||||
cm.openShopNPC(9201101);
|
cm.openShopNPC(9201101);
|
||||||
} else {
|
} else {
|
||||||
cm.sendOk("The patrol in New Leaf City is always ready. No creatures are able to break through to the city.");
|
//cm.sendOk("The patrol in New Leaf City is always ready. No creatures are able to break through to the city.");
|
||||||
|
cm.sendDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
cm.dispose();
|
cm.dispose();
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ function action(mode, type, selection) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
if (player.getLevel() < cwkpq.getMinLevel() && player.getLevel() > cwkpq.getMaxLevel()) { //Don't fit requirement
|
if (player.getLevel() < cwkpq.getMinLevel() || player.getLevel() > cwkpq.getMaxLevel()) { //Don't fit requirement, thanks Conrad
|
||||||
cm.sendOk("You do not meet the criteria to take attempt Crimsonwood Keep Party Quest!");
|
cm.sendOk("You do not meet the criteria to take attempt Crimsonwood Keep Party Quest!");
|
||||||
cm.dispose();
|
cm.dispose();
|
||||||
} else if (expedition == null) { //Start an expedition
|
} else if (expedition == null) { //Start an expedition
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ function action(mode, type, selection) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
if (player.getLevel() < exped.getMinLevel() && player.getLevel() > exped.getMaxLevel()) { //Don't fit requirement
|
if (player.getLevel() < exped.getMinLevel() || player.getLevel() > exped.getMaxLevel()) { //Don't fit requirement, thanks Conrad
|
||||||
cm.sendOk("You do not meet the criteria to battle " + expedBoss + "!");
|
cm.sendOk("You do not meet the criteria to battle " + expedBoss + "!");
|
||||||
cm.dispose();
|
cm.dispose();
|
||||||
} else if (expedition == null) { //Start an expedition
|
} else if (expedition == null) { //Start an expedition
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ function writeFeatureTab_Skills() {
|
|||||||
addFeature("Maker skill features properly developed.");
|
addFeature("Maker skill features properly developed.");
|
||||||
addFeature("Chair Mastery - map chair boosts HP/MP rec.");
|
addFeature("Chair Mastery - map chair boosts HP/MP rec.");
|
||||||
addFeature("Mu Lung Dojo skills functional.");
|
addFeature("Mu Lung Dojo skills functional.");
|
||||||
|
addFeature("Monster Magnet skill no longer crashes players.");
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeFeatureTab_Quests() {
|
function writeFeatureTab_Quests() {
|
||||||
@@ -72,6 +73,7 @@ function writeFeatureTab_Quests() {
|
|||||||
addFeature("Reviewed several 4th job skill questlines.");
|
addFeature("Reviewed several 4th job skill questlines.");
|
||||||
addFeature("Rewarding system now looks up for item stacking.");
|
addFeature("Rewarding system now looks up for item stacking.");
|
||||||
addFeature("3rd job quiz with all 40-question pool available.");
|
addFeature("3rd job quiz with all 40-question pool available.");
|
||||||
|
addFeature("Item raising functional.");
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeFeatureTab_PlayerSocialNetwork() {
|
function writeFeatureTab_PlayerSocialNetwork() {
|
||||||
@@ -113,6 +115,7 @@ function writeFeatureTab_CashItems() {
|
|||||||
addFeature("Reviewed an pet position issue within CASH inventory.");
|
addFeature("Reviewed an pet position issue within CASH inventory.");
|
||||||
addFeature("Reviewed fashion-related contents, almost GMS-like.");
|
addFeature("Reviewed fashion-related contents, almost GMS-like.");
|
||||||
addFeature("Plastic surgeons/stylists no longer stuck characters.");
|
addFeature("Plastic surgeons/stylists no longer stuck characters.");
|
||||||
|
addFeature("Reworked gachapon loots, website-lists lookalike.");
|
||||||
addFeature("Scroll for Spikes on Shoes.");
|
addFeature("Scroll for Spikes on Shoes.");
|
||||||
addFeature("Scroll for Cold Protection.");
|
addFeature("Scroll for Cold Protection.");
|
||||||
addFeature("Vega's spell.");
|
addFeature("Vega's spell.");
|
||||||
|
|||||||
@@ -26,12 +26,12 @@
|
|||||||
|
|
||||||
var status;
|
var status;
|
||||||
var ticketId = 5220000;
|
var ticketId = 5220000;
|
||||||
var mapName = ["Henesys", "Ellinia", "Perion", "Kerning City", "Sleepywood", "Mushroom Shrine", "Showa Spa (M)", "Showa Spa (F)", "New Leaf City", "Nautilus"];
|
var mapName = ["Henesys", "Ellinia", "Perion", "Kerning City", "Sleepywood", "Mushroom Shrine", "Showa Spa (M)", "Showa Spa (F)", "Ludibrium", "New Leaf City", "El Nath", "Nautilus"];
|
||||||
var curMapName = "";
|
var curMapName = "";
|
||||||
|
|
||||||
function start() {
|
function start() {
|
||||||
status = -1;
|
status = -1;
|
||||||
curMapName = mapName[(cm.getNpc() != 9100117 && cm.getNpc() != 9100109) ? (cm.getNpc() - 9100100) : cm.getNpc() == 9100109 ? 8 : 9];
|
curMapName = mapName[(cm.getNpc() != 9100117 && cm.getNpc() != 9100109) ? (cm.getNpc() - 9100100) : cm.getNpc() == 9100109 ? 9 : 11];
|
||||||
|
|
||||||
action(1, 0, 0);
|
action(1, 0, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the HeavenMS MapleStory Server
|
||||||
|
Copyleft (L) 2016 - 2018 RonanLana
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as
|
||||||
|
published by the Free Software Foundation version 3 as published by
|
||||||
|
the Free Software Foundation. You may not use, modify or distribute
|
||||||
|
this program under any other version of the GNU Affero General Public
|
||||||
|
License.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @author: Ronan
|
||||||
|
* @npc: Pio
|
||||||
|
* @func: Gachapon Loot Announcer
|
||||||
|
*/
|
||||||
|
|
||||||
|
var status;
|
||||||
|
var gachaMessages;
|
||||||
|
|
||||||
|
function start() {
|
||||||
|
gachaMessages = Packages.server.gachapon.MapleGachapon.Gachapon.getLootInfo();
|
||||||
|
gachas = Packages.server.gachapon.MapleGachapon.Gachapon.values();
|
||||||
|
|
||||||
|
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) {
|
||||||
|
var sendStr = "Hi, #r#p" + cm.getNpc() + "##k here! I'm announcing all obtainable loots from the Gachapons. Which Gachapon machine would you like to look?\r\n\r\n#b" + gachaMessages[0] + "#k";
|
||||||
|
cm.sendSimple(sendStr);
|
||||||
|
} else if(status == 1) {
|
||||||
|
var sendStr = "Loots from #b" + gachas[selection].name() + "#k:\r\n\r\n" + gachaMessages[selection + 1];
|
||||||
|
cm.sendPrev(sendStr);
|
||||||
|
} else if(status == 2) {
|
||||||
|
cm.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,18 +22,21 @@ function enter(pi) {
|
|||||||
else if(pi.isQuestStarted(2332) && pi.hasItem(4032388)){
|
else if(pi.isQuestStarted(2332) && pi.hasItem(4032388)){
|
||||||
pi.forceCompleteQuest(2332, 1300002);
|
pi.forceCompleteQuest(2332, 1300002);
|
||||||
pi.getPlayer().message("You've found the princess!");
|
pi.getPlayer().message("You've found the princess!");
|
||||||
pi.giveCharacterExp(4400 * 1.5, pi.getPlayer());
|
pi.giveCharacterExp(4400, pi.getPlayer());
|
||||||
|
|
||||||
var em = pi.getEventManager("MK_PrimeMinister");
|
var em = pi.getEventManager("MK_PrimeMinister");
|
||||||
var party = pi.getPlayer().getParty();
|
var party = pi.getPlayer().getParty();
|
||||||
if (party != null) {
|
if (party != null) {
|
||||||
if (em.startInstance(party, pi.getMap())) {
|
var eli = em.getEligibleParty(pi.getParty()); // thanks Conrad for pointing out missing eligible party declaration here
|
||||||
|
if(eli.size() > 0) {
|
||||||
|
if (em.startInstance(party, pi.getMap(), 1)) {
|
||||||
pi.playPortalSound();
|
pi.playPortalSound();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
pi.message("Another party is already challenging the boss in this channel.");
|
pi.message("Another party is already challenging the boss in this channel.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (em.startInstance(pi.getPlayer())) { // thanks RedHat for noticing an issue here
|
if (em.startInstance(pi.getPlayer())) { // thanks RedHat for noticing an issue here
|
||||||
pi.playPortalSound();
|
pi.playPortalSound();
|
||||||
@@ -49,13 +52,16 @@ function enter(pi) {
|
|||||||
|
|
||||||
var party = pi.getPlayer().getParty();
|
var party = pi.getPlayer().getParty();
|
||||||
if (party != null) {
|
if (party != null) {
|
||||||
if (em.startInstance(1, party, pi.getMap())) {
|
var eli = em.getEligibleParty(pi.getParty());
|
||||||
|
if(eli.size() > 0) {
|
||||||
|
if (em.startInstance(party, pi.getMap(), 1)) {
|
||||||
pi.playPortalSound();
|
pi.playPortalSound();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
pi.message("Another party is already challenging the boss in this channel.");
|
pi.message("Another party is already challenging the boss in this channel.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (em.startInstance(pi.getPlayer())) {
|
if (em.startInstance(pi.getPlayer())) {
|
||||||
pi.playPortalSound();
|
pi.playPortalSound();
|
||||||
|
|||||||
@@ -20,11 +20,20 @@
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
function enter(pi) {
|
function enter(pi) {
|
||||||
if(!pi.isQuestCompleted(3706)) {
|
if (pi.isQuestCompleted(3706)) {
|
||||||
pi.playPortalSound(); pi.warp(240040611, "out00");
|
|
||||||
} else {
|
|
||||||
pi.playPortalSound(); pi.warp(240040612, "out00");
|
pi.playPortalSound(); pi.warp(240040612, "out00");
|
||||||
}
|
return true;
|
||||||
|
} else if (pi.isQuestStarted(100203) || pi.getPlayer().haveItem(4001094)) {
|
||||||
|
var em = pi.getEventManager("NineSpirit");
|
||||||
|
if (!em.startInstance(pi.getPlayer())) {
|
||||||
|
pi.message("There is currently someone in this map, come back later.");
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
pi.playPortalSound();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
pi.message("A strange force is blocking you from entering.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,12 @@
|
|||||||
function enter(pi) {
|
function enter(pi) {
|
||||||
|
if(!pi.isQuestCompleted(2335) && !(pi.isQuestStarted(2335) && pi.hasItem(4032405))){
|
||||||
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.");
|
pi.getPlayer().message("The door is locked securely. I will need a key if I want to go in there.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pi.isQuestStarted(2335) && pi.hasItem(4032405)){
|
if(pi.isQuestStarted(2335)){
|
||||||
pi.forceCompleteQuest(2335, 1300002);
|
pi.forceCompleteQuest(2335, 1300002);
|
||||||
pi.giveCharacterExp(5000 * 1.5, pi.getPlayer());
|
pi.giveCharacterExp(5000, pi.getPlayer());
|
||||||
pi.gainItem(4032405, -1);
|
pi.gainItem(4032405, -1);
|
||||||
}
|
}
|
||||||
pi.playPortalSound();
|
pi.playPortalSound();
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
function enter(pi) {
|
function enter(pi) {
|
||||||
if (pi.isQuestActive(2324)) {
|
if (pi.isQuestCompleted(2324)) {
|
||||||
var player = pi.getPlayer();
|
|
||||||
player.gainExp(3300 * player.getExpRate());
|
|
||||||
|
|
||||||
pi.forceCompleteQuest(2324);
|
|
||||||
pi.removeAll(2430015);
|
|
||||||
pi.playerMessage(5, "You have used the Thorn Remover to clear the path.");
|
|
||||||
}
|
|
||||||
pi.playPortalSound(); pi.warp(106020501,0);
|
pi.playPortalSound(); pi.warp(106020501,0);
|
||||||
return true;
|
return true;
|
||||||
|
} else {
|
||||||
|
pi.playerMessage(5, "The path ahead is covered with sprawling vine thorns, only a Thorn Remover to clear this out...");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -5,17 +5,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function enter(pi){
|
function enter(pi){
|
||||||
if (pi.isQuestCompleted(2316)) {
|
if (pi.isQuestStarted(100202)) {
|
||||||
if (pi.hasItem(2430014)) {
|
|
||||||
pi.gainItem(2430014, -1 * pi.getPlayer().getItemQuantity(2430014, false));
|
|
||||||
pi.message("You have used the Killer Mushroom Spore to open the way.");
|
|
||||||
}
|
|
||||||
|
|
||||||
pi.playPortalSound(); pi.warp(106020400, 2);
|
pi.playPortalSound(); pi.warp(106020400, 2);
|
||||||
return true;
|
return true;
|
||||||
} else if (pi.hasItem(2430015)) {
|
} else if (pi.hasItem(4000507)) {
|
||||||
pi.gainItem(2430015, -1 * pi.getPlayer().getItemQuantity(2430015, false));
|
pi.gainItem(4000507, -1);
|
||||||
pi.message("You have used the Thorn Remover to clean the way.");
|
pi.message("You have used a Poison Spore to pass through the barrier.");
|
||||||
|
|
||||||
pi.playPortalSound(); pi.warp(106020400, 2);
|
pi.playPortalSound(); pi.warp(106020400, 2);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ var status = -1;
|
|||||||
function start(mode, type, selection){
|
function start(mode, type, selection){
|
||||||
if(qm.hasItem(4032388) && !qm.isQuestStarted(2332)){
|
if(qm.hasItem(4032388) && !qm.isQuestStarted(2332)){
|
||||||
qm.forceStartQuest();
|
qm.forceStartQuest();
|
||||||
qm.getPlayer().showHint("I must find Violetta. (quest started)");
|
qm.getPlayer().showHint("I must find Violetta!! (#bquest started#k)");
|
||||||
}
|
}
|
||||||
qm.dispose();
|
qm.dispose();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ Dragon nest
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function sendToHeaven() {
|
function sendToHeaven() {
|
||||||
rm.destroyNpc(2081008);
|
rm.spawnNpc(2081008);
|
||||||
rm.mapMessage(6, "In a flicker of light, Nine Spirit's Little Dragon returns to the place it belongs, high above the skies.");
|
rm.startQuest(100203);
|
||||||
rm.getReactor().getMap().resetReactors();
|
rm.mapMessage(6, "In a flicker of light the egg has matured and cracked, thus born a radiant baby dragon.");
|
||||||
}
|
}
|
||||||
|
|
||||||
function touch() {
|
function touch() {
|
||||||
@@ -18,6 +18,5 @@ function touch() {
|
|||||||
function untouch() {}
|
function untouch() {}
|
||||||
|
|
||||||
function act() {
|
function act() {
|
||||||
rm.spawnNpc(2081008);
|
sendToHeaven(); // thanks Conrad for pointing out the GMS-like way of Nine Spirit's Nest
|
||||||
rm.schedule("sendToHeaven", 12 * 1000);
|
|
||||||
}
|
}
|
||||||
+6
-54
@@ -16,8 +16,8 @@ CREATE TABLE IF NOT EXISTS `accounts` (
|
|||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
`name` varchar(13) NOT NULL DEFAULT '',
|
`name` varchar(13) NOT NULL DEFAULT '',
|
||||||
`password` varchar(128) NOT NULL DEFAULT '',
|
`password` varchar(128) NOT NULL DEFAULT '',
|
||||||
`pin` varchar(10) DEFAULT NULL,
|
`pin` varchar(10) NOT NULL DEFAULT '',
|
||||||
`pic` varchar(26) DEFAULT NULL,
|
`pic` varchar(26) NOT NULL DEFAULT '',
|
||||||
`loggedin` tinyint(4) NOT NULL DEFAULT '0',
|
`loggedin` tinyint(4) NOT NULL DEFAULT '0',
|
||||||
`lastlogin` timestamp NULL DEFAULT NULL,
|
`lastlogin` timestamp NULL DEFAULT NULL,
|
||||||
`createdat` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
`createdat` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
@@ -9474,7 +9474,7 @@ INSERT IGNORE INTO `temp_data` (`dropperid`, `itemid`, `minimum_quantity`, `maxi
|
|||||||
(3300001, 4130009, 1, 1, 0, 6000),
|
(3300001, 4130009, 1, 1, 0, 6000),
|
||||||
(3300001, 4130021, 1, 1, 0, 6000),
|
(3300001, 4130021, 1, 1, 0, 6000),
|
||||||
(3300001, 4000500, 1, 1, 0, 600000),
|
(3300001, 4000500, 1, 1, 0, 600000),
|
||||||
(3300001, 4000507, 1, 1, 0, 600000),
|
(3300001, 4000507, 1, 1, 0, 100000),
|
||||||
(3300001, 2044024, 1, 1, 0, 300),
|
(3300001, 2044024, 1, 1, 0, 300),
|
||||||
(3300001, 2044116, 1, 1, 0, 300),
|
(3300001, 2044116, 1, 1, 0, 300),
|
||||||
(3300001, 2382093, 1, 1, 0, 20000),
|
(3300001, 2382093, 1, 1, 0, 20000),
|
||||||
@@ -12800,30 +12800,9 @@ INSERT INTO `drop_data_global` (`id`, `continent`, `itemid`, `minimum_quantity`,
|
|||||||
CREATE TABLE IF NOT EXISTS `dueyitems` (
|
CREATE TABLE IF NOT EXISTS `dueyitems` (
|
||||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
`PackageId` int(10) unsigned NOT NULL DEFAULT '0',
|
`PackageId` int(10) unsigned NOT NULL DEFAULT '0',
|
||||||
`itemid` int(10) unsigned NOT NULL DEFAULT '0',
|
`inventoryitemid` int(10) unsigned NOT NULL DEFAULT '0',
|
||||||
`quantity` int(10) unsigned NOT NULL DEFAULT '0',
|
|
||||||
`upgradeslots` int(11) DEFAULT '0',
|
|
||||||
`level` int(11) DEFAULT '0',
|
|
||||||
`itemlevel` int(11) DEFAULT '0',
|
|
||||||
`itemexp` int(11) DEFAULT '0',
|
|
||||||
`str` int(11) DEFAULT '0',
|
|
||||||
`dex` int(11) DEFAULT '0',
|
|
||||||
`int` int(11) DEFAULT '0',
|
|
||||||
`luk` int(11) DEFAULT '0',
|
|
||||||
`hp` int(11) DEFAULT '0',
|
|
||||||
`mp` int(11) DEFAULT '0',
|
|
||||||
`watk` int(11) DEFAULT '0',
|
|
||||||
`matk` int(11) DEFAULT '0',
|
|
||||||
`wdef` int(11) DEFAULT '0',
|
|
||||||
`mdef` int(11) DEFAULT '0',
|
|
||||||
`acc` int(11) DEFAULT '0',
|
|
||||||
`avoid` int(11) DEFAULT '0',
|
|
||||||
`hands` int(11) DEFAULT '0',
|
|
||||||
`speed` int(11) DEFAULT '0',
|
|
||||||
`jump` int(11) DEFAULT '0',
|
|
||||||
`flag` int(11) DEFAULT '0',
|
|
||||||
`owner` varchar(13) DEFAULT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `INVENTORYITEMID` (`inventoryitemid`),
|
||||||
KEY `PackageId` (`PackageId`)
|
KEY `PackageId` (`PackageId`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
|
||||||
|
|
||||||
@@ -12833,8 +12812,8 @@ CREATE TABLE IF NOT EXISTS `dueypackages` (
|
|||||||
`SenderName` varchar(13) NOT NULL,
|
`SenderName` varchar(13) NOT NULL,
|
||||||
`Mesos` int(10) unsigned DEFAULT '0',
|
`Mesos` int(10) unsigned DEFAULT '0',
|
||||||
`TimeStamp` varchar(10) NOT NULL,
|
`TimeStamp` varchar(10) NOT NULL,
|
||||||
|
`Message` varchar(200) NOT NULL DEFAULT "",
|
||||||
`Checked` tinyint(1) unsigned DEFAULT '1',
|
`Checked` tinyint(1) unsigned DEFAULT '1',
|
||||||
`Type` tinyint(1) unsigned NOT NULL,
|
|
||||||
PRIMARY KEY (`PackageId`)
|
PRIMARY KEY (`PackageId`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
|
||||||
|
|
||||||
@@ -12909,33 +12888,6 @@ CREATE TABLE IF NOT EXISTS `guilds` (
|
|||||||
INDEX (guildid, name)
|
INDEX (guildid, name)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `hiredmerchant` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`ownerid` int(11) DEFAULT '0',
|
|
||||||
`itemid` int(10) unsigned NOT NULL DEFAULT '0',
|
|
||||||
`quantity` int(10) unsigned NOT NULL DEFAULT '0',
|
|
||||||
`upgradeslots` int(11) DEFAULT '0',
|
|
||||||
`level` int(11) DEFAULT '0',
|
|
||||||
`str` int(11) DEFAULT '0',
|
|
||||||
`dex` int(11) DEFAULT '0',
|
|
||||||
`int` int(11) DEFAULT '0',
|
|
||||||
`luk` int(11) DEFAULT '0',
|
|
||||||
`hp` int(11) DEFAULT '0',
|
|
||||||
`mp` int(11) DEFAULT '0',
|
|
||||||
`watk` int(11) DEFAULT '0',
|
|
||||||
`matk` int(11) DEFAULT '0',
|
|
||||||
`wdef` int(11) DEFAULT '0',
|
|
||||||
`mdef` int(11) DEFAULT '0',
|
|
||||||
`acc` int(11) DEFAULT '0',
|
|
||||||
`avoid` int(11) DEFAULT '0',
|
|
||||||
`hands` int(11) DEFAULT '0',
|
|
||||||
`speed` int(11) DEFAULT '0',
|
|
||||||
`jump` int(11) DEFAULT '0',
|
|
||||||
`owner` varchar(13) DEFAULT '',
|
|
||||||
`type` tinyint(1) unsigned NOT NULL,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `hwidaccounts` (
|
CREATE TABLE IF NOT EXISTS `hwidaccounts` (
|
||||||
`accountid` int(11) NOT NULL DEFAULT '0',
|
`accountid` int(11) NOT NULL DEFAULT '0',
|
||||||
`hwid` varchar(40) NOT NULL DEFAULT '',
|
`hwid` varchar(40) NOT NULL DEFAULT '',
|
||||||
|
|||||||
+1
-1
@@ -2751,7 +2751,7 @@ USE `heavenms`;
|
|||||||
(3300000, 1082046, 1, 1, 0, 700),
|
(3300000, 1082046, 1, 1, 0, 700),
|
||||||
(3300000, 1002622, 1, 1, 0, 700),
|
(3300000, 1002622, 1, 1, 0, 700),
|
||||||
(3300001, 4000500, 1, 1, 0, 200000),
|
(3300001, 4000500, 1, 1, 0, 200000),
|
||||||
(3300001, 4000507, 1, 1, 0, 200000),
|
(3300001, 4000507, 1, 1, 0, 100000),
|
||||||
(3300001, 4130021, 1, 1, 0, 3000),
|
(3300001, 4130021, 1, 1, 0, 3000),
|
||||||
(3300001, 2382093, 1, 1, 0, 20000),
|
(3300001, 2382093, 1, 1, 0, 20000),
|
||||||
(3300001, 2044701, 1, 1, 0, 750),
|
(3300001, 2044701, 1, 1, 0, 750),
|
||||||
|
|||||||
+75
-74
@@ -182,80 +182,81 @@ INSERT INTO `shopitems` ( `shopid`, `itemid`, `price`, `position`) VALUES
|
|||||||
(1337, 2100003, 1, 9),
|
(1337, 2100003, 1, 9),
|
||||||
(1337, 2100002, 1, 10),
|
(1337, 2100002, 1, 10),
|
||||||
(1337, 2100001, 1, 11),
|
(1337, 2100001, 1, 11),
|
||||||
(1337, 1002140, 1, 12),
|
(1337, 1002959, 1, 12),
|
||||||
(1337, 1042003, 1, 13),
|
(1337, 1002140, 1, 13),
|
||||||
(1337, 1062007, 1, 14),
|
(1337, 1042003, 1, 14),
|
||||||
(1337, 1322013, 1, 15),
|
(1337, 1062007, 1, 15),
|
||||||
(1337, 1072010, 1, 16),
|
(1337, 1322013, 1, 16),
|
||||||
(1337, 2022179, 1, 17),
|
(1337, 1072010, 1, 17),
|
||||||
(1337, 2022273, 1, 18),
|
(1337, 2022179, 1, 18),
|
||||||
(1337, 2041200, 1, 19),
|
(1337, 2022273, 1, 19),
|
||||||
(1337, 4006001, 1, 20),
|
(1337, 2041200, 1, 20),
|
||||||
(1337, 4001017, 1, 21),
|
(1337, 4006001, 1, 21),
|
||||||
(1337, 4031179, 1, 22),
|
(1337, 4001017, 1, 22),
|
||||||
(1337, 2070018, 1, 23),
|
(1337, 4031179, 1, 23),
|
||||||
(1337, 2060004, 1, 24),
|
(1337, 2070018, 1, 24),
|
||||||
(1337, 2061004, 1, 25),
|
(1337, 2060004, 1, 25),
|
||||||
(1337, 2330005, 1, 26),
|
(1337, 2061004, 1, 26),
|
||||||
(1337, 2332000, 1, 27),
|
(1337, 2330005, 1, 27),
|
||||||
(1337, 2331000, 1, 28),
|
(1337, 2332000, 1, 28),
|
||||||
(1337, 5072000, 1, 29),
|
(1337, 2331000, 1, 29),
|
||||||
(1337, 5390000, 1, 30),
|
(1337, 5072000, 1, 30),
|
||||||
(1337, 5390001, 1, 31),
|
(1337, 5390000, 1, 31),
|
||||||
(1337, 5390002, 1, 32),
|
(1337, 5390001, 1, 32),
|
||||||
(1337, 5390005, 1, 33),
|
(1337, 5390002, 1, 33),
|
||||||
(1337, 5390006, 1, 34),
|
(1337, 5390005, 1, 34),
|
||||||
(1337, 1492013, 1, 35),
|
(1337, 5390006, 1, 35),
|
||||||
(1337, 1482013, 1, 36),
|
(1337, 1492013, 1, 36),
|
||||||
(1337, 1452044, 1, 37),
|
(1337, 1482013, 1, 37),
|
||||||
(1337, 1472052, 1, 38),
|
(1337, 1452044, 1, 38),
|
||||||
(1337, 1462039, 1, 39),
|
(1337, 1472052, 1, 39),
|
||||||
(1337, 1332050, 1, 40),
|
(1337, 1462039, 1, 40),
|
||||||
(1337, 1312031, 1, 41),
|
(1337, 1332050, 1, 41),
|
||||||
(1337, 1322052, 1, 42),
|
(1337, 1312031, 1, 42),
|
||||||
(1337, 1302059, 1, 43),
|
(1337, 1322052, 1, 43),
|
||||||
(1337, 1442045, 1, 44),
|
(1337, 1302059, 1, 44),
|
||||||
(1337, 1432038, 1, 45),
|
(1337, 1442045, 1, 45),
|
||||||
(1337, 1382036, 1, 46),
|
(1337, 1432038, 1, 46),
|
||||||
(1337, 1412026, 1, 47),
|
(1337, 1382036, 1, 47),
|
||||||
(1337, 1422028, 1, 48),
|
(1337, 1412026, 1, 48),
|
||||||
(1337, 1402036, 1, 49),
|
(1337, 1422028, 1, 49),
|
||||||
(1337, 1372032, 1, 50),
|
(1337, 1402036, 1, 50),
|
||||||
(1337, 1122000, 1, 51),
|
(1337, 1372032, 1, 51),
|
||||||
(1337, 1082149, 1, 52),
|
(1337, 1122000, 1, 52),
|
||||||
(1337, 1912000, 1, 53),
|
(1337, 1082149, 1, 53),
|
||||||
(1337, 1902000, 1, 54),
|
(1337, 1912000, 1, 54),
|
||||||
(1337, 1902001, 1, 55),
|
(1337, 1902000, 1, 55),
|
||||||
(1337, 1902002, 1, 56),
|
(1337, 1902001, 1, 56),
|
||||||
(1337, 1912005, 1, 57),
|
(1337, 1902002, 1, 57),
|
||||||
(1337, 1902005, 1, 58),
|
(1337, 1912005, 1, 58),
|
||||||
(1337, 1902006, 1, 59),
|
(1337, 1902005, 1, 59),
|
||||||
(1337, 1902007, 1, 60),
|
(1337, 1902006, 1, 60),
|
||||||
(1337, 1912011, 1, 61),
|
(1337, 1902007, 1, 61),
|
||||||
(1337, 1902015, 1, 62),
|
(1337, 1912011, 1, 62),
|
||||||
(1337, 1902016, 1, 63),
|
(1337, 1902015, 1, 63),
|
||||||
(1337, 1902017, 1, 64),
|
(1337, 1902016, 1, 64),
|
||||||
(1337, 1902018, 1, 65),
|
(1337, 1902017, 1, 65),
|
||||||
(1337, 2044908, 1, 66),
|
(1337, 1902018, 1, 66),
|
||||||
(1337, 2044815, 1, 67),
|
(1337, 2044908, 1, 67),
|
||||||
(1337, 2044512, 1, 68),
|
(1337, 2044815, 1, 68),
|
||||||
(1337, 2044712, 1, 69),
|
(1337, 2044512, 1, 69),
|
||||||
(1337, 2044612, 1, 70),
|
(1337, 2044712, 1, 70),
|
||||||
(1337, 2043312, 1, 71),
|
(1337, 2044612, 1, 71),
|
||||||
(1337, 2043117, 1, 72),
|
(1337, 2043312, 1, 72),
|
||||||
(1337, 2043217, 1, 73),
|
(1337, 2043117, 1, 73),
|
||||||
(1337, 2043023, 1, 74),
|
(1337, 2043217, 1, 74),
|
||||||
(1337, 2044417, 1, 75),
|
(1337, 2043023, 1, 75),
|
||||||
(1337, 2044317, 1, 76),
|
(1337, 2044417, 1, 76),
|
||||||
(1337, 2043812, 1, 77),
|
(1337, 2044317, 1, 77),
|
||||||
(1337, 2044117, 1, 78),
|
(1337, 2043812, 1, 78),
|
||||||
(1337, 2044217, 1, 79),
|
(1337, 2044117, 1, 79),
|
||||||
(1337, 2044025, 1, 80),
|
(1337, 2044217, 1, 80),
|
||||||
(1337, 2043712, 1, 81),
|
(1337, 2044025, 1, 81),
|
||||||
(1337, 2340000, 1, 82),
|
(1337, 2043712, 1, 82),
|
||||||
(1337, 2040807, 1, 83),
|
(1337, 2340000, 1, 83),
|
||||||
(1337, 2210032, 1, 84),
|
(1337, 2040807, 1, 84),
|
||||||
(1337, 2050004, 1, 85);
|
(1337, 2210032, 1, 85),
|
||||||
|
(1337, 2050004, 1, 86);
|
||||||
|
|
||||||
-- Thanks to DietStory v1.02 dev team
|
-- Thanks to DietStory v1.02 dev team
|
||||||
INSERT INTO `shopitems` ( `shopid`, `itemid`, `price`, `pitch`, `position`) VALUES
|
INSERT INTO `shopitems` ( `shopid`, `itemid`, `price`, `pitch`, `position`) VALUES
|
||||||
|
|||||||
@@ -84,13 +84,12 @@ import server.events.gm.MapleFitness;
|
|||||||
import server.events.gm.MapleOla;
|
import server.events.gm.MapleOla;
|
||||||
import server.life.MapleMonster;
|
import server.life.MapleMonster;
|
||||||
import server.life.MobSkill;
|
import server.life.MobSkill;
|
||||||
import server.loot.MapleLootManager;
|
|
||||||
import server.maps.MapleHiredMerchant;
|
import server.maps.MapleHiredMerchant;
|
||||||
import server.maps.MapleDoor;
|
import server.maps.MapleDoor;
|
||||||
import server.maps.MapleDragon;
|
import server.maps.MapleDragon;
|
||||||
import server.maps.MapleMap;
|
import server.maps.MapleMap;
|
||||||
import server.maps.MapleMapEffect;
|
import server.maps.MapleMapEffect;
|
||||||
import server.maps.MapleMapFactory;
|
import server.maps.MapleMapManager;
|
||||||
import server.maps.MapleMapObject;
|
import server.maps.MapleMapObject;
|
||||||
import server.maps.MapleMapObjectType;
|
import server.maps.MapleMapObjectType;
|
||||||
import server.maps.MapleMiniGame;
|
import server.maps.MapleMiniGame;
|
||||||
@@ -206,7 +205,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
|||||||
private transient int localstr, localdex, localluk, localint_, localmagic, localwatk;
|
private transient int localstr, localdex, localluk, localint_, localmagic, localwatk;
|
||||||
private transient int equipmaxhp, equipmaxmp, equipstr, equipdex, equipluk, equipint_, equipmagic, equipwatk, localchairhp, localchairmp;
|
private transient int equipmaxhp, equipmaxmp, equipstr, equipdex, equipluk, equipint_, equipmagic, equipwatk, localchairhp, localchairmp;
|
||||||
private int localchairrate;
|
private int localchairrate;
|
||||||
private boolean hidden, equipchanged = true, canDoor = true, berserk, hasMerchant, hasSandboxItem = false, whiteChat = false, canRecvPartySearchInvite = true;
|
private boolean hidden, equipchanged = true, berserk, hasMerchant, hasSandboxItem = false, whiteChat = false, canRecvPartySearchInvite = true;
|
||||||
private boolean equippedMesoMagnet = false, equippedItemPouch = false, equippedPetItemIgnore = false;
|
private boolean equippedMesoMagnet = false, equippedItemPouch = false, equippedPetItemIgnore = false;
|
||||||
private int linkedLevel = 0;
|
private int linkedLevel = 0;
|
||||||
private String linkedName = null;
|
private String linkedName = null;
|
||||||
@@ -961,7 +960,8 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean canDoor() {
|
public boolean canDoor() {
|
||||||
return canDoor;
|
MapleDoor door = getPlayerDoor();
|
||||||
|
return door == null || (door.isActive() && door.getElapsedDeployTime() > 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHasSandboxItem() {
|
public void setHasSandboxItem() {
|
||||||
@@ -2297,6 +2297,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
deleteQuestProgressWhereCharacterId(con, cid);
|
deleteQuestProgressWhereCharacterId(con, cid);
|
||||||
|
FredrickProcessor.removeFredrickLog(cid); // thanks maple006 for pointing out the player's Fredrick items are not being deleted at character deletion
|
||||||
|
|
||||||
try (PreparedStatement ps = con.prepareStatement("SELECT id FROM mts_cart WHERE cid = ?")) {
|
try (PreparedStatement ps = con.prepareStatement("SELECT id FROM mts_cart WHERE cid = ?")) {
|
||||||
ps.setInt(1, cid);
|
ps.setInt(1, cid);
|
||||||
@@ -2521,19 +2522,6 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
|||||||
}, healInterval, healInterval);
|
}, healInterval, healInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disableDoorSpawn() {
|
|
||||||
canDoor = false;
|
|
||||||
|
|
||||||
Runnable r = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
canDoor = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
client.getChannelServer().registerOverallAction(mapid, r, 5000);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void disbandGuild() {
|
public void disbandGuild() {
|
||||||
if (guildid < 1 || guildRank != 1) {
|
if (guildid < 1 || guildRank != 1) {
|
||||||
return;
|
return;
|
||||||
@@ -3500,7 +3488,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
|||||||
for(Entry<Integer, Map<MapleBuffStat, MapleBuffStatValueHolder>> bpl: buffEffects.entrySet()) {
|
for(Entry<Integer, Map<MapleBuffStat, MapleBuffStatValueHolder>> bpl: buffEffects.entrySet()) {
|
||||||
MapleBuffStatValueHolder mbsvhi = bpl.getValue().get(mbs);
|
MapleBuffStatValueHolder mbsvhi = bpl.getValue().get(mbs);
|
||||||
if(mbsvhi != null) {
|
if(mbsvhi != null) {
|
||||||
if(!mbsvhi.effect.isActive(mapid)) {
|
if(!mbsvhi.effect.isActive(this)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3725,17 +3713,57 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateActiveEffects() {
|
private static MapleStatEffect getEffectFromBuffSource(Map<MapleBuffStat, MapleBuffStatValueHolder> buffSource) {
|
||||||
chrLock.lock();
|
|
||||||
try {
|
try {
|
||||||
effects.clear();
|
return buffSource.entrySet().iterator().next().getValue().effect;
|
||||||
updateEffects(buffEffectsCount.keySet());
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isUpdatingEffect(Set<MapleStatEffect> activeEffects, MapleStatEffect mse) {
|
||||||
|
if (mse == null) return false;
|
||||||
|
|
||||||
|
// thanks xinyifly for noticing "Speed Infusion" crashing game when updating buffs during map transition
|
||||||
|
boolean active = mse.isActive(this);
|
||||||
|
if (active) {
|
||||||
|
return !activeEffects.contains(mse);
|
||||||
|
} else {
|
||||||
|
return activeEffects.contains(mse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateActiveEffects() {
|
||||||
|
effLock.lock(); // thanks davidlafriniere, maple006, RedHat for pointing a deadlock occurring here
|
||||||
|
try {
|
||||||
|
Set<MapleBuffStat> updatedBuffs = new LinkedHashSet<>();
|
||||||
|
Set<MapleStatEffect> activeEffects = new LinkedHashSet<>();
|
||||||
|
|
||||||
|
for (MapleBuffStatValueHolder mse : effects.values()) {
|
||||||
|
activeEffects.add(mse.effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Map<MapleBuffStat, MapleBuffStatValueHolder> buff : buffEffects.values()) {
|
||||||
|
MapleStatEffect mse = getEffectFromBuffSource(buff);
|
||||||
|
if (isUpdatingEffect(activeEffects, mse)) {
|
||||||
|
for (Pair<MapleBuffStat, Integer> p : mse.getStatups()) {
|
||||||
|
updatedBuffs.add(p.getLeft());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (MapleBuffStat mbs : updatedBuffs) {
|
||||||
|
effects.remove(mbs);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateEffects(updatedBuffs);
|
||||||
} finally {
|
} finally {
|
||||||
chrLock.unlock();
|
effLock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateEffects(Set<MapleBuffStat> removedStats) {
|
private void updateEffects(Set<MapleBuffStat> removedStats) {
|
||||||
|
effLock.lock();
|
||||||
chrLock.lock();
|
chrLock.lock();
|
||||||
try {
|
try {
|
||||||
Set<MapleBuffStat> retrievedStats = new LinkedHashSet<>();
|
Set<MapleBuffStat> retrievedStats = new LinkedHashSet<>();
|
||||||
@@ -3754,6 +3782,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
|||||||
propagateBuffEffectUpdates(new LinkedHashMap<Integer, Pair<MapleStatEffect, Long>>(), retrievedStats, removedStats);
|
propagateBuffEffectUpdates(new LinkedHashMap<Integer, Pair<MapleStatEffect, Long>>(), retrievedStats, removedStats);
|
||||||
} finally {
|
} finally {
|
||||||
chrLock.unlock();
|
chrLock.unlock();
|
||||||
|
effLock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3783,29 +3812,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (effect.isMagicDoor()) {
|
if (effect.isMagicDoor()) {
|
||||||
MapleDoor destroyDoor = removePartyDoor(false);
|
MapleDoor.attemptRemoveDoor(this);
|
||||||
|
|
||||||
if (destroyDoor != null) {
|
|
||||||
destroyDoor.getTarget().removeMapObject(destroyDoor.getAreaDoor());
|
|
||||||
destroyDoor.getTown().removeMapObject(destroyDoor.getTownDoor());
|
|
||||||
|
|
||||||
for (MapleCharacter chr : destroyDoor.getTarget().getCharacters()) {
|
|
||||||
destroyDoor.getAreaDoor().sendDestroyData(chr.getClient());
|
|
||||||
}
|
|
||||||
|
|
||||||
Collection<MapleCharacter> townChars = destroyDoor.getTown().getCharacters();
|
|
||||||
for (MapleCharacter chr : townChars) {
|
|
||||||
destroyDoor.getTownDoor().sendDestroyData(chr.getClient());
|
|
||||||
}
|
|
||||||
if (destroyDoor.getTownPortal().getId() == 0x80) {
|
|
||||||
for (MapleCharacter chr : townChars) {
|
|
||||||
MapleDoor door = chr.getMainTownDoor();
|
|
||||||
if (door != null) {
|
|
||||||
destroyDoor.getTownDoor().sendSpawnData(chr.getClient());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (effect.isMapChair()) {
|
} else if (effect.isMapChair()) {
|
||||||
stopChairTask();
|
stopChairTask();
|
||||||
}
|
}
|
||||||
@@ -4202,6 +4209,12 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
|||||||
case COUPON_DRP1:
|
case COUPON_DRP1:
|
||||||
case COUPON_DRP2:
|
case COUPON_DRP2:
|
||||||
case COUPON_DRP3:
|
case COUPON_DRP3:
|
||||||
|
case MESO_UP_BY_ITEM:
|
||||||
|
case ITEM_UP_BY_ITEM:
|
||||||
|
case RESPECT_PIMMUNE:
|
||||||
|
case RESPECT_MIMMUNE:
|
||||||
|
case DEFENSE_ATT:
|
||||||
|
case DEFENSE_STATE:
|
||||||
case WATK:
|
case WATK:
|
||||||
case WDEF:
|
case WDEF:
|
||||||
case MATK:
|
case MATK:
|
||||||
@@ -4347,7 +4360,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
|||||||
appliedStatups.put(ps.getLeft(), new MapleBuffStatValueHolder(effect, starttime, ps.getRight()));
|
appliedStatups.put(ps.getLeft(), new MapleBuffStatValueHolder(effect, starttime, ps.getRight()));
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean active = effect.isActive(mapid);
|
boolean active = effect.isActive(this);
|
||||||
if(ServerConstants.USE_BUFF_MOST_SIGNIFICANT) {
|
if(ServerConstants.USE_BUFF_MOST_SIGNIFICANT) {
|
||||||
toDeploy = new LinkedHashMap<>();
|
toDeploy = new LinkedHashMap<>();
|
||||||
Map<Integer, Pair<MapleStatEffect, Long>> retrievedEffects = new LinkedHashMap<>();
|
Map<Integer, Pair<MapleStatEffect, Long>> retrievedEffects = new LinkedHashMap<>();
|
||||||
@@ -4559,7 +4572,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
|||||||
silentPartyUpdateInternal(chrParty);
|
silentPartyUpdateInternal(chrParty);
|
||||||
}
|
}
|
||||||
|
|
||||||
private MapleDoor removePartyDoor(boolean partyUpdate) {
|
public MapleDoor removePartyDoor(boolean partyUpdate) {
|
||||||
MapleDoor ret = null;
|
MapleDoor ret = null;
|
||||||
MapleParty chrParty;
|
MapleParty chrParty;
|
||||||
|
|
||||||
@@ -5322,20 +5335,6 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<MonsterDropEntry> retrieveRelevantDrops(int monsterId) {
|
|
||||||
List<MapleCharacter> pchars = new LinkedList<>();
|
|
||||||
for (MapleCharacter chr : getPartyMembers()) {
|
|
||||||
if (chr.isLoggedinWorld()) {
|
|
||||||
pchars.add(chr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pchars.isEmpty()) {
|
|
||||||
pchars.add(this);
|
|
||||||
}
|
|
||||||
return MapleLootManager.retrieveRelevantDrops(monsterId, pchars);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MaplePlayerShop getPlayerShop() {
|
public MaplePlayerShop getPlayerShop() {
|
||||||
return playerShop;
|
return playerShop;
|
||||||
}
|
}
|
||||||
@@ -5356,7 +5355,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
|||||||
closeNpcShop();
|
closeNpcShop();
|
||||||
closeTrade();
|
closeTrade();
|
||||||
closePlayerShop();
|
closePlayerShop();
|
||||||
closeMiniGame();
|
closeMiniGame(true);
|
||||||
closeHiredMerchant(false);
|
closeHiredMerchant(false);
|
||||||
closePlayerMessenger();
|
closePlayerMessenger();
|
||||||
|
|
||||||
@@ -5398,18 +5397,16 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
|||||||
this.setPlayerShop(null);
|
this.setPlayerShop(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void closeMiniGame() {
|
public void closeMiniGame(boolean forceClose) {
|
||||||
MapleMiniGame game = this.getMiniGame();
|
MapleMiniGame game = this.getMiniGame();
|
||||||
if (game == null) {
|
if (game == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setMiniGame(null);
|
|
||||||
if (game.isOwner(this)) {
|
if (game.isOwner(this)) {
|
||||||
this.getMap().broadcastMessage(MaplePacketCreator.removeMinigameBox(this));
|
game.closeRoom(forceClose);
|
||||||
game.broadcastToVisitor(MaplePacketCreator.getMiniGameClose(3));
|
|
||||||
} else {
|
} else {
|
||||||
game.removeVisitor(this);
|
game.removeVisitor(forceClose, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6542,9 +6539,10 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void updateCouponRates() {
|
public void updateCouponRates() {
|
||||||
if (cpnLock.tryLock()) {
|
|
||||||
MapleInventory cashInv = this.getInventory(MapleInventoryType.CASH);
|
MapleInventory cashInv = this.getInventory(MapleInventoryType.CASH);
|
||||||
|
if (cashInv == null) return;
|
||||||
|
|
||||||
|
if (cpnLock.tryLock()) {
|
||||||
effLock.lock();
|
effLock.lock();
|
||||||
chrLock.lock();
|
chrLock.lock();
|
||||||
cashInv.lockInventory();
|
cashInv.lockInventory();
|
||||||
@@ -6979,11 +6977,11 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
|||||||
ret.commitExcludedItems();
|
ret.commitExcludedItems();
|
||||||
|
|
||||||
if (channelserver) {
|
if (channelserver) {
|
||||||
MapleMapFactory mapFactory = client.getChannelServer().getMapFactory();
|
MapleMapManager mapManager = client.getChannelServer().getMapFactory();
|
||||||
ret.map = mapFactory.getMap(ret.mapid);
|
ret.map = mapManager.getMap(ret.mapid);
|
||||||
|
|
||||||
if (ret.map == null) {
|
if (ret.map == null) {
|
||||||
ret.map = mapFactory.getMap(100000000);
|
ret.map = mapManager.getMap(100000000);
|
||||||
}
|
}
|
||||||
MaplePortal portal = ret.map.getPortal(ret.initialSpawnPoint);
|
MaplePortal portal = ret.map.getPortal(ret.initialSpawnPoint);
|
||||||
if (portal == null) {
|
if (portal == null) {
|
||||||
|
|||||||
@@ -109,11 +109,11 @@ public class MapleClient {
|
|||||||
private Map<String, ScriptEngine> engines = new HashMap<>();
|
private Map<String, ScriptEngine> engines = new HashMap<>();
|
||||||
private byte characterSlots = 3;
|
private byte characterSlots = 3;
|
||||||
private byte loginattempt = 0;
|
private byte loginattempt = 0;
|
||||||
private String pin = null;
|
private String pin = "";
|
||||||
private int pinattempt = 0;
|
private int pinattempt = 0;
|
||||||
private String pic = null;
|
private String pic = "";
|
||||||
private String hwid = null;
|
|
||||||
private int picattempt = 0;
|
private int picattempt = 0;
|
||||||
|
private String hwid = null;
|
||||||
private byte csattempt = 0;
|
private byte csattempt = 0;
|
||||||
private byte gender = -1;
|
private byte gender = -1;
|
||||||
private boolean disconnecting = false;
|
private boolean disconnecting = false;
|
||||||
@@ -480,6 +480,10 @@ public class MapleClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean checkPin(String other) {
|
public boolean checkPin(String other) {
|
||||||
|
if (!(ServerConstants.ENABLE_PIN && !canBypassPin())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
pinattempt++;
|
pinattempt++;
|
||||||
if (pinattempt > 5) {
|
if (pinattempt > 5) {
|
||||||
MapleSessionCoordinator.getInstance().closeSession(session, false);
|
MapleSessionCoordinator.getInstance().closeSession(session, false);
|
||||||
@@ -521,7 +525,7 @@ public class MapleClient {
|
|||||||
if (picattempt > 5) {
|
if (picattempt > 5) {
|
||||||
MapleSessionCoordinator.getInstance().closeSession(session, false);
|
MapleSessionCoordinator.getInstance().closeSession(session, false);
|
||||||
}
|
}
|
||||||
if (pic.equals(other)) {
|
if (pic.equals(other)) { // thanks ryantpayton (HeavenClient) for noticing null pics being checked here
|
||||||
picattempt = 0;
|
picattempt = 0;
|
||||||
MapleLoginBypassCoordinator.getInstance().registerLoginBypassEntry(getNibbleHWID(), accId, true);
|
MapleLoginBypassCoordinator.getInstance().registerLoginBypassEntry(getNibbleHWID(), accId, true);
|
||||||
return true;
|
return true;
|
||||||
@@ -1486,6 +1490,8 @@ public class MapleClient {
|
|||||||
player.clearBanishPlayerData();
|
player.clearBanishPlayerData();
|
||||||
player.getClient().getChannelServer().removePlayer(player);
|
player.getClient().getChannelServer().removePlayer(player);
|
||||||
|
|
||||||
|
player.saveCharToDB();
|
||||||
|
|
||||||
player.getClient().updateLoginState(MapleClient.LOGIN_SERVER_TRANSITION);
|
player.getClient().updateLoginState(MapleClient.LOGIN_SERVER_TRANSITION);
|
||||||
player.setSessionTransitionState();
|
player.setSessionTransitionState();
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ public enum AutobanFactory {
|
|||||||
|
|
||||||
public void alert(MapleCharacter chr, String reason) {
|
public void alert(MapleCharacter chr, String reason) {
|
||||||
if(ServerConstants.USE_AUTOBAN == true) {
|
if(ServerConstants.USE_AUTOBAN == true) {
|
||||||
if (chr != null && MapleLogger.ignored.contains(chr.getName())){
|
if (chr != null && MapleLogger.ignored.contains(chr.getId())){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Server.getInstance().broadcastGMMessage((chr != null ? chr.getWorld() : 0), MaplePacketCreator.sendYellowTip((chr != null ? MapleCharacter.makeMapleReadable(chr.getName()) : "") + " caused " + this.name() + " " + reason));
|
Server.getInstance().broadcastGMMessage((chr != null ? chr.getWorld() : 0), MaplePacketCreator.sendYellowTip((chr != null ? MapleCharacter.makeMapleReadable(chr.getName()) : "") + " caused " + this.name() + " " + reason));
|
||||||
|
|||||||
@@ -119,9 +119,9 @@ public class AutobanManager {
|
|||||||
|
|
||||||
FilePrinter.print(FilePrinter.EXPLOITS, "Player " + chr + " was caught spamming TYPE " + type + " and has been disconnected.");
|
FilePrinter.print(FilePrinter.EXPLOITS, "Player " + chr + " was caught spamming TYPE " + type + " and has been disconnected.");
|
||||||
}
|
}
|
||||||
return;
|
} else {
|
||||||
}
|
|
||||||
this.timestamp[type] = time;
|
this.timestamp[type] = time;
|
||||||
this.timestampcounter[type] = 0;
|
this.timestampcounter[type] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -93,6 +93,10 @@ public class CommandsExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleInternal(MapleClient client, String message){
|
private void handleInternal(MapleClient client, String message){
|
||||||
|
if (client.getPlayer().getMapId() == 300000012) {
|
||||||
|
client.getPlayer().yellowMessage("You not have permission to use this command while in jail.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
final String splitRegex = "[ ]";
|
final String splitRegex = "[ ]";
|
||||||
String[] splitedMessage = message.substring(1).split(splitRegex, 2);
|
String[] splitedMessage = message.substring(1).split(splitRegex, 2);
|
||||||
if (splitedMessage.length < 2) {
|
if (splitedMessage.length < 2) {
|
||||||
@@ -259,6 +263,7 @@ public class CommandsExecutor {
|
|||||||
addCommand("job", 2, JobCommand.class);
|
addCommand("job", 2, JobCommand.class);
|
||||||
addCommand("unbug", 2, UnBugCommand.class);
|
addCommand("unbug", 2, UnBugCommand.class);
|
||||||
addCommand("id", 2, IdCommand.class);
|
addCommand("id", 2, IdCommand.class);
|
||||||
|
addCommand("gachalist", GachaListCommand.class);
|
||||||
|
|
||||||
commandsNameDesc.add(levelCommandsCursor);
|
commandsNameDesc.add(levelCommandsCursor);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import net.server.Server;
|
|||||||
import server.MaplePortal;
|
import server.MaplePortal;
|
||||||
import server.maps.FieldLimit;
|
import server.maps.FieldLimit;
|
||||||
import server.maps.MapleMap;
|
import server.maps.MapleMap;
|
||||||
import server.maps.MapleMapFactory;
|
import server.maps.MapleMapManager;
|
||||||
import server.maps.MapleMiniDungeonInfo;
|
import server.maps.MapleMiniDungeonInfo;
|
||||||
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
@@ -47,18 +47,18 @@ public class GotoCommand extends Command {
|
|||||||
{
|
{
|
||||||
setDescription("");
|
setDescription("");
|
||||||
|
|
||||||
MapleMapFactory mapFactory = Server.getInstance().getWorlds().get(0).getChannels().get(0).getMapFactory();
|
MapleMapManager mapManager = Server.getInstance().getWorlds().get(0).getChannels().get(0).getMapFactory();
|
||||||
|
|
||||||
List<Entry<String, Integer>> towns = new ArrayList<>(GameConstants.GOTO_TOWNS.entrySet());
|
List<Entry<String, Integer>> towns = new ArrayList<>(GameConstants.GOTO_TOWNS.entrySet());
|
||||||
sortGotoEntries(towns);
|
sortGotoEntries(towns);
|
||||||
for (Map.Entry<String, Integer> e : towns) {
|
for (Map.Entry<String, Integer> e : towns) {
|
||||||
GOTO_TOWNS_INFO += ("'" + e.getKey() + "' - #b" + (mapFactory.getMap(e.getValue()).getMapName()) + "#k\r\n");
|
GOTO_TOWNS_INFO += ("'" + e.getKey() + "' - #b" + (mapManager.getMap(e.getValue()).getMapName()) + "#k\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Entry<String, Integer>> areas = new ArrayList<>(GameConstants.GOTO_AREAS.entrySet());
|
List<Entry<String, Integer>> areas = new ArrayList<>(GameConstants.GOTO_AREAS.entrySet());
|
||||||
sortGotoEntries(areas);
|
sortGotoEntries(areas);
|
||||||
for (Map.Entry<String, Integer> e : areas) {
|
for (Map.Entry<String, Integer> e : areas) {
|
||||||
GOTO_AREAS_INFO += ("'" + e.getKey() + "' - #b" + (mapFactory.getMap(e.getValue()).getMapName()) + "#k\r\n");
|
GOTO_AREAS_INFO += ("'" + e.getKey() + "' - #b" + (mapManager.getMap(e.getValue()).getMapName()) + "#k\r\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,6 +103,7 @@ public class GotoCommand extends Command {
|
|||||||
HashMap<String, Integer> gotomaps;
|
HashMap<String, Integer> gotomaps;
|
||||||
if (player.isGM()) {
|
if (player.isGM()) {
|
||||||
gotomaps = new HashMap<>(GameConstants.GOTO_AREAS); // distinct map registry for GM/users suggested thanks to Vcoc
|
gotomaps = new HashMap<>(GameConstants.GOTO_AREAS); // distinct map registry for GM/users suggested thanks to Vcoc
|
||||||
|
gotomaps.putAll(GameConstants.GOTO_TOWNS); // thanks Halcyon for pointing out duplicates on listed entries functionality
|
||||||
} else {
|
} else {
|
||||||
gotomaps = new HashMap<>(GameConstants.GOTO_TOWNS);
|
gotomaps = new HashMap<>(GameConstants.GOTO_TOWNS);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
|
||||||
|
Copyleft (L) 2016 - 2018 RonanLana
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as
|
||||||
|
published by the Free Software Foundation version 3 as published by
|
||||||
|
the Free Software Foundation. You may not use, modify or distribute
|
||||||
|
this program under any other version of the GNU Affero General Public
|
||||||
|
License.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package client.command.commands.gm2;
|
||||||
|
|
||||||
|
import client.MapleClient;
|
||||||
|
import client.command.Command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Ronan
|
||||||
|
*/
|
||||||
|
public class GachaListCommand extends Command {
|
||||||
|
{
|
||||||
|
setDescription("");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(MapleClient c, String[] params) {
|
||||||
|
c.getAbstractPlayerInteraction().openNpc(10000, "gachaponInfo");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -47,11 +47,11 @@ public class IgnoreCommand extends Command {
|
|||||||
player.message("Player '" + params[0] + "' could not be found on this world.");
|
player.message("Player '" + params[0] + "' could not be found on this world.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
boolean monitored_ = MapleLogger.ignored.contains(victim.getName());
|
boolean monitored_ = MapleLogger.ignored.contains(victim.getId());
|
||||||
if (monitored_) {
|
if (monitored_) {
|
||||||
MapleLogger.ignored.remove(victim.getName());
|
MapleLogger.ignored.remove(victim.getId());
|
||||||
} else {
|
} else {
|
||||||
MapleLogger.ignored.add(victim.getName());
|
MapleLogger.ignored.add(victim.getId());
|
||||||
}
|
}
|
||||||
player.yellowMessage(victim.getName() + " is " + (!monitored_ ? "now being ignored." : "no longer being ignored."));
|
player.yellowMessage(victim.getName() + " is " + (!monitored_ ? "now being ignored." : "no longer being ignored."));
|
||||||
String message_ = player.getName() + (!monitored_ ? " has started ignoring " : " has stopped ignoring ") + victim.getName() + ".";
|
String message_ = player.getName() + (!monitored_ ? " has started ignoring " : " has stopped ignoring ") + victim.getName() + ".";
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ public class IgnoredCommand extends Command {
|
|||||||
@Override
|
@Override
|
||||||
public void execute(MapleClient c, String[] params) {
|
public void execute(MapleClient c, String[] params) {
|
||||||
MapleCharacter player = c.getPlayer();
|
MapleCharacter player = c.getPlayer();
|
||||||
for (String ign : MapleLogger.ignored) {
|
for (Integer cid : MapleLogger.ignored) {
|
||||||
player.yellowMessage(ign + " is being ignored.");
|
player.yellowMessage(MapleCharacter.getNameById(cid) + " is being ignored.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,14 +47,14 @@ public class MonitorCommand extends Command {
|
|||||||
player.message("Player '" + params[0] + "' could not be found on this world.");
|
player.message("Player '" + params[0] + "' could not be found on this world.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
boolean monitored = MapleLogger.monitored.contains(victim.getName());
|
boolean monitored = MapleLogger.monitored.contains(victim.getId());
|
||||||
if (monitored) {
|
if (monitored) {
|
||||||
MapleLogger.monitored.remove(victim.getName());
|
MapleLogger.monitored.remove(victim.getId());
|
||||||
} else {
|
} else {
|
||||||
MapleLogger.monitored.add(victim.getName());
|
MapleLogger.monitored.add(victim.getId());
|
||||||
}
|
}
|
||||||
player.yellowMessage(victim.getName() + " is " + (!monitored ? "now being monitored." : "no longer being monitored."));
|
player.yellowMessage(victim.getId() + " is " + (!monitored ? "now being monitored." : "no longer being monitored."));
|
||||||
String message = player.getName() + (!monitored ? " has started monitoring " : " has stopped monitoring ") + victim.getName() + ".";
|
String message = player.getName() + (!monitored ? " has started monitoring " : " has stopped monitoring ") + victim.getId() + ".";
|
||||||
Server.getInstance().broadcastGMMessage(c.getWorld(), MaplePacketCreator.serverNotice(5, message));
|
Server.getInstance().broadcastGMMessage(c.getWorld(), MaplePacketCreator.serverNotice(5, message));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ public class MonitorsCommand extends Command {
|
|||||||
@Override
|
@Override
|
||||||
public void execute(MapleClient c, String[] params) {
|
public void execute(MapleClient c, String[] params) {
|
||||||
MapleCharacter player = c.getPlayer();
|
MapleCharacter player = c.getPlayer();
|
||||||
for (String ign : MapleLogger.monitored) {
|
for (Integer cid : MapleLogger.monitored) {
|
||||||
player.yellowMessage(ign + " is being monitored.");
|
player.yellowMessage(MapleCharacter.getNameById(cid) + " is being monitored.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,13 +46,16 @@ public enum ItemFactory {
|
|||||||
CASH_ARAN(5, true),
|
CASH_ARAN(5, true),
|
||||||
MERCHANT(6, false),
|
MERCHANT(6, false),
|
||||||
CASH_OVERALL(7, true),
|
CASH_OVERALL(7, true),
|
||||||
MARRIAGE_GIFTS(8, false);
|
MARRIAGE_GIFTS(8, false),
|
||||||
|
DUEY(9, false);
|
||||||
private final int value;
|
private final int value;
|
||||||
private final boolean account;
|
private final boolean account;
|
||||||
private static final Lock locks[] = new Lock[200]; // thanks Masterrulax for pointing out a bottleneck issue here
|
|
||||||
|
private static final int lockCount = 400;
|
||||||
|
private static final Lock locks[] = new Lock[lockCount]; // thanks Masterrulax for pointing out a bottleneck issue here
|
||||||
|
|
||||||
static {
|
static {
|
||||||
for (int i = 0; i < 200; i++) {
|
for (int i = 0; i < lockCount; i++) {
|
||||||
locks[i] = MonitoredReentrantLockFactory.createLock(MonitoredLockType.ITEM, true);
|
locks[i] = MonitoredReentrantLockFactory.createLock(MonitoredLockType.ITEM, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,7 +78,9 @@ public enum ItemFactory {
|
|||||||
saveItems(items, null, id, con);
|
saveItems(items, null, id, con);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void saveItems(List<Pair<Item, MapleInventoryType>> items, List<Short> bundlesList, int id, Connection con) throws SQLException {
|
public void saveItems(List<Pair<Item, MapleInventoryType>> items, List<Short> bundlesList, int id, Connection con) throws SQLException {
|
||||||
|
// thanks Arufonsu, MedicOP, BHB for pointing a "synchronized" bottleneck here
|
||||||
|
|
||||||
if(value != 6) saveItemsCommon(items, id, con);
|
if(value != 6) saveItemsCommon(items, id, con);
|
||||||
else saveItemsMerchant(items, bundlesList, id, con);
|
else saveItemsMerchant(items, bundlesList, id, con);
|
||||||
}
|
}
|
||||||
@@ -199,7 +204,7 @@ public enum ItemFactory {
|
|||||||
PreparedStatement pse = null;
|
PreparedStatement pse = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
|
|
||||||
Lock lock = locks[id % 200];
|
Lock lock = locks[id % lockCount];
|
||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
StringBuilder query = new StringBuilder();
|
StringBuilder query = new StringBuilder();
|
||||||
@@ -365,7 +370,7 @@ public enum ItemFactory {
|
|||||||
PreparedStatement pse = null;
|
PreparedStatement pse = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
|
|
||||||
Lock lock = locks[id % 200];
|
Lock lock = locks[id % lockCount];
|
||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
ps = con.prepareStatement("DELETE FROM `inventorymerchant` WHERE `characterid` = ?");
|
ps = con.prepareStatement("DELETE FROM `inventorymerchant` WHERE `characterid` = ?");
|
||||||
|
|||||||
@@ -463,32 +463,42 @@ public class MapleInventory implements Iterable<Item> {
|
|||||||
public static boolean checkSpots(MapleCharacter chr, List<Pair<Item, MapleInventoryType>> items, List<Integer> typesSlotsUsed, boolean useProofInv) {
|
public static boolean checkSpots(MapleCharacter chr, List<Pair<Item, MapleInventoryType>> items, List<Integer> typesSlotsUsed, boolean useProofInv) {
|
||||||
// assumption: no "UNDEFINED" or "EQUIPPED" items shall be tested here, all counts are >= 0.
|
// assumption: no "UNDEFINED" or "EQUIPPED" items shall be tested here, all counts are >= 0.
|
||||||
|
|
||||||
Map<Integer, Short> rcvItems = new LinkedHashMap<>();
|
Map<Integer, List<Integer>> rcvItems = new LinkedHashMap<>();
|
||||||
Map<Integer, Byte> rcvTypes = new LinkedHashMap<>();
|
Map<Integer, Byte> rcvTypes = new LinkedHashMap<>();
|
||||||
|
|
||||||
for (Pair<Item, MapleInventoryType> item : items) {
|
for (Pair<Item, MapleInventoryType> item : items) {
|
||||||
Integer itemId = item.left.getItemId();
|
Integer itemId = item.left.getItemId();
|
||||||
Short qty = rcvItems.get(itemId);
|
List<Integer> qty = rcvItems.get(itemId);
|
||||||
|
|
||||||
if(qty == null) {
|
if(qty == null) {
|
||||||
rcvItems.put(itemId, item.left.getQuantity());
|
List<Integer> itemQtyList = new LinkedList<>();
|
||||||
|
itemQtyList.add((int) item.left.getQuantity());
|
||||||
|
|
||||||
|
rcvItems.put(itemId, itemQtyList);
|
||||||
rcvTypes.put(itemId, item.right.getType());
|
rcvTypes.put(itemId, item.right.getType());
|
||||||
} else {
|
} else {
|
||||||
rcvItems.put(itemId, (short)(qty + item.left.getQuantity()));
|
if (!ItemConstants.isRechargeable(itemId)) {
|
||||||
|
qty.set(0, qty.get(0) + item.left.getQuantity());
|
||||||
|
} else {
|
||||||
|
qty.add((int) item.left.getQuantity());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MapleClient c = chr.getClient();
|
MapleClient c = chr.getClient();
|
||||||
for(Entry<Integer, Short> it: rcvItems.entrySet()) {
|
for(Entry<Integer, List<Integer>> it: rcvItems.entrySet()) {
|
||||||
int itemType = rcvTypes.get(it.getKey()) - 1;
|
int itemType = rcvTypes.get(it.getKey()) - 1;
|
||||||
|
|
||||||
|
for (Integer itValue : it.getValue()) {
|
||||||
int usedSlots = typesSlotsUsed.get(itemType);
|
int usedSlots = typesSlotsUsed.get(itemType);
|
||||||
|
|
||||||
int result = MapleInventoryManipulator.checkSpaceProgressively(c, it.getKey(), it.getValue(), "", usedSlots, useProofInv);
|
int result = MapleInventoryManipulator.checkSpaceProgressively(c, it.getKey(), itValue, "", usedSlots, useProofInv);
|
||||||
boolean hasSpace = ((result % 2) != 0);
|
boolean hasSpace = ((result % 2) != 0);
|
||||||
|
|
||||||
if(!hasSpace) return false;
|
if(!hasSpace) return false;
|
||||||
typesSlotsUsed.set(itemType, (result >> 1));
|
typesSlotsUsed.set(itemType, (result >> 1));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -525,39 +535,49 @@ public class MapleInventory implements Iterable<Item> {
|
|||||||
public static boolean checkSpotsAndOwnership(MapleCharacter chr, List<Pair<Item, MapleInventoryType>> items, List<Integer> typesSlotsUsed, boolean useProofInv) {
|
public static boolean checkSpotsAndOwnership(MapleCharacter chr, List<Pair<Item, MapleInventoryType>> items, List<Integer> typesSlotsUsed, boolean useProofInv) {
|
||||||
//assumption: no "UNDEFINED" or "EQUIPPED" items shall be tested here, all counts are >= 0 and item list to be checked is a legal one.
|
//assumption: no "UNDEFINED" or "EQUIPPED" items shall be tested here, all counts are >= 0 and item list to be checked is a legal one.
|
||||||
|
|
||||||
Map<Long, Short> rcvItems = new LinkedHashMap<>();
|
Map<Long, List<Integer>> rcvItems = new LinkedHashMap<>();
|
||||||
Map<Long, Byte> rcvTypes = new LinkedHashMap<>();
|
Map<Long, Byte> rcvTypes = new LinkedHashMap<>();
|
||||||
Map<Long, String> rcvOwners = new LinkedHashMap<>();
|
Map<Long, String> rcvOwners = new LinkedHashMap<>();
|
||||||
|
|
||||||
for (Pair<Item, MapleInventoryType> item : items) {
|
for (Pair<Item, MapleInventoryType> item : items) {
|
||||||
Long itemHash = hashKey(item.left.getItemId(), item.left.getOwner());
|
Long itemHash = hashKey(item.left.getItemId(), item.left.getOwner());
|
||||||
Short qty = rcvItems.get(itemHash);
|
List<Integer> qty = rcvItems.get(itemHash);
|
||||||
|
|
||||||
if(qty == null) {
|
if(qty == null) {
|
||||||
rcvItems.put(itemHash, item.left.getQuantity());
|
List<Integer> itemQtyList = new LinkedList<>();
|
||||||
|
itemQtyList.add((int) item.left.getQuantity());
|
||||||
|
|
||||||
|
rcvItems.put(itemHash, itemQtyList);
|
||||||
rcvTypes.put(itemHash, item.right.getType());
|
rcvTypes.put(itemHash, item.right.getType());
|
||||||
rcvOwners.put(itemHash, item.left.getOwner());
|
rcvOwners.put(itemHash, item.left.getOwner());
|
||||||
} else {
|
} else {
|
||||||
rcvItems.put(itemHash, (short)(qty + item.left.getQuantity()));
|
// thanks BHB88 for pointing out an issue with rechargeable items being stacked on inventory check
|
||||||
|
if (!ItemConstants.isRechargeable(item.left.getItemId())) {
|
||||||
|
qty.set(0, qty.get(0) + item.left.getQuantity());
|
||||||
|
} else {
|
||||||
|
qty.add((int) item.left.getQuantity());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MapleClient c = chr.getClient();
|
MapleClient c = chr.getClient();
|
||||||
for(Entry<Long, Short> it: rcvItems.entrySet()) {
|
for(Entry<Long, List<Integer>> it: rcvItems.entrySet()) {
|
||||||
int itemType = rcvTypes.get(it.getKey()) - 1;
|
int itemType = rcvTypes.get(it.getKey()) - 1;
|
||||||
int usedSlots = typesSlotsUsed.get(itemType);
|
int itemId = (int) (it.getKey() >> 32L);
|
||||||
|
|
||||||
Long itemId = it.getKey() >> 32L;
|
for (Integer itValue : it.getValue()) {
|
||||||
|
int usedSlots = typesSlotsUsed.get(itemType);
|
||||||
|
|
||||||
//System.out.print("inserting " + itemId.intValue() + " with type " + itemType + " qty " + it.getValue() + " owner '" + rcvOwners.get(it.getKey()) + "' current usedSlots:");
|
//System.out.print("inserting " + itemId.intValue() + " with type " + itemType + " qty " + it.getValue() + " owner '" + rcvOwners.get(it.getKey()) + "' current usedSlots:");
|
||||||
//for(Integer i : typesSlotsUsed) System.out.print(" " + i);
|
//for(Integer i : typesSlotsUsed) System.out.print(" " + i);
|
||||||
int result = MapleInventoryManipulator.checkSpaceProgressively(c, itemId.intValue(), it.getValue(), rcvOwners.get(it.getKey()), usedSlots, useProofInv);
|
int result = MapleInventoryManipulator.checkSpaceProgressively(c, itemId, itValue, rcvOwners.get(it.getKey()), usedSlots, useProofInv);
|
||||||
boolean hasSpace = ((result % 2) != 0);
|
boolean hasSpace = ((result % 2) != 0);
|
||||||
//System.out.print(" -> hasSpace: " + hasSpace + " RESULT : " + result + "\n");
|
//System.out.print(" -> hasSpace: " + hasSpace + " RESULT : " + result + "\n");
|
||||||
|
|
||||||
if(!hasSpace) return false;
|
if(!hasSpace) return false;
|
||||||
typesSlotsUsed.set(itemType, (result >> 1));
|
typesSlotsUsed.set(itemType, (result >> 1));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -316,7 +316,11 @@ public class MapleInventoryManipulator {
|
|||||||
if (!type.equals(MapleInventoryType.EQUIP)) {
|
if (!type.equals(MapleInventoryType.EQUIP)) {
|
||||||
short slotMax = ii.getSlotMax(c, itemid);
|
short slotMax = ii.getSlotMax(c, itemid);
|
||||||
List<Item> existing = inv.listById(itemid);
|
List<Item> existing = inv.listById(itemid);
|
||||||
if (!ItemConstants.isRechargeable(itemid)) {
|
|
||||||
|
final int numSlotsNeeded;
|
||||||
|
if (ItemConstants.isRechargeable(itemid)) {
|
||||||
|
numSlotsNeeded = 1;
|
||||||
|
} else {
|
||||||
if (existing.size() > 0) // first update all existing slots to slotMax
|
if (existing.size() > 0) // first update all existing slots to slotMax
|
||||||
{
|
{
|
||||||
for (Item eItem : existing) {
|
for (Item eItem : existing) {
|
||||||
@@ -330,15 +334,14 @@ public class MapleInventoryManipulator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
final int numSlotsNeeded;
|
|
||||||
if (slotMax > 0) {
|
if (slotMax > 0) {
|
||||||
numSlotsNeeded = (int) (Math.ceil(((double) quantity) / slotMax));
|
numSlotsNeeded = (int) (Math.ceil(((double) quantity) / slotMax));
|
||||||
} else if (ItemConstants.isRechargeable(itemid)) {
|
|
||||||
numSlotsNeeded = 1;
|
|
||||||
} else {
|
} else {
|
||||||
numSlotsNeeded = 1;
|
numSlotsNeeded = 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return !inv.isFull(numSlotsNeeded - 1);
|
return !inv.isFull(numSlotsNeeded - 1);
|
||||||
} else {
|
} else {
|
||||||
return !inv.isFull();
|
return !inv.isFull();
|
||||||
@@ -367,7 +370,11 @@ public class MapleInventoryManipulator {
|
|||||||
|
|
||||||
if (!type.equals(MapleInventoryType.EQUIP)) {
|
if (!type.equals(MapleInventoryType.EQUIP)) {
|
||||||
short slotMax = ii.getSlotMax(c, itemid);
|
short slotMax = ii.getSlotMax(c, itemid);
|
||||||
if (!ItemConstants.isRechargeable(itemid)) {
|
final int numSlotsNeeded;
|
||||||
|
|
||||||
|
if (ItemConstants.isRechargeable(itemid)) {
|
||||||
|
numSlotsNeeded = 1;
|
||||||
|
} else {
|
||||||
List<Item> existing = inv.listById(itemid);
|
List<Item> existing = inv.listById(itemid);
|
||||||
|
|
||||||
if (existing.size() > 0) // first update all existing slots to slotMax
|
if (existing.size() > 0) // first update all existing slots to slotMax
|
||||||
@@ -383,15 +390,13 @@ public class MapleInventoryManipulator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
final int numSlotsNeeded;
|
|
||||||
if (slotMax > 0) {
|
if (slotMax > 0) {
|
||||||
numSlotsNeeded = (int) (Math.ceil(((double) quantity) / slotMax));
|
numSlotsNeeded = (int) (Math.ceil(((double) quantity) / slotMax));
|
||||||
} else if (ItemConstants.isRechargeable(itemid)) {
|
|
||||||
numSlotsNeeded = 1;
|
|
||||||
} else {
|
} else {
|
||||||
numSlotsNeeded = 1;
|
numSlotsNeeded = 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
returnValue = ((numSlotsNeeded + usedSlots) << 1);
|
returnValue = ((numSlotsNeeded + usedSlots) << 1);
|
||||||
returnValue += (numSlotsNeeded == 0 || !inv.isFullAfterSomeItems(numSlotsNeeded - 1, usedSlots)) ? 1 : 0;
|
returnValue += (numSlotsNeeded == 0 || !inv.isFullAfterSomeItems(numSlotsNeeded - 1, usedSlots)) ? 1 : 0;
|
||||||
@@ -718,13 +723,9 @@ public class MapleInventoryManipulator {
|
|||||||
}
|
}
|
||||||
} else if (ItemConstants.isWeddingRing(source.getItemId())) {
|
} else if (ItemConstants.isWeddingRing(source.getItemId())) {
|
||||||
map.disappearingItemDrop(chr, chr, target, dropPos);
|
map.disappearingItemDrop(chr, chr, target, dropPos);
|
||||||
} else if (map.getEverlast()) {
|
|
||||||
if (ii.isDropRestricted(target.getItemId()) || ii.isCash(target.getItemId()) || isDroppedItemRestricted(target)) {
|
|
||||||
map.disappearingItemDrop(chr, chr, target, dropPos);
|
|
||||||
} else {
|
|
||||||
map.spawnItemDrop(chr, chr, target, dropPos, true, true);
|
|
||||||
}
|
}
|
||||||
} else if (ii.isDropRestricted(target.getItemId()) || ii.isCash(target.getItemId()) || isDroppedItemRestricted(target)) {
|
|
||||||
|
if (ii.isDropRestricted(target.getItemId()) || ii.isCash(target.getItemId()) || isDroppedItemRestricted(target)) {
|
||||||
map.disappearingItemDrop(chr, chr, target, dropPos);
|
map.disappearingItemDrop(chr, chr, target, dropPos);
|
||||||
} else {
|
} else {
|
||||||
map.spawnItemDrop(chr, chr, target, dropPos, true, true);
|
map.spawnItemDrop(chr, chr, target, dropPos, true, true);
|
||||||
@@ -753,19 +754,15 @@ public class MapleInventoryManipulator {
|
|||||||
NewYearCardRecord.removeAllNewYearCard(false, chr);
|
NewYearCardRecord.removeAllNewYearCard(false, chr);
|
||||||
c.getAbstractPlayerInteraction().removeAll(4301000);
|
c.getAbstractPlayerInteraction().removeAll(4301000);
|
||||||
}
|
}
|
||||||
|
} else if (ItemConstants.isWeddingRing(source.getItemId())) {
|
||||||
|
map.disappearingItemDrop(chr, chr, source, dropPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (map.getEverlast()) {
|
|
||||||
if (ii.isDropRestricted(itemId) || ii.isCash(itemId) || isDroppedItemRestricted(source)) {
|
if (ii.isDropRestricted(itemId) || ii.isCash(itemId) || isDroppedItemRestricted(source)) {
|
||||||
map.disappearingItemDrop(chr, chr, source, dropPos);
|
map.disappearingItemDrop(chr, chr, source, dropPos);
|
||||||
} else {
|
} else {
|
||||||
map.spawnItemDrop(chr, chr, source, dropPos, true, true);
|
map.spawnItemDrop(chr, chr, source, dropPos, true, true);
|
||||||
}
|
}
|
||||||
} else if (ii.isDropRestricted(itemId) || ii.isCash(itemId) || isDroppedItemRestricted(source)) {
|
|
||||||
map.disappearingItemDrop(chr, chr, source, dropPos);
|
|
||||||
} else {
|
|
||||||
map.spawnItemDrop(chr, chr, source, dropPos, true, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int quantityNow = chr.getItemQuantity(itemId, false);
|
int quantityNow = chr.getItemQuantity(itemId, false);
|
||||||
|
|||||||
@@ -26,26 +26,31 @@ package client.processor;
|
|||||||
import client.MapleCharacter;
|
import client.MapleCharacter;
|
||||||
import client.MapleClient;
|
import client.MapleClient;
|
||||||
import client.autoban.AutobanFactory;
|
import client.autoban.AutobanFactory;
|
||||||
import client.inventory.Equip;
|
|
||||||
import client.inventory.Item;
|
import client.inventory.Item;
|
||||||
|
import client.inventory.ItemFactory;
|
||||||
|
import client.inventory.MapleInventory;
|
||||||
import client.inventory.MapleInventoryType;
|
import client.inventory.MapleInventoryType;
|
||||||
import client.inventory.manipulator.MapleInventoryManipulator;
|
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||||
import client.inventory.manipulator.MapleKarmaManipulator;
|
import client.inventory.manipulator.MapleKarmaManipulator;
|
||||||
import constants.ItemConstants;
|
import constants.ItemConstants;
|
||||||
|
import constants.ServerConstants;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import net.server.channel.Channel;
|
import net.server.channel.Channel;
|
||||||
import server.DueyPackages;
|
import server.DueyPackage;
|
||||||
import server.MapleItemInformationProvider;
|
import server.MapleItemInformationProvider;
|
||||||
import server.MapleTrade;
|
import server.MapleTrade;
|
||||||
import tools.DatabaseConnection;
|
import tools.DatabaseConnection;
|
||||||
import tools.FilePrinter;
|
import tools.FilePrinter;
|
||||||
import tools.MaplePacketCreator;
|
import tools.MaplePacketCreator;
|
||||||
|
import tools.Pair;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -86,21 +91,17 @@ public class DueyProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getAccIdFromCNAME(String name, boolean accountid) {
|
private static Pair<Integer, Integer> getAccountCharacterIdFromCNAME(String name) {
|
||||||
try {
|
try {
|
||||||
PreparedStatement ps;
|
|
||||||
String text = "SELECT id,accountid FROM characters WHERE name = ?";
|
|
||||||
Connection con = DatabaseConnection.getConnection();
|
Connection con = DatabaseConnection.getConnection();
|
||||||
ps = con.prepareStatement(text);
|
PreparedStatement ps = con.prepareStatement("SELECT id,accountid FROM characters WHERE name = ?");
|
||||||
ps.setString(1, name);
|
ps.setString(1, name);
|
||||||
int id_;
|
|
||||||
|
Pair<Integer, Integer> id_ = null;
|
||||||
try (ResultSet rs = ps.executeQuery()) {
|
try (ResultSet rs = ps.executeQuery()) {
|
||||||
if (!rs.next()) {
|
if (rs.next()) {
|
||||||
rs.close();
|
id_ = new Pair<>(rs.getInt("accountid"), rs.getInt("id"));
|
||||||
ps.close();
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
id_ = accountid ? rs.getInt("accountid") : rs.getInt("id");
|
|
||||||
}
|
}
|
||||||
ps.close();
|
ps.close();
|
||||||
con.close();
|
con.close();
|
||||||
@@ -108,7 +109,7 @@ public class DueyProcessor {
|
|||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return -1;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getCurrentDate() {
|
private static String getCurrentDate() {
|
||||||
@@ -124,67 +125,6 @@ public class DueyProcessor {
|
|||||||
return date;
|
return date;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void removeItemFromDB(int packageid) {
|
|
||||||
Connection con = null;
|
|
||||||
try {
|
|
||||||
con = DatabaseConnection.getConnection();
|
|
||||||
|
|
||||||
PreparedStatement ps = con.prepareStatement("DELETE FROM dueypackages WHERE PackageId = ?");
|
|
||||||
ps.setInt(1, packageid);
|
|
||||||
ps.executeUpdate();
|
|
||||||
ps.close();
|
|
||||||
ps = con.prepareStatement("DELETE FROM dueyitems WHERE PackageId = ?");
|
|
||||||
ps.setInt(1, packageid);
|
|
||||||
ps.executeUpdate();
|
|
||||||
ps.close();
|
|
||||||
con.close();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static DueyPackages getItemByPID(ResultSet rs) {
|
|
||||||
try {
|
|
||||||
DueyPackages dueypack;
|
|
||||||
if (rs.getInt("type") == 1) {
|
|
||||||
Equip eq = new Equip(rs.getInt("itemid"), (byte) 0, -1);
|
|
||||||
eq.setUpgradeSlots((byte) rs.getInt("upgradeslots"));
|
|
||||||
eq.setLevel((byte) rs.getInt("level"));
|
|
||||||
eq.setItemLevel((byte) rs.getInt("itemlevel"));
|
|
||||||
eq.setItemExp(rs.getInt("itemexp"));
|
|
||||||
eq.setStr((short) rs.getInt("str"));
|
|
||||||
eq.setDex((short) rs.getInt("dex"));
|
|
||||||
eq.setInt((short) rs.getInt("int"));
|
|
||||||
eq.setLuk((short) rs.getInt("luk"));
|
|
||||||
eq.setHp((short) rs.getInt("hp"));
|
|
||||||
eq.setMp((short) rs.getInt("mp"));
|
|
||||||
eq.setWatk((short) rs.getInt("watk"));
|
|
||||||
eq.setMatk((short) rs.getInt("matk"));
|
|
||||||
eq.setWdef((short) rs.getInt("wdef"));
|
|
||||||
eq.setMdef((short) rs.getInt("mdef"));
|
|
||||||
eq.setAcc((short) rs.getInt("acc"));
|
|
||||||
eq.setAvoid((short) rs.getInt("avoid"));
|
|
||||||
eq.setHands((short) rs.getInt("hands"));
|
|
||||||
eq.setSpeed((short) rs.getInt("speed"));
|
|
||||||
eq.setJump((short) rs.getInt("jump"));
|
|
||||||
eq.setFlag((byte) rs.getInt("flag"));
|
|
||||||
eq.setOwner(rs.getString("owner"));
|
|
||||||
dueypack = new DueyPackages(rs.getInt("PackageId"), eq);
|
|
||||||
} else if (rs.getInt("type") == 2) {
|
|
||||||
Item newItem = new Item(rs.getInt("itemid"), (short) 0, (short) rs.getInt("quantity"));
|
|
||||||
newItem.setFlag((byte) rs.getInt("flag"));
|
|
||||||
newItem.setOwner(rs.getString("owner"));
|
|
||||||
dueypack = new DueyPackages(rs.getInt("PackageId"), newItem);
|
|
||||||
} else {
|
|
||||||
dueypack = new DueyPackages(rs.getInt("PackageId"));
|
|
||||||
}
|
|
||||||
return dueypack;
|
|
||||||
} catch (SQLException se) {
|
|
||||||
se.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void showDueyNotification(MapleClient c, MapleCharacter player) {
|
private static void showDueyNotification(MapleClient c, MapleCharacter player) {
|
||||||
Connection con = null;
|
Connection con = null;
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
@@ -231,69 +171,20 @@ public class DueyProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addMesoToDB(int mesos, String sName, int recipientID) {
|
private static void deletePackageFromInventoryDB(Connection con, int packageId) throws SQLException {
|
||||||
addItemToDB(null, 1, mesos, sName, recipientID);
|
ItemFactory.DUEY.saveItems(new LinkedList<Pair<Item, MapleInventoryType>>(), packageId, con);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addItemToDB(Item item, int quantity, int mesos, String sName, int recipientID) {
|
private static void removePackageFromDB(int packageId) {
|
||||||
Connection con = null;
|
|
||||||
try {
|
try {
|
||||||
con = DatabaseConnection.getConnection();
|
Connection con = DatabaseConnection.getConnection();
|
||||||
try (PreparedStatement ps = con.prepareStatement("INSERT INTO dueypackages (ReceiverId, SenderName, Mesos, TimeStamp, Checked, Type) VALUES (?, ?, ?, ?, ?, ?)")) {
|
|
||||||
ps.setInt(1, recipientID);
|
|
||||||
ps.setString(2, sName);
|
|
||||||
ps.setInt(3, mesos);
|
|
||||||
ps.setString(4, getCurrentDate());
|
|
||||||
ps.setInt(5, 1);
|
|
||||||
if (item == null) {
|
|
||||||
ps.setInt(6, 3);
|
|
||||||
ps.executeUpdate();
|
|
||||||
} else {
|
|
||||||
ps.setInt(6, item.getItemType());
|
|
||||||
|
|
||||||
|
PreparedStatement ps = con.prepareStatement("DELETE FROM dueypackages WHERE PackageId = ?");
|
||||||
|
ps.setInt(1, packageId);
|
||||||
ps.executeUpdate();
|
ps.executeUpdate();
|
||||||
try (ResultSet rs = ps.getGeneratedKeys()) {
|
ps.close();
|
||||||
rs.next();
|
|
||||||
PreparedStatement ps2;
|
deletePackageFromInventoryDB(con, packageId);
|
||||||
if (item.getInventoryType().equals(MapleInventoryType.EQUIP)) {
|
|
||||||
ps2 = con.prepareStatement("INSERT INTO dueyitems (PackageId, itemid, quantity, upgradeslots, level, itemlevel, itemexp, str, dex, `int`, luk, hp, mp, watk, matk, wdef, mdef, acc, avoid, hands, speed, jump, flag, owner) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
||||||
Equip eq = (Equip) item;
|
|
||||||
ps2.setInt(2, eq.getItemId());
|
|
||||||
ps2.setInt(3, 1);
|
|
||||||
ps2.setInt(4, eq.getUpgradeSlots());
|
|
||||||
ps2.setInt(5, eq.getLevel());
|
|
||||||
ps2.setInt(6, eq.getItemLevel());
|
|
||||||
ps2.setInt(7, eq.getItemExp());
|
|
||||||
ps2.setInt(8, eq.getStr());
|
|
||||||
ps2.setInt(9, eq.getDex());
|
|
||||||
ps2.setInt(10, eq.getInt());
|
|
||||||
ps2.setInt(11, eq.getLuk());
|
|
||||||
ps2.setInt(12, eq.getHp());
|
|
||||||
ps2.setInt(13, eq.getMp());
|
|
||||||
ps2.setInt(14, eq.getWatk());
|
|
||||||
ps2.setInt(15, eq.getMatk());
|
|
||||||
ps2.setInt(16, eq.getWdef());
|
|
||||||
ps2.setInt(17, eq.getMdef());
|
|
||||||
ps2.setInt(18, eq.getAcc());
|
|
||||||
ps2.setInt(19, eq.getAvoid());
|
|
||||||
ps2.setInt(20, eq.getHands());
|
|
||||||
ps2.setInt(21, eq.getSpeed());
|
|
||||||
ps2.setInt(22, eq.getJump());
|
|
||||||
ps2.setInt(23, eq.getFlag());
|
|
||||||
ps2.setString(24, eq.getOwner());
|
|
||||||
} else {
|
|
||||||
ps2 = con.prepareStatement("INSERT INTO dueyitems (PackageId, itemid, quantity, flag, owner) VALUES (?, ?, ?, ?, ?)");
|
|
||||||
ps2.setInt(2, item.getItemId());
|
|
||||||
ps2.setInt(3, quantity);
|
|
||||||
ps2.setInt(4, item.getFlag());
|
|
||||||
ps2.setString(5, item.getOwner());
|
|
||||||
}
|
|
||||||
ps2.setInt(1, rs.getInt(1));
|
|
||||||
ps2.executeUpdate();
|
|
||||||
ps2.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
con.close();
|
con.close();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
@@ -301,49 +192,181 @@ public class DueyProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<DueyPackages> loadItems(MapleCharacter chr) {
|
private static DueyPackage getPackageFromDB(ResultSet rs) {
|
||||||
List<DueyPackages> packages = new LinkedList<>();
|
|
||||||
Connection con = null;
|
|
||||||
try {
|
try {
|
||||||
con = DatabaseConnection.getConnection();
|
int packageId = rs.getInt("PackageId");
|
||||||
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM dueypackages dp LEFT JOIN dueyitems di ON dp.PackageId=di.PackageId WHERE ReceiverId = ?")) {
|
|
||||||
ps.setInt(1, chr.getId());
|
List<Pair<Item, MapleInventoryType>> dueyItems = ItemFactory.DUEY.loadItems(packageId, false);
|
||||||
try (ResultSet rs = ps.executeQuery()) {
|
DueyPackage dueypack;
|
||||||
while (rs.next()) {
|
|
||||||
DueyPackages dueypack = getItemByPID(rs);
|
if (!dueyItems.isEmpty()) { // in a duey package there's only one item
|
||||||
|
dueypack = new DueyPackage(packageId, dueyItems.get(0).getLeft());
|
||||||
|
} else {
|
||||||
|
dueypack = new DueyPackage(packageId);
|
||||||
|
}
|
||||||
|
|
||||||
dueypack.setSender(rs.getString("SenderName"));
|
dueypack.setSender(rs.getString("SenderName"));
|
||||||
dueypack.setMesos(rs.getInt("Mesos"));
|
dueypack.setMesos(rs.getInt("Mesos"));
|
||||||
dueypack.setSentTime(rs.getString("TimeStamp"));
|
dueypack.setSentTime(rs.getString("TimeStamp"));
|
||||||
|
dueypack.setMessage(rs.getString("Message"));
|
||||||
|
|
||||||
|
return dueypack;
|
||||||
|
} catch (SQLException sqle) {
|
||||||
|
sqle.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<DueyPackage> loadPackages(MapleCharacter chr) {
|
||||||
|
List<DueyPackage> packages = new LinkedList<>();
|
||||||
|
try {
|
||||||
|
Connection con = DatabaseConnection.getConnection();
|
||||||
|
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM dueypackages dp WHERE ReceiverId = ?")) {
|
||||||
|
ps.setInt(1, chr.getId());
|
||||||
|
try (ResultSet rs = ps.executeQuery()) {
|
||||||
|
while (rs.next()) {
|
||||||
|
DueyPackage dueypack = getPackageFromDB(rs);
|
||||||
|
if (dueypack == null) continue;
|
||||||
|
|
||||||
packages.add(dueypack);
|
packages.add(dueypack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
con.close();
|
con.close();
|
||||||
return packages;
|
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return null;
|
}
|
||||||
|
|
||||||
|
return packages;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int createPackage(int mesos, String message, String sender, int toCid) {
|
||||||
|
try {
|
||||||
|
Connection con = null;
|
||||||
|
PreparedStatement ps = null;
|
||||||
|
ResultSet rs = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
con = DatabaseConnection.getConnection();
|
||||||
|
ps = con.prepareStatement("INSERT INTO `dueypackages` (ReceiverId, SenderName, Mesos, TimeStamp, Message, Checked) VALUES (?, ?, ?, ?, ?, 1)", Statement.RETURN_GENERATED_KEYS);
|
||||||
|
ps.setInt(1, toCid);
|
||||||
|
ps.setString(2, sender);
|
||||||
|
ps.setInt(3, mesos);
|
||||||
|
ps.setString(4, getCurrentDate());
|
||||||
|
ps.setString(5, message);
|
||||||
|
|
||||||
|
int updateRows = ps.executeUpdate();
|
||||||
|
if (updateRows < 1) {
|
||||||
|
FilePrinter.printError(FilePrinter.INSERT_CHAR, "Error trying to create package [mesos: " + mesos + ", " + sender + ", to CharacterId: " + toCid + "]");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int packageId;
|
||||||
|
rs = ps.getGeneratedKeys();
|
||||||
|
if (rs.next()) {
|
||||||
|
packageId = rs.getInt(1);
|
||||||
|
} else {
|
||||||
|
FilePrinter.printError(FilePrinter.INSERT_CHAR, "Failed inserting package [mesos: " + mesos + ", " + sender + ", to CharacterId: " + toCid + "]");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return packageId;
|
||||||
|
} finally {
|
||||||
|
if (rs != null && !rs.isClosed()) {
|
||||||
|
rs.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ps != null && !ps.isClosed()) {
|
||||||
|
ps.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (con != null && !con.isClosed()) {
|
||||||
|
con.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SQLException sqle) {
|
||||||
|
sqle.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean insertPackageItem(int packageId, Item item) {
|
||||||
|
try {
|
||||||
|
Pair<Item, MapleInventoryType> dueyItem = new Pair<>(item, MapleInventoryType.getByType(item.getItemType()));
|
||||||
|
Connection con = DatabaseConnection.getConnection();
|
||||||
|
ItemFactory.DUEY.saveItems(Collections.singletonList(dueyItem), packageId, con);
|
||||||
|
con.close();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (SQLException sqle) {
|
||||||
|
sqle.printStackTrace();
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void dueySendItem(MapleClient c, byte inventId, short itemPos, short amount, int mesos, String recipient) {
|
private static int addPackageItemFromInventory(int packageId, MapleClient c, byte invTypeId, short itemPos, short amount) {
|
||||||
|
if (invTypeId > 0) {
|
||||||
|
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
||||||
|
|
||||||
|
MapleInventoryType invType = MapleInventoryType.getByType(invTypeId);
|
||||||
|
MapleInventory inv = c.getPlayer().getInventory(invType);
|
||||||
|
|
||||||
|
Item item;
|
||||||
|
inv.lockInventory();
|
||||||
|
try {
|
||||||
|
item = inv.getItem(itemPos);
|
||||||
|
if (item != null && item.getQuantity() >= amount) {
|
||||||
|
if (item.isUntradeable() || ii.isUnmerchable(item.getItemId())) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ItemConstants.isRechargeable(item.getItemId())) {
|
||||||
|
MapleInventoryManipulator.removeFromSlot(c, invType, itemPos, item.getQuantity(), true);
|
||||||
|
} else {
|
||||||
|
MapleInventoryManipulator.removeFromSlot(c, invType, itemPos, amount, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
item = item.copy();
|
||||||
|
} else {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
inv.unlockInventory();
|
||||||
|
}
|
||||||
|
|
||||||
|
MapleKarmaManipulator.toggleKarmaFlagToUntradeable(item);
|
||||||
|
item.setQuantity(amount);
|
||||||
|
|
||||||
|
if (!insertPackageItem(packageId, item)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void dueySendItem(MapleClient c, byte invTypeId, short itemPos, short amount, int sendMesos, String sendMessage, String recipient) {
|
||||||
if (c.tryacquireClient()) {
|
if (c.tryacquireClient()) {
|
||||||
try {
|
try {
|
||||||
final int fee = 5000;
|
final int fee = 5000 + MapleTrade.getFee(sendMesos);
|
||||||
final long sendMesos = (long) mesos + fee;
|
|
||||||
if (mesos < 0 || sendMesos > Integer.MAX_VALUE || (amount < 1 && mesos == 0)) {
|
long finalcost = (long) sendMesos + fee;
|
||||||
|
if (finalcost < 0 || finalcost > Integer.MAX_VALUE || (amount < 1 && sendMesos == 0)) {
|
||||||
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit with duey.");
|
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit with duey.");
|
||||||
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to use duey with mesos " + mesos + " and amount " + amount);
|
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to use duey with mesos " + sendMesos + " and amount " + amount);
|
||||||
c.disconnect(true, false);
|
c.disconnect(true, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int finalcost = mesos + fee;
|
Pair<Integer, Integer> accIdCid;
|
||||||
if (c.getPlayer().getMeso() >= finalcost) {
|
if (c.getPlayer().getMeso() >= finalcost) {
|
||||||
int accid = getAccIdFromCNAME(recipient, true);
|
accIdCid = getAccountCharacterIdFromCNAME(recipient);
|
||||||
if (accid != -1) {
|
int recipientAccId = accIdCid.getLeft();
|
||||||
if (accid == c.getAccID()) {
|
if (recipientAccId != -1) {
|
||||||
|
if (recipientAccId == c.getAccID()) {
|
||||||
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_SAMEACC_ERROR.getCode()));
|
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_SAMEACC_ERROR.getCode()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -356,6 +379,28 @@ public class DueyProcessor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int recipientCid = accIdCid.getRight();
|
||||||
|
if (recipientCid == -1) {
|
||||||
|
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_NAME_DOES_NOT_EXIST.getCode()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int packageId = createPackage(sendMesos, sendMessage, c.getPlayer().getName(), recipientCid);
|
||||||
|
if (packageId == -1) {
|
||||||
|
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_ENABLE_ACTIONS.getCode()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
c.getPlayer().gainMeso((int) -finalcost, false);
|
||||||
|
|
||||||
|
int res = addPackageItemFromInventory(packageId, c, invTypeId, itemPos, amount);
|
||||||
|
if (res == 0) {
|
||||||
|
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_SUCCESSFULLY_SENT.getCode()));
|
||||||
|
} else if (res > 0) {
|
||||||
|
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_ENABLE_ACTIONS.getCode()));
|
||||||
|
} else {
|
||||||
|
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_INCORRECT_REQUEST.getCode()));
|
||||||
|
}
|
||||||
|
|
||||||
MapleClient rClient = null;
|
MapleClient rClient = null;
|
||||||
int channel = c.getWorldServer().find(recipient);
|
int channel = c.getWorldServer().find(recipient);
|
||||||
if (channel > -1) {
|
if (channel > -1) {
|
||||||
@@ -368,39 +413,6 @@ public class DueyProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inventId > 0) {
|
|
||||||
MapleInventoryType inv = MapleInventoryType.getByType(inventId);
|
|
||||||
Item item = c.getPlayer().getInventory(inv).getItem(itemPos);
|
|
||||||
if (item != null && c.getPlayer().getItemQuantity(item.getItemId(), false) >= amount) {
|
|
||||||
if (item.isUntradeable()) {
|
|
||||||
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_INCORRECT_REQUEST.getCode()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
c.getPlayer().gainMeso(-finalcost, false);
|
|
||||||
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_SUCCESSFULLY_SENT.getCode()));
|
|
||||||
|
|
||||||
if (ItemConstants.isRechargeable(item.getItemId())) {
|
|
||||||
MapleInventoryManipulator.removeFromSlot(c, inv, itemPos, item.getQuantity(), true);
|
|
||||||
} else {
|
|
||||||
MapleInventoryManipulator.removeFromSlot(c, inv, itemPos, amount, true, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
MapleKarmaManipulator.toggleKarmaFlagToUntradeable(item);
|
|
||||||
addItemToDB(item, amount, mesos - MapleTrade.getFee(mesos), c.getPlayer().getName(), getAccIdFromCNAME(recipient, false));
|
|
||||||
} else {
|
|
||||||
if (item != null) {
|
|
||||||
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_INCORRECT_REQUEST.getCode()));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
c.getPlayer().gainMeso(-finalcost, false);
|
|
||||||
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_SUCCESSFULLY_SENT.getCode()));
|
|
||||||
|
|
||||||
addMesoToDB(mesos - MapleTrade.getFee(mesos), c.getPlayer().getName(), getAccIdFromCNAME(recipient, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rClient != null && rClient.isLoggedIn() && !rClient.getPlayer().isAwayFromWorld()) {
|
if (rClient != null && rClient.isLoggedIn() && !rClient.getPlayer().isAwayFromWorld()) {
|
||||||
showDueyNotification(rClient, rClient.getPlayer());
|
showDueyNotification(rClient, rClient.getPlayer());
|
||||||
}
|
}
|
||||||
@@ -410,55 +422,50 @@ public class DueyProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void dueyRemovePackage(MapleClient c, int packageid) {
|
public static void dueyRemovePackage(MapleClient c, int packageid, boolean playerRemove) {
|
||||||
if (c.tryacquireClient()) {
|
if (c.tryacquireClient()) {
|
||||||
try {
|
try {
|
||||||
removeItemFromDB(packageid);
|
removePackageFromDB(packageid);
|
||||||
c.announce(MaplePacketCreator.removeItemFromDuey(true, packageid));
|
c.announce(MaplePacketCreator.removeItemFromDuey(playerRemove, packageid));
|
||||||
} finally {
|
} finally {
|
||||||
c.releaseClient();
|
c.releaseClient();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void dueyClaimPackage(MapleClient c, int packageid) {
|
public static void dueyClaimPackage(MapleClient c, int packageId) {
|
||||||
if (c.tryacquireClient()) {
|
if (c.tryacquireClient()) {
|
||||||
try {
|
try {
|
||||||
List<DueyPackages> packages = new LinkedList<>();
|
|
||||||
DueyPackages dp = null;
|
|
||||||
Connection con = null;
|
|
||||||
try {
|
try {
|
||||||
con = DatabaseConnection.getConnection();
|
DueyPackage dp = null;
|
||||||
DueyPackages dueypack;
|
|
||||||
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM dueypackages LEFT JOIN dueyitems USING (PackageId) WHERE PackageId = ?")) {
|
|
||||||
ps.setInt(1, packageid);
|
|
||||||
try (ResultSet rs = ps.executeQuery()) {
|
|
||||||
dueypack = null;
|
|
||||||
if (rs.next()) {
|
|
||||||
dueypack = getItemByPID(rs);
|
|
||||||
dueypack.setSender(rs.getString("SenderName"));
|
|
||||||
dueypack.setMesos(rs.getInt("Mesos"));
|
|
||||||
dueypack.setSentTime(rs.getString("TimeStamp"));
|
|
||||||
|
|
||||||
packages.add(dueypack);
|
Connection con = DatabaseConnection.getConnection();
|
||||||
|
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM dueypackages dp WHERE PackageId = ?")) {
|
||||||
|
ps.setInt(1, packageId);
|
||||||
|
|
||||||
|
try (ResultSet rs = ps.executeQuery()) {
|
||||||
|
if (rs.next()) {
|
||||||
|
dp = getPackageFromDB(rs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dp = dueypack;
|
con.close();
|
||||||
|
|
||||||
if(dp == null) {
|
if(dp == null) {
|
||||||
c.announce(MaplePacketCreator.sendDueyMSG(Actions.TOCLIENT_RECV_UNKNOWN_ERROR.getCode()));
|
c.announce(MaplePacketCreator.sendDueyMSG(Actions.TOCLIENT_RECV_UNKNOWN_ERROR.getCode()));
|
||||||
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to receive package from duey with id " + packageid);
|
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to receive package from duey with id " + packageId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dp.getItem() != null) {
|
Item dpItem = dp.getItem();
|
||||||
|
if (dpItem != null) {
|
||||||
if (!c.getPlayer().canHoldMeso(dp.getMesos())) {
|
if (!c.getPlayer().canHoldMeso(dp.getMesos())) {
|
||||||
c.announce(MaplePacketCreator.sendDueyMSG(Actions.TOCLIENT_RECV_UNKNOWN_ERROR.getCode()));
|
c.announce(MaplePacketCreator.sendDueyMSG(Actions.TOCLIENT_RECV_UNKNOWN_ERROR.getCode()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!MapleInventoryManipulator.checkSpace(c, dp.getItem().getItemId(), dp.getItem().getQuantity(), dp.getItem().getOwner())) {
|
if (!MapleInventoryManipulator.checkSpace(c, dpItem.getItemId(), dpItem.getQuantity(), dpItem.getOwner())) {
|
||||||
int itemid = dp.getItem().getItemId();
|
int itemid = dpItem.getItemId();
|
||||||
if(MapleItemInformationProvider.getInstance().isPickupRestricted(itemid) && c.getPlayer().getInventory(ItemConstants.getInventoryType(itemid)).findById(itemid) != null) {
|
if(MapleItemInformationProvider.getInstance().isPickupRestricted(itemid) && c.getPlayer().getInventory(ItemConstants.getInventoryType(itemid)).findById(itemid) != null) {
|
||||||
c.announce(MaplePacketCreator.sendDueyMSG(Actions.TOCLIENT_RECV_RECEIVER_WITH_UNIQUE.getCode()));
|
c.announce(MaplePacketCreator.sendDueyMSG(Actions.TOCLIENT_RECV_RECEIVER_WITH_UNIQUE.getCode()));
|
||||||
} else {
|
} else {
|
||||||
@@ -467,16 +474,13 @@ public class DueyProcessor {
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
MapleInventoryManipulator.addFromDrop(c, dp.getItem(), false);
|
MapleInventoryManipulator.addFromDrop(c, dpItem, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.getPlayer().gainMeso(dp.getMesos(), false);
|
c.getPlayer().gainMeso(dp.getMesos(), false);
|
||||||
|
|
||||||
removeItemFromDB(packageid);
|
dueyRemovePackage(c, packageId, false);
|
||||||
c.announce(MaplePacketCreator.removeItemFromDuey(false, packageid));
|
|
||||||
|
|
||||||
con.close();
|
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -489,10 +493,17 @@ public class DueyProcessor {
|
|||||||
public static void dueySendTalk(MapleClient c) {
|
public static void dueySendTalk(MapleClient c) {
|
||||||
if (c.tryacquireClient()) {
|
if (c.tryacquireClient()) {
|
||||||
try {
|
try {
|
||||||
c.announce(MaplePacketCreator.sendDuey((byte) 8, loadItems(c.getPlayer())));
|
c.announce(MaplePacketCreator.sendDuey((byte) 8, loadPackages(c.getPlayer())));
|
||||||
} finally {
|
} finally {
|
||||||
c.releaseClient();
|
c.releaseClient();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void dueyCreatePackage(Item item, int mesos, String sender, int recipientCid) {
|
||||||
|
int packageId = createPackage(mesos, "", sender, recipientCid);
|
||||||
|
if (packageId != -1) {
|
||||||
|
insertPackageItem(packageId, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ public class FredrickProcessor {
|
|||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void removeFredrickLog(int cid) {
|
public static void removeFredrickLog(int cid) {
|
||||||
try {
|
try {
|
||||||
Connection con = DatabaseConnection.getConnection();
|
Connection con = DatabaseConnection.getConnection();
|
||||||
removeFredrickLog(con, cid);
|
removeFredrickLog(con, cid);
|
||||||
|
|||||||
@@ -139,6 +139,8 @@ public class StorageProcessor {
|
|||||||
c.announce(MaplePacketCreator.enableActions());
|
c.announce(MaplePacketCreator.enableActions());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
item = item.copy(); // thanks Robin Schulz & BHB88 for noticing a inventory glitch when storing items
|
||||||
} finally {
|
} finally {
|
||||||
inv.unlockInventory();
|
inv.unlockInventory();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,8 +92,6 @@ public class GameConstants {
|
|||||||
|
|
||||||
// used by the "goto" command for only-GMs
|
// used by the "goto" command for only-GMs
|
||||||
public static final HashMap<String, Integer> GOTO_AREAS = new HashMap<String, Integer>() {{
|
public static final HashMap<String, Integer> GOTO_AREAS = new HashMap<String, Integer>() {{
|
||||||
putAll(GOTO_TOWNS);
|
|
||||||
|
|
||||||
put("gmmap", 180000000);
|
put("gmmap", 180000000);
|
||||||
put("excavation", 990000000);
|
put("excavation", 990000000);
|
||||||
put("mushmom", 100000005);
|
put("mushmom", 100000005);
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public class ServerConstants {
|
|||||||
public static final boolean AUTOMATIC_REGISTER = true; //Automatically register players when they login with a nonexistent username.
|
public static final boolean AUTOMATIC_REGISTER = true; //Automatically register players when they login with a nonexistent username.
|
||||||
public static final boolean BCRYPT_MIGRATION = true; //Performs a migration from old SHA-1 and SHA-512 password to bcrypt.
|
public static final boolean BCRYPT_MIGRATION = true; //Performs a migration from old SHA-1 and SHA-512 password to bcrypt.
|
||||||
public static final boolean COLLECTIVE_CHARSLOT = false; //Available character slots are contabilized globally rather than per world server.
|
public static final boolean COLLECTIVE_CHARSLOT = false; //Available character slots are contabilized globally rather than per world server.
|
||||||
public static final boolean DETERRED_MULTICLIENT = false; //Enables multi-client and suspicious remote IP detection on the login system.
|
public static final boolean DETERRED_MULTICLIENT = false; //Enables detection of multi-client and suspicious remote IP on the login system.
|
||||||
|
|
||||||
//Besides blocking logging in with several client sessions on the same machine, this also blocks suspicious login attempts for players that tries to login on an account using several diferent remote addresses.
|
//Besides blocking logging in with several client sessions on the same machine, this also blocks suspicious login attempts for players that tries to login on an account using several diferent remote addresses.
|
||||||
|
|
||||||
@@ -98,6 +98,7 @@ public class ServerConstants {
|
|||||||
public static final boolean USE_ENFORCE_UNMERCHABLE_PET = false; //Forces players to not sell pets via merchants. (since non-named pets gets dirty name and other possible DB-related issues)
|
public static final boolean USE_ENFORCE_UNMERCHABLE_PET = false; //Forces players to not sell pets via merchants. (since non-named pets gets dirty name and other possible DB-related issues)
|
||||||
public static final boolean USE_ENFORCE_MERCHANT_SAVE = true; //Forces automatic DB save on merchant owners, at every item movement on shop.
|
public static final boolean USE_ENFORCE_MERCHANT_SAVE = true; //Forces automatic DB save on merchant owners, at every item movement on shop.
|
||||||
public static final boolean USE_ENFORCE_MDOOR_POSITION = false; //Forces mystic door to be spawned near spawnpoints.
|
public static final boolean USE_ENFORCE_MDOOR_POSITION = false; //Forces mystic door to be spawned near spawnpoints.
|
||||||
|
public static final boolean USE_SPAWN_CLEAN_MDOOR = false; //Makes mystic doors to be spawned without deploy animation. This clears disconnecting issues that may happen when trying to cancel doors a couple seconds after deployment.
|
||||||
public static final boolean USE_SPAWN_LOOT_ON_ANIMATION = false;//Makes loot appear some time after the mob has been killed (following the mob death animation, instead of instantly).
|
public static final boolean USE_SPAWN_LOOT_ON_ANIMATION = false;//Makes loot appear some time after the mob has been killed (following the mob death animation, instead of instantly).
|
||||||
public static final boolean USE_SPAWN_RELEVANT_LOOT = true; //Forces to only spawn loots that are collectable by the player or any of their party members.
|
public static final boolean USE_SPAWN_RELEVANT_LOOT = true; //Forces to only spawn loots that are collectable by the player or any of their party members.
|
||||||
public static final boolean USE_ERASE_PERMIT_ON_OPENSHOP = true;//Forces "shop permit" item to be consumed when player deploy his/her player shop.
|
public static final boolean USE_ERASE_PERMIT_ON_OPENSHOP = true;//Forces "shop permit" item to be consumed when player deploy his/her player shop.
|
||||||
@@ -149,15 +150,18 @@ public class ServerConstants {
|
|||||||
public static final int TRAVEL_RATE = 10; //Means of transportation rides/departs using 1/N of the default time.
|
public static final int TRAVEL_RATE = 10; //Means of transportation rides/departs using 1/N of the default time.
|
||||||
|
|
||||||
public static final double EQUIP_EXP_RATE = 1.0; //Rate for equipment exp gain, grows linearly. Set 1.0 for default (about 100~200 same-level range mobs killed to pass equip from level 1 to 2).
|
public static final double EQUIP_EXP_RATE = 1.0; //Rate for equipment exp gain, grows linearly. Set 1.0 for default (about 100~200 same-level range mobs killed to pass equip from level 1 to 2).
|
||||||
public static final float PARTY_BONUS_EXP_RATE = 1.0f; //Rate for the party exp bonus reward.
|
|
||||||
public static final double PQ_BONUS_EXP_RATE = 0.5; //Rate for the PQ exp reward.
|
public static final double PQ_BONUS_EXP_RATE = 0.5; //Rate for the PQ exp reward.
|
||||||
|
|
||||||
|
public static final byte EXP_SPLIT_LEVEL_INTERVAL = 5; //Non-contributing players must be within N level between the mob to receive EXP.
|
||||||
|
public static final byte EXP_SPLIT_LEECH_INTERVAL = 5; //Non-contributing players must be within N level between any contributing party member to receive EXP.
|
||||||
|
public static final float EXP_SPLIT_MVP_MOD = 0.2f;
|
||||||
|
public static final float EXP_SPLIT_COMMON_MOD = 0.8f;
|
||||||
|
public static final float PARTY_BONUS_EXP_RATE = 1.0f; //Rate for the party exp bonus reward.
|
||||||
|
|
||||||
//Miscellaneous Configuration
|
//Miscellaneous Configuration
|
||||||
public static String TIMEZONE = "GMT-3";
|
public static String TIMEZONE = "GMT-3";
|
||||||
public static boolean USE_DISPLAY_NUMBERS_WITH_COMMA = true; //Enforce comma on displayed strings (use this when USE_UNITPRICE_WITH_COMMA is active and you still want to display comma-separated values).
|
public static boolean USE_DISPLAY_NUMBERS_WITH_COMMA = true; //Enforce comma on displayed strings (use this when USE_UNITPRICE_WITH_COMMA is active and you still want to display comma-separated values).
|
||||||
public static boolean USE_UNITPRICE_WITH_COMMA = true; //Set this accordingly with the layout of the unitPrices on Item.wz XML's, whether it's using commas or dots to represent fractions.
|
public static boolean USE_UNITPRICE_WITH_COMMA = true; //Set this accordingly with the layout of the unitPrices on Item.wz XML's, whether it's using commas or dots to represent fractions.
|
||||||
public static final byte MIN_UNDERLEVEL_TO_EXP_GAIN = 20; //Characters are unable to get EXP from a mob if their level are under this threshold, only if "USE_ENFORCE_MOB_LEVEL_RANGE" is enabled. For bosses, this attribute is doubled.
|
|
||||||
public static final byte MIN_RANGELEVEL_TO_EXP_LEECH = 40; //Characters are unable to leech EXP from party member kills whose level difference are past this limit.
|
|
||||||
public static final byte MAX_MONITORED_BUFFSTATS = 5; //Limits accounting for "dormant" buff effects, that should take place when stronger stat buffs expires.
|
public static final byte MAX_MONITORED_BUFFSTATS = 5; //Limits accounting for "dormant" buff effects, that should take place when stronger stat buffs expires.
|
||||||
public static final int MAX_AP = 32767; //Max AP allotted on the auto-assigner.
|
public static final int MAX_AP = 32767; //Max AP allotted on the auto-assigner.
|
||||||
public static final int MAX_EVENT_LEVELS = 8; //Event has different levels of rewarding system.
|
public static final int MAX_EVENT_LEVELS = 8; //Event has different levels of rewarding system.
|
||||||
|
|||||||
@@ -263,7 +263,8 @@ public final class PacketProcessor {
|
|||||||
registerHandler(RecvOpcode.WATER_OF_LIFE, new UseWaterOfLifeHandler());
|
registerHandler(RecvOpcode.WATER_OF_LIFE, new UseWaterOfLifeHandler());
|
||||||
registerHandler(RecvOpcode.ADMIN_CHAT, new AdminChatHandler());
|
registerHandler(RecvOpcode.ADMIN_CHAT, new AdminChatHandler());
|
||||||
registerHandler(RecvOpcode.MOVE_DRAGON, new MoveDragonHandler());
|
registerHandler(RecvOpcode.MOVE_DRAGON, new MoveDragonHandler());
|
||||||
registerHandler(RecvOpcode.USE_ITEMUI, new UseItemCanvasHandler());
|
registerHandler(RecvOpcode.OPEN_ITEMUI, new RaiseUIStateHandler());
|
||||||
|
registerHandler(RecvOpcode.USE_ITEMUI, new RaiseIncExpHandler());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -495,15 +495,12 @@ public class Server {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resetServerWorlds() {
|
private void resetServerWorlds() { // thanks maple006 for noticing proprietary lists assigned to null
|
||||||
wldWLock.lock();
|
wldWLock.lock();
|
||||||
try {
|
try {
|
||||||
worlds.clear();
|
worlds.clear();
|
||||||
worlds = null;
|
|
||||||
channels.clear();
|
channels.clear();
|
||||||
channels = null;
|
|
||||||
worldRecommendedList.clear();
|
worldRecommendedList.clear();
|
||||||
worldRecommendedList = null;
|
|
||||||
} finally {
|
} finally {
|
||||||
wldWLock.unlock();
|
wldWLock.unlock();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -239,7 +239,10 @@ public class ThreadTracker {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
AtomicInteger c = lockCount.get(lockOid);
|
AtomicInteger c = lockCount.get(lockOid);
|
||||||
|
if (c != null) { // thanks BHB for detecting an NPE here
|
||||||
c.decrementAndGet();
|
c.decrementAndGet();
|
||||||
|
}
|
||||||
|
|
||||||
lockUpdate.put(lockOid, 0);
|
lockUpdate.put(lockOid, 0);
|
||||||
|
|
||||||
List<MonitoredLockType> list = threadTracker.get(tid);
|
List<MonitoredLockType> list = threadTracker.get(tid);
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ package net.server.audit.locks;
|
|||||||
|
|
||||||
public enum MonitoredLockType {
|
public enum MonitoredLockType {
|
||||||
UNDEFINED,
|
UNDEFINED,
|
||||||
|
INTERVAL,
|
||||||
CHARACTER_CHR,
|
CHARACTER_CHR,
|
||||||
CHARACTER_CPN,
|
CHARACTER_CPN,
|
||||||
CHARACTER_EFF,
|
CHARACTER_EFF,
|
||||||
@@ -96,7 +97,7 @@ public enum MonitoredLockType {
|
|||||||
VISITOR_MERCH,
|
VISITOR_MERCH,
|
||||||
MAP_CHRS,
|
MAP_CHRS,
|
||||||
MAP_OBJS,
|
MAP_OBJS,
|
||||||
MAP_FACTORY,
|
MAP_MANAGER,
|
||||||
MAP_ITEM,
|
MAP_ITEM,
|
||||||
MAP_LOOT,
|
MAP_LOOT,
|
||||||
MAP_BOUNDS,
|
MAP_BOUNDS,
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import java.net.InetSocketAddress;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@@ -64,7 +63,6 @@ import org.apache.mina.filter.codec.ProtocolCodecFilter;
|
|||||||
import org.apache.mina.transport.socket.SocketSessionConfig;
|
import org.apache.mina.transport.socket.SocketSessionConfig;
|
||||||
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
|
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
|
||||||
|
|
||||||
import provider.MapleDataProviderFactory;
|
|
||||||
import scripting.event.EventScriptManager;
|
import scripting.event.EventScriptManager;
|
||||||
import server.TimerManager;
|
import server.TimerManager;
|
||||||
import server.events.gm.MapleEvent;
|
import server.events.gm.MapleEvent;
|
||||||
@@ -72,7 +70,7 @@ import server.expeditions.MapleExpedition;
|
|||||||
import server.expeditions.MapleExpeditionType;
|
import server.expeditions.MapleExpeditionType;
|
||||||
import server.maps.MapleHiredMerchant;
|
import server.maps.MapleHiredMerchant;
|
||||||
import server.maps.MapleMap;
|
import server.maps.MapleMap;
|
||||||
import server.maps.MapleMapFactory;
|
import server.maps.MapleMapManager;
|
||||||
import server.maps.MapleMiniDungeon;
|
import server.maps.MapleMiniDungeon;
|
||||||
import tools.MaplePacketCreator;
|
import tools.MaplePacketCreator;
|
||||||
import tools.Pair;
|
import tools.Pair;
|
||||||
@@ -88,7 +86,7 @@ public final class Channel {
|
|||||||
private int world, channel;
|
private int world, channel;
|
||||||
private IoAcceptor acceptor;
|
private IoAcceptor acceptor;
|
||||||
private String ip, serverMessage;
|
private String ip, serverMessage;
|
||||||
private MapleMapFactory mapFactory;
|
private MapleMapManager mapManager;
|
||||||
private EventScriptManager eventSM;
|
private EventScriptManager eventSM;
|
||||||
private MobStatusScheduler mobStatusSchedulers[] = new MobStatusScheduler[ServerConstants.CHANNEL_LOCKS];
|
private MobStatusScheduler mobStatusSchedulers[] = new MobStatusScheduler[ServerConstants.CHANNEL_LOCKS];
|
||||||
private MobAnimationScheduler mobAnimationSchedulers[] = new MobAnimationScheduler[ServerConstants.CHANNEL_LOCKS];
|
private MobAnimationScheduler mobAnimationSchedulers[] = new MobAnimationScheduler[ServerConstants.CHANNEL_LOCKS];
|
||||||
@@ -108,8 +106,6 @@ public final class Channel {
|
|||||||
private int usedDojo = 0;
|
private int usedDojo = 0;
|
||||||
private Set<Integer> usedMC = new HashSet<>();
|
private Set<Integer> usedMC = new HashSet<>();
|
||||||
|
|
||||||
private ScheduledFuture<?> respawnTask;
|
|
||||||
|
|
||||||
private int[] dojoStage;
|
private int[] dojoStage;
|
||||||
private long[] dojoFinishTime;
|
private long[] dojoFinishTime;
|
||||||
private ScheduledFuture<?>[] dojoTask;
|
private ScheduledFuture<?>[] dojoTask;
|
||||||
@@ -142,7 +138,7 @@ public final class Channel {
|
|||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
|
|
||||||
this.ongoingStartTime = startTime + 10000; // rude approach to a world's last channel boot time, placeholder for the 1st wedding reservation ever
|
this.ongoingStartTime = startTime + 10000; // rude approach to a world's last channel boot time, placeholder for the 1st wedding reservation ever
|
||||||
this.mapFactory = new MapleMapFactory(null, MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Map.wz")), MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/String.wz")), world, channel);
|
this.mapManager = new MapleMapManager(null, world, channel);
|
||||||
try {
|
try {
|
||||||
eventSM = new EventScriptManager(this, getEvents());
|
eventSM = new EventScriptManager(this, getEvents());
|
||||||
port = 7575 + this.channel - 1;
|
port = 7575 + this.channel - 1;
|
||||||
@@ -151,7 +147,6 @@ public final class Channel {
|
|||||||
IoBuffer.setUseDirectBuffer(false);
|
IoBuffer.setUseDirectBuffer(false);
|
||||||
IoBuffer.setAllocator(new SimpleBufferAllocator());
|
IoBuffer.setAllocator(new SimpleBufferAllocator());
|
||||||
acceptor = new NioSocketAcceptor();
|
acceptor = new NioSocketAcceptor();
|
||||||
respawnTask = TimerManager.getInstance().register(new respawnMaps(), ServerConstants.RESPAWN_INTERVAL);
|
|
||||||
acceptor.setHandler(new MapleServerHandler(world, channel));
|
acceptor.setHandler(new MapleServerHandler(world, channel));
|
||||||
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 30);
|
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 30);
|
||||||
acceptor.getFilterChain().addLast("codec", (IoFilter) new ProtocolCodecFilter(new MapleCodecFactory()));
|
acceptor.getFilterChain().addLast("codec", (IoFilter) new ProtocolCodecFilter(new MapleCodecFactory()));
|
||||||
@@ -204,13 +199,8 @@ public final class Channel {
|
|||||||
disconnectAwayPlayers();
|
disconnectAwayPlayers();
|
||||||
players.disconnectAll();
|
players.disconnectAll();
|
||||||
|
|
||||||
if(respawnTask != null) {
|
mapManager.dispose();
|
||||||
respawnTask.cancel(false);
|
mapManager = null;
|
||||||
respawnTask = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
mapFactory.dispose();
|
|
||||||
mapFactory = null;
|
|
||||||
|
|
||||||
eventSM.cancel();
|
eventSM.cancel();
|
||||||
eventSM = null;
|
eventSM = null;
|
||||||
@@ -315,8 +305,8 @@ public final class Channel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public MapleMapFactory getMapFactory() {
|
public MapleMapManager getMapFactory() {
|
||||||
return mapFactory;
|
return mapManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getWorld() {
|
public int getWorld() {
|
||||||
@@ -417,16 +407,6 @@ public final class Channel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class respawnMaps implements Runnable {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
for (MapleMap map : mapFactory.getMaps().values()) {
|
|
||||||
map.respawn();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<Integer, MapleHiredMerchant> getHiredMerchants() {
|
public Map<Integer, MapleHiredMerchant> getHiredMerchants() {
|
||||||
merchRlock.lock();
|
merchRlock.lock();
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -45,12 +45,12 @@ public final class DueyHandler extends AbstractMaplePacketHandler {
|
|||||||
short amount = slea.readShort();
|
short amount = slea.readShort();
|
||||||
int mesos = slea.readInt();
|
int mesos = slea.readInt();
|
||||||
String recipient = slea.readMapleAsciiString();
|
String recipient = slea.readMapleAsciiString();
|
||||||
|
String message = slea.readByte() != 0 ? slea.readMapleAsciiString() : "";
|
||||||
DueyProcessor.dueySendItem(c, inventId, itemPos, amount, mesos, recipient);
|
DueyProcessor.dueySendItem(c, inventId, itemPos, amount, mesos, message, recipient);
|
||||||
} else if (operation == DueyProcessor.Actions.TOSERVER_REMOVE_PACKAGE.getCode()) {
|
} else if (operation == DueyProcessor.Actions.TOSERVER_REMOVE_PACKAGE.getCode()) {
|
||||||
int packageid = slea.readInt();
|
int packageid = slea.readInt();
|
||||||
|
|
||||||
DueyProcessor.dueyRemovePackage(c, packageid);
|
DueyProcessor.dueyRemovePackage(c, packageid, true);
|
||||||
} else if (operation == DueyProcessor.Actions.TOSERVER_CLAIM_PACKAGE.getCode()) {
|
} else if (operation == DueyProcessor.Actions.TOSERVER_CLAIM_PACKAGE.getCode()) {
|
||||||
int packageid = slea.readInt();
|
int packageid = slea.readInt();
|
||||||
|
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
|
|||||||
ANSWER_TIE(0x33),
|
ANSWER_TIE(0x33),
|
||||||
GIVE_UP(0x34),
|
GIVE_UP(0x34),
|
||||||
EXIT_AFTER_GAME(0x38),
|
EXIT_AFTER_GAME(0x38),
|
||||||
CANCEL_EXIT(0x39),
|
CANCEL_EXIT_AFTER_GAME(0x39),
|
||||||
READY(0x3A),
|
READY(0x3A),
|
||||||
UN_READY(0x3B),
|
UN_READY(0x3B),
|
||||||
EXPEL(0x3C),
|
EXPEL(0x3C),
|
||||||
@@ -344,7 +344,7 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
|
|||||||
MapleTrade.cancelTrade(chr, MapleTrade.TradeResult.PARTNER_CANCEL);
|
MapleTrade.cancelTrade(chr, MapleTrade.TradeResult.PARTNER_CANCEL);
|
||||||
} else {
|
} else {
|
||||||
chr.closePlayerShop();
|
chr.closePlayerShop();
|
||||||
chr.closeMiniGame();
|
chr.closeMiniGame(false);
|
||||||
chr.closeHiredMerchant(true);
|
chr.closeHiredMerchant(true);
|
||||||
}
|
}
|
||||||
} else if (mode == Action.OPEN_STORE.getCode() || mode == Action.OPEN_CASH.getCode()) {
|
} else if (mode == Action.OPEN_STORE.getCode() || mode == Action.OPEN_CASH.getCode()) {
|
||||||
@@ -495,13 +495,14 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ServerConstants.USE_ENFORCE_UNMERCHABLE_CASH && ii.isCash(item.getItemId())) {
|
if (ii.isUnmerchable(item.getItemId())) {
|
||||||
|
if (ItemConstants.isPet(item.getItemId())) {
|
||||||
|
c.announce(MaplePacketCreator.serverNotice(1, "Pets are not allowed to be traded."));
|
||||||
|
} else {
|
||||||
c.announce(MaplePacketCreator.serverNotice(1, "Cash items are not allowed to be traded."));
|
c.announce(MaplePacketCreator.serverNotice(1, "Cash items are not allowed to be traded."));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ServerConstants.USE_ENFORCE_UNMERCHABLE_PET && ItemConstants.isPet(item.getItemId())) {
|
c.announce(MaplePacketCreator.enableActions());
|
||||||
c.announce(MaplePacketCreator.serverNotice(1, "Pets are not allowed to be traded."));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -567,6 +568,15 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
|
|||||||
|
|
||||||
if (ivItem == null || ivItem.isUntradeable()) {
|
if (ivItem == null || ivItem.isUntradeable()) {
|
||||||
c.announce(MaplePacketCreator.serverNotice(1, "Could not perform shop operation with that item."));
|
c.announce(MaplePacketCreator.serverNotice(1, "Could not perform shop operation with that item."));
|
||||||
|
c.announce(MaplePacketCreator.enableActions());
|
||||||
|
return;
|
||||||
|
} else if (MapleItemInformationProvider.getInstance().isUnmerchable(ivItem.getItemId())) {
|
||||||
|
if (ItemConstants.isPet(ivItem.getItemId())) {
|
||||||
|
c.announce(MaplePacketCreator.serverNotice(1, "Pets are not allowed to be sold on the Player Store."));
|
||||||
|
} else {
|
||||||
|
c.announce(MaplePacketCreator.serverNotice(1, "Cash items are not allowed to be sold on the Player Store."));
|
||||||
|
}
|
||||||
|
|
||||||
c.announce(MaplePacketCreator.enableActions());
|
c.announce(MaplePacketCreator.enableActions());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -589,16 +599,6 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ServerConstants.USE_ENFORCE_UNMERCHABLE_CASH && MapleItemInformationProvider.getInstance().isCash(ivItem.getItemId())) {
|
|
||||||
c.announce(MaplePacketCreator.serverNotice(1, "Cash items are not allowed to be sold on the Player Store."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ServerConstants.USE_ENFORCE_UNMERCHABLE_PET && ItemConstants.isPet(ivItem.getItemId())) {
|
|
||||||
c.announce(MaplePacketCreator.serverNotice(1, "Pets are not allowed to be sold on the Player Store."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Item sellItem = ivItem.copy();
|
Item sellItem = ivItem.copy();
|
||||||
if(!ItemConstants.isRechargeable(ivItem.getItemId())) {
|
if(!ItemConstants.isRechargeable(ivItem.getItemId())) {
|
||||||
sellItem.setQuantity(perBundle);
|
sellItem.setQuantity(perBundle);
|
||||||
@@ -608,8 +608,6 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
|
|||||||
MaplePlayerShop shop = chr.getPlayerShop();
|
MaplePlayerShop shop = chr.getPlayerShop();
|
||||||
MapleHiredMerchant merchant = chr.getHiredMerchant();
|
MapleHiredMerchant merchant = chr.getHiredMerchant();
|
||||||
if (shop != null && shop.isOwner(chr)) {
|
if (shop != null && shop.isOwner(chr)) {
|
||||||
System.out.println(shopItem.getItem().getPet() + " " + shopItem.getItem().getPetId());
|
|
||||||
System.out.println(ivItem.getPet() + " " + ivItem.getPetId());
|
|
||||||
if (shop.isOpen() || !shop.addItem(shopItem)) { // thanks Vcoc for pointing an exploit with unlimited shop slots
|
if (shop.isOpen() || !shop.addItem(shopItem)) { // thanks Vcoc for pointing an exploit with unlimited shop slots
|
||||||
c.announce(MaplePacketCreator.serverNotice(1, "You can't sell it anymore."));
|
c.announce(MaplePacketCreator.serverNotice(1, "You can't sell it anymore."));
|
||||||
return;
|
return;
|
||||||
@@ -770,10 +768,20 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
|
|||||||
MapleCharacter visitor = miniGame.getVisitor();
|
MapleCharacter visitor = miniGame.getVisitor();
|
||||||
|
|
||||||
if(visitor != null) {
|
if(visitor != null) {
|
||||||
visitor.closeMiniGame();
|
visitor.closeMiniGame(false);
|
||||||
visitor.announce(MaplePacketCreator.getMiniGameClose(5));
|
visitor.announce(MaplePacketCreator.getMiniGameClose(true, 5));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (mode == Action.EXIT_AFTER_GAME.getCode()) {
|
||||||
|
MapleMiniGame miniGame = chr.getMiniGame();
|
||||||
|
if(miniGame != null) {
|
||||||
|
miniGame.setQuitAfterGame(chr, true);
|
||||||
|
}
|
||||||
|
} else if (mode == Action.CANCEL_EXIT_AFTER_GAME.getCode()) {
|
||||||
|
MapleMiniGame miniGame = chr.getMiniGame();
|
||||||
|
if(miniGame != null) {
|
||||||
|
miniGame.setQuitAfterGame(chr, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
c.releaseClient();
|
c.releaseClient();
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package net.server.channel.handlers;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import client.MapleClient;
|
||||||
|
import client.inventory.MapleInventory;
|
||||||
|
import client.inventory.MapleInventoryType;
|
||||||
|
import net.AbstractMaplePacketHandler;
|
||||||
|
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||||
|
import server.MapleItemInformationProvider;
|
||||||
|
import server.MapleItemInformationProvider.QuestConsItem;
|
||||||
|
import tools.data.input.SeekableLittleEndianAccessor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Xari
|
||||||
|
* @author Ronan - added concurrency protection and quest progress limit
|
||||||
|
*/
|
||||||
|
public class RaiseIncExpHandler extends AbstractMaplePacketHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||||
|
byte inventorytype = slea.readByte();//nItemIT
|
||||||
|
short slot = slea.readShort();//nSlotPosition
|
||||||
|
int itemid = slea.readInt();//nItemID
|
||||||
|
|
||||||
|
if (c.tryacquireClient()) {
|
||||||
|
try {
|
||||||
|
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
||||||
|
QuestConsItem consItem = ii.getQuestConsumablesInfo(itemid);
|
||||||
|
if (consItem == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int questid = consItem.questid;
|
||||||
|
Map<Integer, Integer> consumables = consItem.items;
|
||||||
|
|
||||||
|
int consId;
|
||||||
|
MapleInventory inv = c.getPlayer().getInventory(MapleInventoryType.getByType(inventorytype));
|
||||||
|
inv.lockInventory();
|
||||||
|
try {
|
||||||
|
consId = inv.getItem(slot).getItemId();
|
||||||
|
if (!consumables.containsKey(consId) || !c.getPlayer().haveItem(consId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.getByType(inventorytype), (short) slot, (short) 1, false, true);
|
||||||
|
} finally {
|
||||||
|
inv.unlockInventory();
|
||||||
|
}
|
||||||
|
|
||||||
|
int nextValue = Math.min(consumables.get(consId) + Integer.parseInt(c.getPlayer().getQuestInfo(questid)), consItem.exp * consItem.grade);
|
||||||
|
c.getPlayer().updateQuestInfo(questid, "" + nextValue);
|
||||||
|
} finally {
|
||||||
|
c.releaseClient();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package net.server.channel.handlers;
|
||||||
|
|
||||||
|
import client.MapleClient;
|
||||||
|
import client.MapleQuestStatus;
|
||||||
|
import net.AbstractMaplePacketHandler;
|
||||||
|
import server.quest.MapleQuest;
|
||||||
|
import tools.MaplePacketCreator;
|
||||||
|
import tools.data.input.SeekableLittleEndianAccessor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Xari
|
||||||
|
*/
|
||||||
|
public class RaiseUIStateHandler extends AbstractMaplePacketHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||||
|
int questid = slea.readShort();
|
||||||
|
|
||||||
|
if (c.tryacquireClient()) {
|
||||||
|
try {
|
||||||
|
MapleQuest quest = MapleQuest.getInstance(questid);
|
||||||
|
MapleQuestStatus mqs = c.getPlayer().getQuest(quest);
|
||||||
|
if (mqs.getStatus() == MapleQuestStatus.Status.NOT_STARTED) {
|
||||||
|
quest.forceStart(c.getPlayer(), 22000);
|
||||||
|
c.getPlayer().updateQuestInfo(quest.getId(), "0");
|
||||||
|
} else if (mqs.getStatus() == MapleQuestStatus.Status.STARTED) {
|
||||||
|
c.announce(MaplePacketCreator.updateQuest(mqs, false));
|
||||||
|
} else {
|
||||||
|
//c.announce(MaplePacketCreator.updateQuestInfo(mqs.getQuestID(), 22000, "0"));
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
c.releaseClient();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -423,7 +423,7 @@ public final class RingActionHandler extends AbstractMaplePacketHandler {
|
|||||||
Item weddingTicket = new Item(newItemId, (short) 0, (short) 1);
|
Item weddingTicket = new Item(newItemId, (short) 0, (short) 1);
|
||||||
weddingTicket.setExpiration(expiration);
|
weddingTicket.setExpiration(expiration);
|
||||||
|
|
||||||
DueyProcessor.addItemToDB(weddingTicket, 1, 0, groom, guest);
|
DueyProcessor.dueyCreatePackage(weddingTicket, 0, groom, guest);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
c.getPlayer().dropMessage(5, "Wedding is already under way. You cannot invite any more guests for the event.");
|
c.getPlayer().dropMessage(5, "Wedding is already under way. You cannot invite any more guests for the event.");
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import client.MapleClient;
|
|||||||
import client.Skill;
|
import client.Skill;
|
||||||
import client.SkillFactory;
|
import client.SkillFactory;
|
||||||
import client.inventory.Item;
|
import client.inventory.Item;
|
||||||
|
import client.inventory.MapleInventory;
|
||||||
import client.inventory.MapleInventoryType;
|
import client.inventory.MapleInventoryType;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import net.AbstractMaplePacketHandler;
|
import net.AbstractMaplePacketHandler;
|
||||||
@@ -41,20 +42,25 @@ public final class SkillBookHandler extends AbstractMaplePacketHandler {
|
|||||||
c.announce(MaplePacketCreator.enableActions());
|
c.announce(MaplePacketCreator.enableActions());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
slea.readInt();
|
slea.readInt();
|
||||||
short slot = (short) slea.readShort();
|
short slot = (short) slea.readShort();
|
||||||
int itemId = slea.readInt();
|
int itemId = slea.readInt();
|
||||||
MapleCharacter player = c.getPlayer();
|
|
||||||
Item toUse = c.getPlayer().getInventory(MapleInventoryType.USE).getItem(slot);
|
|
||||||
if (toUse != null && toUse.getQuantity() == 1) {
|
|
||||||
if (toUse.getItemId() != itemId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Map<String, Integer> skilldata = MapleItemInformationProvider.getInstance().getSkillStats(toUse.getItemId(), c.getPlayer().getJob().getId());
|
|
||||||
boolean canuse;
|
boolean canuse;
|
||||||
boolean success = false;
|
boolean success = false;
|
||||||
int skill = 0;
|
int skill = 0;
|
||||||
int maxlevel = 0;
|
int maxlevel = 0;
|
||||||
|
|
||||||
|
MapleCharacter player = c.getPlayer();
|
||||||
|
if (c.tryacquireClient()) {
|
||||||
|
try {
|
||||||
|
MapleInventory inv = c.getPlayer().getInventory(MapleInventoryType.USE);
|
||||||
|
Item toUse = inv.getItem(slot);
|
||||||
|
if (toUse == null || toUse.getItemId() != itemId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Map<String, Integer> skilldata = MapleItemInformationProvider.getInstance().getSkillStats(toUse.getItemId(), c.getPlayer().getJob().getId());
|
||||||
if (skilldata == null) {
|
if (skilldata == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -62,6 +68,18 @@ public final class SkillBookHandler extends AbstractMaplePacketHandler {
|
|||||||
if (skilldata.get("skillid") == 0) {
|
if (skilldata.get("skillid") == 0) {
|
||||||
canuse = false;
|
canuse = false;
|
||||||
} else if ((player.getSkillLevel(skill2) >= skilldata.get("reqSkillLevel") || skilldata.get("reqSkillLevel") == 0) && player.getMasterLevel(skill2) < skilldata.get("masterLevel")) {
|
} else if ((player.getSkillLevel(skill2) >= skilldata.get("reqSkillLevel") || skilldata.get("reqSkillLevel") == 0) && player.getMasterLevel(skill2) < skilldata.get("masterLevel")) {
|
||||||
|
inv.lockInventory();
|
||||||
|
try {
|
||||||
|
Item used = inv.getItem(slot);
|
||||||
|
if (used != toUse || toUse.getQuantity() < 1) { // thanks ClouD for noticing skillbooks not being usable when stacked
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.USE, slot, (short) 1, false);
|
||||||
|
} finally {
|
||||||
|
inv.unlockInventory();
|
||||||
|
}
|
||||||
|
|
||||||
canuse = true;
|
canuse = true;
|
||||||
if (MapleItemInformationProvider.rollSuccessChance(skilldata.get("success"))) {
|
if (MapleItemInformationProvider.rollSuccessChance(skilldata.get("success"))) {
|
||||||
success = true;
|
success = true;
|
||||||
@@ -70,10 +88,12 @@ public final class SkillBookHandler extends AbstractMaplePacketHandler {
|
|||||||
success = false;
|
success = false;
|
||||||
//player.dropMessage("The skill book lights up, but the skill winds up as if nothing happened.");
|
//player.dropMessage("The skill book lights up, but the skill winds up as if nothing happened.");
|
||||||
}
|
}
|
||||||
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.USE, slot, (short) 1, false);
|
|
||||||
} else {
|
} else {
|
||||||
canuse = false;
|
canuse = false;
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
c.releaseClient();
|
||||||
|
}
|
||||||
|
|
||||||
// thanks Vcoc for noting skill book result not showing for all in area
|
// thanks Vcoc for noting skill book result not showing for all in area
|
||||||
player.getMap().broadcastMessage(MaplePacketCreator.skillBookResult(player, skill, maxlevel, canuse, success));
|
player.getMap().broadcastMessage(MaplePacketCreator.skillBookResult(player, skill, maxlevel, canuse, success));
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ public final class SpecialMoveHandler extends AbstractMaplePacketHandler {
|
|||||||
monster.aggroClearDamages();
|
monster.aggroClearDamages();
|
||||||
monster.aggroMonsterDamage(chr, 1);
|
monster.aggroMonsterDamage(chr, 1);
|
||||||
|
|
||||||
|
// thanks onechord for pointing out Magnet disconnecting the caster (issue would actually happen upon failing to catch mob)
|
||||||
monster.aggroSwitchController(chr, true);
|
monster.aggroSwitchController(chr, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -133,12 +134,20 @@ public final class SpecialMoveHandler extends AbstractMaplePacketHandler {
|
|||||||
} else {
|
} else {
|
||||||
skill.getEffect(skillLevel).applyEchoOfHero(chr);
|
skill.getEffect(skillLevel).applyEchoOfHero(chr);
|
||||||
}
|
}
|
||||||
} else if(chr.canDoor()) {
|
} else {
|
||||||
//update door lists
|
if (c.tryacquireClient()) {
|
||||||
|
try {
|
||||||
|
if (chr.canDoor()) {
|
||||||
chr.cancelMagicDoor();
|
chr.cancelMagicDoor();
|
||||||
skill.getEffect(skillLevel).applyTo(chr, pos);
|
skill.getEffect(skillLevel).applyTo(chr, pos);
|
||||||
} else {
|
} else {
|
||||||
chr.message("Please wait 5 seconds before casting Mystic Door again.");
|
chr.message("Please wait 5 seconds before casting Mystic Door again.");
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
c.releaseClient();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
c.announce(MaplePacketCreator.enableActions());
|
c.announce(MaplePacketCreator.enableActions());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import client.inventory.ModifyInventory;
|
|||||||
import client.inventory.manipulator.MapleInventoryManipulator;
|
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||||
import client.inventory.manipulator.MapleKarmaManipulator;
|
import client.inventory.manipulator.MapleKarmaManipulator;
|
||||||
import client.processor.AssignAPProcessor;
|
import client.processor.AssignAPProcessor;
|
||||||
|
import client.processor.DueyProcessor;
|
||||||
import constants.GameConstants;
|
import constants.GameConstants;
|
||||||
import constants.ItemConstants;
|
import constants.ItemConstants;
|
||||||
import constants.ServerConstants;
|
import constants.ServerConstants;
|
||||||
@@ -47,7 +48,6 @@ import java.util.List;
|
|||||||
|
|
||||||
import net.AbstractMaplePacketHandler;
|
import net.AbstractMaplePacketHandler;
|
||||||
import net.server.Server;
|
import net.server.Server;
|
||||||
import scripting.npc.NPCScriptManager;
|
|
||||||
import server.MapleItemInformationProvider;
|
import server.MapleItemInformationProvider;
|
||||||
import server.MapleShop;
|
import server.MapleShop;
|
||||||
import server.MapleShopFactory;
|
import server.MapleShopFactory;
|
||||||
@@ -130,7 +130,7 @@ public final class UseCashItemHandler extends AbstractMaplePacketHandler {
|
|||||||
if (victim != null) {
|
if (victim != null) {
|
||||||
MapleMap targetMap = victim.getMap();
|
MapleMap targetMap = victim.getMap();
|
||||||
if (!FieldLimit.CANNOTVIPROCK.check(targetMap.getFieldLimit()) && (targetMap.getForcedReturnId() == 999999999 || targetMap.getId() < 100000000)) {
|
if (!FieldLimit.CANNOTVIPROCK.check(targetMap.getFieldLimit()) && (targetMap.getForcedReturnId() == 999999999 || targetMap.getId() < 100000000)) {
|
||||||
if (victim.gmLevel() <= player.gmLevel()) {
|
if (!victim.isGM() || victim.gmLevel() <= player.gmLevel()) { // thanks Yoboes for noticing non-GM's being unreachable through rocks
|
||||||
player.forceChangeMap(targetMap, targetMap.findClosestPlayerSpawnpoint(victim.getPosition()));
|
player.forceChangeMap(targetMap, targetMap.findClosestPlayerSpawnpoint(victim.getPosition()));
|
||||||
success = true;
|
success = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -294,7 +294,7 @@ public final class UseCashItemHandler extends AbstractMaplePacketHandler {
|
|||||||
if (item == null) //hack
|
if (item == null) //hack
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
} else if (item.isUntradeable()) {
|
} else if (item.isUntradeable() || ii.isUnmerchable(item.getItemId())) {
|
||||||
player.dropMessage(1, "You cannot trade this item.");
|
player.dropMessage(1, "You cannot trade this item.");
|
||||||
c.announce(MaplePacketCreator.enableActions());
|
c.announce(MaplePacketCreator.enableActions());
|
||||||
return;
|
return;
|
||||||
@@ -398,7 +398,7 @@ public final class UseCashItemHandler extends AbstractMaplePacketHandler {
|
|||||||
ii.getItemEffect(itemId).applyTo(player);
|
ii.getItemEffect(itemId).applyTo(player);
|
||||||
remove(c, position, itemId);
|
remove(c, position, itemId);
|
||||||
} else if (itemType == 533) {
|
} else if (itemType == 533) {
|
||||||
NPCScriptManager.getInstance().start(c, 9010009, null);
|
DueyProcessor.dueySendTalk(c);
|
||||||
} else if (itemType == 537) {
|
} else if (itemType == 537) {
|
||||||
if (GameConstants.isFreeMarketRoom(player.getMapId())) {
|
if (GameConstants.isFreeMarketRoom(player.getMapId())) {
|
||||||
player.dropMessage(5, "You cannot use the chalkboard here.");
|
player.dropMessage(5, "You cannot use the chalkboard here.");
|
||||||
@@ -409,7 +409,7 @@ public final class UseCashItemHandler extends AbstractMaplePacketHandler {
|
|||||||
player.setChalkboard(slea.readMapleAsciiString());
|
player.setChalkboard(slea.readMapleAsciiString());
|
||||||
player.getMap().broadcastMessage(MaplePacketCreator.useChalkboard(player, false));
|
player.getMap().broadcastMessage(MaplePacketCreator.useChalkboard(player, false));
|
||||||
player.getClient().announce(MaplePacketCreator.enableActions());
|
player.getClient().announce(MaplePacketCreator.enableActions());
|
||||||
remove(c, position, itemId);
|
//remove(c, position, itemId); thanks Conrad for noticing chalkboards shouldn't be depleted upon use
|
||||||
} else if (itemType == 539) {
|
} else if (itemType == 539) {
|
||||||
List<String> strLines = new LinkedList<>();
|
List<String> strLines = new LinkedList<>();
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
package net.server.channel.handlers;
|
|
||||||
|
|
||||||
import client.MapleClient;
|
|
||||||
import net.AbstractMaplePacketHandler;
|
|
||||||
import tools.data.input.SeekableLittleEndianAccessor;
|
|
||||||
import tools.MaplePacketCreator;
|
|
||||||
|
|
||||||
public final class UseItemCanvasHandler extends AbstractMaplePacketHandler {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
|
||||||
c.announce(MaplePacketCreator.enableActions());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -237,9 +237,11 @@ public class MapleMonsterAggroCoordinator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mobAggro.isEmpty()) { // all aggro on this mob expired
|
if (mobAggro.isEmpty()) { // all aggro on this mob expired
|
||||||
|
if (!am.getLeft().isBoss()) {
|
||||||
am.getLeft().aggroResetAggro();
|
am.getLeft().aggroResetAggro();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!toRemoveIdx.isEmpty()) {
|
if (!toRemoveIdx.isEmpty()) {
|
||||||
Collections.sort(toRemoveIdx, new Comparator<Integer>() { // last to first indexes
|
Collections.sort(toRemoveIdx, new Comparator<Integer>() { // last to first indexes
|
||||||
|
|||||||
@@ -64,6 +64,10 @@ public class MaplePartySearchCoordinator {
|
|||||||
private Map<Integer, MapleCharacter> searchLeaders = new HashMap<>();
|
private Map<Integer, MapleCharacter> searchLeaders = new HashMap<>();
|
||||||
private Map<Integer, LeaderSearchMetadata> searchSettings = new HashMap<>();
|
private Map<Integer, LeaderSearchMetadata> searchSettings = new HashMap<>();
|
||||||
|
|
||||||
|
private Map<MapleCharacter, LeaderSearchMetadata> timeoutLeaders = new HashMap<>();
|
||||||
|
|
||||||
|
private int updateCount = 0;
|
||||||
|
|
||||||
private static Map<Integer, Set<Integer>> mapNeighbors = fetchNeighbouringMaps();
|
private static Map<Integer, Set<Integer>> mapNeighbors = fetchNeighbouringMaps();
|
||||||
private static Map<Integer, MapleJob> jobTable = instantiateJobTable();
|
private static Map<Integer, MapleJob> jobTable = instantiateJobTable();
|
||||||
|
|
||||||
@@ -245,11 +249,21 @@ public class MaplePartySearchCoordinator {
|
|||||||
addQueueLeader(leader);
|
addQueueLeader(leader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void registerPartyLeader(MapleCharacter leader, LeaderSearchMetadata settings) {
|
||||||
|
if (searchLeaders.containsKey(leader.getId())) return;
|
||||||
|
|
||||||
|
searchSettings.put(leader.getId(), settings);
|
||||||
|
searchLeaders.put(leader.getId(), leader);
|
||||||
|
addQueueLeader(leader);
|
||||||
|
}
|
||||||
|
|
||||||
public void unregisterPartyLeader(MapleCharacter leader) {
|
public void unregisterPartyLeader(MapleCharacter leader) {
|
||||||
MapleCharacter toRemove = searchLeaders.remove(leader.getId());
|
MapleCharacter toRemove = searchLeaders.remove(leader.getId());
|
||||||
if (toRemove != null) {
|
if (toRemove != null) {
|
||||||
removeQueueLeader(toRemove);
|
removeQueueLeader(toRemove);
|
||||||
searchSettings.remove(leader.getId());
|
searchSettings.remove(leader.getId());
|
||||||
|
} else {
|
||||||
|
unregisterLongTermPartyLeader(leader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,6 +321,41 @@ public class MaplePartySearchCoordinator {
|
|||||||
return new Pair<>(queuedLeaders, nextLeaders);
|
return new Pair<>(queuedLeaders, nextLeaders);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void registerLongTermPartyLeaders(List<Pair<MapleCharacter, LeaderSearchMetadata>> recycledLeaders) {
|
||||||
|
leaderQueueRLock.lock();
|
||||||
|
try {
|
||||||
|
for (Pair<MapleCharacter, LeaderSearchMetadata> p : recycledLeaders) {
|
||||||
|
timeoutLeaders.put(p.getLeft(), p.getRight());
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
leaderQueueRLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void unregisterLongTermPartyLeader(MapleCharacter leader) {
|
||||||
|
leaderQueueRLock.lock();
|
||||||
|
try {
|
||||||
|
timeoutLeaders.remove(leader);
|
||||||
|
} finally {
|
||||||
|
leaderQueueRLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reinstateLongTermPartyLeaders() {
|
||||||
|
Map<MapleCharacter, LeaderSearchMetadata> timeoutLeadersCopy;
|
||||||
|
leaderQueueWLock.lock();
|
||||||
|
try {
|
||||||
|
timeoutLeadersCopy = new HashMap<>(timeoutLeaders);
|
||||||
|
timeoutLeaders.clear();
|
||||||
|
} finally {
|
||||||
|
leaderQueueWLock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Entry<MapleCharacter, LeaderSearchMetadata> e : timeoutLeadersCopy.entrySet()) {
|
||||||
|
registerPartyLeader(e.getKey(), e.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void runPartySearch() {
|
public void runPartySearch() {
|
||||||
Pair<List<MapleCharacter>, List<MapleCharacter>> queuedLeaders = fetchQueuedLeaders();
|
Pair<List<MapleCharacter>, List<MapleCharacter>> queuedLeaders = fetchQueuedLeaders();
|
||||||
|
|
||||||
@@ -356,10 +405,28 @@ public class MaplePartySearchCoordinator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<Pair<MapleCharacter, LeaderSearchMetadata>> recycledLeaders = new LinkedList<>();
|
||||||
for (MapleCharacter leader : expiredLeaders) {
|
for (MapleCharacter leader : expiredLeaders) {
|
||||||
if (leader.isLoggedinWorld()) leader.dropMessage(5, "Your Party Search token session expired, please stop your Party Search and retry again later.");
|
|
||||||
searchLeaders.remove(leader.getId());
|
searchLeaders.remove(leader.getId());
|
||||||
searchSettings.remove(leader.getId());
|
LeaderSearchMetadata settings = searchSettings.remove(leader.getId());
|
||||||
|
|
||||||
|
if (leader.isLoggedinWorld()) {
|
||||||
|
if (settings != null) {
|
||||||
|
recycledLeaders.add(new Pair<>(leader, settings));
|
||||||
|
if (ServerConstants.USE_DEBUG && leader.isGM()) leader.dropMessage(5, "Your Party Search token session is now on waiting queue for up to 7 minutes, to get it working right away please stop your Party Search and retry again later.");
|
||||||
|
} else {
|
||||||
|
leader.dropMessage(5, "Your Party Search token session expired, please stop your Party Search and retry again later.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!recycledLeaders.isEmpty()) {
|
||||||
|
registerLongTermPartyLeaders(recycledLeaders);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateCount++;
|
||||||
|
if (updateCount % 77 == 0) {
|
||||||
|
reinstateLongTermPartyLeaders();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,8 +34,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
|||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
||||||
import net.server.audit.locks.MonitoredLockType;
|
import net.server.audit.locks.MonitoredLockType;
|
||||||
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
||||||
|
import tools.IntervalBuilder;
|
||||||
import java.awt.geom.Line2D;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -44,84 +43,7 @@ import java.awt.geom.Line2D;
|
|||||||
public class PartySearchStorage {
|
public class PartySearchStorage {
|
||||||
|
|
||||||
private List<PartySearchCharacter> storage = new ArrayList<>(20);
|
private List<PartySearchCharacter> storage = new ArrayList<>(20);
|
||||||
private PartySearchEmptyIntervals emptyManager = new PartySearchEmptyIntervals();
|
private IntervalBuilder emptyIntervals = new IntervalBuilder();
|
||||||
|
|
||||||
private class PartySearchEmptyIntervals {
|
|
||||||
|
|
||||||
private List<Line2D> emptyLimits = new ArrayList<>();
|
|
||||||
|
|
||||||
private void refitEmptyIntervals(int st, int en, int minLevel, int maxLevel) {
|
|
||||||
List<Line2D> checkLimits = new ArrayList<>(emptyLimits.subList(st, en));
|
|
||||||
|
|
||||||
float newLimitX1, newLimitX2;
|
|
||||||
if (!checkLimits.isEmpty()) {
|
|
||||||
Line2D firstLimit = checkLimits.get(0);
|
|
||||||
Line2D lastLimit = checkLimits.get(checkLimits.size() - 1);
|
|
||||||
|
|
||||||
newLimitX1 = (float) ((minLevel < firstLimit.getX1()) ? minLevel : firstLimit.getX1());
|
|
||||||
newLimitX2 = (float) ((maxLevel > lastLimit.getX2()) ? maxLevel : lastLimit.getX2());
|
|
||||||
|
|
||||||
for (Line2D limit : checkLimits) {
|
|
||||||
emptyLimits.remove(st);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
newLimitX1 = minLevel;
|
|
||||||
newLimitX2 = maxLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
emptyLimits.add(st, new Line2D.Float((float) newLimitX1, 0, (float) newLimitX2, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
private int bsearchInterval(int level) {
|
|
||||||
int st = 0, en = emptyLimits.size() - 1;
|
|
||||||
|
|
||||||
int mid, idx;
|
|
||||||
while (en >= st) {
|
|
||||||
idx = (st + en) / 2;
|
|
||||||
mid = (int) emptyLimits.get(idx).getX1();
|
|
||||||
|
|
||||||
if (mid == level) {
|
|
||||||
return idx;
|
|
||||||
} else if (mid < level) {
|
|
||||||
st = idx + 1;
|
|
||||||
} else {
|
|
||||||
en = idx - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return en;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addEmptyInterval(int fromLevel, int toLevel) {
|
|
||||||
synchronized (emptyLimits) { // adding intervals occurs on a same-thread process, so this is actually not performance grinding
|
|
||||||
int st = bsearchInterval(fromLevel);
|
|
||||||
if (st < 0) {
|
|
||||||
st = 0;
|
|
||||||
} else if (emptyLimits.get(st).getX2() < fromLevel) {
|
|
||||||
st += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int en = bsearchInterval(toLevel);
|
|
||||||
if (en < st) en = st - 1;
|
|
||||||
|
|
||||||
refitEmptyIntervals(st, en + 1, fromLevel, toLevel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isInEmptyInterval(int minLevel, int maxLevel) {
|
|
||||||
synchronized (emptyLimits) {
|
|
||||||
int idx = bsearchInterval(minLevel);
|
|
||||||
return idx >= 0 && maxLevel <= emptyLimits.get(idx).getX2();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearEmptyInterval() {
|
|
||||||
synchronized (emptyLimits) {
|
|
||||||
emptyLimits.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private final ReentrantReadWriteLock psLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.WORLD_PARTY_SEARCH_STORAGE, true);
|
private final ReentrantReadWriteLock psLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.WORLD_PARTY_SEARCH_STORAGE, true);
|
||||||
private final ReadLock psRLock = psLock.readLock();
|
private final ReadLock psRLock = psLock.readLock();
|
||||||
@@ -183,7 +105,7 @@ public class PartySearchStorage {
|
|||||||
psWLock.unlock();
|
psWLock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
emptyManager.clearEmptyInterval();
|
emptyIntervals.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int bsearchStorage(List<PartySearchCharacter> storage, int level) {
|
private static int bsearchStorage(List<PartySearchCharacter> storage, int level) {
|
||||||
@@ -207,7 +129,7 @@ public class PartySearchStorage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public MapleCharacter callPlayer(int callerCid, int callerMapid, int minLevel, int maxLevel) {
|
public MapleCharacter callPlayer(int callerCid, int callerMapid, int minLevel, int maxLevel) {
|
||||||
if (emptyManager.isInEmptyInterval(minLevel, maxLevel)) {
|
if (emptyIntervals.inInterval(minLevel, maxLevel)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,7 +152,7 @@ public class PartySearchStorage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emptyManager.addEmptyInterval(minLevel, maxLevel);
|
emptyIntervals.addInterval(minLevel, maxLevel);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public final class AfterLoginHandler extends AbstractMaplePacketHandler {
|
|||||||
c3 = slea.readByte();
|
c3 = slea.readByte();
|
||||||
}
|
}
|
||||||
if (c2 == 1 && c3 == 1) {
|
if (c2 == 1 && c3 == 1) {
|
||||||
if (c.getPin() == null) {
|
if (c.getPin() == null || c.getPin().equals("")) {
|
||||||
c.announce(MaplePacketCreator.registerPin());
|
c.announce(MaplePacketCreator.registerPin());
|
||||||
} else {
|
} else {
|
||||||
c.announce(MaplePacketCreator.requestPin());
|
c.announce(MaplePacketCreator.requestPin());
|
||||||
|
|||||||
@@ -457,6 +457,64 @@ public class AbstractPlayerInteraction {
|
|||||||
getClient().announce(MaplePacketCreator.updateQuest(getPlayer().getQuest(MapleQuest.getInstance(qid)), false));
|
getClient().announce(MaplePacketCreator.updateQuest(getPlayer().getQuest(MapleQuest.getInstance(qid)), false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean forceStartQuest(int id) {
|
||||||
|
return forceStartQuest(id, 9010000);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean forceStartQuest(int id, int npc) {
|
||||||
|
return startQuest(id, npc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean forceCompleteQuest(int id) {
|
||||||
|
return forceCompleteQuest(id, 9010000);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean forceCompleteQuest(int id, int npc) {
|
||||||
|
return completeQuest(id, npc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean startQuest(short id) {
|
||||||
|
return startQuest((int) id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean completeQuest(short id) {
|
||||||
|
return completeQuest((int) id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean startQuest(int id) {
|
||||||
|
return startQuest(id, 9010000);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean completeQuest(int id) {
|
||||||
|
return completeQuest(id, 9010000);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean startQuest(short id, int npcId) {
|
||||||
|
return startQuest((int) id, npcId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean completeQuest(short id, int npcId) {
|
||||||
|
return completeQuest((int) id, npcId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean startQuest(int id, int npcId) {
|
||||||
|
try {
|
||||||
|
return MapleQuest.getInstance(id).forceStart(getPlayer(), npcId);
|
||||||
|
} catch (NullPointerException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean completeQuest(int id, int npcId) {
|
||||||
|
try {
|
||||||
|
return MapleQuest.getInstance(id).forceComplete(getPlayer(), npcId);
|
||||||
|
} catch (NullPointerException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Item evolvePet(byte slot, int afterId) {
|
public Item evolvePet(byte slot, int afterId) {
|
||||||
MaplePet evolved = null;
|
MaplePet evolved = null;
|
||||||
MaplePet target;
|
MaplePet target;
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
*/
|
*/
|
||||||
package scripting.event;
|
package scripting.event;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import tools.Pair;
|
import tools.Pair;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@@ -40,14 +39,13 @@ import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
|||||||
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
||||||
import net.server.world.MapleParty;
|
import net.server.world.MapleParty;
|
||||||
import net.server.world.MaplePartyCharacter;
|
import net.server.world.MaplePartyCharacter;
|
||||||
import provider.MapleDataProviderFactory;
|
|
||||||
import server.MaplePortal;
|
import server.MaplePortal;
|
||||||
import server.TimerManager;
|
import server.TimerManager;
|
||||||
import server.MapleStatEffect;
|
import server.MapleStatEffect;
|
||||||
import server.expeditions.MapleExpedition;
|
import server.expeditions.MapleExpedition;
|
||||||
import server.life.MapleMonster;
|
import server.life.MapleMonster;
|
||||||
import server.maps.MapleMap;
|
import server.maps.MapleMap;
|
||||||
import server.maps.MapleMapFactory;
|
import server.maps.MapleMapManager;
|
||||||
import server.maps.MapleReactor;
|
import server.maps.MapleReactor;
|
||||||
import client.MapleCharacter;
|
import client.MapleCharacter;
|
||||||
import client.SkillFactory;
|
import client.SkillFactory;
|
||||||
@@ -82,7 +80,7 @@ public class EventInstanceManager {
|
|||||||
private Map<MapleCharacter, Integer> killCount = new HashMap<>();
|
private Map<MapleCharacter, Integer> killCount = new HashMap<>();
|
||||||
private EventManager em;
|
private EventManager em;
|
||||||
private EventScriptScheduler ess;
|
private EventScriptScheduler ess;
|
||||||
private MapleMapFactory mapFactory;
|
private MapleMapManager mapManager;
|
||||||
private String name;
|
private String name;
|
||||||
private Properties props = new Properties();
|
private Properties props = new Properties();
|
||||||
private Map<String, Object> objectProps = new HashMap<>();
|
private Map<String, Object> objectProps = new HashMap<>();
|
||||||
@@ -125,8 +123,7 @@ public class EventInstanceManager {
|
|||||||
this.em = em;
|
this.em = em;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.ess = new EventScriptScheduler();
|
this.ess = new EventScriptScheduler();
|
||||||
mapFactory = new MapleMapFactory(this, MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Map.wz")), MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/String.wz")), (byte) 0, (byte) 1);//Fk this
|
this.mapManager = new MapleMapManager(this, em.getWorldServer().getId(), em.getChannelServer().getId());
|
||||||
mapFactory.setChannel(em.getChannelServer().getId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
@@ -647,10 +644,10 @@ public class EventInstanceManager {
|
|||||||
TimerManager.getInstance().schedule(new Runnable() {
|
TimerManager.getInstance().schedule(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
mapFactory.dispose(); // issues from instantly disposing some event objects found thanks to MedicOP
|
mapManager.dispose(); // issues from instantly disposing some event objects found thanks to MedicOP
|
||||||
wL.lock();
|
wL.lock();
|
||||||
try {
|
try {
|
||||||
mapFactory = null;
|
mapManager = null;
|
||||||
em = null;
|
em = null;
|
||||||
} finally {
|
} finally {
|
||||||
wL.unlock();
|
wL.unlock();
|
||||||
@@ -675,8 +672,8 @@ public class EventInstanceManager {
|
|||||||
sL = sL.dispose();
|
sL = sL.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public MapleMapFactory getMapFactory() {
|
public MapleMapManager getMapFactory() {
|
||||||
return mapFactory;
|
return mapManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void schedule(final String methodName, long delay) {
|
public void schedule(final String methodName, long delay) {
|
||||||
@@ -706,10 +703,10 @@ public class EventInstanceManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public MapleMap getMapInstance(int mapId) {
|
public MapleMap getMapInstance(int mapId) {
|
||||||
MapleMap map = mapFactory.getMap(mapId);
|
MapleMap map = mapManager.getMap(mapId);
|
||||||
map.setEventInstance(this);
|
map.setEventInstance(this);
|
||||||
|
|
||||||
if (!mapFactory.isMapLoaded(mapId)) {
|
if (!mapManager.isMapLoaded(mapId)) {
|
||||||
sL.lock();
|
sL.lock();
|
||||||
try {
|
try {
|
||||||
if (em.getProperty("shuffleReactors") != null && em.getProperty("shuffleReactors").equals("true")) {
|
if (em.getProperty("shuffleReactors") != null && em.getProperty("shuffleReactors").equals("true")) {
|
||||||
|
|||||||
@@ -41,10 +41,9 @@ import server.gachapon.MapleGachapon;
|
|||||||
import server.gachapon.MapleGachapon.MapleGachaponItem;
|
import server.gachapon.MapleGachapon.MapleGachaponItem;
|
||||||
import server.life.MaplePlayerNPC;
|
import server.life.MaplePlayerNPC;
|
||||||
import server.maps.MapleMap;
|
import server.maps.MapleMap;
|
||||||
import server.maps.MapleMapFactory;
|
import server.maps.MapleMapManager;
|
||||||
import server.partyquest.Pyramid;
|
import server.partyquest.Pyramid;
|
||||||
import server.partyquest.Pyramid.PyramidMode;
|
import server.partyquest.Pyramid.PyramidMode;
|
||||||
import server.quest.MapleQuest;
|
|
||||||
import tools.LogHelper;
|
import tools.LogHelper;
|
||||||
import tools.MaplePacketCreator;
|
import tools.MaplePacketCreator;
|
||||||
import client.MapleCharacter;
|
import client.MapleCharacter;
|
||||||
@@ -63,9 +62,11 @@ import constants.LanguageConstants;
|
|||||||
import net.server.PlayerStorage;
|
import net.server.PlayerStorage;
|
||||||
import net.server.channel.Channel;
|
import net.server.channel.Channel;
|
||||||
import net.server.coordinator.matchchecker.MatchCheckerListenerFactory.MatchCheckerType;
|
import net.server.coordinator.matchchecker.MatchCheckerListenerFactory.MatchCheckerType;
|
||||||
|
import server.MapleMarriage;
|
||||||
import server.MapleSkillbookInformationProvider;
|
import server.MapleSkillbookInformationProvider;
|
||||||
import server.MapleSkillbookInformationProvider.SkillBookEntry;
|
import server.MapleSkillbookInformationProvider.SkillBookEntry;
|
||||||
import server.TimerManager;
|
import server.TimerManager;
|
||||||
|
import server.life.MapleLifeFactory;
|
||||||
import server.maps.MapleMapObject;
|
import server.maps.MapleMapObject;
|
||||||
import server.maps.MapleMapObjectType;
|
import server.maps.MapleMapObjectType;
|
||||||
import server.expeditions.MapleExpedition;
|
import server.expeditions.MapleExpedition;
|
||||||
@@ -77,10 +78,11 @@ import tools.packets.Wedding;
|
|||||||
import java.awt.Point;
|
import java.awt.Point;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import server.MapleMarriage;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -95,6 +97,18 @@ public class NPCConversationManager extends AbstractPlayerInteraction {
|
|||||||
private boolean itemScript;
|
private boolean itemScript;
|
||||||
private List<MaplePartyCharacter> otherParty;
|
private List<MaplePartyCharacter> otherParty;
|
||||||
|
|
||||||
|
private static Map<Integer, String> npcDefaultTalks = new HashMap<>();
|
||||||
|
|
||||||
|
private static String getDefaultTalk(int npcid) {
|
||||||
|
String talk = npcDefaultTalks.get(npcid);
|
||||||
|
if (talk == null) {
|
||||||
|
talk = MapleLifeFactory.getNPCDefaultTalk(npcid);
|
||||||
|
npcDefaultTalks.put(npcid, talk);
|
||||||
|
}
|
||||||
|
|
||||||
|
return talk;
|
||||||
|
}
|
||||||
|
|
||||||
public NPCConversationManager(MapleClient c, int npc, String scriptName) {
|
public NPCConversationManager(MapleClient c, int npc, String scriptName) {
|
||||||
this(c, npc, -1, scriptName, false);
|
this(c, npc, -1, scriptName, false);
|
||||||
}
|
}
|
||||||
@@ -155,6 +169,10 @@ public class NPCConversationManager extends AbstractPlayerInteraction {
|
|||||||
getClient().announce(MaplePacketCreator.getNPCTalk(npc, (byte) 0, text, "00 00", (byte) 0));
|
getClient().announce(MaplePacketCreator.getNPCTalk(npc, (byte) 0, text, "00 00", (byte) 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void sendDefault() {
|
||||||
|
sendOk(getDefaultTalk(npc));
|
||||||
|
}
|
||||||
|
|
||||||
public void sendYesNo(String text) {
|
public void sendYesNo(String text) {
|
||||||
getClient().announce(MaplePacketCreator.getNPCTalk(npc, (byte) 1, text, "", (byte) 0));
|
getClient().announce(MaplePacketCreator.getNPCTalk(npc, (byte) 1, text, "", (byte) 0));
|
||||||
}
|
}
|
||||||
@@ -196,7 +214,12 @@ public class NPCConversationManager extends AbstractPlayerInteraction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void sendStyle(String text, int styles[]) {
|
public void sendStyle(String text, int styles[]) {
|
||||||
|
if (styles.length > 0) {
|
||||||
getClient().announce(MaplePacketCreator.getNPCTalkStyle(npc, text, styles));
|
getClient().announce(MaplePacketCreator.getNPCTalkStyle(npc, text, styles));
|
||||||
|
} else { // thanks Conrad for noticing empty styles crashing players
|
||||||
|
sendOk("Sorry, there are no options of cosmetics available for you here at the moment.");
|
||||||
|
dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendGetNumber(String text, int def, int min, int max) {
|
public void sendGetNumber(String text, int def, int min, int max) {
|
||||||
@@ -236,76 +259,34 @@ public class NPCConversationManager extends AbstractPlayerInteraction {
|
|||||||
return getPlayer().getJob();
|
return getPlayer().getJob();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startQuest(short id) {
|
@Override
|
||||||
try {
|
|
||||||
MapleQuest.getInstance(id).forceStart(getPlayer(), npc);
|
|
||||||
} catch (NullPointerException ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void completeQuest(short id) {
|
|
||||||
try {
|
|
||||||
MapleQuest.getInstance(id).forceComplete(getPlayer(), npc);
|
|
||||||
} catch (NullPointerException ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean forceStartQuest(int id) {
|
public boolean forceStartQuest(int id) {
|
||||||
return MapleQuest.getInstance(id).forceStart(getPlayer(), npc);
|
return forceStartQuest(id, npc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean forceCompleteQuest(int id) {
|
public boolean forceCompleteQuest(int id) {
|
||||||
return MapleQuest.getInstance(id).forceComplete(getPlayer(), npc);
|
return forceCompleteQuest(id, npc);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startQuest(int id) {
|
@Override
|
||||||
try {
|
public boolean startQuest(short id) {
|
||||||
MapleQuest.getInstance(id).forceStart(getPlayer(), npc);
|
return startQuest((int) id);
|
||||||
} catch (NullPointerException ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void completeQuest(int id) {
|
@Override
|
||||||
try {
|
public boolean completeQuest(short id) {
|
||||||
MapleQuest.getInstance(id).forceComplete(getPlayer(), npc);
|
return completeQuest((int) id);
|
||||||
} catch (NullPointerException ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startQuest(short id, int npcId) {
|
@Override
|
||||||
try {
|
public boolean startQuest(int id) {
|
||||||
MapleQuest.getInstance(id).forceStart(getPlayer(), npcId);
|
return startQuest(id, npc);
|
||||||
} catch (NullPointerException ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startQuest(int id, int npcId) {
|
@Override
|
||||||
try {
|
public boolean completeQuest(int id) {
|
||||||
MapleQuest.getInstance(id).forceStart(getPlayer(), npcId);
|
return completeQuest(id, npc);
|
||||||
} catch (NullPointerException ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void completeQuest(short id, int npcId) {
|
|
||||||
try {
|
|
||||||
MapleQuest.getInstance(id).forceComplete(getPlayer(), npcId);
|
|
||||||
} catch (NullPointerException ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void completeQuest(int id, int npcId) {
|
|
||||||
try {
|
|
||||||
MapleQuest.getInstance(id).forceComplete(getPlayer(), npcId);
|
|
||||||
} catch (NullPointerException ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMeso() {
|
public int getMeso() {
|
||||||
@@ -538,7 +519,7 @@ public class NPCConversationManager extends AbstractPlayerInteraction {
|
|||||||
PyramidMode mod = PyramidMode.valueOf(mode);
|
PyramidMode mod = PyramidMode.valueOf(mode);
|
||||||
|
|
||||||
MapleParty partyz = getPlayer().getParty();
|
MapleParty partyz = getPlayer().getParty();
|
||||||
MapleMapFactory mf = c.getChannelServer().getMapFactory();
|
MapleMapManager mapManager = c.getChannelServer().getMapFactory();
|
||||||
|
|
||||||
MapleMap map = null;
|
MapleMap map = null;
|
||||||
int mapid = 926010100;
|
int mapid = 926010100;
|
||||||
@@ -548,7 +529,7 @@ public class NPCConversationManager extends AbstractPlayerInteraction {
|
|||||||
mapid += (mod.getMode() * 1000);
|
mapid += (mod.getMode() * 1000);
|
||||||
|
|
||||||
for (byte b = 0; b < 5; b++) {//They cannot warp to the next map before the timer ends (:
|
for (byte b = 0; b < 5; b++) {//They cannot warp to the next map before the timer ends (:
|
||||||
map = mf.getMap(mapid + b);
|
map = mapManager.getMap(mapid + b);
|
||||||
if (map.getCharacters().size() > 0) {
|
if (map.getCharacters().size() > 0) {
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -92,14 +92,8 @@ public class NPCScriptManager extends AbstractScriptManager {
|
|||||||
cms.put(c, cm);
|
cms.put(c, cm);
|
||||||
Invocable iv = null;
|
Invocable iv = null;
|
||||||
iv = getInvocable("npc/" + filename + ".js", c);
|
iv = getInvocable("npc/" + filename + ".js", c);
|
||||||
NPCScriptManager npcsm = NPCScriptManager.getInstance();
|
|
||||||
|
|
||||||
if (iv == null || NPCScriptManager.getInstance() == null) {
|
if (iv == null) {
|
||||||
c.getPlayer().dropMessage(1, npc + "");
|
|
||||||
cm.dispose();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (iv == null || npcsm == null) {
|
|
||||||
c.getPlayer().dropMessage(1, npc + "");
|
c.getPlayer().dropMessage(1, npc + "");
|
||||||
cm.dispose();
|
cm.dispose();
|
||||||
return;
|
return;
|
||||||
@@ -147,7 +141,7 @@ public class NPCScriptManager extends AbstractScriptManager {
|
|||||||
iv = getInvocable("npc/" + npc + ".js", c);
|
iv = getInvocable("npc/" + npc + ".js", c);
|
||||||
cm.resetItemScript();
|
cm.resetItemScript();
|
||||||
}
|
}
|
||||||
if (iv == null || NPCScriptManager.getInstance() == null) {
|
if (iv == null) {
|
||||||
dispose(c);
|
dispose(c);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -166,7 +160,6 @@ public class NPCScriptManager extends AbstractScriptManager {
|
|||||||
} else {
|
} else {
|
||||||
c.announce(MaplePacketCreator.enableActions());
|
c.announce(MaplePacketCreator.enableActions());
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (final UndeclaredThrowableException | ScriptException ute) {
|
} catch (final UndeclaredThrowableException | ScriptException ute) {
|
||||||
FilePrinter.printError(FilePrinter.NPC + npc + ".txt", ute);
|
FilePrinter.printError(FilePrinter.NPC + npc + ".txt", ute);
|
||||||
|
|||||||
@@ -82,22 +82,6 @@ public class PortalPlayerInteraction extends AbstractPlayerInteraction {
|
|||||||
return getPlayer().getLevel() >= 30;
|
return getPlayer().getLevel() >= 30;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean forceStartQuest(int id) {
|
|
||||||
return forceStartQuest(id, 9010000);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean forceStartQuest(int id, int npc) {
|
|
||||||
return MapleQuest.getInstance(id).forceStart(getPlayer(), npc);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean forceCompleteQuest(int id) {
|
|
||||||
return forceCompleteQuest(id, 9010000);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean forceCompleteQuest(int id, int npc) {
|
|
||||||
return MapleQuest.getInstance(id).forceComplete(getPlayer(), npc);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void blockPortal() {
|
public void blockPortal() {
|
||||||
c.getPlayer().blockPortal(getPortal().getScriptName());
|
c.getPlayer().blockPortal(getPortal().getScriptName());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,21 +24,22 @@ package server;
|
|||||||
import client.inventory.Item;
|
import client.inventory.Item;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
|
||||||
public class DueyPackages {
|
public class DueyPackage {
|
||||||
private String sender = null;
|
private String sender = null;
|
||||||
private Item item = null;
|
private Item item = null;
|
||||||
private int mesos = 0;
|
private int mesos = 0;
|
||||||
|
private String message = "";
|
||||||
private int day;
|
private int day;
|
||||||
private int month;
|
private int month;
|
||||||
private int year;
|
private int year;
|
||||||
private int packageId = 0;
|
private int packageId = 0;
|
||||||
|
|
||||||
public DueyPackages(int pId, Item item) {
|
public DueyPackage(int pId, Item item) {
|
||||||
this.item = item;
|
this.item = item;
|
||||||
packageId = pId;
|
packageId = pId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DueyPackages(int pId) { // Meso only package.
|
public DueyPackage(int pId) { // Meso only package.
|
||||||
this.packageId = pId;
|
this.packageId = pId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,6 +63,14 @@ public class DueyPackages {
|
|||||||
mesos = set;
|
mesos = set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessage(String m) {
|
||||||
|
message = m;
|
||||||
|
}
|
||||||
|
|
||||||
public int getPackageId() {
|
public int getPackageId() {
|
||||||
return packageId;
|
return packageId;
|
||||||
}
|
}
|
||||||
@@ -136,6 +136,7 @@ public class MapleItemInformationProvider {
|
|||||||
protected Map<Integer, Map<String, Integer>> skillUpgradeCache = new HashMap<>();
|
protected Map<Integer, Map<String, Integer>> skillUpgradeCache = new HashMap<>();
|
||||||
protected Map<Integer, MapleData> skillUpgradeInfoCache = new HashMap<>();
|
protected Map<Integer, MapleData> skillUpgradeInfoCache = new HashMap<>();
|
||||||
protected Map<Integer, Pair<Integer, Set<Integer>>> cashPetFoodCache = new HashMap<>();
|
protected Map<Integer, Pair<Integer, Set<Integer>>> cashPetFoodCache = new HashMap<>();
|
||||||
|
protected Map<Integer, QuestConsItem> questItemConsCache = new HashMap<>();
|
||||||
|
|
||||||
private MapleItemInformationProvider() {
|
private MapleItemInformationProvider() {
|
||||||
loadCardIdData();
|
loadCardIdData();
|
||||||
@@ -1381,12 +1382,6 @@ public class MapleItemInformationProvider {
|
|||||||
return partyquestItem;
|
return partyquestItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getQuestIdFromItem(int itemId) {
|
|
||||||
MapleData data = getItemData(itemId);
|
|
||||||
int questItem = MapleDataTool.getIntConvert("info/quest", data, 0);
|
|
||||||
return questItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadCardIdData() {
|
private void loadCardIdData() {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
@@ -1440,9 +1435,10 @@ public class MapleItemInformationProvider {
|
|||||||
if ((itemId / 10000) != 243) {
|
if ((itemId / 10000) != 243) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ScriptedItem script = new ScriptedItem(MapleDataTool.getInt("spec/npc", getItemData(itemId), 0),
|
MapleData itemInfo = getItemData(itemId);
|
||||||
MapleDataTool.getString("spec/script", getItemData(itemId), ""),
|
ScriptedItem script = new ScriptedItem(MapleDataTool.getInt("spec/npc", itemInfo, 0),
|
||||||
MapleDataTool.getInt("spec/runOnPickup", getItemData(itemId), 0) == 1);
|
MapleDataTool.getString("spec/script", itemInfo, ""),
|
||||||
|
MapleDataTool.getInt("spec/runOnPickup", itemInfo, 0) == 1);
|
||||||
scriptedItemCache.put(itemId, script);
|
scriptedItemCache.put(itemId, script);
|
||||||
return scriptedItemCache.get(itemId);
|
return scriptedItemCache.get(itemId);
|
||||||
}
|
}
|
||||||
@@ -1595,6 +1591,18 @@ public class MapleItemInformationProvider {
|
|||||||
eq.getAvoid() > 0 || eq.getSpeed() > 0 || eq.getJump() > 0 || eq.getHp() > 0 || eq.getMp() > 0);
|
eq.getAvoid() > 0 || eq.getSpeed() > 0 || eq.getJump() > 0 || eq.getHp() > 0 || eq.getMp() > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isUnmerchable(int itemId) {
|
||||||
|
if(ServerConstants.USE_ENFORCE_UNMERCHABLE_CASH && isCash(itemId)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ServerConstants.USE_ENFORCE_UNMERCHABLE_PET && ItemConstants.isPet(itemId)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public Collection<Item> canWearEquipment(MapleCharacter chr, Collection<Item> items) {
|
public Collection<Item> canWearEquipment(MapleCharacter chr, Collection<Item> items) {
|
||||||
MapleInventory inv = chr.getInventory(MapleInventoryType.EQUIPPED);
|
MapleInventory inv = chr.getInventory(MapleInventoryType.EQUIPPED);
|
||||||
if (inv.checked()) {
|
if (inv.checked()) {
|
||||||
@@ -2126,6 +2134,35 @@ public class MapleItemInformationProvider {
|
|||||||
return skillbook;
|
return skillbook;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final QuestConsItem getQuestConsumablesInfo(final int itemId) {
|
||||||
|
if (questItemConsCache.containsKey(itemId)) {
|
||||||
|
return questItemConsCache.get(itemId);
|
||||||
|
}
|
||||||
|
MapleData data = getItemData(itemId);
|
||||||
|
|
||||||
|
MapleData infoData = data.getChildByPath("info");
|
||||||
|
MapleData ciData = infoData.getChildByPath("consumeItem");
|
||||||
|
QuestConsItem qcItem = null;
|
||||||
|
if (ciData != null) {
|
||||||
|
qcItem = new QuestConsItem();
|
||||||
|
qcItem.exp = MapleDataTool.getInt("exp", infoData);
|
||||||
|
qcItem.grade = MapleDataTool.getInt("grade", infoData);
|
||||||
|
qcItem.questid = MapleDataTool.getInt("questId", infoData);
|
||||||
|
qcItem.items = new HashMap<>(2);
|
||||||
|
|
||||||
|
Map<Integer, Integer> cItems = qcItem.items;
|
||||||
|
for (MapleData ciItem : ciData.getChildren()) {
|
||||||
|
int itemid = MapleDataTool.getInt("0", ciItem);
|
||||||
|
int qty = MapleDataTool.getInt("1", ciItem);
|
||||||
|
|
||||||
|
cItems.put(itemid, qty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
questItemConsCache.put(itemId, qcItem);
|
||||||
|
return qcItem;
|
||||||
|
}
|
||||||
|
|
||||||
public class ScriptedItem {
|
public class ScriptedItem {
|
||||||
|
|
||||||
private boolean runOnPickup;
|
private boolean runOnPickup;
|
||||||
@@ -2157,4 +2194,15 @@ public class MapleItemInformationProvider {
|
|||||||
public short prob, quantity;
|
public short prob, quantity;
|
||||||
public String effect, worldmsg;
|
public String effect, worldmsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final class QuestConsItem {
|
||||||
|
|
||||||
|
public int questid, exp, grade;
|
||||||
|
public Map<Integer, Integer> items;
|
||||||
|
|
||||||
|
public Integer getItemRequirement(int itemid) {
|
||||||
|
return items.get(itemid);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,12 +150,14 @@ public class MapleStatEffect {
|
|||||||
|
|
||||||
private static class CardItemupStats {
|
private static class CardItemupStats {
|
||||||
protected int itemCode, prob;
|
protected int itemCode, prob;
|
||||||
|
protected boolean party;
|
||||||
private List<Pair<Integer, Integer>> areas;
|
private List<Pair<Integer, Integer>> areas;
|
||||||
|
|
||||||
private CardItemupStats(int code, int prob, List<Pair<Integer, Integer>> areas) {
|
private CardItemupStats(int code, int prob, List<Pair<Integer, Integer>> areas, boolean inParty) {
|
||||||
this.itemCode = code;
|
this.itemCode = code;
|
||||||
this.prob = prob;
|
this.prob = prob;
|
||||||
this.areas = areas;
|
this.areas = areas;
|
||||||
|
this.party = inParty;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isInArea(int mapid) {
|
private boolean isInArea(int mapid) {
|
||||||
@@ -173,8 +175,22 @@ public class MapleStatEffect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isActive(int mapid) {
|
private boolean isEffectActive(int mapid, boolean partyHunting) {
|
||||||
return cardStats == null || cardStats.isInArea(mapid);
|
if (cardStats == null) return true;
|
||||||
|
|
||||||
|
if (!cardStats.isInArea(mapid)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cardStats.party && !partyHunting) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isActive(MapleCharacter applyto) {
|
||||||
|
return isEffectActive(applyto.getMapId(), applyto.getPartyMembersOnSameMap().size() > 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCardRate(int mapid, int itemid) {
|
public int getCardRate(int mapid, int itemid) {
|
||||||
@@ -354,16 +370,27 @@ public class MapleStatEffect {
|
|||||||
} else if (isMonsterCard(sourceid)) {
|
} else if (isMonsterCard(sourceid)) {
|
||||||
int prob = 0, itemupCode = Integer.MAX_VALUE;
|
int prob = 0, itemupCode = Integer.MAX_VALUE;
|
||||||
List<Pair<Integer, Integer>> areas = null;
|
List<Pair<Integer, Integer>> areas = null;
|
||||||
|
boolean inParty = false;
|
||||||
|
|
||||||
MapleData con = source.getChildByPath("con");
|
MapleData con = source.getChildByPath("con");
|
||||||
if (con != null) {
|
if (con != null) {
|
||||||
areas = new ArrayList<>(3);
|
areas = new ArrayList<>(3);
|
||||||
|
|
||||||
for (MapleData conData : con.getChildren()) {
|
for (MapleData conData : con.getChildren()) {
|
||||||
|
int type = MapleDataTool.getInt("type", conData, -1);
|
||||||
|
|
||||||
|
if (type == 0) {
|
||||||
int startMap = MapleDataTool.getInt("sMap", conData, 0);
|
int startMap = MapleDataTool.getInt("sMap", conData, 0);
|
||||||
int endMap = MapleDataTool.getInt("eMap", conData, 0);
|
int endMap = MapleDataTool.getInt("eMap", conData, 0);
|
||||||
|
|
||||||
areas.add(new Pair<>(startMap, endMap));
|
areas.add(new Pair<>(startMap, endMap));
|
||||||
|
} else if (type == 2) {
|
||||||
|
inParty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (areas.isEmpty()) {
|
||||||
|
areas = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -409,7 +436,7 @@ public class MapleStatEffect {
|
|||||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.MAP_PROTECTION, thaw > 0 ? 1 : 2);
|
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.MAP_PROTECTION, thaw > 0 ? 1 : 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.cardStats = new CardItemupStats(itemupCode, prob, areas);
|
ret.cardStats = new CardItemupStats(itemupCode, prob, areas, inParty);
|
||||||
} else if (isExpIncrease(sourceid)) {
|
} else if (isExpIncrease(sourceid)) {
|
||||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.EXP_INCREASE, MapleDataTool.getInt("expinc", source, 0));
|
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.EXP_INCREASE, MapleDataTool.getInt("expinc", source, 0));
|
||||||
}
|
}
|
||||||
@@ -1045,8 +1072,6 @@ public class MapleStatEffect {
|
|||||||
|
|
||||||
door.getTarget().spawnDoor(door.getAreaDoor());
|
door.getTarget().spawnDoor(door.getAreaDoor());
|
||||||
door.getTown().spawnDoor(door.getTownDoor());
|
door.getTown().spawnDoor(door.getTownDoor());
|
||||||
|
|
||||||
applyto.disableDoorSpawn();
|
|
||||||
} else {
|
} else {
|
||||||
MapleInventoryManipulator.addFromDrop(applyto.getClient(), new Item(4006000, (short) 0, (short) 1), false);
|
MapleInventoryManipulator.addFromDrop(applyto.getClient(), new Item(4006000, (short) 0, (short) 1), false);
|
||||||
|
|
||||||
@@ -1182,15 +1207,9 @@ public class MapleStatEffect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Rectangle calculateBoundingBox(Point posFrom, boolean facingLeft) {
|
private Rectangle calculateBoundingBox(Point posFrom, boolean facingLeft) {
|
||||||
Point mylt;
|
int multiplier = facingLeft ? 1 : -1;
|
||||||
Point myrb;
|
Point mylt = new Point(lt.x * multiplier + posFrom.x, lt.y + posFrom.y);
|
||||||
if (facingLeft) {
|
Point myrb = new Point(rb.x * multiplier + posFrom.x, rb.y + posFrom.y);
|
||||||
mylt = new Point(lt.x + posFrom.x, lt.y + posFrom.y);
|
|
||||||
myrb = new Point(rb.x + posFrom.x, rb.y + posFrom.y);
|
|
||||||
} else {
|
|
||||||
myrb = new Point(-lt.x + posFrom.x, rb.y + posFrom.y);
|
|
||||||
mylt = new Point(-rb.x + posFrom.x, lt.y + posFrom.y);
|
|
||||||
}
|
|
||||||
Rectangle bounds = new Rectangle(mylt.x, mylt.y, myrb.x - mylt.x, myrb.y - mylt.y);
|
Rectangle bounds = new Rectangle(mylt.x, mylt.y, myrb.x - mylt.x, myrb.y - mylt.y);
|
||||||
return bounds;
|
return bounds;
|
||||||
}
|
}
|
||||||
@@ -1315,7 +1334,7 @@ public class MapleStatEffect {
|
|||||||
if (localstatups.size() > 0) {
|
if (localstatups.size() > 0) {
|
||||||
byte[] buff = null;
|
byte[] buff = null;
|
||||||
byte[] mbuff = null;
|
byte[] mbuff = null;
|
||||||
if (getSummonMovementType() == null && this.isActive(applyto.getMapId())) {
|
if (getSummonMovementType() == null && this.isActive(applyto)) {
|
||||||
buff = MaplePacketCreator.giveBuff((skill ? sourceid : -sourceid), localDuration, localstatups);
|
buff = MaplePacketCreator.giveBuff((skill ? sourceid : -sourceid), localDuration, localstatups);
|
||||||
}
|
}
|
||||||
if (isDash()) {
|
if (isDash()) {
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
package server.gachapon;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Ronan - parsed MapleSEA loots
|
||||||
|
*
|
||||||
|
* MapleSEA-like loots thanks to AyumiLove, src: https://ayumilovemaple.wordpress.com/maplestory-gachapon-guide/
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class ElNath extends GachaponItems {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] getCommonItems() {
|
||||||
|
return new int [] {
|
||||||
|
|
||||||
|
/* Scroll */
|
||||||
|
2041012, 2048003, 2043800, 2043301, 2040301, 2043101, 2043201, 2043001, 2044301, 2043801, 2044201, 2043701, 2044502,
|
||||||
|
2041011, 2041014, 2044602, 2043302, 2043202, 2043002, 2048005, 2044402, 2044302, 2043802, 2044102, 2044202, 2043702,
|
||||||
|
2044812,
|
||||||
|
|
||||||
|
/* Useable drop */
|
||||||
|
2000004, 2000005,
|
||||||
|
|
||||||
|
/* Common equipment */
|
||||||
|
1402010, 1032003, 1442013, 1432009, 1302022, 1302029, 1322021, 1302026, 1442017, 1322023, 1102011, 1032008, 1322026,
|
||||||
|
1442016, 1312000, 1032007, 1322025, 1322027, 1032020, 1442015, 1432017, 1302027, 1302049, 1372006, 1032022, 1032021,
|
||||||
|
1372004, 1332020, 1322007, 1032006, 1302028, 1322003, 1302007, 1092030, 1302021, 1322024, 1322012, 1032005, 1322022,
|
||||||
|
1032013, 1302025, 1302013, 1032017, 1032002, 1032001, 1302017, 1432018, 1442012, 1302000, 1032000, 1102013, 1442022,
|
||||||
|
1372005, 1442021, 1032009, 1302016,
|
||||||
|
|
||||||
|
/* Warrior equipment */
|
||||||
|
1442003, 1312007, 1402008, 1312008, 1412008, 1442009, 1302004, 1312006, 1442016, 1402012, 1302003, 1312005, 1432002,
|
||||||
|
1432001, 1302008, 1040030, 1402015, 1322015, 1432006, 1322002, 1302010, 1322017, 1402003, 1402006, 1322000, 1422001,
|
||||||
|
1442001, 1422004, 1412004, 1322009, 1322011, 1442000, 1412005, 1402002, 1432004, 1442010, 1422008, 1442007, 1422009,
|
||||||
|
1322019, 1412003, 1412007, 1302009, 1412000, 1322014, 1402001, 1402007, 1432005,
|
||||||
|
|
||||||
|
/* Magician equipment */
|
||||||
|
1382001, 1372007, 1382010, 1382007, 1372000, 1372003, 1382011, 1382006, 1382000,
|
||||||
|
|
||||||
|
/* Bowman equipment */
|
||||||
|
1452004, 1452000, 1452010, 1452015, 1452014, 1462012, 1462010, 1452017, 1462000, 1452008, 1452006, 1462006, 1452007,
|
||||||
|
1452002, 1402001,
|
||||||
|
|
||||||
|
/* Thief equipment */
|
||||||
|
1472006, 1472010, 1332022, 1332011, 1472015, 1472016, 1472023, 1472028, 1472022, 1472011, 1472026, 1332024, 1332009,
|
||||||
|
1472017, 1472013, 1472029, 1472021, 1332015, 1332031, 1332023, 1332004, 1472000, 1332019, 1472027, 1332018, 1472007,
|
||||||
|
1332012, 1332016, 1472024, 1332017, 1332003, 1472012, 1472014, 1472005, 1472018, 1472001,
|
||||||
|
|
||||||
|
/* Pirate equipment */
|
||||||
|
1072294, 1492009
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] getUncommonItems() {
|
||||||
|
return new int [] {2022439, 2040804, 2040805, 2340000};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] getRareItems() {
|
||||||
|
return new int [] {2043803, 1102085};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,7 +2,10 @@ package server.gachapon;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alan (SharpAceX)
|
* @author Alan (SharpAceX) - gachapon source classes stub & pirate equipment
|
||||||
|
* @author Ronan - parsed MapleSEA loots
|
||||||
|
*
|
||||||
|
* MapleSEA-like loots thanks to AyumiLove, src: https://ayumilovemaple.wordpress.com/maplestory-gachapon-guide/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class Ellinia extends GachaponItems {
|
public class Ellinia extends GachaponItems {
|
||||||
@@ -10,79 +13,41 @@ public class Ellinia extends GachaponItems {
|
|||||||
@Override
|
@Override
|
||||||
public int[] getCommonItems() {
|
public int[] getCommonItems() {
|
||||||
return new int[] {
|
return new int[] {
|
||||||
//warriorEquips = {
|
|
||||||
1082025, 1060028, 1051011, 1060016, 1051001,
|
/* Scroll */
|
||||||
1422001, 1002025, 1082000, 1302002, 1412012,
|
2043302, 2040002, 2043102, 2043002, 2044402, 2044302, 2043802, 2044002, 2041017, 2044902,
|
||||||
//magicianEquips = {
|
|
||||||
1002013, 1002016, 1002017, 1002034, 1002035,
|
/* Useable drop */
|
||||||
1002036, 1002037, 1002038, 1002064, 1002065,
|
2000004, 2000005, 2022025, 2022026,
|
||||||
1002072, 1002073, 1002074, 1002075, 1002102,
|
|
||||||
1002103, 1002104, 1002105, 1002106, 1002141,
|
/* Common equipment */
|
||||||
1002142, 1002143, 1002144, 1002145, 1002151,
|
1402010, 1442013, 1432009, 1002060, 1002063, 1322023, 1002042, 1050018, 1082147, 1002026, 1002392, 1062024, 1442016, 1322025,
|
||||||
1002152, 1002153, 1002154, 1002155, 1002215,
|
1322027, 1302027, 1372006, 1302019, 1092022, 1302021, 1041004, 1002395, 1322024, 1082148, 1002012, 1322012, 1032028, 1102012,
|
||||||
1002216, 1002217, 1002218, 1002242, 1002243,
|
1322022, 1051017, 1302013, 1082146, 1442014, 1302017, 1102013, 1102003, 1002041, 1002097, 1302016, 1082145,
|
||||||
1002244, 1002245, 1002246, 1002252, 1002253,
|
|
||||||
1002254, 1002271, 1002272, 1002273, 1002274,
|
/* Warrior equipment */
|
||||||
1002363, 1002364, 1002365, 1002366, 1002398,
|
1412006, 1040029, 1040086, 1050005, 1060028, 1002059, 1060008, 1061088, 1402012, 1302003, 1432002, 1312011, 1302008, 1040030,
|
||||||
1002399, 1002400, 1002401, 1002579, 1002773,
|
1002004, 1402015, 1322028, 1322015, 1432006, 1442006, 1322000, 1002085, 1002056, 1092013, 1002058, 1002050, 1060011, 1322009,
|
||||||
1040004, 1040017, 1040018,
|
1322011, 1442000, 1051011, 1061016, 1060018, 1041024, 1061020, 1302005, 1402002, 1002030, 1092004, 1041023, 1422008, 1060009,
|
||||||
1040019, 1040020, 1041015, 1041016, 1041017,
|
1051000, 1002021, 1442005, 1412003, 1412007, 1422007, 1302009, 1402000, 1402001, 1402007, 1432005,
|
||||||
1041018, 1041025, 1041026, 1041029, 1041030,
|
|
||||||
1041031, 1041041, 1041042, 1041043, 1041051,
|
/* Magician equipment */
|
||||||
1041052, 1041053, 1050001, 1050002, 1050003,
|
1382001, 1002037, 1060014, 1040018, 1061027, 1050002, 1002152, 1051027, 1050035, 1050056, 1051047, 1051030, 1002274, 1050074,
|
||||||
1050008, 1050009, 1050010, 1050023, 1050024,
|
1002218, 1002254, 1082088, 1382007, 1002013, 1082087, 1372008, 1382008, 1372002, 1372003, 1382011, 1382004, 1050047, 1040019,
|
||||||
1050025, 1050026, 1050027, 1050028, 1050029,
|
1041041, 1061034, 1041051, 1051045, 1051024, 1082081, 1041030, 1040018, 1002073, 1382003, 1082086, 1382014, 1050055, 1050025,
|
||||||
1050030, 1050031, 1050035, 1050036, 1050037,
|
1002155, 1060015,
|
||||||
1050038, 1050039, 1050045, 1050046, 1050047,
|
|
||||||
1050048, 1050049, 1050053, 1050054, 1050055,
|
/* Bowman equipment */
|
||||||
1050056, 1050067, 1050068, 1050069, 1050070,
|
1452004, 1462003, 1060070, 1002118, 1061058, 1040003, 1002160, 1002121, 1040068, 1061063, 1040080, 1462004, 1041008, 1061006,
|
||||||
1050072, 1050073, 1050074, 1050092, 1050093,
|
1061009, 1040022, 1002168, 1040067, 1060056, 1041054, 1041067, 1060063, 1002213, 1002119, 1462005, 1452001, 1462000, 1040025,
|
||||||
1050094, 1050095, 1050102, 1050103, 1050104,
|
1002166, 1002161, 1040069, 1051039, 1452006, 1462006, 1452007, 1402001, 1041062,
|
||||||
1050105, 1051003, 1051004, 1051005, 1051023,
|
|
||||||
1051024, 1051025, 1051026, 1051027, 1051030,
|
/* Thief equipment */
|
||||||
1051031, 1051032, 1051033, 1051034, 1051044,
|
1472010, 1472006, 1332011, 1472031, 1041048, 1472019, 1041095, 1040095, 1002128, 1061077, 1060025, 1041040, 1061033, 1472028,
|
||||||
1051045, 1051046, 1051047, 1051052, 1051053,
|
1472022, 1472011, 1040096, 1062002, 1002129, 1472026, 1332009, 1060043, 1002249, 1472021, 1040084, 1332015, 1002173, 1002148,
|
||||||
1051054, 1051055, 1051056, 1051057, 1051058,
|
1332004, 1332018, 1472009, 1061069, 1002176, 1041044, 1061037, 1060032, 1472020, 1040060, 1472018, 1332013, 1332002, 1402001,
|
||||||
1051094, 1051095, 1051096, 1051097, 1051101,
|
|
||||||
1051102, 1051103, 1051104, 1052076,
|
/* Pirate equipment */
|
||||||
1060012, 1060013, 1060014, 1060015,
|
|
||||||
1061010, 1061011, 1061012, 1061013, 1061021,
|
|
||||||
1061022, 1061027, 1061028, 1061034, 1061035,
|
|
||||||
1061036, 1061047, 1061048, 1061049, 1072006,
|
|
||||||
1072019, 1072020, 1072021, 1072023, 1072024,
|
|
||||||
1072044, 1072045, 1072072, 1072073, 1072074,
|
|
||||||
1072075, 1072076, 1072077, 1072078, 1072089,
|
|
||||||
1072090, 1072091, 1072114, 1072115, 1072116,
|
|
||||||
1072117, 1072136, 1072137, 1072138, 1072139,
|
|
||||||
1072140, 1072141, 1072142, 1072143, 1072157,
|
|
||||||
1072158, 1072159, 1072160, 1072169, 1072177,
|
|
||||||
1072178, 1072179, 1072206, 1072207, 1072208,
|
|
||||||
1072209, 1072223, 1072224, 1072225, 1072226,
|
|
||||||
1072268, 1082019, 1082020,
|
|
||||||
1082021, 1082022, 1082026, 1082027, 1082028,
|
|
||||||
1082051, 1082052, 1082053, 1082054, 1082055,
|
|
||||||
1082056, 1082062, 1082063, 1082064, 1082080,
|
|
||||||
1082081, 1082082, 1082086, 1082087, 1082088,
|
|
||||||
1082098, 1082099, 1082100, 1082121, 1082122,
|
|
||||||
1082123, 1082131, 1082132, 1082133, 1082134,
|
|
||||||
1082151, 1082152, 1082153, 1082154, 1082164,
|
|
||||||
1092021, 1092029, 1092057,
|
|
||||||
1372000, 1372001, 1372002, 1372003, 1372004,
|
|
||||||
1372007, 1372008, 1372009, 1372010, 1372011,
|
|
||||||
1372012, 1372014, 1372015, 1372016, 1372032,
|
|
||||||
1382000, 1382001, 1382002, 1382003, 1382004,
|
|
||||||
1382005, 1382006, 1382007, 1382008, 1382010,
|
|
||||||
1382011, 1382014, 1382015, 1382016, 1382017,
|
|
||||||
1382018, 1382019, 1382035, 1382036, 1382037,
|
|
||||||
1382041, 1382053, 1382054, 1382055, 1382056,
|
|
||||||
1382060,
|
|
||||||
//bowmanEquips = {
|
|
||||||
1040003, 1462005, 1002157, 1002119, 1062002,
|
|
||||||
1062004, 1041083, 1061082, 1082017, 1041061,
|
|
||||||
//thiefEquips = {
|
|
||||||
1002174, 1040063, 1072108, 1082044, 1061071,
|
|
||||||
1060052, 1072029, 1472002, 1082031, 1060023,
|
|
||||||
//pirateEquips = {
|
|
||||||
1002625, 1002616, 1482005, 1052098, 1482003,
|
1002625, 1002616, 1482005, 1052098, 1482003,
|
||||||
1482001, 1492004, 1002622, 1492005, 1082195
|
1482001, 1492004, 1002622, 1492005, 1082195
|
||||||
};
|
};
|
||||||
@@ -90,15 +55,12 @@ public class Ellinia extends GachaponItems {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getUncommonItems() {
|
public int[] getUncommonItems() {
|
||||||
return new int [] { 1372035, 1372036, 1372037, 1372038, 1372039,
|
return new int [] {1082149, 1002391, 1002419};
|
||||||
1372040, 1372041, 1372042, 1382045, 1382046,
|
|
||||||
1382047, 1382048, 1382049, 1382050, 1382051,
|
|
||||||
1382052 };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getRareItems() {
|
public int[] getRareItems() {
|
||||||
return new int [] {1382059, 1382057, 1072362, 1002791, 1052161, 1082240};
|
return new int [] {};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package server.gachapon;
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alan (SharpAceX)
|
* @author Alan (SharpAceX)
|
||||||
|
* @author Ronan - added ores, reworked global loots
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class Global extends GachaponItems {
|
public class Global extends GachaponItems {
|
||||||
@@ -10,50 +11,36 @@ public class Global extends GachaponItems {
|
|||||||
@Override
|
@Override
|
||||||
public int[] getCommonItems() {
|
public int[] getCommonItems() {
|
||||||
return new int[] {
|
return new int[] {
|
||||||
/* Gloves */ 1082002, 1082147, 1082148, 1082146, 1082145, 1082150,
|
/* Potions */
|
||||||
/* Capes */ 1102040, 1102043, 1102087, 1102079, 1102080, 1102081, 1102082, 1102083, 1102053, 1102054,
|
2000004, 2000005, 2001002, 2001001, 2020012, 2020013, 2020014, 2020015,
|
||||||
1102055, 1102056, 1102176, 1102177, 1102178, 1102179, 1102000, 1102001, 1102002, 1102003,
|
|
||||||
1102004, 1102011, 1102012, 1102013, 1102014, 1102015, 1102016, 1102017, 1102018, 1102021,
|
/* Ores */
|
||||||
1102022, 1102023, 1102024, 1102026, 1102027, 1102028,
|
4004000, 4004001, 4004002, 4004003, 4004004,
|
||||||
/* Tube Eqp */ 1322026, 1322025, 1322024, 1322022, 1322021,
|
4006000, 4006001,
|
||||||
/* Umbrellas */ 1302026, 1302027, 1302028, 1302017,
|
4010000, 4010001, 4010002, 4010003, 4010004, 4010005, 4010006, 4010007,
|
||||||
/* Snowboards */ 1442017, 1442016, 1442014, 1442012,
|
4020000, 4020001, 4020002, 4020003, 4020004, 4020005, 4020006, 4020007, 4020008
|
||||||
/* Skis */ 1432017, 1432016, 1432015,
|
|
||||||
/* Beginner Eqp */ 1442018, 1422011,
|
|
||||||
/* Potions */ 2000004, 2000005, 2001002, 2001001, 2020012, 2020013, 2020014, 2020015, 2022182, 2022245,
|
|
||||||
2022284, 2022285, 2022439,
|
|
||||||
/* Other Scrolls */ 2049000, 2049001, 2049002, 2041058, 2040727,
|
|
||||||
/* 10% Scrolls */ 2041002, 2040402, 2040702, 2040805, 2040026, 2040031, 2040318, 2040323, 2040328, 2040419,
|
|
||||||
2040422, 2040427, 2040534, 2040619, 2040622, 2040627, 2040825, 2040925, 2040928, 2040933,
|
|
||||||
2040016,
|
|
||||||
/* 60% Scrolls */ 2040001, 2040321, 2040425, 2040625, 2040931, 2048013, 2040025, 2040326, 2040532, 2040824,
|
|
||||||
2048010, 2040029, 2040418, 2040618, 2040924, 2048011, 2040317, 2040421, 2040621, 2040927,
|
|
||||||
2048012,
|
|
||||||
/* 100% Scrolls */ 2040923, 2040027, 2040417, 2040617, 2040000, 2040202, 2040400, 2040512, 2040700, 2040803,
|
|
||||||
2041000, 2041012, 2048000, 2040926, 2040316, 2040420, 2040620, 2040003, 2040207, 2040414,
|
|
||||||
2040515, 2040703, 2040818, 2041003, 2041015, 2048003, 2040929, 2040319, 2040423, 2040623,
|
|
||||||
2040102, 2040300, 2040500, 2040600, 2040706, 2040900, 2041006, 2041018, 2040024, 2040324,
|
|
||||||
2040530, 2040823, 2040107, 2040312, 2040503, 2040614, 2040800, 2040918, 2041009, 2041021
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getUncommonItems() {
|
public int[] getUncommonItems() {
|
||||||
return new int[] {
|
return new int[] {
|
||||||
/* Capes */ 1102180,
|
/* Potions */
|
||||||
/* Potions */ 2022179, 2022273, 2022282, 2022283,
|
2022179, 2022273, 2022282, 2022283, 2022285, 2022245, 2022182,
|
||||||
/* Scrolls */ 2049003,
|
|
||||||
/* Skis */ 1432018
|
/* Scrolls */
|
||||||
|
2049003
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getRareItems() {
|
public int[] getRareItems() {
|
||||||
return new int[] {
|
return new int[] {
|
||||||
/* Gloves */ 1082149,
|
/* Scrolls */
|
||||||
/* Capes */ 1102041, 1102042, 1102084, 1102085,
|
2049100, 2340000,
|
||||||
/* Scrolls */ 2049100, 2340000,
|
|
||||||
/* Chairs */ 3010046, 3010047
|
/* Chairs */
|
||||||
|
3010063, 3010064
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,10 @@ package server.gachapon;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alan (SharpAceX)
|
* @author Alan (SharpAceX) - gachapon source classes stub
|
||||||
|
* @author Ronan - parsed MapleSEA loots
|
||||||
|
*
|
||||||
|
* MapleSEA-like loots thanks to AyumiLove, src: https://ayumilovemaple.wordpress.com/maplestory-gachapon-guide/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class Henesys extends GachaponItems {
|
public class Henesys extends GachaponItems {
|
||||||
@@ -10,31 +13,49 @@ public class Henesys extends GachaponItems {
|
|||||||
@Override
|
@Override
|
||||||
public int[] getCommonItems() {
|
public int[] getCommonItems() {
|
||||||
return new int [] {
|
return new int [] {
|
||||||
/* Common Eqps */ 1432009, 1302022, 1322027, 1062000, 1002033, 1092022, 1302021, 1322009, 1002012, 1322012,
|
|
||||||
/* Warrior Eqps */ 1312007, 1002093, 1051016, 1040030, 1060009, 1060000, 1082025, 1402002, 1092000, 1072041,
|
/* Scroll */
|
||||||
/* Mage Equips */ 1051023, 1002035, 1061028, 1040019, 1002152, 1002155, 1041018, 1050031, 1002102, 1082028,
|
2040001, 2041002, 2040702, 2043802, 2040402, 2043702, 2044813,
|
||||||
/* Bowman Equips */ 1002010, 1002057, 1002112, 1002113, 1002114, 1002115, 1002116, 1002117, 1002118, 1002119,
|
|
||||||
1002120, 1002121, 1002135, 1002136, 1002137, 1002138, 1002139, 1002156, 1002157, 1002158,
|
/* Useable Drops */
|
||||||
1002159, 1002160, 1002161, 1002162, 1002163, 1002164, 1002165, 1002166, 1002167, 1002168,
|
2000004, 2000005, 2020012, 2030007,
|
||||||
1002169, 1002170, 1002211, 1002212, 1002213, 1002214, 1002267, 1002268, 1002269, 1002270,
|
|
||||||
1002275, 1002276, 1002277, 1002278, 1002286, 1002287, 1002288, 1002289, 1002402, 1002403,
|
/* Common equipment */
|
||||||
1002404, 1002405, 1002406, 1002407, 1002408, 1002580, 1002749
|
1432009, 1302022, 1322021, 1302026, 1442017, 1082147, 1102043, 1322026, 1442016, 1402012, 1322025, 1322027, 1302027,
|
||||||
|
1312012, 1062000, 1332020, 1302028, 1372002, 1002033, 1092022, 1302021, 1322009, 1322024, 1082148, 1002012, 1322012,
|
||||||
|
1322022, 1002020, 1302013, 1082146, 1442014, 1002096, 1302017, 1442012,
|
||||||
|
|
||||||
|
/* Warrior equipment */
|
||||||
|
1092011, 1092014, 1302003, 1432001, 1312011, 1002088, 1041020, 1322015, 1442004, 1422008, 1302056, 1432000, 1442005,
|
||||||
|
|
||||||
|
/* Magician equipment */
|
||||||
|
1382001, 1041053, 1041029, 1050053, 1051032, 1050073, 1061036, 1002253, 1002034, 1051025, 1050067, 1051052, 1002072,
|
||||||
|
1002144, 1051054, 1050069, 1372007, 1050056, 1050074, 1002254, 1002274, 1002218, 1051055, 1382010, 1002246, 1050039,
|
||||||
|
1382007, 1372000, 1002013, 1050072, 1002036, 1002244, 1372008, 1382008, 1382011, 1092021, 1051034, 1050047, 1040019,
|
||||||
|
1041031, 1051033, 1002153, 1002252, 1051024, 1051053, 1050068, 1382003, 1382006, 1050055, 1051031, 1050025, 1002155,
|
||||||
|
1002245, 1372001,
|
||||||
|
|
||||||
|
/* Bowman equipment */
|
||||||
|
1452004, 1452023, 1060057, 1432001, 1040071, 1002137, 1462009, 1452017, 1040025, 1041027, 1452005, 1452007, 1061057,
|
||||||
|
|
||||||
|
/* Thief equipment */
|
||||||
|
1472006, 1472019, 1060084, 1472028, 1472004, 1002179, 1082074, 1472029, 1040100, 1332015, 1432001, 1040097, 1060071,
|
||||||
|
1472007, 1472002, 1051009, 1041044, 1041003, 1332016, 1472020, 1332003,
|
||||||
|
|
||||||
|
/* Pirate equipment */
|
||||||
|
1002622, 1082204, 1082213, 1082198, 1002631, 1052122, 1482012, 1052131, 1482007, 1482004, 1072318, 1492007
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getUncommonItems() {
|
public int[] getUncommonItems() {
|
||||||
return new int[] {
|
return new int[] {2040805, 1102041, 1102042, 1442018};
|
||||||
/* 110 Equips */ 1002547
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getRareItems() {
|
public int[] getRareItems() {
|
||||||
return new int[] {
|
return new int[] {};
|
||||||
/* Reverse Eqps */ 1002792,
|
|
||||||
1462052, 1462053, 1462054, 1462055,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,10 @@ package server.gachapon;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alan (SharpAceX)
|
* @author Alan (SharpAceX) - gachapon source classes stub & pirate equipment
|
||||||
|
* @author Ronan - parsed MapleSEA loots
|
||||||
|
*
|
||||||
|
* MapleSEA-like loots thanks to AyumiLove, src: https://ayumilovemaple.wordpress.com/maplestory-gachapon-guide/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class KerningCity extends GachaponItems {
|
public class KerningCity extends GachaponItems {
|
||||||
@@ -10,112 +13,47 @@ public class KerningCity extends GachaponItems {
|
|||||||
@Override
|
@Override
|
||||||
public int[] getCommonItems() {
|
public int[] getCommonItems() {
|
||||||
return new int [] {
|
return new int [] {
|
||||||
//warriorEquips = {
|
|
||||||
1002023, 1082001, 1041084, 1060017, 1422008,
|
/* Scroll */
|
||||||
1402018, 1060019, 1072047, 1040009, 1060060,
|
2041016, 2043302, 2040902, 2044804, 2044906,
|
||||||
//magicianEquips = {
|
|
||||||
1050029, 1072045, 1050028, 1372001, 1051024,
|
/* Useable drop */
|
||||||
1061049, 1072091, 1041030, 1041042, 1002036,
|
2000004, 2000005, 2022025, 2022027,
|
||||||
//bowmanEquips = {
|
|
||||||
1072103, 1072034, 1072069, 1062004, 1082050,
|
/* Common equipment */
|
||||||
1040003, 1061064, 1040074, 1061051, 1040079,
|
1442013, 1432009, 1322021, 1050018, 1002392, 1002394, 1442004, 1372002, 1002418, 1002033, 1092008,
|
||||||
//thiefEquips = {
|
1082148, 1062001, 1302017, 1032023, 1102013, 1102040, 1002041, 1002097,
|
||||||
1002107, 1002108, 1002109, 1002110, 1002111,
|
|
||||||
1002122, 1002123, 1002124, 1002125, 1002126,
|
/* Warrior equipment */
|
||||||
1002127, 1002128, 1002129, 1002130, 1002131,
|
1332026, 1051010, 1432001, 1422005, 1332019, 1302010, 1002056, 1060011, 1322011, 1432004, 1002028,
|
||||||
1002146, 1002147, 1002148, 1002149, 1002150,
|
1051000, 1442007, 1302002,
|
||||||
1002171, 1002172, 1002173, 1002174, 1002175,
|
|
||||||
1002176, 1002177, 1002178, 1002179, 1002180,
|
/* Magician equipment */
|
||||||
1002181, 1002182, 1002183, 1002184, 1002185,
|
1002037, 1002034, 1082020, 1050039, 1372000, 1002215, 1051034, 1040019, 1061034, 1382003, 1382006,
|
||||||
1002207, 1002208, 1002209, 1002210, 1002247,
|
1050025,
|
||||||
1002248, 1002249, 1002281, 1002282, 1002283,
|
|
||||||
1002284, 1002285, 1002323, 1002324, 1002325,
|
/* Bowman equipment */
|
||||||
1002326, 1002327, 1002328, 1002329, 1002330,
|
1002118, 1061081, 1452011, 1462012, 1452006, 1452007,
|
||||||
1002380, 1002381, 1002382, 1002383, 1002550,
|
|
||||||
1002577, 1002656, 1002750,
|
/* Thief equipment */
|
||||||
1040031, 1040032, 1040033, 1040034, 1040035,
|
1472010, 1472029, 1041048, 1041095, 1060031, 1061033, 1041049, 1472011, 1040096, 1472033, 1332026,
|
||||||
1040042, 1040043, 1040044, 1040048, 1040049,
|
1051006, 1082074, 1472025, 1061106, 1040084, 1332015, 1472000, 1332019, 1002183, 1002209, 1092020,
|
||||||
1040050, 1040057, 1040058, 1040059, 1040060,
|
1332029, 1092019, 1061099, 1060106, 1040032, 1040059, 1332003, 1040060, 1060046, 1472005, 1332027,
|
||||||
1040061, 1040062, 1040063, 1040082, 1040083,
|
|
||||||
1040084, 1040094, 1040095, 1040096, 1040097,
|
/* Pirate equipment */
|
||||||
1040098, 1040099, 1040100, 1040105, 1040106,
|
|
||||||
1040107, 1040108, 1040109, 1040110, 1040115,
|
|
||||||
1040116, 1040117, 1040118, 1041003, 1041036,
|
|
||||||
1041037, 1041038, 1041039, 1041040, 1041044,
|
|
||||||
1041045, 1041047, 1041048, 1041049, 1041050,
|
|
||||||
1041057, 1041058, 1041059, 1041060, 1041074,
|
|
||||||
1041075, 1041076, 1041077, 1041078, 1041079,
|
|
||||||
1041080, 1041094, 1041095, 1041096, 1041100,
|
|
||||||
1041101, 1041102, 1041103, 1041105, 1041106,
|
|
||||||
1041107, 1041115, 1041116, 1041117, 1041118,
|
|
||||||
1050096, 1050097, 1050098, 1050099, 1051006,
|
|
||||||
1051007, 1051008, 1051009, 1051090, 1051091,
|
|
||||||
1051092, 1051093, 1052072, 1052163,
|
|
||||||
1060021, 1060022, 1060023, 1060024, 1060025,
|
|
||||||
1060031, 1060032, 1060033, 1060037, 1060038,
|
|
||||||
1060039, 1060043, 1060044, 1060045, 1060046,
|
|
||||||
1060050, 1060051, 1060052, 1060071, 1060072,
|
|
||||||
1060073, 1060083, 1060084, 1060085, 1060086,
|
|
||||||
1060087, 1060088, 1060089, 1060093, 1060094,
|
|
||||||
1060095, 1060097, 1060098, 1060099, 1060104,
|
|
||||||
1060105, 1060106, 1060107, 1061003, 1061029,
|
|
||||||
1061030, 1061031, 1061032, 1061033, 1061037,
|
|
||||||
1061038, 1061040, 1061041, 1061042, 1061043,
|
|
||||||
1061044, 1061045, 1061046, 1061053, 1061054,
|
|
||||||
1061055, 1061056, 1061069, 1061070, 1061071,
|
|
||||||
1061076, 1061077, 1061078, 1061079, 1061093,
|
|
||||||
1061094, 1061095, 1061099, 1061100, 1061101,
|
|
||||||
1061102, 1061104, 1061105, 1061106, 1061114,
|
|
||||||
1061115, 1061116, 1061117, 1072022, 1072028,
|
|
||||||
1072029, 1072030, 1072031, 1072032, 1072033,
|
|
||||||
1072035, 1072036, 1072065, 1072066, 1072070,
|
|
||||||
1072071, 1072084, 1072085, 1072086, 1072087,
|
|
||||||
1072104, 1072105, 1072106, 1072107, 1072108,
|
|
||||||
1072109, 1072110, 1072128, 1072129, 1072130,
|
|
||||||
1072131, 1072150, 1072151, 1072152, 1072161,
|
|
||||||
1072162, 1072163, 1072171, 1072172, 1072173,
|
|
||||||
1072174, 1072192, 1072193, 1072194, 1072195,
|
|
||||||
1072213, 1072214, 1072215, 1072216, 1072272,
|
|
||||||
1072346, 1082029, 1082030,
|
|
||||||
1082031, 1082032, 1082033, 1082034, 1082037,
|
|
||||||
1082038, 1082039, 1082042, 1082043, 1082044,
|
|
||||||
1082045, 1082046, 1082047, 1082065, 1082066,
|
|
||||||
1082067, 1082074, 1082075, 1082076, 1082092,
|
|
||||||
1082093, 1082094, 1082095, 1082096, 1082097,
|
|
||||||
1082118, 1082119, 1082120, 1082135, 1082136,
|
|
||||||
1082137, 1082138, 1082142, 1082143, 1082144,
|
|
||||||
1082167, 1082242, 1092018, 1092019,
|
|
||||||
1092020, 1302001,
|
|
||||||
1312002, 1332000, 1332001, 1332002, 1332003,
|
|
||||||
1332004, 1332011, 1332012, 1332013, 1332014,
|
|
||||||
1332015, 1332018, 1332023, 1332024, 1332027,
|
|
||||||
1332031, 1332050, 1332052, 1332054,
|
|
||||||
1332067, 1332068, 1332069, 1332070, 1332071,
|
|
||||||
1332072, 1332077,
|
|
||||||
1472000, 1472001, 1472002,
|
|
||||||
1472003, 1472004, 1472005, 1472006, 1472007,
|
|
||||||
1472008, 1472009, 1472010, 1472011, 1472012,
|
|
||||||
1472013, 1472014, 1472015, 1472016, 1472017,
|
|
||||||
1472018, 1472019, 1472020, 1472021, 1472022,
|
|
||||||
1472023, 1472024, 1472025, 1472026, 1472027,
|
|
||||||
1472028, 1472029, 1472031, 1472033, 1472051,
|
|
||||||
1472052,
|
|
||||||
1472069, 1472072, 1472074,
|
|
||||||
1472075,
|
|
||||||
///pirateEquips = {
|
|
||||||
1082192, 1072288, 1492003, 1052113, 1052104,
|
1082192, 1072288, 1492003, 1052113, 1052104,
|
||||||
1492002, 1052095, 1492001, 1002613, 1492004,
|
1492002, 1052095, 1492001, 1002613, 1492004
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getUncommonItems() {
|
public int[] getUncommonItems() {
|
||||||
return new int[] {1472053, 1332064, 1092050, 1472054};
|
return new int[] {2040805, 1082149, 1102041};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getRareItems() {
|
public int[] getRareItems() {
|
||||||
return new int[] {1472073, 1092049, 1002793, 1332079, 1072364, 1472062, 1332078, 1332080};
|
return new int[] {};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package server.gachapon;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Ronan - parsed MapleSEA loots
|
||||||
|
*
|
||||||
|
* MapleSEA-like loots thanks to AyumiLove, src: https://ayumilovemaple.wordpress.com/maplestory-gachapon-guide/
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Ludibrium extends GachaponItems {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] getCommonItems() {
|
||||||
|
return new int [] {
|
||||||
|
|
||||||
|
/* Scroll */
|
||||||
|
2048000, 2040601, 2041019, 2041007, 2041016, 2041022, 2041001, 2041010, 2041013, 2041004, 2044701, 2043301, 2040301, 2048004, 2048001, 2040901, 2040701, 2040704, 2040707, 2040602, 2041020, 2041008, 2041017, 2041023, 2041002, 2041011, 2041014, 2041005, 2044702, 2043302, 2040302, 2040002, 2044402, 2048005, 2048002, 2040702, 2040705, 2040708, 2044302, 2043802, 2040402, 2043702, 2044811,
|
||||||
|
|
||||||
|
/* Useable drop */
|
||||||
|
2000004, 2000005, 4006000, 4006001,
|
||||||
|
|
||||||
|
/* Common equipment */
|
||||||
|
1032003, 1432009, 1302022, 1302029, 1102014, 1102018, 1312014, 1302026, 1102015, 1032011, 1312013, 1032008, 1032019, 1032007, 1332030, 1032020, 1032004, 1302027, 1032022, 1312012, 1032021, 1032006, 1302028, 1322003, 1032016, 1032015, 1302024, 1092008, 1032018, 1302021, 1032014, 1332021, 1322012, 1032005, 1032013, 1102012, 1302025, 1302013, 1032002, 1032001, 1032012, 1302017, 1032010, 1402014, 1102017, 1102013, 1442021, 1032009,
|
||||||
|
|
||||||
|
/* Beginner equipment */
|
||||||
|
1332021, 1422011,
|
||||||
|
|
||||||
|
/* Warrior equipment */
|
||||||
|
1402017, 1422005, 1002023, 1332016, 1432005,
|
||||||
|
|
||||||
|
/* Magician equipment */
|
||||||
|
1002037, 1002034, 1002064, 1002038, 1002013, 1002036, 1382011, 1002035, 1002065, 1382014, 1372001,
|
||||||
|
|
||||||
|
/* Bowman equipment */
|
||||||
|
1452026, 1002162, 1002164, 1462018, 1002165, 1452014, 1002163, 1452012, 1002161, 1452009, 1462007,
|
||||||
|
|
||||||
|
/* Thief Equipment */
|
||||||
|
1332022, 1002175, 1002172, 1002174, 1040096, 1472033, 1002173, 1332054, 1472054, 1002171, 1332016,
|
||||||
|
|
||||||
|
/* Pirate equipment */
|
||||||
|
1002646
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] getUncommonItems() {
|
||||||
|
return new int [] {2040805, 1002419, 1442018};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] getRareItems() {
|
||||||
|
return new int [] {};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
*/
|
*/
|
||||||
package server.gachapon;
|
package server.gachapon;
|
||||||
|
|
||||||
|
import server.MapleItemInformationProvider;
|
||||||
import tools.Randomizer;
|
import tools.Randomizer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -46,7 +47,9 @@ public class MapleGachapon {
|
|||||||
MUSHROOM_SHRINE(9100105, 90, 8, 2, new MushroomShrine()),
|
MUSHROOM_SHRINE(9100105, 90, 8, 2, new MushroomShrine()),
|
||||||
SHOWA_SPA_MALE(9100106, 90, 8, 2, new ShowaSpaMale()),
|
SHOWA_SPA_MALE(9100106, 90, 8, 2, new ShowaSpaMale()),
|
||||||
SHOWA_SPA_FEMALE(9100107, 90, 8, 2, new ShowaSpaFemale()),
|
SHOWA_SPA_FEMALE(9100107, 90, 8, 2, new ShowaSpaFemale()),
|
||||||
|
LUDIBRIUM(9100108, 90, 8, 2, new Ludibrium()),
|
||||||
NEW_LEAF_CITY(9100109, 90, 8, 2, new NewLeafCity()),
|
NEW_LEAF_CITY(9100109, 90, 8, 2, new NewLeafCity()),
|
||||||
|
EL_NATH(9100110, 90, 8, 2, new ElNath()),
|
||||||
NAUTILUS_HARBOR(9100117, 90, 8, 2, new NautilusHarbor());
|
NAUTILUS_HARBOR(9100117, 90, 8, 2, new NautilusHarbor());
|
||||||
|
|
||||||
private static final Gachapon[] values = Gachapon.values();
|
private static final Gachapon[] values = Gachapon.values();
|
||||||
@@ -71,9 +74,10 @@ public class MapleGachapon {
|
|||||||
return 2; //Rare
|
return 2; //Rare
|
||||||
} else if (chance > common) {
|
} else if (chance > common) {
|
||||||
return 1; //Uncommon
|
return 1; //Uncommon
|
||||||
}
|
} else {
|
||||||
return 0; //Common
|
return 0; //Common
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int [] getItems(int tier){
|
public int [] getItems(int tier){
|
||||||
return gachapon.getItems(tier);
|
return gachapon.getItems(tier);
|
||||||
@@ -94,6 +98,44 @@ public class MapleGachapon {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String[] getLootInfo() {
|
||||||
|
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
||||||
|
|
||||||
|
String[] strList = new String[values.length + 1];
|
||||||
|
|
||||||
|
String menuStr = "";
|
||||||
|
int j = 0;
|
||||||
|
for (Gachapon gacha : values) {
|
||||||
|
menuStr += "#L" + j + "#" + gacha.name() + "#l\r\n";
|
||||||
|
j++;
|
||||||
|
|
||||||
|
String str = "";
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
int[] gachaItems = gacha.getItems(i);
|
||||||
|
|
||||||
|
if (gachaItems.length > 0) {
|
||||||
|
str += (" #rTier " + i + "#k:\r\n");
|
||||||
|
for (int itemid : gachaItems) {
|
||||||
|
String itemName = ii.getName(itemid);
|
||||||
|
if (itemName == null) {
|
||||||
|
itemName = "MISSING NAME #" + itemid;
|
||||||
|
}
|
||||||
|
|
||||||
|
str += (" " + itemName + "\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
str += "\r\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
str += "\r\n";
|
||||||
|
|
||||||
|
strList[j] = str;
|
||||||
|
}
|
||||||
|
strList[0] = menuStr;
|
||||||
|
|
||||||
|
return strList;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public MapleGachaponItem process(int npcId) {
|
public MapleGachaponItem process(int npcId) {
|
||||||
|
|||||||
@@ -2,7 +2,10 @@ package server.gachapon;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alan (SharpAceX)
|
* @author Alan (SharpAceX) - gachapon source classes stub
|
||||||
|
* @author Ronan - parsed MapleSEA loots
|
||||||
|
*
|
||||||
|
* MapleSEA-like loots thanks to AyumiLove, src: https://ayumilovemaple.wordpress.com/maplestory-gachapon-guide/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class MushroomShrine extends GachaponItems {
|
public class MushroomShrine extends GachaponItems {
|
||||||
@@ -10,31 +13,46 @@ public class MushroomShrine extends GachaponItems {
|
|||||||
@Override
|
@Override
|
||||||
public int[] getCommonItems() {
|
public int[] getCommonItems() {
|
||||||
return new int [] {
|
return new int [] {
|
||||||
1382011, 1332024, 1302022, 1302021, 1462006, 1402009, 1402010, 1322012, 1312013, 1472008,
|
|
||||||
1432008, 1050100, 1051098,
|
/* Scroll */
|
||||||
|
2040305, 2040306, 2040308, 2044604, 2041039, 2041037, 2041035, 2041034, 2041041, 2040608, 2040605, 2040604, 2040611,
|
||||||
|
2040610, 2040813, 2040808, 2043004, 2040017, 2040015, 2040011, 2040013, 2040405, 2040406, 2040410, 2040511, 2040509,
|
||||||
|
2040508, 2040519, 2040521, 2040108, 2040904, 2040908, 2043104, 2044104, 2043005, 2043004, 2043006, 2044004, 2044205,
|
||||||
|
2043304, 2040607, 2040715, 2040713, 2044305, 2044904,
|
||||||
|
|
||||||
|
/* Common equipment */
|
||||||
|
1102040, 1002392, 1432009, 1002393, 1002394, 1082147, 1082148, 1032028, 1002585, 1002586, 1432013, 1022047, 1322027,
|
||||||
|
1012056, 1432018,
|
||||||
|
|
||||||
|
/* Beginner equipment */
|
||||||
|
1072264, 1072262, 1072263,
|
||||||
|
|
||||||
|
/* Warrior equipment */
|
||||||
|
1060074, 1322002, 1002340, 1442004, 1402037, 1422008, 1050022,
|
||||||
|
|
||||||
|
/* Mage equipment */
|
||||||
|
1382037, 1060014, 1051026, 1050056, 1050029, 1051030, 1382036, 1372032, 1041015, 1382015, 1372008, 1382008,
|
||||||
|
|
||||||
|
/* Bowman equipment */
|
||||||
|
1452018, 1041068, 1462007,
|
||||||
|
|
||||||
|
/* Thief equipment */
|
||||||
|
1060052, 1472013, 1002180, 1002170, 1060073, 1060099,
|
||||||
|
|
||||||
|
/* Pirate equipment */
|
||||||
|
1492004, 1492012, 1482009, 1072303, 1002637, 1052107, 1082189, 1052116, 1072309
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getUncommonItems() {
|
public int[] getUncommonItems() {
|
||||||
//All Scrolls
|
return new int [] {2040811, 2040810, 2040815, 1102041, 1102042, 1082149};
|
||||||
return new int [] {
|
|
||||||
2043015, 2043017, 2043019, 2044000, 2044001, 2044002, 2044004, 2044005, 2044010, 2044012,
|
|
||||||
2044014, 2043200, 2043201, 2043202, 2043204, 2043205, 2043210, 2043212, 2043214, 2044200,
|
|
||||||
2044201, 2044202, 2044204, 2044205, 2044210, 2044212, 2044214, 2044300, 2044301, 2044302,
|
|
||||||
2044304, 2044305, 2044310, 2044312, 2044314, 2044400, 2044401, 2044402, 2044404, 2044405,
|
|
||||||
2044410, 2044412, 2044414,
|
|
||||||
2043800, 2043801, 2043802, 2043804, 2043805, 2043700, 2043701, 2043702, 2043704, 2043705,
|
|
||||||
2044605, 2044604, 2044602, 2044601, 2044600, 2044505, 2044504, 2044502, 2044501, 2044500,
|
|
||||||
2044700, 2044701, 2044702, 2044704, 2044705, 2043300, 2043301, 2043302, 2043304, 2043305,
|
|
||||||
2044800, 2044801, 2044802, 2044803, 2044804, 2044805, 2044807, 2044809, 2044900, 2044901,
|
|
||||||
2044902, 2044903, 2044904,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getRareItems() {
|
public int[] getRareItems() {
|
||||||
return new int [] {};
|
return new int [] {1102084, 3010019};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,10 @@ package server.gachapon;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alan (SharpAceX)
|
* @author Alan (SharpAceX) - gachapon source classes stub & pirate items
|
||||||
|
* @author Ronan - parsed MapleSEA loots
|
||||||
|
*
|
||||||
|
* MapleSEA-like loots thanks to AyumiLove, src: https://ayumilovemaple.wordpress.com/maplestory-gachapon-guide/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class NautilusHarbor extends GachaponItems {
|
public class NautilusHarbor extends GachaponItems {
|
||||||
@@ -10,11 +13,30 @@ public class NautilusHarbor extends GachaponItems {
|
|||||||
@Override
|
@Override
|
||||||
public int[] getCommonItems() {
|
public int[] getCommonItems() {
|
||||||
return new int[] {
|
return new int[] {
|
||||||
/* Warrior Equips*/ 1060017, 1302008, 1002055, 1041064, 1072127, 1072047, 1072002, 1040028, 1072041, 1092000,
|
/* Scroll */
|
||||||
/* Mage Equips */ 1050010, 1072006, 1061022, 1051003, 1072074, 1050008, 1082053, 1051026, 1382015, 1002013,
|
2040605, 2040626, 2040609, 2040607, 2041029, 2041027, 2041031, 2041037, 2041033, 2041039, 2041041, 2041035,
|
||||||
/* Bowman Equips */ 1082048, 1041056, 1002157, 1462048, 1041054, 1061061, 1002161, 1002162, 1002158, 1002120,
|
2040809, 2040813, 2040015, 2040009, 2040011, 2040013, 2040509, 2040521, 2040519, 2040507, 2040905, 2040909,
|
||||||
/* Thief Equips */ 1040061, 1072031, 1051009, 1072036, 1002182, 1060073, 1472013, 1472009, 1002184, 1061055,
|
2040907, 2040713, 2040715, 2040717, 2040405, 2040409, 2040407, 2040426, 2040303, 2040307, 2040309, 2044505,
|
||||||
/* Pirate Equips */ 1002610, 1002616, 1002622, 1002628, 1002634, 1002640, 1002646, 1052095, 1052101, 1052107,
|
2044705, 2044605, 2043305, 2043105, 2043205, 2043005, 2043007, 2044405, 2044305, 2043805, 2044105, 2044205,
|
||||||
|
2044005, 2043705, 2044901,
|
||||||
|
|
||||||
|
/* Useable drop */
|
||||||
|
2012000, 2000004, 2020008, 2000005, 2012002, 2101004, 2101005, 2101002, 2101003, 4006000,
|
||||||
|
|
||||||
|
/* Warrior equipment */
|
||||||
|
1092014, 1402017,
|
||||||
|
|
||||||
|
/* Magician equipment */
|
||||||
|
1002037, 1002034, 1002064, 1002038, 1382037, 1372000, 1002013, 1002035, 1002065, 1382000,
|
||||||
|
|
||||||
|
/* Bowman equipment */
|
||||||
|
1452018,
|
||||||
|
|
||||||
|
/* Thief equipment */
|
||||||
|
1472010, 1002175, 1472017, 1472025,
|
||||||
|
|
||||||
|
/* Pirate equipment */
|
||||||
|
1002610, 1002616, 1002622, 1002628, 1002634, 1002640, 1002646, 1052095, 1052101, 1052107,
|
||||||
1052113, 1052119, 1052125, 1052131, 1072285, 1072291, 1072297, 1072303, 1072309, 1072315,
|
1052113, 1052119, 1052125, 1052131, 1072285, 1072291, 1072297, 1072303, 1072309, 1072315,
|
||||||
1082180, 1082186, 1082192, 1082198, 1082204, 1082210, 1482001, 1482003, 1482005, 1482007,
|
1082180, 1082186, 1082192, 1082198, 1082204, 1082210, 1482001, 1482003, 1482005, 1482007,
|
||||||
1482009, 1482011, 1492000, 1492002, 1492004, 1492006, 1492008, 1492010, 1492012, 1002613,
|
1482009, 1482011, 1492000, 1492002, 1492004, 1492006, 1492008, 1492010, 1492012, 1002613,
|
||||||
@@ -22,28 +44,23 @@ public class NautilusHarbor extends GachaponItems {
|
|||||||
1052128, 1072288, 1072294, 1072300, 1072306, 1072312, 1072318, 1072338, 1082183, 1082189,
|
1052128, 1072288, 1072294, 1072300, 1072306, 1072312, 1072318, 1072338, 1082183, 1082189,
|
||||||
1082195, 1082201, 1082207, 1082213, 1482000, 1482002, 1482004, 1482006, 1482008, 1482010,
|
1082195, 1082201, 1082207, 1082213, 1482000, 1482002, 1482004, 1482006, 1482008, 1482010,
|
||||||
1482012, 1492001, 1492003, 1492005, 1492007, 1492009, 1492011,
|
1482012, 1492001, 1492003, 1492005, 1492007, 1492009, 1492011,
|
||||||
/*KnucklerScrolls*/ 2044800, 2044801, 2044802, 2044803, 2044804, 2044805, 2044806, 2044807, 2044808, 2044809,
|
|
||||||
/* Gun Scrolls */ 2044900, 2044901, 2044902, 2044903, 2044904,
|
/* Knuckler Scrolls */
|
||||||
/* Bullets */ 2330005, 2330004
|
2044800, 2044801, 2044802, 2044803, 2044804, 2044805, 2044806, 2044807, 2044808, 2044809,
|
||||||
|
|
||||||
|
/* Gun Scrolls */
|
||||||
|
2044900, 2044901, 2044902, 2044903, 2044904
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getUncommonItems() {
|
public int[] getUncommonItems() {
|
||||||
return new int[] {
|
return new int[] {2040811, 2040815, 2101001};
|
||||||
/* Pirate Equips */ 1072321, 1082216, 1482013, 1002649, 1052134, 1492013,
|
|
||||||
/* Mastery Books */ 2290097, 2290098, 2290099, 2290100, 2290101, 2290102, 2290103, 2290104, 2290105, 2290106,
|
|
||||||
2290107, 2290108, 2290110, 2290111, 2290111, 2290113, 2290114, 2290115, 2290116, 2290117,
|
|
||||||
2290118, 2290119, 2290120, 2290121, 2290122, 2290123, 2290124
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getRareItems() {
|
public int[] getRareItems() {
|
||||||
return new int[] {
|
return new int[] {};
|
||||||
/* Pirate Equips */ 1082243, 1482024, 1002794, 1052164, 1072365,
|
|
||||||
1482034, 1492025
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,10 @@ package server.gachapon;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alan (SharpAceX)
|
* @author Alan (SharpAceX) - gachapon source classes stub & pirate equipment
|
||||||
|
* @author Ronan - parsed MapleSEA loots, thanks Vcoc for noticing somewhat unbalanced loots in NLC
|
||||||
|
*
|
||||||
|
* MapleSEA-like loots thanks to AyumiLove, src: https://ayumilovemaple.wordpress.com/maplestory-gachapon-guide/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class NewLeafCity extends GachaponItems {
|
public class NewLeafCity extends GachaponItems {
|
||||||
@@ -10,57 +13,43 @@ public class NewLeafCity extends GachaponItems {
|
|||||||
@Override
|
@Override
|
||||||
public int[] getCommonItems() {
|
public int[] getCommonItems() {
|
||||||
return new int[] {
|
return new int[] {
|
||||||
/* Warrior Equips*/ 1002338, 1002339, 1002340, 1002377, 1002378, 1002379, 1002528, 1002529, 1002530, 1002531,
|
|
||||||
1002532, 1040111, 1040112, 1040113, 1040120, 1040121, 1040122, 1041119, 1041120, 1041121,
|
/* Scroll */
|
||||||
1041122, 1041123, 1041124, 1050080, 1050081, 1050082, 1050083, 1051077, 1051078, 1051079,
|
2040406, 2040408, 2040404, 2040411, 2040409, 2044405, 2040610, 2040607, 2040812, 2041039, 2041040, 2041034,
|
||||||
1051080, 1060100, 1060101, 1060102, 1060109, 1060110, 1060111, 1061118, 1061119, 1061120,
|
2041030, 2041037, 2043105, 2043304, 2040103, 2040605, 2040611, 2043004, 2043204, 2044204, 2044005, 2040521,
|
||||||
1061121, 1061122, 1061123, 1072196, 1072197, 1072198, 1072210, 1072211, 1072212, 1072220,
|
2040510, 2043304, 2040908, 2040904, 2040907, 2040809, 2040812, 2040014, 2040714, 2040712, 2044004, 2043705,
|
||||||
1072221, 1072222, 1082114, 1082115, 1082116, 1082117, 1082128, 1082129, 1082130, 1082139,
|
2044505, 2040519, 2040204, 2040104, 2040109, 2044704, 2040906, 2044304, 2043007, 2040307, 2040304, 2040309,
|
||||||
1082140, 1082141, 1092023, 1092024, 1092025, 1092026, 1092027, 1092028, 1092036, 1092037,
|
2040208, 2040209, 2044803,
|
||||||
1092038, 1092061, 1302018, 1302023, 1302056, 1312011, 1312015, 1312030, 1322020, 1322028,
|
|
||||||
1322029, 1322045, 1402004, 1402005, 1402015, 1402016, 1402035,
|
/* Common equipment */
|
||||||
1412009, 1412010, 1412021, 1412040, 1422012, 1422013, 1422027, 1432010,
|
1102040, 1102086, 1082145, 1032027, 1082146, 1002395, 1002083, 1002392, 1002587, 1022047,
|
||||||
1432011, 1432030, 1432056, 1442019, 1442020, 1442044,
|
|
||||||
/* Mage Equips */ 1002271, 1002272, 1002273, 1002274, 1002363, 1002364, 1002365, 1002366, 1002398, 1002399,
|
/* Warrior equipment */
|
||||||
1002400, 1002401, 1050072, 1050073, 1050074, 1050092, 1050093, 1050094, 1050095, 1050102,
|
1312002, 1432013, 1060030, 1422008, 1050022, 1050011, 1402013, 1402017, 1302012,
|
||||||
1050103, 1050104, 1050105, 1051056, 1051057, 1051058, 1051094, 1051095, 1051096, 1051097,
|
|
||||||
1051101, 1051102, 1051103, 1051104, 1072177, 1072178, 1072179, 1072206, 1072207, 1072208,
|
/* Mage equipment */
|
||||||
1072209, 1072223, 1072224, 1072225, 1072226, 1082121, 1082122, 1082123, 1082131, 1082132,
|
1002074, 1050029, 1040093, 1050056, 1050039, 1382008,
|
||||||
1082133, 1082134, 1082151, 1082152, 1082153, 1082154, 1372009, 1372010, 1372016, 1382008,
|
|
||||||
1382010, 1382016, 1382035, 1382056, 1382060,
|
/* Bowman equipment */
|
||||||
/* Bowman Equips */ 1002275, 1002276, 1002277, 1002275, 1002278, 1002402, 1002403, 1002404, 1002405, 1002406,
|
1002159, 1061051, 1040023,
|
||||||
1002407, 1002408, 1050075, 1050076, 1050077, 1050078, 1050088, 1050089, 1050090, 1050091,
|
|
||||||
1050106, 1050107, 1050108, 1002275, 1051066, 1051067, 1051068, 1051069, 1051082, 1051083,
|
/* Thief equipment */
|
||||||
1051084, 1051085, 1051105, 1051106, 1051107, 1072182, 1072183, 1072184, 1072185, 1072203,
|
1061054, 1061106, 1002249, 1040084, 1060052, 1472054,
|
||||||
1072204, 1072205, 1072227, 1072228, 1072229, 1082109, 1082110, 1082111, 1082112, 1082125,
|
|
||||||
1082126, 1082127, 1082158, 1082159, 1082160, 1452012, 1452013, 1452014, 1452015, 1452017,
|
/* Pirate equipment */
|
||||||
1452019, 1452020, 1452021, 1452025, 1452026, 1452060, 1462010, 1452017, 1462011, 1462012,
|
1002640, 1002643, 1002646, 1052125, 1052128, 1052131, 1072312, 1072315, 1072318, 1082207, 1082210, 1082213,
|
||||||
1462013, 1462015, 1462016, 1462017, 1462018, 1462021, 1462022, 1462049,
|
1482010, 1482011, 1002640, 1482012, 1492010, 1492011, 1492012
|
||||||
/* Thief Equips */ 1002323, 1002324, 1002325, 1002326, 1002327, 1002328, 1002329, 1002330, 1002380, 1002381,
|
|
||||||
1002382, 1002383, 1040108, 1040109, 1040110, 1040115, 1040117, 1040118, 1041105, 1041106,
|
|
||||||
1041107, 1041115, 1041116, 1041117, 1041118, 1050096, 1050097, 1050098, 1050099, 1051090,
|
|
||||||
1051091, 1051092, 1051093, 1060097, 1060098, 1060099, 1060104, 1060105, 1060106, 1060107,
|
|
||||||
1061104, 1061105, 1061106, 1061114, 1061115, 1061116, 1061117, 1072172, 1072173, 1072174,
|
|
||||||
1072192, 1072193, 1072194, 1072195, 1072213, 1072214, 1072215, 1072216, 1082118, 1082119,
|
|
||||||
1082120, 1082135, 1082136, 1082137, 1082138, 1082143, 1082144, 1092050, 1332023, 1332027,
|
|
||||||
1332052, 1332069, 1332072, 1472031, 1472033, 1472053,
|
|
||||||
/* Pirate Equips */ 1002640, 1002643, 1002646, 1052125, 1052128, 1052131, 1072312, 1072315, 1072318, 1082207,
|
|
||||||
1082210, 1082213, 1482010, 1482011, 1002640, 1482012, 1492010, 1492011, 1492012
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getUncommonItems() {
|
public int[] getUncommonItems() {
|
||||||
return new int[] {
|
return new int[] {2022284, 2040811, 2040815, 2040811, 1102041, 1102042, 1082149};
|
||||||
2022179
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getRareItems() {
|
public int[] getRareItems() {
|
||||||
return new int[] {
|
return new int[] {};
|
||||||
2049100
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+34
-114
@@ -2,7 +2,10 @@ package server.gachapon;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alan (SharpAceX)
|
* @author Alan (SharpAceX) - gachapon source classes stub & pirate equipment
|
||||||
|
* @author Ronan - parsed MapleSEA loots
|
||||||
|
*
|
||||||
|
* MapleSEA-like loots thanks to AyumiLove, src: https://ayumilovemaple.wordpress.com/maplestory-gachapon-guide/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class Perion extends GachaponItems {
|
public class Perion extends GachaponItems {
|
||||||
@@ -10,128 +13,45 @@ public class Perion extends GachaponItems {
|
|||||||
@Override
|
@Override
|
||||||
public int[] getCommonItems() {
|
public int[] getCommonItems() {
|
||||||
return new int [] {
|
return new int [] {
|
||||||
//warriorEquips = {
|
|
||||||
1002002, 1002003, 1002004, 1002005, 1002007,
|
/* Scrolls */
|
||||||
1002009, 1002011, 1002021, 1002022, 1002023,
|
2044907, 2044802,
|
||||||
1002024, 1002025, 1002027, 1002028, 1002029,
|
|
||||||
1002030, 1002039, 1002040, 1002043, 1002044,
|
/* Useable drop */
|
||||||
1002045, 1002046, 1002047, 1002048, 1002049,
|
2000004, 2000005,
|
||||||
1002050, 1002051, 1002052, 1002055, 1002056,
|
|
||||||
1002058, 1002059, 1002084, 1002085, 1002086,
|
/* Common equipment */
|
||||||
1002087, 1002088, 1002091, 1002092, 1002093,
|
1402010, 1302022, 1002060, 1322021, 1082147, 1002006, 1002026, 1002392, 1322025, 1322027, 1102000, 1082150,
|
||||||
1002094, 1002095, 1002098, 1002099, 1002100,
|
1332020, 1322007, 1302021, 1002395, 1082148, 1322012, 1302017, 1322010, 1032000, 1102013, 1002097,
|
||||||
1002101, 1002338, 1002339, 1002340, 1002377,
|
|
||||||
1002378, 1002379, 1002528, 1002529, 1002530,
|
/* Warrior equipment */
|
||||||
1002531, 1002532, 1002551, 1002578,
|
1322020, 1312007, 1312008, 1302004, 1312006, 1082036, 1082117, 1061088, 1302008, 1422005, 1002048, 1061087,
|
||||||
1002790, 1040000, 1040009, 1040012, 1040015,
|
1302018, 1322017, 1422001, 1040103, 1060077, 1002022, 1002050, 1442000, 1432030, 1402037, 1092002, 1041092,
|
||||||
1040016, 1040021, 1040026, 1040028, 1040029,
|
1050006, 1432004, 1061019, 1432000, 1060009, 1051000, 1002021, 1322014, 1432005,
|
||||||
1040030, 1040037, 1040038, 1040039, 1040040,
|
|
||||||
1040041, 1040085, 1040086, 1040087, 1040088,
|
/* Magician equipment */
|
||||||
1040089, 1040090, 1040091, 1040092, 1040093,
|
1051032, 1040018, 1051027, 1372007, 1050049, 1002036, 1382012, 1002217, 1051033, 1382006, 1050048,
|
||||||
1040102, 1040103, 1040104, 1040111, 1040112,
|
|
||||||
1040113, 1040120, 1040121, 1040122, 1041014,
|
/* Bowman equipment */
|
||||||
1041019, 1041020, 1041021, 1041022, 1041023,
|
1061061, 1060062, 1040075, 1462013, 1041065, 1452006,
|
||||||
1041024, 1041064, 1041084, 1041085, 1041086,
|
|
||||||
1041087, 1041088, 1041089, 1041091, 1041092,
|
/* Thief equipment */
|
||||||
1041093, 1041097, 1041098, 1041099, 1041119,
|
1040095, 1060084, 1002182, 1041049, 1002247, 1332024, 1332009, 1060024, 1332015, 1041060, 1061032, 1041074,
|
||||||
1041120, 1041121, 1041122, 1041123, 1041124,
|
1041003, 1332016, 1472020, 1332003, 1041059,
|
||||||
1050000, 1050005, 1050006, 1050007, 1050011,
|
|
||||||
1050021, 1050022, 1050080, 1050081, 1050082,
|
/* Pirate equipment */
|
||||||
1050083, 1051000, 1051001, 1051010, 1051011,
|
1482001, 1492002, 1052113, 1002616, 1072294, 1492004, 1482006, 1082192, 1082189, 1082195
|
||||||
1051012, 1051013, 1051014, 1051015, 1051016,
|
|
||||||
1051077, 1051078, 1051079, 1051080, 1052075,
|
|
||||||
1052160, 1060000, 1060008, 1060009,
|
|
||||||
1060010, 1060011, 1060016, 1060017, 1060018,
|
|
||||||
1060019, 1060020, 1060027, 1060028, 1060029,
|
|
||||||
1060030, 1060060, 1060074, 1060075, 1060076,
|
|
||||||
1060077, 1060078, 1060079, 1060080, 1060081,
|
|
||||||
1060082, 1060090, 1060091, 1060092, 1060100,
|
|
||||||
1060101, 1060102, 1060109, 1060110, 1060111,
|
|
||||||
1061014, 1061015, 1061016, 1061017, 1061018,
|
|
||||||
1061019, 1061020, 1061023, 1061083, 1061084,
|
|
||||||
1061085, 1061086, 1061087, 1061088, 1061090,
|
|
||||||
1061091, 1061092, 1061096, 1061097, 1061098,
|
|
||||||
1061118, 1061119, 1061120, 1061121, 1061122,
|
|
||||||
1061123, 1072000, 1072002, 1072003, 1072007,
|
|
||||||
1072009, 1072011, 1072039, 1072040, 1072041,
|
|
||||||
1072046, 1072047, 1072050, 1072051, 1072052,
|
|
||||||
1072053, 1072112, 1072113, 1072126, 1072127,
|
|
||||||
1072132, 1072133, 1072134, 1072135, 1072147,
|
|
||||||
1072148, 1072149, 1072154, 1072155, 1072156,
|
|
||||||
1072168, 1072196, 1072197, 1072198, 1072210,
|
|
||||||
1072211, 1072212, 1072220, 1072221, 1072222,
|
|
||||||
1072273, 1082000, 1082001,
|
|
||||||
1082003, 1082004, 1082005, 1082006, 1082007,
|
|
||||||
1082008, 1082009, 1082010, 1082011, 1082023,
|
|
||||||
1082024, 1082025, 1082035, 1082036, 1082059,
|
|
||||||
1082060, 1082061, 1082103, 1082104, 1082105,
|
|
||||||
1082114, 1082115, 1082116, 1082117, 1082128,
|
|
||||||
1082129, 1082130, 1082139, 1082140, 1082141,
|
|
||||||
1082168, 1082218, 1082239, 1092000,
|
|
||||||
1092001, 1092002, 1092004, 1092005, 1092006,
|
|
||||||
1092007, 1092009, 1092010, 1092011, 1092012,
|
|
||||||
1092013, 1092014, 1092015, 1092016, 1092017,
|
|
||||||
1092023, 1092024, 1092025, 1092026, 1092027,
|
|
||||||
1092028, 1092036, 1092037, 1092038,
|
|
||||||
1092060, 1092061, 1302002, 1302004, 1302005,
|
|
||||||
1302008, 1302009, 1302010, 1302011, 1302012,
|
|
||||||
1302015, 1302018, 1302019, 1302023, 1302037,
|
|
||||||
1302056, 1302059, 1302068, 1302079,
|
|
||||||
1312001, 1312003, 1312005,
|
|
||||||
1312006, 1312007, 1312008, 1312009, 1312010,
|
|
||||||
1312011, 1312015, 1312016, 1312030, 1312031,
|
|
||||||
1322014, 1322015,
|
|
||||||
1322016, 1322017, 1322018, 1322019, 1322020,
|
|
||||||
1322028, 1322029, 1322045, 1322052, 1322059,
|
|
||||||
1322062, 1402000,
|
|
||||||
1402002, 1402003, 1402004, 1402005, 1402006,
|
|
||||||
1402007, 1402008, 1402011, 1402012, 1402015,
|
|
||||||
1402016, 1402017, 1402018, 1402035, 1402036,
|
|
||||||
1412000, 1412002,
|
|
||||||
1412003, 1412004, 1412005, 1412006, 1412007,
|
|
||||||
1412008, 1412009, 1412010, 1412012, 1412021,
|
|
||||||
1412026, 1412032, 1412040,
|
|
||||||
1422001, 1422002, 1422003, 1422005,
|
|
||||||
1422007, 1422008, 1422009, 1422010, 1422012,
|
|
||||||
1422013, 1422027, 1422028, 1422030, 1422031,
|
|
||||||
1422038, 1422044, 1432002, 1432003,
|
|
||||||
1432004, 1432005, 1432006, 1432007, 1432010,
|
|
||||||
1432011, 1432030, 1432038, 1432045,
|
|
||||||
1432048, 1432056, 1442001, 1442002,
|
|
||||||
1442003, 1442005, 1442006, 1442007, 1442008,
|
|
||||||
1442009, 1442010, 1442019, 1442020, 1442044,
|
|
||||||
1442045, 1442060, 1442067,
|
|
||||||
//magicianEquips = {
|
|
||||||
1002075, 1050035, 1002151, 1051023, 1072089,
|
|
||||||
1072115, 1072076, 1040018, 1382017, 1072072,
|
|
||||||
//bowmanEquips = {
|
|
||||||
1040011, 1041061, 1040076, 1040003, 1072059,
|
|
||||||
1082017, 1002114, 1041066, 1060057, 1040007,
|
|
||||||
//thiefEquips = {
|
|
||||||
1072032, 1472011, 1082037, 1040059, 1040084,
|
|
||||||
1040043, 1072085, 1040031, 1332031, 1082075,
|
|
||||||
//pirateEquips = {
|
|
||||||
1482001, 1492002, 1052113, 1002616, 1072294,
|
|
||||||
1492004, 1482006, 1082192, 1082189, 1082195,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getUncommonItems() {
|
public int[] getUncommonItems() {
|
||||||
//All Scrolls
|
return new int [] {1082149, 1002391, 1002419, 1102041};
|
||||||
return new int [] {
|
|
||||||
2043000, 2043001, 2043002, 2043004, 2043005, 2043006, 2043007, 2043008, 2043009, 2043010,
|
|
||||||
2043015, 2043017, 2043019, 2044000, 2044001, 2044002, 2044004, 2044005, 2044010, 2044012,
|
|
||||||
2044014, 2043200, 2043201, 2043202, 2043204, 2043205, 2043210, 2043212, 2043214, 2044200,
|
|
||||||
2044201, 2044202, 2044204, 2044205, 2044210, 2044212, 2044214, 2044300, 2044301, 2044302,
|
|
||||||
2044304, 2044305, 2044310, 2044312, 2044314, 2044400, 2044401, 2044402, 2044404, 2044405,
|
|
||||||
2044410, 2044412, 2044414,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getRareItems() {
|
public int[] getRareItems() {
|
||||||
return new int [] {1402037, 1402049, 1072361, 1402048, 1402049, 1402050, 1402051};
|
return new int [] {};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,24 +2,57 @@ package server.gachapon;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alan (SharpAceX)
|
* @author Alan (SharpAceX) - gachapon source classes stub
|
||||||
|
* @author Ronan - parsed MapleSEA loots
|
||||||
|
*
|
||||||
|
* MapleSEA-like loots src: http://maplesecrets.blogspot.com/2011/06/gachapon-showa-towns-sauna-female-spa.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class ShowaSpaFemale extends GachaponItems {
|
public class ShowaSpaFemale extends GachaponItems {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getCommonItems() {
|
public int[] getCommonItems() {
|
||||||
return new int [] {};
|
return new int [] {
|
||||||
|
|
||||||
|
/* Scroll */
|
||||||
|
2048005, 2048002, 2043202, 2044602, 2043214, 2041307, 2041035, 2044104, 2044505, 2044305, 2043304, 2041309,
|
||||||
|
2044010, 2044803, 2044814, 2044904, 2044902, 2044901,
|
||||||
|
|
||||||
|
/* Useable drop */
|
||||||
|
2022016, 2000005, 2022025, 2022027,
|
||||||
|
|
||||||
|
/* Common equipment */
|
||||||
|
1402000, 1402013, 1002418, 1022047, 1082145, 1082147, 1082146, 1082178, 1082175,
|
||||||
|
|
||||||
|
/* Common setup */
|
||||||
|
3010073, 3010099,
|
||||||
|
|
||||||
|
/* Warrior equipment */
|
||||||
|
1422013, 1432030,
|
||||||
|
|
||||||
|
/* Magician equipment */
|
||||||
|
1372002, 1382003,
|
||||||
|
|
||||||
|
/* Bowman equipment */
|
||||||
|
1040023,
|
||||||
|
|
||||||
|
/* Thief equipment */
|
||||||
|
1332003, 1002209,
|
||||||
|
|
||||||
|
/* Pirate equipment */
|
||||||
|
1082198, 1082213, 1482007, 1492004, 1002646
|
||||||
|
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getUncommonItems() {
|
public int[] getUncommonItems() {
|
||||||
return new int [] {};
|
return new int [] {2040916, 1102042};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getRareItems() {
|
public int[] getRareItems() {
|
||||||
return new int [] {1022082, 1022060};
|
return new int [] {};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,24 +2,59 @@ package server.gachapon;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alan (SharpAceX)
|
* @author Alan (SharpAceX) - gachapon source classes stub
|
||||||
|
* @author Ronan - parsed MapleSEA loots
|
||||||
|
*
|
||||||
|
* MapleSEA-like loots src: http://maplesecrets.blogspot.com/2011/05/gachapon-showa-towns-sauna.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class ShowaSpaMale extends GachaponItems {
|
public class ShowaSpaMale extends GachaponItems {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getCommonItems() {
|
public int[] getCommonItems() {
|
||||||
return new int [] {};
|
return new int [] {
|
||||||
|
|
||||||
|
/* Scroll */
|
||||||
|
2048005, 2048002, 2043202, 2044602, 2043214, 2041307, 2041035, 2044104, 2044505, 2044305, 2043304, 2044902,
|
||||||
|
2044901, 2044811, 2044903, 2044804,
|
||||||
|
|
||||||
|
/* Useable drop */
|
||||||
|
2022016, 2000005, 2022025, 2022027,
|
||||||
|
|
||||||
|
/* Common equipment */
|
||||||
|
1332020, 1312004, 1332032, 1322023, 1322026, 1322022, 1322012, 1302014, 1302049, 1302017, 1332007, 1432009,
|
||||||
|
1432016, 1432017, 1432009, 1402013, 1402044, 1442014, 1442017, 1442016, 1442025, 1002418, 1082178, 1082179,
|
||||||
|
1082148, 1032027, 1032032, 1102028, 1102086,
|
||||||
|
|
||||||
|
/* Common setup */
|
||||||
|
3010073, 3010111,
|
||||||
|
|
||||||
|
/* Warrior equipment */
|
||||||
|
1412005, 1402048, 1402049, 1322011, 1302003, 1302004, 1302008,
|
||||||
|
|
||||||
|
/* Magician equipment */
|
||||||
|
1372000, 1372009, 1372001, 1372011, 1382006, 1382014,
|
||||||
|
|
||||||
|
/* Bowman equipment */
|
||||||
|
1452018, 1452006, 1452008, 1452005, 1462002, 1462007, 1462003, 1002169,
|
||||||
|
|
||||||
|
/* Thief equipment */
|
||||||
|
1472023, 1332012, 1332017, 1332022, 1332006, 1332029, 1040097,
|
||||||
|
|
||||||
|
/* Pirate equipment */
|
||||||
|
1052107, 1082204, 1072318, 1002637, 1482009, 1492007
|
||||||
|
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getUncommonItems() {
|
public int[] getUncommonItems() {
|
||||||
return new int [] {};
|
return new int [] {2040916, 1102042};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getRareItems() {
|
public int[] getRareItems() {
|
||||||
return new int [] {1022082, 1022060};
|
return new int [] {};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,10 @@ package server.gachapon;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alan (SharpAceX)
|
* @author Alan (SharpAceX) - gachapon source classes stub & pirate equipment
|
||||||
|
* @author Ronan - parsed MapleSEA loots
|
||||||
|
*
|
||||||
|
* MapleSEA-like loots thanks to AyumiLove, src: https://ayumilovemaple.wordpress.com/maplestory-gachapon-guide/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class Sleepywood extends GachaponItems {
|
public class Sleepywood extends GachaponItems {
|
||||||
@@ -10,97 +13,47 @@ public class Sleepywood extends GachaponItems {
|
|||||||
@Override
|
@Override
|
||||||
public int[] getCommonItems() {
|
public int[] getCommonItems() {
|
||||||
return new int [] {
|
return new int [] {
|
||||||
//warriorEquips = {
|
|
||||||
1002022, 1002024, 1002028, 1002029, 1002030,
|
/* Scroll */
|
||||||
1002045, 1002046, 1002084, 1002085, 1002086,
|
2048003, 2048000, 2040601, 2044501, 2041019, 2041016, 2041022, 2041010, 2041013, 2043301, 2040301, 2040801, 2040001,
|
||||||
1002091, 1002094, 1002095, 1002100, 1002101,
|
2040004, 2043101, 2043201, 2043001, 2040504, 2040501, 2048004, 2048001, 2044401, 2040901, 2040701, 2040704, 2040707,
|
||||||
1040087, 1040088, 1040089, 1040090, 1040091,
|
2044301, 2043801, 2044101, 2044201, 2044001, 2040602, 2044502, 2041020, 2041017, 2041023, 2041014, 2041005, 2044702,
|
||||||
1040092, 1040093, 1040102, 1040103, 1040104,
|
2044602, 2043302, 2040302, 2040802, 2040005, 2043202, 2043002, 2040505, 2040502, 2048005, 2048002, 2044402, 2040902,
|
||||||
1041087, 1041088, 1041089, 1041091, 1041092,
|
2040702, 2040705, 2040708, 2044302, 2043802, 2044202, 2044002, 2044801, 2044903, 2044814,
|
||||||
1041093, 1041097, 1041098, 1041099, 1060076,
|
|
||||||
1060077, 1060078, 1060079, 1060080, 1060081,
|
/* Useable drop */
|
||||||
1060082, 1060090, 1060091, 1060092, 1061086,
|
2012000, 2012003, 2020007, 2000004, 2012001, 2020008, 2070006, 2020012, 2000005, 2030007, 2012002, 2002001, 2070005,
|
||||||
1061087, 1061088, 1061090, 1061091, 1061092,
|
|
||||||
1061096, 1061097, 1061098, 1072132, 1072133,
|
/* Common equipment */
|
||||||
1072134, 1072135, 1072147, 1072148, 1072149,
|
1032003, 1432009, 1102014, 1102018, 1002392, 1322026, 1032022, 1312012, 1332020, 1092030, 1032016, 1032015, 1032014,
|
||||||
1072154, 1072155, 1072156, 1082009, 1082010,
|
1322024, 1032013, 1322022, 1102016, 1032012, 1032023, 1402014, 1032000, 1102017,
|
||||||
1082011, 1082059, 1082060, 1082061, 1082103,
|
|
||||||
1082104, 1082105, 1082218, 1092004, 1092009,
|
/* Warrior equipment */
|
||||||
1092010, 1092011, 1092015, 1092016, 1092017,
|
1402017, 1051010, 1432011, 1442006, 1322002, 1422004, 1432010, 1051011, 1060018, 1432000, 1422003, 1412003, 1422000,
|
||||||
1302010, 1302011, 1302012, 1302015, 1302019,
|
|
||||||
1302037, 1302079, 1312008, 1312009,
|
/* Magician equipment */
|
||||||
1312010, 1322017, 1322018, 1322019, 1322059,
|
1002034, 1002142, 1382010, 1002013, 1382008, 1382011, 1050047, 1002065,
|
||||||
1402003, 1402011, 1402012, 1402017, 1412003,
|
|
||||||
1412007, 1412008, 1412032, 1422005, 1422009,
|
/* Bowman equipment */
|
||||||
1422010, 1432004, 1432006, 1432007, 1432045,
|
1452003, 1002165, 1040068, 1462013, 1462011, 1462012, 1061050, 1462010, 1002161,
|
||||||
1442005, 1442008, 1442010, 1442060,
|
|
||||||
//magicianEquips = {
|
/* Thief equipment */
|
||||||
1002215, 1002216, 1002217, 1002218, 1002242,
|
1332022, 1002175, 1040042, 1472004, 1040057, 1332031, 1332023, 1332010, 1002171, 1060046,
|
||||||
1002243, 1002244, 1002245, 1002246, 1002252,
|
|
||||||
1002253, 1002254, 1050045, 1050046, 1050047,
|
/* Pirate equipment */
|
||||||
1050048, 1050049, 1050053, 1050054, 1050055,
|
1002631, 1002634, 1002637, 1052116, 1052119, 1052122, 1072303, 1072306, 1072309, 1082198, 1082201, 1082204, 1482007,
|
||||||
1050056, 1050067, 1050068, 1050069, 1050070,
|
1482008, 1482009
|
||||||
1051030, 1051031, 1051032, 1051033, 1051034,
|
|
||||||
1051044, 1051045, 1051046, 1051047, 1051052,
|
|
||||||
1051053, 1051054, 1051055, 1072136, 1072137,
|
|
||||||
1072138, 1072139, 1072140, 1072141, 1072142,
|
|
||||||
1072143, 1072157, 1072158, 1072159, 1072160,
|
|
||||||
1082080, 1082081, 1082082, 1082086, 1082087,
|
|
||||||
1082088, 1082098, 1082099, 1082100, 1372007,
|
|
||||||
1372008, 1372011, 1372014, 1372015, 1372035,
|
|
||||||
1372036, 1372037, 1372038, 1382001, 1382006,
|
|
||||||
1382007, 1382011, 1382014, 1382041,
|
|
||||||
//bowmanEquips = {
|
|
||||||
1002211, 1002212, 1002213, 1002214, 1002267,
|
|
||||||
1002268, 1002269, 1002270, 1002286, 1002287,
|
|
||||||
1002288, 1002289, 1002749, 1050051, 1050052,
|
|
||||||
1050058, 1050059, 1050060, 1050061, 1050062,
|
|
||||||
1050063, 1050064, 1051037, 1051038, 1051039,
|
|
||||||
1051041, 1051042, 1051043, 1051062, 1051063,
|
|
||||||
1051064, 1051065, 1072122, 1072123, 1072124,
|
|
||||||
1072125, 1072144, 1072145, 1072146, 1072164,
|
|
||||||
1072165, 1072166, 1072167, 1072345, 1082083,
|
|
||||||
1082084, 1082085, 1082089, 1082090, 1082091,
|
|
||||||
1082106, 1082107, 1082108, 1452004, 1452008,
|
|
||||||
1452009, 1452010, 1452011, 1452018, 1452023,
|
|
||||||
1452052, 1462006, 1462007, 1462008, 1462009,
|
|
||||||
1462046,
|
|
||||||
//thiefEquips = {
|
|
||||||
1002207, 1002208, 1002209, 1002210, 1002247,
|
|
||||||
1002248, 1002249, 1002281, 1002282, 1002283,
|
|
||||||
1002284, 1002285, 1002656, 1002750, 1040094,
|
|
||||||
1040095, 1040096, 1040097, 1040098, 1040099,
|
|
||||||
1040100, 1040105, 1040106, 1040107, 1041077,
|
|
||||||
1041078, 1041079, 1041080, 1041094, 1041095,
|
|
||||||
1041096, 1041100, 1041101, 1041102, 1041103,
|
|
||||||
1060083, 1060084, 1060085, 1060086, 1060087,
|
|
||||||
1060088, 1060089, 1060093, 1060094, 1060095,
|
|
||||||
1061076, 1061077, 1061078, 1061079, 1061093,
|
|
||||||
1061094, 1061095, 1061099, 1061100, 1061101,
|
|
||||||
1061102, 1072128, 1072129, 1072130, 1072131,
|
|
||||||
1072150, 1072151, 1072152, 1072161, 1072162,
|
|
||||||
1072163, 1072346, 1082065, 1082066, 1082067,
|
|
||||||
1082092, 1082093, 1082094, 1082095, 1082096,
|
|
||||||
1082097, 1332003, 1332015, 1332018, 1332024,
|
|
||||||
1332054, 1332064, 1472018, 1472019, 1472020,
|
|
||||||
1472021, 1472022, 1472023, 1472024, 1472025,
|
|
||||||
1472026, 1472027, 1472028, 1472029, 1472054,
|
|
||||||
1472062,
|
|
||||||
//pirateEquips = {
|
|
||||||
1002631, 1002634, 1002637, 1052116, 1052119,
|
|
||||||
1052122, 1072303, 1072306, 1072309, 1082198,
|
|
||||||
1082201, 1082204, 1482007, 1482008, 1482009,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getUncommonItems() {
|
public int[] getUncommonItems() {
|
||||||
return new int [] {};
|
return new int [] {2040804, 2040817, 2040805, 2340000, 1082149, 1442018};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getRareItems() {
|
public int[] getRareItems() {
|
||||||
return new int [] {1302068, 2070007, 1022082, 1022058};
|
return new int [] {};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
*/
|
*/
|
||||||
package server.life;
|
package server.life;
|
||||||
|
|
||||||
|
import java.awt.Point;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -216,6 +217,14 @@ public class MapleLifeFactory {
|
|||||||
stats.setBanishInfo(new BanishInfo(MapleDataTool.getString("banMsg", banishData), MapleDataTool.getInt("banMap/0/field", banishData, -1), MapleDataTool.getString("banMap/0/portal", banishData, "sp")));
|
stats.setBanishInfo(new BanishInfo(MapleDataTool.getString("banMsg", banishData), MapleDataTool.getInt("banMap/0/field", banishData, -1), MapleDataTool.getString("banMap/0/portal", banishData, "sp")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int noFlip = MapleDataTool.getInt("noFlip", monsterInfoData, 0);
|
||||||
|
if (noFlip > 0) {
|
||||||
|
Point origin = MapleDataTool.getPoint("stand/0/origin", monsterData, null);
|
||||||
|
if (origin != null) {
|
||||||
|
stats.setFixedStance(origin.getX() < 1 ? 5 : 4); // fixed left/right
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return new Pair<>(stats, attackInfos);
|
return new Pair<>(stats, attackInfos);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,6 +279,10 @@ public class MapleLifeFactory {
|
|||||||
return new MapleNPC(nid, new MapleNPCStats(MapleDataTool.getString(nid + "/name", npcStringData, "MISSINGNO")));
|
return new MapleNPC(nid, new MapleNPCStats(MapleDataTool.getString(nid + "/name", npcStringData, "MISSINGNO")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getNPCDefaultTalk(int nid) {
|
||||||
|
return MapleDataTool.getString(nid + "/d0", npcStringData, "(...)");
|
||||||
|
}
|
||||||
|
|
||||||
public static class BanishInfo {
|
public static class BanishInfo {
|
||||||
|
|
||||||
private int map;
|
private int map;
|
||||||
|
|||||||
+160
-141
@@ -56,7 +56,6 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
import net.server.audit.locks.MonitoredReentrantLock;
|
import net.server.audit.locks.MonitoredReentrantLock;
|
||||||
import net.server.channel.Channel;
|
import net.server.channel.Channel;
|
||||||
import net.server.world.World;
|
|
||||||
import net.server.world.MapleParty;
|
import net.server.world.MapleParty;
|
||||||
import net.server.world.MaplePartyCharacter;
|
import net.server.world.MaplePartyCharacter;
|
||||||
import scripting.event.EventInstanceManager;
|
import scripting.event.EventInstanceManager;
|
||||||
@@ -64,6 +63,7 @@ import server.TimerManager;
|
|||||||
import server.life.MapleLifeFactory.BanishInfo;
|
import server.life.MapleLifeFactory.BanishInfo;
|
||||||
import server.maps.MapleMap;
|
import server.maps.MapleMap;
|
||||||
import server.maps.MapleMapObjectType;
|
import server.maps.MapleMapObjectType;
|
||||||
|
import tools.IntervalBuilder;
|
||||||
import tools.MaplePacketCreator;
|
import tools.MaplePacketCreator;
|
||||||
import tools.Pair;
|
import tools.Pair;
|
||||||
import tools.Randomizer;
|
import tools.Randomizer;
|
||||||
@@ -72,6 +72,7 @@ import net.server.audit.locks.MonitoredLockType;
|
|||||||
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
||||||
import net.server.coordinator.MapleMonsterAggroCoordinator;
|
import net.server.coordinator.MapleMonsterAggroCoordinator;
|
||||||
import server.MapleStatEffect;
|
import server.MapleStatEffect;
|
||||||
|
import server.loot.MapleLootManager;
|
||||||
import server.maps.MapleSummon;
|
import server.maps.MapleSummon;
|
||||||
|
|
||||||
public class MapleMonster extends AbstractLoadedMapleLife {
|
public class MapleMonster extends AbstractLoadedMapleLife {
|
||||||
@@ -94,12 +95,11 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
|||||||
private Map<Pair<Integer, Integer>, Integer> skillsUsed = new HashMap<>();
|
private Map<Pair<Integer, Integer>, Integer> skillsUsed = new HashMap<>();
|
||||||
private Set<Integer> usedAttacks = new HashSet<>();
|
private Set<Integer> usedAttacks = new HashSet<>();
|
||||||
private Set<Integer> calledMobOids = null;
|
private Set<Integer> calledMobOids = null;
|
||||||
private int calledMobCount = 0;
|
|
||||||
private WeakReference<MapleMonster> callerMob = new WeakReference<>(null);
|
private WeakReference<MapleMonster> callerMob = new WeakReference<>(null);
|
||||||
private List<Integer> stolenItems = new ArrayList<>();
|
private List<Integer> stolenItems = new ArrayList<>();
|
||||||
private int team;
|
private int team;
|
||||||
private int parentMobOid = 0;
|
private int parentMobOid = 0;
|
||||||
private final HashMap<Integer, AtomicInteger> takenDamage = new HashMap<>();
|
private final HashMap<Integer, AtomicLong> takenDamage = new HashMap<>();
|
||||||
private Runnable removeAfterAction = null;
|
private Runnable removeAfterAction = null;
|
||||||
private boolean availablePuppetUpdate = true;
|
private boolean availablePuppetUpdate = true;
|
||||||
|
|
||||||
@@ -160,13 +160,17 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
|||||||
this.parentMobOid = parentMobId;
|
this.parentMobOid = parentMobId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int countAvailableMobSummons(int limit, int skillLimit) { // limit prop for summons has another conotation, found thanks to MedicOP
|
public int countAvailableMobSummons(int summonsSize, int skillLimit) { // limit prop for summons has another conotation, found thanks to MedicOP
|
||||||
|
int summonsCount;
|
||||||
|
|
||||||
Set<Integer> calledOids = this.calledMobOids;
|
Set<Integer> calledOids = this.calledMobOids;
|
||||||
if(calledOids != null) {
|
if(calledOids != null) {
|
||||||
limit -= calledOids.size();
|
summonsCount = calledOids.size();
|
||||||
|
} else {
|
||||||
|
summonsCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Math.min(limit, skillLimit - this.calledMobCount);
|
return Math.min(summonsSize, skillLimit - summonsCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addSummonedMob(MapleMonster mob) {
|
public void addSummonedMob(MapleMonster mob) {
|
||||||
@@ -178,7 +182,6 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
|||||||
|
|
||||||
calledOids.add(mob.getObjectId());
|
calledOids.add(mob.getObjectId());
|
||||||
mob.setSummonerMob(this);
|
mob.setSummonerMob(this);
|
||||||
this.calledMobCount += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeSummonedMob(int mobOid) {
|
private void removeSummonedMob(int mobOid) {
|
||||||
@@ -442,7 +445,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
|||||||
dispatchMonsterDamaged(from, trueDamage);
|
dispatchMonsterDamaged(from, trueDamage);
|
||||||
|
|
||||||
if (!takenDamage.containsKey(from.getId())) {
|
if (!takenDamage.containsKey(from.getId())) {
|
||||||
takenDamage.put(from.getId(), new AtomicInteger(trueDamage));
|
takenDamage.put(from.getId(), new AtomicLong(trueDamage));
|
||||||
} else {
|
} else {
|
||||||
takenDamage.get(from.getId()).addAndGet(trueDamage);
|
takenDamage.get(from.getId()).addAndGet(trueDamage);
|
||||||
}
|
}
|
||||||
@@ -475,98 +478,85 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
|||||||
return takenDamage.containsKey(chr.getId());
|
return takenDamage.containsKey(chr.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void distributeExperienceToParty(int pid, float exp, int mostDamageCid, int minThresholdLevel, int killerLevel, Set<MapleCharacter> underleveled, Map<MapleCharacter, Float> partyExpReward, Set<MapleCharacter> participants) {
|
private static boolean isWhiteExpGain(MapleCharacter chr, Map<Integer, Float> personalRatio, double sdevRatio) {
|
||||||
MapleCharacter pchar = getMap().getAnyCharacterFromParty(pid); // thanks G h o s t, Alfred, Vcoc, BHB for poiting out a bug in detecting party members after membership transactions in a party took place
|
Float pr = personalRatio.get(chr.getId());
|
||||||
|
if (pr == null) {
|
||||||
List<MapleCharacter> members;
|
return false;
|
||||||
if (pchar != null) {
|
|
||||||
members = pchar.getPartyMembersOnSameMap();
|
|
||||||
} else {
|
|
||||||
members = new LinkedList<>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<MapleCharacter> expSharers = new LinkedList<>();
|
return pr >= sdevRatio;
|
||||||
int expParticipantsMaxLevel = 1;
|
|
||||||
boolean hasMostDamageCid = false;
|
|
||||||
for (MapleCharacter mc : members) {
|
|
||||||
if (mc.getId() == mostDamageCid) {
|
|
||||||
hasMostDamageCid = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mc.getLevel() >= minThresholdLevel) { //NO EXP WILL BE GIVEN for those who are underleveled!
|
private static double calcExperienceStandDevThreshold(List<Float> entryExpRatio, int totalEntries) {
|
||||||
if (Math.abs(killerLevel - mc.getLevel()) < ServerConstants.MIN_RANGELEVEL_TO_EXP_LEECH) {
|
|
||||||
// thanks Thora for pointing out leech level limitation
|
|
||||||
|
|
||||||
if (expParticipantsMaxLevel < mc.getLevel() && participants.contains(mc)) {
|
|
||||||
expParticipantsMaxLevel = mc.getLevel();
|
|
||||||
}
|
|
||||||
expSharers.add(mc);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
underleveled.add(mc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int numExpSharers = expSharers.size();
|
|
||||||
|
|
||||||
// PARTY BONUS: 2p -> +5% , 3p -> +6.25% , 4p -> +7.5% , 5p -> +8.75% , 6p -> +10%
|
|
||||||
// MOST DAMAGE BONUS: 1.5x bonus
|
|
||||||
|
|
||||||
// thanks Crypter for reporting an insufficiency on party exp bonuses
|
|
||||||
final float partyModifier = numExpSharers <= 1 ? 0.0f : 0.05f + (0.0125f * (numExpSharers - 1));
|
|
||||||
final float mostDamageModifier = hasMostDamageCid ? 1.5f : 1.0f;
|
|
||||||
final float partyExp = exp * partyModifier * mostDamageModifier;
|
|
||||||
|
|
||||||
for (MapleCharacter mc : expSharers) {
|
|
||||||
float levelPenaltyModifier = (float) Math.min(1.0, Math.sqrt(((float) mc.getLevel()) / expParticipantsMaxLevel));
|
|
||||||
partyExpReward.put(mc, partyExp * levelPenaltyModifier);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int calcThresholdLevel(boolean isPqMob) {
|
|
||||||
if(!ServerConstants.USE_ENFORCE_MOB_LEVEL_RANGE) {
|
|
||||||
return 0;
|
|
||||||
} else if (isPqMob) {
|
|
||||||
double thresholdLevel = getLevel();
|
|
||||||
thresholdLevel /= 32.55916838;
|
|
||||||
thresholdLevel = Math.log(thresholdLevel) / 0.02058204546;
|
|
||||||
|
|
||||||
return (int) Math.ceil(thresholdLevel);
|
|
||||||
} else {
|
|
||||||
return getLevel() - (!isBoss() ? ServerConstants.MIN_UNDERLEVEL_TO_EXP_GAIN : 2 * ServerConstants.MIN_UNDERLEVEL_TO_EXP_GAIN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double calcExperienceStandDevThreshold(Map<MapleCharacter, Float> personalExpReward, float exp2) {
|
|
||||||
float avgExpReward = 0.0f;
|
float avgExpReward = 0.0f;
|
||||||
for (Float exp : personalExpReward.values()) {
|
for (Float exp : entryExpRatio) {
|
||||||
avgExpReward += exp;
|
avgExpReward += exp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// thanks Simon for finding an issue with solo party player gaining yellow EXP when soloing mobs
|
// thanks Simon for finding an issue with solo party player gaining yellow EXP when soloing mobs
|
||||||
float realAvgExpReward = avgExpReward;
|
avgExpReward /= totalEntries;
|
||||||
avgExpReward -= exp2; // clear out the 20% raw exp from last hitting
|
|
||||||
avgExpReward /= personalExpReward.size();
|
|
||||||
|
|
||||||
float varExpReward = 0.0f;
|
float varExpReward = 0.0f;
|
||||||
for (Float exp : personalExpReward.values()) {
|
for (Float exp : entryExpRatio) {
|
||||||
varExpReward += Math.pow(exp - realAvgExpReward, 2);
|
varExpReward += Math.pow(exp - avgExpReward, 2);
|
||||||
}
|
}
|
||||||
varExpReward /= personalExpReward.size();
|
varExpReward /= entryExpRatio.size();
|
||||||
|
|
||||||
return avgExpReward + Math.sqrt(varExpReward);
|
return avgExpReward + Math.sqrt(varExpReward);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void propagateExperienceGains(Map<MapleCharacter, Float> personalExpReward, Map<MapleCharacter, Float> partyExpReward, float exp2) {
|
private void distributePlayerExperience(MapleCharacter chr, float exp, float partyBonusMod, int totalPartyLevel, boolean highestPartyDamager, boolean whiteExpGain) {
|
||||||
Set<MapleCharacter> expRewardPlayers = new HashSet<>(personalExpReward.keySet());
|
float playerExp = (ServerConstants.EXP_SPLIT_COMMON_MOD * chr.getLevel()) / totalPartyLevel;
|
||||||
expRewardPlayers.addAll(partyExpReward.keySet());
|
if (highestPartyDamager) playerExp += ServerConstants.EXP_SPLIT_MVP_MOD;
|
||||||
|
|
||||||
double sdevExp = calcExperienceStandDevThreshold(personalExpReward, exp2);
|
playerExp *= exp;
|
||||||
for (MapleCharacter chr : expRewardPlayers) {
|
float bonusExp = partyBonusMod * playerExp;
|
||||||
Float personalExp = personalExpReward.get(chr);
|
|
||||||
Float partyExp = partyExpReward.get(chr);
|
|
||||||
|
|
||||||
this.giveExpToCharacter(chr, personalExp, partyExp, personalExp != null && personalExp >= sdevExp);
|
this.giveExpToCharacter(chr, playerExp, bonusExp, whiteExpGain);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void distributePartyExperience(Map<MapleCharacter, Long> partyParticipation, float expPerDmg, Set<MapleCharacter> underleveled, Map<Integer, Float> personalRatio, double sdevRatio) {
|
||||||
|
IntervalBuilder leechInterval = new IntervalBuilder();
|
||||||
|
leechInterval.addInterval(this.getLevel() - ServerConstants.EXP_SPLIT_LEVEL_INTERVAL, this.getLevel() + ServerConstants.EXP_SPLIT_LEVEL_INTERVAL);
|
||||||
|
|
||||||
|
long maxDamage = 0, partyDamage = 0;
|
||||||
|
MapleCharacter participationMvp = null;
|
||||||
|
for (Entry<MapleCharacter, Long> e : partyParticipation.entrySet()) {
|
||||||
|
long entryDamage = e.getValue();
|
||||||
|
partyDamage += entryDamage;
|
||||||
|
|
||||||
|
if (maxDamage < entryDamage) {
|
||||||
|
maxDamage = entryDamage;
|
||||||
|
participationMvp = e.getKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
// thanks Thora for pointing out leech level limitation
|
||||||
|
int chrLevel = e.getKey().getLevel();
|
||||||
|
leechInterval.addInterval(chrLevel - ServerConstants.EXP_SPLIT_LEECH_INTERVAL, chrLevel + ServerConstants.EXP_SPLIT_LEECH_INTERVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<MapleCharacter> expMembers = new LinkedList<>();
|
||||||
|
int totalPartyLevel = 0;
|
||||||
|
|
||||||
|
// thanks G h o s t, Alfred, Vcoc, BHB for poiting out a bug in detecting party members after membership transactions in a party took place
|
||||||
|
for (MapleCharacter member : partyParticipation.keySet().iterator().next().getPartyMembersOnSameMap()) {
|
||||||
|
if (!leechInterval.inInterval(member.getLevel())) {
|
||||||
|
underleveled.add(member);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
totalPartyLevel += member.getLevel();
|
||||||
|
expMembers.add(member);
|
||||||
|
}
|
||||||
|
|
||||||
|
int membersSize = expMembers.size();
|
||||||
|
float participationExp = partyDamage * expPerDmg;
|
||||||
|
|
||||||
|
// thanks Crypter for reporting an insufficiency on party exp bonuses
|
||||||
|
float partyBonusMod = (membersSize > 1) ? 0.05f * membersSize : 0.0f;
|
||||||
|
|
||||||
|
for (MapleCharacter mc : expMembers) {
|
||||||
|
distributePlayerExperience(mc, participationExp, partyBonusMod, totalPartyLevel, mc == participationMvp, isWhiteExpGain(mc, personalRatio, sdevRatio));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -575,84 +565,89 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<MapleCharacter, Float> personalExpReward = new HashMap<>();
|
Map<MapleParty, Map<MapleCharacter, Long>> partyExpDist = new HashMap<>();
|
||||||
Map<MapleCharacter, Float> partyExpReward = new HashMap<>();
|
Map<MapleCharacter, Long> soloExpDist = new HashMap<>();
|
||||||
|
|
||||||
EventInstanceManager eim = getMap().getEventInstance();
|
Map<Integer, MapleCharacter> mapPlayers = map.getMapAllPlayers();
|
||||||
int minThresholdLevel = calcThresholdLevel(eim != null), killerLevel = Integer.MAX_VALUE;
|
|
||||||
int exp = getExp();
|
|
||||||
long totalHealth = maxHpPlusHeal.get();
|
|
||||||
Map<Integer, Float> expDist = new HashMap<>();
|
|
||||||
Map<Integer, Float> partyExp = new HashMap<>();
|
|
||||||
|
|
||||||
float exp8perHp = (0.8f * exp) / totalHealth; // 80% of pool is split amongst all the damagers
|
int totalEntries = 0; // counts "participant parties", players who no longer are available in the map is an "independent party"
|
||||||
float exp2 = (0.2f * exp); // 20% of pool goes to the killer or his/her party
|
for (Entry<Integer, AtomicLong> e : takenDamage.entrySet()) {
|
||||||
|
MapleCharacter chr = mapPlayers.get(e.getKey());
|
||||||
|
if (chr != null) {
|
||||||
|
long damage = e.getValue().longValue();
|
||||||
|
|
||||||
for (Entry<Integer, AtomicInteger> damage : takenDamage.entrySet()) {
|
MapleParty p = chr.getParty();
|
||||||
expDist.put(damage.getKey(), exp8perHp * damage.getValue().get());
|
if (p != null) {
|
||||||
|
Map<MapleCharacter, Long> partyParticipation = partyExpDist.get(p);
|
||||||
|
if (partyParticipation == null) {
|
||||||
|
partyParticipation = new HashMap<>(6);
|
||||||
|
partyExpDist.put(p, partyParticipation);
|
||||||
|
|
||||||
|
totalEntries += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<MapleCharacter> underleveled = new HashSet<>();
|
partyParticipation.put(chr, damage);
|
||||||
Collection<MapleCharacter> mapChrs = map.getCharacters();
|
} else {
|
||||||
for (MapleCharacter mc : mapChrs) {
|
soloExpDist.put(chr, damage);
|
||||||
Float mcExp = expDist.remove(mc.getId());
|
totalEntries += 1;
|
||||||
if (mcExp != null) {
|
|
||||||
float xp = mcExp;
|
|
||||||
boolean isKiller = (mc.getId() == killerId);
|
|
||||||
if (isKiller) {
|
|
||||||
if (eim != null) {
|
|
||||||
eim.monsterKilled(mc, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
killerLevel = mc.getLevel();
|
|
||||||
xp += exp2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mc.getLevel() >= minThresholdLevel) {
|
|
||||||
//NO EXP WILL BE GIVEN for those who are underleveled!
|
|
||||||
personalExpReward.put(mc, xp);
|
|
||||||
|
|
||||||
MapleParty p = mc.getParty();
|
|
||||||
if (p != null) { // for party bonus exp
|
|
||||||
int pID = p.getId();
|
|
||||||
float pXP = xp + (partyExp.containsKey(pID) ? partyExp.get(pID) : 0);
|
|
||||||
partyExp.put(pID, pXP);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
underleveled.add(mc);
|
totalEntries += 1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!expDist.isEmpty()) { // locate on world server the partyid of the missing characters
|
long totalDamage = maxHpPlusHeal.get();
|
||||||
World wserv = map.getWorldServer();
|
int mobExp = getExp();
|
||||||
|
float expPerDmg = ((float) mobExp) / totalDamage;
|
||||||
|
|
||||||
for (Entry<Integer, Float> ed : expDist.entrySet()) {
|
Map<Integer, Float> personalRatio = new HashMap<>();
|
||||||
boolean isKiller = (ed.getKey() == killerId);
|
List<Float> entryExpRatio = new LinkedList<>();
|
||||||
float xp = ed.getValue();
|
for (Entry<MapleCharacter, Long> e : soloExpDist.entrySet()) {
|
||||||
if (isKiller) {
|
float ratio = ((float) e.getValue()) / totalDamage;
|
||||||
xp += exp2;
|
|
||||||
|
personalRatio.put(e.getKey().getId(), ratio);
|
||||||
|
entryExpRatio.add(ratio);
|
||||||
}
|
}
|
||||||
|
|
||||||
Integer pID = wserv.getCharacterPartyid(ed.getKey());
|
for (Map<MapleCharacter, Long> m : partyExpDist.values()) {
|
||||||
if (pID != null) {
|
float ratio = 0.0f;
|
||||||
float pXP = xp + (partyExp.containsKey(pID) ? partyExp.get(pID) : 0);
|
for (Entry<MapleCharacter, Long> e : m.entrySet()) {
|
||||||
partyExp.put(pID, pXP);
|
float chrRatio = ((float) e.getValue()) / totalDamage;
|
||||||
}
|
|
||||||
}
|
personalRatio.put(e.getKey().getId(), chrRatio);
|
||||||
|
ratio += chrRatio;
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<MapleCharacter> participants = personalExpReward.keySet();
|
entryExpRatio.add(ratio);
|
||||||
int mostDamageCid = this.getHighestDamagerId();
|
}
|
||||||
for (Entry<Integer, Float> party : partyExp.entrySet()) {
|
|
||||||
distributeExperienceToParty(party.getKey(), party.getValue(), mostDamageCid, minThresholdLevel, killerLevel, underleveled, partyExpReward, participants);
|
double sdevRatio = calcExperienceStandDevThreshold(entryExpRatio, totalEntries);
|
||||||
|
|
||||||
|
// GMS-like player and party split calculations found thanks to Russt, KaidaTan, Dusk, AyumiLove. Src: https://ayumilovemaple.wordpress.com/maplestory_calculator_formula/
|
||||||
|
Set<MapleCharacter> underleveled = new HashSet<>();
|
||||||
|
for (Entry<MapleCharacter, Long> chrParticipation : soloExpDist.entrySet()) {
|
||||||
|
float exp = chrParticipation.getValue() * expPerDmg;
|
||||||
|
MapleCharacter chr = chrParticipation.getKey();
|
||||||
|
|
||||||
|
distributePlayerExperience(chr, exp, 0.0f, chr.getLevel(), true, isWhiteExpGain(chr, personalRatio, sdevRatio));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Map<MapleCharacter, Long> partyParticipation : partyExpDist.values()) {
|
||||||
|
distributePartyExperience(partyParticipation, expPerDmg, underleveled, personalRatio, sdevRatio);
|
||||||
|
}
|
||||||
|
|
||||||
|
EventInstanceManager eim = getMap().getEventInstance();
|
||||||
|
if (eim != null) {
|
||||||
|
MapleCharacter chr = mapPlayers.get(killerId);
|
||||||
|
if (chr != null) {
|
||||||
|
eim.monsterKilled(chr, this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(MapleCharacter mc : underleveled) {
|
for(MapleCharacter mc : underleveled) {
|
||||||
mc.showUnderleveledInfo(this);
|
mc.showUnderleveledInfo(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
propagateExperienceGains(personalExpReward, partyExpReward, killerLevel != Integer.MAX_VALUE ? exp2 : 0.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private float getStatusExpMultiplier(MapleCharacter attacker) {
|
private float getStatusExpMultiplier(MapleCharacter attacker) {
|
||||||
@@ -719,6 +714,20 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<MonsterDropEntry> retrieveRelevantDrops() {
|
||||||
|
Map<Integer, MapleCharacter> pchars = map.getMapAllPlayers();
|
||||||
|
|
||||||
|
List<MapleCharacter> lootChars = new LinkedList<>();
|
||||||
|
for (Integer cid : takenDamage.keySet()) {
|
||||||
|
MapleCharacter chr = pchars.get(cid);
|
||||||
|
if (chr != null && chr.isLoggedinWorld()) {
|
||||||
|
lootChars.add(chr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MapleLootManager.retrieveRelevantDrops(this.getId(), lootChars);
|
||||||
|
}
|
||||||
|
|
||||||
public MapleCharacter killBy(final MapleCharacter killer) {
|
public MapleCharacter killBy(final MapleCharacter killer) {
|
||||||
distributeExperience(killer != null ? killer.getId() : 0);
|
distributeExperience(killer != null ? killer.getId() : 0);
|
||||||
|
|
||||||
@@ -904,9 +913,9 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
|||||||
|
|
||||||
public int getHighestDamagerId() {
|
public int getHighestDamagerId() {
|
||||||
int curId = 0;
|
int curId = 0;
|
||||||
int curDmg = 0;
|
long curDmg = 0;
|
||||||
|
|
||||||
for (Entry<Integer, AtomicInteger> damage : takenDamage.entrySet()) {
|
for (Entry<Integer, AtomicLong> damage : takenDamage.entrySet()) {
|
||||||
curId = damage.getValue().get() >= curDmg ? damage.getKey() : curId;
|
curId = damage.getValue().get() >= curDmg ? damage.getKey() : curId;
|
||||||
curDmg = damage.getKey() == curId ? damage.getValue().get() : curDmg;
|
curDmg = damage.getKey() == curId ? damage.getValue().get() : curDmg;
|
||||||
}
|
}
|
||||||
@@ -1012,6 +1021,16 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
|||||||
return stats.isMobile();
|
return stats.isMobile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFacingLeft() {
|
||||||
|
int fixedStance = stats.getFixedStance(); // thanks DimDiDima for noticing inconsistency on some AOE mobskills
|
||||||
|
if (fixedStance != 0) {
|
||||||
|
return Math.abs(fixedStance) % 2 == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.isFacingLeft();
|
||||||
|
}
|
||||||
|
|
||||||
public ElementalEffectiveness getElementalEffectiveness(Element e) {
|
public ElementalEffectiveness getElementalEffectiveness(Element e) {
|
||||||
statiLock.lock();
|
statiLock.lock();
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ public class MapleMonsterStats {
|
|||||||
public BanishInfo banish = null;
|
public BanishInfo banish = null;
|
||||||
public List<loseItem> loseItem = null;
|
public List<loseItem> loseItem = null;
|
||||||
public selfDestruction selfDestruction = null;
|
public selfDestruction selfDestruction = null;
|
||||||
|
public int fixedStance = 0;
|
||||||
public boolean friendly;
|
public boolean friendly;
|
||||||
|
|
||||||
public void setChange(boolean change) {
|
public void setChange(boolean change) {
|
||||||
@@ -339,6 +340,14 @@ public class MapleMonsterStats {
|
|||||||
this.MDDamage = MDDamage;
|
this.MDDamage = MDDamage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getFixedStance() {
|
||||||
|
return this.fixedStance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFixedStance(int stance) {
|
||||||
|
this.fixedStance = stance;
|
||||||
|
}
|
||||||
|
|
||||||
public MapleMonsterStats copy() {
|
public MapleMonsterStats copy() {
|
||||||
MapleMonsterStats copy = new MapleMonsterStats();
|
MapleMonsterStats copy = new MapleMonsterStats();
|
||||||
try {
|
try {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user