Custom Quest System v1.6 || Quick Quest Creator
Custom Quest System v1.6
Update:
- Re-code the whole system.
- Improved and cleaned up by a bit
- Quick Quest Creator added [Still in Development]
- Each Quest gets a .ini file, where every neccessary information about the quest is stored.
- No more compiling after changing quest related stuff!!! (That freaked me out some time)
- Removed the side-story stuff. It's useless and coded badly. I will think of another way.
Are you sick of gMS's Quests?
Didn't you ever once thought about to make your own Quests?
It's possibru now!
Infos:
- Create a Custom Quest with up to 2 Monster Targets and 2 Items to Collect
- EXP & Meso Rewards up to 2,1bil possibru
- Handing out up to 1 Item type as reward (but as many as you want at once of selected type)
In Development:
So yeah. I was thinking on how to create quests quicker.
It end up writing a QuestCreator. It's not finished yet, but most
of it is done.
I would like to get some feedback on that, that's why I'm releasing
an unfinished version.
But first let's go on adding the Quest System itself:
Create a new file called MapleCQuests
PHP Code:
package client;
import java.util.Properties;
import java.io.FileInputStream;
/*
* Custom Quest System v1.6
* Author: LikeABaws
*/
public class MapleCQuests {
private int id;
private int target1, target2;
private int item1, item2;
private int reward1, reward2, reward3, reward4;
private int amount1, amount2, amount3, amount4;
private String npc;
private String title;
private String target1n, target2n;
private String item1n, item2n;
private String info;
public void loadQuest(int id) {
Properties p = new Properties();
try {
p.load(new FileInputStream("quests/" + id + ".ini"));
this.id = id;
this.target1 = Integer.parseInt(p.getProperty("MonsterID1"));
this.target2 = Integer.parseInt(p.getProperty("MonsterID2"));
this.item1 = Integer.parseInt(p.getProperty("CollectItemID1"));
this.item2 = Integer.parseInt(p.getProperty("CollectItemID2"));
this.amount1 = Integer.parseInt(p.getProperty("ToKill1"));
this.amount2 = Integer.parseInt(p.getProperty("ToKill2"));
this.amount3 = Integer.parseInt(p.getProperty("ToCollect1"));
this.amount4 = Integer.parseInt(p.getProperty("ToCollect2"));
this.reward1 = Integer.parseInt(p.getProperty("EXP"));
this.reward2 = Integer.parseInt(p.getProperty("MESO"));
this.reward3 = Integer.parseInt(p.getProperty("ITEM"));
this.reward4 = Integer.parseInt(p.getProperty("ITEM_amount"));
this.npc = "" + p.getProperty("NPC");
this.title = "" + p.getProperty("Title");
this.target1n = "" + p.getProperty("MonsterName1");
this.target2n = "" + p.getProperty("MonsterName2");
this.item1n = "" + p.getProperty("ItemName1");
this.item2n = "" + p.getProperty("ItemName2");
this.info = "" + p.getProperty("Info");
} catch (Exception e) {
System.out.println(e + " - Failed to load Quest " + id);
this.id = 0;
}
}
public int getId() {
return id;
}
public int getTargetId(int type) {
switch (type) {
case 1:
return target1;
case 2:
return target2;
}
return 0;
}
public String getTargetName(int type) {
switch (type) {
case 1:
return target1n;
case 2:
return target2n;
}
return "";
}
public int getItemId(int type) {
switch (type) {
case 1:
return item1;
case 2:
return item2;
}
return 0;
}
public String getItemName(int type) {
switch (type) {
case 1:
return item1n;
case 2:
return item2n;
}
return "";
}
public int getReward(int type) {
switch (type) {
case 1:
return reward1;
case 2:
return reward2;
case 3:
return reward3;
}
return 0;
}
public int getItemRewardAmount() {
return reward4;
}
public String getNPC() {
return npc;
}
public String loadTitle(int questid) {
String title = "";
Properties p = new Properties();
try {
p.load(new FileInputStream("quests/" + questid + ".ini"));
title += p.getProperty("Title");
} catch (Exception e) {
System.out.println(e + " - Failed to load Title of Quest: " + questid);
title += "u gotz error in thiz func";
}
return title;
}
public String getTitle() {
return title;
}
public String loadInfo(int questid) {
String info = "";
Properties p = new Properties();
try {
p.load(new FileInputStream("quests/" + questid + ".ini"));
info += p.getProperty("Info");
} catch (Exception e) {
System.out.println(e + " - Failed to load Info of Quest: " + questid);
title += "u gotz error in thiz func";
}
return info;
}
public String getInfo() {
return info;
}
public int getToKill(int type) {
switch (type) {
case 1:
return amount1;
case 2:
return amount2;
}
return 0;
}
public int getToCollect(int type) {
switch (type) {
case 1:
return amount3;
case 2:
return amount4;
}
return 0;
}
public void closeQuest() {
loadQuest(0);
}
}
Now add these parameters to MapleCharacter
PHP Code:
private MapleCQuests quest = new MapleCQuests();
private int story, storypoints;
private int questkills, questkills2;
private int questidd, queststatus;
I'm not going to explain how to add this to saveToDB, loadCharFromDB, etc.
There's a tutorial on adding parameters to MapleCharacter.
queststatus doesn't need to be saved or loaded.
For the questidd, save it as getCQuest().getId()
You need such basic knowlegde to understand what I actually code (since my code is a bit mess xD)
Add this to loadCharFromDB:
PHP Code:
if (ret.questidd > 0) {
ret.getCQuest().loadQuest(ret.questidd);
}
below this
PHP Code:
ret.questidd = rs.getInt("questidd");
after you added the parameters to loadCharFromDB.
If you're done with that, go on adding this:
PHP Code:
public MapleCQuests getCQuest() {
return quest;
}
public int getStory() {
return story;
}
public void setStory(int story) {
this.story = story;
}
public void addStory(int amt) {
story += amt;
}
public int getStoryPoints() {
return storypoints;
}
public void setStoryPoints(int points) {
this.storypoints = points;
}
public void addStoryPoints(int amt) {
storypoints += amt;
}
public int getQuestKills(int type) {
switch (type) {
case 1:
return questkills;
case 2:
return questkills2;
}
return 0;
}
public void setQuestKills(int type, int kills) {
switch (type) {
case 1:
this.questkills = kills;
break;
case 2:
this.questkills2 = kills;
break;
}
}
public void doQuestKill(int type) {
switch (type) {
case 1:
questkills++;
break;
case 2:
questkills2++;
break;
}
}
public int getQuestId() {
return questidd;
}
public void setQuestId(int id) {
this.questidd = id;
}
public boolean canComplete() {
int done = 0;
int toDo = 0;
if (getCQuest().getTargetId(1) > 0) {
toDo++;
if (questkills >= getCQuest().getToKill(1)) {
done++;
}
}
if (getCQuest().getTargetId(2) > 0) {
toDo++;
if (questkills >= getCQuest().getToKill(2)) {
done++;
}
}
if (getCQuest().getItemId(1) > 0) {
toDo++;
if (getItemQuantity(getCQuest().getItemId(1), false) >= getCQuest().getToCollect(1)) {
done++;
}
}
if (getCQuest().getItemId(2) > 0) {
toDo++;
if (getItemQuantity(getCQuest().getItemId(2), false) >= getCQuest().getToCollect(2)) {
done++;
}
}
return done == toDo;
}
public void makeQuestProgress(int mobid, int itemid) {
int a = 0;
if (mobid > 0) {
a += (mobid == getCQuest().getTargetId(1) ? 1 : 2);
doQuestKill(a);
if (getQuestKills(a) <= getCQuest().getToKill(a)) {
sendHint("#e" + getCQuest().getTargetName(a) + ": " + (getQuestKills(a) == getCQuest().getToKill(a) ? "#g" : "#r") + getQuestKills(a) + " #k/ " + getCQuest().getToKill(a));
}
} else if (itemid > 0) {
a += (itemid == getCQuest().getItemId(1) ? 1 : 2);
boolean needItem = getItemQuantity(getCQuest().getItemId(a), false) < getCQuest().getToCollect(a);
if (needItem) {
sendHint("#e" + getCQuest().getItemName(a) + ": " + (getItemQuantity(getCQuest().getItemId(a), false) >= getCQuest().getToCollect(a) ? "#g" : "#r") + getItemQuantity(getCQuest().getItemId(a), false) + " #k/ " + getCQuest().getToCollect(a));
}
}
if (canComplete() && queststatus == 0) {
sendHint("#eReturn to the NPC: " + getCQuest().getNPC());
dropMessage("Return to the NPC: " + getCQuest().getNPC());
queststatus++;
}
}
Go on adding:
PHP Code:
public void sendHint(String ms) {
sendHint(ms, 275, 10);
}
public void sendHint(String msg, int x, int y) {
getClient().announce(MaplePacketCreator.sendHint(msg, x, y));
getClient().announce(MaplePacketCreator.enableActions());
}
public static String makeNumberReadable(int nr) {
StringBuilder sb = new StringBuilder();
String readable;
String num = "" + nr;
String first_num = "";
String left_num = "";
int repeat = 0;
if (num.length() > 3) {
first_num += num;
while (first_num.length() > 3) {
first_num = first_num.substring(0, first_num.length() - 3);
repeat++;
}
sb.append(first_num).append(",");
left_num += num.substring(first_num.length(), num.length());
for (int x = 0; x < repeat; x++) {
sb.append(left_num.substring((3 * x), (3 * x) + 3)).append(",");
}
readable = sb.toString().substring(0, sb.toString().length() - 1);
} else {
readable = num;
}
return readable;
}
You might have sendHint already. If so, either replace it with mine or find a way to have mine and yours. Since removing one could cause problems.
As for makeNumberReadable, it's most likely the case, that you don't have.
Go on with NPCConversationManager
PHP Code:
import client.MapleCQuests;
PHP Code:
public int getStory() {
return getPlayer().getStory();
}
public void startQuest(int id) {
getPlayer().getCQuest().loadQuest(id);
getPlayer().setQuestId(id);
getPlayer().setQuestKills(1, 0);
getPlayer().setQuestKills(2, 0);
if (id == 0) {
getPlayer().sendHint("#eQuest Canceled!");
} else {
getPlayer().sendHint("#eQuest Start: " + getPlayer().getCQuest().getTitle());
}
}
public boolean onQuest() {
return getPlayer().getQuestId() > 0;
}
public boolean onQuest(int questid) {
return getPlayer().getQuestId() == questid;
}
public boolean canComplete() {
return getPlayer().canComplete();
}
public String selectQuest(int questid, String msg) {
String intro = msg + "\r\n\r\n#fUI/UIWindow.img/QuestIcon/3/0#\r\n#L0#";
String selection = "#k[" + (getPlayer().getQuestId() == 0 ? "#rAvailable" : (getPlayer().getQuestId() == questid && !canComplete()) ? "#dIn Prog." : "#gComplete") + "#k]";
return intro + selection + " #e" + getPlayer().getCQuest().loadTitle(questid);
}
public String showReward(String msg) {
StringBuilder sb = new StringBuilder();
sb.append(msg);
sb.append("\r\n\r\n#fUI/UIWindow.img/QuestIcon/4/0#\r\n\r\n");
sb.append("#fUI/UIWindow.img/QuestIcon/8/0# ").append(getPlayer().makeNumberReadable(getPlayer().getCQuest().getReward(1))).append("\r\n");
sb.append("#fUI/UIWindow.img/QuestIcon/7/0# ").append(getPlayer().makeNumberReadable(getPlayer().getCQuest().getReward(2))).append("\r\n");
if (getPlayer().getCQuest().getReward(3) > 0) {
sb.append("\r\n#i").append(getPlayer().getCQuest().getReward(3)).append("# ").append(getPlayer().makeNumberReadable(getPlayer().getCQuest().getItemRewardAmount()));
}
return sb.toString();
}
public void rewardPlayer(int story, int storypoints) {
MapleCQuests q = getPlayer().getCQuest();
getPlayer().addStory(story);
getPlayer().addStoryPoints(storypoints);
gainExp(q.getReward(1));
gainMeso(q.getReward(2));
if (q.getReward(3) > 0) {
gainItem(q.getReward(3), (short) (q.getItemRewardAmount() > 0 ? q.getItemRewardAmount() : 1));
}
if (q.getItemId(1) > 0) {
gainItem(q.getItemId(1), (short) q.getToCollect(1));
}
if (q.getItemId(2) > 0) {
gainItem(q.getItemId(2), (short) q.getToCollect(2));
}
c.announce(MaplePacketCreator.playSound("Dojan/clear"));
c.announce(MaplePacketCreator.showEffect("dojang/end/clear"));
startQuest(0);
}
public void rewardPlayer() {
rewardPlayer(1, 1);
}
public String showQuestProgress() {
MapleCQuests q = getPlayer().getCQuest();
boolean mob1 = q.getTargetId(1) > 0;
boolean mob2 = q.getTargetId(2) > 0;
boolean item1 = q.getItemId(1) > 0;
boolean item2 = q.getItemId(2) > 0;
boolean killed1 = getPlayer().getQuestKills(1) >= q.getToKill(1);
boolean killed2 = getPlayer().getQuestKills(2) >= q.getToKill(2);
boolean collected1 = false;
boolean collected2 = false;
if (item1) {
if (itemQuantity(q.getItemId(1)) >= q.getToCollect(1)) {
collected1 = true;
}
}
if (item2) {
if (itemQuantity(q.getItemId(2)) >= q.getToCollect(2)) {
collected2 = true;
}
}
StringBuilder sb = new StringBuilder();
sb.append("Your Quest Info for:\r\n#e#r").append(q.getTitle()).append("#n#k\r\n\r\n");
if (mob1 || mob2) {
sb.append("#eMonster Targets: #n\r\n");
if (mob1) {
sb.append(q.getTargetName(1)).append(": ").append(killed1 ? "#g" : "#r").append(getPlayer().getQuestKills(1)).append(" #k/ ").append(q.getToKill(1)).append("\r\n");
}
if (mob2) {
sb.append(q.getTargetName(2)).append(": ").append(killed2 ? "#g" : "#r").append(getPlayer().getQuestKills(2)).append(" #k/ ").append(q.getToKill(2)).append("\r\n");
}
sb.append("\r\n");
}
if (item1 || item2) {
sb.append("#eItems To Collect: #n\r\n");
if (item1) {
sb.append(q.getItemName(1)).append(": ").append(collected1 ? "#g" : "#r").append(itemQuantity(q.getItemId(1))).append(" #k/ ").append(q.getToCollect(1)).append("\r\n");
}
if (item2) {
sb.append(q.getItemName(2)).append(": ").append(collected2 ? "#g" : "#r").append(itemQuantity(q.getItemId(2))).append(" #k/ ").append(q.getToCollect(2)).append("\r\n");
}
sb.append("\r\n");
}
sb.append("#eQuest NPC: #n\r\n#d").append(q.getNPC()).append("\r\n");
sb.append("#eQuest Info: #n\r\n").append(q.getInfo());
return sb.toString();
}
public String randomText(int type) {
switch (type) {
case 1:
return "Hey, what's up?";
case 2:
return "Well, done";
case 3:
return "What a shame";
case 4:
return "You already accepted: ";
case 5:
return ". Do you want to cancel it?";
case 6:
return "Quest Complete!";
case 7:
return "You didn't complete your task yet. You can look it up by typing @questinfo in the chat.\r\nDo you want to cancel this Quest?";
}
return "";
}
Add this in the main killMonster function in MapleMap
PHP Code:
if ((monster.getId() == chr.getCQuest().getTargetId(1)) || (monster.getId() == chr.getCQuest().getTargetId(2))) {
chr.makeQuestProgress(monster.getId(), 0);
}
And this in ItemPickupHandler
PHP Code:
if ((mapitem.getItem().getItemId() == chr.getCQuest().getItemId(1)) || (mapitem.getItem().getItemId() == chr.getCQuest().getItemId(2))) {
chr.makeQuestProgress(0, mapitem.getItem().getItemId());
}
Below
PHP Code:
mapitem.setPickedUp(true);
chr.getMap().broadcastMessage(MaplePacketCreator.removeItemFromMap(mapitem.getObjectId(), 2, chr.getId()), mapitem.getPosition());
chr.getMap().removeMapObject(ob);
Since it loads quests from .ini files you have to add the following:
Firstly you have to add a folder called quests.
That's where all quests gonna be in.
If you are going to create the files by your own, the file has to look like this:
(This is an example how a working quest file can look like)
PHP Code:
# Created Quest (ID: 1000)
# Quest Name as String
Title=Whut Whut
# Monster Target Name as String
MonsterName1=Snail
MonsterName2=
# Monster Target ID as Integer
MonsterID1=100100
MonsterID2=0
# How many to kill of each as Integer
ToKill1=100
ToKill2=0
# Collect Item Name as String
ItemName1=
ItemName2=
# Collect Item ID as Integer
CollectItemID1=0
CollectItemID2=0
# How many to collect of each as Integer
ToCollect1=0
ToCollect2=0
# Rewards as Integer
EXP=1337
MESO=1337
ITEM=1302000
ITEM_amount=1
# Quest NPC as String
NPC=John
# Quest Info as String
Info=Kill 100 Snails to get the God of the World. That's a pretty badass quest, so take care!
If you don't use all items and monster target slot, than you can leave the NAMES blank.
As for the ID and the amounts it has to be 0 if you don't use it!
Same for rewards. If you don't use any of these slots, just set it to 0
The name of the file has to be the ID of the Quest
Developing:
Yeah ...
As I said, I worked on a Quick Quest Creator.
Gonna show you the code and explain how it is supposed to work after.
If you want to use this, first create a file in src > tools called QuestCreator
PHP Code:
package tools;
import java.io.Console;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
/*
* QuestCreator
* Author: LikeABaws
*/
public class QuestCreator {
public static void main(String args[]) {
StringBuilder sb = new StringBuilder();
Console con = System.console();
Properties p = new Properties();
boolean create_config = false;
boolean create_script_file = false;
System.out.println("Welcome to the QQC!\r\n\r\n");
try {
p.load(new FileInputStream("qqc_config.ini"));
} catch (Exception e) {
System.out.println("Seems like it's the first time you use QQC.\r\nGot to config really quick first.\r\n");
create_config = true;
}
if (create_config) {
sb.append("#Quick Quest Creator - Configuration\r\n\r\n");
String moople = con.readLine("Are you using Moople (non-RMI): (true/false) ");
while (!moople.equals("false") && !moople.equals("true")) {
System.out.println("If you are using Moople non-RMI type true. Otherweise type false!");
moople = con.readLine("Are you using Moople (non-RMI): (true/false) ");
}
String create_script = con.readLine("\r\nShall the QQC always add a basic NPC script for a created Quest? (true/false/?) ");
while (!create_script.equals("true") && !create_script.equals("false") && !create_script.equals("?")) {
create_script = con.readLine("\r\nShall the QQC always add a basic NPC script for a created Quest? (true/false/?) ");
}
while (create_script.equals("?")) {
System.out.println("\r\nSetting this to true will add a basic NPC script for every created custom Quest.\r\nThe Script contains: Quest Selecting, Quest Accepting, Quest Canceling, \r\nRewarding Player for succesful Quest.");
System.out.println("It will keep the script basic. So there won't be much NPC chat.\r\n");
create_script = con.readLine("\r\nShall the QQC always add a basic NPC script for a created Quest? (true/false/?) ");
}
sb.append("always_script=");
if (create_script.equals("true")) {
sb.append("true");
} else if (create_script.equals("false")) {
sb.append("false");
System.out.println("\r\nNonetheless the QQC will ask you for every quest if you want to!\r\nThis is why you still have to config the following:");
}
System.out.println("\r\n");
sb.append("\r\n");
if (moople.equals("true")) {
sb.append("moople=true").append("\r\n\r\n");
String all_world = con.readLine(" Since you are using Moople. \r\n Do you want an NPC Script created for all worlds? (true/false) ");
while (!all_world.equals("true") && !all_world.equals("false") && !all_world.equals("?")) {
System.out.println("If you want one for all worlds type true else type false.");
all_world = con.readLine(" Since you are using Moople.\r\n Do you want an NPC Script created for all worlds? (true/false) ");
}
if (all_world.equals("true")) {
sb.append("all_world=true").append("\r\n");
sb.append("world=");
} else if (all_world.equals("false")) {
sb.append("all_world=false").append("\r\n");;
try {
p.load(new FileInputStream("moople.ini"));
} catch (Exception e) {
System.out.println("There seems to be a problem. QQC will exit now.");
System.exit(0);
}
int worlds = Integer.parseInt(p.getProperty("worlds"));
String world = con.readLine("\r\n QQC found " + worlds + " world(s). For which one do you want scripts to be created? \r\n (0 for world0, 1 for world1, etc) ");
while (Integer.parseInt(world) + 1 > worlds) {
world = con.readLine("\r\n world" + world + " doesn't exist. Try again: ");
}
sb.append("world=").append(world);
}
sb.append("\r\n\r\nnpc_dir=");
} else if (moople.equals("false")) {
sb.append("moople=false").append("\r\n\r\n");
sb.append("all_world=").append("\r\n");
sb.append("world=").append("\r\n\r\n");
String dir = con.readLine("\r\nAre your NPC Scripts located in scripts/npc? (true/false) ");
while (!dir.equals("false") && !dir.equals("true")) {
System.out.println("If the scripts are located in scripts/npc then just type true else type false!");
dir = con.readLine("Are your NPC Scripts located in scripts/npc? (true/false) ");
}
if (dir.equals("true")) {
sb.append("npc_dir=").append("scripts/npc").append("\r\n");;
} else if (dir.equals("false")) {
sb.append("npc_dir=").append(con.readLine(" Type your NPC direction here: ")).append("\r\n");
}
}
sb.append("\r\n\r\n").append("next_quest=1000");
System.out.println("\r\nThe QQC Configuration file will now be created. \r\nTo start creating your own quests, please restart the QuestCreator!");
FileOutputStream out = null;
try {
out = new FileOutputStream("qqc_config.ini");
out.write(sb.toString().getBytes());
} catch (Exception e) {
System.out.println(e);
} finally {
try {
if (out != null) out.close();
} catch (IOException ex) {
System.out.println(ex);
}
}
} else {
System.out.println("Config file succesfully loaded.\r\nStart creating Quest");
sb.append("# Created Quest (ID: " + p.getProperty("next_quest") + ")").append("\r\n\r\n");
sb.append("# Quest Name as String").append("\r\n");
sb.append("Title=").append(con.readLine(" Quest Title: ")).append("\r\n\r\n");
System.out.println("");
sb.append("# Monster Target Name as String").append("\r\n");
sb.append("MonsterName1=").append(con.readLine(" 1st Monster Name: ")).append("\r\n");
sb.append("MonsterName2=").append(con.readLine(" 2nd Monster Name: ")).append("\r\n\r\n");
System.out.println("");
sb.append("# Monster Target ID as Integer").append("\r\n");
sb.append("MonsterID1=").append(Integer.parseInt(con.readLine(" 1st Monster ID: "))).append("\r\n");
sb.append("MonsterID2=").append(Integer.parseInt(con.readLine(" 2nd Monster ID: "))).append("\r\n\r\n");
System.out.println("");
sb.append("# How many to kill of each as Integer").append("\r\n");
sb.append("ToKill1=").append(Integer.parseInt(con.readLine(" How many to kill of 1st: "))).append("\r\n");
sb.append("ToKill2=").append(Integer.parseInt(con.readLine(" How many to kill of 2nd: "))).append("\r\n\r\n");
System.out.println("");
sb.append("# Collect Item Name as String").append("\r\n");
sb.append("ItemName1=").append(con.readLine(" 1st Collect Item Name: ")).append("\r\n");
sb.append("ItemName2=").append(con.readLine(" 2nd Collect Item Name: ")).append("\r\n\r\n");
System.out.println("");
sb.append("# Collect Item ID as Integer").append("\r\n");
sb.append("CollectItemID1=").append(Integer.parseInt(con.readLine(" 1st Collect Item ID: "))).append("\r\n");
sb.append("CollectItemID2=").append(Integer.parseInt(con.readLine(" 2nd Collect Item ID: "))).append("\r\n\r\n");
System.out.println("");
sb.append("# How many to collect of each as Integer").append("\r\n");
sb.append("ToCollect1=").append(Integer.parseInt(con.readLine(" How many to collect of 1st: "))).append("\r\n");
sb.append("ToCollect2=").append(Integer.parseInt(con.readLine(" How many to collect of 2nd: "))).append("\r\n\r\n");
System.out.println("");
sb.append("# Rewards as Integer").append("\r\n");
sb.append("EXP=").append(Integer.parseInt(con.readLine(" Exp reward: "))).append("\r\n");
sb.append("MESO=").append(Integer.parseInt(con.readLine(" Meso reward: "))).append("\r\n");
String item = con.readLine(" Item ID reward: ");
if (Integer.parseInt(item) > 0) {
sb.append("ITEM=").append(item).append("\r\n");
sb.append("ITEM_amount=").append(con.readLine(" Amount of Items: ")).append("\r\n\r\n");
} else {
sb.append("ITEM=").append("0").append("\r\n");
sb.append("Item_amount=").append("0").append("\r\n\r\n");
}
System.out.println("");
sb.append("# Quest NPC as String").append("\r\n");
sb.append("NPC=").append(con.readLine(" Quest NPC Name: ")).append("\r\n\r\n");
System.out.println("");
sb.append("# Quest Info as String").append("\r\n");
sb.append("Info=").append(con.readLine(" Quest Info: ")).append("\r\n");
FileOutputStream out = null;
try {
out = new FileOutputStream("quests/" + p.getProperty("next_quest") + ".ini");
out.write(sb.toString().getBytes());
} catch (Exception e) {
System.out.println(e);
} finally {
try {
if (out != null) out.close();
} catch (IOException ex) {
System.out.println(ex);
}
}
int new_next_quest = (Integer.parseInt(p.getProperty("next_quest")) + 1);
StringBuilder s = new StringBuilder();
s.append("always_script=").append(p.getProperty("always_script")).append("\r\n");
s.append("moople=").append(p.getProperty("moople")).append("\r\n\r\n");
s.append("all_world=").append(p.getProperty("all_world")).append("\r\n");
s.append("world=").append(p.getProperty("world")).append("\r\n\r\n");
s.append("npc_dir=").append(p.getProperty("npc_dir")).append("\r\n\r\n");
s.append("next_quest=").append(new_next_quest);
if (p.getProperty("always_script").equals("false")) {
String script = con.readLine("\r\nDo you want to create the basic NPC Script for this Quest? (y/n)");
while (!script.equals("y") && !script.equals("n")) {
script = con.readLine("\r\nDo you want to create the basic NPC Script for this Quest? (y/n)");
}
if (script.equals("y")) {
create_script_file = true;
} else if (script.equals("n")) {
System.out.println("\r\nNo Script was created. QQC will exit now!");
System.exit(0);
}
}
if (p.getProperty("always_script").equals("true")) {
create_script_file = true;
}
if (create_script_file) {
int npcid = Integer.parseInt(con.readLine("\r\n Type in the Quest NPC's ID: "));
int id = new_next_quest - 1;
if (p.getProperty("moople").equals("true")) {
if (p.getProperty("all_world").equals("true")) {
Properties ini = new Properties();
try {
ini.load(new FileInputStream("moople.ini"));
} catch (Exception e) {
System.out.println("There seems to be a problem. QQC will exit now");
System.exit(0);
}
int worlds = Integer.parseInt(ini.getProperty("worlds"));
for (int x = 0; x < worlds; x++) {
createQuestScript(id, npcid, "scripts/npc/world" + x);
}
} else {
createQuestScript(id, npcid, "scripts/npc/world" + p.getProperty("world"));
}
} else {
createQuestScript(id, npcid, p.getProperty("npc_dir"));
}
System.out.println("\r\nScript was created.");
}
FileOutputStream out2 = null;
try {
out2 = new FileOutputStream("qqc_config.ini");
out2.write(s.toString().getBytes());
} catch (Exception e) {
System.out.println(e);
} finally {
try {
if (out2 != null) out2.close();
} catch (IOException ex) {
System.out.println(ex);
}
}
System.out.println("QQC will exit now.");
}
}
public static void createQuestScript(int id, int npcid, String direction) {
StringBuilder b = new StringBuilder();
b.append("/**\r\n * Quick Quest: ").append(id).append("\r\n * Author: LikeABaws \r\n **/");
b.append("\r\n\r\n");
b.append("var id = ").append(id);
b.append("\r\n\r\n");
b.append("function start() {").append("\r\n");
b.append(" status = -1;").append("\r\n");
b.append(" action(1, 0, 0);").append("\r\n").append("}").append("\r\n\r\n");
b.append("function action (mode, type, selection) {").append("\r\n");
b.append(" if (mode == -1) {").append("\r\n");
b.append(" cm.dispose();").append("\r\n");
b.append(" } else {").append("\r\n");
b.append(" if (mode == 0 && status == 0) {").append("\r\n");
b.append(" cm.dispose();").append("\r\n");
b.append(" return;").append("\r\n").append(" }").append("\r\n");
b.append(" if (mode == 1)").append("\r\n");
b.append(" status++;").append("\r\n");
b.append(" else").append("\r\n");
b.append(" status--;").append("\r\n");
b.append(" if (!cm.onQuest()) {").append("\r\n");
b.append(" if (status == 0) {").append("\r\n");
b.append(" if (mode == 0) {").append("\r\n");
b.append(" cm.sendOk(cm.randomText(3));").append("\r\n");
b.append(" cm.dispose();").append("\r\n");
b.append(" } else {").append("\r\n");
b.append(" cm.sendSimple(cm.selectQuest(id, cm.randomText(1)));").append("\r\n");
b.append(" }").append("\r\n");
b.append(" } else if (status == 1) { ").append("\r\n");
b.append(" cm.sendAcceptDecline(cm.getPlayer().getCQuest().loadInfo(id));").append("\r\n");
b.append(" } else if (status == 2) { ").append("\r\n");
b.append(" cm.startQuest(id);").append("\r\n");
b.append(" cm.dispose();").append("\r\n");
b.append(" }").append("\r\n");
b.append(" } else if (!cm.onQuest(id)) {").append("\r\n");
b.append(" if (status == 0) {").append("\r\n");
b.append(" cm.sendYesNo(cm.randomText(4) + cm.getPlayer().getCQuest().getTitle() + cm.randomText(5));").append("\r\n");
b.append(" } else if (status == 1) {").append("\r\n");
b.append(" cm.startQuest(0);").append("\r\n");
b.append(" cm.dispose();").append("\r\n");
b.append(" }").append("\r\n");
b.append(" } else if (cm.onQuest(id) && cm.canComplete()) {").append("\r\n");
b.append(" if (status == 0) {").append("\r\n");
b.append(" cm.sendSimple(cm.selectQuest(id, cm.randomText(1)));").append("\r\n");
b.append(" } else if (status == 1) {").append("\r\n");
b.append(" cm.sendOk(cm.showReward(cm.randomText(2)));").append("\r\n");
b.append(" } else if (status == 2) {").append("\r\n");
b.append(" cm.rewardPlayer(0, 0);").append("\r\n");
b.append(" cm.getPlayer().sendHint(cm.randomText(6));").append("\r\n");
b.append(" cm.dispose();").append("\r\n");
b.append(" }").append("\r\n");
b.append(" } else if (cm.onQuest(id) && !cm.canComplete()) {").append("\r\n");
b.append(" if (status == 0) {").append("\r\n");
b.append(" if (mode == 0) {").append("\r\n");
b.append(" cm.dispose();").append("\r\n");
b.append(" } else {").append("\r\n");
b.append(" cm.sendSimple(cm.selectQuest(id, cm.randomText(1)));").append("\r\n");
b.append(" }").append("\r\n");
b.append(" } else if (status == 1) {").append("\r\n");
b.append(" cm.sendYesNo(cm.randomText(7));").append("\r\n");
b.append(" } else if (status == 2) {").append("\r\n");
b.append(" cm.startQuest(0);").append("\r\n");
b.append(" cm.dispose();").append("\r\n");
b.append(" }").append("\r\n");
b.append(" }").append("\r\n");
b.append(" }").append("\r\n");
b.append("}");
FileOutputStream out2 = null;
try {
out2 = new FileOutputStream(direction + "/" + npcid + ".js");
out2.write(b.toString().getBytes());
} catch (Exception e) {
System.out.println(e);
} finally {
try {
if (out2 != null) out2.close();
} catch (IOException ex) {
System.out.println(ex);
}
}
}
}
It works through a .bat file, so you gonna make one containing:
PHP Code:
@echo off
@title LikeABaws's Quick Quest Creator
set CLASSPATH=.;dist\*
java -Xmx10m -Djavax.net.ssl.keyStore=filename.keystore -Djavax.net.ssl.keyStorePassword=passwd -Djavax.net.ssl.trustStore=filename.keystore -Djavax.net.ssl.trustStorePassword=passwd tools.QuestCreator
pause
I have added a little configuration file to the Quest Creator.
Before creating any quest it will force you to set some settings.
Just a few. Couldn't think of anything else yet.
It pretty much looks like this:
PHP Code:
always_script=false
moople=true
all_world=true
world=
npc_dir=
next_quest=1003
If always_script is set to true, it will always automatically create a (very) basic NPC Script. It will contain anything neccessary to accept, cancel and finish a quest, as well as reward the player for his/her task.
Since most people use moople as a "base", I thought of adding a check for it.
If you set it to true, you will be asked if it the QQC shall add an NPC script to all online worlds or just a specific one. (all_world & world).
I assume that, if people use moople they don't change their script direction. (Who does that at all?! lol)
If you don't use moople, you will be asked if your NPC scripts are located in scripts/npc. If not, you may change it to whereever they are located. Thatfor I added npc_dir
Everytime you created a new .ini file for a quest, this configuration file will be modified.
You don't have to type a Quest ID yourself.
next_quest raises by 1 everytime a new quest is created.
If you set always_script to false, it will nonetheless ask you everytime you are creating a new quest, if you want to create a script for the new created quest.
You can decline, but if you accept (as well as when always_script is true) the script will look like:
PHP Code:
/**
* Quick Quest: 1002
* Author: LikeABaws
**/
var id = 1002
function start() {
status = -1;
action(1, 0, 0);
}
function action (mode, type, selection) {
if (mode == -1) {
cm.dispose();
} else {
if (mode == 0 && status == 0) {
cm.dispose();
return;
}
if (mode == 1)
status++;
else
status--;
if (!cm.onQuest()) {
if (status == 0) {
if (mode == 0) {
cm.sendOk(cm.randomText(3));
cm.dispose();
} else {
cm.sendSimple(cm.selectQuest(id, cm.randomText(1)));
}
} else if (status == 1) {
cm.sendAcceptDecline(cm.getPlayer().getCQuest().loadInfo(id));
} else if (status == 2) {
cm.startQuest(id);
cm.dispose();
}
} else if (!cm.onQuest(id)) {
if (status == 0) {
cm.sendYesNo(cm.randomText(4) + cm.getPlayer().getCQuest().getTitle() + cm.randomText(5));
} else if (status == 1) {
cm.startQuest(0);
cm.dispose();
}
} else if (cm.onQuest(id) && cm.canComplete()) {
if (status == 0) {
cm.sendSimple(cm.selectQuest(id, cm.randomText(1)));
} else if (status == 1) {
cm.sendOk(cm.showReward(cm.randomText(2)));
} else if (status == 2) {
cm.rewardPlayer(0, 0);
cm.getPlayer().sendHint(cm.randomText(6));
cm.dispose();
}
} else if (cm.onQuest(id) && !cm.canComplete()) {
if (status == 0) {
if (mode == 0) {
cm.dispose();
} else {
cm.sendSimple(cm.selectQuest(id, cm.randomText(1)));
}
} else if (status == 1) {
cm.sendYesNo(cm.randomText(7));
} else if (status == 2) {
cm.startQuest(0);
cm.dispose();
}
}
}
}
Hope I didn't forgot anything for the Quest System itself.
I can't assure your that it works 100% since there's quite much to test.
When I made a little quest test, it worked though.
As I said, I would like to get some feedback on that.
Maybe someone has an idea on what else to add or how to improve.
Trying to record a video in the next few days to show you how everything looks like.
(yea ik, I promised that last time already. But I got busy and totally forgot that I've released something :blush:)
re: Custom Quest System v1.6 || Quick Quest Creator
Instead of using an enumerator to store all the custom quest data, just make a new sql table having all the data and have a flags column for items.
This is still pretty cool though, and r u blueberry :)?
re: Custom Quest System v1.6 || Quick Quest Creator
Quote:
Originally Posted by
Expedia
Instead of using an enumerator to store all the custom quest data, just make a new sql table having all the data and have a flags column for items.
Gonna try that out as soon as I have time to.
I'm kinda new to Java, so used the way I was thinking of first.
Quote:
Originally Posted by
Expedia
This is still pretty cool though, and r u blueberry :)?
Nope :/:
re: Custom Quest System v1.6 || Quick Quest Creator
Quote:
Originally Posted by
LikeABaws
Gonna try that out as soon as I have time to.
I'm kinda new to Java, so used the way I was thinking of first.
Nope :/:
Well my idea with SQL is only to make it cleaner and is easier to read, otherwise it sucks.
re: Custom Quest System v1.6 || Quick Quest Creator
I didn't read what Expedia said, but storing all quest information sql sided, including mob kills for that specific quest (just add a counter to killMonster) and it'd be a lot cleaner. I was going to do this but I'm much too lazy. :3
re: Custom Quest System v1.6 || Quick Quest Creator
Uhhh.
You're either Ricky or Chris. :(
re: Custom Quest System v1.6 || Quick Quest Creator
Quote:
Originally Posted by
Veda
Uhhh.
You're either Ricky or Chris. :(
nope. its someone else. But he looks like he put a SHITLOAD of work into this GJ ;D:D:
re: Custom Quest System v1.6 || Quick Quest Creator
Quote:
Originally Posted by
Veda
Uhhh.
You're either Ricky or Chris. :(
wow travis i thought u knew me better :*: :*: :*: :*:
re: Custom Quest System v1.6 || Quick Quest Creator
I like how it's like blank so they can fill in everything, it's just a very detailed outline. It's a great way to release something, nice job.
re: Custom Quest System v1.6 || Quick Quest Creator
Quote:
Originally Posted by
YoWhatsGood
wow travis i thought u knew me better :*: :*: :*: :*:
Well, it had something about weed so I thought of you...
re: Custom Quest System v1.6 || Quick Quest Creator
re: Custom Quest System v1.6 || Quick Quest Creator
This is kind've like the quest system from KudoMs. :)
I'll use it haha.
Thanks! :)
re: Custom Quest System v1.6 || Quick Quest Creator
I'm pretty sure the Quest System in KudoMS isn't any like that.
At least it wasn't when I played it like ... 5 months ago or something.
I'll make a vid to show how everything looks like.
Since no one ask for how to make the NPC script, I guess it's
easy to figure out :blush:
Going to add a way for Sidestory Quests in a few days!
Quote:
Originally Posted by
Veda
Well, it had something about weed
LOL! I got bored, so I used stupid parameters :D
re: Custom Quest System v1.6 || Quick Quest Creator
it looks weird how its coded, but since I quit deving java I can't 'clean' it a bit, but other than that nice work :]
re: Custom Quest System v1.6 || Quick Quest Creator
Quote:
Originally Posted by
iAkira
it looks weird how its coded, but since I quit deving java I can't 'clean' it a bit, but other than that nice work :]
You should've seen my first try then :P
Tried to make this as clean as possible. Really don't know how to make it cleaner :wink:
Thanks (: