Missing Pirate questlines + Find & MoveLife update + Party-Map patch

Implemented missing scripts for Aerial Strike, Hypnotize and Time Leap skill questlines.
Fixed an deadlock issue within player's inventory and status.
Fixed skill spam detection disconnecting players when legitimatelly spamming Flash Jump or Heal.
Fixed party members map location not being properly updated after changing maps.
Rehauled MoveLife handler. Improved packet read of attack and skill elements, properly reflecting incoming actions to other player on the map.
Reviewed an issue with equipments MaxHP/MaxMP getting unsynced with player's MaxHP/MaxMP, resulting in differences within server-client view of a player's pool.
Fixed mobs not being spawned by dojo bosses after enough spawn actions were instanced.
Implemented proper Mob.wz linked mob data support.
Fixed /find not identifying a player's channel properly.
Fixed Echo of Hero not affecting other player in the map.
Fixed commands warp and goto not taking player off events/expeditions properly.
Fixed storage expansion not being registered on DB when buying the cash item.
Fixed party leadership being reassigned after changing channels.
Implemented suggested level range limit between party members on the EXP share system. Players whose level range from the attacker exceeds the estipulated threshold will not receive any EXP from the action.

Happy Thanksgiving Day everyone!!!
This commit is contained in:
ronancpl
2018-11-22 16:16:21 -02:00
parent 5ee0cd1c98
commit 0910dc2428
163 changed files with 4618 additions and 3186 deletions

View File

@@ -27,6 +27,7 @@ package net.server.audit.locks;
public enum MonitoredLockType {
UNDEFINED,
CHARACTER_CHR,
CHARACTER_CPN,
CHARACTER_EFF,
CHARACTER_PET,
CHARACTER_PRT,

View File

@@ -32,8 +32,7 @@ public final class AutoAggroHandler extends AbstractMaplePacketHandler {
@Override
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
if(c.getPlayer().isHidden())
return; // Don't auto aggro GM's in hide...
if (c.getPlayer().isHidden()) return; // Don't auto aggro GM's in hide...
MapleMap map = c.getPlayer().getMap();
int oid = slea.readInt();

View File

@@ -63,7 +63,7 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
final int snCS = slea.readInt();
CashItem cItem = CashItemFactory.getItem(snCS);
if (!canBuy(cItem, cs.getCash(useNX))) {
FilePrinter.printError(FilePrinter.ITEM, "Denied to sell cash item with SN " + cItem.getSN());
FilePrinter.printError(FilePrinter.ITEM, "Denied to sell cash item with SN " + snCS); // preventing NPE here thanks to MedicOP
c.enableCSActions();
return;
}
@@ -185,7 +185,10 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
c.enableCSActions();
return;
}
if (chr.getStorage().gainSlots(8)) {
if (chr.getStorage().gainSlots(8)) { // thanks ABaldParrot & Thora for detecting storage issues here
FilePrinter.print(FilePrinter.STORAGE + c.getAccountName() + ".txt", c.getPlayer().getName() + " bought 8 slots to their account storage.\r\n");
chr.setUsedStorage();
c.announce(MaplePacketCreator.showBoughtStorageSlots(chr.getStorage().getSlots()));
cs.gainCash(cash, cItem, chr.getWorld());
c.announce(MaplePacketCreator.showCash(chr));

View File

@@ -194,14 +194,15 @@ public final class GuildOperationHandler extends AbstractMaplePacketHandler {
restancePlayer(mc);
break;
case 0x07:
allianceId = mc.getGuild().getAllianceId();
cid = slea.readInt();
name = slea.readMapleAsciiString();
if (cid != mc.getId() || !name.equals(mc.getName()) || mc.getGuildId() <= 0) {
System.out.println("[hax] " + mc.getName() + " tried to quit guild under the name \"" + name + "\" and current guild id of " + mc.getGuildId() + ".");
return;
}
allianceId = mc.getGuild().getAllianceId();
c.announce(MaplePacketCreator.updateGP(mc.getGuildId(), 0));
Server.getInstance().leaveGuild(mc.getMGC());
@@ -209,6 +210,7 @@ public final class GuildOperationHandler extends AbstractMaplePacketHandler {
if(allianceId > 0) Server.getInstance().getAlliance(allianceId).updateAlliancePackets(mc);
mc.getMGC().setGuildId(0);
mc.getMGC().setGuildRank(5);
mc.saveGuildStatus();
restancePlayer(mc);
break;

View File

@@ -216,8 +216,8 @@ public final class InventorySortHandler extends AbstractMaplePacketHandler {
}
for (Item item : itemarray) {
inventory.removeSlot(item.getPosition());
mods.add(new ModifyInventory(3, item));
inventory.removeSlot(item.getPosition());
mods.add(new ModifyInventory(3, item));
}
int invTypeCriteria = (MapleInventoryType.getByType(invType) == MapleInventoryType.EQUIP) ? 3 : 1;

View File

@@ -37,7 +37,8 @@ import tools.Randomizer;
import tools.data.input.SeekableLittleEndianAccessor;
/**
* @author Jay Estrella/ Modified by kevintjuh93
* @author Jay Estrella
* @author kevintjuh93
*/
public final class ItemRewardHandler extends AbstractMaplePacketHandler {
@Override

View File

@@ -47,8 +47,7 @@ public final class MobDamageMobFriendlyHandler extends AbstractMaplePacketHandle
}
int damage = Randomizer.nextInt(((monster.getMaxHp() / 13 + monster.getPADamage() * 10)) * 2 + 500) / 10; //Beng's formula.
// int damage = monster.getStats().getPADamage() + monster.getStats().getPDDamage() - 1;
if (monster.getHp() - damage < 1) { // friendly dies
if(monster.getId() == 9300102) {
monster.getMap().broadcastMessage(MaplePacketCreator.serverNotice(6, "The Watch Hog has been injured by the aliens. Better luck next time..."));
@@ -60,8 +59,10 @@ public final class MobDamageMobFriendlyHandler extends AbstractMaplePacketHandle
monster.getMap().broadcastMessage(MaplePacketCreator.serverNotice(6, "Juliet has fainted in the middle of the combat."));
} else if(monster.getId() == 9300138) { //romeo
monster.getMap().broadcastMessage(MaplePacketCreator.serverNotice(6, "Romeo has fainted in the middle of the combat."));
} else if(monster.getId() == 9400322 || monster.getId() == 9400327 || monster.getId() == 9400332) {
} else if(monster.getId() == 9400322 || monster.getId() == 9400327 || monster.getId() == 9400332) { //snowman
monster.getMap().broadcastMessage(MaplePacketCreator.serverNotice(6, "The Snowman has melted on the heat of the battle."));
} else if(monster.getId() == 9300162) { //delli
monster.getMap().broadcastMessage(MaplePacketCreator.serverNotice(6, "Delli vanished after the ambush, sheets still laying on the ground..."));
}
c.getPlayer().getMap().killFriendlies(monster);

View File

@@ -26,6 +26,7 @@ import client.MapleClient;
import java.awt.Point;
import java.util.LinkedList;
import java.util.List;
import constants.ServerConstants;
import server.life.MapleMonster;
import server.life.MapleMonsterInformationProvider;
//import server.life.MobAttackInfo;
@@ -63,10 +64,10 @@ public final class MoveLifeHandler extends AbstractMovementPacketHandler {
MapleMonster monster = (MapleMonster) mmo;
List<MapleCharacter> banishPlayers = null;
byte pNibbles = slea.readByte();
byte pNibbles = slea.readByte();
byte rawActivity = slea.readByte();
slea.readByte();
slea.readByte();
int skillId = slea.readByte() & 0xff;
int skillLv = slea.readByte() & 0xff;
short pOption = slea.readShort();
slea.skip(8);
@@ -74,65 +75,69 @@ public final class MoveLifeHandler extends AbstractMovementPacketHandler {
rawActivity = (byte) (rawActivity & 0xFF >> 1);
}
boolean isAttack = inRangeInclusive(rawActivity, 12, 20);
boolean isSkill = inRangeInclusive(rawActivity, 21, 25);
byte attackId = (byte) (isAttack ? rawActivity - 12 : -1);
isSkill |= (pNibbles != 0);
boolean nextMovementCouldBeSkill = true;
boolean pUnk = (pNibbles & 0xF0) != 0;
boolean isAttack = inRangeInclusive(rawActivity, 24, 41);
boolean isSkill = inRangeInclusive(rawActivity, 42, 59);
boolean currentController = (monster.getController() == player);
MobSkill toUse = null;
int useSkillId = 0, useSkillLevel = 0;
int rnd = 0;
MobSkill nextUse = null;
int nextSkillId = 0, nextSkillLevel = 0;
boolean nextMovementCouldBeSkill = !(isSkill || (pNibbles != 0));
int castPos;
if (isSkill) {
int noSkills = monster.getNoSkills();
if (noSkills > 0) {
int rndSkill = Randomizer.nextInt(noSkills);
Pair<Integer, Integer> skillToUse = monster.getSkills().get(rndSkill);
useSkillId = skillToUse.getLeft();
useSkillLevel = skillToUse.getRight();
useSkillId = skillId;
useSkillLevel = skillLv;
castPos = monster.getSkillPos(useSkillId, useSkillLevel);
if (castPos != -1) {
toUse = MobSkillFactory.getMobSkill(useSkillId, useSkillLevel);
rnd = rndSkill;
nextMovementCouldBeSkill = false;
}
}
int mobMp;
if (toUse != null && toUse.getHP() >= (int) (((float) monster.getHp() / monster.getMaxHp()) * 100) && monster.canUseSkill(toUse)) {
mobMp = monster.getMp();
int animationTime = MapleMonsterInformationProvider.getInstance().getMobSkillAnimationTime(toUse);
if(animationTime > 0 && toUse.getSkillId() != 129) {
toUse.applyDelayedEffect(player, monster, true, animationTime);
} else {
banishPlayers = new LinkedList<>();
toUse.applyEffect(player, monster, true, banishPlayers);
if (monster.canUseSkill(toUse)) {
int animationTime = MapleMonsterInformationProvider.getInstance().getMobSkillAnimationTime(toUse);
if(animationTime > 0 && toUse.getSkillId() != 129) {
toUse.applyDelayedEffect(player, monster, true, animationTime);
} else {
banishPlayers = new LinkedList<>();
toUse.applyEffect(player, monster, true, banishPlayers);
}
}
}
} else {
int atkStatus = monster.canUseAttack((attackId - 13) / 2);
castPos = (rawActivity - 24) / 2;
int atkStatus = monster.canUseAttack(castPos, isSkill);
if (atkStatus < 1) {
if (!currentController) {
return;
}
mobMp = atkStatus < 0 ? 0 : monster.getMp();
} else {
mobMp = monster.getMp();
rawActivity = -1;
pOption = 0;
}
}
int mobMp = monster.getMp();
if (nextMovementCouldBeSkill) {
int noSkills = monster.getNoSkills();
if (noSkills > 0) {
int rndSkill = Randomizer.nextInt(noSkills);
Pair<Integer, Integer> skillToUse = monster.getSkills().get(rndSkill);
nextSkillId = skillToUse.getLeft();
nextSkillLevel = skillToUse.getRight();
nextUse = MobSkillFactory.getMobSkill(nextSkillId, nextSkillLevel);
if (!(nextUse != null && nextUse.getHP() >= (int) (((float) monster.getHp() / monster.getMaxHp()) * 100) && mobMp >= nextUse.getMpCon())) {
nextSkillId = 0;
nextSkillLevel = 0;
nextUse = null;
}
}
useSkillId = 0;
useSkillLevel = 0;
rawActivity = -1;
pOption = 0;
toUse = null;
}
slea.readByte();
@@ -151,9 +156,6 @@ public final class MoveLifeHandler extends AbstractMovementPacketHandler {
} else {
return;
}
} else if (rawActivity == -1 && monster.isControllerKnowsAboutAggro() && !monster.isMobile() && !monster.isFirstAttack()) {
monster.setControllerHasAggro(false);
monster.setControllerKnowsAboutAggro(false);
}
aggro = monster.isControllerHasAggro();
@@ -164,13 +166,17 @@ public final class MoveLifeHandler extends AbstractMovementPacketHandler {
monster.unlockMonster();
}
if (toUse != null) {
c.announce(MaplePacketCreator.moveMonsterResponse(objectid, moveid, mobMp, aggro, toUse.getSkillId(), toUse.getSkillLevel()));
if (nextUse != null) {
c.announce(MaplePacketCreator.moveMonsterResponse(objectid, moveid, mobMp, aggro, nextSkillId, nextSkillLevel));
} else {
c.announce(MaplePacketCreator.moveMonsterResponse(objectid, moveid, mobMp, aggro));
}
if (res != null) {
if (ServerConstants.USE_DEBUG_SHOW_RCVD_MVLIFE) {
System.out.println((isSkill ? "SKILL " : (isAttack ? "ATTCK " : " ")) + "castPos: " + castPos + " rawAct: " + rawActivity + " opt: " + pOption + " skillID: " + useSkillId + " skillLV: " + useSkillLevel + " " + "allowSkill: " + nextMovementCouldBeSkill);
}
map.broadcastMessage(player, MaplePacketCreator.moveMonster(objectid, nextMovementCouldBeSkill, rawActivity, useSkillId, useSkillLevel, pOption, startPos, res), monster.getPosition());
updatePosition(res, monster, -2);
map.moveMonster(monster, monster.getPosition());

View File

@@ -37,7 +37,7 @@ import java.util.List;
/**
*
* @author Ronan (multi-pot consumption feature)
* @author Ronan - multi-pot consumption feature
*/
public final class PetAutoPotHandler extends AbstractMaplePacketHandler {
short slot;

View File

@@ -49,7 +49,7 @@ import tools.data.input.SeekableLittleEndianAccessor;
/**
*
* @author Matze
* @author Ronan (concurrency safety & reviewed minigames)
* @author Ronan - concurrency safety & reviewed minigames
*/
public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
public enum Action {

View File

@@ -224,6 +224,7 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
if (playerGuild == null) {
player.deleteGuild(player.getGuildId());
player.getMGC().setGuildId(0);
player.getMGC().setGuildRank(5);
} else {
playerGuild.getMGC(player.getId()).setCharacter(player);
player.setMGC(playerGuild.getMGC(player.getId()));

View File

@@ -51,7 +51,7 @@ import client.inventory.Item;
/**
* @author Jvlaple
* @author Ronan (major overhaul on Ring handling mechanics)
* @author Ronan - major overhaul on Ring handling mechanics
*/
public final class RingActionHandler extends AbstractMaplePacketHandler {
private static int getBoxId(int useItemId) {

View File

@@ -48,7 +48,7 @@ public final class SpecialMoveHandler extends AbstractMaplePacketHandler {
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
MapleCharacter chr = c.getPlayer();
slea.readInt();
chr.getAutobanManager().setTimestamp(4, Server.getInstance().getCurrentTimestamp(), 5);
chr.getAutobanManager().setTimestamp(4, Server.getInstance().getCurrentTimestamp(), 28);
int skillid = slea.readInt();
/*
@@ -132,7 +132,11 @@ public final class SpecialMoveHandler extends AbstractMaplePacketHandler {
}
if (chr.isAlive()) {
if (skill.getId() != Priest.MYSTIC_DOOR) {
skill.getEffect(skillLevel).applyTo(chr, pos);
if (skill.getId() % 10000000 != 1005) {
skill.getEffect(skillLevel).applyTo(chr, pos);
} else {
skill.getEffect(skillLevel).applyEchoOfHero(chr);
}
} else if(chr.canDoor()) {
//update door lists
chr.cancelMagicDoor();

View File

@@ -83,12 +83,14 @@ public final class WhisperHandler extends AbstractMaplePacketHandler {
c.getPlayer().getAutobanManager().spam(7);
} else if (mode == 5) { // - /find
String recipient = slea.readMapleAsciiString();
MapleCharacter victim = c.getChannelServer().getPlayerStorage().getCharacterByName(recipient);
MapleCharacter victim = c.getWorldServer().getPlayerStorage().getCharacterByName(recipient);
if (victim != null && c.getPlayer().gmLevel() >= victim.gmLevel()) {
if (victim.getCashShop().isOpened()) {
if (victim.getCashShop().isOpened()) { // in CashShop
c.announce(MaplePacketCreator.getFindReply(victim.getName(), -1, 2));
//} else if (victim.inMTS()) {
// c.announce(MaplePacketCreator.getFindReply(victim.getName(), -1, 0));
} else if (victim.isAwayFromWorld()) { // in MTS
c.announce(MaplePacketCreator.getFindReply(victim.getName(), -1, 0));
} else if (victim.getClient().getChannel() != c.getChannel()) { // in another channel, issue detected thanks to MedicOP
c.announce(MaplePacketCreator.getFindReply(victim.getName(), victim.getClient().getChannel() - 1, 3));
} else {
c.announce(MaplePacketCreator.getFindReply(victim.getName(), victim.getMap().getId(), 1));
}

View File

@@ -90,7 +90,7 @@ import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
/**
*
* @author kevintjuh93
* @author Ronan (thread-oriented world schedules, guild queue, marriages & party chars)
* @author Ronan - thread-oriented world schedules, guild queue, marriages & party chars
*/
public class World {