MagatiaPQ + several minor fixes

Added MagatiaPQ. Fixed a bug on Dojo where parties quitting the boss
fight without completing until rest point couldn't not start Dojo again
w/o reforming the party. Fixed issues with 2nd job NPC scripts. Reverted
command layout to use "!" and "@" again.
This commit is contained in:
ronancpl
2017-08-11 12:41:35 -03:00
parent f78defec1f
commit e0a27e00ab
185 changed files with 3316 additions and 527 deletions
+1 -1
View File
@@ -1227,7 +1227,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
long banTime = System.currentTimeMillis();
dropMessage(5, msg);
MapleMap map_ = client.getChannelServer().getMapFactory().getMap(mapid);
MapleMap map_ = getWarpMap(mapid);
changeMap(map_, map_.getPortal(portal));
setBanishPlayerData(banMap, banSp, banTime);
+59 -59
View File
@@ -108,9 +108,9 @@ public class Commands {
private static HashMap<String, Integer> gotomaps = new HashMap<String, Integer>();
private static String[] tips = {
"Please only use /gm in emergencies or to report somebody.",
"Please only use @gm in emergencies or to report somebody.",
"To report a bug or make a suggestion, use the forum.",
"Please do not use /gm to ask if a GM is online.",
"Please do not use @gm to ask if a GM is online.",
"Do not ask if you can receive help, just state your issue.",
"Do not say 'I have a bug to report', just state it.",
};
@@ -387,7 +387,7 @@ public class Commands {
}
}
if (gacha == null){
player.yellowMessage("Please use /gacha <name> where name corresponds to one of the below:");
player.yellowMessage("Please use @gacha <name> where name corresponds to one of the below:");
for (String name : names){
player.yellowMessage(name);
}
@@ -405,7 +405,7 @@ public class Commands {
case "whatdropsfrom":
if (sub.length < 2) {
player.dropMessage(5, "Please do /whatdropsfrom <monster name>");
player.dropMessage(5, "Please do @whatdropsfrom <monster name>");
break;
}
String monsterName = joinStringFrom(sub, 1);
@@ -439,7 +439,7 @@ public class Commands {
case "whodrops":
if (sub.length < 2) {
player.dropMessage(5, "Please do /whodrops <item name>");
player.dropMessage(5, "Please do @whodrops <item name>");
break;
}
String searchString = joinStringFrom(sub, 1);
@@ -551,7 +551,7 @@ public class Commands {
case "bug":
if (sub.length < 2) {
player.dropMessage(5, "Message too short and not sent. Please do /bug <bug>");
player.dropMessage(5, "Message too short and not sent. Please do @bug <bug>");
break;
}
message = joinStringFrom(sub, 1);
@@ -691,7 +691,7 @@ public class Commands {
case "goto":
if (sub.length < 2){
player.yellowMessage("Syntax: /goto <map name>");
player.yellowMessage("Syntax: @goto <map name>");
break;
}
@@ -738,7 +738,7 @@ public class Commands {
for (MapleMapObject npcs : player.getMap().getMapObjects()) {
if (npcs instanceof MapleNPC) {
MapleNPC npc = (MapleNPC) npcs;
player.dropMessage(5, ">> " + npc.getName() + " - " + npc.getId());
player.dropMessage(5, ">> " + npc.getName() + " - " + npc.getId() + " - Oid: " + npc.getObjectId());
}
}
player.yellowMessage("Monsters on this map:");
@@ -775,7 +775,7 @@ public class Commands {
case "sp":
if (sub.length < 2){
player.yellowMessage("Syntax: /sp [<playername>] <newsp>");
player.yellowMessage("Syntax: !sp [<playername>] <newsp>");
break;
}
@@ -791,7 +791,7 @@ public class Commands {
case "ap":
if (sub.length < 2){
player.yellowMessage("Syntax: /ap [<playername>] <newap>");
player.yellowMessage("Syntax: !ap [<playername>] <newap>");
break;
}
@@ -822,7 +822,7 @@ public class Commands {
case "buff":
if (sub.length < 2){
player.yellowMessage("Syntax: /buff <buffid>");
player.yellowMessage("Syntax: !buff <buffid>");
break;
}
int skillid=Integer.parseInt(sub[1]);
@@ -835,7 +835,7 @@ public class Commands {
if (sub.length > 1){
victim = c.getWorldServer().getPlayerStorage().getCharacterByName(sub[1]);
victim.getMap().spawnMonsterOnGroundBelow(MapleLifeFactory.getMonster(9300166), victim.getPosition());
Server.getInstance().broadcastGMMessage(MaplePacketCreator.serverNotice(5, player.getName() + " used /bomb on " + victim.getName()));
Server.getInstance().broadcastGMMessage(MaplePacketCreator.serverNotice(5, player.getName() + " used !bomb on " + victim.getName()));
} else {
player.getMap().spawnMonsterOnGroundBelow(MapleLifeFactory.getMonster(9300166), player.getPosition());
}
@@ -843,7 +843,7 @@ public class Commands {
case "dc":
if (sub.length < 2){
player.yellowMessage("Syntax: /dc <playername>");
player.yellowMessage("Syntax: !dc <playername>");
break;
}
@@ -876,7 +876,7 @@ public class Commands {
case "clearslot":
if (sub.length < 2) {
player.yellowMessage("Syntax: /clearslot <all, equip, use, setup, etc or cash.>");
player.yellowMessage("Syntax: !clearslot <all, equip, use, setup, etc or cash.>");
break;
}
String type = sub[1];
@@ -963,7 +963,7 @@ public class Commands {
case "warp":
if (sub.length < 2){
player.yellowMessage("Syntax: /warp <mapid>");
player.yellowMessage("Syntax: !warp <mapid>");
break;
}
@@ -985,7 +985,7 @@ public class Commands {
case "warpto":
if (sub.length < 3){
player.yellowMessage("Syntax: /warpto <playername> <mapid>");
player.yellowMessage("Syntax: !warpto <playername> <mapid>");
break;
}
@@ -1026,7 +1026,7 @@ public class Commands {
case "warphere":
case "summon":
if (sub.length < 2){
player.yellowMessage("Syntax: /warphere <playername>");
player.yellowMessage("Syntax: !warphere <playername>");
break;
}
@@ -1081,7 +1081,7 @@ public class Commands {
case "item":
case "drop":
if (sub.length < 2){
player.yellowMessage("Syntax: /item <itemid> <quantity>");
player.yellowMessage("Syntax: !item <itemid> <quantity>");
break;
}
@@ -1109,7 +1109,7 @@ public class Commands {
case "level":
if (sub.length < 2){
player.yellowMessage("Syntax: /level <newlevel>");
player.yellowMessage("Syntax: !level <newlevel>");
break;
}
@@ -1124,7 +1124,7 @@ public class Commands {
case "levelpro":
if (sub.length < 2){
player.yellowMessage("Syntax: /levelpro <newlevel>");
player.yellowMessage("Syntax: !levelpro <newlevel>");
break;
}
@@ -1146,7 +1146,7 @@ public class Commands {
break;
case "maxstat":
final String[] s = {"setall", String.valueOf(Short.MAX_VALUE)};
final String[] s = {"setstat", String.valueOf(Short.MAX_VALUE)};
executeSolaxiaCommandLv2(cserv, srv, c, s);
player.loseExp(player.getExp(), false, false);
player.revertPlayerRates();
@@ -1187,7 +1187,7 @@ public class Commands {
case "search":
if (sub.length < 3){
player.yellowMessage("Syntax: /search <type> <name>");
player.yellowMessage("Syntax: !search <type> <name>");
break;
}
@@ -1205,9 +1205,9 @@ public class Commands {
} else if (sub[1].equalsIgnoreCase("SKILL")) {
data = dataProvider.getData("Skill.img");
} else if (sub[1].equalsIgnoreCase("MAP")) {
sb.append("#bUse the '/m' command to find a map. If it finds a map with the same name, it will warp you to it.");
sb.append("#bUse the '!m' command to find a map. If it finds a map with the same name, it will warp you to it.");
} else {
sb.append("#bInvalid search.\r\nSyntax: '/search [type] [name]', where [type] is NPC, ITEM, MOB, or SKILL.");
sb.append("#bInvalid search.\r\nSyntax: '!search [type] [name]', where [type] is NPC, ITEM, MOB, or SKILL.");
}
if (data != null) {
String name;
@@ -1241,7 +1241,7 @@ public class Commands {
case "jail":
if (sub.length < 2) {
player.yellowMessage("Syntax: /jail <playername> [<minutes>]");
player.yellowMessage("Syntax: !jail <playername> [<minutes>]");
break;
}
@@ -1249,7 +1249,7 @@ public class Commands {
if(sub.length >= 3) {
minutesJailed = Integer.valueOf(sub[2]);
if(minutesJailed <= 0) {
player.yellowMessage("Syntax: /jail <playername> [<minutes>]");
player.yellowMessage("Syntax: !jail <playername> [<minutes>]");
break;
}
}
@@ -1277,7 +1277,7 @@ public class Commands {
case "unjail":
if (sub.length < 2) {
player.yellowMessage("Syntax: /unjail <playername>");
player.yellowMessage("Syntax: !unjail <playername>");
break;
}
@@ -1313,7 +1313,7 @@ public class Commands {
switch(sub[0]) {
case "spawn":
if (sub.length < 2) {
player.yellowMessage("Syntax: /spawn <mobid>");
player.yellowMessage("Syntax: !spawn <mobid>");
break;
}
@@ -1400,7 +1400,7 @@ public class Commands {
} else if(sub.length == 2) {
statUpdate = Integer.valueOf(sub[1]);
} else {
player.yellowMessage("Syntax: /sethpmp [<playername>] <value>");
player.yellowMessage("Syntax: !sethpmp [<playername>] <value>");
}
victim.setHp(statUpdate);
@@ -1411,7 +1411,7 @@ public class Commands {
case "music":
if (sub.length < 2) {
player.yellowMessage("Syntax: /music <song>");
player.yellowMessage("Syntax: !music <song>");
for (String s : songs){
player.yellowMessage(s);
}
@@ -1433,7 +1433,7 @@ public class Commands {
case "monitor":
if (sub.length < 1){
player.yellowMessage("Syntax: /monitor <ign>");
player.yellowMessage("Syntax: !monitor <ign>");
break;
}
victim = c.getWorldServer().getPlayerStorage().getCharacterByName(sub[1]);
@@ -1460,7 +1460,7 @@ public class Commands {
case "ignore":
if (sub.length < 1){
player.yellowMessage("Syntax: /ignore <ign>");
player.yellowMessage("Syntax: !ignore <ign>");
break;
}
victim = c.getWorldServer().getPlayerStorage().getCharacterByName(sub[1]);
@@ -1495,7 +1495,7 @@ public class Commands {
case "togglecoupon":
if (sub.length < 2){
player.yellowMessage("Syntax: /togglecoupon <itemid>");
player.yellowMessage("Syntax: !togglecoupon <itemid>");
break;
}
Server.getInstance().toggleCoupon(Integer.parseInt(sub[1]));
@@ -1508,7 +1508,7 @@ public class Commands {
case "fame":
if (sub.length < 3){
player.yellowMessage("Syntax: /fame <playername> <gainfame>");
player.yellowMessage("Syntax: !fame <playername> <gainfame>");
break;
}
@@ -1519,7 +1519,7 @@ public class Commands {
case "giftnx":
if (sub.length < 3){
player.yellowMessage("Syntax: /giftnx <playername> <gainnx>");
player.yellowMessage("Syntax: !giftnx <playername> <gainnx>");
break;
}
cserv.getPlayerStorage().getCharacterByName(sub[1]).getCashShop().gainCash(1, Integer.parseInt(sub[2]));
@@ -1528,7 +1528,7 @@ public class Commands {
case "vp":
if (sub.length < 2){
player.yellowMessage("Syntax: /vp <gainvotepoint>");
player.yellowMessage("Syntax: !vp <gainvotepoint>");
break;
}
c.addVotePoints(Integer.parseInt(sub[1]));
@@ -1536,7 +1536,7 @@ public class Commands {
case "id":
if (sub.length < 2){
player.yellowMessage("Syntax: /id <id>");
player.yellowMessage("Syntax: !id <id>");
break;
}
try {
@@ -1580,13 +1580,13 @@ public class Commands {
case "kill":
if (sub.length < 2){
player.yellowMessage("Syntax: /kill <playername>");
player.yellowMessage("Syntax: !kill <playername>");
break;
}
victim = cserv.getPlayerStorage().getCharacterByName(sub[1]);
victim.setHpMp(0);
Server.getInstance().broadcastGMMessage(MaplePacketCreator.serverNotice(5, player.getName() + " used /kill on " + victim.getName()));
Server.getInstance().broadcastGMMessage(MaplePacketCreator.serverNotice(5, player.getName() + " used !kill on " + victim.getName()));
break;
case "seed":
@@ -1630,7 +1630,7 @@ public class Commands {
case "openportal":
if (sub.length < 2){
player.yellowMessage("Syntax: /openportal <portalid>");
player.yellowMessage("Syntax: !openportal <portalid>");
break;
}
player.getMap().getPortal(sub[1]).setPortalState(true);
@@ -1638,7 +1638,7 @@ public class Commands {
case "closeportals":
if (sub.length < 2){
player.yellowMessage("Syntax: /closeportal <portalid>");
player.yellowMessage("Syntax: !closeportal <portalid>");
break;
}
player.getMap().getPortal(sub[1]).setPortalState(false);
@@ -1712,7 +1712,7 @@ public class Commands {
case "ban":
if (sub.length < 3) {
player.yellowMessage("Syntax: /ban <IGN> <Reason> (Please be descriptive)");
player.yellowMessage("Syntax: !ban <IGN> <Reason> (Please be descriptive)");
break;
}
String ign = sub[1];
@@ -1762,7 +1762,7 @@ public class Commands {
case "unban":
if (sub.length < 2){
player.yellowMessage("Syntax: /unban <playername>");
player.yellowMessage("Syntax: !unban <playername>");
break;
}
@@ -1842,7 +1842,7 @@ public class Commands {
case "proitem":
if (sub.length < 3) {
player.yellowMessage("Syntax: /proitem <itemid> <statvalue>");
player.yellowMessage("Syntax: !proitem <itemid> <statvalue>");
break;
}
@@ -1866,7 +1866,7 @@ public class Commands {
case "seteqstat":
if (sub.length < 2) {
player.yellowMessage("Syntax: /seteqstat <statvalue>");
player.yellowMessage("Syntax: !seteqstat <statvalue>");
break;
}
@@ -1907,14 +1907,14 @@ public class Commands {
case "exprate":
if (sub.length < 2){
player.yellowMessage("Syntax: /exprate <newrate>");
player.yellowMessage("Syntax: !exprate <newrate>");
break;
}
c.getWorldServer().setExpRate(Integer.parseInt(sub[1]));
break;
case "mesorate":
if (sub.length < 2){
player.yellowMessage("Syntax: /mesorate <newrate>");
player.yellowMessage("Syntax: !mesorate <newrate>");
break;
}
c.getWorldServer().setMesoRate(Integer.parseInt(sub[1]));
@@ -1922,7 +1922,7 @@ public class Commands {
case "droprate":
if (sub.length < 2){
player.yellowMessage("Syntax: /droprate <newrate>");
player.yellowMessage("Syntax: !droprate <newrate>");
break;
}
c.getWorldServer().setDropRate(Integer.parseInt(sub[1]));
@@ -1930,7 +1930,7 @@ public class Commands {
case "bossdroprate":
if (sub.length < 2){
player.yellowMessage("Syntax: /bossdroprate <newrate>");
player.yellowMessage("Syntax: !bossdroprate <newrate>");
break;
}
c.getWorldServer().setBossDropRate(Integer.parseInt(sub[1]));
@@ -1994,7 +1994,7 @@ public class Commands {
case "playernpc":
if (sub.length < 3){
player.yellowMessage("Syntax: /playernpc <playername> <npcid>");
player.yellowMessage("Syntax: !playernpc <playername> <npcid>");
break;
}
player.playerNPC(c.getChannelServer().getPlayerStorage().getCharacterByName(sub[1]), Integer.parseInt(sub[2]));
@@ -2002,7 +2002,7 @@ public class Commands {
case "face":
if (sub.length < 2){
player.yellowMessage("Syntax: /face [<playername>] <faceid>");
player.yellowMessage("Syntax: !face [<playername>] <faceid>");
break;
}
@@ -2022,7 +2022,7 @@ public class Commands {
case "hair":
if (sub.length < 2){
player.yellowMessage("Syntax: /hair [<playername>] <hairid>");
player.yellowMessage("Syntax: !hair [<playername>] <hairid>");
break;
}
@@ -2159,7 +2159,7 @@ public class Commands {
switch(sub[0]) {
case "warpworld":
if (sub.length < 2){
player.yellowMessage("Syntax: /warpworld <worldid>");
player.yellowMessage("Syntax: !warpworld <worldid>");
break;
}
@@ -2190,7 +2190,7 @@ public class Commands {
chr.saveToDB();
}
}
String message = player.getName() + " used /saveall.";
String message = player.getName() + " used !saveall.";
Server.getInstance().broadcastGMMessage(MaplePacketCreator.serverNotice(5, message));
player.message("All players saved successfully.");
break;
@@ -2225,7 +2225,7 @@ public class Commands {
case "getacc":
if (sub.length < 2){
player.yellowMessage("Syntax: /getacc <playername>");
player.yellowMessage("Syntax: !getacc <playername>");
break;
}
victim = c.getChannelServer().getPlayerStorage().getCharacterByName(sub[1]);
@@ -2234,7 +2234,7 @@ public class Commands {
case "npc":
if (sub.length < 2){
player.yellowMessage("Syntax: /npc <npcid>");
player.yellowMessage("Syntax: !npc <npcid>");
break;
}
MapleNPC npc = MapleLifeFactory.getNPC(Integer.parseInt(sub[1]));
@@ -2258,7 +2258,7 @@ public class Commands {
victim.changeJob(MapleJob.getById(Integer.parseInt(sub[2])));
player.equipChanged();
} else {
player.message("Syntax: /job <job id> <opt: IGN of another person>");
player.message("Syntax: !job <job id> <opt: IGN of another person>");
}
break;
@@ -2317,10 +2317,10 @@ public class Commands {
public static boolean executeSolaxiaCommand(Channel cserv, Server srv, MapleClient c, String[] sub, int gmLevel) {
if(gmLevel == -1) {
c.getPlayer().yellowMessage("Command '" + sub[0] + "' is not available. See /commands for a list of available commands.");
c.getPlayer().yellowMessage("Command '" + sub[0] + "' is not available. See @commands for a list of available commands.");
return false;
}
boolean executedCommand;
switch(gmLevel) {
case 0: //Player
+1 -1
View File
@@ -34,7 +34,7 @@ public class ServerConstants {
public static final boolean USE_CUSTOM_KEYSET = true; //Enables auto-setup of the MapleSolaxiaV2's custom keybindings when creating characters.
public static final boolean USE_MAXRANGE_ECHO_OF_HERO = true;
public static final boolean USE_MAXRANGE = true; //Will send and receive packets from all events of a map, rather than those of only view range.
public static final boolean USE_DEBUG = false; //Will enable some text prints on the client, oriented for debugging purposes.
public static final boolean USE_DEBUG = true; //Will enable some text prints on the client, oriented for debugging purposes.
public static final boolean USE_DEBUG_SHOW_RCVD_PACKET = false; //Prints on the cmd all received packet ids.
public static final boolean USE_DEBUG_SHOW_INFO_EQPEXP = false; //Prints on the cmd all equip exp gain info.
public static final boolean USE_MTS = false;
+12 -1
View File
@@ -30,6 +30,7 @@ import java.util.List;
import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
@@ -374,6 +375,16 @@ public final class Channel {
usedDojo &= mask;
if(party != null) dojoParty.remove(party.hashCode());
else if(dojoParty.containsValue(slot)) { // they left the dojo before completing it, no party there!
Set<Entry<Integer, Integer>> es = Collections.unmodifiableSet(dojoParty.entrySet());
for(Entry<Integer, Integer> e: es) {
if(e.getValue() == slot) {
dojoParty.remove(e.getKey());
break;
}
}
}
}
private int getDojoSlot(int dojoMapId) {
@@ -405,7 +416,7 @@ public final class Channel {
final int stage = (dojoMapId / 100) % 100;
if(stage <= dojoStage[slot]) return;
long clockTime = (stage > 36 ? 15 : stage / 6 + 5) * 60000;
long clockTime = (stage > 36 ? 15 : (stage / 6) + 5) * 60000;
this.dojoTask[slot] = TimerManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
@@ -787,14 +787,14 @@ public abstract class AbstractDealDamageHandler extends AbstractMaplePacketHandl
hitDmgMax = 200000;
}
int maxWithCrit = hitDmgMax;
int maxWithCrit = hitDmgMax;
if(canCrit) // They can crit, so up the max.
maxWithCrit *= 2;
// Warn if the damage is over 1.5x what we calculated above.
if(damage > maxWithCrit * 1.5) {
AutobanFactory.DAMAGE_HACK.alert(chr, "DMG: " + damage + " MaxDMG: " + maxWithCrit + " SID: " + ret.skill + " MobID: " + (monster != null ? monster.getId() : "null") + " Map: " + chr.getMap().getMapName() + " (" + chr.getMapId() + ")");
}
if(damage > maxWithCrit * 1.5) {
AutobanFactory.DAMAGE_HACK.alert(chr, "DMG: " + damage + " MaxDMG: " + maxWithCrit + " SID: " + ret.skill + " MobID: " + (monster != null ? monster.getId() : "null") + " Map: " + chr.getMap().getMapName() + " (" + chr.getMapId() + ")");
}
// Add a ab point if its over 5x what we calculated.
if(damage > maxWithCrit * 5) {
@@ -47,7 +47,7 @@ public final class GeneralChatHandler extends net.AbstractMaplePacketHandler {
return;
}
char heading = s.charAt(0);
if (heading == '/') {
if (heading == '!' || heading == '@') { // client seems to not send command with '/' heading to the server, if not a GM account
String[] sp = s.split(" ");
sp[0] = sp[0].toLowerCase().substring(1);
@@ -58,6 +58,12 @@ public final class MobDamageMobFriendlyHandler extends AbstractMaplePacketHandle
else if(monster.getId() == 9300093) { //tylus
monster.getMap().broadcastMessage(MaplePacketCreator.serverNotice(6, "Tylus has fallen by the overwhelming forces of this ambush."));
}
else if(monster.getId() == 9300137) { //juliet
monster.getMap().broadcastMessage(MaplePacketCreator.serverNotice(6, "Juliet has fainted on the middle of the combat."));
}
else if(monster.getId() == 9300138) { //romeo
monster.getMap().broadcastMessage(MaplePacketCreator.serverNotice(6, "Romeo has fainted on the middle of the combat."));
}
c.getPlayer().getMap().killFriendlies(monster);
}
@@ -62,7 +62,7 @@ public final class NPCTalkHandler extends AbstractMaplePacketHandler {
// Custom handling for gachapon scripts to reduce the amount of scripts needed.
NPCScriptManager.getInstance().start(c, npc.getId(), "gachapon", null);
} else {
boolean hasNpcScript = NPCScriptManager.getInstance().start(c, npc.getId(), null);
boolean hasNpcScript = NPCScriptManager.getInstance().start(c, npc.getId(), oid, null);
if (!hasNpcScript) {
if (!npc.hasShop()) {
FilePrinter.printError(FilePrinter.NPC_UNCODED, "NPC " + npc.getName() + "(" + npc.getId() + ") is not coded.\r\n");
@@ -447,6 +447,14 @@ public class EventInstanceManager {
}
}
}
public void friendlyKilled(MapleMonster mob) {
try {
em.getIv().invokeFunction("friendlyKilled", mob, this);
} catch (ScriptException | NoSuchMethodException ex) {
//optional
}
}
public void playerKilled(MapleCharacter chr) {
try {
+12 -8
View File
@@ -44,7 +44,6 @@ import server.partyquest.Pyramid;
import server.partyquest.Pyramid.PyramidMode;
import server.quest.MapleQuest;
import tools.LogHelper;
import tools.FilePrinter;
import tools.MaplePacketCreator;
import client.MapleCharacter;
import client.MapleClient;
@@ -56,27 +55,35 @@ import client.SkillFactory;
import client.inventory.Item;
import client.inventory.ItemFactory;
import client.inventory.MaplePet;
import constants.ServerConstants;
/**
*
* @author Matze
*/
public class NPCConversationManager extends AbstractPlayerInteraction {
private int npc;
private int npcOid;
private String scriptName;
private String getText;
public NPCConversationManager(MapleClient c, int npc, String scriptName) {
public NPCConversationManager(MapleClient c, int npc, String scriptName) {
this(c, npc, -1, scriptName);
}
public NPCConversationManager(MapleClient c, int npc, int oid, String scriptName) {
super(c);
this.npc = npc;
this.npcOid = oid;
this.scriptName = scriptName;
}
public int getNpc() {
return npc;
}
public int getNpcObjectId() {
return npcOid;
}
public String getScriptName() {
return scriptName;
@@ -220,9 +227,6 @@ public class NPCConversationManager extends AbstractPlayerInteraction {
}
public void gainMeso(int gain) {
if (gain > 0 && ServerConstants.USE_AUTOBAN == true) {
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " gained " + gain + " mesos from NPC " + npc + "\r\n");
}
getPlayer().gainMeso(gain);
}
+10 -3
View File
@@ -32,7 +32,6 @@ import javax.script.Invocable;
import javax.script.ScriptException;
import scripting.AbstractScriptManager;
import server.life.MapleLifeFactory;
import tools.FilePrinter;
import tools.MaplePacketCreator;
@@ -53,10 +52,18 @@ public class NPCScriptManager extends AbstractScriptManager {
public boolean start(MapleClient c, int npc, MapleCharacter chr) {
return start(c, npc, null, chr);
}
public boolean start(MapleClient c, int npc, int oid, MapleCharacter chr) {
return start(c, npc, oid, null, chr);
}
public boolean start(MapleClient c, int npc, String fileName, MapleCharacter chr) {
return start(c, npc, -1, fileName, chr);
}
public boolean start(MapleClient c, int npc, int oid, String fileName, MapleCharacter chr) {
try {
NPCConversationManager cm = new NPCConversationManager(c, npc, fileName);
NPCConversationManager cm = new NPCConversationManager(c, npc, oid, fileName);
if (cms.containsKey(c)) {
dispose(c);
}
+2
View File
@@ -445,6 +445,8 @@ public class MapleMonster extends AbstractLoadedMapleLife {
if (getMap().getEventInstance() != null) {
if (!this.getStats().isFriendly()) {
getMap().getEventInstance().monsterKilled(this);
} else {
getMap().getEventInstance().friendlyKilled(this);
}
}
+17 -15
View File
@@ -246,12 +246,12 @@ public class MapleMap {
mr.lockReactor();
try {
mr.setState((byte) 1);
mr.setShouldCollect(true);
mr.resetReactorActions();
broadcastMessage(MaplePacketCreator.triggerReactor((MapleReactor) o, 1));
} finally {
mr.unlockReactor();
}
broadcastMessage(MaplePacketCreator.triggerReactor((MapleReactor) o, 1));
}
}
}
@@ -1076,6 +1076,7 @@ public class MapleMap {
final MapleReactor reactor = getReactorByOid(oid);
TimerManager tMan = TimerManager.getInstance();
broadcastMessage(MaplePacketCreator.destroyReactor(reactor));
reactor.cancelReactorTimeout();
reactor.setAlive(false);
removeMapObject(reactor);
@@ -1099,12 +1100,12 @@ public class MapleMap {
r.lockReactor();
try {
r.setState((byte) 0);
r.setShouldCollect(true);
r.resetReactorActions();
broadcastMessage(MaplePacketCreator.triggerReactor(r, 0));
} finally {
r.unlockReactor();
}
broadcastMessage(MaplePacketCreator.triggerReactor(r, 0));
}
}
} finally {
@@ -1547,8 +1548,8 @@ public class MapleMap {
private void respawnReactor(final MapleReactor reactor) {
reactor.lockReactor();
try {
reactor.setShouldCollect(true);
reactor.setState((byte) 0);
reactor.resetReactorActions();
reactor.setAlive(true);
} finally {
reactor.unlockReactor();
@@ -1979,7 +1980,7 @@ public class MapleMap {
public MaplePortal getRandomPlayerSpawnpoint() {
List<MaplePortal> spawnPoints = new ArrayList<>();
for (MaplePortal portal : portals.values()) {
if (portal.getType() >= 0 && portal.getType() <= 1) {
if (portal.getType() >= 0 && portal.getType() <= 1 && portal.getTargetMapId() == 999999999) {
spawnPoints.add(portal);
}
}
@@ -2608,13 +2609,14 @@ public class MapleMap {
@Override
public void run() {
reactor.lockReactor();
try {
reactor.setState((byte) 0);
reactor.setShouldCollect(true);
} finally {
reactor.unlockReactor();
}
broadcastMessage(MaplePacketCreator.triggerReactor(reactor, 0));
try {
reactor.setState((byte) 0);
reactor.resetReactorActions();
broadcastMessage(MaplePacketCreator.triggerReactor(reactor, 0));
} finally {
reactor.unlockReactor();
}
}
}, reactor.getDelay());
}
+3 -2
View File
@@ -293,11 +293,12 @@ public class MapleMapFactory {
MapleReactor myReactor = new MapleReactor(MapleReactorFactory.getReactor(Integer.parseInt(id)), Integer.parseInt(id));
int x = MapleDataTool.getInt(reactor.getChildByPath("x"));
int y = MapleDataTool.getInt(reactor.getChildByPath("y"));
myReactor.setName(MapleDataTool.getString(reactor.getChildByPath("name"), ""));
myReactor.setPosition(new Point(x, y));
myReactor.setDelay(MapleDataTool.getInt(reactor.getChildByPath("reactorTime")) * 1000);
myReactor.setState((byte) 0);
myReactor.setShouldCollect(true);
myReactor.setName(MapleDataTool.getString(reactor.getChildByPath("name"), ""));
myReactor.resetReactorActions();
return myReactor;
}
+90 -37
View File
@@ -27,6 +27,7 @@ import constants.ServerConstants;
import java.awt.Rectangle;
import java.util.List;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@@ -38,6 +39,7 @@ import tools.Pair;
/**
*
* @author Lerk
* @author Ronan
*/
public class MapleReactor extends AbstractMapleMapObject {
private int rid;
@@ -50,6 +52,7 @@ public class MapleReactor extends AbstractMapleMapObject {
private boolean alive;
private boolean shouldCollect;
private boolean attackHit;
private ScheduledFuture<?> timeoutTask = null;
private Lock reactorLock = new ReentrantLock(true);
public MapleReactor(MapleReactorStats stats, int rid) {
@@ -158,16 +161,57 @@ public class MapleReactor extends AbstractMapleMapObject {
return MaplePacketCreator.spawnReactor(this);
}
public void resetReactorActions() {
cancelReactorTimeout();
setShouldCollect(true);
refreshReactorTimeout();
}
public void forceHitReactor(final byte newState) {
this.lockReactor();
try {
setState((byte) newState);
this.setShouldCollect(true);
this.resetReactorActions();
map.broadcastMessage(MaplePacketCreator.triggerReactor(this, (short) 0));
} finally {
this.unlockReactor();
}
}
private void tryForceHitReactor(final byte newState) { // weak hit state signal, if already changed reactor state before timeout then drop this
if(!this.reactorLock.tryLock()) return;
map.broadcastMessage(MaplePacketCreator.triggerReactor(this, (short) 0));
try {
setState((byte) newState);
this.resetReactorActions();
map.broadcastMessage(MaplePacketCreator.triggerReactor(this, (short) 0));
} finally {
this.unlockReactor();
}
}
public void cancelReactorTimeout() {
if (timeoutTask != null) {
timeoutTask.cancel(false);
timeoutTask = null;
}
}
private void refreshReactorTimeout() {
int timeOut = stats.getTimeout(state);
if(timeOut > -1) {
final byte nextState = stats.getTimeoutState(state);
timeoutTask = TimerManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
timeoutTask = null;
tryForceHitReactor(nextState);
}
}, timeOut);
}
}
public void delayedHitReactor(final MapleClient c, long delay) {
@@ -189,48 +233,57 @@ public class MapleReactor extends AbstractMapleMapObject {
return;
}
attackHit = wHit;
if(ServerConstants.USE_DEBUG == true) c.getPlayer().dropMessage(5, "Hitted REACTOR " + this.getId() + " with POS " + charPos + " , STANCE " + stance + " , SkillID " + skillid + " , STATE " + stats.getType(state) + " STATESIZE " + stats.getStateSize(state));
ReactorScriptManager.getInstance().onHit(c, this);
int reactorType = stats.getType(state);
if (reactorType < 999 && reactorType != -1) {//type 2 = only hit from right (kerning swamp plants), 00 is air left 02 is ground left
if (!(reactorType == 2 && (stance == 0 || stance == 2))) { //get next state
for (byte b = 0; b < stats.getStateSize(state); b++) {//YAY?
List<Integer> activeSkills = stats.getActiveSkills(state, b);
if (activeSkills != null) {
if (!activeSkills.contains(skillid)) continue;
}
state = stats.getNextState(state, b);
if (stats.getNextState(state, b) == -1) {//end of reactor
if (reactorType < 100) {//reactor broken
if (delay > 0) {
map.destroyReactor(getObjectId());
} else {//trigger as normal
this.lockReactor();
try {
cancelReactorTimeout();
attackHit = wHit;
if(ServerConstants.USE_DEBUG == true) c.getPlayer().dropMessage(5, "Hitted REACTOR " + this.getId() + " with POS " + charPos + " , STANCE " + stance + " , SkillID " + skillid + " , STATE " + stats.getType(state) + " STATESIZE " + stats.getStateSize(state));
ReactorScriptManager.getInstance().onHit(c, this);
int reactorType = stats.getType(state);
if (reactorType < 999 && reactorType != -1) {//type 2 = only hit from right (kerning swamp plants), 00 is air left 02 is ground left
if (!(reactorType == 2 && (stance == 0 || stance == 2))) { //get next state
for (byte b = 0; b < stats.getStateSize(state); b++) {//YAY?
List<Integer> activeSkills = stats.getActiveSkills(state, b);
if (activeSkills != null) {
if (!activeSkills.contains(skillid)) continue;
}
state = stats.getNextState(state, b);
if (stats.getNextState(state, b) == -1) {//end of reactor
if (reactorType < 100) {//reactor broken
if (delay > 0) {
map.destroyReactor(getObjectId());
} else {//trigger as normal
map.broadcastMessage(MaplePacketCreator.triggerReactor(this, stance));
}
} else {//item-triggered on final step
map.broadcastMessage(MaplePacketCreator.triggerReactor(this, stance));
}
} else {//item-triggered on final step
map.broadcastMessage(MaplePacketCreator.triggerReactor(this, stance));
}
ReactorScriptManager.getInstance().act(c, this);
} else { //reactor not broken yet
map.broadcastMessage(MaplePacketCreator.triggerReactor(this, stance));
if (state == stats.getNextState(state, b)) {//current state = next state, looping reactor
ReactorScriptManager.getInstance().act(c, this);
} else { //reactor not broken yet
map.broadcastMessage(MaplePacketCreator.triggerReactor(this, stance));
if (state == stats.getNextState(state, b)) {//current state = next state, looping reactor
ReactorScriptManager.getInstance().act(c, this);
}
setShouldCollect(true); // refresh collectability on item drop-based reactors
refreshReactorTimeout();
}
setShouldCollect(true); // refresh collectability on item drop-based reactors
break;
}
break;
}
} else {
state++;
map.broadcastMessage(MaplePacketCreator.triggerReactor(this, stance));
ReactorScriptManager.getInstance().act(c, this);
setShouldCollect(true);
refreshReactorTimeout();
}
} else {
state++;
map.broadcastMessage(MaplePacketCreator.triggerReactor(this, stance));
ReactorScriptManager.getInstance().act(c, this);
setShouldCollect(true);
} finally {
this.unlockReactor();
}
} catch(Exception e) {
e.printStackTrace();
+27 -22
View File
@@ -57,46 +57,51 @@ public class MapleReactorFactory {
reactorData = data.getData(StringUtil.getLeftPaddedStr(Integer.toString(infoId) + ".img", '0', 11));
MapleData reactorInfoData = reactorData.getChildByPath("0");
stats = new MapleReactorStats();
List<StateData> statedatas = new ArrayList<StateData>();
List<StateData> statedatas = new ArrayList<>();
if (reactorInfoData != null) {
boolean areaSet = false;
byte i = 0;
while (reactorInfoData != null) {
MapleData eventData = reactorInfoData.getChildByPath("event");
if (eventData != null) {
int timeOut = -1;
for (MapleData fknexon : eventData.getChildren()) {
if (fknexon.getName().equals("timeOut")) continue;
Pair<Integer, Integer> reactItem = null;
int type = MapleDataTool.getIntConvert("type", fknexon);
if (type == 100) { //reactor waits for item
reactItem = new Pair<Integer, Integer>(MapleDataTool.getIntConvert("0", fknexon), MapleDataTool.getIntConvert("1", fknexon));
if (!areaSet || loadArea) { //only set area of effect for item-triggered reactors once
stats.setTL(MapleDataTool.getPoint("lt", fknexon));
stats.setBR(MapleDataTool.getPoint("rb", fknexon));
areaSet = true;
if (fknexon.getName().equals("timeOut")) {
timeOut = MapleDataTool.getInt(fknexon);
} else {
Pair<Integer, Integer> reactItem = null;
int type = MapleDataTool.getIntConvert("type", fknexon);
if (type == 100) { //reactor waits for item
reactItem = new Pair<Integer, Integer>(MapleDataTool.getIntConvert("0", fknexon), MapleDataTool.getIntConvert("1", fknexon));
if (!areaSet || loadArea) { //only set area of effect for item-triggered reactors once
stats.setTL(MapleDataTool.getPoint("lt", fknexon));
stats.setBR(MapleDataTool.getPoint("rb", fknexon));
areaSet = true;
}
}
}
MapleData activeSkillID = fknexon.getChildByPath("activeSkillID");
List<Integer> skillids = null;
if (activeSkillID != null) {
skillids = new ArrayList<Integer>();
for (MapleData skill : activeSkillID.getChildren()) {
skillids.add(MapleDataTool.getInt(skill));
MapleData activeSkillID = fknexon.getChildByPath("activeSkillID");
List<Integer> skillids = null;
if (activeSkillID != null) {
skillids = new ArrayList<Integer>();
for (MapleData skill : activeSkillID.getChildren()) {
skillids.add(MapleDataTool.getInt(skill));
}
}
byte nextState = (byte) MapleDataTool.getIntConvert("state", fknexon);
statedatas.add(new StateData(type, reactItem, skillids, nextState));
}
byte nextState = (byte) MapleDataTool.getIntConvert("state", fknexon);
statedatas.add(new StateData(type, reactItem, skillids, nextState));
}
stats.addState(i, statedatas);
stats.addState(i, statedatas, timeOut);
}
i++;
reactorInfoData = reactorData.getChildByPath(Byte.toString(i));
statedatas = new ArrayList<StateData>();
statedatas = new ArrayList<>();
}
} else //sit there and look pretty; likely a reactor such as Zakum/Papulatus doors that shows if player can enter
{
statedatas.add(new StateData(999, null, null, (byte) 0));
stats.addState((byte) 0, statedatas);
stats.addState((byte) 0, statedatas, -1);
}
reactorStats.put(Integer.valueOf(infoId), stats);
if (rid != infoId) {
+14 -2
View File
@@ -29,11 +29,13 @@ import tools.Pair;
/**
* @author Lerk
* @author Ronan
*/
public class MapleReactorStats {
private Point tl;
private Point br;
private Map<Byte, List<StateData>> stateInfo = new HashMap<Byte, List<StateData>>();
private Map<Byte, List<StateData>> stateInfo = new HashMap<>();
private Map<Byte, Integer> timeoutInfo = new HashMap<>();
public void setTL(Point tl) {
this.tl = tl;
@@ -51,8 +53,18 @@ public class MapleReactorStats {
return br;
}
public void addState(byte state, List<StateData> data) {
public void addState(byte state, List<StateData> data, int timeOut) {
stateInfo.put(state, data);
if(timeOut > -1) timeoutInfo.put(state, timeOut);
}
public int getTimeout(byte state) {
Integer i = timeoutInfo.get(state);
return (i == null) ? -1 : i;
}
public byte getTimeoutState(byte state) {
return stateInfo.get(state).get(stateInfo.get(state).size() - 1).getNextState();
}
public byte getStateSize(byte state) {
+1
View File
@@ -3701,6 +3701,7 @@ public class MaplePacketCreator {
return mplew.getPacket();
}
// is there a way to trigger reactors without performing the hit animation?
public static byte[] triggerReactor(MapleReactor reactor, int stance) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
Point pos = reactor.getPosition();