Maker-oriented commit
Implemented the multiple features of the Maker skill (equip disassembly, leftover merging into monster crystal and item crafting). Updated the DB with the Maker data featured on the WZ. Added a new table for the strenghtening reagents gain data (compiled with the MapleSkillMakerReagentIndexer). Fixed quests that improves the Maker skill level and some other Maker-related quests.
This commit is contained in:
1 parent
4dd2764776
commit
3b30244239
87 files changed
+8384
-18469
No files matched your search
+8
-4
@@ -19,6 +19,10 @@
|
|||||||
/tools/MapleIdRetriever/dist/
|
/tools/MapleIdRetriever/dist/
|
||||||
/tools/MapleIdRetriever/nbproject/private/
|
/tools/MapleIdRetriever/nbproject/private/
|
||||||
|
|
||||||
|
/tools/MapleMapInfoRetriever/build/
|
||||||
|
/tools/MapleMapInfoRetriever/dist/
|
||||||
|
/tools/MapleMapInfoRetriever/nbproject/private/
|
||||||
|
|
||||||
/tools/MapleMesoFetcher/build/
|
/tools/MapleMesoFetcher/build/
|
||||||
/tools/MapleMesoFetcher/dist/
|
/tools/MapleMesoFetcher/dist/
|
||||||
/tools/MapleMesoFetcher/nbproject/private/
|
/tools/MapleMesoFetcher/nbproject/private/
|
||||||
@@ -31,6 +35,10 @@
|
|||||||
/tools/MapleSkillMakerFetcher/dist/
|
/tools/MapleSkillMakerFetcher/dist/
|
||||||
/tools/MapleSkillMakerFetcher/nbproject/private/
|
/tools/MapleSkillMakerFetcher/nbproject/private/
|
||||||
|
|
||||||
|
/tools/MapleSkillMakerReagentIndexer/build/
|
||||||
|
/tools/MapleSkillMakerReagentIndexer/dist/
|
||||||
|
/tools/MapleSkillMakerReagentIndexer/nbproject/private/
|
||||||
|
|
||||||
/tools/MobBookIndexer/build/
|
/tools/MobBookIndexer/build/
|
||||||
/tools/MobBookIndexer/dist/
|
/tools/MobBookIndexer/dist/
|
||||||
/tools/MobBookIndexer/nbproject/private/
|
/tools/MobBookIndexer/nbproject/private/
|
||||||
@@ -38,7 +46,3 @@
|
|||||||
/tools/MobBookUpdate/build/
|
/tools/MobBookUpdate/build/
|
||||||
/tools/MobBookUpdate/dist/
|
/tools/MobBookUpdate/dist/
|
||||||
/tools/MobBookUpdate/nbproject/private/
|
/tools/MobBookUpdate/nbproject/private/
|
||||||
|
|
||||||
/tools/MapleMapInfoRetriever/build/
|
|
||||||
/tools/MapleMapInfoRetriever/dist/
|
|
||||||
/tools/MapleMapInfoRetriever/nbproject/private/
|
|
||||||
Vendored
BIN
Binary file not shown.
@@ -27,6 +27,10 @@ PQs:
|
|||||||
* BalrogPQ semi-functional.
|
* BalrogPQ semi-functional.
|
||||||
* Capt. Latanica remade as an event (parties can now fight the boss).
|
* Capt. Latanica remade as an event (parties can now fight the boss).
|
||||||
|
|
||||||
|
Skills:
|
||||||
|
* Maker skill features properly developed.
|
||||||
|
* Server is using heurisitics to calculate fee costs for the Maker (errors sums up to 8k mesos, reagent errors stacks up comformant with it's level).
|
||||||
|
|
||||||
Quests:
|
Quests:
|
||||||
* Doll house quest functional.
|
* Doll house quest functional.
|
||||||
* Quests can now reward properly items when matching a reward item with the player's job.
|
* Quests can now reward properly items when matching a reward item with the player's job.
|
||||||
|
|||||||
@@ -686,3 +686,10 @@ Corrigido bug no ThreadTracker n
|
|||||||
Implementado items sendo dropados de reatores intervaladamente, GMS-like.
|
Implementado items sendo dropados de reatores intervaladamente, GMS-like.
|
||||||
Adicionado informação ao jogador que tentar completar uma quest com item necessário equipado.
|
Adicionado informação ao jogador que tentar completar uma quest com item necessário equipado.
|
||||||
Nova ferramenta: MapleMapInfoRetriever. Detecção básica de mapas com sem nó de info em sua estrutura WZ.
|
Nova ferramenta: MapleMapInfoRetriever. Detecção básica de mapas com sem nó de info em sua estrutura WZ.
|
||||||
|
Adicionado scripts para Power B. Fore npc.
|
||||||
|
|
||||||
|
21 - 23 Novembro 2017,
|
||||||
|
Implementado Maker skill (métodos de packets pelo menos já existiam).
|
||||||
|
Corrigido bug em MapleSkillMakerFetcher, atualizado DB com as tabelas normalizadas.
|
||||||
|
Nova ferramenta: MapleSkillMakerReagentIndexer. Agrupa no banco de dados informação pertinente aos reagentes do Maker, para serem usados pelo server.
|
||||||
|
Quests nivelando/utilizando o Maker funcionam corretamente agora.
|
||||||
@@ -2,6 +2,9 @@
|
|||||||
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
|
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
|
||||||
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="2"/>
|
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="2"/>
|
||||||
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
|
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
|
||||||
<group/>
|
<group>
|
||||||
|
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/constants/ServerConstants.java</file>
|
||||||
|
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/MakerItemFactory.java</file>
|
||||||
|
</group>
|
||||||
</open-files>
|
</open-files>
|
||||||
</project-private>
|
</project-private>
|
||||||
+12
-1
@@ -3,6 +3,10 @@ var map = 910060000;
|
|||||||
var num = 5;
|
var num = 5;
|
||||||
var maxp = 5;
|
var maxp = 5;
|
||||||
|
|
||||||
|
function start() {
|
||||||
|
action(1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
function action(mode, type, selection) {
|
function action(mode, type, selection) {
|
||||||
if (mode == 1) {
|
if (mode == 1) {
|
||||||
status++;
|
status++;
|
||||||
@@ -14,10 +18,17 @@ function action(mode, type, selection) {
|
|||||||
status--;
|
status--;
|
||||||
}
|
}
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
if (cm.isQuestStarted(22515) || cm.isQuestStarted(22516) || cm.isQuestStarted(22517) || cm.isQuestStarted(22518)) {
|
if(cm.getLevel() >= 20) {
|
||||||
|
cm.sendOk("This training ground is available only for those under level 20.");
|
||||||
|
cm.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cm.isQuestActive(22515) || cm.isQuestActive(22516) || cm.isQuestActive(22517) || cm.isQuestActive(22518)) {
|
||||||
cm.sendYesNo("Would you like to go in the special Spore Training Center?");
|
cm.sendYesNo("Would you like to go in the special Spore Training Center?");
|
||||||
status = 1;
|
status = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
var selStr = "Would you like to go into the Training Center?";
|
var selStr = "Would you like to go into the Training Center?";
|
||||||
for (var i = 0; i < num; i++) {
|
for (var i = 0; i < num; i++) {
|
||||||
selStr += "\r\n#b#L" + i + "#Training Center " + i + " (" + cm.getPlayerCount(map + i) + "/" + maxp + ")#l#k";
|
selStr += "\r\n#b#L" + i + "#Training Center " + i + " (" + cm.getPlayerCount(map + i) + "/" + maxp + ")#l#k";
|
||||||
|
|||||||
+12
-1
@@ -3,6 +3,10 @@ var map = 910060000;
|
|||||||
var num = 5;
|
var num = 5;
|
||||||
var maxp = 5;
|
var maxp = 5;
|
||||||
|
|
||||||
|
function start() {
|
||||||
|
action(1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
function action(mode, type, selection) {
|
function action(mode, type, selection) {
|
||||||
if (mode == 1) {
|
if (mode == 1) {
|
||||||
status++;
|
status++;
|
||||||
@@ -14,10 +18,17 @@ function action(mode, type, selection) {
|
|||||||
status--;
|
status--;
|
||||||
}
|
}
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
if (cm.isQuestStarted(22515) || cm.isQuestStarted(22516) || cm.isQuestStarted(22517) || cm.isQuestStarted(22518)) {
|
if(cm.getLevel() >= 20) {
|
||||||
|
cm.sendOk("This training ground is available only for those under level 20.");
|
||||||
|
cm.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cm.isQuestActive(22515) || cm.isQuestActive(22516) || cm.isQuestActive(22517) || cm.isQuestActive(22518)) {
|
||||||
cm.sendYesNo("Would you like to go in the special Spore Training Center?");
|
cm.sendYesNo("Would you like to go in the special Spore Training Center?");
|
||||||
status = 1;
|
status = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
var selStr = "Would you like to go into the Training Center?";
|
var selStr = "Would you like to go into the Training Center?";
|
||||||
for (var i = 0; i < num; i++) {
|
for (var i = 0; i < num; i++) {
|
||||||
selStr += "\r\n#b#L" + i + "#Training Center " + i + " (" + cm.getPlayerCount(map + i) + "/" + maxp + ")#l#k";
|
selStr += "\r\n#b#L" + i + "#Training Center " + i + " (" + cm.getPlayerCount(map + i) + "/" + maxp + ")#l#k";
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
var status = -1;
|
||||||
|
var map = 910220000;
|
||||||
|
var num = 5;
|
||||||
|
var maxp = 5;
|
||||||
|
|
||||||
|
function start() {
|
||||||
|
action(1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function action(mode, type, selection) {
|
||||||
|
if (mode == 1) {
|
||||||
|
status++;
|
||||||
|
} else {
|
||||||
|
if (status <= 1) {
|
||||||
|
cm.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
status--;
|
||||||
|
}
|
||||||
|
if (status == 0) {
|
||||||
|
if(cm.getLevel() >= 20) {
|
||||||
|
cm.sendOk("This training ground is available only for those under level 20.");
|
||||||
|
cm.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var selStr = "Would you like to go into the Training Center?";
|
||||||
|
for (var i = 0; i < num; i++) {
|
||||||
|
selStr += "\r\n#b#L" + i + "#Training Center " + i + " (" + cm.getPlayerCount(map + i) + "/" + maxp + ")#l#k";
|
||||||
|
}
|
||||||
|
cm.sendSimple(selStr);
|
||||||
|
} else if (status == 1) {
|
||||||
|
if (selection < 0 || selection >= num) {
|
||||||
|
cm.dispose();
|
||||||
|
} else if (cm.getPlayerCount(map + selection) >= maxp) {
|
||||||
|
cm.sendNext("This training center is full.");
|
||||||
|
status = -1;
|
||||||
|
} else {
|
||||||
|
cm.warp(map + selection, 0);
|
||||||
|
cm.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,10 @@ var map = 910220000;
|
|||||||
var num = 5;
|
var num = 5;
|
||||||
var maxp = 5;
|
var maxp = 5;
|
||||||
|
|
||||||
|
function start() {
|
||||||
|
action(1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
function action(mode, type, selection) {
|
function action(mode, type, selection) {
|
||||||
if (mode == 1) {
|
if (mode == 1) {
|
||||||
status++;
|
status++;
|
||||||
@@ -14,6 +18,12 @@ function action(mode, type, selection) {
|
|||||||
status--;
|
status--;
|
||||||
}
|
}
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
|
if(cm.getLevel() >= 20) {
|
||||||
|
cm.sendOk("This training ground is available only for those under level 20.");
|
||||||
|
cm.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var selStr = "Would you like to go into the Training Center?";
|
var selStr = "Would you like to go into the Training Center?";
|
||||||
for (var i = 0; i < num; i++) {
|
for (var i = 0; i < num; i++) {
|
||||||
selStr += "\r\n#b#L" + i + "#Training Center " + i + " (" + cm.getPlayerCount(map + i) + "/" + maxp + ")#l#k";
|
selStr += "\r\n#b#L" + i + "#Training Center " + i + " (" + cm.getPlayerCount(map + i) + "/" + maxp + ")#l#k";
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
var status = -1;
|
||||||
|
var map = 910120000;
|
||||||
|
var num = 5;
|
||||||
|
var maxp = 5;
|
||||||
|
|
||||||
|
function start() {
|
||||||
|
action(1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function action(mode, type, selection) {
|
||||||
|
if (mode == 1) {
|
||||||
|
status++;
|
||||||
|
} else {
|
||||||
|
if (status <= 1) {
|
||||||
|
cm.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
status--;
|
||||||
|
}
|
||||||
|
if (status == 0) {
|
||||||
|
if(cm.getLevel() >= 20) {
|
||||||
|
cm.sendOk("This training ground is available only for those under level 20.");
|
||||||
|
cm.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var selStr = "Would you like to go into the Training Center?";
|
||||||
|
for (var i = 0; i < num; i++) {
|
||||||
|
selStr += "\r\n#b#L" + i + "#Training Center " + i + " (" + cm.getPlayerCount(map + i) + "/" + maxp + ")#l#k";
|
||||||
|
}
|
||||||
|
cm.sendSimple(selStr);
|
||||||
|
} else if (status == 1) {
|
||||||
|
if (selection < 0 || selection >= num) {
|
||||||
|
cm.dispose();
|
||||||
|
} else if (cm.getPlayerCount(map + selection) >= maxp) {
|
||||||
|
cm.sendNext("This training center is full.");
|
||||||
|
status = -1;
|
||||||
|
} else {
|
||||||
|
cm.warp(map + selection, 0);
|
||||||
|
cm.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,10 @@ var map = 910120000;
|
|||||||
var num = 5;
|
var num = 5;
|
||||||
var maxp = 5;
|
var maxp = 5;
|
||||||
|
|
||||||
|
function start() {
|
||||||
|
action(1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
function action(mode, type, selection) {
|
function action(mode, type, selection) {
|
||||||
if (mode == 1) {
|
if (mode == 1) {
|
||||||
status++;
|
status++;
|
||||||
@@ -14,6 +18,12 @@ function action(mode, type, selection) {
|
|||||||
status--;
|
status--;
|
||||||
}
|
}
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
|
if(cm.getLevel() >= 20) {
|
||||||
|
cm.sendOk("This training ground is available only for those under level 20.");
|
||||||
|
cm.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var selStr = "Would you like to go into the Training Center?";
|
var selStr = "Would you like to go into the Training Center?";
|
||||||
for (var i = 0; i < num; i++) {
|
for (var i = 0; i < num; i++) {
|
||||||
selStr += "\r\n#b#L" + i + "#Training Center " + i + " (" + cm.getPlayerCount(map + i) + "/" + maxp + ")#l#k";
|
selStr += "\r\n#b#L" + i + "#Training Center " + i + " (" + cm.getPlayerCount(map + i) + "/" + maxp + ")#l#k";
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
var status = -1;
|
||||||
|
var map = 910310000;
|
||||||
|
var num = 5;
|
||||||
|
var maxp = 5;
|
||||||
|
|
||||||
|
function start() {
|
||||||
|
action(1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function action(mode, type, selection) {
|
||||||
|
if (mode == 1) {
|
||||||
|
status++;
|
||||||
|
} else {
|
||||||
|
if (status <= 1) {
|
||||||
|
cm.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
status--;
|
||||||
|
}
|
||||||
|
if (status == 0) {
|
||||||
|
if(cm.getLevel() >= 20) {
|
||||||
|
cm.sendOk("This training ground is available only for those under level 20.");
|
||||||
|
cm.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var selStr = "Would you like to go into the Training Center?";
|
||||||
|
for (var i = 0; i < num; i++) {
|
||||||
|
selStr += "\r\n#b#L" + i + "#Training Center " + i + " (" + cm.getPlayerCount(map + i) + "/" + maxp + ")#l#k";
|
||||||
|
}
|
||||||
|
cm.sendSimple(selStr);
|
||||||
|
} else if (status == 1) {
|
||||||
|
if (selection < 0 || selection >= num) {
|
||||||
|
cm.dispose();
|
||||||
|
} else if (cm.getPlayerCount(map + selection) >= maxp) {
|
||||||
|
cm.sendNext("This training center is full.");
|
||||||
|
status = -1;
|
||||||
|
} else {
|
||||||
|
cm.warp(map + selection, 0);
|
||||||
|
cm.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
var status = -1;
|
||||||
|
var map = 910310000;
|
||||||
|
var num = 5;
|
||||||
|
var maxp = 5;
|
||||||
|
|
||||||
|
function start() {
|
||||||
|
action(1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function action(mode, type, selection) {
|
||||||
|
if (mode == 1) {
|
||||||
|
status++;
|
||||||
|
} else {
|
||||||
|
if (status <= 1) {
|
||||||
|
cm.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
status--;
|
||||||
|
}
|
||||||
|
if (status == 0) {
|
||||||
|
if(cm.getLevel() >= 20) {
|
||||||
|
cm.sendOk("This training ground is available only for those under level 20.");
|
||||||
|
cm.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var selStr = "Would you like to go into the Training Center?";
|
||||||
|
for (var i = 0; i < num; i++) {
|
||||||
|
selStr += "\r\n#b#L" + i + "#Training Center " + i + " (" + cm.getPlayerCount(map + i) + "/" + maxp + ")#l#k";
|
||||||
|
}
|
||||||
|
cm.sendSimple(selStr);
|
||||||
|
} else if (status == 1) {
|
||||||
|
if (selection < 0 || selection >= num) {
|
||||||
|
cm.dispose();
|
||||||
|
} else if (cm.getPlayerCount(map + selection) >= maxp) {
|
||||||
|
cm.sendNext("This training center is full.");
|
||||||
|
status = -1;
|
||||||
|
} else {
|
||||||
|
cm.warp(map + selection, 0);
|
||||||
|
cm.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,10 @@ var map = 912030000;
|
|||||||
var num = 5;
|
var num = 5;
|
||||||
var maxp = 5;
|
var maxp = 5;
|
||||||
|
|
||||||
|
function start() {
|
||||||
|
action(1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
function action(mode, type, selection) {
|
function action(mode, type, selection) {
|
||||||
if (mode == 1) {
|
if (mode == 1) {
|
||||||
status++;
|
status++;
|
||||||
@@ -14,6 +18,12 @@ function action(mode, type, selection) {
|
|||||||
status--;
|
status--;
|
||||||
}
|
}
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
|
if(cm.getLevel() >= 20) {
|
||||||
|
cm.sendOk("This training ground is available only for those under level 20.");
|
||||||
|
cm.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var selStr = "Would you like to go into the Training Center?";
|
var selStr = "Would you like to go into the Training Center?";
|
||||||
for (var i = 0; i < num; i++) {
|
for (var i = 0; i < num; i++) {
|
||||||
selStr += "\r\n#b#L" + i + "#Training Center " + i + " (" + cm.getPlayerCount(map + i) + "/" + maxp + ")#l#k";
|
selStr += "\r\n#b#L" + i + "#Training Center " + i + " (" + cm.getPlayerCount(map + i) + "/" + maxp + ")#l#k";
|
||||||
|
|||||||
@@ -3,6 +3,10 @@ var map = 912030000;
|
|||||||
var num = 5;
|
var num = 5;
|
||||||
var maxp = 5;
|
var maxp = 5;
|
||||||
|
|
||||||
|
function start() {
|
||||||
|
action(1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
function action(mode, type, selection) {
|
function action(mode, type, selection) {
|
||||||
if (mode == 1) {
|
if (mode == 1) {
|
||||||
status++;
|
status++;
|
||||||
@@ -14,6 +18,12 @@ function action(mode, type, selection) {
|
|||||||
status--;
|
status--;
|
||||||
}
|
}
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
|
if(cm.getLevel() >= 20) {
|
||||||
|
cm.sendOk("This training ground is available only for those under level 20.");
|
||||||
|
cm.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var selStr = "Would you like to go into the Training Center?";
|
var selStr = "Would you like to go into the Training Center?";
|
||||||
for (var i = 0; i < num; i++) {
|
for (var i = 0; i < num; i++) {
|
||||||
selStr += "\r\n#b#L" + i + "#Training Center " + i + " (" + cm.getPlayerCount(map + i) + "/" + maxp + ")#l#k";
|
selStr += "\r\n#b#L" + i + "#Training Center " + i + " (" + cm.getPlayerCount(map + i) + "/" + maxp + ")#l#k";
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
function enter(pi) {
|
function enter(pi) {
|
||||||
if (pi.getPlayer().haveItem(4031582) == true) {
|
if (pi.getPlayer().haveItem(4031582) == true) {
|
||||||
pi.playPortalSound();
|
pi.playPortalSound();
|
||||||
pi.warp(260000301, 0);
|
pi.warp(260000301, 5);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
pi.playerMessage(5, "You can enter only if you have a Entry Pass to the Palace.");
|
pi.playerMessage(5, "You can enter only if you have a Entry Pass to the Palace.");
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
//some quest where you must use hidden portals
|
//some quest where you must use hidden portals
|
||||||
function enter(pi) {
|
function enter(pi) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the MapleSolaxiaV2 Maple Story Server
|
||||||
|
|
||||||
|
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/>.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
Quest: Carson's Fundamentals of Alchemy
|
||||||
|
*/
|
||||||
|
|
||||||
|
var status = -1;
|
||||||
|
|
||||||
|
function end(mode, type, selection) {
|
||||||
|
if (mode == -1) {
|
||||||
|
qm.dispose();
|
||||||
|
} else {
|
||||||
|
if(mode == 0 && type > 0) {
|
||||||
|
qm.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == 1)
|
||||||
|
status++;
|
||||||
|
else
|
||||||
|
status--;
|
||||||
|
|
||||||
|
if (status == 0) {
|
||||||
|
qm.sendNext("I am to teach you about the fundamentals of Alchemy.");
|
||||||
|
} else if (status == 1) {
|
||||||
|
qm.sendNextPrev("While science is good to take a look on the thoughtful side of the elements that compounds the items, it alone is not nearly enough to devise an item.");
|
||||||
|
} else if (status == 2) {
|
||||||
|
qm.sendNextPrev("In fact, to be able to 'tell the pieces' to become a whole, how should it be done? The rustic ways of the blacksmithing winds up dumbing down some latent potentials of the items.");
|
||||||
|
} else if (status == 3) {
|
||||||
|
qm.sendNextPrev("Alchemy can be employed for this task. Cleanly and swiftly, #rit merges the parts that forms an item with almost no drawbacks#k, making out the most of the process with almost no scrapover, if done right. It takes a while to master it, but once it is done, everything will run out neatly.");
|
||||||
|
} else if (status == 4) {
|
||||||
|
qm.sendNextPrev("And remember this: the maxima of #bExchange#k, the area of the fundamentals of Alchemy where the total amount of the material does not change, is that no item can be created from nothing. Understood?");
|
||||||
|
} else if (status == 5) {
|
||||||
|
qm.gainMeso(-10000);
|
||||||
|
|
||||||
|
qm.forceCompleteQuest();
|
||||||
|
qm.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the MapleSolaxiaV2 Maple Story Server
|
||||||
|
|
||||||
|
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/>.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
Quest: Hughes the Fuse's Basic of Theory of Science
|
||||||
|
*/
|
||||||
|
|
||||||
|
var status = -1;
|
||||||
|
|
||||||
|
function end(mode, type, selection) {
|
||||||
|
if (mode == -1) {
|
||||||
|
qm.dispose();
|
||||||
|
} else {
|
||||||
|
if(mode == 0 && type > 0) {
|
||||||
|
qm.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == 1)
|
||||||
|
status++;
|
||||||
|
else
|
||||||
|
status--;
|
||||||
|
|
||||||
|
if (status == 0) {
|
||||||
|
qm.sendNext("I am to teach you about the basics of the Theory of Science.");
|
||||||
|
} else if (status == 1) {
|
||||||
|
qm.sendNextPrev("Science stages where the alchemy doesn't meet the requirements. All items have molecular constitutions. The #rnature of their arrangements and each intrinsic unit of matter#k defines the many properties an item will have.");
|
||||||
|
} else if (status == 2) {
|
||||||
|
qm.sendNextPrev("This makes true in the scenario of the #rMaker#k as well. One must be able to study the traces of each component that is being used to form the item, to be able to tell if the experiment will utmostly succeed of fail.");
|
||||||
|
} else if (status == 3) {
|
||||||
|
qm.sendNextPrev("Take that in mind: the main perspective of science, that one engine that makes it flows the strongest, whatever scenario it is, is the aspect of #bunderstanding the process#k that generates the results, not simply throwing away tries at will.");
|
||||||
|
} else if (status == 4) {
|
||||||
|
qm.sendNextPrev("That has been made clear, right? Good, then the class is over. Dismissed.");
|
||||||
|
} else if (status == 5) {
|
||||||
|
qm.gainMeso(-10000);
|
||||||
|
|
||||||
|
qm.forceCompleteQuest();
|
||||||
|
qm.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the MapleSolaxiaV2 Maple Story Server
|
||||||
|
|
||||||
|
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/>.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
Quest: Meren's Class on the Actual Practice
|
||||||
|
*/
|
||||||
|
|
||||||
|
var status = -1;
|
||||||
|
|
||||||
|
function end(mode, type, selection) {
|
||||||
|
if (mode == -1) {
|
||||||
|
qm.dispose();
|
||||||
|
} else {
|
||||||
|
if(mode == 0 && type > 0) {
|
||||||
|
qm.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == 1)
|
||||||
|
status++;
|
||||||
|
else
|
||||||
|
status--;
|
||||||
|
|
||||||
|
if (status == 0) {
|
||||||
|
qm.sendNext("So you've come to attend my class, huh? Right, I'll make it fast.");
|
||||||
|
} else if (status == 1) {
|
||||||
|
qm.sendNextPrev("I will teach you the actual application of the #bMaker#k method. All you need to do is have an item in mind to make, gather all the ingredients from the receipt and mix them in a #rscientifically alchemisty way#k. Easy, isn't it?");
|
||||||
|
} else if (status == 2) {
|
||||||
|
qm.sendNextPrev("Let's take producing the #bWeight Earrings#k as an example. There is a rather specific #rductility theory#k to generate it, as any other 'unique' items have, the name going around the #rmain physical force#k acting over the thing we are working on: on that case, the #bDuctility Theory of Gravity#k (as it is a 'Weighted Earrings', got it?).");
|
||||||
|
} else if (status == 3) {
|
||||||
|
qm.sendNextPrev("Ok, now you need to hand me a fee, 10,000 mesos that is, for that information. The collected fee shall be used for acquiring the needed materials for your learning of the fine art of the #bMaker#k.");
|
||||||
|
} else if (status == 4) {
|
||||||
|
qm.gainMeso(-10000);
|
||||||
|
|
||||||
|
qm.forceCompleteQuest();
|
||||||
|
qm.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the MapleSolaxiaV2 Maple Story Server
|
||||||
|
|
||||||
|
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/>.
|
||||||
|
*/
|
||||||
|
/* Maker Skill
|
||||||
|
Moren's Second round of teaching
|
||||||
|
2nd skill level
|
||||||
|
*/
|
||||||
|
|
||||||
|
var status = -1;
|
||||||
|
|
||||||
|
function end(mode, type, selection) {
|
||||||
|
if (mode == -1) {
|
||||||
|
qm.dispose();
|
||||||
|
} else {
|
||||||
|
if(mode == 0 && type > 0) {
|
||||||
|
qm.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == 1)
|
||||||
|
status++;
|
||||||
|
else
|
||||||
|
status--;
|
||||||
|
|
||||||
|
if (status == 0) {
|
||||||
|
qm.sendNext("Hm, so you claim to have brought the #b#t4260003##k? Ok, let's take a look into it.");
|
||||||
|
} else if (status == 1) {
|
||||||
|
if(qm.getQuestProgress(6033) == 1 && qm.haveItem(4260003, 1)) {
|
||||||
|
qm.sendNext("You indeed have crafted a fine piece of Monster Crystal, I see. You passed! Now, I shall teach you the next steps of the Maker skill. Keep the monster crystal with you as well, it's your work.");
|
||||||
|
|
||||||
|
var skillid = Math.floor(qm.getPlayer().getJob().getId() / 1000) * 10000000 + 1007;
|
||||||
|
qm.teachSkill(skillid, 2, 3, -1);
|
||||||
|
|
||||||
|
qm.gainExp(230000 * qm.getPlayer().getExpRate());
|
||||||
|
qm.forceCompleteQuest();
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
qm.sendNext("Hey, what's wrong? I did tell you to make a monster crystal to pass my test, didn't I? Buying one or crafting before the start of the test is NOT part of the deal. Go craft me an #b#t4260003##k.");
|
||||||
|
}
|
||||||
|
|
||||||
|
qm.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the MapleSolaxiaV2 Maple Story Server
|
||||||
|
|
||||||
|
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/>.
|
||||||
|
*/
|
||||||
|
/* Maker Skill
|
||||||
|
A Surprise Outcome
|
||||||
|
3rd skill level
|
||||||
|
*/
|
||||||
|
|
||||||
|
var status = -1;
|
||||||
|
|
||||||
|
function end(mode, type, selection) {
|
||||||
|
if (mode == -1) {
|
||||||
|
qm.dispose();
|
||||||
|
} else {
|
||||||
|
if(mode == 0 && type > 0) {
|
||||||
|
qm.dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == 1)
|
||||||
|
status++;
|
||||||
|
else
|
||||||
|
status--;
|
||||||
|
|
||||||
|
if (status == 0) {
|
||||||
|
qm.sendNext("Bothering me again? What's it?");
|
||||||
|
} else if (status == 1) {
|
||||||
|
if(qm.haveItem(4031980, 1)) {
|
||||||
|
qm.sendNext("You crafted a #b#t4031980##k?! How comes, how did you do it?? ... Well, that can't be helped, I guess. The student surpassed the teacher! Youth sure do wonders to one's perception capabilities.\r\n\r\nYou are now ready to take the last step on mastering the Maker skill, contemplate it at it's finest form!");
|
||||||
|
qm.gainItem(4031980, -1);
|
||||||
|
|
||||||
|
var skillid = Math.floor(qm.getPlayer().getJob().getId() / 1000) * 10000000 + 1007;
|
||||||
|
qm.teachSkill(skillid, 3, 3, -1);
|
||||||
|
|
||||||
|
qm.gainExp(300000 * qm.getPlayer().getExpRate());
|
||||||
|
qm.forceCompleteQuest();
|
||||||
|
} else {
|
||||||
|
qm.sendNext("... Please step aside, I can't finish this work if I'm being distracted at every moment.");
|
||||||
|
}
|
||||||
|
|
||||||
|
qm.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+873
-817
File diff suppressed because it is too large.
Load diff
+15
-15
@@ -14125,8 +14125,8 @@ USE `maplesolaxia`;
|
|||||||
(7140000, 1002640, 1, 1, 0, 700),
|
(7140000, 1002640, 1, 1, 0, 700),
|
||||||
(9300322, 1002640, 1, 1, 0, 40000),
|
(9300322, 1002640, 1, 1, 0, 40000),
|
||||||
(9301004, 1002640, 1, 1, 0, 700),
|
(9301004, 1002640, 1, 1, 0, 700),
|
||||||
(8140002, 4000240, 1, 1, 0, 200000),
|
(8140002, 4000240, 1, 1, 0, 60000),
|
||||||
(9500163, 4000240, 1, 1, 0, 200000),
|
(9500163, 4000240, 1, 1, 0, 60000),
|
||||||
(8140002, 2070005, 1, 1, 0, 400),
|
(8140002, 2070005, 1, 1, 0, 400),
|
||||||
(9500163, 2070005, 1, 1, 0, 400),
|
(9500163, 2070005, 1, 1, 0, 400),
|
||||||
(8140002, 2040707, 1, 1, 0, 750),
|
(8140002, 2040707, 1, 1, 0, 750),
|
||||||
@@ -18142,13 +18142,13 @@ USE `maplesolaxia`;
|
|||||||
(8820012, 2290106, 1, 1, 0, 1000),
|
(8820012, 2290106, 1, 1, 0, 1000),
|
||||||
(8820013, 2290106, 1, 1, 0, 1000),
|
(8820013, 2290106, 1, 1, 0, 1000),
|
||||||
(8820014, 2290106, 1, 1, 0, 1000),
|
(8820014, 2290106, 1, 1, 0, 1000),
|
||||||
(8820000, 4021010, 1, 1, 0, 7000),
|
(8820000, 4021010, 1, 1, 0, 40000),
|
||||||
(8820001, 4021010, 1, 1, 0, 7000),
|
(8820001, 4021010, 1, 1, 0, 40000),
|
||||||
(8820010, 4021010, 1, 1, 0, 7000),
|
(8820010, 4021010, 1, 1, 0, 40000),
|
||||||
(8820011, 4021010, 1, 1, 0, 7000),
|
(8820011, 4021010, 1, 1, 0, 40000),
|
||||||
(8820012, 4021010, 1, 1, 0, 7000),
|
(8820012, 4021010, 1, 1, 0, 40000),
|
||||||
(8820013, 4021010, 1, 1, 0, 7000),
|
(8820013, 4021010, 1, 1, 0, 40000),
|
||||||
(8820014, 4021010, 1, 1, 0, 7000),
|
(8820014, 4021010, 1, 1, 0, 40000),
|
||||||
(8820000, 1122011, 1, 1, 0, 40000),
|
(8820000, 1122011, 1, 1, 0, 40000),
|
||||||
(8820001, 1122011, 1, 1, 0, 40000),
|
(8820001, 1122011, 1, 1, 0, 40000),
|
||||||
(8820010, 1122011, 1, 1, 0, 700),
|
(8820010, 1122011, 1, 1, 0, 700),
|
||||||
@@ -19569,7 +19569,7 @@ USE `maplesolaxia`;
|
|||||||
(9400583, 4030012, 1, 1, 0, 300),
|
(9400583, 4030012, 1, 1, 0, 300),
|
||||||
(9400583, 4010006, 1, 1, 0, 40000),
|
(9400583, 4010006, 1, 1, 0, 40000),
|
||||||
(9400583, 4020007, 1, 1, 0, 40000),
|
(9400583, 4020007, 1, 1, 0, 40000),
|
||||||
(9400583, 4007004, 1, 1, 0, 40000),
|
(9400583, 4007004, 1, 1, 0, 10000),
|
||||||
(9400583, 2000003, 1, 1, 0, 40000),
|
(9400583, 2000003, 1, 1, 0, 40000),
|
||||||
(9400583, 2000005, 1, 1, 0, 20000),
|
(9400583, 2000005, 1, 1, 0, 20000),
|
||||||
(9400583, 2050004, 1, 1, 0, 20000),
|
(9400583, 2050004, 1, 1, 0, 20000),
|
||||||
@@ -19597,8 +19597,8 @@ USE `maplesolaxia`;
|
|||||||
(9400549, 0, 2000, 3000, 0, 400000),
|
(9400549, 0, 2000, 3000, 0, 400000),
|
||||||
(9400638, 0, 100, 200, 0, 400000),
|
(9400638, 0, 100, 200, 0, 400000),
|
||||||
(9400638, 4011007, 1, 1, 0, 1000),
|
(9400638, 4011007, 1, 1, 0, 1000),
|
||||||
(9400638, 4007001, 1, 1, 0, 40000),
|
(9400638, 4007001, 1, 1, 0, 10000),
|
||||||
(9400638, 4007000, 1, 1, 0, 40000),
|
(9400638, 4007000, 1, 1, 0, 10000),
|
||||||
(9400638, 2000001, 1, 1, 0, 40000),
|
(9400638, 2000001, 1, 1, 0, 40000),
|
||||||
(9400638, 2022244, 1, 1, 0, 40000),
|
(9400638, 2022244, 1, 1, 0, 40000),
|
||||||
(9400638, 2010003, 1, 1, 0, 40000),
|
(9400638, 2010003, 1, 1, 0, 40000),
|
||||||
@@ -19608,9 +19608,9 @@ USE `maplesolaxia`;
|
|||||||
(9400638, 1041008, 1, 1, 0, 2000),
|
(9400638, 1041008, 1, 1, 0, 2000),
|
||||||
(9400639, 0, 200, 250, 0, 400000),
|
(9400639, 0, 200, 250, 0, 400000),
|
||||||
(9400639, 4000018, 1, 1, 0, 400000),
|
(9400639, 4000018, 1, 1, 0, 400000),
|
||||||
(9400639, 4130018, 1, 1, 0, 40000),
|
(9400639, 4130018, 1, 1, 0, 5000),
|
||||||
(9400639, 4130009, 1, 1, 0, 40000),
|
(9400639, 4130009, 1, 1, 0, 5000),
|
||||||
(9400639, 4007003, 1, 1, 0, 40000),
|
(9400639, 4007003, 1, 1, 0, 10000),
|
||||||
(9400639, 2000002, 1, 1, 0, 40000),
|
(9400639, 2000002, 1, 1, 0, 40000),
|
||||||
(9400639, 2000006, 1, 1, 0, 40000),
|
(9400639, 2000006, 1, 1, 0, 40000),
|
||||||
(9400639, 2000002, 1, 1, 0, 40000),
|
(9400639, 2000002, 1, 1, 0, 40000),
|
||||||
|
|||||||
@@ -1665,17 +1665,27 @@ public class Commands {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case "givenx":
|
case "givenx":
|
||||||
if (sub.length < 3){
|
if (sub.length < 2){
|
||||||
player.yellowMessage("Syntax: !givenx <playername> <gainnx>");
|
player.yellowMessage("Syntax: !givenx [<playername>] <gainnx>");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
victim = cserv.getPlayerStorage().getCharacterByName(sub[1]);
|
String recv;
|
||||||
|
int value;
|
||||||
|
if(sub.length > 2) {
|
||||||
|
recv = sub[1];
|
||||||
|
value = Integer.parseInt(sub[2]);
|
||||||
|
} else {
|
||||||
|
recv = c.getPlayer().getName();
|
||||||
|
value = Integer.parseInt(sub[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
victim = cserv.getPlayerStorage().getCharacterByName(recv);
|
||||||
if(victim != null) {
|
if(victim != null) {
|
||||||
victim.getCashShop().gainCash(1, Integer.parseInt(sub[2]));
|
victim.getCashShop().gainCash(1, value);
|
||||||
player.message("NX given.");
|
player.message("NX given.");
|
||||||
} else {
|
} else {
|
||||||
player.message("Player '" + sub[1] + "' could not be found on this channel.");
|
player.message("Player '" + recv + "' could not be found on this channel.");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1695,17 +1705,27 @@ public class Commands {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case "givems":
|
case "givems":
|
||||||
if (sub.length < 3){
|
if (sub.length < 2){
|
||||||
player.yellowMessage("Syntax: !givems <playername> <gainms>");
|
player.yellowMessage("Syntax: !givems [<playername>] <gainmeso>");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
victim = cserv.getPlayerStorage().getCharacterByName(sub[1]);
|
String recv_;
|
||||||
|
int value_;
|
||||||
|
if(sub.length > 2) {
|
||||||
|
recv_ = sub[1];
|
||||||
|
value_ = Integer.parseInt(sub[2]);
|
||||||
|
} else {
|
||||||
|
recv_ = c.getPlayer().getName();
|
||||||
|
value_ = Integer.parseInt(sub[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
victim = cserv.getPlayerStorage().getCharacterByName(recv_);
|
||||||
if(victim != null) {
|
if(victim != null) {
|
||||||
victim.gainMeso(Integer.parseInt(sub[2]), true);
|
victim.gainMeso(value_, true);
|
||||||
player.message("MESO given.");
|
player.message("MESO given.");
|
||||||
} else {
|
} else {
|
||||||
player.message("Player '" + sub[1] + "' could not be found on this channel.");
|
player.message("Player '" + recv_ + "' could not be found on this channel.");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MapleSolaxiaV2 Maple Story Server
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 RonanLana
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package constants;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author RonanLana
|
||||||
|
*/
|
||||||
|
public enum EquipType {
|
||||||
|
UNDEFINED(-1),
|
||||||
|
ACCESSORY(0),
|
||||||
|
CAP(100),
|
||||||
|
CAPE(110),
|
||||||
|
COAT(104),
|
||||||
|
FACE(2),
|
||||||
|
GLOVES(108),
|
||||||
|
HAIR(3),
|
||||||
|
LONGCOAT(105),
|
||||||
|
PANTS(106),
|
||||||
|
PET_EQUIP(180),
|
||||||
|
PET_EQUIP_FIELD(181),
|
||||||
|
PET_EQUIP_LABEL(182),
|
||||||
|
PET_EQUIP_QUOTE(183),
|
||||||
|
RING(111),
|
||||||
|
SHIELD(109),
|
||||||
|
SHOES(107),
|
||||||
|
TAMING(190),
|
||||||
|
TAMING_SADDLE(191),
|
||||||
|
SWORD(1302),
|
||||||
|
AXE(1312),
|
||||||
|
MACE(1322),
|
||||||
|
DAGGER(1332),
|
||||||
|
WAND(1372),
|
||||||
|
STAFF(1382),
|
||||||
|
SWORD_2H(1402),
|
||||||
|
AXE_2H(1412),
|
||||||
|
MACE_2H(1422),
|
||||||
|
SPEAR(1432),
|
||||||
|
POLEARM(1442),
|
||||||
|
BOW(1452),
|
||||||
|
CROSSBOW(1462),
|
||||||
|
CLAW(1472),
|
||||||
|
KNUCKLER(1482),
|
||||||
|
PISTOL(1492);
|
||||||
|
|
||||||
|
private final int i;
|
||||||
|
private static final Map<Integer, EquipType> map = new HashMap(34);
|
||||||
|
|
||||||
|
private EquipType(int val) {
|
||||||
|
this.i = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
for (EquipType eqEnum : EquipType.values()) {
|
||||||
|
map.put(eqEnum.i, eqEnum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static EquipType getEquipTypeById(int itemid) {
|
||||||
|
EquipType ret;
|
||||||
|
int val = itemid / 100000;
|
||||||
|
|
||||||
|
if(val == 13 || val == 14) {
|
||||||
|
ret = map.get(itemid / 1000);
|
||||||
|
} else {
|
||||||
|
ret = map.get(itemid / 10000);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ret != null) ? ret : EquipType.UNDEFINED;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -89,6 +89,10 @@ public final class ItemConstants {
|
|||||||
return itemId / 1000 == 5000;
|
return itemId / 1000 == 5000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isAccessory(int itemId) {
|
||||||
|
return itemId >= 1110000 && itemId < 1140000;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isTownScroll(int itemId) {
|
public static boolean isTownScroll(int itemId) {
|
||||||
return itemId >= 2030000 && itemId < 2030021;
|
return itemId >= 2030000 && itemId < 2030021;
|
||||||
}
|
}
|
||||||
@@ -135,4 +139,16 @@ public final class ItemConstants {
|
|||||||
}
|
}
|
||||||
return MapleInventoryType.getByType(type);
|
return MapleInventoryType.getByType(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isMakerReagent(int itemId) {
|
||||||
|
return itemId / 10000 == 425;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isOverall(int itemId) {
|
||||||
|
return itemId / 10000 == 105;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isWeapon(int itemId) {
|
||||||
|
return itemId >= 1302000 && itemId < 1492024;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -65,6 +65,7 @@ public class ServerConstants {
|
|||||||
public static final boolean USE_ERASE_UNTRADEABLE_DROP = true; //Forces flagged untradeable items to disappear when dropped.
|
public static final boolean USE_ERASE_UNTRADEABLE_DROP = true; //Forces flagged untradeable items to disappear when dropped.
|
||||||
public static final boolean USE_ERASE_PET_ON_EXPIRATION = false;//Forces pets to be removed from inventory when expire time comes, rather than converting it to a doll.
|
public static final boolean USE_ERASE_PET_ON_EXPIRATION = false;//Forces pets to be removed from inventory when expire time comes, rather than converting it to a doll.
|
||||||
public static final boolean USE_BUFF_MOST_SIGNIFICANT = true; //When applying buffs, the player will stick with the highest stat boost among the listed, rather than overwriting stats.
|
public static final boolean USE_BUFF_MOST_SIGNIFICANT = true; //When applying buffs, the player will stick with the highest stat boost among the listed, rather than overwriting stats.
|
||||||
|
public static final boolean USE_MAKER_FEE_HEURISTICS = true; //Apply compiled values for stimulants and reagents into the Maker fee calculations (max error revolves around 50k mesos). Set false to use basic constant values instead (results are never higher than requested by the client-side).
|
||||||
|
|
||||||
//Server Rates And Experience
|
//Server Rates And Experience
|
||||||
public static final int EXP_RATE = 10;
|
public static final int EXP_RATE = 10;
|
||||||
@@ -86,7 +87,7 @@ public class ServerConstants {
|
|||||||
public static final long BLOCK_NPC_RACE_CONDT = (long)(0.5 * 1000); //Time the player client must wait before reopening a conversation with an NPC.
|
public static final long BLOCK_NPC_RACE_CONDT = (long)(0.5 * 1000); //Time the player client must wait before reopening a conversation with an NPC.
|
||||||
public static final long PET_LOOT_UPON_ATTACK = (long)(0.7 * 1000); //Time the pet must wait before trying to pick items up.
|
public static final long PET_LOOT_UPON_ATTACK = (long)(0.7 * 1000); //Time the pet must wait before trying to pick items up.
|
||||||
|
|
||||||
//Dangling Items Configuration
|
//Dangling Items/Locks Configuration
|
||||||
public static final int ITEM_EXPIRE_TIME = 3 * 60 * 1000; //Time before items start disappearing. Recommended to be set up to 3 minutes.
|
public static final int ITEM_EXPIRE_TIME = 3 * 60 * 1000; //Time before items start disappearing. Recommended to be set up to 3 minutes.
|
||||||
public static final int ITEM_MONITOR_TIME = 5 * 60 * 1000; //Interval between item monitoring tasks on maps, which checks for dangling (null) item objects on the map item history.
|
public static final int ITEM_MONITOR_TIME = 5 * 60 * 1000; //Interval between item monitoring tasks on maps, which checks for dangling (null) item objects on the map item history.
|
||||||
public static final int LOCK_MONITOR_TIME = 30 * 1000; //Waiting time for a lock to be released. If it reach timed out, a critical server deadlock has made present.
|
public static final int LOCK_MONITOR_TIME = 30 * 1000; //Waiting time for a lock to be released. If it reach timed out, a critical server deadlock has made present.
|
||||||
@@ -98,7 +99,7 @@ public class ServerConstants {
|
|||||||
public static final boolean USE_PERFECT_GM_SCROLL = true; //Scrolls from GMs never uses up slots nor fails.
|
public static final boolean USE_PERFECT_GM_SCROLL = true; //Scrolls from GMs never uses up slots nor fails.
|
||||||
public static final boolean USE_PERFECT_SCROLLING = true; //Scrolls doesn't use slots upon failure.
|
public static final boolean USE_PERFECT_SCROLLING = true; //Scrolls doesn't use slots upon failure.
|
||||||
public static final boolean USE_ENHANCED_CHSCROLL = true; //Equips even more powerful with chaos upgrade.
|
public static final boolean USE_ENHANCED_CHSCROLL = true; //Equips even more powerful with chaos upgrade.
|
||||||
public static final boolean USE_ENHANCED_CRAFTING = true; //Applys chaos scroll on every equip crafted.
|
public static final boolean USE_ENHANCED_CRAFTING = true; //Apply chaos scroll on every equip crafted.
|
||||||
public static final int SCROLL_CHANCE_RATE = 0; //Number of rolls for success on a scroll, set 0 for default.
|
public static final int SCROLL_CHANCE_RATE = 0; //Number of rolls for success on a scroll, set 0 for default.
|
||||||
public static final int CHSCROLL_STAT_RANGE = 6; //Stat upgrade range (-N, N) on chaos scrolls.
|
public static final int CHSCROLL_STAT_RANGE = 6; //Stat upgrade range (-N, N) on chaos scrolls.
|
||||||
|
|
||||||
@@ -118,10 +119,12 @@ public class ServerConstants {
|
|||||||
public static final boolean USE_EQUIPMNT_LVLUP_SLOTS = true;//Equips can upgrade slots at level up.
|
public static final boolean USE_EQUIPMNT_LVLUP_SLOTS = true;//Equips can upgrade slots at level up.
|
||||||
public static final boolean USE_EQUIPMNT_LVLUP_POWER = true;//Enable more powerful stat upgrades at equip level up.
|
public static final boolean USE_EQUIPMNT_LVLUP_POWER = true;//Enable more powerful stat upgrades at equip level up.
|
||||||
public static final boolean USE_SPIKES_AVOID_BANISH = true; //Shoes equipped with spikes prevents mobs from banishing wearer.
|
public static final boolean USE_SPIKES_AVOID_BANISH = true; //Shoes equipped with spikes prevents mobs from banishing wearer.
|
||||||
public static final boolean USE_CHAIR_EXTRAHEAL = true; //Enable map chairs to further recover player's HP and MP (player must have the Chair Mastery skill).
|
|
||||||
public static final int MAX_EQUIPMNT_LVLUP_STAT_UP = 10000; //Max stat upgrade an equipment can have on a levelup.
|
public static final int MAX_EQUIPMNT_LVLUP_STAT_UP = 10000; //Max stat upgrade an equipment can have on a levelup.
|
||||||
public static final int MAX_EQUIPMNT_STAT = 32767; //Max stat on an equipment by leveling up.
|
public static final int MAX_EQUIPMNT_STAT = 32767; //Max stat on an equipment by leveling up.
|
||||||
public static final int USE_EQUIPMNT_LVLUP = 7; //All equips lvlup at max level of N, set 1 to disable.
|
public static final int USE_EQUIPMNT_LVLUP = 7; //All equips lvlup at max level of N, set 1 to disable.
|
||||||
|
|
||||||
|
//Map-Chair Configuration
|
||||||
|
public static final boolean USE_CHAIR_EXTRAHEAL = true; //Enable map chairs to further recover player's HP and MP (player must have the Chair Mastery skill).
|
||||||
public static final byte CHAIR_EXTRA_HEAL_HP = 70; //Each chair extra heal proc increasing HP.
|
public static final byte CHAIR_EXTRA_HEAL_HP = 70; //Each chair extra heal proc increasing HP.
|
||||||
public static final byte CHAIR_EXTRA_HEAL_MP = 42; //Each chair extra heal proc increasing MP.
|
public static final byte CHAIR_EXTRA_HEAL_MP = 42; //Each chair extra heal proc increasing MP.
|
||||||
|
|
||||||
|
|||||||
@@ -21,12 +21,27 @@
|
|||||||
*/
|
*/
|
||||||
package net.server.channel.handlers;
|
package net.server.channel.handlers;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import constants.ItemConstants;
|
||||||
import client.MapleClient;
|
import client.MapleClient;
|
||||||
|
import client.inventory.Equip;
|
||||||
|
import client.inventory.Item;
|
||||||
|
import client.inventory.MapleInventoryType;
|
||||||
|
import constants.EquipType;
|
||||||
|
import constants.ServerConstants;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.text.NumberFormat;
|
||||||
import net.AbstractMaplePacketHandler;
|
import net.AbstractMaplePacketHandler;
|
||||||
import server.MapleInventoryManipulator;
|
import server.MapleInventoryManipulator;
|
||||||
import server.MapleItemInformationProvider;
|
import server.MapleItemInformationProvider;
|
||||||
import server.MakerItemFactory;
|
import server.MakerItemFactory;
|
||||||
import server.MakerItemFactory.MakerItemCreateEntry;
|
import server.MakerItemFactory.MakerItemCreateEntry;
|
||||||
|
import tools.FilePrinter;
|
||||||
import tools.Pair;
|
import tools.Pair;
|
||||||
import tools.MaplePacketCreator;
|
import tools.MaplePacketCreator;
|
||||||
import tools.data.input.SeekableLittleEndianAccessor;
|
import tools.data.input.SeekableLittleEndianAccessor;
|
||||||
@@ -36,50 +51,317 @@ import tools.data.input.SeekableLittleEndianAccessor;
|
|||||||
* @author Jay Estrella, Ronan
|
* @author Jay Estrella, Ronan
|
||||||
*/
|
*/
|
||||||
public final class MakerSkillHandler extends AbstractMaplePacketHandler {
|
public final class MakerSkillHandler extends AbstractMaplePacketHandler {
|
||||||
private MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
private static MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||||
slea.readInt();
|
int type = slea.readInt();
|
||||||
int toCreate = slea.readInt();
|
int toCreate = slea.readInt();
|
||||||
|
int toDisassemble = -1, pos = -1;
|
||||||
|
boolean makerSucceeded = true;
|
||||||
|
|
||||||
|
MakerItemCreateEntry recipe;
|
||||||
|
Map<Integer, Short> reagentids = new LinkedHashMap<>();
|
||||||
|
int stimulantid = -1;
|
||||||
|
|
||||||
|
if(type == 3) { // building monster crystal
|
||||||
|
int fromLeftover = toCreate;
|
||||||
|
toCreate = ii.getMakerCrystalFromLeftover(toCreate);
|
||||||
|
if(toCreate == -1) {
|
||||||
|
c.announce(MaplePacketCreator.serverNotice(1, ii.getName(toCreate) + " is unavailable for Monster Crystal conversion."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
recipe = MakerItemFactory.generateLeftoverCrystalEntry(fromLeftover);
|
||||||
|
} 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);
|
||||||
|
} else {
|
||||||
|
c.announce(MaplePacketCreator.serverNotice(1, ii.getName(toCreate) + " is unavailable for Monster Crystal disassembly."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c.announce(MaplePacketCreator.serverNotice(1, "An unknown error occurred when trying to apply that item for disassembly."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(toCreate < 2000000) { // only equips uses stimulant and reagents
|
||||||
|
if(slea.readByte() != 0) { // stimulant
|
||||||
|
stimulantid = getMakerStimulant(toCreate);
|
||||||
|
if(!c.getAbstractPlayerInteraction().haveItem(stimulantid)) {
|
||||||
|
stimulantid = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int reagents = Math.min(slea.readInt(), getMakerReagentSlots(toCreate));
|
||||||
|
for(int i = 0; i < reagents; i++) { // crystals
|
||||||
|
int reagentid = slea.readInt();
|
||||||
|
if(ItemConstants.isMakerReagent(reagentid)) {
|
||||||
|
Short r = reagentids.get(reagentid);
|
||||||
|
if(r == null) {
|
||||||
|
reagentids.put(reagentid, (short) 1);
|
||||||
|
} else {
|
||||||
|
reagentids.put(reagentid, (short) (r + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Pair<Integer, Short>> toUpdate = new LinkedList<>();
|
||||||
|
for(Entry<Integer, Short> r : reagentids.entrySet()) {
|
||||||
|
int qty = c.getAbstractPlayerInteraction().getItemQuantity(r.getKey());
|
||||||
|
|
||||||
|
if(qty < r.getValue()) {
|
||||||
|
toUpdate.add(new Pair<>(r.getKey(), (short) qty));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove those not present on player inventory
|
||||||
|
if(!toUpdate.isEmpty()) {
|
||||||
|
for(Pair<Integer, Short> r : toUpdate) {
|
||||||
|
if(r.getRight() > 0) {
|
||||||
|
reagentids.put(r.getLeft(), r.getRight());
|
||||||
|
} else {
|
||||||
|
reagentids.remove(r.getLeft());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!reagentids.isEmpty()) removeOddMakerReagents(toCreate, reagentids);
|
||||||
|
}
|
||||||
|
|
||||||
|
recipe = MakerItemFactory.getItemCreateEntry(toCreate, stimulantid, reagentids);
|
||||||
|
}
|
||||||
|
|
||||||
MakerItemCreateEntry recipe = MakerItemFactory.getItemCreateEntry(toCreate);
|
|
||||||
short createStatus = getCreateStatus(c, recipe);
|
short createStatus = getCreateStatus(c, recipe);
|
||||||
|
|
||||||
switch(createStatus) {
|
switch(createStatus) {
|
||||||
case 4: // no req skill level
|
case -1:// non-available for Maker itemid has been tried to forge
|
||||||
c.announce(MaplePacketCreator.serverNotice(1, "You don't have enough Maker level to complete this operation."));
|
FilePrinter.printError(FilePrinter.EXPLOITS, "Player " + c.getPlayer().getName() + " tried to craft itemid " + toCreate + " using the Maker skill.");
|
||||||
break;
|
c.announce(MaplePacketCreator.serverNotice(1, "The requested item could not be crafted on this operation."));
|
||||||
|
|
||||||
case 3: // no meso
|
|
||||||
c.announce(MaplePacketCreator.serverNotice(1, "You don't have enough mesos to complete this operation."));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2: // no req level
|
|
||||||
c.announce(MaplePacketCreator.serverNotice(1, "You don't have enough level to complete this operation."));
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: // no items
|
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 " + recipe.getRewardAmount() + " " + ii.getName(toCreate) + "."));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
case 2: // no meso
|
||||||
if (!c.getPlayer().getInventory(ii.getInventoryType(toCreate)).isFull()) {
|
NumberFormat nf = new DecimalFormat("#,###,###,###");
|
||||||
for (Pair<Integer, Integer> p : recipe.getReqItems()) {
|
c.announce(MaplePacketCreator.serverNotice(1, "You don't have enough mesos (" + nf.format(recipe.getCost()) + ") to complete this operation."));
|
||||||
int toRemove = p.getLeft();
|
break;
|
||||||
MapleInventoryManipulator.removeById(c, ii.getInventoryType(toRemove), toRemove, p.getRight(), false, false);
|
|
||||||
}
|
|
||||||
MapleInventoryManipulator.addById(c, toCreate, (short) recipe.getRewardAmount());
|
|
||||||
|
|
||||||
c.announce(MaplePacketCreator.serverNotice(1, "You have created " + recipe.getRewardAmount() + " " + ii.getName(toCreate) + "."));
|
case 3: // no req level
|
||||||
c.announce(MaplePacketCreator.showMakerEffect());
|
c.announce(MaplePacketCreator.serverNotice(1, "You don't have enough level to complete this operation."));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4: // no req skill level
|
||||||
|
c.announce(MaplePacketCreator.serverNotice(1, "You don't have enough Maker level to complete this operation."));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (MapleInventoryManipulator.checkSpace(c, toCreate, (short) recipe.getRewardAmount(), "")) {
|
||||||
|
for (Pair<Integer, Integer> p : recipe.getReqItems()) {
|
||||||
|
c.getAbstractPlayerInteraction().gainItem(p.getLeft(), (short) -p.getRight());
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
c.getPlayer().setCS(true);
|
||||||
|
c.getAbstractPlayerInteraction().gainItem(toCreate, (short) recipe.getRewardAmount());
|
||||||
|
c.getPlayer().setCS(false);
|
||||||
|
} else {
|
||||||
|
if(stimulantid != -1) c.getAbstractPlayerInteraction().gainItem(stimulantid, (short) -1);
|
||||||
|
if(!reagentids.isEmpty()) {
|
||||||
|
for(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 && c.getPlayer().getQuestStatus(6033) == 1) {
|
||||||
|
c.getAbstractPlayerInteraction().setQuestProgress(6033, 1);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
c.announce(MaplePacketCreator.serverNotice(1, "Your inventory is full."));
|
c.announce(MaplePacketCreator.serverNotice(1, "Your inventory is full."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private short getCreateStatus(MapleClient c, MakerItemCreateEntry recipe) {
|
// checks and prevents hackers from PE'ing Maker operations with invalid operations
|
||||||
|
private static void removeOddMakerReagents(int toCreate, Map<Integer, Short> reagentids) {
|
||||||
|
Map<Integer, Integer> reagentType = new LinkedHashMap<>();
|
||||||
|
List<Integer> toRemove = new LinkedList<>();
|
||||||
|
|
||||||
|
boolean isWeapon = ItemConstants.isWeapon(toCreate);
|
||||||
|
|
||||||
|
for(Entry<Integer, Short> r : reagentids.entrySet()) {
|
||||||
|
int curRid = r.getKey();
|
||||||
|
int type = r.getKey() / 100;
|
||||||
|
|
||||||
|
if(type < 42502 && !isWeapon) { // only weapons should gain w.att/m.att from these.
|
||||||
|
toRemove.add(curRid);
|
||||||
|
} else {
|
||||||
|
Integer tableRid = reagentType.get(type);
|
||||||
|
|
||||||
|
if(tableRid != null) {
|
||||||
|
if(tableRid < curRid) {
|
||||||
|
toRemove.add(tableRid);
|
||||||
|
reagentType.put(type, curRid);
|
||||||
|
} else {
|
||||||
|
toRemove.add(curRid);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reagentType.put(type, curRid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// removing less effective gems of repeated type
|
||||||
|
for(Integer i : toRemove) {
|
||||||
|
reagentids.remove(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// only quantity 1 of each gem will be accepted by the Maker skill
|
||||||
|
for(Integer i : reagentids.keySet()) {
|
||||||
|
reagentids.put(i, (short) 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getMakerReagentSlots(int itemId) {
|
||||||
|
try {
|
||||||
|
int eqpLevel = ii.getEquipStats(itemId).get("reqLevel");
|
||||||
|
|
||||||
|
if(eqpLevel < 78) {
|
||||||
|
return 1;
|
||||||
|
} else if(eqpLevel >= 78 && eqpLevel < 108) {
|
||||||
|
return 2;
|
||||||
|
} else {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
} catch(NullPointerException npe) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getMakerStimulant(int itemId) {
|
||||||
|
EquipType et = EquipType.getEquipTypeById(itemId);
|
||||||
|
|
||||||
|
switch(et) {
|
||||||
|
case GLOVES:
|
||||||
|
return 4130000;
|
||||||
|
|
||||||
|
case SHOES:
|
||||||
|
return 4130001;
|
||||||
|
|
||||||
|
case SWORD:
|
||||||
|
return 4130002;
|
||||||
|
|
||||||
|
case AXE:
|
||||||
|
return 4130003;
|
||||||
|
|
||||||
|
case MACE:
|
||||||
|
return 4130004;
|
||||||
|
|
||||||
|
case SWORD_2H:
|
||||||
|
return 4130005;
|
||||||
|
|
||||||
|
case AXE_2H:
|
||||||
|
return 4130006;
|
||||||
|
|
||||||
|
case MACE_2H:
|
||||||
|
return 4130007;
|
||||||
|
|
||||||
|
case SPEAR:
|
||||||
|
return 4130008;
|
||||||
|
|
||||||
|
case POLEARM:
|
||||||
|
return 4130009;
|
||||||
|
|
||||||
|
case WAND:
|
||||||
|
return 4130010;
|
||||||
|
|
||||||
|
case STAFF:
|
||||||
|
return 4130011;
|
||||||
|
|
||||||
|
case BOW:
|
||||||
|
return 4130012;
|
||||||
|
|
||||||
|
case CROSSBOW:
|
||||||
|
return 4130013;
|
||||||
|
|
||||||
|
case DAGGER:
|
||||||
|
return 4130014;
|
||||||
|
|
||||||
|
case CLAW:
|
||||||
|
return 4130015;
|
||||||
|
|
||||||
|
case KNUCKLER:
|
||||||
|
return 4130016;
|
||||||
|
|
||||||
|
case PISTOL:
|
||||||
|
return 4130017;
|
||||||
|
|
||||||
|
case CAP:
|
||||||
|
return 4130018;
|
||||||
|
|
||||||
|
case COAT:
|
||||||
|
return 4130019;
|
||||||
|
|
||||||
|
case PANTS:
|
||||||
|
return 4130020;
|
||||||
|
|
||||||
|
case LONGCOAT:
|
||||||
|
return 4130021;
|
||||||
|
|
||||||
|
case SHIELD:
|
||||||
|
return 4130022;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static short getCreateStatus(MapleClient c, MakerItemCreateEntry recipe) {
|
||||||
|
if(recipe == null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if(!hasItems(c, recipe)) {
|
if(!hasItems(c, recipe)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -99,7 +381,7 @@ public final class MakerSkillHandler extends AbstractMaplePacketHandler {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasItems(MapleClient c, MakerItemCreateEntry recipe) {
|
private static boolean hasItems(MapleClient c, MakerItemCreateEntry recipe) {
|
||||||
for (Pair<Integer, Integer> p : recipe.getReqItems()) {
|
for (Pair<Integer, Integer> p : recipe.getReqItems()) {
|
||||||
int itemId = p.getLeft();
|
int itemId = p.getLeft();
|
||||||
if (c.getPlayer().getInventory(ii.getInventoryType(itemId)).countById(itemId) < p.getRight()) {
|
if (c.getPlayer().getInventory(ii.getInventoryType(itemId)).countById(itemId) < p.getRight()) {
|
||||||
@@ -108,4 +390,84 @@ public final class MakerSkillHandler extends AbstractMaplePacketHandler {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean addBoostedMakerItem(MapleClient c, int itemid, int stimulantid, Map<Integer, Short> reagentids) {
|
||||||
|
if(stimulantid != -1 && !ii.rollSuccessChance(90.0)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Item item = ii.getEquipById(itemid);
|
||||||
|
if(item == null) return false;
|
||||||
|
|
||||||
|
Equip eqp = (Equip)item;
|
||||||
|
if(ItemConstants.isAccessory(item.getItemId()) && eqp.getUpgradeSlots() <= 0) eqp.setUpgradeSlots(3);
|
||||||
|
|
||||||
|
if(ServerConstants.USE_ENHANCED_CRAFTING == true) {
|
||||||
|
if(!(c.getPlayer().isGM() && ServerConstants.USE_PERFECT_GM_SCROLL)) {
|
||||||
|
eqp.setUpgradeSlots((byte)(eqp.getUpgradeSlots() + 1));
|
||||||
|
}
|
||||||
|
item = MapleItemInformationProvider.getInstance().scrollEquipWithId(eqp, 2049100, true, 0, c.getPlayer().isGM());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!reagentids.isEmpty()) {
|
||||||
|
Map<String, Integer> stats = new LinkedHashMap<>();
|
||||||
|
List<Short> randOption = new LinkedList<>();
|
||||||
|
List<Short> randStat = new LinkedList<>();
|
||||||
|
|
||||||
|
for(Entry<Integer, Short> r : reagentids.entrySet()) {
|
||||||
|
Pair<String, Integer> reagentBuff = ii.getMakerReagentStatUpgrade(r.getKey());
|
||||||
|
|
||||||
|
if(reagentBuff != null) {
|
||||||
|
String s = reagentBuff.getLeft();
|
||||||
|
|
||||||
|
if(s.substring(0, 4).contains("rand")) {
|
||||||
|
if(s.substring(4).equals("Stat")) {
|
||||||
|
randStat.add((short) (reagentBuff.getRight() * r.getValue()));
|
||||||
|
} else {
|
||||||
|
randOption.add((short) (reagentBuff.getRight() * r.getValue()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
String stat = s.substring(3);
|
||||||
|
|
||||||
|
if(!stat.equals("ReqLevel")) { // improve req level... really?
|
||||||
|
switch (stat) {
|
||||||
|
case "MaxHP":
|
||||||
|
stat = "MHP";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "MaxMP":
|
||||||
|
stat = "MMP";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer d = stats.get(stat);
|
||||||
|
if(d == null) {
|
||||||
|
stats.put(stat, reagentBuff.getRight() * r.getValue());
|
||||||
|
} else {
|
||||||
|
stats.put(stat, d + (reagentBuff.getRight() * r.getValue()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ii.improveEquipStats(eqp, stats);
|
||||||
|
|
||||||
|
for(Short s : randStat) {
|
||||||
|
ii.scrollOptionEquipWithChaos(eqp, s, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Short s : randOption) {
|
||||||
|
ii.scrollOptionEquipWithChaos(eqp, s, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(stimulantid != -1) {
|
||||||
|
eqp = ii.randomizeUpgradeStats(eqp);
|
||||||
|
}
|
||||||
|
|
||||||
|
MapleInventoryManipulator.addFromDrop(c, item, false, -1);
|
||||||
|
c.announce(MaplePacketCreator.getShowItemGain(itemid, (short) 1, true));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -342,14 +342,9 @@ public class AbstractPlayerInteraction {
|
|||||||
|
|
||||||
public Item evolvePet(byte slot, int afterId) {
|
public Item evolvePet(byte slot, int afterId) {
|
||||||
MaplePet evolved = null;
|
MaplePet evolved = null;
|
||||||
MaplePet target = null;
|
MaplePet target;
|
||||||
Item tmp;
|
|
||||||
|
|
||||||
long period = 90; //refreshes expiration date: 90 days
|
long period = 90 * 24 * 60 * 60 * 1000; //refreshes expiration date: 90 days
|
||||||
period *= 24;
|
|
||||||
period *= 60;
|
|
||||||
period *= 60;
|
|
||||||
period *= 1000;
|
|
||||||
|
|
||||||
target = getPlayer().getPet(slot);
|
target = getPlayer().getPet(slot);
|
||||||
if(target == null) {
|
if(target == null) {
|
||||||
@@ -357,7 +352,7 @@ public class AbstractPlayerInteraction {
|
|||||||
return(null);
|
return(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp = gainItem(afterId, (short)1, false, true, period, target);
|
Item tmp = gainItem(afterId, (short) 1, false, true, period, target);
|
||||||
getPlayer().unequipPet(target, true, false);
|
getPlayer().unequipPet(target, true, false);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -410,18 +405,13 @@ public class AbstractPlayerInteraction {
|
|||||||
return gainItem(id, quantity, randomStats, showMessage, expires, null);
|
return gainItem(id, quantity, randomStats, showMessage, expires, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isAccessory(int id) {
|
|
||||||
int val = id / 10000;
|
|
||||||
return(val >= 111 && val <= 113);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Item gainItem(int id, short quantity, boolean randomStats, boolean showMessage, long expires, MaplePet from) {
|
public Item gainItem(int id, short quantity, boolean randomStats, boolean showMessage, long expires, MaplePet from) {
|
||||||
Item item = null;
|
Item item = null;
|
||||||
MaplePet evolved = null;
|
MaplePet evolved;
|
||||||
int petId = -1;
|
int petId = -1;
|
||||||
|
|
||||||
if (quantity >= 0) {
|
if (quantity >= 0) {
|
||||||
if (id >= 5000000 && id <= 5000100) {
|
if (ItemConstants.isPet(id)) {
|
||||||
petId = MaplePet.createPet(id);
|
petId = MaplePet.createPet(id);
|
||||||
|
|
||||||
if(from != null) {
|
if(from != null) {
|
||||||
@@ -451,12 +441,13 @@ public class AbstractPlayerInteraction {
|
|||||||
|
|
||||||
if(item != null) {
|
if(item != null) {
|
||||||
Equip it = (Equip)item;
|
Equip it = (Equip)item;
|
||||||
if(isAccessory(item.getItemId()) && it.getUpgradeSlots() <= 0) it.setUpgradeSlots(3);
|
if(ItemConstants.isAccessory(item.getItemId()) && it.getUpgradeSlots() <= 0) it.setUpgradeSlots(3);
|
||||||
|
|
||||||
if(ServerConstants.USE_ENHANCED_CRAFTING == true && c.getPlayer().getCS() == true) {
|
if(ServerConstants.USE_ENHANCED_CRAFTING == true && c.getPlayer().getCS() == true) {
|
||||||
Equip eqp = (Equip)item;
|
Equip eqp = (Equip)item;
|
||||||
|
if(!(c.getPlayer().isGM() && ServerConstants.USE_PERFECT_GM_SCROLL)) {
|
||||||
eqp.setUpgradeSlots((byte)(eqp.getUpgradeSlots() + 1));
|
eqp.setUpgradeSlots((byte)(eqp.getUpgradeSlots() + 1));
|
||||||
|
}
|
||||||
item = MapleItemInformationProvider.getInstance().scrollEquipWithId(item, 2049100, true, 0, c.getPlayer().isGM());
|
item = MapleItemInformationProvider.getInstance().scrollEquipWithId(item, 2049100, true, 0, c.getPlayer().isGM());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,8 +104,18 @@ public class CashShop {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ItemConstants.EXPIRING_ITEMS) {
|
if (ItemConstants.EXPIRING_ITEMS) {
|
||||||
|
if(period == 1) {
|
||||||
if(itemId == 5211048 || itemId == 5360042) { // 4 Hour 2X coupons, the period is 1, but we don't want them to last a day.
|
if(itemId == 5211048 || itemId == 5360042) { // 4 Hour 2X coupons, the period is 1, but we don't want them to last a day.
|
||||||
item.setExpiration(System.currentTimeMillis() + (1000 * 60 * 60 * 4));
|
item.setExpiration(System.currentTimeMillis() + (1000 * 60 * 60 * 4));
|
||||||
|
/*
|
||||||
|
} else if(itemId == 5211047 || itemId == 5360014) { // 3 Hour 2X coupons, unused as of now
|
||||||
|
item.setExpiration(System.currentTimeMillis() + (1000 * 60 * 60 * 3));
|
||||||
|
*/
|
||||||
|
} else if(itemId == 5211060) { // 2 Hour 3X coupons.
|
||||||
|
item.setExpiration(System.currentTimeMillis() + (1000 * 60 * 60 * 2));
|
||||||
|
} else {
|
||||||
|
item.setExpiration(System.currentTimeMillis() + (1000 * 60 * 60 * 24));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
item.setExpiration(System.currentTimeMillis() + (1000 * 60 * 60 * 24 * period));
|
item.setExpiration(System.currentTimeMillis() + (1000 * 60 * 60 * 24 * period));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,76 +21,148 @@
|
|||||||
*/
|
*/
|
||||||
package server;
|
package server;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import constants.EquipType;
|
||||||
import java.sql.PreparedStatement;
|
import constants.ServerConstants;
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import tools.DatabaseConnection;
|
import java.util.Map.Entry;
|
||||||
import tools.Pair;
|
import tools.Pair;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Jay Estrella
|
* @author Jay Estrella, Ronan
|
||||||
*/
|
*/
|
||||||
public class MakerItemFactory {
|
public class MakerItemFactory {
|
||||||
private static Map<Integer, MakerItemCreateEntry> createCache = new HashMap<Integer, MakerItemCreateEntry>();
|
private static MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
||||||
|
|
||||||
public static MakerItemCreateEntry getItemCreateEntry(int toCreate) {
|
public static MakerItemCreateEntry getItemCreateEntry(int toCreate, int stimulantid, Map<Integer, Short> reagentids) {
|
||||||
if (createCache.get(toCreate) != null) {
|
MakerItemCreateEntry makerEntry = ii.getMakerItemEntry(toCreate);
|
||||||
return createCache.get(toCreate);
|
if(makerEntry == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// THEY DECIDED FOR SOME BIZARRE PATTERN ON THE FEE THING, ALMOST RANDOMIZED.
|
||||||
|
if(stimulantid != -1) {
|
||||||
|
makerEntry.addCost(getMakerStimulantFee(toCreate));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!reagentids.isEmpty()) {
|
||||||
|
for(Entry<Integer, Short> r : reagentids.entrySet()) {
|
||||||
|
makerEntry.addCost((getMakerReagentFee(toCreate, ((r.getKey() % 10) + 1))) * r.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
makerEntry.trimCost(); // "commit" the real cost of the recipe.
|
||||||
|
return makerEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MakerItemCreateEntry generateLeftoverCrystalEntry(int fromLeftoverid) {
|
||||||
|
MakerItemCreateEntry ret = new MakerItemCreateEntry(0, 0, 1, 1);
|
||||||
|
ret.addReqItem(fromLeftoverid, 100);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MakerItemCreateEntry generateDisassemblyCrystalEntry(int cost, int crystalGain) { // equipment at specific position already taken
|
||||||
|
MakerItemCreateEntry ret = new MakerItemCreateEntry(cost, 0, 1, crystalGain);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getMakerStimulantFee(int itemid) {
|
||||||
|
if(ServerConstants.USE_MAKER_FEE_HEURISTICS) {
|
||||||
|
EquipType et = EquipType.getEquipTypeById(itemid);
|
||||||
|
int eqpLevel = ii.getEquipStats(itemid).get("reqLevel");
|
||||||
|
|
||||||
|
switch(et) {
|
||||||
|
case CAP:
|
||||||
|
return 1145.736246 * Math.exp(0.03336832546 * eqpLevel);
|
||||||
|
|
||||||
|
case LONGCOAT:
|
||||||
|
return 2117.469118 * Math.exp(0.03355349137 * eqpLevel);
|
||||||
|
|
||||||
|
case SHOES:
|
||||||
|
return 1218.624674 * Math.exp(0.0342266043 * eqpLevel);
|
||||||
|
|
||||||
|
case GLOVES:
|
||||||
|
return 2129.531152 * Math.exp(0.03421778102 * eqpLevel);
|
||||||
|
|
||||||
|
case COAT:
|
||||||
|
return 1770.630579 * Math.exp(0.03359768677 * eqpLevel);
|
||||||
|
|
||||||
|
case PANTS:
|
||||||
|
return 1442.98837 * Math.exp(0.03444783295 * eqpLevel);
|
||||||
|
|
||||||
|
case SHIELD:
|
||||||
|
return 6312.40136 * Math.exp(0.0237929527 * eqpLevel);
|
||||||
|
|
||||||
|
default: // weapons
|
||||||
|
return 4313.581428 * Math.exp(0.03147837094 * eqpLevel);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
return 14000;
|
||||||
Connection con = DatabaseConnection.getConnection();
|
|
||||||
PreparedStatement ps = con.prepareStatement("SELECT req_level, req_maker_level, req_meso, quantity FROM makercreatedata WHERE itemid = ?");
|
|
||||||
ps.setInt(1, toCreate);
|
|
||||||
ResultSet rs = ps.executeQuery();
|
|
||||||
int reqLevel = 0;
|
|
||||||
int reqMakerLevel = 0;
|
|
||||||
int cost = 0;
|
|
||||||
int toGive = 0;
|
|
||||||
if (rs.next()) {
|
|
||||||
reqLevel = rs.getInt("req_level");
|
|
||||||
reqMakerLevel = rs.getInt("req_maker_level");
|
|
||||||
cost = rs.getInt("req_meso");
|
|
||||||
toGive = rs.getInt("quantity");
|
|
||||||
}
|
|
||||||
ps.close();
|
|
||||||
rs.close();
|
|
||||||
MakerItemCreateEntry ret = new MakerItemCreateEntry(cost, reqLevel, reqMakerLevel, toGive);
|
|
||||||
ps = con.prepareStatement("SELECT req_item, count FROM makerrecipedata WHERE itemid = ?");
|
|
||||||
ps.setInt(1, toCreate);
|
|
||||||
rs = ps.executeQuery();
|
|
||||||
while (rs.next()) {
|
|
||||||
ret.addReqItem(rs.getInt("req_item"), rs.getInt("count"));
|
|
||||||
}
|
|
||||||
rs.close();
|
|
||||||
ps.close();
|
|
||||||
con.close();
|
|
||||||
createCache.put(toCreate, ret);
|
|
||||||
} catch (SQLException sqle) {
|
|
||||||
sqle.printStackTrace();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return createCache.get(toCreate);
|
|
||||||
|
private static double getMakerReagentFee(int itemid, int reagentLevel) {
|
||||||
|
if(ServerConstants.USE_MAKER_FEE_HEURISTICS) {
|
||||||
|
EquipType et = EquipType.getEquipTypeById(itemid);
|
||||||
|
int eqpLevel = ii.getEquipStats(itemid).get("reqLevel");
|
||||||
|
|
||||||
|
switch(et) {
|
||||||
|
case CAP:
|
||||||
|
return 5592.01613 * Math.exp(0.02914576018 * eqpLevel) * reagentLevel;
|
||||||
|
|
||||||
|
case LONGCOAT:
|
||||||
|
return 3405.23441 * Math.exp(0.03413001038 * eqpLevel) * reagentLevel;
|
||||||
|
|
||||||
|
case SHOES:
|
||||||
|
return 2115.697484 * Math.exp(0.0354881705 * eqpLevel) * reagentLevel;
|
||||||
|
|
||||||
|
case GLOVES:
|
||||||
|
return 4684.040894 * Math.exp(0.03166500585 * eqpLevel) * reagentLevel;
|
||||||
|
|
||||||
|
case COAT:
|
||||||
|
return 2955.89017 * Math.exp(0.0339948456 * eqpLevel) * reagentLevel;
|
||||||
|
|
||||||
|
case PANTS:
|
||||||
|
return 1774.722181 * Math.exp(0.03854321409 * eqpLevel) * reagentLevel;
|
||||||
|
|
||||||
|
case SHIELD:
|
||||||
|
return 12014.11296 * Math.exp(0.02185471162 * eqpLevel) * reagentLevel;
|
||||||
|
|
||||||
|
default: // weapons
|
||||||
|
return 4538.650247 * Math.exp(0.0371980303 * eqpLevel) * reagentLevel;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return 8000 * reagentLevel;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class MakerItemCreateEntry {
|
public static class MakerItemCreateEntry {
|
||||||
private int reqLevel, reqMakerLevel;
|
private int reqLevel, reqMakerLevel;
|
||||||
private int cost;
|
private double cost;
|
||||||
private List<Pair<Integer, Integer>> reqItems = new ArrayList<Pair<Integer, Integer>>(); // itemId / amount
|
private int reqCost;
|
||||||
|
private List<Pair<Integer, Integer>> reqItems = new ArrayList<>(); // itemId / amount
|
||||||
private int toGive;
|
private int toGive;
|
||||||
|
|
||||||
private MakerItemCreateEntry(int cost, int reqLevel, int reqMakerLevel, int toGive) {
|
public MakerItemCreateEntry(int cost, int reqLevel, int reqMakerLevel, int toGive) {
|
||||||
this.cost = cost;
|
this.cost = cost;
|
||||||
this.reqLevel = reqLevel;
|
this.reqLevel = reqLevel;
|
||||||
this.reqMakerLevel = reqMakerLevel;
|
this.reqMakerLevel = reqMakerLevel;
|
||||||
this.toGive = toGive;
|
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() {
|
public int getRewardAmount() {
|
||||||
return toGive;
|
return toGive;
|
||||||
}
|
}
|
||||||
@@ -108,11 +180,20 @@ public class MakerItemFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int getCost() {
|
public int getCost() {
|
||||||
return cost;
|
return reqCost;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addCost(double amount) {
|
||||||
|
cost += amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addReqItem(int itemId, int amount) {
|
protected void addReqItem(int itemId, int amount) {
|
||||||
reqItems.add(new Pair<>(itemId, amount));
|
reqItems.add(new Pair<>(itemId, amount));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void trimCost() {
|
||||||
|
reqCost = (int) (cost / 1000);
|
||||||
|
reqCost *= 1000;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -410,7 +410,7 @@ public class MapleInventoryManipulator {
|
|||||||
}
|
}
|
||||||
if (dst == -6) { // unequip the overall
|
if (dst == -6) { // unequip the overall
|
||||||
Item top = c.getPlayer().getInventory(MapleInventoryType.EQUIPPED).getItem((short) -5);
|
Item top = c.getPlayer().getInventory(MapleInventoryType.EQUIPPED).getItem((short) -5);
|
||||||
if (top != null && isOverall(top.getItemId())) {
|
if (top != null && ItemConstants.isOverall(top.getItemId())) {
|
||||||
if (c.getPlayer().getInventory(MapleInventoryType.EQUIP).isFull()) {
|
if (c.getPlayer().getInventory(MapleInventoryType.EQUIP).isFull()) {
|
||||||
c.announce(MaplePacketCreator.getInventoryFull());
|
c.announce(MaplePacketCreator.getInventoryFull());
|
||||||
c.announce(MaplePacketCreator.getShowInventoryFull());
|
c.announce(MaplePacketCreator.getShowInventoryFull());
|
||||||
@@ -420,7 +420,7 @@ public class MapleInventoryManipulator {
|
|||||||
}
|
}
|
||||||
} else if (dst == -5) {
|
} else if (dst == -5) {
|
||||||
final Item bottom = c.getPlayer().getInventory(MapleInventoryType.EQUIPPED).getItem((short) -6);
|
final Item bottom = c.getPlayer().getInventory(MapleInventoryType.EQUIPPED).getItem((short) -6);
|
||||||
if (bottom != null && isOverall(source.getItemId())) {
|
if (bottom != null && ItemConstants.isOverall(source.getItemId())) {
|
||||||
if (c.getPlayer().getInventory(MapleInventoryType.EQUIP).isFull()) {
|
if (c.getPlayer().getInventory(MapleInventoryType.EQUIP).isFull()) {
|
||||||
c.announce(MaplePacketCreator.getInventoryFull());
|
c.announce(MaplePacketCreator.getInventoryFull());
|
||||||
c.announce(MaplePacketCreator.getShowInventoryFull());
|
c.announce(MaplePacketCreator.getShowInventoryFull());
|
||||||
@@ -477,7 +477,7 @@ public class MapleInventoryManipulator {
|
|||||||
target.setPosition(src);
|
target.setPosition(src);
|
||||||
c.getPlayer().getInventory(MapleInventoryType.EQUIP).addFromDB(target);
|
c.getPlayer().getInventory(MapleInventoryType.EQUIP).addFromDB(target);
|
||||||
}
|
}
|
||||||
if (c.getPlayer().getBuffedValue(MapleBuffStat.BOOSTER) != null && isWeapon(source.getItemId())) {
|
if (c.getPlayer().getBuffedValue(MapleBuffStat.BOOSTER) != null && ItemConstants.isWeapon(source.getItemId())) {
|
||||||
c.getPlayer().cancelBuffStats(MapleBuffStat.BOOSTER);
|
c.getPlayer().cancelBuffStats(MapleBuffStat.BOOSTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -590,12 +590,4 @@ public class MapleInventoryManipulator {
|
|||||||
private static boolean isDroppedItemRestricted(Item it) {
|
private static boolean isDroppedItemRestricted(Item it) {
|
||||||
return ServerConstants.USE_ERASE_UNTRADEABLE_DROP && ((it.getFlag() & ItemConstants.UNTRADEABLE) == ItemConstants.UNTRADEABLE);
|
return ServerConstants.USE_ERASE_UNTRADEABLE_DROP && ((it.getFlag() & ItemConstants.UNTRADEABLE) == ItemConstants.UNTRADEABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isOverall(int itemId) {
|
|
||||||
return itemId / 10000 == 105;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isWeapon(int itemId) {
|
|
||||||
return itemId >= 1302000 && itemId < 1492024;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -66,7 +66,9 @@ import constants.skills.Assassin;
|
|||||||
import constants.skills.Gunslinger;
|
import constants.skills.Gunslinger;
|
||||||
import constants.skills.NightWalker;
|
import constants.skills.NightWalker;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
|
import server.MakerItemFactory.MakerItemCreateEntry;
|
||||||
import server.life.MapleMonsterInformationProvider;
|
import server.life.MapleMonsterInformationProvider;
|
||||||
|
import server.life.MapleLifeFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -111,6 +113,10 @@ public class MapleItemInformationProvider {
|
|||||||
protected Map<Integer, Boolean> isQuestItemCache = new HashMap<>();
|
protected Map<Integer, Boolean> isQuestItemCache = new HashMap<>();
|
||||||
protected Map<Integer, String> equipmentSlotCache = new HashMap<>();
|
protected Map<Integer, String> equipmentSlotCache = new HashMap<>();
|
||||||
protected Map<Integer, Boolean> noCancelMouseCache = new HashMap<>();
|
protected Map<Integer, Boolean> noCancelMouseCache = new HashMap<>();
|
||||||
|
protected Map<Integer, Integer> mobCrystalMakerCache = new HashMap<>();
|
||||||
|
protected Map<Integer, Pair<String, Integer>> statUpgradeMakerCache = new HashMap<>();
|
||||||
|
protected Map<Integer, MakerItemFactory.MakerItemCreateEntry> makerItemCache = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
private MapleItemInformationProvider() {
|
private MapleItemInformationProvider() {
|
||||||
loadCardIdData();
|
loadCardIdData();
|
||||||
@@ -575,11 +581,77 @@ public class MapleItemInformationProvider {
|
|||||||
return (short)Math.min(Short.MAX_VALUE, value);
|
return (short)Math.min(Short.MAX_VALUE, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static short chscrollRandomizedStat() {
|
private static short chscrollRandomizedStat(int range) {
|
||||||
return (short) Randomizer.rand(-ServerConstants.CHSCROLL_STAT_RANGE, ServerConstants.CHSCROLL_STAT_RANGE);
|
return (short) Randomizer.rand(-range, range);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void scrollEquipWithChaos(Equip nEquip) {
|
public void scrollOptionEquipWithChaos(Equip nEquip, int range, boolean option) {
|
||||||
|
// option: watk, matk, wdef, mdef, spd, jump, hp, mp
|
||||||
|
// stat: dex, luk, str, int, avoid, acc
|
||||||
|
|
||||||
|
if(!option) {
|
||||||
|
if (nEquip.getStr() > 0) {
|
||||||
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setStr(getMaximumShortMaxIfOverflow(nEquip.getStr(), (nEquip.getStr() + chscrollRandomizedStat(range))));
|
||||||
|
else nEquip.setStr(getMaximumShortMaxIfOverflow(0, (nEquip.getStr() + chscrollRandomizedStat(range))));
|
||||||
|
}
|
||||||
|
if (nEquip.getDex() > 0) {
|
||||||
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setDex(getMaximumShortMaxIfOverflow(nEquip.getDex(), (nEquip.getDex() + chscrollRandomizedStat(range))));
|
||||||
|
else nEquip.setDex(getMaximumShortMaxIfOverflow(0, (nEquip.getDex() + chscrollRandomizedStat(range))));
|
||||||
|
}
|
||||||
|
if (nEquip.getInt() > 0) {
|
||||||
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setInt(getMaximumShortMaxIfOverflow(nEquip.getInt(), (nEquip.getInt() + chscrollRandomizedStat(range))));
|
||||||
|
else nEquip.setInt(getMaximumShortMaxIfOverflow(0, (nEquip.getInt() + chscrollRandomizedStat(range))));
|
||||||
|
}
|
||||||
|
if (nEquip.getLuk() > 0) {
|
||||||
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setLuk(getMaximumShortMaxIfOverflow(nEquip.getLuk(), (nEquip.getLuk() + chscrollRandomizedStat(range))));
|
||||||
|
else nEquip.setLuk(getMaximumShortMaxIfOverflow(0, (nEquip.getLuk() + chscrollRandomizedStat(range))));
|
||||||
|
}
|
||||||
|
if (nEquip.getAcc() > 0) {
|
||||||
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setAcc(getMaximumShortMaxIfOverflow(nEquip.getAcc(), (nEquip.getAcc() + chscrollRandomizedStat(range))));
|
||||||
|
else nEquip.setAcc(getMaximumShortMaxIfOverflow(0, (nEquip.getAcc() + chscrollRandomizedStat(range))));
|
||||||
|
}
|
||||||
|
if (nEquip.getAvoid() > 0) {
|
||||||
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setAvoid(getMaximumShortMaxIfOverflow(nEquip.getAvoid(), (nEquip.getAvoid() + chscrollRandomizedStat(range))));
|
||||||
|
else nEquip.setAvoid(getMaximumShortMaxIfOverflow(0, (nEquip.getAvoid() + chscrollRandomizedStat(range))));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (nEquip.getWatk() > 0) {
|
||||||
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setWatk(getMaximumShortMaxIfOverflow(nEquip.getWatk(), (nEquip.getWatk() + chscrollRandomizedStat(range))));
|
||||||
|
else nEquip.setWatk(getMaximumShortMaxIfOverflow(0, (nEquip.getWatk() + chscrollRandomizedStat(range))));
|
||||||
|
}
|
||||||
|
if (nEquip.getWdef() > 0) {
|
||||||
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setWdef(getMaximumShortMaxIfOverflow(nEquip.getWdef(), (nEquip.getWdef() + chscrollRandomizedStat(range))));
|
||||||
|
else nEquip.setWdef(getMaximumShortMaxIfOverflow(0, (nEquip.getWdef() + chscrollRandomizedStat(range))));
|
||||||
|
}
|
||||||
|
if (nEquip.getMatk() > 0) {
|
||||||
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setMatk(getMaximumShortMaxIfOverflow(nEquip.getMatk(), (nEquip.getMatk() + chscrollRandomizedStat(range))));
|
||||||
|
else nEquip.setMatk(getMaximumShortMaxIfOverflow(0, (nEquip.getMatk() + chscrollRandomizedStat(range))));
|
||||||
|
}
|
||||||
|
if (nEquip.getMdef() > 0) {
|
||||||
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setMdef(getMaximumShortMaxIfOverflow(nEquip.getMdef(), (nEquip.getMdef() + chscrollRandomizedStat(range))));
|
||||||
|
else nEquip.setMdef(getMaximumShortMaxIfOverflow(0, (nEquip.getMdef() + chscrollRandomizedStat(range))));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nEquip.getSpeed() > 0) {
|
||||||
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setSpeed(getMaximumShortMaxIfOverflow(nEquip.getSpeed(), (nEquip.getSpeed() + chscrollRandomizedStat(range))));
|
||||||
|
else nEquip.setSpeed(getMaximumShortMaxIfOverflow(0, (nEquip.getSpeed() + chscrollRandomizedStat(range))));
|
||||||
|
}
|
||||||
|
if (nEquip.getJump() > 0) {
|
||||||
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setJump(getMaximumShortMaxIfOverflow(nEquip.getJump(), (nEquip.getJump() + chscrollRandomizedStat(range))));
|
||||||
|
else nEquip.setJump(getMaximumShortMaxIfOverflow(0, (nEquip.getJump() + chscrollRandomizedStat(range))));
|
||||||
|
}
|
||||||
|
if (nEquip.getHp() > 0) {
|
||||||
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setHp(getMaximumShortMaxIfOverflow(nEquip.getHp(), (nEquip.getHp() + chscrollRandomizedStat(range))));
|
||||||
|
else nEquip.setHp(getMaximumShortMaxIfOverflow(0, (nEquip.getHp() + chscrollRandomizedStat(range))));
|
||||||
|
}
|
||||||
|
if (nEquip.getMp() > 0) {
|
||||||
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setMp(getMaximumShortMaxIfOverflow(nEquip.getMp(), (nEquip.getMp() + chscrollRandomizedStat(range))));
|
||||||
|
else nEquip.setMp(getMaximumShortMaxIfOverflow(0, (nEquip.getMp() + chscrollRandomizedStat(range))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scrollEquipWithChaos(Equip nEquip, int range) {
|
||||||
if(ServerConstants.SCROLL_CHANCE_RATE > 0) {
|
if(ServerConstants.SCROLL_CHANCE_RATE > 0) {
|
||||||
int temp;
|
int temp;
|
||||||
short curStr, curDex, curInt, curLuk, curWatk, curWdef, curMatk, curMdef, curAcc, curAvoid, curSpeed, curJump, curHp, curMp;
|
short curStr, curDex, curInt, curLuk, curWatk, curWdef, curMatk, curMdef, curAcc, curAvoid, curSpeed, curJump, curHp, curMp;
|
||||||
@@ -618,99 +690,99 @@ public class MapleItemInformationProvider {
|
|||||||
|
|
||||||
for(int i = 0; i < ServerConstants.SCROLL_CHANCE_RATE; i++) {
|
for(int i = 0; i < ServerConstants.SCROLL_CHANCE_RATE; i++) {
|
||||||
if (nEquip.getStr() > 0) {
|
if (nEquip.getStr() > 0) {
|
||||||
if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curStr + chscrollRandomizedStat();
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curStr + chscrollRandomizedStat(range);
|
||||||
else temp = nEquip.getStr() + chscrollRandomizedStat();
|
else temp = nEquip.getStr() + chscrollRandomizedStat(range);
|
||||||
|
|
||||||
curStr = getMaximumShortMaxIfOverflow(temp, curStr);
|
curStr = getMaximumShortMaxIfOverflow(temp, curStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nEquip.getDex() > 0) {
|
if (nEquip.getDex() > 0) {
|
||||||
if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curDex + chscrollRandomizedStat();
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curDex + chscrollRandomizedStat(range);
|
||||||
else temp = nEquip.getDex() + chscrollRandomizedStat();
|
else temp = nEquip.getDex() + chscrollRandomizedStat(range);
|
||||||
|
|
||||||
curDex = getMaximumShortMaxIfOverflow(temp, curDex);
|
curDex = getMaximumShortMaxIfOverflow(temp, curDex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nEquip.getInt() > 0) {
|
if (nEquip.getInt() > 0) {
|
||||||
if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curInt + chscrollRandomizedStat();
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curInt + chscrollRandomizedStat(range);
|
||||||
else temp = nEquip.getInt() + chscrollRandomizedStat();
|
else temp = nEquip.getInt() + chscrollRandomizedStat(range);
|
||||||
|
|
||||||
curInt = getMaximumShortMaxIfOverflow(temp, curInt);
|
curInt = getMaximumShortMaxIfOverflow(temp, curInt);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nEquip.getLuk() > 0) {
|
if (nEquip.getLuk() > 0) {
|
||||||
if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curLuk + chscrollRandomizedStat();
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curLuk + chscrollRandomizedStat(range);
|
||||||
else temp = nEquip.getLuk() + chscrollRandomizedStat();
|
else temp = nEquip.getLuk() + chscrollRandomizedStat(range);
|
||||||
|
|
||||||
curLuk = getMaximumShortMaxIfOverflow(temp, curLuk);
|
curLuk = getMaximumShortMaxIfOverflow(temp, curLuk);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nEquip.getWatk() > 0) {
|
if (nEquip.getWatk() > 0) {
|
||||||
if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curWatk + chscrollRandomizedStat();
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curWatk + chscrollRandomizedStat(range);
|
||||||
else temp = nEquip.getWatk() + chscrollRandomizedStat();
|
else temp = nEquip.getWatk() + chscrollRandomizedStat(range);
|
||||||
|
|
||||||
curWatk = getMaximumShortMaxIfOverflow(temp, curWatk);
|
curWatk = getMaximumShortMaxIfOverflow(temp, curWatk);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nEquip.getWdef() > 0) {
|
if (nEquip.getWdef() > 0) {
|
||||||
if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curWdef + chscrollRandomizedStat();
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curWdef + chscrollRandomizedStat(range);
|
||||||
else temp = nEquip.getWdef() + chscrollRandomizedStat();
|
else temp = nEquip.getWdef() + chscrollRandomizedStat(range);
|
||||||
|
|
||||||
curWdef = getMaximumShortMaxIfOverflow(temp, curWdef);
|
curWdef = getMaximumShortMaxIfOverflow(temp, curWdef);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nEquip.getMatk() > 0) {
|
if (nEquip.getMatk() > 0) {
|
||||||
if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curMatk + chscrollRandomizedStat();
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curMatk + chscrollRandomizedStat(range);
|
||||||
else temp = nEquip.getMatk() + chscrollRandomizedStat();
|
else temp = nEquip.getMatk() + chscrollRandomizedStat(range);
|
||||||
|
|
||||||
curMatk = getMaximumShortMaxIfOverflow(temp, curMatk);
|
curMatk = getMaximumShortMaxIfOverflow(temp, curMatk);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nEquip.getMdef() > 0) {
|
if (nEquip.getMdef() > 0) {
|
||||||
if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curMdef + chscrollRandomizedStat();
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curMdef + chscrollRandomizedStat(range);
|
||||||
else temp = nEquip.getMdef() + chscrollRandomizedStat();
|
else temp = nEquip.getMdef() + chscrollRandomizedStat(range);
|
||||||
|
|
||||||
curMdef = getMaximumShortMaxIfOverflow(temp, curMdef);
|
curMdef = getMaximumShortMaxIfOverflow(temp, curMdef);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nEquip.getAcc() > 0) {
|
if (nEquip.getAcc() > 0) {
|
||||||
if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curAcc + chscrollRandomizedStat();
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curAcc + chscrollRandomizedStat(range);
|
||||||
else temp = nEquip.getAcc() + chscrollRandomizedStat();
|
else temp = nEquip.getAcc() + chscrollRandomizedStat(range);
|
||||||
|
|
||||||
curAcc = getMaximumShortMaxIfOverflow(temp, curAcc);
|
curAcc = getMaximumShortMaxIfOverflow(temp, curAcc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nEquip.getAvoid() > 0) {
|
if (nEquip.getAvoid() > 0) {
|
||||||
if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curAvoid + chscrollRandomizedStat();
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curAvoid + chscrollRandomizedStat(range);
|
||||||
else temp = nEquip.getAvoid() + chscrollRandomizedStat();
|
else temp = nEquip.getAvoid() + chscrollRandomizedStat(range);
|
||||||
|
|
||||||
curAvoid = getMaximumShortMaxIfOverflow(temp, curAvoid);
|
curAvoid = getMaximumShortMaxIfOverflow(temp, curAvoid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nEquip.getSpeed() > 0) {
|
if (nEquip.getSpeed() > 0) {
|
||||||
if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curSpeed + chscrollRandomizedStat();
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curSpeed + chscrollRandomizedStat(range);
|
||||||
else temp = nEquip.getSpeed() + chscrollRandomizedStat();
|
else temp = nEquip.getSpeed() + chscrollRandomizedStat(range);
|
||||||
|
|
||||||
curSpeed = getMaximumShortMaxIfOverflow(temp, curSpeed);
|
curSpeed = getMaximumShortMaxIfOverflow(temp, curSpeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nEquip.getJump() > 0) {
|
if (nEquip.getJump() > 0) {
|
||||||
if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curJump + chscrollRandomizedStat();
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curJump + chscrollRandomizedStat(range);
|
||||||
else temp = nEquip.getJump() + chscrollRandomizedStat();
|
else temp = nEquip.getJump() + chscrollRandomizedStat(range);
|
||||||
|
|
||||||
curJump = getMaximumShortMaxIfOverflow(temp, curJump);
|
curJump = getMaximumShortMaxIfOverflow(temp, curJump);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nEquip.getHp() > 0) {
|
if (nEquip.getHp() > 0) {
|
||||||
if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curHp + chscrollRandomizedStat();
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curHp + chscrollRandomizedStat(range);
|
||||||
else temp = nEquip.getHp() + chscrollRandomizedStat();
|
else temp = nEquip.getHp() + chscrollRandomizedStat(range);
|
||||||
|
|
||||||
curHp = getMaximumShortMaxIfOverflow(temp, curHp);
|
curHp = getMaximumShortMaxIfOverflow(temp, curHp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nEquip.getMp() > 0) {
|
if (nEquip.getMp() > 0) {
|
||||||
if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curMp + chscrollRandomizedStat();
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) temp = curMp + chscrollRandomizedStat(range);
|
||||||
else temp = nEquip.getMp() + chscrollRandomizedStat();
|
else temp = nEquip.getMp() + chscrollRandomizedStat(range);
|
||||||
|
|
||||||
curMp = getMaximumShortMaxIfOverflow(temp, curMp);
|
curMp = getMaximumShortMaxIfOverflow(temp, curMp);
|
||||||
}
|
}
|
||||||
@@ -734,60 +806,60 @@ public class MapleItemInformationProvider {
|
|||||||
|
|
||||||
else {
|
else {
|
||||||
if (nEquip.getStr() > 0) {
|
if (nEquip.getStr() > 0) {
|
||||||
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setStr(getMaximumShortMaxIfOverflow(nEquip.getStr(), (nEquip.getStr() + chscrollRandomizedStat())));
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setStr(getMaximumShortMaxIfOverflow(nEquip.getStr(), (nEquip.getStr() + chscrollRandomizedStat(range))));
|
||||||
else nEquip.setStr(getMaximumShortMaxIfOverflow(0, (nEquip.getStr() + chscrollRandomizedStat())));
|
else nEquip.setStr(getMaximumShortMaxIfOverflow(0, (nEquip.getStr() + chscrollRandomizedStat(range))));
|
||||||
}
|
}
|
||||||
if (nEquip.getDex() > 0) {
|
if (nEquip.getDex() > 0) {
|
||||||
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setDex(getMaximumShortMaxIfOverflow(nEquip.getDex(), (nEquip.getDex() + chscrollRandomizedStat())));
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setDex(getMaximumShortMaxIfOverflow(nEquip.getDex(), (nEquip.getDex() + chscrollRandomizedStat(range))));
|
||||||
else nEquip.setDex(getMaximumShortMaxIfOverflow(0, (nEquip.getDex() + chscrollRandomizedStat())));
|
else nEquip.setDex(getMaximumShortMaxIfOverflow(0, (nEquip.getDex() + chscrollRandomizedStat(range))));
|
||||||
}
|
}
|
||||||
if (nEquip.getInt() > 0) {
|
if (nEquip.getInt() > 0) {
|
||||||
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setInt(getMaximumShortMaxIfOverflow(nEquip.getInt(), (nEquip.getInt() + chscrollRandomizedStat())));
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setInt(getMaximumShortMaxIfOverflow(nEquip.getInt(), (nEquip.getInt() + chscrollRandomizedStat(range))));
|
||||||
else nEquip.setInt(getMaximumShortMaxIfOverflow(0, (nEquip.getInt() + chscrollRandomizedStat())));
|
else nEquip.setInt(getMaximumShortMaxIfOverflow(0, (nEquip.getInt() + chscrollRandomizedStat(range))));
|
||||||
}
|
}
|
||||||
if (nEquip.getLuk() > 0) {
|
if (nEquip.getLuk() > 0) {
|
||||||
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setLuk(getMaximumShortMaxIfOverflow(nEquip.getLuk(), (nEquip.getLuk() + chscrollRandomizedStat())));
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setLuk(getMaximumShortMaxIfOverflow(nEquip.getLuk(), (nEquip.getLuk() + chscrollRandomizedStat(range))));
|
||||||
else nEquip.setLuk(getMaximumShortMaxIfOverflow(0, (nEquip.getLuk() + chscrollRandomizedStat())));
|
else nEquip.setLuk(getMaximumShortMaxIfOverflow(0, (nEquip.getLuk() + chscrollRandomizedStat(range))));
|
||||||
}
|
}
|
||||||
if (nEquip.getWatk() > 0) {
|
if (nEquip.getWatk() > 0) {
|
||||||
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setWatk(getMaximumShortMaxIfOverflow(nEquip.getWatk(), (nEquip.getWatk() + chscrollRandomizedStat())));
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setWatk(getMaximumShortMaxIfOverflow(nEquip.getWatk(), (nEquip.getWatk() + chscrollRandomizedStat(range))));
|
||||||
else nEquip.setWatk(getMaximumShortMaxIfOverflow(0, (nEquip.getWatk() + chscrollRandomizedStat())));
|
else nEquip.setWatk(getMaximumShortMaxIfOverflow(0, (nEquip.getWatk() + chscrollRandomizedStat(range))));
|
||||||
}
|
}
|
||||||
if (nEquip.getWdef() > 0) {
|
if (nEquip.getWdef() > 0) {
|
||||||
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setWdef(getMaximumShortMaxIfOverflow(nEquip.getWdef(), (nEquip.getWdef() + chscrollRandomizedStat())));
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setWdef(getMaximumShortMaxIfOverflow(nEquip.getWdef(), (nEquip.getWdef() + chscrollRandomizedStat(range))));
|
||||||
else nEquip.setWdef(getMaximumShortMaxIfOverflow(0, (nEquip.getWdef() + chscrollRandomizedStat())));
|
else nEquip.setWdef(getMaximumShortMaxIfOverflow(0, (nEquip.getWdef() + chscrollRandomizedStat(range))));
|
||||||
}
|
}
|
||||||
if (nEquip.getMatk() > 0) {
|
if (nEquip.getMatk() > 0) {
|
||||||
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setMatk(getMaximumShortMaxIfOverflow(nEquip.getMatk(), (nEquip.getMatk() + chscrollRandomizedStat())));
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setMatk(getMaximumShortMaxIfOverflow(nEquip.getMatk(), (nEquip.getMatk() + chscrollRandomizedStat(range))));
|
||||||
else nEquip.setMatk(getMaximumShortMaxIfOverflow(0, (nEquip.getMatk() + chscrollRandomizedStat())));
|
else nEquip.setMatk(getMaximumShortMaxIfOverflow(0, (nEquip.getMatk() + chscrollRandomizedStat(range))));
|
||||||
}
|
}
|
||||||
if (nEquip.getMdef() > 0) {
|
if (nEquip.getMdef() > 0) {
|
||||||
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setMdef(getMaximumShortMaxIfOverflow(nEquip.getMdef(), (nEquip.getMdef() + chscrollRandomizedStat())));
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setMdef(getMaximumShortMaxIfOverflow(nEquip.getMdef(), (nEquip.getMdef() + chscrollRandomizedStat(range))));
|
||||||
else nEquip.setMdef(getMaximumShortMaxIfOverflow(0, (nEquip.getMdef() + chscrollRandomizedStat())));
|
else nEquip.setMdef(getMaximumShortMaxIfOverflow(0, (nEquip.getMdef() + chscrollRandomizedStat(range))));
|
||||||
}
|
}
|
||||||
if (nEquip.getAcc() > 0) {
|
if (nEquip.getAcc() > 0) {
|
||||||
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setAcc(getMaximumShortMaxIfOverflow(nEquip.getAcc(), (nEquip.getAcc() + chscrollRandomizedStat())));
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setAcc(getMaximumShortMaxIfOverflow(nEquip.getAcc(), (nEquip.getAcc() + chscrollRandomizedStat(range))));
|
||||||
else nEquip.setAcc(getMaximumShortMaxIfOverflow(0, (nEquip.getAcc() + chscrollRandomizedStat())));
|
else nEquip.setAcc(getMaximumShortMaxIfOverflow(0, (nEquip.getAcc() + chscrollRandomizedStat(range))));
|
||||||
}
|
}
|
||||||
if (nEquip.getAvoid() > 0) {
|
if (nEquip.getAvoid() > 0) {
|
||||||
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setAvoid(getMaximumShortMaxIfOverflow(nEquip.getAvoid(), (nEquip.getAvoid() + chscrollRandomizedStat())));
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setAvoid(getMaximumShortMaxIfOverflow(nEquip.getAvoid(), (nEquip.getAvoid() + chscrollRandomizedStat(range))));
|
||||||
else nEquip.setAvoid(getMaximumShortMaxIfOverflow(0, (nEquip.getAvoid() + chscrollRandomizedStat())));
|
else nEquip.setAvoid(getMaximumShortMaxIfOverflow(0, (nEquip.getAvoid() + chscrollRandomizedStat(range))));
|
||||||
}
|
}
|
||||||
if (nEquip.getSpeed() > 0) {
|
if (nEquip.getSpeed() > 0) {
|
||||||
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setSpeed(getMaximumShortMaxIfOverflow(nEquip.getSpeed(), (nEquip.getSpeed() + chscrollRandomizedStat())));
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setSpeed(getMaximumShortMaxIfOverflow(nEquip.getSpeed(), (nEquip.getSpeed() + chscrollRandomizedStat(range))));
|
||||||
else nEquip.setSpeed(getMaximumShortMaxIfOverflow(0, (nEquip.getSpeed() + chscrollRandomizedStat())));
|
else nEquip.setSpeed(getMaximumShortMaxIfOverflow(0, (nEquip.getSpeed() + chscrollRandomizedStat(range))));
|
||||||
}
|
}
|
||||||
if (nEquip.getJump() > 0) {
|
if (nEquip.getJump() > 0) {
|
||||||
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setJump(getMaximumShortMaxIfOverflow(nEquip.getJump(), (nEquip.getJump() + chscrollRandomizedStat())));
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setJump(getMaximumShortMaxIfOverflow(nEquip.getJump(), (nEquip.getJump() + chscrollRandomizedStat(range))));
|
||||||
else nEquip.setJump(getMaximumShortMaxIfOverflow(0, (nEquip.getJump() + chscrollRandomizedStat())));
|
else nEquip.setJump(getMaximumShortMaxIfOverflow(0, (nEquip.getJump() + chscrollRandomizedStat(range))));
|
||||||
}
|
}
|
||||||
if (nEquip.getHp() > 0) {
|
if (nEquip.getHp() > 0) {
|
||||||
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setHp(getMaximumShortMaxIfOverflow(nEquip.getHp(), (nEquip.getHp() + chscrollRandomizedStat())));
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setHp(getMaximumShortMaxIfOverflow(nEquip.getHp(), (nEquip.getHp() + chscrollRandomizedStat(range))));
|
||||||
else nEquip.setHp(getMaximumShortMaxIfOverflow(0, (nEquip.getHp() + chscrollRandomizedStat())));
|
else nEquip.setHp(getMaximumShortMaxIfOverflow(0, (nEquip.getHp() + chscrollRandomizedStat(range))));
|
||||||
}
|
}
|
||||||
if (nEquip.getMp() > 0) {
|
if (nEquip.getMp() > 0) {
|
||||||
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setMp(getMaximumShortMaxIfOverflow(nEquip.getMp(), (nEquip.getMp() + chscrollRandomizedStat())));
|
if(ServerConstants.USE_ENHANCED_CHSCROLL) nEquip.setMp(getMaximumShortMaxIfOverflow(nEquip.getMp(), (nEquip.getMp() + chscrollRandomizedStat(range))));
|
||||||
else nEquip.setMp(getMaximumShortMaxIfOverflow(0, (nEquip.getMp() + chscrollRandomizedStat())));
|
else nEquip.setMp(getMaximumShortMaxIfOverflow(0, (nEquip.getMp() + chscrollRandomizedStat(range))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -831,10 +903,33 @@ public class MapleItemInformationProvider {
|
|||||||
case 2049100:
|
case 2049100:
|
||||||
case 2049101:
|
case 2049101:
|
||||||
case 2049102:
|
case 2049102:
|
||||||
scrollEquipWithChaos(nEquip);
|
scrollEquipWithChaos(nEquip, ServerConstants.CHSCROLL_STAT_RANGE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
improveEquipStats(nEquip, stats);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!ItemConstants.isCleanSlate(scrollId)) {
|
||||||
|
if (!assertGM) {
|
||||||
|
nEquip.setUpgradeSlots((byte) (nEquip.getUpgradeSlots() - 1));
|
||||||
|
}
|
||||||
|
nEquip.setLevel((byte) (nEquip.getLevel() + 1));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!ServerConstants.USE_PERFECT_SCROLLING && !usingWhiteScroll && !ItemConstants.isCleanSlate(scrollId) && !assertGM) {
|
||||||
|
nEquip.setUpgradeSlots((byte) (nEquip.getUpgradeSlots() - 1));
|
||||||
|
}
|
||||||
|
if (Randomizer.nextInt(101) < stats.get("cursed")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return equip;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void improveEquipStats(Equip nEquip, Map<String, Integer> stats) {
|
||||||
for (Entry<String, Integer> stat : stats.entrySet()) {
|
for (Entry<String, Integer> stat : stats.entrySet()) {
|
||||||
switch (stat.getKey()) {
|
switch (stat.getKey()) {
|
||||||
case "STR":
|
case "STR":
|
||||||
@@ -883,25 +978,6 @@ public class MapleItemInformationProvider {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!ItemConstants.isCleanSlate(scrollId)) {
|
|
||||||
if (!assertGM) {
|
|
||||||
nEquip.setUpgradeSlots((byte) (nEquip.getUpgradeSlots() - 1));
|
|
||||||
}
|
|
||||||
nEquip.setLevel((byte) (nEquip.getLevel() + 1));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!ServerConstants.USE_PERFECT_SCROLLING && !usingWhiteScroll && !ItemConstants.isCleanSlate(scrollId) && !assertGM) {
|
|
||||||
nEquip.setUpgradeSlots((byte) (nEquip.getUpgradeSlots() - 1));
|
|
||||||
}
|
|
||||||
if (Randomizer.nextInt(101) < stats.get("cursed")) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return equip;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Item getEquipById(int equipId) {
|
public Item getEquipById(int equipId) {
|
||||||
@@ -986,6 +1062,31 @@ public class MapleItemInformationProvider {
|
|||||||
return equip;
|
return equip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static short getRandUpgradedStat(short defaultValue, int maxRange) {
|
||||||
|
if (defaultValue == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int lMaxRange = maxRange;
|
||||||
|
return (short) (defaultValue + Math.floor(Randomizer.nextDouble() * (lMaxRange + 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Equip randomizeUpgradeStats(Equip equip) {
|
||||||
|
equip.setStr(getRandUpgradedStat(equip.getStr(), 2));
|
||||||
|
equip.setDex(getRandUpgradedStat(equip.getDex(), 2));
|
||||||
|
equip.setInt(getRandUpgradedStat(equip.getInt(), 2));
|
||||||
|
equip.setLuk(getRandUpgradedStat(equip.getLuk(), 2));
|
||||||
|
equip.setMatk(getRandUpgradedStat(equip.getMatk(), 2));
|
||||||
|
equip.setWatk(getRandUpgradedStat(equip.getWatk(), 2));
|
||||||
|
equip.setAcc(getRandUpgradedStat(equip.getAcc(), 2));
|
||||||
|
equip.setAvoid(getRandUpgradedStat(equip.getAvoid(), 2));
|
||||||
|
equip.setJump(getRandUpgradedStat(equip.getJump(), 2));
|
||||||
|
equip.setWdef(getRandUpgradedStat(equip.getWdef(), 5));
|
||||||
|
equip.setMdef(getRandUpgradedStat(equip.getMdef(), 5));
|
||||||
|
equip.setHp(getRandUpgradedStat(equip.getHp(), 5));
|
||||||
|
equip.setMp(getRandUpgradedStat(equip.getMp(), 5));
|
||||||
|
return equip;
|
||||||
|
}
|
||||||
|
|
||||||
public MapleStatEffect getItemEffect(int itemId) {
|
public MapleStatEffect getItemEffect(int itemId) {
|
||||||
MapleStatEffect ret = itemEffects.get(Integer.valueOf(itemId));
|
MapleStatEffect ret = itemEffects.get(Integer.valueOf(itemId));
|
||||||
if (ret == null) {
|
if (ret == null) {
|
||||||
@@ -1503,6 +1604,212 @@ public class MapleItemInformationProvider {
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int getCrystalForLevel(int level) {
|
||||||
|
int range = (level - 1) / 10;
|
||||||
|
|
||||||
|
if(range < 5) {
|
||||||
|
return 4260000;
|
||||||
|
} else if(range > 11) {
|
||||||
|
return 4260008;
|
||||||
|
} else {
|
||||||
|
switch(range) {
|
||||||
|
case 5:
|
||||||
|
return 4260001;
|
||||||
|
|
||||||
|
case 6:
|
||||||
|
return 4260002;
|
||||||
|
|
||||||
|
case 7:
|
||||||
|
return 4260003;
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
return 4260004;
|
||||||
|
|
||||||
|
case 9:
|
||||||
|
return 4260005;
|
||||||
|
|
||||||
|
case 10:
|
||||||
|
return 4260006;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 4260007;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pair<String, Integer> getMakerReagentStatUpgrade(int itemId) {
|
||||||
|
try {
|
||||||
|
Pair<String, Integer> statUpgd = statUpgradeMakerCache.get(itemId);
|
||||||
|
if(statUpgd != null) {
|
||||||
|
return statUpgd;
|
||||||
|
} else if(statUpgradeMakerCache.containsKey(itemId)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Connection con = DatabaseConnection.getConnection();
|
||||||
|
PreparedStatement ps = con.prepareStatement("SELECT stat, value FROM makerreagentdata WHERE itemid = ?");
|
||||||
|
ps.setInt(1, itemId);
|
||||||
|
ResultSet rs = ps.executeQuery();
|
||||||
|
if(rs.next()) {
|
||||||
|
String statType = rs.getString("stat");
|
||||||
|
int statGain = rs.getInt("value");
|
||||||
|
|
||||||
|
statUpgd = new Pair<>(statType, statGain);
|
||||||
|
}
|
||||||
|
rs.close();
|
||||||
|
ps.close();
|
||||||
|
con.close();
|
||||||
|
|
||||||
|
statUpgradeMakerCache.put(itemId, statUpgd);
|
||||||
|
return statUpgd;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMakerCrystalFromLeftover(Integer leftoverId) {
|
||||||
|
try {
|
||||||
|
Integer itemid = mobCrystalMakerCache.get(leftoverId);
|
||||||
|
if(itemid != null) {
|
||||||
|
return itemid;
|
||||||
|
}
|
||||||
|
|
||||||
|
itemid = -1;
|
||||||
|
|
||||||
|
Connection con = DatabaseConnection.getConnection();
|
||||||
|
PreparedStatement ps = con.prepareStatement("SELECT dropperid FROM drop_data WHERE itemid = ? ORDER BY dropperid;");
|
||||||
|
ps.setInt(1, leftoverId);
|
||||||
|
ResultSet rs = ps.executeQuery();
|
||||||
|
if(rs.next()) {
|
||||||
|
int dropperid = rs.getInt("dropperid");
|
||||||
|
itemid = getCrystalForLevel(MapleLifeFactory.getMonsterLevel(dropperid) - 1);
|
||||||
|
}
|
||||||
|
rs.close();
|
||||||
|
ps.close();
|
||||||
|
con.close();
|
||||||
|
|
||||||
|
mobCrystalMakerCache.put(leftoverId, itemid);
|
||||||
|
return itemid;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MakerItemCreateEntry getMakerItemEntry(int toCreate) {
|
||||||
|
MakerItemCreateEntry makerEntry;
|
||||||
|
|
||||||
|
if ((makerEntry = makerItemCache.get(toCreate)) != null) {
|
||||||
|
return new MakerItemCreateEntry(makerEntry);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
Connection con = DatabaseConnection.getConnection();
|
||||||
|
PreparedStatement ps = con.prepareStatement("SELECT req_level, req_maker_level, req_meso, quantity FROM makercreatedata WHERE itemid = ?");
|
||||||
|
ps.setInt(1, toCreate);
|
||||||
|
ResultSet rs = ps.executeQuery();
|
||||||
|
int reqLevel = 0;
|
||||||
|
int reqMakerLevel = 0;
|
||||||
|
int cost = 0;
|
||||||
|
int toGive = 0;
|
||||||
|
if (rs.next()) {
|
||||||
|
reqLevel = rs.getInt("req_level");
|
||||||
|
reqMakerLevel = rs.getInt("req_maker_level");
|
||||||
|
cost = rs.getInt("req_meso");
|
||||||
|
toGive = rs.getInt("quantity");
|
||||||
|
}
|
||||||
|
ps.close();
|
||||||
|
rs.close();
|
||||||
|
makerEntry = new MakerItemCreateEntry(cost, reqLevel, reqMakerLevel, toGive);
|
||||||
|
ps = con.prepareStatement("SELECT req_item, count FROM makerrecipedata WHERE itemid = ?");
|
||||||
|
ps.setInt(1, toCreate);
|
||||||
|
rs = ps.executeQuery();
|
||||||
|
while (rs.next()) {
|
||||||
|
makerEntry.addReqItem(rs.getInt("req_item"), rs.getInt("count"));
|
||||||
|
}
|
||||||
|
rs.close();
|
||||||
|
ps.close();
|
||||||
|
con.close();
|
||||||
|
makerItemCache.put(toCreate, new MakerItemCreateEntry(makerEntry));
|
||||||
|
} catch (SQLException sqle) {
|
||||||
|
sqle.printStackTrace();
|
||||||
|
makerEntry = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return makerEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMakerCrystalFromEquip(Integer equipId) {
|
||||||
|
try {
|
||||||
|
Map<String, Integer> stats = getEquipStats(equipId);
|
||||||
|
return getCrystalForLevel(stats.get("reqLevel"));
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMakerStimulantFromEquip(Integer equipId) {
|
||||||
|
try {
|
||||||
|
return getCrystalForLevel(getEquipStats(equipId).get("reqLevel"));
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMakerDisassembledQuantity(Integer itemId) {
|
||||||
|
int avail = 0;
|
||||||
|
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");
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
rs.close();
|
||||||
|
ps.close();
|
||||||
|
con.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return avail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMakerDisassembledFee(Integer itemId) {
|
||||||
|
int fee = -1;
|
||||||
|
Connection con;
|
||||||
|
try {
|
||||||
|
con = DatabaseConnection.getConnection();
|
||||||
|
PreparedStatement ps = con.prepareStatement("SELECT req_meso FROM makercreatedata WHERE itemid = ?");
|
||||||
|
ps.setInt(1, itemId);
|
||||||
|
ResultSet rs = ps.executeQuery();
|
||||||
|
|
||||||
|
if(rs.next()) { // cost is 13.6363~ % of the original value trimmed by 1000.
|
||||||
|
float val = (float) (rs.getInt("req_meso") * 0.13636363636364);
|
||||||
|
fee = (int) (val / 1000);
|
||||||
|
fee *= 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
rs.close();
|
||||||
|
ps.close();
|
||||||
|
con.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return fee;
|
||||||
|
}
|
||||||
|
|
||||||
public Set<String> getWhoDrops(Integer itemId) {
|
public Set<String> getWhoDrops(Integer itemId) {
|
||||||
Set<String> list = new HashSet<>();
|
Set<String> list = new HashSet<>();
|
||||||
Connection con = null;
|
Connection con = null;
|
||||||
|
|||||||
@@ -158,6 +158,27 @@ public class MapleLifeFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int getMonsterLevel(int mid) {
|
||||||
|
try {
|
||||||
|
MapleMonsterStats stats = monsterStats.get(Integer.valueOf(mid));
|
||||||
|
if (stats == null) {
|
||||||
|
MapleData monsterData = data.getData(StringUtil.getLeftPaddedStr(Integer.toString(mid) + ".img", '0', 11));
|
||||||
|
if (monsterData == null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
MapleData monsterInfoData = monsterData.getChildByPath("info");
|
||||||
|
return MapleDataTool.getIntConvert("level", monsterInfoData);
|
||||||
|
} else {
|
||||||
|
return stats.getLevel();
|
||||||
|
}
|
||||||
|
} catch(NullPointerException npe) {
|
||||||
|
System.out.println("[SEVERE] MOB " + mid + " failed to load. Issue: " + npe.getMessage() + "\n\n");
|
||||||
|
npe.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
private static void decodeElementalString(MapleMonsterStats stats, String elemAttr) {
|
private static void decodeElementalString(MapleMonsterStats stats, String elemAttr) {
|
||||||
for (int i = 0; i < elemAttr.length(); i += 2) {
|
for (int i = 0; i < elemAttr.length(); i += 2) {
|
||||||
stats.setEffectiveness(Element.getFromChar(elemAttr.charAt(i)), ElementalEffectiveness.getByNumber(Integer.valueOf(String.valueOf(elemAttr.charAt(i + 1)))));
|
stats.setEffectiveness(Element.getFromChar(elemAttr.charAt(i)), ElementalEffectiveness.getByNumber(Integer.valueOf(String.valueOf(elemAttr.charAt(i + 1)))));
|
||||||
|
|||||||
@@ -5887,11 +5887,20 @@ public class MaplePacketCreator {
|
|||||||
return mplew.getPacket();
|
return mplew.getPacket();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] showMakerEffect() {
|
public static byte[] showMakerEffect(boolean makerSucceeded) {
|
||||||
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
|
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
|
||||||
mplew.writeShort(SendOpcode.SHOW_ITEM_GAIN_INCHAT.getValue());
|
mplew.writeShort(SendOpcode.SHOW_ITEM_GAIN_INCHAT.getValue());
|
||||||
mplew.write(16);
|
mplew.write(16);
|
||||||
mplew.writeInt(0);
|
mplew.writeInt(makerSucceeded ? 0 : 1);
|
||||||
|
return mplew.getPacket();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] showForeignMakerEffect(int cid, boolean makerSucceeded) {
|
||||||
|
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
|
||||||
|
mplew.writeShort(SendOpcode.SHOW_FOREIGN_EFFECT.getValue());
|
||||||
|
mplew.writeInt(cid);
|
||||||
|
mplew.write(16);
|
||||||
|
mplew.writeInt(makerSucceeded ? 0 : 1);
|
||||||
return mplew.getPacket();
|
return mplew.getPacket();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ public enum MonitoredLockType {
|
|||||||
MAP_OBJS(37),
|
MAP_OBJS(37),
|
||||||
MAP_FACTORY(38),
|
MAP_FACTORY(38),
|
||||||
MAP_ITEM(39),
|
MAP_ITEM(39),
|
||||||
MAP_BOUNDS(41),
|
MAP_BOUNDS(40),
|
||||||
MINIDUNGEON(41),
|
MINIDUNGEON(41),
|
||||||
REACTOR(42);
|
REACTOR(42);
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
+201
@@ -0,0 +1,201 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 mapleskillmakerfetcher;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import provider.MapleData;
|
||||||
|
import provider.MapleDataDirectoryEntry;
|
||||||
|
import provider.MapleDataFileEntry;
|
||||||
|
import provider.MapleDataProvider;
|
||||||
|
import provider.MapleDataProviderFactory;
|
||||||
|
import provider.MapleDataTool;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Ronan
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class MapleItemInformationProvider {
|
||||||
|
private final static String wzPath = "../../wz";
|
||||||
|
|
||||||
|
private static MapleItemInformationProvider instance = null;
|
||||||
|
protected MapleDataProvider itemData;
|
||||||
|
protected MapleDataProvider equipData;
|
||||||
|
protected MapleDataProvider stringData;
|
||||||
|
protected MapleData eqpStringData;
|
||||||
|
|
||||||
|
protected Map<Integer, Map<String, Integer>> equipStatsCache = new HashMap<>();
|
||||||
|
protected Map<Integer, String> nameCache = new HashMap<>();
|
||||||
|
|
||||||
|
private MapleItemInformationProvider() {
|
||||||
|
itemData = MapleDataProviderFactory.getDataProvider(new File(wzPath + "/Item.wz"));
|
||||||
|
equipData = MapleDataProviderFactory.getDataProvider(new File(wzPath + "/Character.wz"));
|
||||||
|
stringData = MapleDataProviderFactory.getDataProvider(new File(wzPath + "/String.wz"));
|
||||||
|
eqpStringData = stringData.getData("Eqp.img");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MapleItemInformationProvider getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new MapleItemInformationProvider();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private MapleData getItemData(int itemId) {
|
||||||
|
MapleData ret = null;
|
||||||
|
String idStr = "0" + String.valueOf(itemId);
|
||||||
|
MapleDataDirectoryEntry root = itemData.getRoot();
|
||||||
|
for (MapleDataDirectoryEntry topDir : root.getSubdirectories()) {
|
||||||
|
for (MapleDataFileEntry iFile : topDir.getFiles()) {
|
||||||
|
if (iFile.getName().equals(idStr.substring(0, 4) + ".img")) {
|
||||||
|
ret = itemData.getData(topDir.getName() + "/" + iFile.getName());
|
||||||
|
if (ret == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ret = ret.getChildByPath(idStr);
|
||||||
|
return ret;
|
||||||
|
} else if (iFile.getName().equals(idStr.substring(1) + ".img")) {
|
||||||
|
return itemData.getData(topDir.getName() + "/" + iFile.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
root = equipData.getRoot();
|
||||||
|
for (MapleDataDirectoryEntry topDir : root.getSubdirectories()) {
|
||||||
|
for (MapleDataFileEntry iFile : topDir.getFiles()) {
|
||||||
|
if (iFile.getName().equals(idStr + ".img")) {
|
||||||
|
return equipData.getData(topDir.getName() + "/" + iFile.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Integer> getEquipStats(int itemId) {
|
||||||
|
if (equipStatsCache.containsKey(itemId)) {
|
||||||
|
return equipStatsCache.get(itemId);
|
||||||
|
}
|
||||||
|
Map<String, Integer> ret = new LinkedHashMap<>();
|
||||||
|
MapleData item = getItemData(itemId);
|
||||||
|
if (item == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
MapleData info = item.getChildByPath("info");
|
||||||
|
if (info == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (MapleData data : info.getChildren()) {
|
||||||
|
if (data.getName().startsWith("inc")) {
|
||||||
|
ret.put(data.getName().substring(3), MapleDataTool.getIntConvert(data));
|
||||||
|
}
|
||||||
|
/*else if (data.getName().startsWith("req"))
|
||||||
|
ret.put(data.getName(), MapleDataTool.getInt(data.getName(), info, 0));*/
|
||||||
|
}
|
||||||
|
ret.put("reqJob", MapleDataTool.getInt("reqJob", info, 0));
|
||||||
|
ret.put("reqLevel", MapleDataTool.getInt("reqLevel", info, 0));
|
||||||
|
ret.put("reqDEX", MapleDataTool.getInt("reqDEX", info, 0));
|
||||||
|
ret.put("reqSTR", MapleDataTool.getInt("reqSTR", info, 0));
|
||||||
|
ret.put("reqINT", MapleDataTool.getInt("reqINT", info, 0));
|
||||||
|
ret.put("reqLUK", MapleDataTool.getInt("reqLUK", info, 0));
|
||||||
|
ret.put("reqPOP", MapleDataTool.getInt("reqPOP", info, 0));
|
||||||
|
ret.put("cash", MapleDataTool.getInt("cash", info, 0));
|
||||||
|
ret.put("tuc", MapleDataTool.getInt("tuc", info, 0));
|
||||||
|
ret.put("cursed", MapleDataTool.getInt("cursed", info, 0));
|
||||||
|
ret.put("success", MapleDataTool.getInt("success", info, 0));
|
||||||
|
ret.put("fs", MapleDataTool.getInt("fs", info, 0));
|
||||||
|
equipStatsCache.put(itemId, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private MapleData getStringData(int itemId) {
|
||||||
|
String cat = "null";
|
||||||
|
MapleData theData;
|
||||||
|
if ((itemId >= 1010000 && itemId < 1040000) || (itemId >= 1122000 && itemId < 1123000) || (itemId >= 1132000 && itemId < 1133000) || (itemId >= 1142000 && itemId < 1143000)) {
|
||||||
|
theData = eqpStringData;
|
||||||
|
cat = "Eqp/Accessory";
|
||||||
|
} else if (itemId >= 1000000 && itemId < 1010000) {
|
||||||
|
theData = eqpStringData;
|
||||||
|
cat = "Eqp/Cap";
|
||||||
|
} else if (itemId >= 1102000 && itemId < 1103000) {
|
||||||
|
theData = eqpStringData;
|
||||||
|
cat = "Eqp/Cape";
|
||||||
|
} else if (itemId >= 1040000 && itemId < 1050000) {
|
||||||
|
theData = eqpStringData;
|
||||||
|
cat = "Eqp/Coat";
|
||||||
|
} else if (itemId >= 20000 && itemId < 22000) {
|
||||||
|
theData = eqpStringData;
|
||||||
|
cat = "Eqp/Face";
|
||||||
|
} else if (itemId >= 1080000 && itemId < 1090000) {
|
||||||
|
theData = eqpStringData;
|
||||||
|
cat = "Eqp/Glove";
|
||||||
|
} else if (itemId >= 30000 && itemId < 35000) {
|
||||||
|
theData = eqpStringData;
|
||||||
|
cat = "Eqp/Hair";
|
||||||
|
} else if (itemId >= 1050000 && itemId < 1060000) {
|
||||||
|
theData = eqpStringData;
|
||||||
|
cat = "Eqp/Longcoat";
|
||||||
|
} else if (itemId >= 1060000 && itemId < 1070000) {
|
||||||
|
theData = eqpStringData;
|
||||||
|
cat = "Eqp/Pants";
|
||||||
|
} else if (itemId >= 1802000 && itemId < 1842000) {
|
||||||
|
theData = eqpStringData;
|
||||||
|
cat = "Eqp/PetEquip";
|
||||||
|
} else if (itemId >= 1112000 && itemId < 1120000) {
|
||||||
|
theData = eqpStringData;
|
||||||
|
cat = "Eqp/Ring";
|
||||||
|
} else if (itemId >= 1092000 && itemId < 1100000) {
|
||||||
|
theData = eqpStringData;
|
||||||
|
cat = "Eqp/Shield";
|
||||||
|
} else if (itemId >= 1070000 && itemId < 1080000) {
|
||||||
|
theData = eqpStringData;
|
||||||
|
cat = "Eqp/Shoes";
|
||||||
|
} else if (itemId >= 1900000 && itemId < 2000000) {
|
||||||
|
theData = eqpStringData;
|
||||||
|
cat = "Eqp/Taming";
|
||||||
|
} else if (itemId >= 1300000 && itemId < 1800000) {
|
||||||
|
theData = eqpStringData;
|
||||||
|
cat = "Eqp/Weapon";
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (cat.equalsIgnoreCase("null")) {
|
||||||
|
return theData.getChildByPath(String.valueOf(itemId));
|
||||||
|
} else {
|
||||||
|
return theData.getChildByPath(cat + "/" + itemId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName(int itemId) {
|
||||||
|
if (nameCache.containsKey(itemId)) {
|
||||||
|
return nameCache.get(itemId);
|
||||||
|
}
|
||||||
|
MapleData strings = getStringData(itemId);
|
||||||
|
if (strings == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String ret = MapleDataTool.getString("name", strings, null);
|
||||||
|
nameCache.put(itemId, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -46,7 +46,6 @@ public class MapleMakerItemEntry {
|
|||||||
this.id = id;
|
this.id = id;
|
||||||
this.itemid = itemid;
|
this.itemid = itemid;
|
||||||
this.reqLevel = reqLevel;
|
this.reqLevel = reqLevel;
|
||||||
//System.out.println("id " + id + "rq" + reqLevel);
|
|
||||||
this.reqMakerLevel = reqMakerLevel;
|
this.reqMakerLevel = reqMakerLevel;
|
||||||
this.reqItem = reqItem;
|
this.reqItem = reqItem;
|
||||||
this.reqMeso = reqMeso;
|
this.reqMeso = reqMeso;
|
||||||
|
|||||||
+38
-4
@@ -21,10 +21,9 @@ package mapleskillmakerfetcher;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import static mapleskillmakerfetcher.MapleSkillMakerFetcher.id;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author RonanLana
|
* @author RonanLana
|
||||||
@@ -41,7 +40,7 @@ public class MapleSkillMakerFetcher {
|
|||||||
static String username = "root";
|
static String username = "root";
|
||||||
static String password = "";
|
static String password = "";
|
||||||
|
|
||||||
static String fileName = "lib/ItemMake.img.xml";
|
static String fileName = "../../wz/Etc.wz/ItemMake.img.xml";
|
||||||
static String newFile = "lib/MakerData.sql";
|
static String newFile = "lib/MakerData.sql";
|
||||||
|
|
||||||
static PrintWriter printWriter = null;
|
static PrintWriter printWriter = null;
|
||||||
@@ -176,6 +175,7 @@ public class MapleSkillMakerFetcher {
|
|||||||
status -= 1;
|
status -= 1;
|
||||||
|
|
||||||
if(status == 2) { //close item maker data
|
if(status == 2) { //close item maker data
|
||||||
|
generateUpdatedItemFee(); // for equipments, this will try to update reqMeso to be conformant with the client.
|
||||||
makerList.add(new MapleMakerItemEntry(id, itemid, reqLevel, reqMakerLevel, reqItem, reqMeso, reqEquip, catalyst, quantity, tuc, recipeCount, recipeItem, recipeList, randomList));
|
makerList.add(new MapleMakerItemEntry(id, itemid, reqLevel, reqMakerLevel, reqItem, reqMeso, reqEquip, catalyst, quantity, tuc, recipeCount, recipeItem, recipeList, randomList));
|
||||||
resetMakerDataFields();
|
resetMakerDataFields();
|
||||||
} else if(status == 4) { //close recipe/random item
|
} else if(status == 4) { //close recipe/random item
|
||||||
@@ -280,6 +280,40 @@ public class MapleSkillMakerFetcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void generateUpdatedItemFee() {
|
||||||
|
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
||||||
|
float adjPrice = reqMeso;
|
||||||
|
|
||||||
|
if(itemid < 2000000) {
|
||||||
|
Map<String, Integer> stats = ii.getEquipStats(itemid);
|
||||||
|
if(stats != null) {
|
||||||
|
int val = itemid / 100000;
|
||||||
|
|
||||||
|
if(val == 13 || val == 14) { // is weapon-type
|
||||||
|
adjPrice /= 10;
|
||||||
|
adjPrice += reqMeso;
|
||||||
|
|
||||||
|
adjPrice /= 1000;
|
||||||
|
reqMeso = 1000 * (int) Math.floor(adjPrice);
|
||||||
|
} else {
|
||||||
|
adjPrice /= ((stats.get("reqLevel") >= 108) ? 10 : 11);
|
||||||
|
adjPrice += reqMeso;
|
||||||
|
|
||||||
|
adjPrice /= 1000;
|
||||||
|
reqMeso = 1000 * (int) Math.ceil(adjPrice);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
System.out.println("null stats for itemid " + itemid);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
adjPrice /= 10;
|
||||||
|
adjPrice += reqMeso;
|
||||||
|
|
||||||
|
adjPrice /= 1000;
|
||||||
|
reqMeso = 1000 * (int) Math.ceil(adjPrice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void WriteMakerTableFile() {
|
private static void WriteMakerTableFile() {
|
||||||
printWriter.println(" # SQL File autogenerated from the MapleSkillMakerFetcher feature by Ronan Lana.");
|
printWriter.println(" # SQL File autogenerated from the MapleSkillMakerFetcher feature by Ronan Lana.");
|
||||||
printWriter.println(" # Generated data is conformant with the ItemMake.img.xml file used to compile this.");
|
printWriter.println(" # Generated data is conformant with the ItemMake.img.xml file used to compile this.");
|
||||||
@@ -312,7 +346,7 @@ public class MapleSkillMakerFetcher {
|
|||||||
sb_recipe.append(";\r\n");
|
sb_recipe.append(";\r\n");
|
||||||
|
|
||||||
sb_reward.setLength(sb_reward.length() - 3);
|
sb_reward.setLength(sb_reward.length() - 3);
|
||||||
sb_reward.append(";\r\n");
|
sb_reward.append(";");
|
||||||
|
|
||||||
printWriter.println(sb_create);
|
printWriter.println(sb_create);
|
||||||
printWriter.println(sb_recipe);
|
printWriter.println(sb_recipe);
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 provider;
|
||||||
|
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
|
public interface MapleCanvas {
|
||||||
|
int getHeight();
|
||||||
|
int getWidth();
|
||||||
|
BufferedImage getImage();
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 provider;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import provider.wz.MapleDataType;
|
||||||
|
|
||||||
|
public interface MapleData extends MapleDataEntity, Iterable<MapleData> {
|
||||||
|
@Override
|
||||||
|
public String getName();
|
||||||
|
public MapleDataType getType();
|
||||||
|
public List<MapleData> getChildren();
|
||||||
|
public MapleData getChildByPath(String path);
|
||||||
|
public Object getData();
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 provider;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Matze
|
||||||
|
*/
|
||||||
|
public interface MapleDataDirectoryEntry extends MapleDataEntry {
|
||||||
|
public List<MapleDataDirectoryEntry> getSubdirectories();
|
||||||
|
public List<MapleDataFileEntry> getFiles();
|
||||||
|
public MapleDataEntry getEntry(String name);
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 provider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Matze
|
||||||
|
*/
|
||||||
|
public interface MapleDataEntity {
|
||||||
|
public String getName();
|
||||||
|
public MapleDataEntity getParent();
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 provider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Matze
|
||||||
|
*/
|
||||||
|
public interface MapleDataEntry extends MapleDataEntity {
|
||||||
|
public String getName();
|
||||||
|
public int getSize();
|
||||||
|
public int getChecksum();
|
||||||
|
public int getOffset();
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 provider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Matze
|
||||||
|
*/
|
||||||
|
public interface MapleDataFileEntry extends MapleDataEntry {
|
||||||
|
public void setOffset(int offset);
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 provider;
|
||||||
|
|
||||||
|
public interface MapleDataProvider {
|
||||||
|
MapleData getData(String path);
|
||||||
|
MapleDataDirectoryEntry getRoot();
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 provider;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import provider.wz.WZFile;
|
||||||
|
import provider.wz.XMLWZFile;
|
||||||
|
|
||||||
|
public class MapleDataProviderFactory {
|
||||||
|
private final static String wzPath = "../../wz";
|
||||||
|
|
||||||
|
private static MapleDataProvider getWZ(File in, boolean provideImages) {
|
||||||
|
if (in.getName().toLowerCase().endsWith("wz") && !in.isDirectory()) {
|
||||||
|
try {
|
||||||
|
return new WZFile(in, provideImages);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Loading WZ File failed", e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return new XMLWZFile(in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MapleDataProvider getDataProvider(File in) {
|
||||||
|
return getWZ(in, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MapleDataProvider getImageProvidingDataProvider(File in) {
|
||||||
|
return getWZ(in, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static File fileInWZPath(String filename) {
|
||||||
|
return new File(wzPath, filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 provider;
|
||||||
|
|
||||||
|
import java.awt.Point;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import provider.wz.MapleDataType;
|
||||||
|
|
||||||
|
public class MapleDataTool {
|
||||||
|
public static String getString(MapleData data) {
|
||||||
|
return ((String) data.getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getString(MapleData data, String def) {
|
||||||
|
if (data == null || data.getData() == null) {
|
||||||
|
return def;
|
||||||
|
} else {
|
||||||
|
return ((String) data.getData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getString(String path, MapleData data) {
|
||||||
|
return getString(data.getChildByPath(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getString(String path, MapleData data, String def) {
|
||||||
|
return getString(data.getChildByPath(path), def);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double getDouble(MapleData data) {
|
||||||
|
return ((Double) data.getData()).doubleValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float getFloat(MapleData data) {
|
||||||
|
return ((Float) data.getData()).floatValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getInt(MapleData data) {
|
||||||
|
if (data == null || data.getData() == null) {
|
||||||
|
return 0;// DEF?
|
||||||
|
}
|
||||||
|
return ((Integer) data.getData()).intValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getInt(String path, MapleData data) {
|
||||||
|
return getInt(data.getChildByPath(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getIntConvert(MapleData data) {
|
||||||
|
if (data.getType() == MapleDataType.STRING) {
|
||||||
|
return Integer.parseInt(getString(data));
|
||||||
|
} else {
|
||||||
|
return getInt(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getIntConvert(String path, MapleData data) {
|
||||||
|
MapleData d = data.getChildByPath(path);
|
||||||
|
if (d.getType() == MapleDataType.STRING) {
|
||||||
|
return Integer.parseInt(getString(d));
|
||||||
|
} else {
|
||||||
|
return getInt(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getInt(MapleData data, int def) {
|
||||||
|
if (data == null || data.getData() == null) {
|
||||||
|
return def;
|
||||||
|
} else if (data.getType() == MapleDataType.STRING) {
|
||||||
|
return Integer.parseInt(getString(data));
|
||||||
|
} else {
|
||||||
|
return ((Integer) data.getData()).intValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getInt(String path, MapleData data, int def) {
|
||||||
|
return getInt(data.getChildByPath(path), def);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getIntConvert(String path, MapleData data, int def) {
|
||||||
|
MapleData d = data.getChildByPath(path);
|
||||||
|
if (d == null) {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
if (d.getType() == MapleDataType.STRING) {
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(getString(d));
|
||||||
|
} catch (NumberFormatException nfe) {
|
||||||
|
nfe.printStackTrace();
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return getInt(d, def);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BufferedImage getImage(MapleData data) {
|
||||||
|
return ((MapleCanvas) data.getData()).getImage();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Point getPoint(MapleData data) {
|
||||||
|
return ((Point) data.getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Point getPoint(String path, MapleData data) {
|
||||||
|
return getPoint(data.getChildByPath(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Point getPoint(String path, MapleData data, Point def) {
|
||||||
|
final MapleData pointData = data.getChildByPath(path);
|
||||||
|
if (pointData == null) {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
return getPoint(pointData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getFullDataPath(MapleData data) {
|
||||||
|
String path = "";
|
||||||
|
MapleDataEntity myData = data;
|
||||||
|
while (myData != null) {
|
||||||
|
path = myData.getName() + "/" + path;
|
||||||
|
myData = myData.getParent();
|
||||||
|
}
|
||||||
|
return path.substring(0, path.length() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 provider.wz;
|
||||||
|
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import provider.MapleCanvas;
|
||||||
|
|
||||||
|
public class FileStoredPngMapleCanvas implements MapleCanvas {
|
||||||
|
private File file;
|
||||||
|
private int width;
|
||||||
|
private int height;
|
||||||
|
private BufferedImage image;
|
||||||
|
|
||||||
|
public FileStoredPngMapleCanvas(int width, int height, File fileIn) {
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
this.file = fileIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHeight() {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getWidth() {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BufferedImage getImage() {
|
||||||
|
loadImageIfNecessary();
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadImageIfNecessary() {
|
||||||
|
if (image == null) {
|
||||||
|
try {
|
||||||
|
image = ImageIO.read(file);
|
||||||
|
// replace the dimensions loaded from the wz by the REAL dimensions from the image - should be equal tho
|
||||||
|
width = image.getWidth();
|
||||||
|
height = image.getHeight();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 provider.wz;
|
||||||
|
|
||||||
|
public class ImgMapleSound {
|
||||||
|
private int dataLength, offset;
|
||||||
|
|
||||||
|
public ImgMapleSound(int dataLength, int offset) {
|
||||||
|
this.dataLength = dataLength;
|
||||||
|
this.offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDataLength() {
|
||||||
|
return dataLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getOffset() {
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 provider.wz;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import provider.MapleDataProviderFactory;
|
||||||
|
import tools.data.input.GenericLittleEndianAccessor;
|
||||||
|
import tools.data.input.InputStreamByteStream;
|
||||||
|
import tools.data.input.LittleEndianAccessor;
|
||||||
|
|
||||||
|
public class ListWZFile {
|
||||||
|
private LittleEndianAccessor lea;
|
||||||
|
private List<String> entries = new ArrayList<String>();
|
||||||
|
private static Collection<String> modernImgs = new HashSet<String>();
|
||||||
|
|
||||||
|
public static byte[] xorBytes(byte[] a, byte[] b) {
|
||||||
|
byte[] wusched = new byte[a.length];
|
||||||
|
for (int i = 0; i < a.length; i++) {
|
||||||
|
wusched[i] = (byte) (a[i] ^ b[i]);
|
||||||
|
}
|
||||||
|
return wusched;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListWZFile(File listwz) throws FileNotFoundException {
|
||||||
|
lea = new GenericLittleEndianAccessor(new InputStreamByteStream(new BufferedInputStream(new FileInputStream(listwz))));
|
||||||
|
while (lea.available() > 0) {
|
||||||
|
int l = lea.readInt() * 2;
|
||||||
|
byte[] chunk = new byte[l];
|
||||||
|
for (int i = 0; i < chunk.length; i++) {
|
||||||
|
chunk[i] = lea.readByte();
|
||||||
|
}
|
||||||
|
lea.readChar();
|
||||||
|
final String value = String.valueOf(WZTool.readListString(chunk));
|
||||||
|
entries.add(value);
|
||||||
|
}
|
||||||
|
entries = Collections.unmodifiableList(entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getEntries() {
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void init() {
|
||||||
|
final String listWz = System.getProperty("listwz");
|
||||||
|
if (listWz != null) {
|
||||||
|
ListWZFile listwz;
|
||||||
|
try {
|
||||||
|
listwz = new ListWZFile(MapleDataProviderFactory.fileInWZPath("List.wz"));
|
||||||
|
modernImgs = new HashSet<String>(listwz.getEntries());
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isModernImgFile(String path) {
|
||||||
|
return modernImgs.contains(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 provider.wz;
|
||||||
|
|
||||||
|
public enum MapleDataType {
|
||||||
|
NONE, IMG_0x00, SHORT, INT, FLOAT, DOUBLE, STRING, EXTENDED, PROPERTY, CANVAS, VECTOR, CONVEX, SOUND, UOL, UNKNOWN_TYPE, UNKNOWN_EXTENDED_TYPE;
|
||||||
|
}
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 provider.wz;
|
||||||
|
|
||||||
|
import java.awt.Point;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.awt.image.DataBuffer;
|
||||||
|
import java.awt.image.DataBufferByte;
|
||||||
|
import java.awt.image.PixelInterleavedSampleModel;
|
||||||
|
import java.awt.image.Raster;
|
||||||
|
import java.awt.image.SampleModel;
|
||||||
|
import java.awt.image.WritableRaster;
|
||||||
|
import java.util.zip.DataFormatException;
|
||||||
|
import java.util.zip.Inflater;
|
||||||
|
import provider.MapleCanvas;
|
||||||
|
|
||||||
|
public class PNGMapleCanvas implements MapleCanvas {
|
||||||
|
private static final int[] ZAHLEN = new int[]{2, 1, 0, 3};
|
||||||
|
private int height;
|
||||||
|
private int width;
|
||||||
|
private int dataLength;
|
||||||
|
private int format;
|
||||||
|
private byte[] data;
|
||||||
|
|
||||||
|
public PNGMapleCanvas(int width, int height, int dataLength, int format, byte[] data) {
|
||||||
|
super();
|
||||||
|
this.height = height;
|
||||||
|
this.width = width;
|
||||||
|
this.dataLength = dataLength;
|
||||||
|
this.format = format;
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHeight() {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getWidth() {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFormat() {
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BufferedImage getImage() {
|
||||||
|
int sizeUncompressed = 0;
|
||||||
|
int size8888 = 0;
|
||||||
|
int maxWriteBuf = 2;
|
||||||
|
int maxHeight = 3;
|
||||||
|
byte[] writeBuf = new byte[maxWriteBuf];
|
||||||
|
@SuppressWarnings ("unused")
|
||||||
|
byte[] rowPointers = new byte[maxHeight];
|
||||||
|
switch (getFormat()) {
|
||||||
|
case 1:
|
||||||
|
case 513:
|
||||||
|
sizeUncompressed = getHeight() * getWidth() * 4;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
sizeUncompressed = getHeight() * getWidth() * 8;
|
||||||
|
break;
|
||||||
|
case 517:
|
||||||
|
sizeUncompressed = getHeight() * getWidth() / 128;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
size8888 = getHeight() * getWidth() * 8;
|
||||||
|
if (size8888 > maxWriteBuf) {
|
||||||
|
maxWriteBuf = size8888;
|
||||||
|
writeBuf = new byte[maxWriteBuf];
|
||||||
|
}
|
||||||
|
if (getHeight() > maxHeight) {
|
||||||
|
maxHeight = getHeight();
|
||||||
|
rowPointers = new byte[maxHeight];
|
||||||
|
}
|
||||||
|
Inflater dec = new Inflater();
|
||||||
|
dec.setInput(getData(), 0, dataLength);
|
||||||
|
int declen = 0;
|
||||||
|
byte[] uc = new byte[sizeUncompressed];
|
||||||
|
try {
|
||||||
|
declen = dec.inflate(uc);
|
||||||
|
} catch (DataFormatException ex) {
|
||||||
|
throw new RuntimeException("zlib fucks", ex);
|
||||||
|
}
|
||||||
|
dec.end();
|
||||||
|
if (getFormat() == 1) {
|
||||||
|
for (int i = 0; i < sizeUncompressed; i++) {
|
||||||
|
byte low = (byte) (uc[i] & 0x0F);
|
||||||
|
byte high = (byte) (uc[i] & 0xF0);
|
||||||
|
writeBuf[(i << 1)] = (byte) (((low << 4) | low) & 0xFF);
|
||||||
|
writeBuf[(i << 1) + 1] = (byte) (high | ((high >>> 4) & 0xF));
|
||||||
|
}
|
||||||
|
} else if (getFormat() == 2) {
|
||||||
|
writeBuf = uc;
|
||||||
|
} else if (getFormat() == 513) {
|
||||||
|
for (int i = 0; i < declen; i += 2) {
|
||||||
|
byte bBits = (byte) ((uc[i] & 0x1F) << 3);
|
||||||
|
byte gBits = (byte) (((uc[i + 1] & 0x07) << 5) | ((uc[i] & 0xE0) >> 3));
|
||||||
|
byte rBits = (byte) (uc[i + 1] & 0xF8);
|
||||||
|
writeBuf[(i << 1)] = (byte) (bBits | (bBits >> 5));
|
||||||
|
writeBuf[(i << 1) + 1] = (byte) (gBits | (gBits >> 6));
|
||||||
|
writeBuf[(i << 1) + 2] = (byte) (rBits | (rBits >> 5));
|
||||||
|
writeBuf[(i << 1) + 3] = (byte) 0xFF;
|
||||||
|
}
|
||||||
|
} else if (getFormat() == 517) {
|
||||||
|
byte b = 0x00;
|
||||||
|
int pixelIndex = 0;
|
||||||
|
for (int i = 0; i < declen; i++) {
|
||||||
|
for (int j = 0; j < 8; j++) {
|
||||||
|
b = (byte) (((uc[i] & (0x01 << (7 - j))) >> (7 - j)) * 255);
|
||||||
|
for (int k = 0; k < 16; k++) {
|
||||||
|
pixelIndex = (i << 9) + (j << 6) + k * 2;
|
||||||
|
writeBuf[pixelIndex] = b;
|
||||||
|
writeBuf[pixelIndex + 1] = b;
|
||||||
|
writeBuf[pixelIndex + 2] = b;
|
||||||
|
writeBuf[pixelIndex + 3] = (byte) 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DataBufferByte imgData = new DataBufferByte(writeBuf, sizeUncompressed);
|
||||||
|
SampleModel sm = new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE, getWidth(), getHeight(), 4, getWidth() * 4, ZAHLEN);
|
||||||
|
WritableRaster imgRaster = Raster.createWritableRaster(sm, imgData, new Point(0, 0));
|
||||||
|
BufferedImage aa = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
|
||||||
|
aa.setData(imgRaster);
|
||||||
|
return aa;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 provider.wz;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import provider.MapleDataDirectoryEntry;
|
||||||
|
import provider.MapleDataEntity;
|
||||||
|
import provider.MapleDataEntry;
|
||||||
|
import provider.MapleDataFileEntry;
|
||||||
|
|
||||||
|
public class WZDirectoryEntry extends WZEntry implements MapleDataDirectoryEntry {
|
||||||
|
private List<MapleDataDirectoryEntry> subdirs = new ArrayList<MapleDataDirectoryEntry>();
|
||||||
|
private List<MapleDataFileEntry> files = new ArrayList<MapleDataFileEntry>();
|
||||||
|
private Map<String, MapleDataEntry> entries = new HashMap<String, MapleDataEntry>();
|
||||||
|
|
||||||
|
public WZDirectoryEntry(String name, int size, int checksum, MapleDataEntity parent) {
|
||||||
|
super(name, size, checksum, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WZDirectoryEntry() {
|
||||||
|
super(null, 0, 0, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addDirectory(MapleDataDirectoryEntry dir) {
|
||||||
|
subdirs.add(dir);
|
||||||
|
entries.put(dir.getName(), dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addFile(MapleDataFileEntry fileEntry) {
|
||||||
|
files.add(fileEntry);
|
||||||
|
entries.put(fileEntry.getName(), fileEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MapleDataDirectoryEntry> getSubdirectories() {
|
||||||
|
return Collections.unmodifiableList(subdirs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MapleDataFileEntry> getFiles() {
|
||||||
|
return Collections.unmodifiableList(files);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MapleDataEntry getEntry(String name) {
|
||||||
|
return entries.get(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 provider.wz;
|
||||||
|
|
||||||
|
import provider.MapleDataEntity;
|
||||||
|
import provider.MapleDataEntry;
|
||||||
|
|
||||||
|
public class WZEntry implements MapleDataEntry {
|
||||||
|
private String name;
|
||||||
|
private int size;
|
||||||
|
private int checksum;
|
||||||
|
private int offset;
|
||||||
|
private MapleDataEntity parent;
|
||||||
|
|
||||||
|
public WZEntry(String name, int size, int checksum, MapleDataEntity parent) {
|
||||||
|
super();
|
||||||
|
this.name = name;
|
||||||
|
this.size = size;
|
||||||
|
this.checksum = checksum;
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getChecksum() {
|
||||||
|
return checksum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getOffset() {
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MapleDataEntity getParent() {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 provider.wz;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.RandomAccessFile;
|
||||||
|
import provider.MapleData;
|
||||||
|
import provider.MapleDataDirectoryEntry;
|
||||||
|
import provider.MapleDataFileEntry;
|
||||||
|
import provider.MapleDataProvider;
|
||||||
|
import tools.data.input.GenericLittleEndianAccessor;
|
||||||
|
import tools.data.input.GenericSeekableLittleEndianAccessor;
|
||||||
|
import tools.data.input.InputStreamByteStream;
|
||||||
|
import tools.data.input.LittleEndianAccessor;
|
||||||
|
import tools.data.input.RandomAccessByteStream;
|
||||||
|
import tools.data.input.SeekableLittleEndianAccessor;
|
||||||
|
|
||||||
|
public class WZFile implements MapleDataProvider {
|
||||||
|
static {
|
||||||
|
ListWZFile.init();
|
||||||
|
}
|
||||||
|
private File wzfile;
|
||||||
|
private LittleEndianAccessor lea;
|
||||||
|
private SeekableLittleEndianAccessor slea;
|
||||||
|
private int headerSize;
|
||||||
|
private WZDirectoryEntry root;
|
||||||
|
private boolean provideImages;
|
||||||
|
private int cOffset;
|
||||||
|
|
||||||
|
public WZFile(File wzfile, boolean provideImages) throws IOException {
|
||||||
|
this.wzfile = wzfile;
|
||||||
|
lea = new GenericLittleEndianAccessor(new InputStreamByteStream(new BufferedInputStream(new FileInputStream(wzfile))));
|
||||||
|
RandomAccessFile raf = new RandomAccessFile(wzfile, "r");
|
||||||
|
slea = new GenericSeekableLittleEndianAccessor(new RandomAccessByteStream(raf));
|
||||||
|
root = new WZDirectoryEntry(wzfile.getName(), 0, 0, null);
|
||||||
|
this.provideImages = provideImages;
|
||||||
|
load();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void load() throws IOException {
|
||||||
|
lea.readAsciiString(4);
|
||||||
|
lea.readInt();
|
||||||
|
lea.readInt();
|
||||||
|
headerSize = lea.readInt();
|
||||||
|
lea.readNullTerminatedAsciiString();
|
||||||
|
lea.readShort();
|
||||||
|
parseDirectory(root);
|
||||||
|
cOffset = (int) lea.getBytesRead();
|
||||||
|
getOffsets(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getOffsets(MapleDataDirectoryEntry dir) {
|
||||||
|
for (MapleDataFileEntry file : dir.getFiles()) {
|
||||||
|
file.setOffset(cOffset);
|
||||||
|
cOffset += file.getSize();
|
||||||
|
}
|
||||||
|
for (MapleDataDirectoryEntry sdir : dir.getSubdirectories()) {
|
||||||
|
getOffsets(sdir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseDirectory(WZDirectoryEntry dir) {
|
||||||
|
int entries = WZTool.readValue(lea);
|
||||||
|
for (int i = 0; i < entries; i++) {
|
||||||
|
byte marker = lea.readByte();
|
||||||
|
String name = null;
|
||||||
|
int size, checksum;
|
||||||
|
switch (marker) {
|
||||||
|
case 0x02:
|
||||||
|
name = WZTool.readDecodedStringAtOffsetAndReset(slea, lea.readInt() + this.headerSize + 1);
|
||||||
|
size = WZTool.readValue(lea);
|
||||||
|
checksum = WZTool.readValue(lea);
|
||||||
|
lea.readInt(); //dummy int
|
||||||
|
dir.addFile(new WZFileEntry(name, size, checksum, dir));
|
||||||
|
break;
|
||||||
|
case 0x03:
|
||||||
|
case 0x04:
|
||||||
|
name = WZTool.readDecodedString(lea);
|
||||||
|
size = WZTool.readValue(lea);
|
||||||
|
checksum = WZTool.readValue(lea);
|
||||||
|
lea.readInt(); //dummy int
|
||||||
|
if (marker == 3) {
|
||||||
|
dir.addDirectory(new WZDirectoryEntry(name, size, checksum, dir));
|
||||||
|
} else {
|
||||||
|
dir.addFile(new WZFileEntry(name, size, checksum, dir));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (MapleDataDirectoryEntry idir : dir.getSubdirectories()) {
|
||||||
|
parseDirectory((WZDirectoryEntry) idir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public WZIMGFile getImgFile(String path) throws IOException {
|
||||||
|
String segments[] = path.split("/");
|
||||||
|
WZDirectoryEntry dir = root;
|
||||||
|
for (int x = 0; x < segments.length - 1; x++) {
|
||||||
|
dir = (WZDirectoryEntry) dir.getEntry(segments[x]);
|
||||||
|
if (dir == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WZFileEntry entry = (WZFileEntry) dir.getEntry(segments[segments.length - 1]);
|
||||||
|
if (entry == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String fullPath = wzfile.getName().substring(0, wzfile.getName().length() - 3).toLowerCase() + "/" + path;
|
||||||
|
return new WZIMGFile(this.wzfile, entry, provideImages, ListWZFile.isModernImgFile(fullPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized MapleData getData(String path) {
|
||||||
|
try {
|
||||||
|
WZIMGFile imgFile = getImgFile(path);
|
||||||
|
if (imgFile == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
MapleData ret = imgFile.getRoot();
|
||||||
|
return ret;
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MapleDataDirectoryEntry getRoot() {
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 provider.wz;
|
||||||
|
|
||||||
|
import provider.MapleDataEntity;
|
||||||
|
import provider.MapleDataFileEntry;
|
||||||
|
|
||||||
|
public class WZFileEntry extends WZEntry implements MapleDataFileEntry {
|
||||||
|
private int offset;
|
||||||
|
|
||||||
|
public WZFileEntry(String name, int size, int checksum, MapleDataEntity parent) {
|
||||||
|
super(name, size, checksum, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOffset() {
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOffset(int offset) {
|
||||||
|
this.offset = offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 provider.wz;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import provider.MapleData;
|
||||||
|
import provider.MapleDataEntity;
|
||||||
|
|
||||||
|
public class WZIMGEntry implements MapleData {
|
||||||
|
private String name;
|
||||||
|
private MapleDataType type;
|
||||||
|
private List<MapleData> children = new ArrayList<MapleData>(10);
|
||||||
|
private Object data;
|
||||||
|
private MapleDataEntity parent;
|
||||||
|
|
||||||
|
public WZIMGEntry(MapleDataEntity parent) {
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MapleDataType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<MapleData> getChildren() {
|
||||||
|
return Collections.unmodifiableList(children);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MapleData getChildByPath(String path) {
|
||||||
|
String segments[] = path.split("/");
|
||||||
|
if (segments[0].equals("..")) {
|
||||||
|
return ((MapleData) getParent()).getChildByPath(path.substring(path.indexOf("/") + 1));
|
||||||
|
}
|
||||||
|
MapleData ret = this;
|
||||||
|
for (int x = 0; x < segments.length; x++) {
|
||||||
|
boolean foundChild = false;
|
||||||
|
for (MapleData child : ret.getChildren()) {
|
||||||
|
if (child.getName().equals(segments[x])) {
|
||||||
|
ret = child;
|
||||||
|
foundChild = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!foundChild) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(MapleDataType type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(Object data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addChild(WZIMGEntry entry) {
|
||||||
|
children.add(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<MapleData> iterator() {
|
||||||
|
return getChildren().iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getName() + ":" + getData();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MapleDataEntity getParent() {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void finish() {
|
||||||
|
((ArrayList<MapleData>) children).trimToSize();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,227 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 provider.wz;
|
||||||
|
|
||||||
|
import java.awt.Point;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.RandomAccessFile;
|
||||||
|
import tools.data.input.GenericSeekableLittleEndianAccessor;
|
||||||
|
import tools.data.input.RandomAccessByteStream;
|
||||||
|
import tools.data.input.SeekableLittleEndianAccessor;
|
||||||
|
|
||||||
|
public class WZIMGFile {
|
||||||
|
private WZFileEntry file;
|
||||||
|
private WZIMGEntry root;
|
||||||
|
private boolean provideImages;
|
||||||
|
@SuppressWarnings ("unused")
|
||||||
|
private boolean modernImg;
|
||||||
|
|
||||||
|
public WZIMGFile(File wzfile, WZFileEntry file, boolean provideImages, boolean modernImg) throws IOException {
|
||||||
|
RandomAccessFile raf = new RandomAccessFile(wzfile, "r");
|
||||||
|
SeekableLittleEndianAccessor slea = new GenericSeekableLittleEndianAccessor(new RandomAccessByteStream(raf));
|
||||||
|
slea.seek(file.getOffset());
|
||||||
|
this.file = file;
|
||||||
|
this.provideImages = provideImages;
|
||||||
|
root = new WZIMGEntry(file.getParent());
|
||||||
|
root.setName(file.getName());
|
||||||
|
root.setType(MapleDataType.EXTENDED);
|
||||||
|
this.modernImg = modernImg;
|
||||||
|
parseExtended(root, slea, 0);
|
||||||
|
root.finish();
|
||||||
|
raf.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void dumpImg(OutputStream out, SeekableLittleEndianAccessor slea) throws IOException {
|
||||||
|
DataOutputStream os = new DataOutputStream(out);
|
||||||
|
long oldPos = slea.getPosition();
|
||||||
|
slea.seek(file.getOffset());
|
||||||
|
for (int x = 0; x < file.getSize(); x++) {
|
||||||
|
os.write(slea.readByte());
|
||||||
|
}
|
||||||
|
slea.seek(oldPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WZIMGEntry getRoot() {
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parse(WZIMGEntry entry, SeekableLittleEndianAccessor slea) {
|
||||||
|
byte marker = slea.readByte();
|
||||||
|
switch (marker) {
|
||||||
|
case 0: {
|
||||||
|
String name = WZTool.readDecodedString(slea);
|
||||||
|
entry.setName(name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: {
|
||||||
|
String name = WZTool.readDecodedStringAtOffsetAndReset(slea, file.getOffset() + slea.readInt());
|
||||||
|
entry.setName(name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
System.out.println("Unknown Image identifier: " + marker + " at offset " + (slea.getPosition() - file.getOffset()));
|
||||||
|
}
|
||||||
|
marker = slea.readByte();
|
||||||
|
switch (marker) {
|
||||||
|
case 0:
|
||||||
|
entry.setType(MapleDataType.IMG_0x00);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
case 11: //??? no idea, since 0.49
|
||||||
|
entry.setType(MapleDataType.SHORT);
|
||||||
|
entry.setData(Short.valueOf(slea.readShort()));
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
entry.setType(MapleDataType.INT);
|
||||||
|
entry.setData(Integer.valueOf(WZTool.readValue(slea)));
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
entry.setType(MapleDataType.FLOAT);
|
||||||
|
entry.setData(Float.valueOf(WZTool.readFloatValue(slea)));
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
entry.setType(MapleDataType.DOUBLE);
|
||||||
|
entry.setData(Double.valueOf(slea.readDouble()));
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
entry.setType(MapleDataType.STRING);
|
||||||
|
byte iMarker = slea.readByte();
|
||||||
|
if (iMarker == 0) {
|
||||||
|
entry.setData(WZTool.readDecodedString(slea));
|
||||||
|
} else if (iMarker == 1) {
|
||||||
|
entry.setData(WZTool.readDecodedStringAtOffsetAndReset(slea, slea.readInt() + file.getOffset()));
|
||||||
|
} else {
|
||||||
|
System.out.println("Unknown String type " + iMarker);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
entry.setType(MapleDataType.EXTENDED);
|
||||||
|
long endOfExtendedBlock = slea.readInt();
|
||||||
|
endOfExtendedBlock += slea.getPosition();
|
||||||
|
parseExtended(entry, slea, endOfExtendedBlock);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
System.out.println("Unknown Image type " + marker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseExtended(WZIMGEntry entry, SeekableLittleEndianAccessor slea, long endOfExtendedBlock) {
|
||||||
|
byte marker = slea.readByte();
|
||||||
|
String type;
|
||||||
|
switch (marker) {
|
||||||
|
case 0x73:
|
||||||
|
type = WZTool.readDecodedString(slea);
|
||||||
|
break;
|
||||||
|
case 0x1B:
|
||||||
|
type = WZTool.readDecodedStringAtOffsetAndReset(slea, file.getOffset() + slea.readInt());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Unknown extended image identifier: " + marker + " at offset " +
|
||||||
|
(slea.getPosition() - file.getOffset()));
|
||||||
|
}
|
||||||
|
if (type.equals("Property")) {
|
||||||
|
entry.setType(MapleDataType.PROPERTY);
|
||||||
|
slea.readByte();
|
||||||
|
slea.readByte();
|
||||||
|
int children = WZTool.readValue(slea);
|
||||||
|
for (int i = 0; i < children; i++) {
|
||||||
|
WZIMGEntry cEntry = new WZIMGEntry(entry);
|
||||||
|
parse(cEntry, slea);
|
||||||
|
cEntry.finish();
|
||||||
|
entry.addChild(cEntry);
|
||||||
|
}
|
||||||
|
} else if (type.equals("Canvas")) {
|
||||||
|
entry.setType(MapleDataType.CANVAS);
|
||||||
|
slea.readByte();
|
||||||
|
marker = slea.readByte();
|
||||||
|
if (marker == 0) {
|
||||||
|
// do nothing
|
||||||
|
} else if (marker == 1) {
|
||||||
|
slea.readByte();
|
||||||
|
slea.readByte();
|
||||||
|
int children = WZTool.readValue(slea);
|
||||||
|
for (int i = 0; i < children; i++) {
|
||||||
|
WZIMGEntry child = new WZIMGEntry(entry);
|
||||||
|
parse(child, slea);
|
||||||
|
child.finish();
|
||||||
|
entry.addChild(child);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
System.out.println("Canvas marker != 1 (" + marker + ")");
|
||||||
|
}
|
||||||
|
int width = WZTool.readValue(slea);
|
||||||
|
int height = WZTool.readValue(slea);
|
||||||
|
int format = WZTool.readValue(slea);
|
||||||
|
int format2 = slea.readByte();
|
||||||
|
slea.readInt();
|
||||||
|
int dataLength = slea.readInt() - 1;
|
||||||
|
slea.readByte();
|
||||||
|
if (provideImages) {
|
||||||
|
byte[] pngdata = slea.read(dataLength);
|
||||||
|
entry.setData(new PNGMapleCanvas(width, height, dataLength, format + format2, pngdata));
|
||||||
|
} else {
|
||||||
|
entry.setData(new PNGMapleCanvas(width, height, dataLength, format + format2, null));
|
||||||
|
slea.skip(dataLength);
|
||||||
|
}
|
||||||
|
} else if (type.equals("Shape2D#Vector2D")) {
|
||||||
|
entry.setType(MapleDataType.VECTOR);
|
||||||
|
int x = WZTool.readValue(slea);
|
||||||
|
int y = WZTool.readValue(slea);
|
||||||
|
entry.setData(new Point(x, y));
|
||||||
|
} else if (type.equals("Shape2D#Convex2D")) {
|
||||||
|
int children = WZTool.readValue(slea);
|
||||||
|
for (int i = 0; i < children; i++) {
|
||||||
|
WZIMGEntry cEntry = new WZIMGEntry(entry);
|
||||||
|
parseExtended(cEntry, slea, 0);
|
||||||
|
cEntry.finish();
|
||||||
|
entry.addChild(cEntry);
|
||||||
|
}
|
||||||
|
} else if (type.equals("Sound_DX8")) {
|
||||||
|
entry.setType(MapleDataType.SOUND);
|
||||||
|
slea.readByte();
|
||||||
|
int dataLength = WZTool.readValue(slea);
|
||||||
|
WZTool.readValue(slea); // no clue what this is
|
||||||
|
int offset = (int) slea.getPosition();
|
||||||
|
entry.setData(new ImgMapleSound(dataLength, offset - file.getOffset()));
|
||||||
|
slea.seek(endOfExtendedBlock);
|
||||||
|
} else if (type.equals("UOL")) {
|
||||||
|
entry.setType(MapleDataType.UOL);
|
||||||
|
slea.readByte();
|
||||||
|
byte uolmarker = slea.readByte();
|
||||||
|
switch (uolmarker) {
|
||||||
|
case 0:
|
||||||
|
entry.setData(WZTool.readDecodedString(slea));
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
entry.setData(WZTool.readDecodedStringAtOffsetAndReset(slea, file.getOffset() + slea.readInt()));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
System.out.println("Unknown UOL marker: " + uolmarker + " " + entry.getName());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Unhandled extended type: " + type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,187 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 provider.wz;
|
||||||
|
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import javax.crypto.BadPaddingException;
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.IllegalBlockSizeException;
|
||||||
|
import javax.crypto.NoSuchPaddingException;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
import tools.data.input.LittleEndianAccessor;
|
||||||
|
import tools.data.input.SeekableLittleEndianAccessor;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ported Code, see WZFile.java for more info
|
||||||
|
*/
|
||||||
|
public class WZTool {
|
||||||
|
private static byte[] encKey;
|
||||||
|
|
||||||
|
static {
|
||||||
|
byte[] iv = new byte[]{(byte) 0x4d, (byte) 0x23, (byte) 0xc7, (byte) 0x2b,
|
||||||
|
(byte) 0x4d, (byte) 0x23, (byte) 0xc7, (byte) 0x2b,
|
||||||
|
(byte) 0x4d, (byte) 0x23, (byte) 0xc7, (byte) 0x2b,
|
||||||
|
(byte) 0x4d, (byte) 0x23, (byte) 0xc7, (byte) 0x2b,};
|
||||||
|
byte[] key = new byte[]{(byte) 0x13, 0x00, 0x00, 0x00,
|
||||||
|
(byte) 0x08, 0x00, 0x00, 0x00,
|
||||||
|
(byte) 0x06, 0x00, 0x00, 0x00,
|
||||||
|
(byte) 0xB4, 0x00, 0x00, 0x00,
|
||||||
|
(byte) 0x1B, 0x00, 0x00, 0x00,
|
||||||
|
(byte) 0x0F, 0x00, 0x00, 0x00,
|
||||||
|
(byte) 0x33, 0x00, 0x00, 0x00,
|
||||||
|
(byte) 0x52, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
Cipher cipher = null;
|
||||||
|
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
|
||||||
|
try {
|
||||||
|
cipher = Cipher.getInstance("AES");
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (NoSuchPaddingException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
|
||||||
|
} catch (InvalidKeyException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
encKey = new byte[0xFFFF];
|
||||||
|
for (int i = 0; i < (0xFFFF / 16); i++) {
|
||||||
|
try {
|
||||||
|
iv = cipher.doFinal(iv);
|
||||||
|
} catch (IllegalBlockSizeException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (BadPaddingException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
System.arraycopy(iv, 0, encKey, (i * 16), 16);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
iv = cipher.doFinal(iv);
|
||||||
|
} catch (IllegalBlockSizeException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (BadPaddingException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
System.arraycopy(iv, 0, encKey, 65520, 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] readListString(byte[] str) {
|
||||||
|
for (int i = 0; i < str.length; i++) {
|
||||||
|
str[i] = (byte) (str[i] ^ encKey[i]);
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String readDecodedString(LittleEndianAccessor llea) {
|
||||||
|
int strLength;
|
||||||
|
byte b = llea.readByte();
|
||||||
|
if (b == 0x00) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (b >= 0) {
|
||||||
|
if (b == 0x7F) {
|
||||||
|
strLength = llea.readInt();
|
||||||
|
} else {
|
||||||
|
strLength = (int) b;
|
||||||
|
}
|
||||||
|
if (strLength < 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
byte str[] = new byte[strLength * 2];
|
||||||
|
for (int i = 0; i < strLength * 2; i++) {
|
||||||
|
str[i] = llea.readByte();
|
||||||
|
}
|
||||||
|
return DecryptUnicodeStr(str);
|
||||||
|
} else {
|
||||||
|
if (b == -128) {
|
||||||
|
strLength = llea.readInt();
|
||||||
|
} else {
|
||||||
|
strLength = -b;
|
||||||
|
}
|
||||||
|
if (strLength < 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
byte str[] = new byte[strLength];
|
||||||
|
for (int i = 0; i < strLength; i++) {
|
||||||
|
str[i] = llea.readByte();
|
||||||
|
}
|
||||||
|
return DecryptAsciiStr(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String DecryptAsciiStr(byte[] str) {
|
||||||
|
byte xorByte = (byte) 0xAA;
|
||||||
|
for (int i = 0; i < str.length; i++) {
|
||||||
|
str[i] = (byte) (str[i] ^ xorByte ^ encKey[i]);
|
||||||
|
xorByte++;
|
||||||
|
}
|
||||||
|
return new String(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String DecryptUnicodeStr(byte[] str) {
|
||||||
|
int xorByte = 0xAAAA;
|
||||||
|
char[] charRet = new char[str.length / 2];
|
||||||
|
for (int i = 0; i < str.length; i++) {
|
||||||
|
str[i] = (byte) (str[i] ^ encKey[i]);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < (str.length / 2); i++) {
|
||||||
|
char toXor = (char) ((str[i] << 8) | str[i + 1]);
|
||||||
|
charRet[i] = (char) (toXor ^ xorByte);
|
||||||
|
xorByte++;
|
||||||
|
}
|
||||||
|
return String.valueOf(charRet);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String readDecodedStringAtOffset(SeekableLittleEndianAccessor slea, int offset) {
|
||||||
|
slea.seek(offset);
|
||||||
|
return readDecodedString(slea);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String readDecodedStringAtOffsetAndReset(SeekableLittleEndianAccessor slea, int offset) {
|
||||||
|
long pos = 0;
|
||||||
|
pos = slea.getPosition();
|
||||||
|
slea.seek(offset);
|
||||||
|
String ret = readDecodedString(slea);
|
||||||
|
slea.seek(pos);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int readValue(LittleEndianAccessor lea) {
|
||||||
|
byte b = lea.readByte();
|
||||||
|
if (b == -128) {
|
||||||
|
return lea.readInt();
|
||||||
|
} else {
|
||||||
|
return ((int) b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float readFloatValue(LittleEndianAccessor lea) {
|
||||||
|
byte b = lea.readByte();
|
||||||
|
if (b == -128) {
|
||||||
|
return lea.readFloat();
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,219 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 provider.wz;
|
||||||
|
|
||||||
|
import java.awt.Point;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.text.NumberFormat;
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
import provider.MapleData;
|
||||||
|
import provider.MapleDataEntity;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.NamedNodeMap;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
public class XMLDomMapleData implements MapleData {
|
||||||
|
private Node node;
|
||||||
|
private File imageDataDir;
|
||||||
|
private NumberFormat nf;
|
||||||
|
|
||||||
|
public XMLDomMapleData(FileInputStream fis, File imageDataDir) {
|
||||||
|
try {
|
||||||
|
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
|
||||||
|
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
|
||||||
|
Document document = documentBuilder.parse(fis);
|
||||||
|
this.node = document.getFirstChild();
|
||||||
|
} catch (ParserConfigurationException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (SAXException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
this.imageDataDir = imageDataDir;
|
||||||
|
this.nf = NumberFormat.getInstance(Locale.FRANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private XMLDomMapleData(Node node) {
|
||||||
|
this.node = node;
|
||||||
|
this.nf = NumberFormat.getInstance(Locale.FRANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MapleData getChildByPath(String path) {
|
||||||
|
String segments[] = path.split("/");
|
||||||
|
if (segments[0].equals("..")) {
|
||||||
|
return ((MapleData) getParent()).getChildByPath(path.substring(path.indexOf("/") + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
Node myNode = node;
|
||||||
|
for (int x = 0; x < segments.length; x++) {
|
||||||
|
NodeList childNodes = myNode.getChildNodes();
|
||||||
|
boolean foundChild = false;
|
||||||
|
for (int i = 0; i < childNodes.getLength(); i++) {
|
||||||
|
Node childNode = childNodes.item(i);
|
||||||
|
if (childNode.getNodeType() == Node.ELEMENT_NODE && childNode.getAttributes().getNamedItem("name").getNodeValue().equals(segments[x])) {
|
||||||
|
myNode = childNode;
|
||||||
|
foundChild = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!foundChild) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
XMLDomMapleData ret = new XMLDomMapleData(myNode);
|
||||||
|
ret.imageDataDir = new File(imageDataDir, getName() + "/" + path).getParentFile();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<MapleData> getChildren() {
|
||||||
|
List<MapleData> ret = new ArrayList<MapleData>();
|
||||||
|
NodeList childNodes = node.getChildNodes();
|
||||||
|
for (int i = 0; i < childNodes.getLength(); i++) {
|
||||||
|
Node childNode = childNodes.item(i);
|
||||||
|
if (childNode.getNodeType() == Node.ELEMENT_NODE) {
|
||||||
|
XMLDomMapleData child = new XMLDomMapleData(childNode);
|
||||||
|
child.imageDataDir = new File(imageDataDir, getName());
|
||||||
|
ret.add(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getData() {
|
||||||
|
NamedNodeMap attributes = node.getAttributes();
|
||||||
|
MapleDataType type = getType();
|
||||||
|
switch (type) {
|
||||||
|
case DOUBLE:
|
||||||
|
case FLOAT:
|
||||||
|
case INT:
|
||||||
|
case SHORT: {
|
||||||
|
String value = attributes.getNamedItem("value").getNodeValue();
|
||||||
|
Number nval;
|
||||||
|
|
||||||
|
try {
|
||||||
|
nval = nf.parse(value);
|
||||||
|
}
|
||||||
|
catch(java.text.ParseException pe) {
|
||||||
|
pe.printStackTrace();
|
||||||
|
nval = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case DOUBLE:
|
||||||
|
return nval.doubleValue();
|
||||||
|
case FLOAT:
|
||||||
|
return nval.floatValue();
|
||||||
|
case INT:
|
||||||
|
return nval.intValue();
|
||||||
|
case SHORT:
|
||||||
|
return nval.shortValue();
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case STRING:
|
||||||
|
case UOL: {
|
||||||
|
String value = attributes.getNamedItem("value").getNodeValue();
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
case VECTOR: {
|
||||||
|
String x = attributes.getNamedItem("x").getNodeValue();
|
||||||
|
String y = attributes.getNamedItem("y").getNodeValue();
|
||||||
|
return new Point(Integer.parseInt(x), Integer.parseInt(y));
|
||||||
|
}
|
||||||
|
case CANVAS: {
|
||||||
|
String width = attributes.getNamedItem("width").getNodeValue();
|
||||||
|
String height = attributes.getNamedItem("height").getNodeValue();
|
||||||
|
return new FileStoredPngMapleCanvas(Integer.parseInt(width), Integer.parseInt(height), new File(
|
||||||
|
imageDataDir, getName() + ".png"));
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MapleDataType getType() {
|
||||||
|
String nodeName = node.getNodeName();
|
||||||
|
if (nodeName.equals("imgdir")) {
|
||||||
|
return MapleDataType.PROPERTY;
|
||||||
|
} else if (nodeName.equals("canvas")) {
|
||||||
|
return MapleDataType.CANVAS;
|
||||||
|
} else if (nodeName.equals("convex")) {
|
||||||
|
return MapleDataType.CONVEX;
|
||||||
|
} else if (nodeName.equals("sound")) {
|
||||||
|
return MapleDataType.SOUND;
|
||||||
|
} else if (nodeName.equals("uol")) {
|
||||||
|
return MapleDataType.UOL;
|
||||||
|
} else if (nodeName.equals("double")) {
|
||||||
|
return MapleDataType.DOUBLE;
|
||||||
|
} else if (nodeName.equals("float")) {
|
||||||
|
return MapleDataType.FLOAT;
|
||||||
|
} else if (nodeName.equals("int")) {
|
||||||
|
return MapleDataType.INT;
|
||||||
|
} else if (nodeName.equals("short")) {
|
||||||
|
return MapleDataType.SHORT;
|
||||||
|
} else if (nodeName.equals("string")) {
|
||||||
|
return MapleDataType.STRING;
|
||||||
|
} else if (nodeName.equals("vector")) {
|
||||||
|
return MapleDataType.VECTOR;
|
||||||
|
} else if (nodeName.equals("null")) {
|
||||||
|
return MapleDataType.IMG_0x00;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MapleDataEntity getParent() {
|
||||||
|
Node parentNode = node.getParentNode();
|
||||||
|
if (parentNode.getNodeType() == Node.DOCUMENT_NODE) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
XMLDomMapleData parentData = new XMLDomMapleData(parentNode);
|
||||||
|
parentData.imageDataDir = imageDataDir.getParentFile();
|
||||||
|
return parentData;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return node.getAttributes().getNamedItem("name").getNodeValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<MapleData> iterator() {
|
||||||
|
return getChildren().iterator();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 provider.wz;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import provider.MapleData;
|
||||||
|
import provider.MapleDataDirectoryEntry;
|
||||||
|
import provider.MapleDataProvider;
|
||||||
|
|
||||||
|
public class XMLWZFile implements MapleDataProvider {
|
||||||
|
private File root;
|
||||||
|
private WZDirectoryEntry rootForNavigation;
|
||||||
|
|
||||||
|
public XMLWZFile(File fileIn) {
|
||||||
|
root = fileIn;
|
||||||
|
rootForNavigation = new WZDirectoryEntry(fileIn.getName(), 0, 0, null);
|
||||||
|
fillMapleDataEntitys(root, rootForNavigation);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillMapleDataEntitys(File lroot, WZDirectoryEntry wzdir) {
|
||||||
|
for (File file : lroot.listFiles()) {
|
||||||
|
String fileName = file.getName();
|
||||||
|
if (file.isDirectory() && !fileName.endsWith(".img")) {
|
||||||
|
WZDirectoryEntry newDir = new WZDirectoryEntry(fileName, 0, 0, wzdir);
|
||||||
|
wzdir.addDirectory(newDir);
|
||||||
|
fillMapleDataEntitys(file, newDir);
|
||||||
|
} else if (fileName.endsWith(".xml")) {
|
||||||
|
wzdir.addFile(new WZFileEntry(fileName.substring(0, fileName.length() - 4), 0, 0, wzdir));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MapleData getData(String path) {
|
||||||
|
File dataFile = new File(root, path + ".xml");
|
||||||
|
File imageDataDir = new File(root, path);
|
||||||
|
if (!dataFile.exists()) {
|
||||||
|
return null;//bitches
|
||||||
|
}
|
||||||
|
FileInputStream fis;
|
||||||
|
try {
|
||||||
|
fis = new FileInputStream(dataFile);
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
throw new RuntimeException("Datafile " + path + " does not exist in " + root.getAbsolutePath());
|
||||||
|
}
|
||||||
|
final XMLDomMapleData domMapleData;
|
||||||
|
try {
|
||||||
|
domMapleData = new XMLDomMapleData(fis, imageDataDir.getParentFile());
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
fis.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return domMapleData;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MapleDataDirectoryEntry getRoot() {
|
||||||
|
return rootForNavigation;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 tools;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
|
||||||
|
public class HexTool {
|
||||||
|
private static final char[] HEX = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||||
|
|
||||||
|
private static String toString(byte byteValue) {
|
||||||
|
int tmp = byteValue << 8;
|
||||||
|
char[] retstr = new char[]{HEX[(tmp >> 12) & 0x0F], HEX[(tmp >> 8) & 0x0F]};
|
||||||
|
return String.valueOf(retstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toString(byte[] bytes) {
|
||||||
|
StringBuilder hexed = new StringBuilder();
|
||||||
|
for (int i = 0; i < bytes.length; i++) {
|
||||||
|
hexed.append(toString(bytes[i]));
|
||||||
|
hexed.append(' ');
|
||||||
|
}
|
||||||
|
return hexed.substring(0, hexed.length() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] getByteArrayFromHexString(String hex) {
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
int nexti = 0;
|
||||||
|
int nextb = 0;
|
||||||
|
boolean highoc = true;
|
||||||
|
outer:
|
||||||
|
for (;;) {
|
||||||
|
int number = -1;
|
||||||
|
while (number == -1) {
|
||||||
|
if (nexti == hex.length()) {
|
||||||
|
break outer;
|
||||||
|
}
|
||||||
|
char chr = hex.charAt(nexti);
|
||||||
|
if (chr >= '0' && chr <= '9') {
|
||||||
|
number = chr - '0';
|
||||||
|
} else if (chr >= 'a' && chr <= 'f') {
|
||||||
|
number = chr - 'a' + 10;
|
||||||
|
} else if (chr >= 'A' && chr <= 'F') {
|
||||||
|
number = chr - 'A' + 10;
|
||||||
|
} else {
|
||||||
|
number = -1;
|
||||||
|
}
|
||||||
|
nexti++;
|
||||||
|
}
|
||||||
|
if (highoc) {
|
||||||
|
nextb = number << 4;
|
||||||
|
highoc = false;
|
||||||
|
} else {
|
||||||
|
nextb |= number;
|
||||||
|
highoc = true;
|
||||||
|
baos.write(nextb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return baos.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 tools.data.input;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import tools.HexTool;
|
||||||
|
|
||||||
|
public class ByteArrayByteStream implements SeekableInputStreamBytestream {
|
||||||
|
private int pos = 0;
|
||||||
|
private long bytesRead = 0;
|
||||||
|
private byte[] arr;
|
||||||
|
|
||||||
|
public ByteArrayByteStream(byte[] arr) {
|
||||||
|
this.arr = arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getPosition() {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void seek(long offset) throws IOException {
|
||||||
|
pos = (int) offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getBytesRead() {
|
||||||
|
return bytesRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int readByte() {
|
||||||
|
bytesRead++;
|
||||||
|
return ((int) arr[pos++]) & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
String nows = "kevintjuh93 pwns";//I lol'd
|
||||||
|
if (arr.length - pos > 0) {
|
||||||
|
byte[] now = new byte[arr.length - pos];
|
||||||
|
System.arraycopy(arr, pos, now, 0, arr.length - pos);
|
||||||
|
nows = HexTool.toString(now);
|
||||||
|
}
|
||||||
|
return "All: " + HexTool.toString(arr) + "\nNow: " + nows;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long available() {
|
||||||
|
return arr.length - pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 tools.data.input;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an abstract stream of bytes.
|
||||||
|
*
|
||||||
|
* @author Frz
|
||||||
|
* @version 1.0
|
||||||
|
* @since Revision 323
|
||||||
|
*/
|
||||||
|
public interface ByteInputStream {
|
||||||
|
int readByte();
|
||||||
|
long getBytesRead();
|
||||||
|
long available();
|
||||||
|
}
|
||||||
@@ -0,0 +1,239 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 tools.data.input;
|
||||||
|
|
||||||
|
import java.awt.Point;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a generic interface to a Little Endian stream of bytes.
|
||||||
|
*
|
||||||
|
* @version 1.0
|
||||||
|
* @author Frz
|
||||||
|
* @since Revision 323
|
||||||
|
*/
|
||||||
|
public class GenericLittleEndianAccessor implements LittleEndianAccessor {
|
||||||
|
private ByteInputStream bs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class constructor - Wraps the accessor around a stream of bytes.
|
||||||
|
*
|
||||||
|
* @param bs The byte stream to wrap the accessor around.
|
||||||
|
*/
|
||||||
|
public GenericLittleEndianAccessor(ByteInputStream bs) {
|
||||||
|
this.bs = bs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a single byte from the stream.
|
||||||
|
*
|
||||||
|
* @return The byte read.
|
||||||
|
* @see tools.data.input.ByteInputStream#readByte
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public byte readByte() {
|
||||||
|
return (byte) bs.readByte();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads an integer from the stream.
|
||||||
|
*
|
||||||
|
* @return The integer read.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int readInt() {
|
||||||
|
return bs.readByte() + (bs.readByte() << 8) + (bs.readByte() << 16) + (bs.readByte() << 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a short integer from the stream.
|
||||||
|
*
|
||||||
|
* @return The short read.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public short readShort() {
|
||||||
|
return (short) (bs.readByte() + (bs.readByte() << 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a single character from the stream.
|
||||||
|
*
|
||||||
|
* @return The character read.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public char readChar() {
|
||||||
|
return (char) readShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a long integer from the stream.
|
||||||
|
*
|
||||||
|
* @return The long integer read.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public long readLong() {
|
||||||
|
long byte1 = bs.readByte();
|
||||||
|
long byte2 = bs.readByte();
|
||||||
|
long byte3 = bs.readByte();
|
||||||
|
long byte4 = bs.readByte();
|
||||||
|
long byte5 = bs.readByte();
|
||||||
|
long byte6 = bs.readByte();
|
||||||
|
long byte7 = bs.readByte();
|
||||||
|
long byte8 = bs.readByte();
|
||||||
|
return (byte8 << 56) + (byte7 << 48) + (byte6 << 40) + (byte5 << 32) + (byte4 << 24) + (byte3 << 16) + (byte2 << 8) + byte1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a floating point integer from the stream.
|
||||||
|
*
|
||||||
|
* @return The float-type integer read.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public float readFloat() {
|
||||||
|
return Float.intBitsToFloat(readInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a double-precision integer from the stream.
|
||||||
|
*
|
||||||
|
* @return The double-type integer read.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public double readDouble() {
|
||||||
|
return Double.longBitsToDouble(readLong());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads an ASCII string from the stream with length <code>n</code>.
|
||||||
|
*
|
||||||
|
* @param n Number of characters to read.
|
||||||
|
* @return The string read.
|
||||||
|
*/
|
||||||
|
public final String readAsciiString(int n) {
|
||||||
|
char ret[] = new char[n];
|
||||||
|
for (int x = 0; x < n; x++) {
|
||||||
|
ret[x] = (char) readByte();
|
||||||
|
}
|
||||||
|
return String.valueOf(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a null-terminated string from the stream.
|
||||||
|
*
|
||||||
|
* @return The string read.
|
||||||
|
*/
|
||||||
|
public final String readNullTerminatedAsciiString() {
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
byte b;
|
||||||
|
while (true) {
|
||||||
|
b = readByte();
|
||||||
|
if (b == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
baos.write(b);
|
||||||
|
}
|
||||||
|
byte[] buf = baos.toByteArray();
|
||||||
|
char[] chrBuf = new char[buf.length];
|
||||||
|
for (int x = 0; x < buf.length; x++) {
|
||||||
|
chrBuf[x] = (char) buf[x];
|
||||||
|
}
|
||||||
|
return String.valueOf(chrBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the number of bytes read from the stream so far.
|
||||||
|
*
|
||||||
|
* @return A long integer representing the number of bytes read.
|
||||||
|
* @see tools.data.input.ByteInputStream#getBytesRead()
|
||||||
|
*/
|
||||||
|
public long getBytesRead() {
|
||||||
|
return bs.getBytesRead();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a MapleStory convention lengthed ASCII string.
|
||||||
|
* This consists of a short integer telling the length of the string,
|
||||||
|
* then the string itself.
|
||||||
|
*
|
||||||
|
* @return The string read.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String readMapleAsciiString() {
|
||||||
|
return readAsciiString(readShort());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads <code>num</code> bytes off the stream.
|
||||||
|
*
|
||||||
|
* @param num The number of bytes to read.
|
||||||
|
* @return An array of bytes with the length of <code>num</code>
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public byte[] read(int num) {
|
||||||
|
byte[] ret = new byte[num];
|
||||||
|
for (int x = 0; x < num; x++) {
|
||||||
|
ret[x] = readByte();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a MapleStory Position information.
|
||||||
|
* This consists of 2 short integer.
|
||||||
|
*
|
||||||
|
* @return The Position read.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public final Point readPos() {
|
||||||
|
final int x = readShort();
|
||||||
|
final int y = readShort();
|
||||||
|
return new Point(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Skips the current position of the stream <code>num</code> bytes ahead.
|
||||||
|
*
|
||||||
|
* @param num Number of bytes to skip.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void skip(int num) {
|
||||||
|
for (int x = 0; x < num; x++) {
|
||||||
|
readByte();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see tools.data.input.ByteInputStream#available
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public long available() {
|
||||||
|
return bs.available();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see java.lang.Object#toString
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return bs.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
+91
@@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 tools.data.input;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides an abstract accessor to a generic Little Endian byte stream. This
|
||||||
|
* accessor is seekable.
|
||||||
|
*
|
||||||
|
* @author Frz
|
||||||
|
* @version 1.0
|
||||||
|
* @since Revision 323
|
||||||
|
* @see tools.data.input.GenericLittleEndianAccessor
|
||||||
|
*/
|
||||||
|
public class GenericSeekableLittleEndianAccessor extends GenericLittleEndianAccessor implements SeekableLittleEndianAccessor {
|
||||||
|
private SeekableInputStreamBytestream bs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class constructor
|
||||||
|
* Provide a seekable input stream to wrap this object around.
|
||||||
|
*
|
||||||
|
* @param bs The byte stream to wrap this around.
|
||||||
|
*/
|
||||||
|
public GenericSeekableLittleEndianAccessor(SeekableInputStreamBytestream bs) {
|
||||||
|
super(bs);
|
||||||
|
this.bs = bs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Seek the pointer to <code>offset</code>
|
||||||
|
*
|
||||||
|
* @param offset The offset to seek to.
|
||||||
|
* @see tools.data.input.SeekableInputStreamBytestream#seek
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void seek(long offset) {
|
||||||
|
try {
|
||||||
|
bs.seek(offset);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
System.out.println("Seek failed " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current position of the pointer.
|
||||||
|
*
|
||||||
|
* @return The current position of the pointer as a long integer.
|
||||||
|
* @see tools.data.input.SeekableInputStreamBytestream#getPosition
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public long getPosition() {
|
||||||
|
try {
|
||||||
|
return bs.getPosition();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
System.out.println("getPosition failed" + e);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Skip <code>num</code> number of bytes in the stream.
|
||||||
|
*
|
||||||
|
* @param num The number of bytes to skip.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void skip(int num) {
|
||||||
|
seek(getPosition() + num);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 tools.data.input;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides an abstract wrapper to a stream of bytes.
|
||||||
|
*
|
||||||
|
* @author Frz
|
||||||
|
* @version 1.0
|
||||||
|
* @since Revision 323
|
||||||
|
*/
|
||||||
|
public class InputStreamByteStream implements ByteInputStream {
|
||||||
|
private InputStream is;
|
||||||
|
private long read = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class constructor.
|
||||||
|
* Provide an input stream to wrap this around.
|
||||||
|
*
|
||||||
|
* @param is The input stream to wrap this object around.
|
||||||
|
*/
|
||||||
|
public InputStreamByteStream(InputStream is) {
|
||||||
|
this.is = is;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the next byte from the stream.
|
||||||
|
*
|
||||||
|
* @return Then next byte in the stream.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int readByte() {
|
||||||
|
int temp;
|
||||||
|
try {
|
||||||
|
temp = is.read();
|
||||||
|
if (temp == -1) {
|
||||||
|
throw new RuntimeException("EOF");
|
||||||
|
}
|
||||||
|
read++;
|
||||||
|
return temp;
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the number of bytes read from the stream.
|
||||||
|
*
|
||||||
|
* @return The number of bytes read as a long integer.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public long getBytesRead() {
|
||||||
|
return read;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of bytes left in the stream.
|
||||||
|
*
|
||||||
|
* @return The number of bytes available for reading as a long integer.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public long available() {
|
||||||
|
try {
|
||||||
|
return is.available();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
System.out.println("ERROR" + e);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 tools.data.input;
|
||||||
|
|
||||||
|
import java.awt.Point;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Frz
|
||||||
|
*/
|
||||||
|
public interface LittleEndianAccessor {
|
||||||
|
byte readByte();
|
||||||
|
char readChar();
|
||||||
|
short readShort();
|
||||||
|
int readInt();
|
||||||
|
Point readPos();
|
||||||
|
long readLong();
|
||||||
|
void skip(int num);
|
||||||
|
byte[] read(int num);
|
||||||
|
float readFloat();
|
||||||
|
double readDouble();
|
||||||
|
String readAsciiString(int n);
|
||||||
|
String readNullTerminatedAsciiString();
|
||||||
|
String readMapleAsciiString();
|
||||||
|
long getBytesRead();
|
||||||
|
long available();
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 tools.data.input;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.RandomAccessFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides an abstract layer to a byte stream. This layer can be accessed
|
||||||
|
* randomly.
|
||||||
|
*
|
||||||
|
* @author Frz
|
||||||
|
* @version 1.0
|
||||||
|
* @since Revision 323
|
||||||
|
*/
|
||||||
|
public class RandomAccessByteStream implements SeekableInputStreamBytestream {
|
||||||
|
private RandomAccessFile raf;
|
||||||
|
private long read = 0;
|
||||||
|
|
||||||
|
public RandomAccessByteStream(RandomAccessFile raf) {
|
||||||
|
super();
|
||||||
|
this.raf = raf;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int readByte() {
|
||||||
|
int temp;
|
||||||
|
try {
|
||||||
|
temp = raf.read();
|
||||||
|
if (temp == -1) {
|
||||||
|
throw new RuntimeException("EOF");
|
||||||
|
}
|
||||||
|
read++;
|
||||||
|
return temp;
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void seek(long offset) throws IOException {
|
||||||
|
raf.seek(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getPosition() throws IOException {
|
||||||
|
return raf.getFilePointer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getBytesRead() {
|
||||||
|
return read;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long available() {
|
||||||
|
try {
|
||||||
|
return raf.length() - raf.getFilePointer();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
System.out.println("ERROR " + e);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 tools.data.input;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides an abstract interface to a stream of bytes. This stream can be
|
||||||
|
* seeked.
|
||||||
|
*
|
||||||
|
* @author Frz
|
||||||
|
* @version 1.0
|
||||||
|
* @since 299
|
||||||
|
*/
|
||||||
|
public interface SeekableInputStreamBytestream extends ByteInputStream {
|
||||||
|
/**
|
||||||
|
* Seeks the stream by the specified offset.
|
||||||
|
*
|
||||||
|
* @param offset
|
||||||
|
* Number of bytes to seek.
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
void seek(long offset) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current position of the stream.
|
||||||
|
*
|
||||||
|
* @return The stream position as a long integer.
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
long getPosition() throws IOException;
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
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 tools.data.input;
|
||||||
|
|
||||||
|
public interface SeekableLittleEndianAccessor extends LittleEndianAccessor {
|
||||||
|
void seek(long offset);
|
||||||
|
long getPosition();
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- You may freely edit this file. See commented blocks below for -->
|
||||||
|
<!-- some examples of how to customize the build. -->
|
||||||
|
<!-- (If you delete it and reopen the project it will be recreated.) -->
|
||||||
|
<!-- By default, only the Clean and Build commands use this build script. -->
|
||||||
|
<!-- Commands such as Run, Debug, and Test only use this build script if -->
|
||||||
|
<!-- the Compile on Save feature is turned off for the project. -->
|
||||||
|
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
|
||||||
|
<!-- in the project's Project Properties dialog box.-->
|
||||||
|
<project name="MapleSkillMakerReagentIndexer" default="default" basedir=".">
|
||||||
|
<description>Builds, tests, and runs the project MapleSkillMakerReagentIndexer.</description>
|
||||||
|
<import file="nbproject/build-impl.xml"/>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
There exist several targets which are by default empty and which can be
|
||||||
|
used for execution of your tasks. These targets are usually executed
|
||||||
|
before and after some main targets. They are:
|
||||||
|
|
||||||
|
-pre-init: called before initialization of project properties
|
||||||
|
-post-init: called after initialization of project properties
|
||||||
|
-pre-compile: called before javac compilation
|
||||||
|
-post-compile: called after javac compilation
|
||||||
|
-pre-compile-single: called before javac compilation of single file
|
||||||
|
-post-compile-single: called after javac compilation of single file
|
||||||
|
-pre-compile-test: called before javac compilation of JUnit tests
|
||||||
|
-post-compile-test: called after javac compilation of JUnit tests
|
||||||
|
-pre-compile-test-single: called before javac compilation of single JUnit test
|
||||||
|
-post-compile-test-single: called after javac compilation of single JUunit test
|
||||||
|
-pre-jar: called before JAR building
|
||||||
|
-post-jar: called after JAR building
|
||||||
|
-post-clean: called after cleaning build products
|
||||||
|
|
||||||
|
(Targets beginning with '-' are not intended to be called on their own.)
|
||||||
|
|
||||||
|
Example of inserting an obfuscator after compilation could look like this:
|
||||||
|
|
||||||
|
<target name="-post-compile">
|
||||||
|
<obfuscate>
|
||||||
|
<fileset dir="${build.classes.dir}"/>
|
||||||
|
</obfuscate>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
For list of available properties check the imported
|
||||||
|
nbproject/build-impl.xml file.
|
||||||
|
|
||||||
|
|
||||||
|
Another way to customize the build is by overriding existing main targets.
|
||||||
|
The targets of interest are:
|
||||||
|
|
||||||
|
-init-macrodef-javac: defines macro for javac compilation
|
||||||
|
-init-macrodef-junit: defines macro for junit execution
|
||||||
|
-init-macrodef-debug: defines macro for class debugging
|
||||||
|
-init-macrodef-java: defines macro for class execution
|
||||||
|
-do-jar: JAR building
|
||||||
|
run: execution of project
|
||||||
|
-javadoc-build: Javadoc generation
|
||||||
|
test-report: JUnit report generation
|
||||||
|
|
||||||
|
An example of overriding the target for project execution could look like this:
|
||||||
|
|
||||||
|
<target name="run" depends="MapleSkillMakerReagentIndexer-impl.jar">
|
||||||
|
<exec dir="bin" executable="launcher.exe">
|
||||||
|
<arg file="${dist.jar}"/>
|
||||||
|
</exec>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
Notice that the overridden target depends on the jar target and not only on
|
||||||
|
the compile target as the regular run target does. Again, for a list of available
|
||||||
|
properties which you can use, check the target you are overriding in the
|
||||||
|
nbproject/build-impl.xml file.
|
||||||
|
|
||||||
|
-->
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
# SQL File autogenerated from the MapleSkillMakerReagentIndexer feature by Ronan Lana.
|
||||||
|
# Generated data is conformant with the Item.wz folder used to compile this.
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `makerreagentdata` (
|
||||||
|
`itemid` int(11) NOT NULL,
|
||||||
|
`stat` varchar(20) NOT NULL,
|
||||||
|
`value` smallint(6) NOT NULL,
|
||||||
|
PRIMARY KEY (`itemid`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||||
|
|
||||||
|
INSERT IGNORE INTO `makerreagentdata` (`itemid`, `stat`, `value`) VALUES
|
||||||
|
(4250000, "incPAD", 1),
|
||||||
|
(4250001, "incPAD", 2),
|
||||||
|
(4250002, "incPAD", 3),
|
||||||
|
(4250100, "incMAD", 1),
|
||||||
|
(4250101, "incMAD", 2),
|
||||||
|
(4250102, "incMAD", 3),
|
||||||
|
(4250200, "incACC", 2),
|
||||||
|
(4250201, "incACC", 3),
|
||||||
|
(4250202, "incACC", 5),
|
||||||
|
(4250300, "incEVA", 2),
|
||||||
|
(4250301, "incEVA", 3),
|
||||||
|
(4250302, "incEVA", 5),
|
||||||
|
(4250400, "incSpeed", 2),
|
||||||
|
(4250401, "incSpeed", 3),
|
||||||
|
(4250402, "incSpeed", 5),
|
||||||
|
(4250500, "incJump", 1),
|
||||||
|
(4250501, "incJump", 2),
|
||||||
|
(4250502, "incJump", 3),
|
||||||
|
(4250600, "incMaxHP", 10),
|
||||||
|
(4250601, "incMaxHP", 20),
|
||||||
|
(4250602, "incMaxHP", 30),
|
||||||
|
(4250700, "incMaxMP", 10),
|
||||||
|
(4250701, "incMaxMP", 20),
|
||||||
|
(4250702, "incMaxMP", 30),
|
||||||
|
(4250800, "incSTR", 2),
|
||||||
|
(4250801, "incSTR", 3),
|
||||||
|
(4250802, "incSTR", 5),
|
||||||
|
(4250900, "incINT", 2),
|
||||||
|
(4250901, "incINT", 3),
|
||||||
|
(4250902, "incINT", 5),
|
||||||
|
(4251000, "incLUK", 2),
|
||||||
|
(4251001, "incLUK", 3),
|
||||||
|
(4251002, "incLUK", 5),
|
||||||
|
(4251100, "incDEX", 2),
|
||||||
|
(4251101, "incDEX", 3),
|
||||||
|
(4251102, "incDEX", 5),
|
||||||
|
(4251200, "incReqLevel", -1),
|
||||||
|
(4251201, "incReqLevel", -2),
|
||||||
|
(4251202, "incReqLevel", -3),
|
||||||
|
(4251300, "randOption", 1),
|
||||||
|
(4251301, "randOption", 2),
|
||||||
|
(4251302, "randOption", 3),
|
||||||
|
(4251400, "randStat", 2),
|
||||||
|
(4251401, "randStat", 3),
|
||||||
|
(4251402, "randStat", 5);
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
Manifest-Version: 1.0
|
||||||
|
X-COMMENT: Main-Class will be added automatically by build
|
||||||
|
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,8 @@
|
|||||||
|
build.xml.data.CRC32=49f97f2c
|
||||||
|
build.xml.script.CRC32=75bbe280
|
||||||
|
build.xml.stylesheet.CRC32=[email protected]
|
||||||
|
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
|
||||||
|
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
|
||||||
|
nbproject/build-impl.xml.data.CRC32=49f97f2c
|
||||||
|
nbproject/build-impl.xml.script.CRC32=919b8bee
|
||||||
|
nbproject/build-impl.xml.stylesheet.CRC32=[email protected]
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
annotation.processing.enabled=true
|
||||||
|
annotation.processing.enabled.in.editor=false
|
||||||
|
annotation.processing.processor.options=
|
||||||
|
annotation.processing.processors.list=
|
||||||
|
annotation.processing.run.all.processors=true
|
||||||
|
annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
|
||||||
|
build.classes.dir=${build.dir}/classes
|
||||||
|
build.classes.excludes=**/*.java,**/*.form
|
||||||
|
# This directory is removed when the project is cleaned:
|
||||||
|
build.dir=build
|
||||||
|
build.generated.dir=${build.dir}/generated
|
||||||
|
build.generated.sources.dir=${build.dir}/generated-sources
|
||||||
|
# Only compile against the classpath explicitly listed here:
|
||||||
|
build.sysclasspath=ignore
|
||||||
|
build.test.classes.dir=${build.dir}/test/classes
|
||||||
|
build.test.results.dir=${build.dir}/test/results
|
||||||
|
# Uncomment to specify the preferred debugger connection transport:
|
||||||
|
#debug.transport=dt_socket
|
||||||
|
debug.classpath=\
|
||||||
|
${run.classpath}
|
||||||
|
debug.test.classpath=\
|
||||||
|
${run.test.classpath}
|
||||||
|
# Os arquivos em build.classes.dir que devem ser exclu\u00eddos do jar de distribui\u00e7\u00e3o
|
||||||
|
dist.archive.excludes=
|
||||||
|
# This directory is removed when the project is cleaned:
|
||||||
|
dist.dir=dist
|
||||||
|
dist.jar=${dist.dir}/MapleSkillMakerReagentIndexer.jar
|
||||||
|
dist.javadoc.dir=${dist.dir}/javadoc
|
||||||
|
excludes=
|
||||||
|
includes=**
|
||||||
|
jar.compress=false
|
||||||
|
javac.classpath=
|
||||||
|
# Space-separated list of extra javac options
|
||||||
|
javac.compilerargs=
|
||||||
|
javac.deprecation=false
|
||||||
|
javac.processorpath=\
|
||||||
|
${javac.classpath}
|
||||||
|
javac.source=1.7
|
||||||
|
javac.target=1.7
|
||||||
|
javac.test.classpath=\
|
||||||
|
${javac.classpath}:\
|
||||||
|
${build.classes.dir}
|
||||||
|
javac.test.processorpath=\
|
||||||
|
${javac.test.classpath}
|
||||||
|
javadoc.additionalparam=
|
||||||
|
javadoc.author=false
|
||||||
|
javadoc.encoding=${source.encoding}
|
||||||
|
javadoc.noindex=false
|
||||||
|
javadoc.nonavbar=false
|
||||||
|
javadoc.notree=false
|
||||||
|
javadoc.private=false
|
||||||
|
javadoc.splitindex=true
|
||||||
|
javadoc.use=true
|
||||||
|
javadoc.version=false
|
||||||
|
javadoc.windowtitle=
|
||||||
|
main.class=mapleskillmakerreagentindexer.MapleSkillMakerReagentIndexer
|
||||||
|
manifest.file=manifest.mf
|
||||||
|
meta.inf.dir=${src.dir}/META-INF
|
||||||
|
mkdist.disabled=false
|
||||||
|
platform.active=JDK_1.7
|
||||||
|
run.classpath=\
|
||||||
|
${javac.classpath}:\
|
||||||
|
${build.classes.dir}
|
||||||
|
# Space-separated list of JVM arguments used when running the project.
|
||||||
|
# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value.
|
||||||
|
# To set system properties for unit tests define test-sys-prop.name=value:
|
||||||
|
run.jvmargs=
|
||||||
|
run.test.classpath=\
|
||||||
|
${javac.test.classpath}:\
|
||||||
|
${build.test.classes.dir}
|
||||||
|
source.encoding=UTF-8
|
||||||
|
src.dir=src
|
||||||
|
test.src.dir=test
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://www.netbeans.org/ns/project/1">
|
||||||
|
<type>org.netbeans.modules.java.j2seproject</type>
|
||||||
|
<configuration>
|
||||||
|
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
|
||||||
|
<name>MapleSkillMakerReagentIndexer</name>
|
||||||
|
<explicit-platform explicit-source-supported="true"/>
|
||||||
|
<source-roots>
|
||||||
|
<root id="src.dir"/>
|
||||||
|
</source-roots>
|
||||||
|
<test-roots>
|
||||||
|
<root id="test.src.dir"/>
|
||||||
|
</test-roots>
|
||||||
|
</data>
|
||||||
|
</configuration>
|
||||||
|
</project>
|
||||||
+226
@@ -0,0 +1,226 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MapleSolaxiaV2 Maple Story Server
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 RonanLana
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package mapleskillmakerreagentindexer;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author RonanLana
|
||||||
|
*
|
||||||
|
* The main objective of this program is to index relevant reagent data
|
||||||
|
* from the Item.wz folder and generate a SQL table with them, to be used
|
||||||
|
* by the server source.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class MapleSkillMakerReagentIndexer {
|
||||||
|
static String host = "jdbc:mysql://localhost:3306/maplesolaxia";
|
||||||
|
static String driver = "com.mysql.jdbc.Driver";
|
||||||
|
static String username = "root";
|
||||||
|
static String password = "";
|
||||||
|
|
||||||
|
static String fileName = "../../wz/Item.wz/Etc/0425.img.xml";
|
||||||
|
static String newFile = "lib/MakerReagentData.sql";
|
||||||
|
|
||||||
|
static PrintWriter printWriter = null;
|
||||||
|
static InputStreamReader fileReader = null;
|
||||||
|
static BufferedReader bufferedReader = null;
|
||||||
|
static byte status = 0;
|
||||||
|
|
||||||
|
static int id = -1;
|
||||||
|
static List<Pair<Integer, Pair<String, Integer>>> reagentList = new ArrayList<>();
|
||||||
|
|
||||||
|
static int initialStringLength = 50;
|
||||||
|
|
||||||
|
private static String getName(String token) {
|
||||||
|
int i, j;
|
||||||
|
char[] dest;
|
||||||
|
String d;
|
||||||
|
|
||||||
|
i = token.lastIndexOf("name");
|
||||||
|
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||||
|
j = token.indexOf("\"", i); //upper bound
|
||||||
|
|
||||||
|
dest = new char[initialStringLength];
|
||||||
|
token.getChars(i, j, dest, 0);
|
||||||
|
|
||||||
|
d = new String(dest);
|
||||||
|
return(d.trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getValue(String token) {
|
||||||
|
int i, j;
|
||||||
|
char[] dest;
|
||||||
|
String d;
|
||||||
|
|
||||||
|
i = token.lastIndexOf("value");
|
||||||
|
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||||
|
j = token.indexOf("\"", i); //upper bound
|
||||||
|
|
||||||
|
dest = new char[initialStringLength];
|
||||||
|
token.getChars(i, j, dest, 0);
|
||||||
|
|
||||||
|
d = new String(dest);
|
||||||
|
return(d.trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void simpleToken(String token) {
|
||||||
|
if(token.contains("/imgdir")) {
|
||||||
|
status -= 1;
|
||||||
|
}
|
||||||
|
else if(token.contains("imgdir")) {
|
||||||
|
status += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void forwardCursor(int st) {
|
||||||
|
String line = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
while(status >= st && (line = bufferedReader.readLine()) != null) {
|
||||||
|
simpleToken(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void translateToken(String token) {
|
||||||
|
String d;
|
||||||
|
|
||||||
|
if(token.contains("/imgdir")) {
|
||||||
|
status -= 1;
|
||||||
|
}
|
||||||
|
else if(token.contains("imgdir")) {
|
||||||
|
if(status == 1) { //getting id
|
||||||
|
d = getName(token);
|
||||||
|
id = Integer.parseInt(d);
|
||||||
|
System.out.println("Parsing maker reagent id " + id);
|
||||||
|
} else if(status == 2) {
|
||||||
|
d = getName(token);
|
||||||
|
if(!d.equals("info")) {
|
||||||
|
System.out.println("not info");
|
||||||
|
forwardCursor(status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
status += 1;
|
||||||
|
} else {
|
||||||
|
if(status == 3) {
|
||||||
|
if(token.contains("int")) {
|
||||||
|
d = getName(token);
|
||||||
|
|
||||||
|
if(d.contains("inc") || d.contains("rand")) {
|
||||||
|
Integer v = Integer.valueOf(getValue(token));
|
||||||
|
Pair<String, Integer> reagBuff = new Pair<>(d, v);
|
||||||
|
|
||||||
|
Pair<Integer, Pair<String, Integer>> reagItem = new Pair<>(id, reagBuff);
|
||||||
|
reagentList.add(reagItem);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(token.contains("canvas")) {
|
||||||
|
forwardCursor(status + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SortReagentList() {
|
||||||
|
Collections.sort(reagentList, new Comparator<Pair<Integer, Pair<String, Integer>>>() {
|
||||||
|
@Override
|
||||||
|
public int compare(Pair<Integer, Pair<String, Integer>> p1, Pair<Integer, Pair<String, Integer>> p2) {
|
||||||
|
return p1.getLeft().compareTo(p2.getLeft());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteMakerReagentTableFile() {
|
||||||
|
printWriter.println(" # SQL File autogenerated from the MapleSkillMakerReagentIndexer feature by Ronan Lana.");
|
||||||
|
printWriter.println(" # Generated data is conformant with the Item.wz folder used to compile this.");
|
||||||
|
printWriter.println();
|
||||||
|
|
||||||
|
printWriter.println("CREATE TABLE IF NOT EXISTS `makerreagentdata` (");
|
||||||
|
printWriter.println(" `itemid` int(11) NOT NULL,");
|
||||||
|
printWriter.println(" `stat` varchar(20) NOT NULL,");
|
||||||
|
printWriter.println(" `value` smallint(6) NOT NULL,");
|
||||||
|
printWriter.println(" PRIMARY KEY (`itemid`)");
|
||||||
|
printWriter.println(") ENGINE=MyISAM DEFAULT CHARSET=latin1;");
|
||||||
|
printWriter.println();
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder("INSERT IGNORE INTO `makerreagentdata` (`itemid`, `stat`, `value`) VALUES\r\n");
|
||||||
|
|
||||||
|
for(Pair<Integer, Pair<String, Integer>> it : reagentList) {
|
||||||
|
sb.append(" (" + it.left + ", \"" + it.right.left + "\", " + it.right.right + "),\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.setLength(sb.length() - 3);
|
||||||
|
sb.append(";");
|
||||||
|
|
||||||
|
printWriter.println(sb);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteMakerReagentTableData() {
|
||||||
|
// This will reference one line at a time
|
||||||
|
String line = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
fileReader = new InputStreamReader(new FileInputStream(fileName), "UTF-8");
|
||||||
|
bufferedReader = new BufferedReader(fileReader);
|
||||||
|
|
||||||
|
while((line = bufferedReader.readLine()) != null) {
|
||||||
|
translateToken(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
bufferedReader.close();
|
||||||
|
fileReader.close();
|
||||||
|
|
||||||
|
SortReagentList();
|
||||||
|
|
||||||
|
printWriter = new PrintWriter(newFile, "UTF-8");
|
||||||
|
WriteMakerReagentTableFile();
|
||||||
|
printWriter.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
catch(FileNotFoundException ex) {
|
||||||
|
System.out.println("Unable to open file '" + fileName + "'");
|
||||||
|
}
|
||||||
|
catch(IOException ex) {
|
||||||
|
System.out.println("Error reading file '" + fileName + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
catch(Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
WriteMakerReagentTableData();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the OdinMS Maple Story Server
|
||||||
|
Copyright (C) 2008 ~ 2010 Patrick Huy <patrick.huy@frz.cc>
|
||||||
|
Matthias Butz <matze@odinms.de>
|
||||||
|
Jan Christian Meyer <vimes@odinms.de>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License version 3
|
||||||
|
as published by the Free Software Foundation. You may not use, modify
|
||||||
|
or distribute this program under any other version of the
|
||||||
|
GNU Affero General Public License.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package mapleskillmakerreagentindexer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a pair of values.
|
||||||
|
*
|
||||||
|
* @author Frz
|
||||||
|
* @since Revision 333
|
||||||
|
* @version 1.0
|
||||||
|
*
|
||||||
|
* @param <E> The type of the left value.
|
||||||
|
* @param <F> The type of the right value.
|
||||||
|
*/
|
||||||
|
public class Pair<E, F> {
|
||||||
|
|
||||||
|
public E left;
|
||||||
|
public F right;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class constructor - pairs two objects together.
|
||||||
|
*
|
||||||
|
* @param left The left object.
|
||||||
|
* @param right The right object.
|
||||||
|
*/
|
||||||
|
public Pair(E left, F right) {
|
||||||
|
this.left = left;
|
||||||
|
this.right = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the left value.
|
||||||
|
*
|
||||||
|
* @return The left value.
|
||||||
|
*/
|
||||||
|
public E getLeft() {
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the right value.
|
||||||
|
*
|
||||||
|
* @return The right value.
|
||||||
|
*/
|
||||||
|
public F getRight() {
|
||||||
|
return right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns the pair into a string.
|
||||||
|
*
|
||||||
|
* @return Each value of the pair as a string joined by a colon.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return left.toString() + ":" + right.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the hash code of this pair.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((left == null) ? 0 : left.hashCode());
|
||||||
|
result = prime * result + ((right == null) ? 0 : right.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks to see if two pairs are equal.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final Pair other = (Pair) obj;
|
||||||
|
if (left == null) {
|
||||||
|
if (other.left != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (!left.equals(other.left)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (right == null) {
|
||||||
|
if (other.right != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (!right.equals(other.right)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34682,7 +34682,6 @@
|
|||||||
<imgdir name="1">
|
<imgdir name="1">
|
||||||
</imgdir>
|
</imgdir>
|
||||||
<imgdir name="0">
|
<imgdir name="0">
|
||||||
<int name="money" value="-10000"/>
|
|
||||||
</imgdir>
|
</imgdir>
|
||||||
</imgdir>
|
</imgdir>
|
||||||
<imgdir name="6033">
|
<imgdir name="6033">
|
||||||
|
|||||||
@@ -56514,33 +56514,12 @@
|
|||||||
<int name="state" value="2"/>
|
<int name="state" value="2"/>
|
||||||
</imgdir>
|
</imgdir>
|
||||||
</imgdir>
|
</imgdir>
|
||||||
<imgdir name="infoex">
|
|
||||||
<imgdir name="0">
|
|
||||||
<string name="value" value="111"/>
|
|
||||||
</imgdir>
|
|
||||||
</imgdir>
|
|
||||||
</imgdir>
|
</imgdir>
|
||||||
</imgdir>
|
</imgdir>
|
||||||
<imgdir name="6030">
|
<imgdir name="6030">
|
||||||
<imgdir name="0">
|
<imgdir name="0">
|
||||||
<int name="npc" value="2110004"/>
|
<int name="npc" value="2110004"/>
|
||||||
<int name="lvmin" value="45"/>
|
<int name="lvmin" value="45"/>
|
||||||
<int name="interval" value="0"/>
|
|
||||||
<int name="infoNumber" value="6029"/>
|
|
||||||
<imgdir name="infoex">
|
|
||||||
<imgdir name="0">
|
|
||||||
<string name="value" value="000"/>
|
|
||||||
</imgdir>
|
|
||||||
<imgdir name="1">
|
|
||||||
<string name="value" value="010"/>
|
|
||||||
</imgdir>
|
|
||||||
<imgdir name="2">
|
|
||||||
<string name="value" value="011"/>
|
|
||||||
</imgdir>
|
|
||||||
<imgdir name="3">
|
|
||||||
<string name="value" value="001"/>
|
|
||||||
</imgdir>
|
|
||||||
</imgdir>
|
|
||||||
<imgdir name="quest">
|
<imgdir name="quest">
|
||||||
<imgdir name="0">
|
<imgdir name="0">
|
||||||
<int name="id" value="6029"/>
|
<int name="id" value="6029"/>
|
||||||
@@ -56628,32 +56607,18 @@
|
|||||||
<imgdir name="1">
|
<imgdir name="1">
|
||||||
<int name="npc" value="2111000"/>
|
<int name="npc" value="2111000"/>
|
||||||
<string name="endscript" value="q6030e"/>
|
<string name="endscript" value="q6030e"/>
|
||||||
|
<int name="endmeso" value="10000"/>
|
||||||
</imgdir>
|
</imgdir>
|
||||||
</imgdir>
|
</imgdir>
|
||||||
<imgdir name="6031">
|
<imgdir name="6031">
|
||||||
<imgdir name="1">
|
<imgdir name="1">
|
||||||
<int name="npc" value="2012017"/>
|
<int name="npc" value="2012017"/>
|
||||||
<string name="endscript" value="q6031e"/>
|
<string name="endscript" value="q6031e"/>
|
||||||
|
<int name="endmeso" value="10000"/>
|
||||||
</imgdir>
|
</imgdir>
|
||||||
<imgdir name="0">
|
<imgdir name="0">
|
||||||
<int name="npc" value="2110004"/>
|
<int name="npc" value="2110004"/>
|
||||||
<int name="lvmin" value="45"/>
|
<int name="lvmin" value="45"/>
|
||||||
<int name="interval" value="0"/>
|
|
||||||
<int name="infoNumber" value="6029"/>
|
|
||||||
<imgdir name="infoex">
|
|
||||||
<imgdir name="0">
|
|
||||||
<string name="value" value="000"/>
|
|
||||||
</imgdir>
|
|
||||||
<imgdir name="1">
|
|
||||||
<string name="value" value="100"/>
|
|
||||||
</imgdir>
|
|
||||||
<imgdir name="2">
|
|
||||||
<string name="value" value="101"/>
|
|
||||||
</imgdir>
|
|
||||||
<imgdir name="3">
|
|
||||||
<string name="value" value="001"/>
|
|
||||||
</imgdir>
|
|
||||||
</imgdir>
|
|
||||||
<imgdir name="quest">
|
<imgdir name="quest">
|
||||||
<imgdir name="0">
|
<imgdir name="0">
|
||||||
<int name="id" value="6029"/>
|
<int name="id" value="6029"/>
|
||||||
@@ -56743,22 +56708,6 @@
|
|||||||
<imgdir name="0">
|
<imgdir name="0">
|
||||||
<int name="npc" value="2110004"/>
|
<int name="npc" value="2110004"/>
|
||||||
<int name="lvmin" value="45"/>
|
<int name="lvmin" value="45"/>
|
||||||
<int name="interval" value="0"/>
|
|
||||||
<int name="infoNumber" value="6029"/>
|
|
||||||
<imgdir name="infoex">
|
|
||||||
<imgdir name="0">
|
|
||||||
<string name="value" value="000"/>
|
|
||||||
</imgdir>
|
|
||||||
<imgdir name="1">
|
|
||||||
<string name="value" value="100"/>
|
|
||||||
</imgdir>
|
|
||||||
<imgdir name="2">
|
|
||||||
<string name="value" value="110"/>
|
|
||||||
</imgdir>
|
|
||||||
<imgdir name="3">
|
|
||||||
<string name="value" value="010"/>
|
|
||||||
</imgdir>
|
|
||||||
</imgdir>
|
|
||||||
<imgdir name="quest">
|
<imgdir name="quest">
|
||||||
<imgdir name="0">
|
<imgdir name="0">
|
||||||
<int name="id" value="6029"/>
|
<int name="id" value="6029"/>
|
||||||
@@ -56846,6 +56795,7 @@
|
|||||||
<imgdir name="1">
|
<imgdir name="1">
|
||||||
<int name="npc" value="2110004"/>
|
<int name="npc" value="2110004"/>
|
||||||
<string name="endscript" value="q6032e"/>
|
<string name="endscript" value="q6032e"/>
|
||||||
|
<int name="endmeso" value="10000"/>
|
||||||
</imgdir>
|
</imgdir>
|
||||||
</imgdir>
|
</imgdir>
|
||||||
<imgdir name="6033">
|
<imgdir name="6033">
|
||||||
|
|||||||
@@ -22668,7 +22668,7 @@
|
|||||||
<imgdir name="0">
|
<imgdir name="0">
|
||||||
<string name="0" value="Ahh... What should I do... I wish he was here right now, so he can help me with this... what should I do..."/>
|
<string name="0" value="Ahh... What should I do... I wish he was here right now, so he can help me with this... what should I do..."/>
|
||||||
<string name="1" value="Ah... are you a traveler? It's really hard to find anyone willing to travel to Magatia... Nice to meet you. The kid you see right there is my daughter, and her name is #p2111005#. She may have an ever-present smile on her face, but she is actually a very sick child."/>
|
<string name="1" value="Ah... are you a traveler? It's really hard to find anyone willing to travel to Magatia... Nice to meet you. The kid you see right there is my daughter, and her name is #p2111005#. She may have an ever-present smile on her face, but she is actually a very sick child."/>
|
||||||
<string name="2" value="Even our best magcian, the president of the Zenumist Society, told me he can't do anything about #p2111005#. Alcadno? ...Alcadno wouldn't want to do anything with the kid... I don't know what to do ."/>
|
<string name="2" value="Even our best magician, the president of the Zenumist Society, told me he can't do anything about #p2111005#. Alcadno? ...Alcadno wouldn't want to do anything with the kid... I don't know what to do ."/>
|
||||||
<string name="3" value="If I could get a hold of him, then he could very well help... but it's so hard to contact him... Ah! Excuse me, but have you ever been to #b#m200000000##k? If you have, then can you do me a big favor?"/>
|
<string name="3" value="If I could get a hold of him, then he could very well help... but it's so hard to contact him... Ah! Excuse me, but have you ever been to #b#m200000000##k? If you have, then can you do me a big favor?"/>
|
||||||
<imgdir name="yes">
|
<imgdir name="yes">
|
||||||
<string name="0" value="Do you know of #b#p2012018##k at #m200000000#? He is very proficient with Fairy potions, and I'd like for him to help us out. I know he's capable of curing #p2111005#. If it's about #p2111004#, then I am sure he'll help out, no questions asked. Please visit him and ask for me, okay?"/>
|
<string name="0" value="Do you know of #b#p2012018##k at #m200000000#? He is very proficient with Fairy potions, and I'd like for him to help us out. I know he's capable of curing #p2111005#. If it's about #p2111004#, then I am sure he'll help out, no questions asked. Please visit him and ask for me, okay?"/>
|
||||||
|
|||||||
Reference in new issue
Block a user