Boss Daily Entry + Maker enable actions + Duey Quick Delivery

Fixed Legendary Spirit UI getting stuck when trying to apply scrolls in equipments without upgrade slots available.
Revised map leasing. Players no longer lose ownership when changing maps. Players are allowed to lease one map each time.
Revised expeditions warping players out as soon as the leader leaves the event or the number of players inside gets to be less than the minimum required to enter.
Fixed start/complete quest commands not acting properly for some quests.
Refactored quest loadouts unnecessarily reloading MapleData.
Implemented support for daily boss limit entry, usable on expeditions.
Revised potential exploit cases within chair, face expression, quest action, summon damage and mob damage mob handlers.
Adjusted displayed date in Duey. Value displayed now should be consistent with the expected expiration time.
Refactored damage for friendly mobs getting handled inside packet structure.
Implemented support for Quick Delivery from Duey.
Fixed Horntail specifically not dropping loots after recent updates.
Refactored commands system. All commands are instanced at boot time instead of at every call.
Fixed usage of Maker skill not sending MAKER_RESULT packet to players. This automatically reenables the actions button (such as create) in Maker UI.
Adjusted minidungeons, now using time limits specified in their respective recipes.
Reviewed the "timeLimit" property utilized by maps, which was poised to work on 2 different concepts altogether.
Fixed Gaga space event, should be functional now.
Added RPS minigame, resources implemented by Arnah.
Fixed damage taken from mob auto-destruction not working properly.
This commit is contained in:
ronancpl
2019-06-27 20:34:39 -03:00
parent a39a210c1f
commit fba27fb3b1
82 changed files with 2902 additions and 2611 deletions
+2 -2
View File
@@ -29,7 +29,7 @@ Java7 SDK: https://www.oracle.com/technetwork/java/javase/downloads/java-archive
**Change log:**
* Fixed Monster Magnet crashing the caster when trying to pull-in bosses.
* Fixed Monster Magnet crashing the caster when trying to pull bosses.
* Fixed some 'rn' problems with quest icons & removed "tab" from party leader changed message. https://hostr.co/tsYsQzzV6xT0
@@ -247,7 +247,7 @@ To change a character's GM level, make sure that character is not logged in, the
---
### Some notes about WZ/WZ.XML EDITING
NOTE: Be extremely wary when using server-side's XMLs data being reimporting into the client's WZ, as some means of synchronization between the server and client modules, this action COULD generate some kind of bugs afterwards. Client-to-server data reimporting seems to be fine, though.
NOTE: Be extremely wary when using server-side's XMLs data being reimported into the client's WZ, as some means of synchronization between the server and client modules, this action COULD generate some kind of bugs afterwards. Client-to-server data reimporting seems to be fine, though.
#### Editing the v83 WZ's:
+35 -1
View File
@@ -1948,4 +1948,38 @@ Ajustado interação com mapa do NPC Nein Spirit's Baby Dragon. Acesso à área
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.
Corrigido limites de requisitos de nível para acessar expedições nos scripts de NPCs que as gerenciam.
19 Junho 2019,
Corrigido janela congelada de Legendary Spirit ao tentar aplicar scrolls em equipamentos sem slots.
Ajustado chance de drops de skillbooks.
Revisado funcionalidade de arrendamento de mapas. Jogadores não mais perdem posse ao trocar de mapas, somente ao expirar devido à falta de atividades ou ao tentar arrendar outro mapa.
Revisado expedições retirando jogadores assim que o líder sai de mapa ou não há mais em campo a quantidade mínima de jogadores requisitada para começar o evento.
Corrigido gerenciador de mapas finalizando antes dos eventos, potencialmente levando a quebra de scripts de evento durante a fase de shutdown do servidor.
Corrigido comandos de começar/completar quests não atuando para quests não previstas pelos XMLs.
Revisado sistema de quests desnecessariamente inicializando estruturas de leitura de XMLs.
Corrigido sistema de quests no objeto do jogador não acessando corretamente certas quests devido a uso indevido de inteiros de tamanho short e int.
20 Junho 2019,
Implementado sistema de contabilização de entradas em bosses.
Corrigido potencial exploit com expressão facial podendo crashar jogadores ao receber expressão inválida.
21 - 22 Junho 2019,
Ajustado data no Duey, que estava atuando de forma inesperada anteriormente.
Adicionado checagem contra potenciais exploits de dano dado em mobs por mobs ou summons em seus respectivos handlers.
Adicionado checagem contra potenciais exploits por itens nos handlers de cadeira e expressão facial.
Ajustado checagem contra potenciais exploits de distância/inexistência de NPC na área onde o jogador se encontra, ao se realizar operações sobre quests.
Refatorado função que modifica estado de mob aliado no mapa (no lado servidor) sendo executada dentro de definição de pacote.
Implementado suporte para entrega rápida pelo Duey.
24 - 25 Junho 2019,
Corrigido Horntail não dropando itens após mudança recente na lógica de drops.
Revisado sistema de comandos. Cada comando no sistema é inicializado somente uma vez, ao iniciar o servidor.
Ajustado Maker skill, agora utilizando pacotes de resultados ao realizar suas operações.
Corrigido Mini Dungeons utilizando tempo limite pré-determinado no código-fonte.
Revisado utilização de "timeLimit" em objeto MapleMap. Valor supostamente pré-determinado pela receita XML poderia ser sobrescrito por outros métodos da classe.
Ajustado evento de Gaga no espaço, evento agora funcional.
Adicionado minigame RPS de NPC, recursos implementados pelo Arnah.
27 Junho 2019,
Corrigido contabilização de dano de auto-destruição de mobs não sendo aplicado corretamente.
-3
View File
@@ -1,3 +0,0 @@
#!/bin/sh
export CLASSPATH=".:dist/*"
java -Xmx2048m -Dwzpath=wz/ net.server.Server
+4
View File
@@ -0,0 +1,4 @@
#!/bin/bash
# thanks to lkxyyjx
sudo ant -Dplatforms.JDK_1.7.home=/opt/jdk1.7.0_80 compile
sudo ant -Dplatforms.JDK_1.7.home=/opt/jdk1.7.0_80 jar
+4
View File
@@ -0,0 +1,4 @@
#!/bin/sh
# cores in classpath, thanks to lkxyyjx
export CLASSPATH=".:dist/*:cores/*"
java -Xmx2048m -Dwzpath=wz/ net.server.Server
-185
View File
@@ -1,185 +0,0 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <[email protected]>
Matthias Butz <[email protected]>
Jan Christian Meyer <[email protected]>
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 exitMap;
var minPlayers = 3;
function init() {}
function monsterValue(eim, mobId) {
return 1;
}
function setup(level, lobbyid) {
exitMap = em.getChannelServer().getMapFactory().getMap(105090800); // <exit>
var eim = em.newInstance("4jberserk_" + lobbyid);
eim.setProperty("level", level);
var mf = eim.getMapFactory();
var map = mf.getMap(910500200);
map.addMapTimer(3*60);
em.schedule("timeOut", 20 * 60000);
//you can't warp up to the rocks until all rogs are dead, I think?
eim.setProperty("canWarp","false");
return eim;
}
function afterSetup(eim) {}
function playerEntry(eim, player) {
var map = eim.getMapInstance(910500200);
player.changeMap(map, map.getPortal(0));
//TODO: hold time across map changes
//player.getClient().announce(tools.MaplePacketCreator.getClock(1800));
}
function playerDead(eim, player) {
}
function playerRevive(eim, player) {
//if (eim.isLeader(player)) { //check for party leader
//boot whole party and end
var party = eim.getPlayers();
for (var i = 0; i < party.size(); i++) {
playerExit(eim, party.get(i));
}
eim.dispose();
/*/}
else { //boot dead player
// If only 2 players are left, uncompletable:
var party = eim.getPlayers();
if (party.size() <= minPlayers) {
for (var i = 0; i < party.size(); i++) {
playerExit(eim,party.get(i));
}
eim.dispose();
}
else
playerExit(eim, player);
}*/
}
function playerDisconnected(eim, player) {
//if (eim.isLeader(player)) { //check for party leader
//boot whole party and end
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();
/*/}
else { //boot d/ced player
// If only 2 players are left, uncompletable:
var party = eim.getPlayers();
if (party.size() < minPlayers) {
for (var i = 0; i < party.size(); i++) {
playerExit(eim,party.get(i));
}
eim.dispose();
}
else
playerExit(eim, player);
}*/
}
function leftParty(eim, player) {
// If only 2 players are left, uncompletable:
var party = eim.getPlayers();
if (true) {
for (var i = 0; i < party.size(); i++) {
playerExit(eim,party.get(i));
}
eim.dispose();
}
else
playerExit(eim, player);
}
function disbandParty(eim) {
//boot whole party and end
var party = eim.getPlayers();
for (var i = 0; i < party.size(); i++) {
playerExit(eim, party.get(i));
}
eim.dispose();
}
function playerUnregistered(eim, player) {}
function playerExit(eim, player) {
eim.unregisterPlayer(player);
player.changeMap(exitMap, exitMap.getPortal(0));
}
//for offline players
function removePlayer(eim, player) {
eim.unregisterPlayer(player);
player.getMap().removePlayer(player);
player.setMap(exitMap);
}
function clearPQ(eim) {
var party = eim.getPlayers();
for (var i = 0; i < party.size(); i++)
playerExit(eim, party.get(i));
eim.dispose();
}
function monsterKilled(mob, eim) {}
function allMonstersDead(eim) {
eim.setProperty("canWarp","true");
}
function cancelSchedule() {}
function timeOut() {
var iter = em.getInstances().iterator();
while (iter.hasNext()) {
var eim = iter.next();
if (eim.getPlayerCount() > 0) {
var pIter = eim.getPlayers().iterator();
while (pIter.hasNext())
playerExit(eim, pIter.next());
}
eim.dispose();
}
}
// ---------- FILLER FUNCTIONS ----------
function dispose() {}
function scheduledTimeout(eim) {}
function changedLeader(eim, leader) {}
-155
View File
@@ -1,155 +0,0 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <[email protected]>
Matthias Butz <[email protected]>
Jan Christian Meyer <[email protected]>
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 AngelSL
*
* 4th Job Rush Quest.
* Based on Kerning City PQ script by Stereo
*/
var exitMap;
var minPlayers = 3;
function init() {}
function monsterValue(eim, mobId) {
return 1;
}
function setup(level, lobbyid) {
exitMap = em.getChannelServer().getMapFactory().getMap(105090700); // <exit>
var eim = em.newInstance("4jrush_" + lobbyid);
eim.setProperty("level", level);
var mf = eim.getMapFactory();
var map = mf.getMap(910500100);
map.addMapTimer(20*60);
em.schedule("timeOut", 20 * 60000);
return eim;
}
function afterSetup(eim) {}
function playerEntry(eim, player) {
var map = eim.getMapInstance(910500100);
player.changeMap(map, map.getPortal(0));
}
function playerDead(eim, player) {
}
function playerRevive(eim, player) {
var party = eim.getPlayers();
for (var i = 0; i < party.size(); i++) {
playerExit(eim, party.get(i));
}
eim.dispose();
}
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 leftParty(eim, player) {
// If only 2 players are left, uncompletable:
var party = eim.getPlayers();
if (true) {
for (var i = 0; i < party.size(); i++) {
playerExit(eim,party.get(i));
}
eim.dispose();
}
else
playerExit(eim, player);
}
function disbandParty(eim) {
//boot whole party and end
var party = eim.getPlayers();
for (var i = 0; i < party.size(); i++) {
playerExit(eim, party.get(i));
}
eim.dispose();
}
function playerUnregistered(eim, player) {}
function playerExit(eim, player) {
eim.unregisterPlayer(player);
player.changeMap(exitMap, exitMap.getPortal(0));
}
//for offline players
function removePlayer(eim, player) {
eim.unregisterPlayer(player);
player.getMap().removePlayer(player);
player.setMap(exitMap);
}
function clearPQ(eim) {
//KPQ does nothing special with winners
var party = eim.getPlayers();
for (var i = 0; i < party.size(); i++) {
playerExit(eim, party.get(i));
}
eim.dispose();
}
function monsterKilled(mob, eim) {}
function allMonstersDead(eim) {}
function cancelSchedule() {}
function timeOut() {
var iter = em.getInstances().iterator();
while (iter.hasNext()) {
var eim = iter.next();
if (eim.getPlayerCount() > 0) {
var pIter = eim.getPlayers().iterator();
while (pIter.hasNext()) {
playerExit(eim, pIter.next());
}
}
eim.dispose();
}
}
// ---------- FILLER FUNCTIONS ----------
function dispose() {}
function scheduledTimeout(eim) {}
function changedLeader(eim, leader) {}
+4 -4
View File
@@ -170,7 +170,7 @@ function playerLeft(eim, player) {
function changedMap(eim, player, mapid) {
if (mapid < minMapId || mapid > maxMapId) {
if (eim.isEventTeamLackingNow(true, minPlayers, player)) {
if (eim.isExpeditionTeamLackingNow(true, minPlayers, player)) {
eim.unregisterPlayer(player);
end(eim);
}
@@ -189,7 +189,7 @@ function changedLeader(eim, leader) {
function playerDead(eim, player) {}
function playerRevive(eim, player) { // player presses ok on the death pop up.
if (eim.isEventTeamLackingNow(true, minPlayers, player)) {
if (eim.isExpeditionTeamLackingNow(true, minPlayers, player)) {
eim.unregisterPlayer(player);
end(eim);
}
@@ -198,7 +198,7 @@ function playerRevive(eim, player) { // player presses ok on the death pop up.
}
function playerDisconnected(eim, player) {
if (eim.isEventTeamLackingNow(true, minPlayers, player)) {
if (eim.isExpeditionTeamLackingNow(true, minPlayers, player)) {
eim.unregisterPlayer(player);
end(eim);
}
@@ -207,7 +207,7 @@ function playerDisconnected(eim, player) {
}
function leftParty(eim, player) {
if (eim.isEventTeamLackingNow(false, minPlayers, player)) {
if (eim.isExpeditionTeamLackingNow(false, minPlayers, player)) {
end(eim);
}
else
+4 -4
View File
@@ -170,7 +170,7 @@ function playerLeft(eim, player) {
function changedMap(eim, player, mapid) {
if (mapid < minMapId || mapid > maxMapId) {
if (eim.isEventTeamLackingNow(true, minPlayers, player)) {
if (eim.isExpeditionTeamLackingNow(true, minPlayers, player)) {
eim.unregisterPlayer(player);
end(eim);
}
@@ -189,7 +189,7 @@ function changedLeader(eim, leader) {
function playerDead(eim, player) {}
function playerRevive(eim, player) { // player presses ok on the death pop up.
if (eim.isEventTeamLackingNow(true, minPlayers, player)) {
if (eim.isExpeditionTeamLackingNow(true, minPlayers, player)) {
eim.unregisterPlayer(player);
end(eim);
}
@@ -198,7 +198,7 @@ function playerRevive(eim, player) { // player presses ok on the death pop up.
}
function playerDisconnected(eim, player) {
if (eim.isEventTeamLackingNow(true, minPlayers, player)) {
if (eim.isExpeditionTeamLackingNow(true, minPlayers, player)) {
eim.unregisterPlayer(player);
end(eim);
}
@@ -207,7 +207,7 @@ function playerDisconnected(eim, player) {
}
function leftParty(eim, player) {
if (eim.isEventTeamLackingNow(false, minPlayers, player)) {
if (eim.isExpeditionTeamLackingNow(false, minPlayers, player)) {
end(eim);
}
else
+3 -3
View File
@@ -241,7 +241,7 @@ function scheduledTimeout(eim) {
function changedMap(eim, player, mapid) {
if (mapid < minMapId || mapid > maxMapId) {
if (eim.isExpeditionTeamLackingNow(true, minPlayers, player)) {
if (eim.isEventTeamLackingNow(true, minPlayers, player)) {
eim.dropMessage(5, "[Expedition] Either the leader has quit the expedition or there is no longer the minimum number of members required to continue it.");
eim.unregisterPlayer(player);
end(eim);
@@ -297,7 +297,7 @@ function changedLeader(eim, leader) {}
function playerDead(eim, player) {}
function playerRevive(eim, player) {
if (eim.isExpeditionTeamLackingNow(true, minPlayers, player)) {
if (eim.isEventTeamLackingNow(true, minPlayers, player)) {
eim.unregisterPlayer(player);
eim.dropMessage(5, "[Expedition] Either the leader has quit the expedition or there is no longer the minimum number of members required to continue it.");
end(eim);
@@ -309,7 +309,7 @@ function playerRevive(eim, player) {
}
function playerDisconnected(eim, player) {
if (eim.isExpeditionTeamLackingNow(true, minPlayers, player)) {
if (eim.isEventTeamLackingNow(true, minPlayers, player)) {
eim.dropMessage(5, "[Expedition] Either the leader has quit the expedition or there is no longer the minimum number of members required to continue it.");
eim.unregisterPlayer(player);
end(eim);
+211
View File
@@ -0,0 +1,211 @@
/**
* @author: kevintjuh93
* @author: Ronan
*/
importPackage(Packages.tools);
var isPq = true;
var minPlayers = 1, maxPlayers = 1;
var minLevel = 12, maxLevel = 255;
var entryMap = 922240000;
var exitMap = 922240200;
var recruitMap = 922240200;
var minMapId = 922240000;
var maxMapId = 922240100;
var eventTime = 3; // 3 minutes
var lobbyRange = [0, 19];
function init() {
setEventRequirements();
}
function setLobbyRange() {
return lobbyRange;
}
function setEventRequirements() {
var reqStr = "";
reqStr += "\r\n Number of players: ";
if(maxPlayers - minPlayers >= 1) reqStr += minPlayers + " ~ " + maxPlayers;
else reqStr += minPlayers;
reqStr += "\r\n Level range: ";
if(maxLevel - minLevel >= 1) reqStr += minLevel + " ~ " + maxLevel;
else reqStr += minLevel;
reqStr += "\r\n Time limit: ";
reqStr += eventTime + " minutes";
em.setProperty("party", reqStr);
}
function setEventExclusives(eim) {
var itemSet = [];
eim.setExclusiveItems(itemSet);
}
function setEventRewards(eim) {
var itemSet, itemQty, evLevel, expStages;
evLevel = 1; //Rewards at clear PQ
itemSet = [];
itemQty = [];
eim.setEventRewards(evLevel, itemSet, itemQty);
expStages = []; //bonus exp given on CLEAR stage signal
eim.setEventClearStageExp(expStages);
}
function getEligibleParty(party) { //selects, from the given party, the team that is allowed to attempt this event
var eligible = [];
var hasLeader = false;
if(party.size() > 0) {
var partyList = party.toArray();
for(var i = 0; i < party.size(); i++) {
var ch = partyList[i];
if(ch.getMapId() == recruitMap && ch.getLevel() >= minLevel && ch.getLevel() <= maxLevel) {
if(ch.isLeader()) hasLeader = true;
eligible.push(ch);
}
}
}
if(!(hasLeader && eligible.length >= minPlayers && eligible.length <= maxPlayers)) eligible = [];
return eligible;
}
function setup(level, lobbyid) {
var eim = em.newInstance("RescueGaga_" + lobbyid);
eim.setProperty("level", level);
eim.setProperty("stage", "0");
eim.setProperty("falls", "0");
respawnStages(eim);
eim.startEventTimer(eventTime * 60000);
setEventRewards(eim);
setEventExclusives(eim);
return eim;
}
function afterSetup(eim) {}
function respawnStages(eim) {}
function playerEntry(eim, player) {
var map = eim.getMapInstance(entryMap);
player.changeMap(map, map.getPortal(0));
player.announce(MaplePacketCreator.showEffect("event/space/start"));
player.startMapEffect("Please rescue Gaga within the time limit.", 5120027);
}
function scheduledTimeout(eim) {
end(eim);
}
function playerUnregistered(eim, player) {}
function playerExit(eim, player) {
eim.unregisterPlayer(player);
player.changeMap(exitMap, 0);
}
function changedMap(eim, player, mapid) {
if (mapid < minMapId || mapid > maxMapId) {
if (eim.isEventTeamLackingNow(true, minPlayers, player)) {
eim.unregisterPlayer(player);
player.changeMap(mapid, 0);
player.cancelEffect(2360002);
end(eim);
} else {
eim.unregisterPlayer(player);
player.changeMap(mapid, 0);
player.cancelEffect(2360002);
}
} else if (mapid == maxMapId) {
eim.clearPQ();
var rgaga = player.getEvents().get("rescueGaga");
rgaga.complete();
}
}
function afterChangedMap(eim, player, mapid) {
if (mapid == minMapId) {
player.getAbstractPlayerInteraction().useItem(2360002);//HOORAY <3
} else {
player.cancelEffect(2360002);
}
}
function changedLeader(eim, leader) {}
function playerDead(eim, player) {}
function playerRevive(eim, player) { // player presses ok on the death pop up.
if (eim.isEventTeamLackingNow(true, minPlayers, player)) {
eim.unregisterPlayer(player);
end(eim);
}
else
eim.unregisterPlayer(player);
}
function playerDisconnected(eim, player) {
if (eim.isEventTeamLackingNow(true, minPlayers, player)) {
eim.unregisterPlayer(player);
end(eim);
}
else
eim.unregisterPlayer(player);
}
function leftParty(eim, player) {}
function disbandParty(eim) {}
function monsterValue(eim, mobId) {
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 giveRandomEventReward(eim, player) {
eim.giveEventReward(player);
}
function clearPQ(eim) {
eim.stopEventTimer();
eim.setEventCleared();
eim.schedule("spawnGrandpaBunny", 10 * 1000);
}
function spawnGrandpaBunny(eim) {
eim.spawnNpc(9001105, new java.awt.Point(175, -20), eim.getInstanceMap(maxMapId));
}
function monsterKilled(mob, eim) {}
function allMonstersDead(eim) {}
function cancelSchedule() {}
function dispose(eim) {}
+9 -2
View File
@@ -85,7 +85,9 @@ function setEventRewards(eim) {
eim.setEventClearStageMeso(mesoStages);
}
function afterSetup(eim) {}
function afterSetup(eim) {
em.getChannelServer().getMapFactory().getMap(211042300).getReactorById(2118002).forceHitReactor(1);
}
function setup(channel) {
var eim = em.newInstance("Zakum" + channel);
@@ -188,6 +190,7 @@ function giveRandomEventReward(eim, player) {
function clearPQ(eim) {
eim.stopEventTimer();
eim.setEventCleared();
em.getChannelServer().getMapFactory().getMap(211042300).getReactorById(2118002).forceHitReactor(0);
}
function isZakum(mob) {
@@ -209,4 +212,8 @@ function allMonstersDead(eim) {}
function cancelSchedule() {}
function dispose(eim) {}
function dispose(eim) {
if (!eim.isEventCleared()) {
em.getChannelServer().getMapFactory().getMap(211042300).getReactorById(2118002).forceHitReactor(0);
}
}
@@ -1,5 +1,4 @@
function start(ms) {
ms.getPlayer().resetEnteredScript();
ms.getPlayer().getMap().addMapTimer(180);
ms.getPlayer().resetEnteredScript();
ms.spawnMonster(9300331, -28, 0);
}
@@ -1,41 +0,0 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <[email protected]>
Matthias Butz <[email protected]>
Jan Christian Meyer <[email protected]>
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: kevintjuh93
*/
importPackage(Packages.tools);
var player;
function start(ms) {
player = ms.getPlayer();
player.resetEnteredScript();
ms.getClient().announce(MaplePacketCreator.showEffect("event/space/start"));
player.startMapEffect("Please rescue Gaga within the time limit.", 5120027);
var map = player.getMap();
if (map.getTimeLeft() > 0) {
ms.getClient().announce(MaplePacketCreator.getClock(map.getTimeLeft()));
} else {
map.addMapTimer(180);
}
ms.useItem(2360002);//HOORAY <3
}
+32
View File
@@ -0,0 +1,32 @@
var status;
function start() {
status = -1;
action(1, 0, 0);
}
function action(mode, type, selection) {
if (mode == -1) {
cm.dispose();
} else {
if (mode == 0 && type > 0) {
cm.dispose();
return;
}
if (mode == 1)
status++;
else
status--;
if(status == 0) {
if(cm.getPlayer().getInventory(Packages.client.inventory.MapleInventoryType.ETC).getNumFreeSlot() < 1) {
cm.sendNext("Check for a available slot on your ETC inventory.");
cm.dispose();
return;
}
cm.getClient().announce(Packages.tools.MaplePacketCreator.openRPSNPC());
cm.dispose();
}
}
}
+54
View File
@@ -0,0 +1,54 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <[email protected]>
Matthias Butz <[email protected]>
Jan Christian Meyer <[email protected]>
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 : iAkira, Kevintjuh93
**/
var status = 0;
var selected = 0;
function start() {
if (cm.getPlayer().getMapId() == 100000000) {
cm.sendNext("There! Did you see that? You didn't? A UFO just passed... there!! Look, someone is getting dragged into the UFO... arrrrrrgh, it's Gaga! #rGaga just got kidnapped by a UFO!#k");
}
}
function action(m,t,s) {
if (m > 0) {
status++;
if (cm.getPlayer().getMapId() == 100000000) { // warper completed
if (status == 1) {
if (cm.getPlayer().getLevel() >= 12)
cm.sendYesNo("What do we do now? It's just a rumor yet, but... I've heard that scary things happen to you if you get kidnapped by aliens... may be that's what happenning to Gaga right now! Please, please rescue Gaga! \r\n #bGaga may be a bit indetermined and clueless, but#k he has a really good heart. I can't let something terrible happen to him. Right! Grandpa from the moon might know how to rescue him! I will send you to the moon, so please go meet Grandpa and rescue Gaga!!!");
else
cm.sendOk("Oh! It seems you don't reach the level requirements to save Gaga. Please come back when you are level 12 or higher.");
} else if (status == 2)
cm.sendNext("Thank you so much. Please rescue Gaga! Grandpa from the moon will help you.");
else if (status == 3) {
cm.warp(922240200, 0);
cm.dispose();
}
}
} else if (m < 1) {
cm.dispose();
}
}
+77
View File
@@ -0,0 +1,77 @@
var status;
function start() {
status = -1;
action(1, 0, 0);
}
function action(mode, type, selection) {
if (mode == -1) {
cm.dispose();
} else {
if (mode == 0 && type > 0) {
if (cm.getPlayer().getMapId() == 922240200) {
cm.sendOk("That's a shame, come back when your ready.");
}
cm.dispose();
return;
}
if (mode == 1)
status++;
else
status--;
if(status == 0) {
if (cm.getMapId() == 922240200) {
cm.sendSimple("Did you have something to say...? #b\b\r\n#L0#I want to rescue Gaga.#l\r\n"); //#L1#I want to go to the Space Mine.#l
} else if (cm.getMapId() >= 922240000 && cm.getMapId() <= 922240019) {
cm.sendYesNo("Don't worry if you fail. You'll have 3 chances. Do you still want to give up?");
} else if (cm.getMapId() >= 922240100 && cm.getMapId() <= 922240119) {
var text = "You went through so much trouble to rescue Gaga, but it looks like we're back to square one. ";
var rgaga = cm.getPlayer().getEvents().get("rescueGaga");
if (rgaga.getCompleted() > 10) {
text += "Please don't give up until Gaga is rescued. To show you my appreciation for what you've accomplished thus far, I've given you a Spaceship. It's rather worn out, but it should still be operational. Check your #bSkill Window#k.";
rgaga.giveSkill(cm.getPlayer());
} else
text += "Let's go back now.";
cm.sendNext(text);
}
} else {
if (cm.getPlayer().getMapId() == 922240200) {
if (status == 1) {
if(selection == 0) {
selected = 1;
cm.sendNext("Welcome! I heard what happened from Baby Moon Bunny I'm glad you came since I was Planning on requesting some help. Gaga is a friend of mine who has helped me before and often stops by to say hello. Unfortunately, he was kidnapped by aliens.");
} else {
selected = 2;
cm.sendYesNo("At the Space Mine, you can find special ores called #bKrypto Crystals#k that contains the mysterious power of space. #bKrypto Crystals#l are usually emerald in color, but will turn brown if hit with the Spaceship's #bSpace Beam#k. Remember, in order to thwart this alien conspracy, #b10 Brown Krypto Crystal's and 10 Emerald Krypto Crystal's are needed. But since even #b1 Krypto Crystal#k can be of help, brign me as many as possible. Oh, and one more thing! The Space Mines are protected by the Space Mateons. They are extemely strong due to the power of the #Krypto Crystals#k, so don't try to defeat them. Simply concentrate on quickly collecting the crystals.");
}
} else if (status == 2) {
if(selected == 1) {
cm.sendYesNo("If we just leave Gaga with the aliens, something terrible will happen to him! I'll let you borrow a spaceship that the Moon Bunnies use for traveling so that you can rescue Gaga.#b Although he might appear a bit indecisive, slow, and immature at times#k, he's really a nice young man. Do you want to go rescue him now?");
} else if(selected == 2) {
cm.sendOk("Not coded yet, f4.");
cm.dispose();
}
} else if (status == 3) {
var em = cm.getEventManager("RescueGaga");
if (em == null) {
cm.sendOk("This event is currently unavailable.");
} else if (!em.startInstance(cm.getPlayer())) {
cm.sendOk("There is currently someone in this map, come back later.");
}
cm.dispose();
}
} else if (cm.getPlayer().getMapId() >= 922240000 && cm.getPlayer().getMapId() <= 922240019) {
cm.warp(922240200, 0);
cm.dispose();
} else if (cm.getPlayer().getMapId() >= 922240100 && cm.getPlayer().getMapId() <= 922240119) {
cm.warp(922240200, 0);
cm.dispose();
}
}
}
}
-108
View File
@@ -1,108 +0,0 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <[email protected]>
Matthias Butz <[email protected]>
Jan Christian Meyer <[email protected]>
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 : iAkira, Kevintjuh93
**/
var status = 0;
var selected = 0;
function start() {
if (cm.getPlayer().getMapId() == 100000000) {
cm.sendNext("There! Did you see that? You didn't? A UFO just passed... there!! Look, someone is getting dragged into the UFO... arrrrrrgh, it's Gaga! #rGaga just got kidnapped by a UFO!#k");
} else if (cm.getPlayer().getMapId() == 922240200) {
cm.sendSimple("Did you have something to say...? #b\b\r\n#L0#I want to rescue Gaga.#l\r\n#L1#I want to go to the Space Mine.#l");
} else if (cm.getPlayer().getMapId() >= 922240000 && cm.getPlayer().getMapId() <= 922240019) {
cm.sendYesNo("Don't worry if you fail. You'll have 3 chances. Do you still want to give up?");
} else if (cm.getPlayer().getMapId() >= 922240100 && cm.getPlayer().getMapId() <= 922240119) {
var text = "You went through so much trouble to rescue Gaga, but it looks like we're back to square one. ";
var rgaga = cm.getPlayer().getEvents().get("rescueGaga");
if (rgaga.getCompleted() == 10 || rgaga.getCompleted() == 20) {
text += "Please don't give up untill Gaga is rescued. To show you my appreciation for what you've accomplished thus far, I've given you a Spaceship. It's rather worn out, but it should still be operational. Check your #bSkill Window#k.";
rgaga.giveSkill(cm.getPlayer());
} else
text += "Let's go back now.";
cm.sendNext(text);
}
}
function action(m,t,s) {
if (m > 0) {
status++;
if (cm.getPlayer().getMapId() == 100000000) { // warper completed
if (status == 1) {
if (cm.getPlayer().getLevel() >= 12)
cm.sendYesNo("What do we do now? It's just a rumor yet, but... I've heard that scary things happen to you if you get kidnapped by aliens... may be that's what happenning to Gaga right now! Please, please rescue Gaga! \r\n #bGaga may be a bit indetermined and clueless, but#k he has a really good heart. I can't let something terrible happen to him. Right! Grandpa from the moon might know how to rescue him! I will send you to the moon, so please go meet Grandpa and rescue Gaga");
else
cm.sendOk("Oh! it seems you don't reach the level requirements to save Gaga. Please come back when you are level 12 or higher.");
} else if (status == 2)
cm.sendNext("Thank you so much. Please rescue Gaga! Grandpa from the moon will help you.");
else if (status == 3) {
cm.warp(922240200, 0);
cm.dispose();
}
} else if (cm.getPlayer().getMapId() == 922240200) {
if (status == 1) {
if(s == 0) {
selected = 1;
cm.sendNext("Welcome! I heard what happened from Baby Moon Bunny I'm glad you came since I was Planning on requesting some help. Gaga is a friend of mine who has helped me before and often stops by to say hello. Unfortunaley, he was kidnapped by aliens.");
} else {
selected = 2;
cm.sendYesNo("At the Space Mine, you can find special ores called #bKrypto Crystals#k that contains the mysterious power of space. #bKrypto Crystals#l are usually emerald in color, but will turn brown if hit with the Spaceship's #bSpace Beam#k. Remember, in order to thwart this alien conspracy, #b10 Brown Krypto Crystal's and 10 Emerald Krypto Crystal's are needed. But since even #b1 Krypto Crystal#k can be of help, brign me as many as possible. Oh, and one more thing! The Space Mines are protected by the Space Mateons. They are extemely strong due to the power of the #Krypto Crystals#k, so don't try to defeat them. Simply concentrate on quickly collecting the crystals.");
}
} else if (status == 2) {
if(selected == 1) {
cm.sendYesNo("If we just leave Gaga with the aliens, something terrible will happen to him! I'll let you borrow a spaceship that the Moon Bunnies use for traveling so that you can rescue Gaga.#b Although he might appear a bit indecieve, slow, and immature at times#k, he's really a nice young man. Do you want to go rescue him now?");
} else if(selected == 2) {
cm.sendOk("Not coded yet, f4.");
cm.dispose();
}
} else if (status == 3) {
var number = -1;
for (var i = 0; i < 20; i++) {
var mapFactory = cm.getClient().getChannelServer().getMapFactory();
if (mapFactory.getMap(922240000 + i).getCharacters().isEmpty()) {
number = i;
break;
}
}
if (number > -1)
cm.warp(922240000 + number);
else
cm.sendOk("There are currently no empty maps, please try again later.");
cm.dispose();
}
} else if ((cm.getPlayer().getMapId() >= 922240000 && cm.getPlayer().getMapId() <= 922240019) || (cm.getPlayer().getMapId() >= 922240100 && cm.getPlayer().getMapId() <= 922240119)) {
cm.warp(922240200, 0);
cm.dispose();
}
} else if (m < 1) {
if(m == 0) {
if (cm.getPlayer().getMapId() == 922240200) {
cm.sendOk("That's a shame, come back when your ready.");
}
}
cm.dispose();
}
}
+3 -1
View File
@@ -43,6 +43,7 @@ function writeFeatureTab_PQs() {
addFeature("RnJPQ/HorntailPQ/TreasurePQ/ElnathPQ/HolidayPQ.");
addFeature("CWKPQ as Expedition-based instance.");
addFeature("Scarga/Horntail/Showa/Balrog/Zakum/Pinkbean.");
addFeature("Expeditions with entry-limit system available.");
addFeature("GuildPQ & queue with multi-lobby system available.");
addFeature("Brand-new PQs: BossRushPQ, CafePQ.");
addFeature("Mu Lung Dojo.");
@@ -57,7 +58,7 @@ function writeFeatureTab_Skills() {
addFeature("Reviewed many skills, such as Steal and M. Door.");
addFeature("Heal GMS-like: fixed HP gain & Heal skill packet.");
addFeature("Improved battleship: HP visible and map-persistent.");
addFeature("Maker skill features properly developed.");
addFeature("Maker skill features developed - pckts thanks Arnah.");
addFeature("Chair Mastery - map chair boosts HP/MP rec.");
addFeature("Mu Lung Dojo skills functional.");
addFeature("Monster Magnet skill no longer crashes players.");
@@ -185,6 +186,7 @@ function writeFeatureTab_Playerpotentials() {
addFeature("Optional cash shop inventory separated by classes.");
addFeature("Players manage 'same-typed' invites exclusively.");
addFeature("Player buffs with conditional active effects.");
addFeature("Rock-paper-scissors minigame - thanks Arnah!");
}
function writeFeatureTab_Serverpotentials() {
+8 -4
View File
@@ -1,11 +1,15 @@
//Author: kevintjuh93
function enter(pi) {
if (pi.getPlayer().getEvents().get("rescueGaga").fallAndGet() > 3) {
pi.playPortalSound(); pi.warp(922240200, 0);
pi.getPlayer().cancelEffect(2360002);
} else
var eim = pi.getPlayer().getEventInstance();
var fc = eim.getIntProperty("falls");
if (fc >= 3) {
pi.playPortalSound(); pi.warp(922240200, 0);
} else {
eim.setIntProperty("falls", fc + 1);
pi.playPortalSound(); pi.warp(pi.getPlayer().getMapId(), 0);
}
return true;
}
+8 -4
View File
@@ -1,11 +1,15 @@
//Author: kevintjuh93
function enter(pi) {
if (pi.getPlayer().getEvents().get("rescueGaga").fallAndGet() > 3) {
pi.playPortalSound(); pi.warp(922240200, 0);
pi.getPlayer().cancelEffect(2360002);
} else
var eim = pi.getPlayer().getEventInstance();
var fc = eim.getIntProperty("falls");
if (fc >= 3) {
pi.playPortalSound(); pi.warp(922240200, 0);
} else {
eim.setIntProperty("falls", fc + 1);
pi.playPortalSound(); pi.warp(pi.getPlayer().getMapId(), 0);
}
return true;
}
+8 -4
View File
@@ -1,11 +1,15 @@
//Author: kevintjuh93
function enter(pi) {
if (pi.getPlayer().getEvents().get("rescueGaga").fallAndGet() > 3) {
pi.playPortalSound(); pi.warp(922240200, 0);
pi.getPlayer().cancelEffect(2360002);
} else
var eim = pi.getPlayer().getEventInstance();
var fc = eim.getIntProperty("falls");
if (fc >= 3) {
pi.playPortalSound(); pi.warp(922240200, 0);
} else {
eim.setIntProperty("falls", fc + 1);
pi.playPortalSound(); pi.warp(pi.getPlayer().getMapId(), 0);
}
return true;
}
+8 -4
View File
@@ -1,11 +1,15 @@
//Author: kevintjuh93
function enter(pi) {
if (pi.getPlayer().getEvents().get("rescueGaga").fallAndGet() > 3) {
pi.playPortalSound(); pi.warp(922240200, 0);
pi.getPlayer().cancelEffect(2360002);
} else
var eim = pi.getPlayer().getEventInstance();
var fc = eim.getIntProperty("falls");
if (fc >= 3) {
pi.playPortalSound(); pi.warp(922240200, 0);
} else {
eim.setIntProperty("falls", fc + 1);
pi.playPortalSound(); pi.warp(pi.getPlayer().getMapId(), 0);
}
return true;
}
+11
View File
@@ -34,6 +34,17 @@ function enter(pi) {
return false;
}
if (!pi.haveItem(4001017)) { // thanks Conrad for pointing out missing checks for token item and unused reactor
pi.getPlayer().dropMessage(5,"You do not have the Eye of Fire. You may not face the boss.");
return false;
}
var react = pi.getMap().getReactorById(2118002);
if (react != null && react.getState() > 0) {
pi.getPlayer().dropMessage(5,"The entrance is currently blocked.");
return false;
}
pi.playPortalSound(); pi.warp(211042400,"west00");
return true;
}
-2
View File
@@ -1,8 +1,6 @@
//Author: kevintjuh93
function enter(pi) {
pi.getPlayer().getEvents().get("rescueGaga").complete();
pi.playPortalSound(); pi.warp(922240100 + (pi.getPlayer().getMapId() - 922240000));
pi.getPlayer().cancelEffect(2360002);
return true;
}
+54 -32
View File
@@ -80,6 +80,22 @@ CREATE TABLE IF NOT EXISTS `area_info` (
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `bosslog_daily` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`characterid` int(11) NOT NULL,
`bosstype` enum('ZAKUM','HORNTAIL','PINKBEAN','SCARGA','PAPULATUS') NOT NULL,
`attempttime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `bosslog_weekly` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`characterid` int(11) NOT NULL,
`bosstype` enum('ZAKUM','HORNTAIL','PINKBEAN','SCARGA','PAPULATUS') NOT NULL,
`attempttime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `bbs_replies` (
`replyid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`threadid` int(10) unsigned NOT NULL,
@@ -13032,36 +13048,36 @@ INSERT IGNORE INTO `makercreatedata` (`id`, `itemid`, `req_level`, `req_maker_le
(0, 4250900, 45, 1, 110000, 0, 0, 0, 1, 0),
(0, 4251000, 45, 1, 110000, 0, 0, 0, 1, 0),
(0, 4251100, 45, 1, 110000, 0, 0, 0, 1, 0),
(0, 4251300, 75, 2, 164000, 0, 0, 0, 1, 0),
(0, 4251400, 75, 2, 164000, 0, 0, 0, 1, 0),
(0, 4250001, 45, 1, 328000, 0, 0, 0, 1, 0),
(0, 4250101, 45, 1, 328000, 0, 0, 0, 1, 0),
(0, 4250201, 45, 1, 328000, 0, 0, 0, 1, 0),
(0, 4250301, 45, 1, 328000, 0, 0, 0, 1, 0),
(0, 4250401, 45, 1, 328000, 0, 0, 0, 1, 0),
(0, 4250501, 45, 1, 328000, 0, 0, 0, 1, 0),
(0, 4250601, 45, 1, 328000, 0, 0, 0, 1, 0),
(0, 4250701, 45, 1, 328000, 0, 0, 0, 1, 0),
(0, 4250801, 45, 1, 328000, 0, 0, 0, 1, 0),
(0, 4250901, 45, 1, 328000, 0, 0, 0, 1, 0),
(0, 4251001, 45, 1, 328000, 0, 0, 0, 1, 0),
(0, 4251101, 45, 1, 328000, 0, 0, 0, 1, 0),
(0, 4251301, 75, 2, 491000, 0, 0, 0, 1, 0),
(0, 4251401, 75, 2, 491000, 0, 0, 0, 1, 0),
(0, 4250002, 45, 2, 546000, 0, 0, 0, 1, 0),
(0, 4250102, 45, 2, 546000, 0, 0, 0, 1, 0),
(0, 4250202, 45, 2, 546000, 0, 0, 0, 1, 0),
(0, 4250302, 45, 2, 546000, 0, 0, 0, 1, 0),
(0, 4250402, 45, 2, 546000, 0, 0, 0, 1, 0),
(0, 4250502, 45, 2, 546000, 0, 0, 0, 1, 0),
(0, 4250602, 45, 2, 546000, 0, 0, 0, 1, 0),
(0, 4250702, 45, 2, 546000, 0, 0, 0, 1, 0),
(0, 4250802, 45, 2, 546000, 0, 0, 0, 1, 0),
(0, 4250902, 45, 2, 546000, 0, 0, 0, 1, 0),
(0, 4251002, 45, 2, 546000, 0, 0, 0, 1, 0),
(0, 4251102, 45, 2, 546000, 0, 0, 0, 1, 0),
(0, 4251302, 75, 3, 819000, 0, 0, 0, 1, 0),
(0, 4251402, 75, 3, 819000, 0, 0, 0, 1, 0),
(0, 4251300, 75, 2, 165000, 0, 0, 0, 1, 0),
(0, 4251400, 75, 2, 165000, 0, 0, 0, 1, 0),
(0, 4250001, 45, 1, 330000, 0, 0, 0, 1, 0),
(0, 4250101, 45, 1, 330000, 0, 0, 0, 1, 0),
(0, 4250201, 45, 1, 330000, 0, 0, 0, 1, 0),
(0, 4250301, 45, 1, 330000, 0, 0, 0, 1, 0),
(0, 4250401, 45, 1, 330000, 0, 0, 0, 1, 0),
(0, 4250501, 45, 1, 330000, 0, 0, 0, 1, 0),
(0, 4250601, 45, 1, 330000, 0, 0, 0, 1, 0),
(0, 4250701, 45, 1, 330000, 0, 0, 0, 1, 0),
(0, 4250801, 45, 1, 330000, 0, 0, 0, 1, 0),
(0, 4250901, 45, 1, 330000, 0, 0, 0, 1, 0),
(0, 4251001, 45, 1, 330000, 0, 0, 0, 1, 0),
(0, 4251101, 45, 1, 330000, 0, 0, 0, 1, 0),
(0, 4251301, 75, 2, 495000, 0, 0, 0, 1, 0),
(0, 4251401, 75, 2, 495000, 0, 0, 0, 1, 0),
(0, 4250002, 45, 2, 550000, 0, 0, 0, 1, 0),
(0, 4250102, 45, 2, 550000, 0, 0, 0, 1, 0),
(0, 4250202, 45, 2, 550000, 0, 0, 0, 1, 0),
(0, 4250302, 45, 2, 550000, 0, 0, 0, 1, 0),
(0, 4250402, 45, 2, 550000, 0, 0, 0, 1, 0),
(0, 4250502, 45, 2, 550000, 0, 0, 0, 1, 0),
(0, 4250602, 45, 2, 550000, 0, 0, 0, 1, 0),
(0, 4250702, 45, 2, 550000, 0, 0, 0, 1, 0),
(0, 4250802, 45, 2, 550000, 0, 0, 0, 1, 0),
(0, 4250902, 45, 2, 550000, 0, 0, 0, 1, 0),
(0, 4251002, 45, 2, 550000, 0, 0, 0, 1, 0),
(0, 4251102, 45, 2, 550000, 0, 0, 0, 1, 0),
(0, 4251302, 75, 3, 825000, 0, 0, 0, 1, 0),
(0, 4251402, 75, 3, 825000, 0, 0, 0, 1, 0),
(0, 4001174, 45, 1, 0, 4031966, 0, 0, 1, 0),
(0, 4001175, 50, 1, 0, 4031967, 0, 0, 1, 0),
(0, 4001176, 55, 1, 0, 4031968, 0, 0, 10, 0),
@@ -13080,6 +13096,8 @@ INSERT IGNORE INTO `makercreatedata` (`id`, `itemid`, `req_level`, `req_maker_le
(0, 4032312, 70, 1, 0, 0, 0, 0, 1, 0),
(0, 2041058, 50, 1, 55000, 0, 1122013, 0, 1, 0),
(0, 2040727, 50, 1, 55000, 0, 1122013, 0, 1, 0),
(0, 4260007, 105, 3, 2200000, 4001126, 0, 0, 5, 0),
(0, 4260008, 105, 3, 5500000, 4001126, 0, 0, 10, 0),
(1, 1002028, 45, 1, 55000, 0, 0, 4130018, 1, 1),
(1, 1002085, 45, 1, 50000, 0, 0, 4130018, 1, 1),
(1, 1002086, 45, 1, 41000, 0, 0, 4130018, 1, 1),
@@ -13963,6 +13981,10 @@ INSERT IGNORE INTO `makerrecipedata` (`itemid`, `req_item`, `count`) VALUES
(2041058, 4000299, 10),
(2040727, 4000159, 50),
(2040727, 4000299, 10),
(4260007, 4260006, 100),
(4260007, 4001126, 5),
(4260008, 4260007, 50),
(4260008, 4001126, 5),
(1002028, 4007001, 5),
(1002028, 4260000, 5),
(1002085, 4007002, 5),
@@ -14808,7 +14830,7 @@ INSERT IGNORE INTO `makerrecipedata` (`itemid`, `req_item`, `count`) VALUES
(1372016, 4011002, 3),
(1372016, 4260003, 26),
(1382008, 4011002, 3),
(1382008, 4260003, 26),
(1382008, 4260004, 26),
(1372009, 4011002, 4),
(1372009, 4260004, 28),
(1382035, 4011002, 4),
@@ -15450,7 +15472,7 @@ INSERT IGNORE INTO `makerrecipedata` (`itemid`, `req_item`, `count`) VALUES
(1072194, 4260004, 9),
(1072195, 4007006, 9),
(1072195, 4260004, 9),
(1072213, 4007001, 10),
(1072213, 4007003, 10),
(1072213, 4260005, 10),
(1072214, 4007002, 10),
(1072214, 4260005, 10),
+592 -591
View File
File diff suppressed because it is too large Load Diff
+80 -39
View File
@@ -22,6 +22,7 @@
*/
package client;
import server.minigame.MapleRockPaperScissor;
import java.awt.Point;
import java.lang.ref.WeakReference;
import java.sql.Connection;
@@ -94,11 +95,10 @@ import server.maps.MapleMapObject;
import server.maps.MapleMapObjectType;
import server.maps.MapleMiniGame;
import server.maps.MapleMiniGame.MiniGameResult;
import server.life.MaplePlayerNPC;
import server.maps.MaplePlayerShop;
import server.maps.MaplePlayerShopItem;
import server.maps.MapleSummon;
import server.life.MaplePlayerNPC;
import server.life.MonsterDropEntry;
import server.maps.SavedLocation;
import server.maps.SavedLocationType;
import server.partyquest.AriantColiseum;
@@ -221,7 +221,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
private AtomicInteger exp = new AtomicInteger();
private AtomicInteger gachaexp = new AtomicInteger();
private AtomicInteger meso = new AtomicInteger();
private AtomicInteger chair = new AtomicInteger();
private AtomicInteger chair = new AtomicInteger(-1);
private int merchantmeso;
private BuddyList buddylist;
private EventInstanceManager eventInstance = null;
@@ -233,6 +233,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
private MapleJob job = MapleJob.BEGINNER;
private MapleMessenger messenger = null;
private MapleMiniGame miniGame;
private MapleRockPaperScissor rps;
private MapleMount maplemount;
private MapleParty party;
private MaplePet[] pets = new MaplePet[3];
@@ -248,6 +249,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
private SkillMacro[] skillMacros = new SkillMacro[5];
private List<Integer> lastmonthfameids;
private List<WeakReference<MapleMap>> lastVisitedMaps = new LinkedList<>();
private WeakReference<MapleMap> ownedMap = new WeakReference<>(null);
private final Map<Short, MapleQuestStatus> quests;
private Set<MapleMonster> controlled = new LinkedHashSet<>();
private Map<Integer, String> entered = new LinkedHashMap<>();
@@ -826,6 +828,26 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
}
return maxbasedamage;
}
public int calculateMaxBaseMagicDamage() {
int maxbasedamage = getTotalMagic();
int totalint = getTotalInt();
if (totalint > 2000) {
maxbasedamage -= 2000;
maxbasedamage += (int) ((0.09033024267 * totalint) + 3823.8038);
} else {
maxbasedamage -= totalint;
if (totalint > 1700) {
maxbasedamage += (int) (0.1996049769 * Math.pow(totalint, 1.300631341));
} else {
maxbasedamage += (int) (0.1996049769 * Math.pow(totalint, 1.290631341));
}
}
return (maxbasedamage * 107) / 100;
}
public void setCombo(short count) {
if (count < combocounter) {
@@ -1664,6 +1686,14 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
petLock.unlock();
}
}
public void setOwnedMap(MapleMap map) {
ownedMap = new WeakReference<>(map);
}
public MapleMap getOwnedMap() {
return ownedMap.get();
}
public void notifyMapTransferToPartner(int mapid) {
if(partnerId > 0) {
@@ -2435,7 +2465,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
}
private void startChairTask() {
if (chair.get() == 0) {
if (chair.get() < 0) {
return;
}
@@ -2644,8 +2674,8 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
chrLock.unlock();
}
if (disease == MapleDisease.SEDUCE && chair.get() != 0) {
sitChair(0);
if (disease == MapleDisease.SEDUCE && chair.get() < 0) {
sitChair(-1);
}
final List<Pair<MapleDisease, Integer>> debuff = Collections.singletonList(new Pair<>(disease, Integer.valueOf(skill.getX())));
@@ -5080,7 +5110,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
public int getTotalMagic() {
return localmagic;
}
public int getTotalWatk() {
return localwatk;
}
@@ -5339,6 +5369,10 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
return playerShop;
}
public MapleRockPaperScissor getRPS() { // thanks inhyuk for suggesting RPS addition
return rps;
}
public void setGMLevel(int level) {
this.gmLevel = Math.min(level, 6);
this.gmLevel = Math.max(level, 0);
@@ -5356,6 +5390,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
closeTrade();
closePlayerShop();
closeMiniGame(true);
closeRPS();
closeHiredMerchant(false);
closePlayerMessenger();
@@ -5512,23 +5547,19 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
public final byte getQuestStatus(final int quest) {
synchronized (quests) {
for (final MapleQuestStatus q : quests.values()) {
if (q.getQuest().getId() == quest) {
return (byte) q.getStatus().getId();
}
MapleQuestStatus mqs = quests.get((short) quest);
if (mqs != null) {
return (byte) mqs.getStatus().getId();
} else {
return 0;
}
return 0;
}
}
public final MapleQuestStatus getMapleQuestStatus(final int quest) {
synchronized (quests) {
for (final MapleQuestStatus q : quests.values()) {
if (q.getQuest().getId() == quest) {
return q;
}
}
return null;
MapleQuestStatus mqs = quests.get((short) quest);
return mqs;
}
}
@@ -6085,15 +6116,11 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
public void leaveMap() {
releaseControlledMonsters();
visibleMapObjects.clear();
setChair(0);
setChair(-1);
if (hpDecreaseTask != null) {
hpDecreaseTask.cancel(false);
}
if (map.unclaimOwnership(this)) {
map.dropMessage(5, "This lawn is now free real estate.");
}
AriantColiseum arena = this.getAriantColiseum();
if (arena != null) {
arena.leaveArena(this);
@@ -7411,12 +7438,12 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
private void unsitChairInternal() {
int chairid = chair.get();
if (chairid != 0) {
if (chairid >= 0) {
if (ItemConstants.isFishingChair(chairid)) {
this.getWorldServer().unregisterFisherPlayer(this);
}
setChair(0);
setChair(-1);
if (unregisterChairBuff()) {
getMap().broadcastMessage(this, MaplePacketCreator.cancelForeignChairSkillEffect(this.getId()), false);
}
@@ -7430,22 +7457,24 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
public void sitChair(int itemId) {
if (client.tryacquireClient()) {
try {
if (itemId >= 1000000) { // sit on item chair
if (chair.get() == 0) {
setChair(itemId);
getMap().broadcastMessage(this, MaplePacketCreator.showChair(this.getId(), itemId), false);
}
announce(MaplePacketCreator.enableActions());
} else if (itemId != 0) { // sit on map chair
if (chair.get() == 0) {
setChair(itemId);
if (registerChairBuff()) {
getMap().broadcastMessage(this, MaplePacketCreator.giveForeignChairSkillEffect(this.getId()), false);
if (this.isLoggedinWorld()) {
if (itemId >= 1000000) { // sit on item chair
if (chair.get() < 0) {
setChair(itemId);
getMap().broadcastMessage(this, MaplePacketCreator.showChair(this.getId(), itemId), false);
}
announce(MaplePacketCreator.cancelChair(itemId));
announce(MaplePacketCreator.enableActions());
} else if (itemId >= 0) { // sit on map chair
if (chair.get() < 0) {
setChair(itemId);
if (registerChairBuff()) {
getMap().broadcastMessage(this, MaplePacketCreator.giveForeignChairSkillEffect(this.getId()), false);
}
announce(MaplePacketCreator.cancelChair(itemId));
}
} else { // stand up
unsitChairInternal();
}
} else { // stand up
unsitChairInternal();
}
} finally {
client.releaseClient();
@@ -8955,6 +8984,18 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
public void setName(String name) {
this.name = name;
}
public void setRPS(MapleRockPaperScissor rps) {
this.rps = rps;
}
public void closeRPS() {
MapleRockPaperScissor rps = this.rps;
if (rps != null) {
rps.dispose(client);
setRPS(null);
}
}
public void changeName(String name) {
FredrickProcessor.removeFredrickReminders(this.getId());
+9
View File
@@ -27,6 +27,7 @@ import client.MapleClient;
public abstract class Command {
protected int rank;
protected String description;
public abstract void execute(MapleClient client, String[] params);
@@ -38,6 +39,14 @@ public abstract class Command {
protected void setDescription(String description) {
this.description = description;
}
public int getRank() {
return rank;
}
public void setRank(int rank) {
this.rank = rank;
}
protected String joinStringFrom(String arr[], int start) {
StringBuilder builder = new StringBuilder();
+18 -17
View File
@@ -62,7 +62,7 @@ public class CommandsExecutor {
return heading == USER_HEADING;
}
private HashMap<String, RegisteredCommand> registeredCommands = new HashMap<>();
private HashMap<String, Command> registeredCommands = new HashMap<>();
private Pair<List<String>, List<String>> levelCommandsCursor;
private List<Pair<List<String>, List<String>>> commandsNameDesc = new ArrayList<>();
@@ -94,7 +94,7 @@ public class CommandsExecutor {
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.");
client.getPlayer().yellowMessage("You do not have permission to use commands while in jail.");
return;
}
final String splitRegex = "[ ]";
@@ -107,13 +107,13 @@ public class CommandsExecutor {
final String commandName = splitedMessage[0].toLowerCase();
final String[] lowercaseParams = splitedMessage[1].toLowerCase().split(splitRegex);
final RegisteredCommand command = registeredCommands.get(commandName);
final Command command = registeredCommands.get(commandName);
if (command == null){
client.getPlayer().yellowMessage("Command '" + commandName + "' is not available. See @commands for a list of available commands.");
return;
}
if (client.getPlayer().gmLevel() < command.getRank()){
client.getPlayer().yellowMessage("You not have permission to use this command.");
client.getPlayer().yellowMessage("You do not have permission to use this command.");
return;
}
String[] params;
@@ -122,16 +122,9 @@ public class CommandsExecutor {
} else {
params = new String[]{};
}
try {
Command commandInstance = command.getCommandClass().newInstance();
commandInstance.execute(client, params);
writeLog(client, message);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
command.execute(client, params);
writeLog(client, message);
}
private void writeLog(MapleClient client, String command){
@@ -172,11 +165,19 @@ public class CommandsExecutor {
return;
}
RegisteredCommand registeredCommand = new RegisteredCommand(commandClass, rank);
String commandName = syntax.toLowerCase();
addCommandInfo(commandName, commandClass);
registeredCommands.put(commandName, registeredCommand);
try {
Command commandInstance = commandClass.newInstance(); // thanks Halcyon for noticing commands getting reinstanced every call
commandInstance.setRank(rank);
registeredCommands.put(commandName, commandInstance);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
private void registerLv0Commands(){
@@ -27,6 +27,7 @@ import client.command.Command;
import client.MapleCharacter;
import client.MapleClient;
import constants.ServerConstants;
import server.maps.MapleMap;
public class MapOwnerClaimCommand extends Command {
{
@@ -41,12 +42,20 @@ public class MapOwnerClaimCommand extends Command {
if (ServerConstants.USE_MAP_OWNERSHIP_SYSTEM) {
if (chr.getEventInstance() == null) {
if (chr.getMap().unclaimOwnership(chr)) {
chr.dropMessage(5, "This lawn is now free real estate.");
} else if (chr.getMap().claimOwnership(chr)) {
MapleMap ownedMap = chr.getOwnedMap(); // thanks Conrad for suggesting not unlease a map as soon as player exits it
if (ownedMap != null) {
ownedMap.unclaimOwnership(chr);
if (chr.getMap() == ownedMap) {
chr.dropMessage(5, "This lawn is now free real estate.");
return;
}
}
if (chr.getMap().claimOwnership(chr)) {
chr.dropMessage(5, "You have leased this lawn for a while, until you leave here or after 1 minute of inactivity.");
} else {
chr.dropMessage(5, "This lawn has already been leased by another player.");
chr.dropMessage(5, "This lawn has already been leased by a player.");
}
} else {
chr.dropMessage(5, "This lawn cannot be leased.");
@@ -105,7 +105,7 @@ public class GotoCommand extends Command {
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 {
gotomaps = new HashMap<>(GameConstants.GOTO_TOWNS);
gotomaps = GameConstants.GOTO_TOWNS;
}
if (gotomaps.containsKey(params[0])) {
@@ -55,7 +55,7 @@ public class IdCommand extends Command {
}
sb.append(String.format("Results found: #r%d#k | Returned: #b%d#k/100 | Refine search query to improve time.", resultList.size(), count) + "\r\n");
player.getClient().getAbstractPlayerInteraction().npcTalk(9010000, sb.toString());
player.getAbstractPlayerInteraction().npcTalk(9010000, sb.toString());
} else {
player.yellowMessage(String.format("Id not found for item: %s, of type: %s.", queryItem, params[0]));
}
@@ -26,7 +26,6 @@ package client.command.commands.gm3;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
import server.quest.MapleQuest;
public class QuestCompleteCommand extends Command {
{
@@ -45,14 +44,8 @@ public class QuestCompleteCommand extends Command {
int questId = Integer.parseInt(params[0]);
if (player.getQuestStatus(questId) == 1) {
MapleQuest quest = MapleQuest.getInstance(questId);
if (quest != null) {
int npcid = quest.getNpcRequirement(true);
quest.forceComplete(player, npcid);
player.dropMessage(5, "QUEST " + questId + " completed.");
} else { // should not occur
player.dropMessage(5, "QUESTID " + questId + " is invalid.");
}
c.getAbstractPlayerInteraction().forceCompleteQuest(questId);
player.dropMessage(5, "QUEST " + questId + " completed.");
} else {
player.dropMessage(5, "QUESTID " + questId + " not started or already completed.");
}
@@ -26,7 +26,6 @@ package client.command.commands.gm3;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
import server.quest.MapleQuest;
public class QuestStartCommand extends Command {
{
@@ -45,14 +44,8 @@ public class QuestStartCommand extends Command {
int questid = Integer.parseInt(params[0]);
if (player.getQuestStatus(questid) == 0) {
MapleQuest quest = MapleQuest.getInstance(questid);
if (quest != null) {
int npcid = quest.getNpcRequirement(false);
quest.forceStart(player, npcid);
player.dropMessage(5, "QUEST " + questid + " started.");
} else {
player.dropMessage(5, "QUESTID " + questid + " is invalid.");
}
c.getAbstractPlayerInteraction().forceStartQuest(questid);
player.dropMessage(5, "QUEST " + questid + " started.");
} else {
player.dropMessage(5, "QUESTID " + questid + " already started/completed.");
}
@@ -34,7 +34,6 @@ import server.life.SpawnPoint;
import server.maps.MapleMapObject;
import server.maps.MapleMapObjectType;
import server.maps.MapleReactor;
import tools.MaplePacketCreator;
import java.awt.*;
import java.util.Arrays;
+40 -16
View File
@@ -112,10 +112,14 @@ public class DueyProcessor {
return null;
}
private static String getCurrentDate() {
private static String getCurrentDate(boolean quick) {
String date = "";
Calendar cal = Calendar.getInstance();
int day = cal.get(Calendar.DATE) - 1; // instant duey ?
if (!quick) {
cal.add(Calendar.DATE, 1);
}
int day = cal.get(Calendar.DATE);
int month = cal.get(Calendar.MONTH) + 1; // its an array of months.
int year = cal.get(Calendar.YEAR);
date += day <= 9 ? "0" + day + "-" : "" + day + "-";
@@ -132,7 +136,7 @@ public class DueyProcessor {
ResultSet rs = null;
try {
con = DatabaseConnection.getConnection();
ps = con.prepareStatement("SELECT Mesos FROM dueypackages WHERE ReceiverId = ? and Checked = 1");
ps = con.prepareStatement("SELECT SenderName, Type FROM dueypackages WHERE ReceiverId = ? AND Checked = 1 ORDER BY Type DESC");
ps.setInt(1, player.getId());
rs = ps.executeQuery();
if (rs.next()) {
@@ -143,11 +147,11 @@ public class DueyProcessor {
pss.executeUpdate();
pss.close();
con2.close();
c.announce(MaplePacketCreator.sendDueyParcelReceived(rs.getString("SenderName"), rs.getInt("Type") == 1));
} catch (SQLException e) {
e.printStackTrace();
}
c.announce(MaplePacketCreator.sendDueyNotification(false));
}
} catch (SQLException e) {
e.printStackTrace();
@@ -241,7 +245,7 @@ public class DueyProcessor {
return packages;
}
private static int createPackage(int mesos, String message, String sender, int toCid) {
private static int createPackage(int mesos, String message, String sender, int toCid, boolean quick) {
try {
Connection con = null;
PreparedStatement ps = null;
@@ -249,16 +253,17 @@ public class DueyProcessor {
try {
con = DatabaseConnection.getConnection();
ps = con.prepareStatement("INSERT INTO `dueypackages` (ReceiverId, SenderName, Mesos, TimeStamp, Message, Checked) VALUES (?, ?, ?, ?, ?, 1)", Statement.RETURN_GENERATED_KEYS);
ps = con.prepareStatement("INSERT INTO `dueypackages` (ReceiverId, SenderName, Mesos, TimeStamp, Message, Type, 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(4, getCurrentDate(quick));
ps.setString(5, message);
ps.setInt(6, quick ? 1 : 0);
int updateRows = ps.executeUpdate();
if (updateRows < 1) {
FilePrinter.printError(FilePrinter.INSERT_CHAR, "Error trying to create package [mesos: " + mesos + ", " + sender + ", to CharacterId: " + toCid + "]");
FilePrinter.printError(FilePrinter.INSERT_CHAR, "Error trying to create package [mesos: " + mesos + ", " + sender + ", quick: " + quick + ", to CharacterId: " + toCid + "]");
return -1;
}
@@ -267,7 +272,7 @@ public class DueyProcessor {
if (rs.next()) {
packageId = rs.getInt(1);
} else {
FilePrinter.printError(FilePrinter.INSERT_CHAR, "Failed inserting package [mesos: " + mesos + ", " + sender + ", to CharacterId: " + toCid + "]");
FilePrinter.printError(FilePrinter.INSERT_CHAR, "Failed inserting package [mesos: " + mesos + ", " + sender + ", quick: " + quick + ", to CharacterId: " + toCid + "]");
return -1;
}
@@ -348,10 +353,18 @@ public class DueyProcessor {
return 0;
}
public static void dueySendItem(MapleClient c, byte invTypeId, short itemPos, short amount, int sendMesos, String sendMessage, String recipient) {
public static void dueySendItem(MapleClient c, byte invTypeId, short itemPos, short amount, int sendMesos, String sendMessage, String recipient, boolean quick) {
if (c.tryacquireClient()) {
try {
final int fee = 5000 + MapleTrade.getFee(sendMesos);
int fee = MapleTrade.getFee(sendMesos);
if (!quick) {
fee += 5000;
} else if (!c.getPlayer().haveItem(5330000)) {
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit with Quick Delivery on duey.");
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to use duey with Quick Delivery, mesos " + sendMesos + " and amount " + amount);
c.disconnect(true, false);
return;
}
long finalcost = (long) sendMesos + fee;
if (finalcost < 0 || finalcost > Integer.MAX_VALUE || (amount < 1 && sendMesos == 0)) {
@@ -385,7 +398,11 @@ public class DueyProcessor {
return;
}
int packageId = createPackage(sendMesos, sendMessage, c.getPlayer().getName(), recipientCid);
if (quick) {
MapleInventoryManipulator.removeById(c, MapleInventoryType.CASH, 5330000, (short) 1, false, false);
}
int packageId = createPackage(sendMesos, sendMessage, c.getPlayer().getName(), recipientCid, quick);
if (packageId == -1) {
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_ENABLE_ACTIONS.getCode()));
return;
@@ -490,10 +507,17 @@ public class DueyProcessor {
}
}
public static void dueySendTalk(MapleClient c) {
public static void dueySendTalk(MapleClient c, boolean quickDelivery) {
if (c.tryacquireClient()) {
try {
c.announce(MaplePacketCreator.sendDuey((byte) 8, loadPackages(c.getPlayer())));
long timeNow = System.currentTimeMillis();
if(timeNow - c.getPlayer().getNpcCooldown() < ServerConstants.BLOCK_NPC_RACE_CONDT) {
c.announce(MaplePacketCreator.enableActions());
return;
}
c.getPlayer().setNpcCooldown(timeNow);
c.announce(MaplePacketCreator.sendDuey(quickDelivery ? 0x1A : 0x8, loadPackages(c.getPlayer())));
} finally {
c.releaseClient();
}
@@ -501,7 +525,7 @@ public class DueyProcessor {
}
public static void dueyCreatePackage(Item item, int mesos, String sender, int recipientCid) {
int packageId = createPackage(mesos, "", sender, recipientCid);
int packageId = createPackage(mesos, "", sender, recipientCid, false);
if (packageId != -1) {
insertPackageItem(packageId, item);
}
+89 -51
View File
@@ -33,6 +33,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import server.MakerItemFactory;
import server.MakerItemFactory.MakerItemCreateEntry;
import server.MapleItemInformationProvider;
import tools.FilePrinter;
import tools.MaplePacketCreator;
@@ -44,6 +45,7 @@ import tools.data.input.SeekableLittleEndianAccessor;
* @author Ronan
*/
public class MakerProcessor {
private static MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
public static void makerAction(SeekableLittleEndianAccessor slea, MapleClient c) {
@@ -54,7 +56,7 @@ public class MakerProcessor {
int toDisassemble = -1, pos = -1;
boolean makerSucceeded = true;
MakerItemFactory.MakerItemCreateEntry recipe;
MakerItemCreateEntry recipe;
Map<Integer, Short> reagentids = new LinkedHashMap<>();
int stimulantid = -1;
@@ -62,29 +64,31 @@ public class MakerProcessor {
int fromLeftover = toCreate;
toCreate = ii.getMakerCrystalFromLeftover(toCreate);
if(toCreate == -1) {
c.announce(MaplePacketCreator.serverNotice(1, ii.getName(toCreate) + " is unavailable for Monster Crystal conversion."));
c.announce(MaplePacketCreator.serverNotice(1, ii.getName(fromLeftover) + " is unavailable for Monster Crystal conversion."));
c.announce(MaplePacketCreator.makerEnableActions());
return;
}
recipe = MakerItemFactory.generateLeftoverCrystalEntry(fromLeftover);
recipe = MakerItemFactory.generateLeftoverCrystalEntry(fromLeftover, toCreate);
} else if(type == 4) { // disassembling
slea.readInt(); // 1... probably inventory type
pos = slea.readInt();
Item it = c.getPlayer().getInventory(MapleInventoryType.EQUIP).getItem((short) pos);
if(it != null && it.getItemId() == toCreate) {
Pair<Integer, Integer> p;
if((p = generateDisassemblyInfo(toCreate)) != null) {
recipe = MakerItemFactory.generateDisassemblyCrystalEntry(p.getLeft(), p.getRight());
toDisassemble = toCreate;
toCreate = ii.getMakerCrystalFromEquip(toCreate);
toDisassemble = toCreate;
Pair<Integer, List<Pair<Integer, Integer>>> p = generateDisassemblyInfo(toDisassemble);
if(p != null) {
recipe = MakerItemFactory.generateDisassemblyCrystalEntry(toDisassemble, p.getLeft(), p.getRight());
} else {
c.announce(MaplePacketCreator.serverNotice(1, ii.getName(toCreate) + " is unavailable for Monster Crystal disassembly."));
c.announce(MaplePacketCreator.makerEnableActions());
return;
}
} else {
c.announce(MaplePacketCreator.serverNotice(1, "An unknown error occurred when trying to apply that item for disassembly."));
c.announce(MaplePacketCreator.makerEnableActions());
return;
}
} else {
@@ -132,6 +136,7 @@ public class MakerProcessor {
if(!reagentids.isEmpty()) {
if(!removeOddMakerReagents(toCreate, reagentids)) {
c.announce(MaplePacketCreator.serverNotice(1, "You can only use WATK and MATK Strengthening Gems on weapon items."));
c.announce(MaplePacketCreator.makerEnableActions());
return;
}
}
@@ -146,65 +151,80 @@ public class MakerProcessor {
case -1:// non-available for Maker itemid has been tried to forge
FilePrinter.printError(FilePrinter.EXPLOITS, "Player " + c.getPlayer().getName() + " tried to craft itemid " + toCreate + " using the Maker skill.");
c.announce(MaplePacketCreator.serverNotice(1, "The requested item could not be crafted on this operation."));
c.announce(MaplePacketCreator.makerEnableActions());
break;
case 1: // no items
c.announce(MaplePacketCreator.serverNotice(1, "You don't have all required items in your inventory to make " + recipe.getRewardAmount() + " " + ii.getName(toCreate) + "."));
c.announce(MaplePacketCreator.serverNotice(1, "You don't have all required items in your inventory to make " + ii.getName(toCreate) + "."));
c.announce(MaplePacketCreator.makerEnableActions());
break;
case 2: // no meso
c.announce(MaplePacketCreator.serverNotice(1, "You don't have enough mesos (" + GameConstants.numberWithCommas(recipe.getCost()) + ") to complete this operation."));
c.announce(MaplePacketCreator.makerEnableActions());
break;
case 3: // no req level
c.announce(MaplePacketCreator.serverNotice(1, "You don't have enough level to complete this operation."));
c.announce(MaplePacketCreator.makerEnableActions());
break;
case 4: // no req skill level
c.announce(MaplePacketCreator.serverNotice(1, "You don't have enough Maker level to complete this operation."));
c.announce(MaplePacketCreator.makerEnableActions());
break;
case 5: // inventory full
c.announce(MaplePacketCreator.serverNotice(1, "Your inventory is full."));
c.announce(MaplePacketCreator.makerEnableActions());
break;
default:
if (MapleInventoryManipulator.checkSpace(c, toCreate, (short) recipe.getRewardAmount(), "")) {
if(toDisassemble != -1) {
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.EQUIP, (short) pos, (short) 1, false);
} else {
for (Pair<Integer, Integer> p : recipe.getReqItems()) {
c.getAbstractPlayerInteraction().gainItem(p.getLeft(), (short) -p.getRight());
c.getAbstractPlayerInteraction().gainItem(p.getLeft(), (short) -p.getRight(), false);
}
}
if(toDisassemble != -1) {
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.EQUIP, (short) pos, (short) 1, false);
c.announce(MaplePacketCreator.getShowItemGain(toDisassemble, (short) -1, true));
}
int cost = recipe.getCost();
if(stimulantid == -1 && reagentids.isEmpty()) {
if(cost > 0) c.getPlayer().gainMeso(-cost);
int cost = recipe.getCost();
if(stimulantid == -1 && reagentids.isEmpty()) {
if(cost > 0) c.getPlayer().gainMeso(-cost, false);
for (Pair<Integer, Integer> p : recipe.getGainItems()) {
c.getPlayer().setCS(true);
c.getAbstractPlayerInteraction().gainItem(toCreate, (short) recipe.getRewardAmount());
c.getAbstractPlayerInteraction().gainItem(p.getLeft(), p.getRight().shortValue(), false);
c.getPlayer().setCS(false);
} else {
if(stimulantid != -1) c.getAbstractPlayerInteraction().gainItem(stimulantid, (short) -1);
if(!reagentids.isEmpty()) {
for(Map.Entry<Integer, Short> r : reagentids.entrySet()) {
c.getAbstractPlayerInteraction().gainItem(r.getKey(), (short) (-1 * r.getValue()));
}
}
if(cost > 0) c.getPlayer().gainMeso(-cost);
makerSucceeded = addBoostedMakerItem(c, toCreate, stimulantid, reagentids);
}
if(makerSucceeded) c.announce(MaplePacketCreator.serverNotice(1, "You have successfully created " + recipe.getRewardAmount() + " " + ii.getName(toCreate) + "."));
else c.getPlayer().dropMessage(5, "The Maker skill lights up, but the skill winds up as if nothing happened.");
c.announce(MaplePacketCreator.showMakerEffect(makerSucceeded));
c.getPlayer().getMap().broadcastMessage(c.getPlayer(), MaplePacketCreator.showForeignMakerEffect(c.getPlayer().getId(), makerSucceeded), false);
if(toCreate == 4260003 && type == 3 && c.getPlayer().getQuestStatus(6033) == 1) {
c.getAbstractPlayerInteraction().setQuestProgress(6033, 1);
}
} else {
c.announce(MaplePacketCreator.serverNotice(1, "Your inventory is full."));
toCreate = recipe.getGainItems().get(0).getLeft();
if(stimulantid != -1) c.getAbstractPlayerInteraction().gainItem(stimulantid, (short) -1, false);
if(!reagentids.isEmpty()) {
for(Map.Entry<Integer, Short> r : reagentids.entrySet()) {
c.getAbstractPlayerInteraction().gainItem(r.getKey(), (short) (-1 * r.getValue()), false);
}
}
if(cost > 0) c.getPlayer().gainMeso(-cost, false);
makerSucceeded = addBoostedMakerItem(c, toCreate, stimulantid, reagentids);
}
// thanks inhyuk for noticing missing MAKER_RESULT packets
if (type == 3) {
c.announce(MaplePacketCreator.makerResultCrystal(recipe.getGainItems().get(0).getLeft(), recipe.getReqItems().get(0).getLeft()));
} else if (type == 4) {
c.announce(MaplePacketCreator.makerResultDesynth(recipe.getReqItems().get(0).getLeft(), recipe.getCost(), recipe.getGainItems()));
} else {
c.announce(MaplePacketCreator.makerResult(makerSucceeded, recipe.getGainItems().get(0).getLeft(), recipe.getGainItems().get(0).getRight(), recipe.getCost(), recipe.getReqItems(), stimulantid, new LinkedList<>(reagentids.keySet())));
}
c.announce(MaplePacketCreator.showMakerEffect(makerSucceeded));
c.getPlayer().getMap().broadcastMessage(c.getPlayer(), MaplePacketCreator.showForeignMakerEffect(c.getPlayer().getId(), makerSucceeded), false);
if(toCreate == 4260003 && type == 3 && c.getPlayer().getQuestStatus(6033) == 1) {
c.getAbstractPlayerInteraction().setQuestProgress(6033, 1);
}
}
} finally {
@@ -271,12 +291,12 @@ public class MakerProcessor {
}
}
private static Pair<Integer, Integer> generateDisassemblyInfo(int itemId) {
private static Pair<Integer, List<Pair<Integer, Integer>>> generateDisassemblyInfo(int itemId) {
int recvFee = ii.getMakerDisassembledFee(itemId);
if(recvFee > -1) {
int recvQty = ii.getMakerDisassembledQuantity(itemId);
if(recvQty > 0) {
return new Pair<>(recvFee, recvQty);
List<Pair<Integer, Integer>> gains = ii.getMakerDisassembledItems(itemId);
if(!gains.isEmpty()) {
return new Pair<>(recvFee, gains);
}
}
@@ -287,7 +307,7 @@ public class MakerProcessor {
return chr.getSkillLevel((chr.getJob().getId() / 1000) * 10000000 + 1007);
}
private static short getCreateStatus(MapleClient c, MakerItemFactory.MakerItemCreateEntry recipe) {
private static short getCreateStatus(MapleClient c, MakerItemCreateEntry recipe) {
if(recipe == null) {
return -1;
}
@@ -308,10 +328,29 @@ public class MakerProcessor {
return 4;
}
List<Integer> addItemids = new LinkedList<>();
List<Integer> addQuantity = new LinkedList<>();
List<Integer> rmvItemids = new LinkedList<>();
List<Integer> rmvQuantity = new LinkedList<>();
for (Pair<Integer, Integer> p : recipe.getReqItems()) {
rmvItemids.add(p.getLeft());
rmvQuantity.add(p.getRight());
}
for (Pair<Integer, Integer> p : recipe.getGainItems()) {
addItemids.add(p.getLeft());
addQuantity.add(p.getRight());
}
if (!c.getAbstractPlayerInteraction().canHoldAllAfterRemoving(addItemids, addQuantity, rmvItemids, rmvQuantity)) {
return 5;
}
return 0;
}
private static boolean hasItems(MapleClient c, MakerItemFactory.MakerItemCreateEntry recipe) {
private static boolean hasItems(MapleClient c, MakerItemCreateEntry recipe) {
for (Pair<Integer, Integer> p : recipe.getReqItems()) {
int itemId = p.getLeft();
if (c.getPlayer().getInventory(ItemConstants.getInventoryType(itemId)).countById(itemId) < p.getRight()) {
@@ -397,7 +436,6 @@ public class MakerProcessor {
}
MapleInventoryManipulator.addFromDrop(c, item, false, -1);
c.announce(MaplePacketCreator.getShowItemGain(itemid, (short) 1, true));
return true;
}
}
+8
View File
@@ -247,4 +247,12 @@ public final class ItemConstants {
public static boolean isHair(int itemId) {
return itemId >= 30000 && itemId < 35000;
}
public static boolean isFaceExpression(int itemId) {
return itemId / 10000 == 516;
}
public static boolean isChair(int itemId) {
return itemId / 10000 == 301;
}
}
@@ -17,6 +17,7 @@ public class ScriptableNPCConstants {
public static final Set<Pair<Integer, String>> SCRIPTABLE_NPCS = new HashSet<Pair<Integer, String>>(){{
add(new Pair<>(9200000, "Cody"));
add(new Pair<>(9001105, "Grandpa Moon Bunny"));
}};
}
+2 -2
View File
@@ -94,7 +94,7 @@ public class ServerConstants {
public static final boolean USE_ENFORCE_JOB_LEVEL_RANGE = false;//Caps the player level on the minimum required to advance their current jobs.
public static final boolean USE_ENFORCE_JOB_SP_RANGE = false; //Caps the player SP level on the total obtainable by their current jobs. After changing jobs, missing SP will be retrieved.
public static final boolean USE_ENFORCE_ITEM_SUGGESTION = false;//Forces the Owl of Minerva and the Cash Shop to always display the defined item array instead of those featured by the players.
public static final boolean USE_ENFORCE_UNMERCHABLE_CASH = false;//Forces players to not sell CASH items via merchants.
public static final boolean USE_ENFORCE_UNMERCHABLE_CASH = true;//Forces players to not sell CASH items via merchants.
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_MDOOR_POSITION = false; //Forces mystic door to be spawned near spawnpoints.
@@ -112,7 +112,7 @@ public class ServerConstants {
public static final boolean USE_ENABLE_CHAT_LOG = false; //Write in-game chat to log
public static final boolean USE_REBIRTH_SYSTEM = false; //Flag to enable/disable rebirth system
public static final boolean USE_MAP_OWNERSHIP_SYSTEM = true; //Flag to enable/disable map ownership system
public static final boolean USE_FISHING_SYSTEM = true; //Flag to enable/disable fishing system
public static final boolean USE_FISHING_SYSTEM = true; //Flag to enable/disable custom fishing system
public static final boolean USE_NPCS_SCRIPTABLE = true; //Flag to enable/disable serverside predefined script NPCs.
//Events/PQs Configuration
+1
View File
@@ -163,6 +163,7 @@ public final class PacketProcessor {
registerHandler(RecvOpcode.CANCEL_BUFF, new CancelBuffHandler());
registerHandler(RecvOpcode.CANCEL_ITEM_EFFECT, new CancelItemEffectHandler());
registerHandler(RecvOpcode.PLAYER_INTERACTION, new PlayerInteractionHandler());
registerHandler(RecvOpcode.RPS_ACTION, new RPSActionHandler());
registerHandler(RecvOpcode.DISTRIBUTE_AP, new DistributeAPHandler());
registerHandler(RecvOpcode.DISTRIBUTE_SP, new DistributeSPHandler());
registerHandler(RecvOpcode.CHANGE_KEYMAP, new KeymapChangeHandler());
+1
View File
@@ -239,6 +239,7 @@ public enum SendOpcode {
MESO_BAG_MESSAGE(0xD2),
UPDATE_QUEST_INFO(0xD3),
PLAYER_HINT(0xD6),
MAKER_RESULT(0xD9),
KOREAN_EVENT(0xDB),
OPEN_UI(0xDC),
LOCK_UI(0xDD),
+16
View File
@@ -57,6 +57,7 @@ import net.server.channel.Channel;
import net.server.guild.MapleAlliance;
import net.server.guild.MapleGuild;
import net.server.guild.MapleGuildCharacter;
import net.server.worker.BossLogWorker;
import net.server.worker.CharacterDiseaseWorker;
import net.server.worker.CouponWorker;
import net.server.worker.EventRecallCoordinatorWorker;
@@ -96,6 +97,7 @@ import server.CashShop.CashItemFactory;
import server.MapleSkillbookInformationProvider;
import server.ThreadManager;
import server.TimerManager;
import server.expeditions.MapleExpeditionBossLog;
import server.life.MaplePlayerNPCFactory;
import server.quest.MapleQuest;
import tools.AutoJCE;
@@ -527,6 +529,16 @@ public class Server {
return Math.max(0, nextHour.getTimeInMillis() - System.currentTimeMillis());
}
private static long getTimeLeftForNextDay() {
Calendar nextDay = Calendar.getInstance();
nextDay.add(Calendar.DAY_OF_MONTH, 1);
nextDay.set(Calendar.HOUR, 0);
nextDay.set(Calendar.MINUTE, 0);
nextDay.set(Calendar.SECOND, 0);
return Math.max(0, nextDay.getTimeInMillis() - System.currentTimeMillis());
}
public Map<Integer, Integer> getCouponRates() {
return couponRates;
}
@@ -895,6 +907,10 @@ public class Server {
tMan.register(new FredrickWorker(), 60 * 60 * 1000, 60 * 60 * 1000);
tMan.register(new InvitationWorker(), 30 * 1000, 30 * 1000);
timeLeft = getTimeLeftForNextDay();
MapleExpeditionBossLog.resetBossLogTable();
tMan.register(new BossLogWorker(), 24 * 60 * 60 * 1000, timeLeft);
long timeToTake = System.currentTimeMillis();
SkillFactory.loadAllSkills();
System.out.println("Skills loaded in " + ((System.currentTimeMillis() - timeToTake) / 1000.0) + " seconds");
+4 -4
View File
@@ -199,12 +199,12 @@ public final class Channel {
disconnectAwayPlayers();
players.disconnectAll();
mapManager.dispose();
mapManager = null;
eventSM.cancel();
eventSM = null;
mapManager.dispose();
mapManager = null;
closeChannelSchedules();
players = null;
@@ -683,7 +683,7 @@ public final class Channel {
if(dungeons.containsKey(dungeonid)) return false;
MapleMiniDungeonInfo mmdi = MapleMiniDungeonInfo.getDungeon(dungeonid);
MapleMiniDungeon mmd = new MapleMiniDungeon(mmdi.getBase(), 30); // all minidungeons timeout on 30 mins
MapleMiniDungeon mmd = new MapleMiniDungeon(mmdi.getBase(), this.getMapFactory().getMap(mmdi.getDungeonId()).getTimeLimit()); // thanks Conrad for noticing hardcoded time limit for minidungeons
dungeons.put(dungeonid, mmd);
return true;
@@ -32,8 +32,11 @@ public final class CancelChairHandler extends AbstractMaplePacketHandler {
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
int id = slea.readShort();
MapleCharacter mc = c.getPlayer();
if(!mc.isLoggedinWorld()) return;
mc.sitChair(id == -1 ? 0 : id);
if (id >= mc.getMap().getSeats()) {
return;
}
mc.sitChair(id);
}
}
@@ -45,8 +45,9 @@ public final class DueyHandler extends AbstractMaplePacketHandler {
short amount = slea.readShort();
int mesos = slea.readInt();
String recipient = slea.readMapleAsciiString();
String message = slea.readByte() != 0 ? slea.readMapleAsciiString() : "";
DueyProcessor.dueySendItem(c, inventId, itemPos, amount, mesos, message, recipient);
boolean quick = slea.readByte() != 0;
String message = quick ? slea.readMapleAsciiString() : "";
DueyProcessor.dueySendItem(c, inventId, itemPos, amount, mesos, message, recipient, quick);
} else if (operation == DueyProcessor.Actions.TOSERVER_REMOVE_PACKAGE.getCode()) {
int packageid = slea.readInt();
@@ -55,6 +56,8 @@ public final class DueyHandler extends AbstractMaplePacketHandler {
int packageid = slea.readInt();
DueyProcessor.dueyClaimPackage(c, packageid);
} else if (operation == DueyProcessor.Actions.TOSERVER_CLAIM_PACKAGE.getCode()) {
DueyProcessor.dueySendTalk(c, false);
}
}
}
@@ -34,15 +34,17 @@ public final class FaceExpressionHandler extends AbstractMaplePacketHandler {
int emote = slea.readInt();
if (emote > 7) {
int emoteid = 5159992 + emote;
if (chr.getInventory(ItemConstants.getInventoryType(emoteid)).findById(emoteid) == null) {
int itemid = 5159992 + emote; // thanks Rajan (Darter) for reporting unchecked emote itemid
if (!ItemConstants.isFaceExpression(itemid) || chr.getInventory(ItemConstants.getInventoryType(itemid)).findById(itemid) == null) {
return;
}
} else if (emote < 1) {
return;
}
if(c.tryacquireClient()) {
try { // expecting players never intends to wear the emote 0 (default face, that changes back after 5sec timeout)
if (emote != 0 && chr.isLoggedinWorld()) {
if (chr.isLoggedinWorld()) {
chr.changeFaceExpression(emote);
}
} finally {
@@ -72,8 +72,15 @@ public final class MobDamageMobFriendlyHandler extends AbstractMaplePacketHandle
map.addBunnyHit();
}
}
monster.applyAndGetHpDamage(damage, false);
int remainingHp = monster.getHp();
if(remainingHp <= 0) {
remainingHp = 0;
monster.getMap().removeMapObject(monster);
}
c.getPlayer().getMap().broadcastMessage(MaplePacketCreator.MobDamageMobFriendly(monster, damage), monster.getPosition());
c.getPlayer().getMap().broadcastMessage(MaplePacketCreator.MobDamageMobFriendly(monster, damage, remainingHp), monster.getPosition());
c.announce(MaplePacketCreator.enableActions());
}
}
@@ -21,16 +21,24 @@
*/
package net.server.channel.handlers;
import java.util.Map;
import client.MapleClient;
import client.MapleCharacter;
import client.autoban.AutobanFactory;
import client.status.MonsterStatus;
import client.status.MonsterStatusEffect;
import net.AbstractMaplePacketHandler;
import server.life.MapleMonster;
import server.life.MapleMonsterInformationProvider;
import server.maps.MapleMap;
import tools.FilePrinter;
import tools.MaplePacketCreator;
import tools.data.input.SeekableLittleEndianAccessor;
/**
*
* @author Jay Estrella
* @author Ronan
*/
public final class MobDamageMobHandler extends AbstractMaplePacketHandler {
@Override
@@ -38,14 +46,69 @@ public final class MobDamageMobHandler extends AbstractMaplePacketHandler {
int from = slea.readInt();
slea.readInt();
int to = slea.readInt();
slea.readByte();
boolean magic = slea.readByte() == 0;
int dmg = slea.readInt();
MapleCharacter chr = c.getPlayer();
MapleMap map = chr.getMap();
if (map.getMonsterByOid(from) != null && map.getMonsterByOid(to) != null) {
map.damageMonster(chr, map.getMonsterByOid(to), dmg);
map.broadcastMessage(MaplePacketCreator.damageMonster(to, dmg));
MapleMonster attacker = map.getMonsterByOid(from);
MapleMonster damaged = map.getMonsterByOid(to);
if (attacker != null && damaged != null) {
int maxDmg = calcMaxDamage(attacker, damaged, magic); // thanks Darter (YungMoozi) for reporting unchecked dmg
if (dmg > maxDmg) {
AutobanFactory.DAMAGE_HACK.alert(c.getPlayer(), "Possible packet editing hypnotize damage exploit."); // thanks Rien dev team
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " had hypnotized " + MapleMonsterInformationProvider.getInstance().getMobNameFromId(attacker.getId()) + " to attack " + MapleMonsterInformationProvider.getInstance().getMobNameFromId(damaged.getId()) + " with damage " + dmg + " (max: " + maxDmg + ")");
dmg = maxDmg;
}
map.damageMonster(chr, damaged, dmg);
map.broadcastMessage(chr, MaplePacketCreator.damageMonster(to, dmg), false);
}
}
private static int calcMaxDamage(MapleMonster attacker, MapleMonster damaged, boolean magic) {
int attackerAtk, damagedDef, attackerLevel = attacker.getLevel();
double maxDamage;
if (magic) {
int atkRate = calcModifier(attacker, MonsterStatus.MAGIC_ATTACK_UP, MonsterStatus.MATK);
attackerAtk = (attacker.getStats().getMADamage() * atkRate) / 100;
int defRate = calcModifier(damaged, MonsterStatus.MAGIC_DEFENSE_UP, MonsterStatus.MDEF);
damagedDef = (damaged.getStats().getMDDamage() * defRate) / 100;
maxDamage = ((attackerAtk * (1.15 + (0.025 * attackerLevel))) - (0.75 * damagedDef)) * (Math.log(Math.abs(damagedDef - attackerAtk)) / Math.log(12));
} else {
int atkRate = calcModifier(attacker, MonsterStatus.WEAPON_ATTACK_UP, MonsterStatus.WATK);
attackerAtk = (attacker.getStats().getPADamage() * atkRate) / 100;
int defRate = calcModifier(damaged, MonsterStatus.WEAPON_DEFENSE_UP, MonsterStatus.WDEF);
damagedDef = (damaged.getStats().getPDDamage() * defRate) / 100;
maxDamage = ((attackerAtk * (1.15 + (0.025 * attackerLevel))) - (0.75 * damagedDef)) * (Math.log(Math.abs(damagedDef - attackerAtk)) / Math.log(17));
}
return (int) maxDamage;
}
private static int calcModifier(MapleMonster monster, MonsterStatus buff, MonsterStatus nerf) {
int atkModifier;
final Map<MonsterStatus, MonsterStatusEffect> monsterStati = monster.getStati();
MonsterStatusEffect atkBuff = monsterStati.get(buff);
if (atkBuff != null) {
atkModifier = atkBuff.getStati().get(buff);
} else {
atkModifier = 100;
}
MonsterStatusEffect atkNerf = monsterStati.get(nerf);
if (atkNerf != null) {
atkModifier -= atkNerf.getStati().get(nerf);
}
return atkModifier;
}
}
@@ -53,8 +53,7 @@ public final class NPCTalkHandler extends AbstractMaplePacketHandler {
if(ServerConstants.USE_DEBUG == true) c.getPlayer().dropMessage(5, "Talking to NPC " + npc.getId());
if (npc.getId() == 9010009) { //is duey
c.getPlayer().setNpcCooldown(currentServerTime());
DueyProcessor.dueySendTalk(c);
DueyProcessor.dueySendTalk(c, false);
} else {
if (c.getCM() != null || c.getQM() != null) {
c.announce(MaplePacketCreator.enableActions());
@@ -424,22 +424,22 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
ResultSet rs = null;
try {
con = DatabaseConnection.getConnection();
ps = con.prepareStatement("SELECT Mesos FROM dueypackages WHERE ReceiverId = ? and Checked = 1");
ps = con.prepareStatement("SELECT Type FROM dueypackages WHERE ReceiverId = ? AND Checked = 1 ORDER BY Type DESC");
ps.setInt(1, player.getId());
rs = ps.executeQuery();
if (rs.next()) {
try {
Connection con2 = DatabaseConnection.getConnection();
pss = con2.prepareStatement("UPDATE dueypackages SET Checked = 0 where ReceiverId = ?");
pss = con2.prepareStatement("UPDATE dueypackages SET Checked = 0 WHERE ReceiverId = ?");
pss.setInt(1, player.getId());
pss.executeUpdate();
pss.close();
con2.close();
c.announce(MaplePacketCreator.sendDueyParcelNotification(rs.getInt("Type") == 1));
} catch (SQLException e) {
e.printStackTrace();
}
c.announce(MaplePacketCreator.sendDueyNotification(false));
}
} catch (SQLException e) {
e.printStackTrace();
@@ -38,13 +38,19 @@ public final class QuestActionHandler extends AbstractMaplePacketHandler {
// isNpcNearby credits to GabrielSin
private static boolean isNpcNearby(SeekableLittleEndianAccessor slea, MapleCharacter player, MapleQuest quest, int npcId) {
Point playerP = null;
Point playerP;
Point pos = player.getPosition();
if(slea.available() >= 4) {
playerP = new Point(slea.readShort(), slea.readShort());
if (playerP.distance(pos) > 1000) { // thanks Darter (YungMoozi) for reporting unchecked player position
playerP = pos;
}
} else {
playerP = pos;
}
if (playerP != null && !quest.isAutoStart() && !quest.isAutoComplete()) {
if (!quest.isAutoStart() && !quest.isAutoComplete()) {
MapleNPC npc = player.getMap().getNPCById(npcId);
if(npc == null) {
return false;
@@ -0,0 +1,71 @@
package net.server.channel.handlers;
import client.MapleCharacter;
import client.MapleClient;
import server.minigame.MapleRockPaperScissor;
import net.AbstractMaplePacketHandler;
import tools.MaplePacketCreator;
import tools.data.input.SeekableLittleEndianAccessor;
/**
* @Author Arnah
* @Website http://Vertisy.ca/
* @since Aug 15, 2016
*/
public final class RPSActionHandler extends AbstractMaplePacketHandler{
@Override
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c){
MapleCharacter chr = c.getPlayer();
MapleRockPaperScissor rps = chr.getRPS();
if (c.tryacquireClient()) {
try {
if(slea.available() == 0 || !chr.getMap().containsNPC(9000019)){
if(rps != null){
rps.dispose(c);
}
return;
}
final byte mode = slea.readByte();
switch (mode){
case 0: // start game
case 5: // retry
if(rps != null){
rps.reward(c);
}
if(chr.getMeso() >= 1000){
chr.setRPS(new MapleRockPaperScissor(c, mode));
}else{
c.announce(MaplePacketCreator.rpsMesoError(-1));
}
break;
case 1: // answer
if(rps == null || !rps.answer(c, slea.readByte())){
c.announce(MaplePacketCreator.rpsMode((byte) 0x0D));// 13
}
break;
case 2: // time over
if(rps == null || !rps.timeOut(c)){
c.announce(MaplePacketCreator.rpsMode((byte) 0x0D));
}
break;
case 3: // continue
if(rps == null || !rps.nextRound(c)){
c.announce(MaplePacketCreator.rpsMode((byte) 0x0D));
}
break;
case 4: // leave
if(rps != null){
rps.dispose(c);
}else{
c.announce(MaplePacketCreator.rpsMode((byte) 0x0D));
}
break;
}
} finally {
c.releaseClient();
}
}
}
}
@@ -78,17 +78,17 @@ public final class ScrollHandler extends AbstractMaplePacketHandler {
if (ItemConstants.isCleanSlate(scroll.getItemId())) {
Map<String, Integer> eqStats = ii.getEquipStats(toScroll.getItemId()); // clean slate issue found thanks to Masterrulax
if (eqStats == null || eqStats.get("tuc") == 0) {
c.announce(MaplePacketCreator.getInventoryFull());
announceCannotScroll(c, legendarySpirit);
return;
}
} else if (!ItemConstants.isModifierScroll(scroll.getItemId()) && ((Equip) toScroll).getUpgradeSlots() < 1) {
c.announce(MaplePacketCreator.getInventoryFull());
announceCannotScroll(c, legendarySpirit); // thanks onechord for noticing zero upgrade slots freezing Legendary Scroll UI
return;
}
List<Integer> scrollReqs = ii.getScrollReqs(scroll.getItemId());
if (scrollReqs.size() > 0 && !scrollReqs.contains(toScroll.getItemId())) {
c.announce(MaplePacketCreator.getInventoryFull());
announceCannotScroll(c, legendarySpirit);
return;
}
if (whiteScroll) {
@@ -100,11 +100,13 @@ public final class ScrollHandler extends AbstractMaplePacketHandler {
if (!ItemConstants.isChaosScroll(scroll.getItemId()) && !ItemConstants.isCleanSlate(scroll.getItemId())) {
if (!canScroll(scroll.getItemId(), toScroll.getItemId())) {
announceCannotScroll(c, legendarySpirit);
return;
}
}
if (ItemConstants.isCleanSlate(scroll.getItemId()) && !ii.canUseCleanSlate(toScroll)) {
announceCannotScroll(c, legendarySpirit);
return;
}
@@ -119,11 +121,13 @@ public final class ScrollHandler extends AbstractMaplePacketHandler {
useInventory.lockInventory();
try {
if (scroll.getQuantity() < 1) {
announceCannotScroll(c, legendarySpirit);
return;
}
if (whiteScroll && !ItemConstants.isCleanSlate(scroll.getItemId())) {
if (wscroll.getQuantity() < 1) {
announceCannotScroll(c, legendarySpirit);
return;
}
@@ -171,7 +175,7 @@ public final class ScrollHandler extends AbstractMaplePacketHandler {
mods.add(new ModifyInventory(0, scrolled));
}
c.announce(MaplePacketCreator.modifyInventory(true, mods));
chr.getMap().broadcastMessage(MaplePacketCreator.getScrollEffect(chr.getId(), scrollSuccess, legendarySpirit));
chr.getMap().broadcastMessage(MaplePacketCreator.getScrollEffect(chr.getId(), scrollSuccess, legendarySpirit, whiteScroll));
if (dst < 0 && (scrollSuccess == Equip.ScrollResult.SUCCESS || scrollSuccess == Equip.ScrollResult.CURSE)) {
chr.equipChanged();
}
@@ -180,6 +184,14 @@ public final class ScrollHandler extends AbstractMaplePacketHandler {
}
}
}
private static void announceCannotScroll(MapleClient c, boolean legendarySpirit) {
if (legendarySpirit) {
c.announce(MaplePacketCreator.getScrollEffect(c.getPlayer().getId(), Equip.ScrollResult.FAIL, false, false));
} else {
c.announce(MaplePacketCreator.getInventoryFull());
}
}
private static boolean canScroll(int scrollid, int itemid) {
int sid = scrollid / 100;
@@ -101,7 +101,8 @@ public final class SpecialMoveHandler extends AbstractMaplePacketHandler {
monster.aggroClearDamages();
monster.aggroMonsterDamage(chr, 1);
// thanks onechord for pointing out Magnet disconnecting the caster (issue would actually happen upon failing to catch mob)
// thanks onechord for pointing out Magnet crashing the caster (issue would actually happen upon failing to catch mob)
// thanks Conrad for noticing Magnet crashing when trying to pull bosses and fixed mobs
monster.aggroSwitchController(chr, true);
}
}
@@ -25,24 +25,32 @@ import client.MapleCharacter;
import client.MapleClient;
import client.Skill;
import client.SkillFactory;
import client.autoban.AutobanFactory;
import client.status.MonsterStatusEffect;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import server.MapleStatEffect;
import server.life.MapleMonster;
import server.life.MapleMonsterInformationProvider;
import server.maps.MapleSummon;
import tools.FilePrinter;
import tools.MaplePacketCreator;
import tools.data.input.SeekableLittleEndianAccessor;
public final class SummonDamageHandler extends AbstractDealDamageHandler {
public final class SummonAttackEntry {
private int monsterOid;
private int damage;
private boolean magic;
public SummonAttackEntry(int monsterOid, int damage) {
public SummonAttackEntry(int monsterOid, int damage, boolean magic) {
this.monsterOid = monsterOid;
this.damage = damage;
this.magic = magic;
}
public int getMonsterOid() {
@@ -52,6 +60,10 @@ public final class SummonDamageHandler extends AbstractDealDamageHandler {
public int getDamage() {
return damage;
}
public boolean isMagic() {
return magic;
}
}
@Override
@@ -79,18 +91,34 @@ public final class SummonDamageHandler extends AbstractDealDamageHandler {
slea.skip(8); //Thanks Gerald :D, I failed lol (mob x,y and summon x,y)
for (int x = 0; x < numAttacked; x++) {
int monsterOid = slea.readInt(); // attacked oid
slea.skip(18);
slea.skip(17);
boolean magic = slea.readByte() != 0;
int damage = slea.readInt();
allDamage.add(new SummonAttackEntry(monsterOid, damage));
allDamage.add(new SummonAttackEntry(monsterOid, damage, magic));
}
player.getMap().broadcastMessage(player, MaplePacketCreator.summonAttack(player.getId(), summon.getObjectId(), direction, allDamage), summon.getPosition());
if (player.getMap().isOwnershipRestricted(player)) {
return;
}
Map<Integer, Integer> maxDmgEntries = new HashMap<>();
for (SummonAttackEntry attackEntry : allDamage) {
int damage = attackEntry.getDamage();
MapleMonster target = player.getMap().getMonsterByOid(attackEntry.getMonsterOid());
if (target != null) {
Integer maxDmg = maxDmgEntries.get(attackEntry.getMonsterOid());
if (maxDmg == null) {
maxDmg = calcMaxDamage(summonEffect, player, attackEntry.isMagic()); // thanks Darter (YungMoozi) for reporting unchecked max dmg
maxDmgEntries.put(attackEntry.getMonsterOid(), maxDmg);
}
if (damage > maxDmg) {
AutobanFactory.DAMAGE_HACK.alert(c.getPlayer(), "Possible packet editing summon damage exploit.");
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " used a summon of skillid " + summon.getSkill() + " to attack " + MapleMonsterInformationProvider.getInstance().getMobNameFromId(target.getId()) + " with damage " + damage + " (max: " + maxDmg + ")");
damage = maxDmg;
}
if (damage > 0 && summonEffect.getMonsterStati().size() > 0) {
if (summonEffect.makeChanceResult()) {
target.applyStatus(player, new MonsterStatusEffect(summonEffect.getMonsterStati(), summonSkill, null, false), summonEffect.isPoison(), 4000);
@@ -100,4 +128,16 @@ public final class SummonDamageHandler extends AbstractDealDamageHandler {
}
}
}
}
private static int calcMaxDamage(MapleStatEffect summonEffect, MapleCharacter player, boolean magic) {
double maxDamage;
if (magic) {
maxDamage = player.calculateMaxBaseMagicDamage() * (0.05 * summonEffect.getMatk());
} else {
maxDamage = player.calculateMaxBaseDamage(player.getTotalWatk()) * (0.021 * summonEffect.getWatk());
}
return (int) maxDamage;
}
}
@@ -44,7 +44,6 @@ import java.util.List;
import net.AbstractMaplePacketHandler;
import client.inventory.manipulator.MapleInventoryManipulator;
import server.MapleStatEffect;
import server.life.MapleLifeFactory;
import server.life.MapleLifeFactory.loseItem;
import server.life.MapleMonster;
import server.life.MobAttackInfo;
@@ -88,16 +87,6 @@ public final class TakeDamageHandler extends AbstractMaplePacketHandler {
}
}
if (monsteridfrom == 9300166 && attacker == null) {
if (c.tryacquireClient()) {
try {
attacker = MapleLifeFactory.getMonster(monsteridfrom);
} finally {
c.releaseClient();
}
}
}
if (attacker != null) {
if (attacker.isBuffed(MonsterStatus.NEUTRALISE)) {
return;
@@ -149,7 +138,7 @@ public final class TakeDamageHandler extends AbstractMaplePacketHandler {
map.removeMapObject(attacker);
}
}
} else {
} else if (damagefrom != 0 || !map.removeSelfDestructive(oid)) { // thanks inhyuk for noticing self-destruct damage not being handled properly
return;
}
} catch(ClassCastException e) {
@@ -196,21 +185,23 @@ public final class TakeDamageHandler extends AbstractMaplePacketHandler {
}
}
}
if (damage == -1) {
fake = 4020002 + (chr.getJob().getId() / 10 - 40) * 100000;
}
if (damage > 0) {
chr.getAutobanManager().resetMisses();
} else {
chr.getAutobanManager().addMiss();
}
//in dojo player cannot use pot, so deadly attacks should be turned off as well
if(is_deadly && chr.getMap().isDojoMap() && !ServerConstants.USE_DEADLY_DOJO) {
damage = 0;
mpattack = 0;
}
if (damage == 0) {
chr.getAutobanManager().addMiss();
} else {
chr.getAutobanManager().resetMisses();
}
if (damage > 0 && !chr.isHidden()) {
if (attacker != null) {
if (damagefrom == -1) {
@@ -294,11 +294,9 @@ public final class UseCashItemHandler extends AbstractMaplePacketHandler {
if (item == null) //hack
{
return;
} else if (item.isUntradeable() || ii.isUnmerchable(item.getItemId())) {
player.dropMessage(1, "You cannot trade this item.");
c.announce(MaplePacketCreator.enableActions());
return;
}
// thanks Conrad for noticing that untradeable items should be allowed in megas
}
Server.getInstance().broadcastMessage(c.getWorld(), MaplePacketCreator.itemMegaphone(msg, whisper, c.getChannel(), item));
break;
@@ -398,7 +396,7 @@ public final class UseCashItemHandler extends AbstractMaplePacketHandler {
ii.getItemEffect(itemId).applyTo(player);
remove(c, position, itemId);
} else if (itemType == 533) {
DueyProcessor.dueySendTalk(c);
DueyProcessor.dueySendTalk(c, true);
} else if (itemType == 537) {
if (GameConstants.isFreeMarketRoom(player.getMapId())) {
player.dropMessage(5, "You cannot use the chalkboard here.");
@@ -569,7 +567,7 @@ public final class UseCashItemHandler extends AbstractMaplePacketHandler {
client.announce(MaplePacketCreator.modifyInventory(true, mods));
ScrollResult scrollResult = scrolled.getLevel() > curlevel ? ScrollResult.SUCCESS : ScrollResult.FAIL;
player.getMap().broadcastMessage(MaplePacketCreator.getScrollEffect(player.getId(), scrollResult, false));
player.getMap().broadcastMessage(MaplePacketCreator.getScrollEffect(player.getId(), scrollResult, false, false));
if (eSlot < 0 && (scrollResult == ScrollResult.SUCCESS)) {
player.equipChanged();
}
@@ -23,6 +23,7 @@ package net.server.channel.handlers;
import client.MapleClient;
import client.inventory.MapleInventoryType;
import constants.ItemConstants;
import net.AbstractMaplePacketHandler;
import tools.data.input.SeekableLittleEndianAccessor;
@@ -30,7 +31,9 @@ public final class UseChairHandler extends AbstractMaplePacketHandler {
@Override
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
int itemId = slea.readInt();
if (c.getPlayer().getInventory(MapleInventoryType.SETUP).findById(itemId) == null) {
// thanks Darter (YungMoozi) for reporting unchecked chair item
if (!ItemConstants.isChair(itemId) || c.getPlayer().getInventory(MapleInventoryType.SETUP).findById(itemId) == null) {
return;
}
@@ -1,5 +1,5 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
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
@@ -17,27 +17,17 @@
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 net.server.worker;
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command;
import server.expeditions.MapleExpeditionBossLog;
class RegisteredCommand {
private final Class<? extends Command> commandClass;
private final int rank;
RegisteredCommand(Class<? extends Command> commandClass, int rank){
this.commandClass = commandClass;
this.rank = rank;
}
public Class<? extends Command> getCommandClass() {
return commandClass;
}
public int getRank() {
return rank;
/**
* @author Ronan
*/
public class BossLogWorker implements Runnable {
@Override
public void run() {
MapleExpeditionBossLog.resetBossLogTable();
}
}
+2 -2
View File
@@ -1073,12 +1073,12 @@ public class AbstractPlayerInteraction {
public boolean createExpedition(MapleExpeditionType type, boolean silent, int minPlayers, int maxPlayers) {
MapleExpedition exped = new MapleExpedition(getPlayer(), type, silent, minPlayers, maxPlayers);
return getPlayer().getClient().getChannelServer().addExpedition(exped);
return exped.addChannelExpedition(getPlayer().getClient().getChannelServer());
}
public void endExpedition(MapleExpedition exped) {
exped.dispose(true);
getPlayer().getClient().getChannelServer().removeExpedition(exped);
exped.removeChannelExpedition(getPlayer().getClient().getChannelServer());
}
public MapleExpedition getExpedition(MapleExpeditionType type) {
@@ -1062,7 +1062,7 @@ public class EventInstanceManager {
sL.lock();
try {
em.getChannelServer().removeExpedition(expedition);
expedition.removeChannelExpedition(em.getChannelServer());
} finally {
sL.unlock();
}
@@ -1127,8 +1127,8 @@ public class EventInstanceManager {
if(eventCleared) {
if(leavingEventMap && getPlayerCount() <= 1) return true;
} else {
if(leavingEventMap && getLeaderId() == quitter.getId()) return true;
if(getPlayerCount() <= (ServerConstants.USE_ENABLE_SOLO_EXPEDITIONS ? 1 : minPlayers)) return true;
// thanks Conrad for noticing expeditions don't need to have neither the leader nor meet the minimum requirement inside the event
if(getPlayerCount() <= 1) return true;
}
return false;
+4
View File
@@ -78,6 +78,10 @@ public class DueyPackage {
public long sentTimeInMilliseconds() {
Calendar cal = Calendar.getInstance();
cal.set(year, month, day);
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTimeInMillis();
}
+23 -12
View File
@@ -57,14 +57,19 @@ public class MakerItemFactory {
return makerEntry;
}
public static MakerItemCreateEntry generateLeftoverCrystalEntry(int fromLeftoverid) {
MakerItemCreateEntry ret = new MakerItemCreateEntry(0, 0, 1, 1);
public static MakerItemCreateEntry generateLeftoverCrystalEntry(int fromLeftoverid, int crystalId) {
MakerItemCreateEntry ret = new MakerItemCreateEntry(0, 0, 1);
ret.addReqItem(fromLeftoverid, 100);
ret.addGainItem(crystalId, 1);
return ret;
}
public static MakerItemCreateEntry generateDisassemblyCrystalEntry(int cost, int crystalGain) { // equipment at specific position already taken
MakerItemCreateEntry ret = new MakerItemCreateEntry(cost, 0, 1, crystalGain);
public static MakerItemCreateEntry generateDisassemblyCrystalEntry(int fromEquipid, int cost, List<Pair<Integer, Integer>> gains) { // equipment at specific position already taken
MakerItemCreateEntry ret = new MakerItemCreateEntry(cost, 0, 1);
ret.addReqItem(fromEquipid, 1);
for (Pair<Integer, Integer> p : gains) {
ret.addGainItem(p.getLeft(), p.getRight());
}
return ret;
}
@@ -143,33 +148,35 @@ public class MakerItemFactory {
private double cost;
private int reqCost;
private List<Pair<Integer, Integer>> reqItems = new ArrayList<>(); // itemId / amount
private int toGive;
private List<Pair<Integer, Integer>> gainItems = new ArrayList<>(); // itemId / amount
public MakerItemCreateEntry(int cost, int reqLevel, int reqMakerLevel, int toGive) {
public MakerItemCreateEntry(int cost, int reqLevel, int reqMakerLevel) {
this.cost = cost;
this.reqLevel = reqLevel;
this.reqMakerLevel = reqMakerLevel;
this.toGive = toGive;
}
public MakerItemCreateEntry(MakerItemCreateEntry mi) {
this.cost = mi.cost;
this.reqLevel = mi.reqLevel;
this.reqMakerLevel = mi.reqMakerLevel;
this.toGive = mi.toGive;
for(Pair<Integer, Integer> p : mi.reqItems) {
reqItems.add(p);
}
}
public int getRewardAmount() {
return toGive;
for(Pair<Integer, Integer> p : mi.gainItems) {
gainItems.add(p);
}
}
public List<Pair<Integer, Integer>> getReqItems() {
return reqItems;
}
public List<Pair<Integer, Integer>> getGainItems() {
return gainItems;
}
public int getReqLevel() {
return reqLevel;
@@ -191,6 +198,10 @@ public class MakerItemFactory {
reqItems.add(new Pair<>(itemId, amount));
}
protected void addGainItem(int itemId, int amount) {
gainItems.add(new Pair<>(itemId, amount));
}
public void trimCost() {
reqCost = (int) (cost / 1000);
reqCost *= 1000;
+9 -7
View File
@@ -1968,7 +1968,8 @@ public class MapleItemInformationProvider {
}
ps.close();
rs.close();
makerEntry = new MakerItemCreateEntry(cost, reqLevel, reqMakerLevel, toGive);
makerEntry = new MakerItemCreateEntry(cost, reqLevel, reqMakerLevel);
makerEntry.addGainItem(toCreate, toGive);
ps = con.prepareStatement("SELECT req_item, count FROM makerrecipedata WHERE itemid = ?");
ps.setInt(1, toCreate);
rs = ps.executeQuery();
@@ -2008,17 +2009,18 @@ public class MapleItemInformationProvider {
return -1;
}
public int getMakerDisassembledQuantity(Integer itemId) {
int avail = 0;
public List<Pair<Integer, Integer>> getMakerDisassembledItems(Integer itemId) {
List<Pair<Integer, Integer>> items = new LinkedList<>();
Connection con;
try {
con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("SELECT count FROM makerrecipedata WHERE itemid = ? AND req_item >= 4260000 AND req_item <= 4260008 ORDER BY count DESC");
PreparedStatement ps = con.prepareStatement("SELECT req_item, count FROM makerrecipedata WHERE itemid = ? AND req_item >= 4260000 AND req_item < 4270000");
ps.setInt(1, itemId);
ResultSet rs = ps.executeQuery();
if(rs.next()) {
avail = (int) Math.ceil(rs.getInt("count") / 2); // return to the player half of the crystals needed
while (rs.next()) {
items.add(new Pair<>(rs.getInt("req_item"), rs.getInt("count") / 2)); // return to the player half of the crystals needed
}
rs.close();
@@ -2028,7 +2030,7 @@ public class MapleItemInformationProvider {
e.printStackTrace();
}
return avail;
return items;
}
public int getMakerDisassembledFee(Integer itemId) {
+36 -47
View File
@@ -13,57 +13,46 @@ import client.SkillFactory;
* @author kevintjuh93
*/
public class RescueGaga extends MapleEvents {
private byte fallen;
private int completed;
private int completed;
public RescueGaga(int completed) {
super();
this.completed = completed;
}
public RescueGaga(int completed) {
super();
this.completed = completed;
this.fallen = 0;
}
public int getCompleted() {
return completed;
}
public int fallAndGet() {
fallen++;
if (fallen > 3) {
fallen = 0;
return 4;
}
return fallen;
}
public void complete() {
completed++;
}
public byte getFallen() {
return fallen;
}
public int getCompleted() {
return completed;
}
public void complete() {
completed++;
@Override
public int getInfo() {
return getCompleted();
}
public void giveSkill(MapleCharacter chr) {
int skillid = 0;
switch (chr.getJobType()) {
case 0:
skillid = 1013;
break;
case 1:
case 2:
skillid = 10001014;
}
public int getInfo() {
return getCompleted();
}
public void giveSkill(MapleCharacter chr) {
int skillid = 0;
switch (chr.getJobType()) {
case 0:
skillid = 1013;
break;
case 1:
case 2:
skillid = 10001014;
}
long expiration = (System.currentTimeMillis() + (long) (3600 * 24 * 20 * 1000));//20 days
if (completed < 20) {
chr.changeSkillLevel(SkillFactory.getSkill(skillid), (byte) 1, 1, expiration);
chr.changeSkillLevel(SkillFactory.getSkill(skillid + 1), (byte) 1, 1, expiration);
chr.changeSkillLevel(SkillFactory.getSkill(skillid + 2), (byte) 1, 1, expiration);
} else {
chr.changeSkillLevel(SkillFactory.getSkill(skillid), (byte) 2, 2, chr.getSkillExpiration(skillid));
}
long expiration = (System.currentTimeMillis() + 3600 * 24 * 20 * 1000);//20 days
if (completed < 20) {
chr.changeSkillLevel(SkillFactory.getSkill(skillid), (byte) 1, 1, expiration);
chr.changeSkillLevel(SkillFactory.getSkill(skillid + 1), (byte) 1, 1, expiration);
chr.changeSkillLevel(SkillFactory.getSkill(skillid + 2), (byte) 1, 1, expiration);
} else {
chr.changeSkillLevel(SkillFactory.getSkill(skillid), (byte) 2, 2, chr.getSkillExpiration(skillid));
}
}
}
+25 -2
View File
@@ -46,6 +46,7 @@ import java.util.Properties;
import net.server.audit.locks.MonitoredLockType;
import net.server.audit.locks.MonitoredReentrantLock;
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
import net.server.channel.Channel;
/**
*
@@ -137,7 +138,7 @@ public class MapleExpedition {
@Override
public void run() {
if (registering){
startMap.getChannelServer().removeExpedition(exped);
exped.removeChannelExpedition(startMap.getChannelServer());
if (!silent) startMap.broadcastMessage(MaplePacketCreator.serverNotice(6, "[Expedition] The time limit has been reached. Expedition has been disbanded."));
dispose(false);
@@ -163,6 +164,7 @@ public class MapleExpedition {
public void start(){
finishRegistration();
registerExpeditionAttempt();
broadcastExped(MaplePacketCreator.removeClock());
if (!silent) broadcastExped(MaplePacketCreator.serverNotice(6, "[Expedition] The expedition has started! Good luck, brave heroes!"));
startTime = System.currentTimeMillis();
@@ -180,6 +182,11 @@ public class MapleExpedition {
return "Sorry, this expedition is full!";
}
int channel = this.getRecruitingMap().getChannelServer().getId();
if (!MapleExpeditionBossLog.attemptBoss(player.getId(), channel, this, false)) { // thanks Conrad, Cato for noticing some expeditions have entry limit
return "Sorry, you've already reached the quota of attempts for this expedition! Try again another day...";
}
members.put(player.getId(), player.getName());
player.announce(MaplePacketCreator.getClock((int)(startTime - System.currentTimeMillis()) / 1000));
if (!silent) broadcastExped(MaplePacketCreator.serverNotice(6, "[Expedition] " + player.getName() + " has joined the expedition!"));
@@ -202,13 +209,21 @@ public class MapleExpedition {
if (!silent) broadcastExped(MaplePacketCreator.serverNotice(6, "[Expedition] " + player.getName() + " has joined the expedition!"));
return 0; //"You have registered for the expedition successfully!";
}
private void registerExpeditionAttempt(){
int channel = this.getRecruitingMap().getChannelServer().getId();
for (MapleCharacter chr : getActiveMembers()){
MapleExpeditionBossLog.attemptBoss(chr.getId(), channel, this, true);
}
}
private void broadcastExped(byte[] packet){
for (MapleCharacter chr : getActiveMembers()){
chr.announce(packet);
}
}
public boolean removeMember(MapleCharacter chr) {
if(members.remove(chr.getId()) != null) {
chr.announce(MaplePacketCreator.removeClock());
@@ -359,6 +374,14 @@ public class MapleExpedition {
chr.changeMap(warpTo, toSp);
}
}
public final boolean addChannelExpedition(Channel ch) {
return ch.addExpedition(this);
}
public final void removeChannelExpedition(Channel ch) {
ch.removeExpedition(this);
}
public MapleCharacter getLeader(){
return leader;
@@ -0,0 +1,205 @@
/*
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/>.
*/
package server.expeditions;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.LinkedList;
import java.util.List;
import tools.DatabaseConnection;
import tools.Pair;
/**
*
* @author Conrad
* @author Ronan
*/
public class MapleExpeditionBossLog {
public enum BossLogEntry {
ZAKUM(2, 1, false),
HORNTAIL(2, 1, false),
PINKBEAN(1, 1, false),
SCARGA(1, 1, false),
PAPULATUS(2, 1, false);
private int entries;
private int timeLength;
private int minChannel, maxChannel;
private boolean week;
private BossLogEntry(int entries, int timeLength, boolean week) {
this(entries, 0, Integer.MAX_VALUE, timeLength, week);
}
private BossLogEntry(int entries, int minChannel, int maxChannel, int timeLength, boolean week) {
this.entries = entries;
this.minChannel = minChannel;
this.maxChannel = maxChannel;
this.timeLength = timeLength;
this.week = week;
}
private static List<Pair<Timestamp, BossLogEntry>> getBossLogResetTimestamps(Calendar timeNow, boolean week) {
List<Pair<Timestamp, BossLogEntry>> resetTimestamps = new LinkedList<>();
for (BossLogEntry b : BossLogEntry.values()) {
if (b.week == week) {
Calendar c = (Calendar) timeNow.clone();
c.roll(Calendar.DAY_OF_MONTH, -1 * (week ? 7 : 1) * b.timeLength);
Timestamp ts = new Timestamp(c.getTime().getTime());
resetTimestamps.add(new Pair<>(ts, b));
}
}
return resetTimestamps;
}
private static BossLogEntry getBossEntryByName(String name) {
for (BossLogEntry b : BossLogEntry.values()) {
if (name.contentEquals(b.name())) {
return b;
}
}
return null;
}
}
public static void resetBossLogTable() {
/*
Boss logs resets 12am, weekly thursday 12AM - thanks Smitty Werbenjagermanjensen (superadlez) - https://www.reddit.com/r/Maplestory/comments/61tiup/about_reset_time/
*/
Calendar thursday = Calendar.getInstance();
thursday.set(Calendar.DAY_OF_WEEK, Calendar.THURSDAY);
thursday.set(Calendar.HOUR, 0);
thursday.set(Calendar.MINUTE, 0);
thursday.set(Calendar.SECOND, 0);
Calendar now = Calendar.getInstance();
long weekLength = 7 * 24 * 60 * 60 * 1000;
long halfDayLength = 12 * 60 * 60 * 1000;
long deltaTime = now.getTime().getTime() - thursday.getTime().getTime(); // 2x time: get Date into millis
deltaTime += halfDayLength;
deltaTime %= weekLength;
deltaTime -= halfDayLength;
if (deltaTime < halfDayLength) {
MapleExpeditionBossLog.resetBossLogTable(true, thursday);
}
now.set(Calendar.HOUR, 0);
now.set(Calendar.MINUTE, 0);
now.set(Calendar.SECOND, 0);
MapleExpeditionBossLog.resetBossLogTable(false, now);
}
private static void resetBossLogTable(boolean week, Calendar c) {
List<Pair<Timestamp, BossLogEntry>> resetTimestamps = BossLogEntry.getBossLogResetTimestamps(c, week);
try {
Connection con = DatabaseConnection.getConnection();
for (Pair<Timestamp, BossLogEntry> p : resetTimestamps) {
PreparedStatement ps = con.prepareStatement("DELETE FROM " + getBossLogTable(week) + " WHERE attempttime <= ? AND bosstype LIKE ?");
ps.setTimestamp(1, p.getLeft());
ps.setString(2, p.getRight().name());
ps.executeUpdate();
ps.close();
}
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
private static String getBossLogTable(boolean week) {
return week ? "bosslog_weekly" : "bosslog_daily";
}
private static int countPlayerEntries(int cid, BossLogEntry boss) {
int ret_count = 0;
try {
Connection con = DatabaseConnection.getConnection();
PreparedStatement ps;
ps = con.prepareStatement("SELECT COUNT(*) FROM " + getBossLogTable(boss.week) + " WHERE characterid = ? AND bosstype LIKE ?");
ps.setInt(1, cid);
ps.setString(2, boss.name());
ResultSet rs = ps.executeQuery();
if (rs.next()) {
ret_count = rs.getInt(1);
} else {
ret_count = -1;
}
rs.close();
ps.close();
con.close();
return ret_count;
} catch (SQLException e) {
e.printStackTrace();
return -1;
}
}
private static void insertPlayerEntry(int cid, BossLogEntry boss) {
try {
Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("INSERT INTO " + getBossLogTable(boss.week) + " (characterid, bosstype) VALUES (?,?)");
ps.setInt(1, cid);
ps.setString(2, boss.name());
ps.executeUpdate();
ps.close();
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static boolean attemptBoss(int cid, int channel, MapleExpedition exped, boolean log) {
BossLogEntry boss = BossLogEntry.getBossEntryByName(exped.getType().name());
if (boss == null) {
return true;
}
if (channel < boss.minChannel || channel > boss.maxChannel) {
return false;
}
if (countPlayerEntries(cid, boss) >= boss.entries) {
return false;
}
if (log) {
insertPlayerEntry(cid, boss);
}
return true;
}
}
+12 -20
View File
@@ -415,7 +415,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
*/
if (damage > 0) {
this.applyDamage(attacker, damage, stayAlive);
this.applyDamage(attacker, damage, stayAlive, false);
if (!this.isAlive()) { // monster just died
lastHit = true;
}
@@ -433,7 +433,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
* @param damage
* @param stayAlive
*/
private void applyDamage(MapleCharacter from, int damage, boolean stayAlive) {
private void applyDamage(MapleCharacter from, int damage, boolean stayAlive, boolean fake) {
Integer trueDamage = applyAndGetHpDamage(damage, stayAlive);
if (trueDamage == null) {
return;
@@ -442,8 +442,11 @@ public class MapleMonster extends AbstractLoadedMapleLife {
if (ServerConstants.USE_DEBUG) {
from.dropMessage(5, "Hitted MOB " + this.getId() + ", OID " + this.getObjectId());
}
dispatchMonsterDamaged(from, trueDamage);
if (!fake) {
dispatchMonsterDamaged(from, trueDamage);
}
if (!takenDamage.containsKey(from.getId())) {
takenDamage.put(from.getId(), new AtomicLong(trueDamage));
} else {
@@ -453,6 +456,10 @@ public class MapleMonster extends AbstractLoadedMapleLife {
broadcastMobHpBar(from);
}
public void applyFakeDamage(MapleCharacter from, int damage, boolean stayAlive) {
applyDamage(from, damage, stayAlive, true);
}
public void heal(int hp, int mp) {
Integer hpHealed = applyAndGetHpDamage(-hp, false);
if (hpHealed == null) {
@@ -744,21 +751,6 @@ public class MapleMonster extends AbstractLoadedMapleLife {
if (toSpawn.contains(timeMob.getLeft())) {
reviveMap.broadcastMessage(MaplePacketCreator.serverNotice(6, timeMob.getRight()));
}
if (timeMob.getLeft() == 9300338 && (reviveMap.getId() >= 922240100 && reviveMap.getId() <= 922240119)) {
if (!reviveMap.containsNPC(9001108)) {
MapleNPC npc = MapleLifeFactory.getNPC(9001108);
npc.setPosition(new Point(172, 9));
npc.setCy(9);
npc.setRx0(172 + 50);
npc.setRx1(172 - 50);
npc.setFh(27);
reviveMap.addMapObject(npc);
reviveMap.broadcastMessage(MaplePacketCreator.spawnNPC(npc));
} else {
reviveMap.toggleHiddenNPC(9001108);
}
}
}
if(toSpawn.size() > 0) {
@@ -1621,7 +1613,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
if (damage > 0) {
lockMonster();
try {
applyDamage(chr, damage, true);
applyDamage(chr, damage, true, false);
} finally {
unlockMonster();
}
+43 -47
View File
@@ -101,6 +101,7 @@ public class MapleMap {
private static final Map<Integer, Pair<Integer, Integer>> dropBoundsCache = new HashMap<>(100);
private Map<Integer, MapleMapObject> mapobjects = new LinkedHashMap<>();
private Set<Integer> selfDestructives = new LinkedHashSet<>();
private Collection<SpawnPoint> monsterSpawn = Collections.synchronizedList(new LinkedList<SpawnPoint>());
private Collection<SpawnPoint> allMonsterSpawn = Collections.synchronizedList(new LinkedList<SpawnPoint>());
private AtomicInteger spawnedMonstersOnMap = new AtomicInteger(0);
@@ -122,6 +123,7 @@ public class MapleMap {
private AtomicInteger runningOid = new AtomicInteger(1000000001);
private int returnMapId;
private int channel, world;
private int seats;
private byte monsterRate;
private boolean clock;
private boolean boat;
@@ -132,7 +134,8 @@ public class MapleMap {
private MapleMapEffect mapEffect = null;
private boolean everlast = false;
private int forcedReturnMap = 999999999;
private long timeLimit;
private int timeLimit;
private long mapTimer;
private int decHP = 0;
private int protectItem = 0;
private boolean town;
@@ -145,7 +148,6 @@ public class MapleMap {
private int fieldLimit = 0;
private int mobCapacity = -1;
private MapleMonsterAggroCoordinator aggroMonitor = null; // aggroMonitor activity in sync with itemMonitor
private ScheduledFuture<?> mapMonitor = null;
private ScheduledFuture<?> itemMonitor = null;
private ScheduledFuture<?> expireItemsTask = null;
private ScheduledFuture<?> mobSpawnLootTask = null;
@@ -307,7 +309,7 @@ public class MapleMap {
this.forcedReturnMap = map;
}
public long getTimeLimit() {
public int getTimeLimit() {
return timeLimit;
}
@@ -316,7 +318,7 @@ public class MapleMap {
}
public int getTimeLeft() {
return (int) ((timeLimit - System.currentTimeMillis()) / 1000);
return (int) ((mapTimer - System.currentTimeMillis()) / 1000);
}
public void setReactorState() {
@@ -398,6 +400,16 @@ public class MapleMap {
}
}
public void addSelfDestructive(MapleMonster mob) {
if (mob.getStats().selfDestruction() != null) {
this.selfDestructives.add(mob.getObjectId());
}
}
public boolean removeSelfDestructive(int mapobjectid) {
return this.selfDestructives.remove(mapobjectid);
}
private void spawnAndAddRangedMapObject(MapleMapObject mapobject, DelayedPacketCreation packetbakery) {
spawnAndAddRangedMapObject(mapobject, packetbakery, null);
}
@@ -1331,9 +1343,11 @@ public class MapleMap {
}
if (monster.isAlive()) {
boolean killed = monster.damage(chr, damage, false);
if (monster.getStats().selfDestruction() != null && monster.getStats().selfDestruction().getHp() > -1) {// should work ;p
if (monster.getHp() <= monster.getStats().selfDestruction().getHp()) {
killMonster(monster, chr, true, monster.getStats().selfDestruction().getAction());
selfDestruction selfDestr = monster.getStats().selfDestruction();
if (selfDestr != null && selfDestr.getHp() > -1) {// should work ;p
if (monster.getHp() <= selfDestr.getHp()) {
killMonster(monster, chr, true, selfDestr.getAction());
return true;
}
}
@@ -1907,7 +1921,6 @@ public class MapleMap {
spawnAndAddRangedMapObject(monster, new DelayedPacketCreation() {
@Override
public void sendPackets(MapleClient c) {
c.announce(MaplePacketCreator.spawnMonster(monster, false));
}
});
@@ -1919,6 +1932,7 @@ public class MapleMap {
}
spawnedMonstersOnMap.incrementAndGet();
addSelfDestructive(monster);
applyRemoveAfter(monster);
}
@@ -2052,6 +2066,7 @@ public class MapleMap {
}
spawnedMonstersOnMap.incrementAndGet();
addSelfDestructive(monster);
applyRemoveAfter(monster); // thanks LightRyuzaki for pointing issues with spawned CWKPQ mobs not applying this
}
@@ -2088,6 +2103,7 @@ public class MapleMap {
}
spawnedMonstersOnMap.incrementAndGet();
addSelfDestructive(monster);
applyRemoveAfter(monster);
}
@@ -2102,6 +2118,7 @@ public class MapleMap {
});
spawnedMonstersOnMap.incrementAndGet();
addSelfDestructive(monster);
}
public void makeMonsterReal(final MapleMonster monster) {
@@ -3812,6 +3829,14 @@ public class MapleMap {
public boolean getDocked() {
return this.docked;
}
public void setSeats(int seats) {
this.seats = seats;
}
public int getSeats() {
return seats;
}
public void broadcastGMMessage(MapleCharacter source, final byte[] packet, boolean repeatToSource) {
broadcastGMMessage(repeatToSource ? null : source, packet, Double.POSITIVE_INFINITY, source.getPosition());
@@ -3904,35 +3929,7 @@ public class MapleMap {
this.broadcastMessage(MaplePacketCreator.removeItemFromMap(i.getObjectId(), 0, 0));
}
}
public void addMapTimer(int time) {
timeLimit = System.currentTimeMillis() + (time * 1000);
broadcastMessage(MaplePacketCreator.getClock(time));
mapMonitor = TimerManager.getInstance().register(new Runnable() {
@Override
public void run() {
if (timeLimit != 0 && timeLimit < System.currentTimeMillis()) {
warpEveryone(getForcedReturnId());
}
if (getCharacters().isEmpty()) {
resetReactors();
killAllMonsters();
clearDrops();
timeLimit = 0;
if (mapid >= 922240100 && mapid <= 922240119) {
toggleHiddenNPC(9001108);
}
if (mapMonitor != null) {
mapMonitor.cancel(true);
mapMonitor = null;
}
}
}
}, 1000);
}
public void setFieldLimit(int fieldLimit) {
this.fieldLimit = fieldLimit;
}
@@ -4079,7 +4076,7 @@ public class MapleMap {
return this.mapid >= 109010000 && this.mapid < 109050000 || this.mapid > 109050001 && this.mapid <= 109090000;
}
public void timeMob(int id, String msg) {
public void setTimeMob(int id, String msg) {
timeMob = new Pair<>(id, msg);
}
@@ -4206,8 +4203,8 @@ public class MapleMap {
@Override
public void monsterDamaged(MapleCharacter from, int trueDmg) {
ht.applyAndGetHpDamage(trueDmg, true);
ht.broadcastMobHpBar(from);
// thanks Halcyon for noticing HT not dropping loots due to propagated damage not registering attacker
ht.applyFakeDamage(from, trueDmg, true);
}
@Override
@@ -4222,7 +4219,9 @@ public class MapleMap {
public boolean claimOwnership(MapleCharacter chr) {
if (mapOwner == null) {
mapOwner = chr;
this.mapOwner = chr;
chr.setOwnedMap(this);
mapOwnerLastActivityTime = Server.getInstance().getCurrentTime();
getChannelServer().registerOwnedMap(this);
@@ -4234,7 +4233,9 @@ public class MapleMap {
public boolean unclaimOwnership(MapleCharacter chr) {
if (mapOwner == chr) {
mapOwner = null;
this.mapOwner = null;
chr.setOwnedMap(null);
mapOwnerLastActivityTime = Long.MAX_VALUE;
getChannelServer().unregisterOwnedMap(this);
@@ -4533,11 +4534,6 @@ public class MapleMap {
portals.clear();
mapEffect = null;
if(mapMonitor != null) {
mapMonitor.cancel(false);
mapMonitor = null;
}
chrWLock.lock();
try {
aggroMonitor.dispose();
+5 -2
View File
@@ -172,8 +172,7 @@ public class MapleMapFactory {
}
MapleData timeMob = infoData.getChildByPath("timeMob");
if (timeMob != null) {
map.timeMob(MapleDataTool.getInt(timeMob.getChildByPath("id")),
MapleDataTool.getString(timeMob.getChildByPath("message")));
map.setTimeMob(MapleDataTool.getInt(timeMob.getChildByPath("id")), MapleDataTool.getString(timeMob.getChildByPath("message")));
}
int bounds[] = new int[4];
@@ -243,6 +242,10 @@ public class MapleMapFactory {
map.addMapleArea(new Rectangle(x1, y1, (x2 - x1), (y2 - y1)));
}
}
if (mapData.getChildByPath("seat") != null) {
int seats = mapData.getChildByPath("seat").getChildren().size();
map.setSeats(seats);
}
if (event == null) {
try {
Connection con = DatabaseConnection.getConnection();
+2 -2
View File
@@ -42,9 +42,9 @@ public class MapleMiniDungeon {
int baseMap;
long expireTime;
public MapleMiniDungeon(int base, int durationMin) {
public MapleMiniDungeon(int base, long timeLimit) {
baseMap = base;
expireTime = durationMin * 60 * 1000;
expireTime = timeLimit * 1000;
timeoutTask = TimerManager.getInstance().schedule(new Runnable() {
@Override
@@ -0,0 +1,84 @@
package server.minigame;
import client.MapleClient;
import client.inventory.Item;
import client.inventory.manipulator.MapleInventoryManipulator;
import tools.MaplePacketCreator;
import tools.Randomizer;
/**
* @Author Arnah
* @Website http://Vertisy.ca/
* @since Aug 15, 2016
*/
public class MapleRockPaperScissor{
private int round = 0;
private boolean ableAnswer = true;
private boolean win = false;
public MapleRockPaperScissor(final MapleClient c, final byte mode){
c.announce(MaplePacketCreator.rpsMode((byte) (9 + mode)));
if(mode == 0){
c.getPlayer().gainMeso(-1000, true, true, true);
}
}
public final boolean answer(final MapleClient c, final int answer){
if(ableAnswer && !win && answer >= 0 && answer <= 2){
final int response = Randomizer.nextInt(3);
if(response == answer){
c.announce(MaplePacketCreator.rpsSelection((byte) response, (byte) round));
// dont do anything. they can still answer once a draw
}else if((answer == 0 && response == 2) || (answer == 1 && response == 0) || (answer == 2 && response == 1)){ // they win
c.announce(MaplePacketCreator.rpsSelection((byte) response, (byte) (round + 1)));
ableAnswer = false;
win = true;
}else{ // they lose
c.announce(MaplePacketCreator.rpsSelection((byte) response, (byte) -1));
ableAnswer = false;
}
return true;
}
reward(c);
return false;
}
public final boolean timeOut(final MapleClient c){
if(ableAnswer && !win){
ableAnswer = false;
c.announce(MaplePacketCreator.rpsMode((byte) 0x0A));
return true;
}
reward(c);
return false;
}
public final boolean nextRound(final MapleClient c){
if(win){
round++;
if(round < 10){
win = false;
ableAnswer = true;
c.announce(MaplePacketCreator.rpsMode((byte) 0x0C));
return true;
} else {
round = 10;
}
}
reward(c);
return false;
}
public final void reward(final MapleClient c){
if(win){
MapleInventoryManipulator.addFromDrop(c, new Item(4031332 + round, (short) 0, (short) 1), true);
}
c.getPlayer().setRPS(null);
}
public final void dispose(final MapleClient c){
reward(c);
c.announce(MaplePacketCreator.rpsMode((byte) 0x0D));
}
}
+1 -1
View File
@@ -272,7 +272,7 @@ public class AriantColiseum {
}
private void enterKingsRoom() {
map.getChannelServer().removeExpedition(exped);
exped.removeChannelExpedition(map.getChannelServer());
cancelAriantSchedules();
for (MapleCharacter chr : map.getAllPlayers()) {
+3 -11
View File
@@ -73,9 +73,9 @@ public class MapleQuest {
private boolean repeatable = false;
private String name = "", parent = "";
private final static MapleDataProvider questData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Quest.wz"));
private static MapleData questInfo;
private static MapleData questAct;
private static MapleData questReq;
private final static MapleData questInfo = questData.getData("QuestInfo.img");
private final static MapleData questAct = questData.getData("Act.img");
private final static MapleData questReq = questData.getData("Check.img");
private MapleQuest(int id) {
this.id = (short) id;
@@ -186,10 +186,6 @@ public class MapleQuest {
public static MapleQuest getInstance(int id) {
MapleQuest ret = quests.get(id);
if (ret == null) {
questInfo = questData.getData("QuestInfo.img");
questReq = questData.getData("Check.img");
questAct = questData.getData("Act.img");
ret = new MapleQuest(id);
quests.put(id, ret);
}
@@ -590,10 +586,6 @@ public class MapleQuest {
}
public static void loadAllQuest() {
questInfo = questData.getData("QuestInfo.img");
questReq = questData.getData("Check.img");
questAct = questData.getData("Act.img");
try {
for(MapleData quest : questInfo.getChildren()) {
int questID = Integer.parseInt(quest.getName());
+161 -33
View File
@@ -110,6 +110,7 @@ import constants.ServerConstants;
import constants.skills.Buccaneer;
import constants.skills.Corsair;
import constants.skills.ThunderBreaker;
import scripting.npc.NPCConversationManager;
import server.maps.AbstractMapleMapObject;
/**
@@ -479,8 +480,7 @@ public class MaplePacketCreator {
equipped.add((Item) item);
}
}
Collections.sort(equipped);
for (Item item : equipped) {
for (Item item : equipped) { // equipped doesn't actually need sorting, thanks Pllsz
addItemInfo(mplew, item);
}
mplew.writeShort(0); // start of equip cash
@@ -1194,7 +1194,7 @@ public class MaplePacketCreator {
return mplew.getPacket();
}
public static byte[] removeKite(int objectid, int animationType) { // thanks to Arnah
public static byte[] removeKite(int objectid, int animationType) { // thanks to Arnah (Vertisy)
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.REMOVE_KITE.getValue());
mplew.write(animationType); // 0 is 10/10, 1 just vanishes
@@ -2511,25 +2511,14 @@ public class MaplePacketCreator {
return mplew.getPacket();
}
public static byte[] getScrollEffect(int chr, ScrollResult scrollSuccess, boolean legendarySpirit) {
public static byte[] getScrollEffect(int chr, ScrollResult scrollSuccess, boolean legendarySpirit, boolean whiteScroll) { // thanks to Rien dev team
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.SHOW_SCROLL_EFFECT.getValue());
mplew.writeInt(chr);
switch (scrollSuccess) {
case SUCCESS:
mplew.writeShort(1);
mplew.writeShort(legendarySpirit ? 1 : 0);
break;
case FAIL:
mplew.writeShort(0);
mplew.writeShort(legendarySpirit ? 1 : 0);
break;
case CURSE:
mplew.write(0);
mplew.write(1);
mplew.writeShort(legendarySpirit ? 1 : 0);
break;
}
mplew.writeBool(scrollSuccess == ScrollResult.SUCCESS);
mplew.writeBool(scrollSuccess == ScrollResult.CURSE);
mplew.writeBool(legendarySpirit);
mplew.writeBool(whiteScroll);
return mplew.getPacket();
}
@@ -3441,6 +3430,44 @@ public class MaplePacketCreator {
mplew.writeInt(0);
return mplew.getPacket();
}
// thanks NPC Quiz packets thanks to Eric
public static byte[] OnAskQuiz(int nSpeakerTypeID, int nSpeakerTemplateID, int nResCode, String sTitle, String sProblemText, String sHintText, int nMinInput, int nMaxInput, int tRemainInitialQuiz) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.NPC_TALK.getValue());
mplew.write(nSpeakerTypeID);
mplew.writeInt(nSpeakerTemplateID);
mplew.write(0x6);
mplew.write(0);
mplew.write(nResCode);
if (nResCode == 0x0) {//fail has no bytes <3
mplew.writeMapleAsciiString(sTitle);
mplew.writeMapleAsciiString(sProblemText);
mplew.writeMapleAsciiString(sHintText);
mplew.writeShort(nMinInput);
mplew.writeShort(nMaxInput);
mplew.writeInt(tRemainInitialQuiz);
}
return mplew.getPacket();
}
public static byte[] OnAskSpeedQuiz(int nSpeakerTypeID, int nSpeakerTemplateID, int nResCode, int nType, int dwAnswer, int nCorrect, int nRemain, int tRemainInitialQuiz) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.NPC_TALK.getValue());
mplew.write(nSpeakerTypeID);
mplew.writeInt(nSpeakerTemplateID);
mplew.write(0x7);
mplew.write(0);
mplew.write(nResCode);
if (nResCode == 0x0) {//fail has no bytes <3
mplew.writeInt(nType);
mplew.writeInt(dwAnswer);
mplew.writeInt(nCorrect);
mplew.writeInt(nRemain);
mplew.writeInt(tRemainInitialQuiz);
}
return mplew.getPacket();
}
public static byte[] showBuffeffect(int cid, int skillid, int effectid) {
return showBuffeffect(cid, skillid, effectid, (byte) 3);
@@ -4246,7 +4273,7 @@ public class MaplePacketCreator {
public static byte[] cancelChair(int id) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.CANCEL_CHAIR.getValue());
if (id == -1) {
if (id < 0) {
mplew.write(0);
} else {
mplew.write(1);
@@ -5414,6 +5441,41 @@ public class MaplePacketCreator {
}
return mplew.getPacket();
}
// RPS_GAME packets thanks to Arnah (Vertisy)
public static byte[] openRPSNPC() {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.RPS_GAME.getValue());
mplew.write(8);// open npc
mplew.writeInt(9000019);
return mplew.getPacket();
}
public static byte[] rpsMesoError(int mesos) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.RPS_GAME.getValue());
mplew.write(0x06);
if (mesos != -1) {
mplew.writeInt(mesos);
}
return mplew.getPacket();
}
public static byte[] rpsSelection(byte selection, byte answer) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.RPS_GAME.getValue());
mplew.write(0x0B);// 11l
mplew.write(selection);
mplew.write(answer);
return mplew.getPacket();
}
public static byte[] rpsMode(byte mode) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.RPS_GAME.getValue());
mplew.write(mode);
return mplew.getPacket();
}
public static byte[] fredrickMessage(byte operation) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
@@ -6678,6 +6740,72 @@ public class MaplePacketCreator {
mplew.writeShort(quest);
return mplew.getPacket();
}
// MAKER_RESULT packets thanks to Arnah (Vertisy)
public static byte[] makerResult(boolean success, int itemMade, int itemCount, int mesos, List<Pair<Integer, Integer>> itemsLost, int catalystID, List<Integer> INCBuffGems) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.MAKER_RESULT.getValue());
mplew.writeInt(success ? 0 : 1); // 0 = success, 1 = fail
mplew.writeInt(1); // 1 or 2 doesn't matter, same methods
mplew.writeBool(!success);
if (success) {
mplew.writeInt(itemMade);
mplew.writeInt(itemCount);
}
mplew.writeInt(itemsLost.size()); // Loop
for (Pair<Integer, Integer> item : itemsLost) {
mplew.writeInt(item.getLeft());
mplew.writeInt(item.getRight());
}
mplew.writeInt(INCBuffGems.size());
for (Integer gem : INCBuffGems) {
mplew.writeInt(gem);
}
if (catalystID != -1) {
mplew.write(1); // stimulator
mplew.writeInt(catalystID);
} else {
mplew.write(0);
}
mplew.writeInt(mesos);
return mplew.getPacket();
}
public static byte[] makerResultCrystal(int itemIdGained, int itemIdLost) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.MAKER_RESULT.getValue());
mplew.writeInt(0); // Always successful!
mplew.writeInt(3); // Monster Crystal
mplew.writeInt(itemIdGained);
mplew.writeInt(itemIdLost);
return mplew.getPacket();
}
public static byte[] makerResultDesynth(int itemId, int mesos, List<Pair<Integer, Integer>> itemsGained) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.MAKER_RESULT.getValue());
mplew.writeInt(0); // Always successful!
mplew.writeInt(4); // Mode Desynth
mplew.writeInt(itemId); // Item desynthed
mplew.writeInt(itemsGained.size()); // Loop of items gained, (int, int)
for (Pair<Integer, Integer> item : itemsGained) {
mplew.writeInt(item.getLeft());
mplew.writeInt(item.getRight());
}
mplew.writeInt(mesos); // Mesos spent.
return mplew.getPacket();
}
public static byte[] makerEnableActions() {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.MAKER_RESULT.getValue());
mplew.writeInt(0); // Always successful!
mplew.writeInt(0); // Monster Crystal
mplew.writeInt(0);
mplew.writeInt(0);
return mplew.getPacket();
}
public static byte[] getMultiMegaphone(String[] messages, int channel, boolean showEar) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
@@ -7025,13 +7153,21 @@ public class MaplePacketCreator {
mplew.write(remove ? 3 : 4);
return mplew.getPacket();
}
public static byte[] sendDueyParcelReceived(String from, boolean quick) { // thanks inhyuk
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.PARCEL.getValue());
mplew.write(0x19);
mplew.writeMapleAsciiString(from);
mplew.writeBool(quick);
return mplew.getPacket();
}
public static byte[] sendDueyNotification(boolean quickDelivery) {
public static byte[] sendDueyParcelNotification(boolean quick) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.PARCEL.getValue());
mplew.write(0x1B);
mplew.writeBool(quickDelivery); // 0 : package received, 1 : quick delivery package
mplew.writeBool(quick); // 0 : package received, 1 : quick delivery package
return mplew.getPacket();
}
@@ -7039,7 +7175,7 @@ public class MaplePacketCreator {
return sendDuey(operation, null);
}
public static byte[] sendDuey(byte operation, List<DueyPackage> packages) {
public static byte[] sendDuey(int operation, List<DueyPackage> packages) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.PARCEL.getValue());
mplew.write(operation);
@@ -7261,20 +7397,12 @@ public class MaplePacketCreator {
return builder.toString();
}
public static byte[] MobDamageMobFriendly(MapleMonster mob, int damage) {
public static byte[] MobDamageMobFriendly(MapleMonster mob, int damage, int remainingHp) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.DAMAGE_MONSTER.getValue());
mplew.writeInt(mob.getObjectId());
mplew.write(1); // direction ?
mplew.writeInt(damage);
mob.applyAndGetHpDamage(damage, false);
int remainingHp = mob.getHp();
if(remainingHp <= 0) {
remainingHp = 0;
mob.getMap().removeMapObject(mob);
}
mplew.writeInt(remainingHp);
mplew.writeInt(mob.getMaxHp());
return mplew.getPacket();
@@ -62,6 +62,8 @@ INSERT IGNORE INTO `makercreatedata` (`id`, `itemid`, `req_level`, `req_maker_le
(0, 4032312, 70, 1, 0, 0, 0, 0, 1, 0),
(0, 2041058, 50, 1, 55000, 0, 1122013, 0, 1, 0),
(0, 2040727, 50, 1, 55000, 0, 1122013, 0, 1, 0),
(0, 4260007, 105, 3, 2200000, 4001126, 0, 0, 5, 0),
(0, 4260008, 105, 3, 5500000, 4001126, 0, 0, 10, 0),
(1, 1002028, 45, 1, 55000, 0, 0, 4130018, 1, 1),
(1, 1002085, 45, 1, 50000, 0, 0, 4130018, 1, 1),
(1, 1002086, 45, 1, 41000, 0, 0, 4130018, 1, 1),
@@ -945,6 +947,10 @@ INSERT IGNORE INTO `makerrecipedata` (`itemid`, `req_item`, `count`) VALUES
(2041058, 4000299, 10),
(2040727, 4000159, 50),
(2040727, 4000299, 10),
(4260007, 4260006, 100),
(4260007, 4001126, 5),
(4260008, 4260007, 50),
(4260008, 4001126, 5),
(1002028, 4007001, 5),
(1002028, 4260000, 5),
(1002085, 4007002, 5),
@@ -1790,7 +1796,7 @@ INSERT IGNORE INTO `makerrecipedata` (`itemid`, `req_item`, `count`) VALUES
(1372016, 4011002, 3),
(1372016, 4260003, 26),
(1382008, 4011002, 3),
(1382008, 4260003, 26),
(1382008, 4260004, 26),
(1372009, 4011002, 4),
(1372009, 4260004, 28),
(1382035, 4011002, 4),
@@ -2432,7 +2438,7 @@ INSERT IGNORE INTO `makerrecipedata` (`itemid`, `req_item`, `count`) VALUES
(1072194, 4260004, 9),
(1072195, 4007006, 9),
(1072195, 4260004, 9),
(1072213, 4007001, 10),
(1072213, 4007003, 10),
(1072213, 4260005, 10),
(1072214, 4007002, 10),
(1072214, 4260005, 10),
@@ -1,447 +0,0 @@
# SQL File autogenerated from the MapleMesoFetcher feature by Ronan Lana.
# Generated data takes into account mob stats such as level and boss for the meso ranges.
# Only mobs with 4 or more items with no meso entry on the DB it was compiled are presented here.
INSERT IGNORE INTO drop_data (`dropperid`, `itemid`, `minimum_quantity`, `maximum_quantity`, `questid`, `chance`) VALUES
(100122, 0, 35, 52, 0, 400000),
(100123, 0, 38, 55, 0, 400000),
(100124, 0, 40, 59, 0, 400000),
(100130, 0, 31, 45, 0, 400000),
(100131, 0, 33, 49, 0, 400000),
(100132, 0, 35, 52, 0, 400000),
(100133, 0, 38, 55, 0, 400000),
(100134, 0, 40, 59, 0, 400000),
(1110130, 0, 49, 72, 0, 400000),
(1140130, 0, 56, 83, 0, 400000),
(2100100, 0, 58, 85, 0, 400000),
(2100101, 0, 60, 88, 0, 400000),
(2100106, 0, 66, 97, 0, 400000),
(2100107, 0, 73, 108, 0, 400000),
(2100108, 0, 78, 115, 0, 400000),
(2110300, 0, 66, 97, 0, 400000),
(2110301, 0, 78, 115, 0, 400000),
(2230105, 0, 64, 94, 0, 400000),
(2230107, 0, 66, 97, 0, 400000),
(2230110, 0, 64, 94, 0, 400000),
(2230111, 0, 66, 97, 0, 400000),
(2230131, 0, 66, 97, 0, 400000),
(3000005, 0, 81, 119, 0, 400000),
(3100101, 0, 86, 127, 0, 400000),
(3100102, 0, 81, 119, 0, 400000),
(3110301, 0, 86, 127, 0, 400000),
(3110302, 0, 95, 140, 0, 400000),
(3110303, 0, 105, 155, 0, 400000),
(3220000, 0, 285, 1400, 0, 400000),
(3220001, 0, 315, 1550, 0, 400000),
(3300000, 0, 81, 119, 0, 400000),
(3300001, 0, 81, 119, 0, 400000),
(3300002, 0, 83, 123, 0, 400000),
(3300003, 0, 86, 127, 0, 400000),
(3300004, 0, 89, 131, 0, 400000),
(3300005, 0, 95, 140, 0, 400000),
(3300006, 0, 95, 140, 0, 400000),
(3300007, 0, 95, 140, 0, 400000),
(3300008, 0, 315, 1550, 0, 400000),
(4110300, 0, 120, 177, 0, 400000),
(4110301, 0, 132, 195, 0, 400000),
(4130103, 0, 423, 2080, 0, 400000),
(4220000, 0, 396, 1950, 0, 400000),
(4230122, 0, 120, 177, 0, 400000),
(4230125, 0, 128, 189, 0, 400000),
(4230400, 0, 132, 195, 0, 400000),
(4230502, 0, 124, 182, 0, 400000),
(4230503, 0, 132, 195, 0, 400000),
(4230504, 0, 132, 195, 0, 400000),
(4230600, 0, 112, 165, 0, 400000),
(4240000, 0, 151, 222, 0, 400000),
(4250000, 0, 120, 177, 0, 400000),
(4250001, 0, 137, 201, 0, 400000),
(5110300, 0, 156, 230, 0, 400000),
(5120500, 0, 190, 280, 0, 400000),
(5120501, 0, 172, 254, 0, 400000),
(5120502, 0, 178, 262, 0, 400000),
(5120505, 0, 203, 299, 0, 400000),
(5120506, 0, 184, 271, 0, 400000),
(5130105, 0, 190, 280, 0, 400000),
(5130108, 0, 196, 289, 0, 400000),
(5220000, 0, 552, 2710, 0, 400000),
(5220002, 0, 468, 2300, 0, 400000),
(5220003, 0, 630, 3090, 0, 400000),
(5220004, 0, 468, 2300, 0, 400000),
(5250000, 0, 184, 271, 0, 400000),
(5250001, 0, 161, 237, 0, 400000),
(5250002, 0, 196, 289, 0, 400000),
(6110300, 0, 255, 377, 0, 400000),
(6130102, 0, 217, 320, 0, 400000),
(6130103, 0, 217, 320, 0, 400000),
(6130203, 0, 217, 320, 0, 400000),
(6130207, 0, 231, 341, 0, 400000),
(6130209, 0, 264, 389, 0, 400000),
(6220000, 0, 765, 3770, 0, 400000),
(6220001, 0, 765, 3770, 0, 400000),
(6230100, 0, 231, 341, 0, 400000),
(6230401, 0, 239, 353, 0, 400000),
(6300005, 0, 765, 3770, 0, 400000),
(6400006, 0, 384, 1890, 0, 400000),
(6400008, 0, 552, 2710, 0, 400000),
(6400009, 0, 552, 2710, 0, 400000),
(7110300, 0, 355, 524, 0, 400000),
(7110301, 0, 332, 490, 0, 400000),
(7120103, 0, 301, 444, 0, 400000),
(7120104, 0, 311, 459, 0, 400000),
(7120106, 0, 355, 524, 0, 400000),
(7120107, 0, 355, 524, 0, 400000),
(7120108, 0, 379, 559, 0, 400000),
(7120109, 0, 405, 597, 0, 400000),
(7130000, 0, 332, 490, 0, 400000),
(7130002, 0, 321, 474, 0, 400000),
(7130003, 0, 367, 541, 0, 400000),
(7130004, 0, 391, 578, 0, 400000),
(7130102, 0, 391, 578, 0, 400000),
(7130103, 0, 332, 490, 0, 400000),
(7130400, 0, 903, 4440, 0, 400000),
(7130401, 0, 903, 4440, 0, 400000),
(7130402, 0, 903, 4440, 0, 400000),
(7130601, 0, 367, 541, 0, 400000),
(7220000, 0, 933, 4590, 0, 400000),
(7220001, 0, 903, 4440, 0, 400000),
(7220002, 0, 1137, 5590, 0, 400000),
(8110300, 0, 418, 617, 0, 400000),
(8120102, 0, 446, 659, 0, 400000),
(8120103, 0, 477, 704, 0, 400000),
(8120104, 0, 509, 752, 0, 400000),
(8120105, 0, 544, 803, 0, 400000),
(8120106, 0, 562, 830, 0, 400000),
(8120107, 0, 562, 830, 0, 400000),
(8140000, 0, 418, 617, 0, 400000),
(8140100, 0, 446, 659, 0, 400000),
(8140511, 0, 581, 871, 0, 400000),
(8140512, 0, 608, 908, 0, 400000),
(8140600, 0, 594, 889, 0, 400000),
(8140702, 0, 637, 946, 0, 400000),
(8140703, 0, 666, 986, 0, 400000),
(8141300, 0, 622, 927, 0, 400000),
(8150000, 0, 2142, 10490, 0, 400000),
(8150100, 0, 714, 1049, 0, 400000),
(8150101, 0, 747, 1093, 0, 400000),
(8150200, 0, 714, 1049, 0, 400000),
(8150201, 0, 800, 1162, 0, 400000),
(8150300, 0, 666, 986, 0, 400000),
(8150301, 0, 730, 1070, 0, 400000),
(8150302, 0, 764, 1115, 0, 400000),
(8190001, 0, 800, 1162, 0, 400000),
(8220003, 0, 3381, 15830, 0, 400000),
(8220005, 0, 4350, 19860, 0, 400000),
(8220006, 0, 5466, 24400, 0, 400000),
(8220007, 0, 1704, 8530, 0, 400000),
(8220009, 0, 1479, 7280, 0, 400000),
(8830000, 0, 2400, 11620, 0, 400000),
(9001009, 0, 1254, 6170, 0, 400000),
(9001011, 0, 95, 140, 0, 400000),
(9200016, 0, 81, 119, 0, 400000),
(9200019, 0, 203, 299, 0, 400000),
(9300011, 0, 109, 160, 0, 400000),
(9300058, 0, 38, 55, 0, 400000),
(9300059, 0, 42, 61, 0, 400000),
(9300060, 0, 120, 177, 0, 400000),
(9300078, 0, 800, 1162, 0, 400000),
(9300080, 0, 282, 416, 0, 400000),
(9300096, 0, 544, 803, 0, 400000),
(9300105, 0, 717, 3530, 0, 400000),
(9300106, 0, 846, 4160, 0, 400000),
(9300127, 0, 81, 119, 0, 400000),
(9300129, 0, 81, 119, 0, 400000),
(9300131, 0, 109, 160, 0, 400000),
(9300132, 0, 81, 119, 0, 400000),
(9300133, 0, 81, 119, 0, 400000),
(9300134, 0, 81, 119, 0, 400000),
(9300136, 0, 243, 1190, 0, 400000),
(9300139, 0, 1296, 6380, 0, 400000),
(9300155, 0, 38, 55, 0, 400000),
(9300160, 0, 396, 1950, 0, 400000),
(9300161, 0, 396, 1950, 0, 400000),
(9300163, 0, 1127, 1583, 0, 400000),
(9300164, 0, 1127, 1583, 0, 400000),
(9300165, 0, 1127, 1583, 0, 400000),
(9300182, 0, 1479, 7280, 0, 400000),
(9300184, 0, 174, 850, 0, 400000),
(9300185, 0, 285, 1400, 0, 400000),
(9300186, 0, 315, 1550, 0, 400000),
(9300187, 0, 336, 1650, 0, 400000),
(9300188, 0, 468, 2300, 0, 400000),
(9300189, 0, 468, 2300, 0, 400000),
(9300190, 0, 552, 2710, 0, 400000),
(9300191, 0, 651, 3200, 0, 400000),
(9300192, 0, 570, 2800, 0, 400000),
(9300193, 0, 630, 3090, 0, 400000),
(9300194, 0, 765, 3770, 0, 400000),
(9300195, 0, 765, 3770, 0, 400000),
(9300196, 0, 765, 3770, 0, 400000),
(9300197, 0, 765, 3770, 0, 400000),
(9300198, 0, 651, 3200, 0, 400000),
(9300199, 0, 903, 4440, 0, 400000),
(9300200, 0, 933, 4590, 0, 400000),
(9300201, 0, 1479, 7280, 0, 400000),
(9300202, 0, 1137, 5590, 0, 400000),
(9300203, 0, 1254, 6170, 0, 400000),
(9300204, 0, 1383, 6810, 0, 400000),
(9300205, 0, 1296, 6380, 0, 400000),
(9300206, 0, 1479, 7280, 0, 400000),
(9300207, 0, 1479, 7280, 0, 400000),
(9300208, 0, 1704, 8530, 0, 400000),
(9300209, 0, 1704, 8530, 0, 400000),
(9300210, 0, 2142, 10490, 0, 400000),
(9300211, 0, 2400, 11620, 0, 400000),
(9300212, 0, 2400, 11620, 0, 400000),
(9300213, 0, 3381, 15830, 0, 400000),
(9300214, 0, 3792, 17550, 0, 400000),
(9300215, 0, 6714, 29370, 0, 400000),
(9300217, 0, 32, 47, 0, 400000),
(9300218, 0, 34, 50, 0, 400000),
(9300219, 0, 34, 50, 0, 400000),
(9300220, 0, 52, 77, 0, 400000),
(9300221, 0, 68, 101, 0, 400000),
(9300222, 0, 75, 111, 0, 400000),
(9300223, 0, 36, 54, 0, 400000),
(9300224, 0, 102, 150, 0, 400000),
(9300225, 0, 102, 150, 0, 400000),
(9300226, 0, 112, 165, 0, 400000),
(9300227, 0, 102, 150, 0, 400000),
(9300228, 0, 146, 215, 0, 400000),
(9300229, 0, 39, 57, 0, 400000),
(9300230, 0, 116, 171, 0, 400000),
(9300231, 0, 137, 201, 0, 400000),
(9300232, 0, 92, 136, 0, 400000),
(9300233, 0, 112, 165, 0, 400000),
(9300234, 0, 86, 127, 0, 400000),
(9300235, 0, 167, 245, 0, 400000),
(9300236, 0, 190, 280, 0, 400000),
(9300237, 0, 210, 309, 0, 400000),
(9300238, 0, 66, 97, 0, 400000),
(9300239, 0, 120, 177, 0, 400000),
(9300240, 0, 132, 195, 0, 400000),
(9300241, 0, 282, 416, 0, 400000),
(9300242, 0, 301, 444, 0, 400000),
(9300243, 0, 190, 280, 0, 400000),
(9300244, 0, 190, 280, 0, 400000),
(9300245, 0, 217, 320, 0, 400000),
(9300246, 0, 231, 341, 0, 400000),
(9300247, 0, 255, 377, 0, 400000),
(9300248, 0, 264, 389, 0, 400000),
(9300249, 0, 301, 444, 0, 400000),
(9300250, 0, 355, 524, 0, 400000),
(9300251, 0, 332, 490, 0, 400000),
(9300252, 0, 132, 195, 0, 400000),
(9300253, 0, 156, 230, 0, 400000),
(9300254, 0, 332, 490, 0, 400000),
(9300255, 0, 141, 208, 0, 400000),
(9300256, 0, 217, 320, 0, 400000),
(9300257, 0, 217, 320, 0, 400000),
(9300258, 0, 255, 377, 0, 400000),
(9300259, 0, 58, 85, 0, 400000),
(9300260, 0, 418, 617, 0, 400000),
(9300261, 0, 544, 803, 0, 400000),
(9300262, 0, 544, 803, 0, 400000),
(9300263, 0, 544, 803, 0, 400000),
(9300264, 0, 764, 1115, 0, 400000),
(9300265, 0, 730, 1070, 0, 400000),
(9300266, 0, 933, 4590, 0, 400000),
(9300267, 0, 1254, 6170, 0, 400000),
(9300268, 0, 933, 4590, 0, 400000),
(9300269, 0, 174, 850, 0, 400000),
(9300270, 0, 418, 617, 0, 400000),
(9300274, 0, 39, 57, 0, 400000),
(9300289, 0, 1704, 8530, 0, 400000),
(9300294, 0, 2142, 10490, 0, 400000),
(9300315, 0, 483, 2370, 0, 400000),
(9300316, 0, 516, 2540, 0, 400000),
(9300317, 0, 552, 2710, 0, 400000),
(9300318, 0, 588, 2890, 0, 400000),
(9300319, 0, 630, 3090, 0, 400000),
(9300320, 0, 672, 3300, 0, 400000),
(9300321, 0, 717, 3530, 0, 400000),
(9300322, 0, 765, 3770, 0, 400000),
(9300332, 0, 112, 165, 0, 400000),
(9300334, 0, 151, 222, 0, 400000),
(9300335, 0, 116, 171, 0, 400000),
(9300336, 0, 137, 201, 0, 400000),
(9300337, 0, 137, 201, 0, 400000),
(9300367, 0, 126, 610, 0, 400000),
(9300368, 0, 174, 850, 0, 400000),
(9300369, 0, 243, 1190, 0, 400000),
(9300370, 0, 336, 1650, 0, 400000),
(9300371, 0, 468, 2300, 0, 400000),
(9300372, 0, 651, 3200, 0, 400000),
(9300373, 0, 903, 4440, 0, 400000),
(9300374, 0, 1254, 6170, 0, 400000),
(9300375, 0, 1704, 8530, 0, 400000),
(9300376, 0, 1704, 8530, 0, 400000),
(9300377, 0, 2691, 12890, 0, 400000),
(9303000, 0, 42, 61, 0, 400000),
(9303001, 0, 42, 61, 0, 400000),
(9303003, 0, 42, 61, 0, 400000),
(9303004, 0, 42, 61, 0, 400000),
(9303005, 0, 71, 104, 0, 400000),
(9303006, 0, 71, 104, 0, 400000),
(9303007, 0, 71, 104, 0, 400000),
(9303008, 0, 71, 104, 0, 400000),
(9303009, 0, 161, 237, 0, 400000),
(9303010, 0, 161, 237, 0, 400000),
(9303011, 0, 161, 237, 0, 400000),
(9303013, 0, 432, 638, 0, 400000),
(9303014, 0, 432, 638, 0, 400000),
(9303016, 0, 432, 638, 0, 400000),
(9400009, 0, 7014, 8225, 0, 400000),
(9400012, 0, 217, 320, 0, 400000),
(9400120, 0, 1911, 9460, 0, 400000),
(9400122, 0, 1911, 9460, 0, 400000),
(9400200, 0, 184, 271, 0, 400000),
(9400203, 0, 112, 165, 0, 400000),
(9400205, 0, 1704, 8530, 0, 400000),
(9400238, 0, 81, 119, 0, 400000),
(9400239, 0, 66, 97, 0, 400000),
(9400241, 0, 38, 55, 0, 400000),
(9400242, 0, 42, 61, 0, 400000),
(9400243, 0, 184, 271, 0, 400000),
(9400244, 0, 210, 309, 0, 400000),
(9400245, 0, 66, 97, 0, 400000),
(9400246, 0, 62, 91, 0, 400000),
(9400247, 0, 81, 119, 0, 400000),
(9400248, 0, 66, 97, 0, 400000),
(9400500, 0, 93, 450, 0, 400000),
(9400501, 0, 35, 52, 0, 400000),
(9400502, 0, 105, 520, 0, 400000),
(9400503, 0, 105, 520, 0, 400000),
(9400504, 0, 31, 45, 0, 400000),
(9400538, 0, 56, 83, 0, 400000),
(9400539, 0, 60, 88, 0, 400000),
(9400540, 0, 68, 101, 0, 400000),
(9400541, 0, 68, 101, 0, 400000),
(9400542, 0, 98, 145, 0, 400000),
(9400543, 0, 116, 171, 0, 400000),
(9400544, 0, 156, 230, 0, 400000),
(9400546, 0, 128, 189, 0, 400000),
(9400547, 0, 73, 108, 0, 400000),
(9400548, 0, 81, 119, 0, 400000),
(9400550, 0, 73, 108, 0, 400000),
(9400556, 0, 60, 88, 0, 400000),
(9400558, 0, 81, 119, 0, 400000),
(9400560, 0, 156, 230, 0, 400000),
(9400561, 0, 217, 320, 0, 400000),
(9400562, 0, 217, 320, 0, 400000),
(9400563, 0, 112, 165, 0, 400000),
(9400565, 0, 60, 88, 0, 400000),
(9400570, 0, 49, 72, 0, 400000),
(9400571, 0, 468, 2300, 0, 400000),
(9400573, 0, 112, 165, 0, 400000),
(9400574, 0, 714, 1049, 0, 400000),
(9400576, 0, 301, 444, 0, 400000),
(9400578, 0, 568, 853, 0, 400000),
(9400579, 0, 714, 1049, 0, 400000),
(9400580, 0, 637, 946, 0, 400000),
(9400581, 0, 418, 617, 0, 400000),
(9400582, 0, 1127, 1583, 0, 400000),
(9400609, 0, 204, 1010, 0, 400000),
(9400612, 0, 204, 1010, 0, 400000),
(9400633, 0, 258, 1270, 0, 400000),
(9400644, 0, 42, 61, 0, 400000),
(9410014, 0, 493, 728, 0, 400000),
(9410015, 0, 1479, 7280, 0, 400000),
(9420507, 0, 146, 215, 0, 400000),
(9420527, 0, 132, 195, 0, 400000),
(9420528, 0, 141, 208, 0, 400000),
(9420529, 0, 167, 245, 0, 400000),
(9420530, 0, 190, 280, 0, 400000),
(9420531, 0, 210, 309, 0, 400000),
(9420532, 0, 210, 309, 0, 400000),
(9420533, 0, 224, 330, 0, 400000),
(9420534, 0, 255, 377, 0, 400000),
(9420535, 0, 282, 416, 0, 400000),
(9420536, 0, 321, 474, 0, 400000),
(9420537, 0, 355, 524, 0, 400000),
(9420538, 0, 446, 659, 0, 400000),
(9420539, 0, 526, 777, 0, 400000),
(9420545, 0, 210, 309, 0, 400000),
(9420550, 0, 210, 309, 0, 400000),
(9500101, 0, 38, 55, 0, 400000),
(9500102, 0, 39, 57, 0, 400000),
(9500103, 0, 49, 72, 0, 400000),
(9500104, 0, 44, 65, 0, 400000),
(9500105, 0, 49, 72, 0, 400000),
(9500106, 0, 62, 91, 0, 400000),
(9500107, 0, 81, 119, 0, 400000),
(9500108, 0, 86, 127, 0, 400000),
(9500109, 0, 86, 127, 0, 400000),
(9500110, 0, 95, 140, 0, 400000),
(9500111, 0, 95, 140, 0, 400000),
(9500112, 0, 95, 140, 0, 400000),
(9500113, 0, 98, 145, 0, 400000),
(9500115, 0, 102, 150, 0, 400000),
(9500116, 0, 112, 165, 0, 400000),
(9500117, 0, 98, 145, 0, 400000),
(9500118, 0, 109, 160, 0, 400000),
(9500119, 0, 109, 160, 0, 400000),
(9500120, 0, 132, 195, 0, 400000),
(9500121, 0, 146, 215, 0, 400000),
(9500122, 0, 151, 222, 0, 400000),
(9500123, 0, 210, 309, 0, 400000),
(9500124, 0, 651, 3200, 0, 400000),
(9500125, 0, 217, 320, 0, 400000),
(9500126, 0, 247, 365, 0, 400000),
(9500127, 0, 273, 402, 0, 400000),
(9500128, 0, 282, 416, 0, 400000),
(9500129, 0, 301, 444, 0, 400000),
(9500130, 0, 903, 4440, 0, 400000),
(9500131, 0, 332, 490, 0, 400000),
(9500132, 0, 355, 524, 0, 400000),
(9500134, 0, 418, 617, 0, 400000),
(9500135, 0, 493, 728, 0, 400000),
(9500136, 0, 682, 1006, 0, 400000),
(9500137, 0, 637, 946, 0, 400000),
(9500138, 0, 568, 853, 0, 400000),
(9500139, 0, 1254, 6170, 0, 400000),
(9500140, 0, 2142, 10490, 0, 400000),
(9500156, 0, 146, 215, 0, 400000),
(9500157, 0, 95, 140, 0, 400000),
(9500158, 0, 903, 4440, 0, 400000),
(9500159, 0, 903, 4440, 0, 400000),
(9500160, 0, 903, 4440, 0, 400000),
(9500161, 0, 418, 617, 0, 400000),
(9500162, 0, 418, 617, 0, 400000),
(9500163, 0, 461, 681, 0, 400000),
(9500164, 0, 544, 803, 0, 400000),
(9500165, 0, 544, 803, 0, 400000),
(9500166, 0, 544, 803, 0, 400000),
(9500178, 0, 112, 165, 0, 400000),
(9500180, 0, 1704, 8530, 0, 400000),
(9500181, 0, 1704, 8530, 0, 400000),
(9500306, 0, 174, 850, 0, 400000),
(9500307, 0, 285, 1400, 0, 400000),
(9500308, 0, 468, 2300, 0, 400000),
(9500309, 0, 552, 2710, 0, 400000),
(9500310, 0, 630, 3090, 0, 400000),
(9500311, 0, 765, 3770, 0, 400000),
(9500312, 0, 903, 4440, 0, 400000),
(9500313, 0, 933, 4590, 0, 400000),
(9500314, 0, 1137, 5590, 0, 400000),
(9500317, 0, 126, 610, 0, 400000),
(9500318, 0, 336, 1650, 0, 400000),
(9500319, 0, 903, 4440, 0, 400000),
(9500321, 0, 42, 61, 0, 400000),
(9500326, 0, 396, 1950, 0, 400000),
(9500327, 0, 243, 1190, 0, 400000),
(9500328, 0, 285, 1400, 0, 400000),
(9500331, 0, 552, 2710, 0, 400000),
(9500332, 0, 396, 1950, 0, 400000),
(9500333, 0, 468, 2300, 0, 400000),
(9500334, 0, 552, 2710, 0, 400000),
(9500335, 0, 468, 2300, 0, 400000),
(9500366, 0, 49, 72, 0, 400000),
(9500367, 0, 49, 72, 0, 400000),
(9500368, 0, 49, 72, 0, 400000),
(9500369, 0, 49, 72, 0, 400000),
(9500370, 0, 49, 72, 0, 400000),
(9500371, 0, 49, 72, 0, 400000),
(9500372, 0, 49, 72, 0, 400000);
DELETE FROM drop_data WHERE dropperid >= 9300184 AND dropperid <= 9300215 AND itemid = 0;
File diff suppressed because it is too large Load Diff
@@ -93,7 +93,7 @@ public class MapleSkillbookChanceFetcher {
int mobid = rs.getInt("dropperid");
int itemid = rs.getInt("itemid");
int expectedChance = 1000;
int expectedChance = 250;
if (mobStats.get(mobid) != null) {
int level = mobStats.get(mobid).getLevel();
+1 -1
View File
@@ -3,7 +3,7 @@
<imgdir name="info">
<int name="version" value="10"/>
<int name="cloud" value="0"/>
<int name="town" value="0"/>
<int name="town" value="1"/>
<int name="swim" value="0"/>
<int name="returnMap" value="922240200"/>
<int name="forcedReturn" value="999999999"/>