"Exp-party" Pi + Event script disabled on dispose + Personal loot fix

Refactored event scripts, no longer triggering after the event is deemed disposed.
Added MCPQ access in Dimensional Doors.
Revised Crusader/Dawn Warrior's Combo Attack, no longer resetting orbs after recasting during active time.
Added 4th job advancement handing out Maple Warrior skill book.
Fixed several issues with not being able to collect drops within owned exclusivity time when back-and-forth changing maps.
Revised visual EXP gain. Players that participated most in the defeat of the mob has the gain displayed in white, else yellow, somewhat similar to GMS.
Fixed client not disconnecting properly after closing the game inside MTS/Cash Shop, leading to no update on account's login state.
Fixed wrongly inputted PIC in anti-multiclient system blocking accounts to login under the same IP.
Fixed parameterless command inputs counting as "one empty command".
This commit is contained in:
ronancpl
2019-04-04 14:02:15 -03:00
parent 0b6951527d
commit a15713dfa2
42 changed files with 344 additions and 198 deletions
+19 -5
View File
@@ -2992,8 +2992,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
int equip = (int) Math.min((long)(gain / 10) * pendantExp, Integer.MAX_VALUE);
long total = (long) gain + equip + party;
gainExpInternal(total, equip, party, show, inChat, white);
gainExpInternal((long) gain, equip, party, show, inChat, white);
}
public void loseExp(int loss, boolean show, boolean inChat) {
@@ -3004,8 +3003,23 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
gainExpInternal(-loss, 0, 0, show, inChat, white);
}
private void announceExpGain(long gain, int equip, int party, boolean inChat, boolean white) {
gain = Math.min(gain, Integer.MAX_VALUE);
if (gain == 0) {
if (party == 0) {
return;
}
gain = party;
party = 0;
white = false;
}
client.announce(MaplePacketCreator.getShowExpGain((int) gain, equip, party, inChat, white));
}
private synchronized void gainExpInternal(long gain, int equip, int party, boolean show, boolean inChat, boolean white) { // need of method synchonization here detected thanks to MedicOP
long total = Math.max(gain, -exp.get());
long total = Math.max(gain + equip + party, -exp.get());
if (level < getMaxLevel() && (allowExpGain || this.getEventInstance() != null)) {
long leftover = 0;
@@ -3016,8 +3030,8 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
leftover = nextExp - Integer.MAX_VALUE;
}
updateSingleStat(MapleStat.EXP, exp.addAndGet((int) total));
if (show && gain != 0) {
client.announce(MaplePacketCreator.getShowExpGain((int)Math.min(gain, Integer.MAX_VALUE), equip, party, inChat, white));
if (show) {
announceExpGain(gain, equip, party, inChat, white);
}
while (exp.get() >= ExpTable.getExpNeededForLevel(level)) {
levelUp(true);
+4 -3
View File
@@ -1474,7 +1474,6 @@ public class MapleClient {
player.unregisterChairBuff();
server.getPlayerBuffStorage().addBuffsToStorage(player.getId(), player.getAllBuffs());
server.getPlayerBuffStorage().addDiseasesToStorage(player.getId(), player.getAllDiseases());
player.setSessionTransitionState();
player.setDisconnectedFromChannelWorld();
player.notifyMapTransferToPartner(-1);
player.removeIncomingInvites();
@@ -1491,8 +1490,10 @@ public class MapleClient {
player.getMap().removePlayer(player);
player.clearBanishPlayerData();
player.getClient().getChannelServer().removePlayer(player);
player.getClient().updateLoginState(MapleClient.LOGIN_SERVER_TRANSITION);
try {
player.getClient().updateLoginState(MapleClient.LOGIN_SERVER_TRANSITION);
player.setSessionTransitionState();
try {
announce(MaplePacketCreator.getChannelChange(InetAddress.getByName(socket[0]), Integer.parseInt(socket[1])));
} catch (IOException e) {
e.printStackTrace();
+3 -3
View File
@@ -81,7 +81,7 @@ public class CommandsExecutor {
}
public void handle(MapleClient client, String message){
if (client.tryacquireClient()) {
if (client.tryacquireClient()) {
try {
handleInternal(client, message);
} finally {
@@ -113,8 +113,8 @@ public class CommandsExecutor {
return;
}
String[] params;
if (lowercaseParams.length > 0) {
params = Arrays.copyOfRange(lowercaseParams, 0, lowercaseParams.length);
if (lowercaseParams.length > 0 && !lowercaseParams[0].isEmpty()) {
params = Arrays.copyOfRange(lowercaseParams, 0, lowercaseParams.length);
} else {
params = new String[]{};
}
@@ -53,6 +53,7 @@ public class WarpWorldCommand extends Command {
c.getWorldServer().removePlayer(player);
player.getMap().removePlayer(player);//LOL FORGOT THIS ><
c.updateLoginState(MapleClient.LOGIN_SERVER_TRANSITION);
player.setSessionTransitionState();
player.setWorld(worldb);
player.saveCharToDB();//To set the new world :O (true because else 2 player instances are created, one in both worlds)
c.announce(MaplePacketCreator.getChannelChange(InetAddress.getByName(socket[0]), Integer.parseInt(socket[1])));
-2
View File
@@ -150,8 +150,6 @@ public class ServerConstants {
public static final float PARTY_BONUS_EXP_RATE = 1.0f; //Rate for the party exp bonus reward.
public static final double PQ_BONUS_EXP_RATE = 0.5; //Rate for the PQ exp reward.
public static final int PARTY_EXPERIENCE_MOD = 1; //Change for event stuff.
//Miscellaneous Configuration
public static String TIMEZONE = "GMT-3";
public static boolean USE_DISPLAY_NUMBERS_WITH_COMMA = true; //Enforce comma on displayed strings (use this when USE_UNITPRICE_WITH_COMMA is active and you still want to display comma-separated values).
+1
View File
@@ -329,6 +329,7 @@ public enum SendOpcode {
CHARGE_PARAM_RESULT(0x143),
QUERY_CASH_RESULT(0x144),
CASHSHOP_OPERATION(0x145),
CASHSHOP_PURCHASE_EXP_CHANGED(0x146), // found thanks to Arnah (Vertisy)
CASHSHOP_GIFT_INFO_RESULT(0x147),
CASHSHOP_CHECK_NAME_CHANGE(0x148),
CASHSHOP_CHECK_NAME_CHANGE_POSSIBLE_RESULT(0x149),
@@ -25,6 +25,7 @@ import net.AbstractMaplePacketHandler;
import server.CashShop;
import tools.data.input.SeekableLittleEndianAccessor;
import tools.MaplePacketCreator;
import tools.Pair;
/**
*
@@ -36,11 +37,14 @@ public class CashShopSurpriseHandler extends AbstractMaplePacketHandler {
CashShop cs = c.getPlayer().getCashShop();
if(cs.isOpened()) {
Item cssItem = cs.openCashShopSurprise();
Pair<Item, Item> cssResult = cs.openCashShopSurprise();
if(cssItem != null) {
if(cssResult != null) {
//Item cssItem = cssResult.getLeft(), cssBox = cssResult.getRight();
//c.announce(MaplePacketCreator.onCashGachaponOpenSuccess(c.getAccID(), cssBox.getSN(), cssBox.getQuantity(), cssItem, cssItem.getItemId(), cssItem.getQuantity(), true));
c.announce(MaplePacketCreator.showCashShopMessage((byte) 0xA4));
} else {
//c.announce(MaplePacketCreator.onCashItemGachaponOpenFailed());
c.announce(MaplePacketCreator.showCashShopMessage((byte) 0x00));
}
}
@@ -61,11 +61,13 @@ public final class ChangeMapHandler extends AbstractMaplePacketHandler {
}
String[] socket = c.getChannelServer().getIP().split(":");
chr.getCashShop().open(false);
c.updateLoginState(MapleClient.LOGIN_SERVER_TRANSITION);
c.updateLoginState(MapleClient.LOGIN_SERVER_TRANSITION);
chr.setSessionTransitionState();
try {
c.announce(MaplePacketCreator.getChannelChange(InetAddress.getByName(socket[0]), Integer.parseInt(socket[1])));
} catch (UnknownHostException ex) {
ex.printStackTrace();
ex.printStackTrace();
}
} else {
if(chr.getCashShop().isOpened()) {
@@ -65,7 +65,6 @@ public class EnterCashShopHandler extends AbstractMaplePacketHandler {
mc.unregisterChairBuff();
Server.getInstance().getPlayerBuffStorage().addBuffsToStorage(mc.getId(), mc.getAllBuffs());
Server.getInstance().getPlayerBuffStorage().addDiseasesToStorage(mc.getId(), mc.getAllDiseases());
mc.setSessionTransitionState();
mc.setAwayFromChannelWorld();
mc.notifyMapTransferToPartner(-1);
mc.removeIncomingInvites();
@@ -91,7 +91,6 @@ public final class EnterMTSHandler extends AbstractMaplePacketHandler {
chr.unregisterChairBuff();
Server.getInstance().getPlayerBuffStorage().addBuffsToStorage(chr.getId(), chr.getAllBuffs());
Server.getInstance().getPlayerBuffStorage().addDiseasesToStorage(chr.getId(), chr.getAllDiseases());
chr.setSessionTransitionState();
chr.setAwayFromChannelWorld();
chr.notifyMapTransferToPartner(-1);
chr.removeIncomingInvites();
@@ -439,7 +439,7 @@ public class MapleSessionCoordinator {
}
try {
String nibbleHwid = (String) session.removeAttribute(MapleClient.CLIENT_NIBBLEHWID);
String nibbleHwid = (String) session.getAttribute(MapleClient.CLIENT_NIBBLEHWID); // thanks Paxum for noticing account stuck after PIC failure
if (nibbleHwid != null) {
onlineRemoteHwids.remove(nibbleHwid);
@@ -51,11 +51,6 @@ public class CharSelectedWithPicHandler extends AbstractMaplePacketHandler {
c.updateHWID(hwid);
IoSession session = c.getSession();
AntiMulticlientResult res = MapleSessionCoordinator.getInstance().attemptGameSession(session, c.getAccID(), hwid);
if (res != AntiMulticlientResult.SUCCESS) {
c.announce(MaplePacketCreator.getAfterLoginError(parseAntiMulticlientError(res)));
return;
}
if (c.hasBannedMac() || c.hasBannedHWID()) {
MapleSessionCoordinator.getInstance().closeSession(c.getSession(), true);
@@ -82,6 +77,12 @@ public class CharSelectedWithPicHandler extends AbstractMaplePacketHandler {
return;
}
AntiMulticlientResult res = MapleSessionCoordinator.getInstance().attemptGameSession(session, c.getAccID(), hwid);
if (res != AntiMulticlientResult.SUCCESS) {
c.announce(MaplePacketCreator.getAfterLoginError(parseAntiMulticlientError(res)));
return;
}
server.unregisterLoginState(c);
c.updateLoginState(MapleClient.LOGIN_SERVER_TRANSITION);
server.setCharacteridInTransition(session, charId);
@@ -59,11 +59,6 @@ public class ViewAllCharSelectedWithPicHandler extends AbstractMaplePacketHandle
}
IoSession session = c.getSession();
AntiMulticlientResult res = MapleSessionCoordinator.getInstance().attemptGameSession(session, c.getAccID(), hwid);
if (res != AntiMulticlientResult.SUCCESS) {
c.announce(MaplePacketCreator.getAfterLoginError(parseAntiMulticlientError(res)));
return;
}
Server server = Server.getInstance();
if(!server.haveCharacterEntry(c.getAccID(), charId)) {
@@ -88,6 +83,12 @@ public class ViewAllCharSelectedWithPicHandler extends AbstractMaplePacketHandle
return;
}
AntiMulticlientResult res = MapleSessionCoordinator.getInstance().attemptGameSession(session, c.getAccID(), hwid);
if (res != AntiMulticlientResult.SUCCESS) {
c.announce(MaplePacketCreator.getAfterLoginError(parseAntiMulticlientError(res)));
return;
}
server.unregisterLoginState(c);
c.updateLoginState(MapleClient.LOGIN_SERVER_TRANSITION);
server.setCharacteridInTransition(session, charId);
+34 -37
View File
@@ -22,8 +22,6 @@
package scripting.event;
import java.io.File;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import tools.Pair;
import java.util.ArrayList;
import java.util.LinkedList;
@@ -51,20 +49,12 @@ import server.life.MapleMonster;
import server.maps.MapleMap;
import server.maps.MapleMapFactory;
import server.maps.MapleReactor;
import tools.DatabaseConnection;
import client.MapleCharacter;
import client.SkillFactory;
import client.Skill;
import client.inventory.Item;
import client.inventory.ItemFactory;
import client.inventory.MapleInventory;
import client.inventory.MapleInventoryType;
import client.inventory.manipulator.MapleInventoryManipulator;
import constants.ItemConstants;
import constants.ServerConstants;
import java.awt.Point;
import java.sql.Connection;
import java.util.Arrays;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
@@ -79,7 +69,6 @@ import server.ThreadManager;
import server.life.MapleLifeFactory;
import server.life.MapleNPC;
import tools.MaplePacketCreator;
import tools.Randomizer;
/**
*
@@ -236,6 +225,14 @@ public class EventInstanceManager {
}
}
public Object invokeScriptFunction(String name, Object... args) throws ScriptException, NoSuchMethodException {
if (!disposed) {
return em.getIv().invokeFunction(name, args);
} else {
return null;
}
}
public synchronized void registerPlayer(final MapleCharacter chr) {
registerPlayer(chr, true);
@@ -260,7 +257,7 @@ public class EventInstanceManager {
if (runEntryScript) {
try {
em.getIv().invokeFunction("playerEntry", EventInstanceManager.this, chr);
invokeScriptFunction("playerEntry", EventInstanceManager.this, chr);
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
@@ -275,7 +272,7 @@ public class EventInstanceManager {
unregisterPlayer(chr);
try {
em.getIv().invokeFunction("playerExit", EventInstanceManager.this, chr);
invokeScriptFunction("playerExit", EventInstanceManager.this, chr);
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
@@ -306,7 +303,7 @@ public class EventInstanceManager {
dismissEventTimer();
try {
em.getIv().invokeFunction("scheduledTimeout", EventInstanceManager.this);
invokeScriptFunction("scheduledTimeout", EventInstanceManager.this);
} catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, "Event '" + em.getName() + "' does not implement scheduledTimeout function.", ex);
}
@@ -326,7 +323,7 @@ public class EventInstanceManager {
dismissEventTimer();
try {
em.getIv().invokeFunction("scheduledTimeout", EventInstanceManager.this);
invokeScriptFunction("scheduledTimeout", EventInstanceManager.this);
} catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, "Event '" + em.getName() + "' does not implement scheduledTimeout function.", ex);
}
@@ -395,7 +392,7 @@ public class EventInstanceManager {
public void unregisterPlayer(final MapleCharacter chr) {
try {
em.getIv().invokeFunction("playerUnregistered", EventInstanceManager.this, chr);
invokeScriptFunction("playerUnregistered", EventInstanceManager.this, chr);
} catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, "Event '" + em.getName() + "' does not implement playerUnregistered function.", ex);
}
@@ -456,7 +453,7 @@ public class EventInstanceManager {
public void movePlayer(final MapleCharacter chr) {
try {
em.getIv().invokeFunction("moveMap", EventInstanceManager.this, chr);
invokeScriptFunction("moveMap", EventInstanceManager.this, chr);
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
@@ -464,19 +461,19 @@ public class EventInstanceManager {
public void changedMap(final MapleCharacter chr, final int mapId) {
try {
em.getIv().invokeFunction("changedMap", EventInstanceManager.this, chr, mapId);
invokeScriptFunction("changedMap", EventInstanceManager.this, chr, mapId);
} catch (ScriptException | NoSuchMethodException ex) {} // optional
}
public void afterChangedMap(final MapleCharacter chr, final int mapId) {
try {
em.getIv().invokeFunction("afterChangedMap", EventInstanceManager.this, chr, mapId);
invokeScriptFunction("afterChangedMap", EventInstanceManager.this, chr, mapId);
} catch (ScriptException | NoSuchMethodException ex) {} // optional
}
public synchronized void changedLeader(final MapleCharacter ldr) {
try {
em.getIv().invokeFunction("changedLeader", EventInstanceManager.this, ldr);
invokeScriptFunction("changedLeader", EventInstanceManager.this, ldr);
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
@@ -504,14 +501,14 @@ public class EventInstanceManager {
if (scriptResult > 0) {
try {
em.getIv().invokeFunction("monsterKilled", mob, EventInstanceManager.this, hasKiller);
invokeScriptFunction("monsterKilled", mob, EventInstanceManager.this, hasKiller);
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
if (scriptResult > 1) {
try {
em.getIv().invokeFunction("allMonstersDead", EventInstanceManager.this, hasKiller);
invokeScriptFunction("allMonstersDead", EventInstanceManager.this, hasKiller);
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
@@ -521,7 +518,7 @@ public class EventInstanceManager {
public void friendlyKilled(final MapleMonster mob, final boolean hasKiller) {
try {
em.getIv().invokeFunction("friendlyKilled", mob, EventInstanceManager.this, hasKiller);
invokeScriptFunction("friendlyKilled", mob, EventInstanceManager.this, hasKiller);
} catch (ScriptException | NoSuchMethodException ex) {} //optional
}
@@ -530,7 +527,7 @@ public class EventInstanceManager {
@Override
public void run() {
try {
em.getIv().invokeFunction("playerDead", EventInstanceManager.this, chr);
invokeScriptFunction("playerDead", EventInstanceManager.this, chr);
} catch (ScriptException | NoSuchMethodException ex) {} // optional
}
});
@@ -538,13 +535,13 @@ public class EventInstanceManager {
public void reviveMonster(final MapleMonster mob) {
try {
em.getIv().invokeFunction("monsterRevive", EventInstanceManager.this, mob);
invokeScriptFunction("monsterRevive", EventInstanceManager.this, mob);
} catch (ScriptException | NoSuchMethodException ex) {} // optional
}
public boolean revivePlayer(final MapleCharacter chr) {
try {
Object b = em.getIv().invokeFunction("playerRevive", EventInstanceManager.this, chr);
Object b = invokeScriptFunction("playerRevive", EventInstanceManager.this, chr);
if (b instanceof Boolean) {
return (Boolean) b;
}
@@ -555,7 +552,7 @@ public class EventInstanceManager {
public void playerDisconnected(final MapleCharacter chr) {
try {
em.getIv().invokeFunction("playerDisconnected", EventInstanceManager.this, chr);
invokeScriptFunction("playerDisconnected", EventInstanceManager.this, chr);
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
@@ -568,9 +565,9 @@ public class EventInstanceManager {
int inc;
if (ServerConstants.JAVA_8) {
inc = (int)em.getIv().invokeFunction("monsterValue", EventInstanceManager.this, mob.getId());
inc = (int)invokeScriptFunction("monsterValue", EventInstanceManager.this, mob.getId());
} else {
inc = ((Double) em.getIv().invokeFunction("monsterValue", EventInstanceManager.this, mob.getId())).intValue();
inc = ((Double) invokeScriptFunction("monsterValue", EventInstanceManager.this, mob.getId())).intValue();
}
if (inc != 0) {
@@ -609,12 +606,12 @@ public class EventInstanceManager {
public synchronized void dispose(boolean shutdown) { // should not trigger any event script method after disposed
if(disposed) return;
disposed = true;
try {
em.getIv().invokeFunction("dispose", EventInstanceManager.this);
invokeScriptFunction("dispose", EventInstanceManager.this);
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
disposed = true;
ess.dispose();
@@ -690,7 +687,7 @@ public class EventInstanceManager {
@Override
public void run() {
try {
em.getIv().invokeFunction(methodName, EventInstanceManager.this);
invokeScriptFunction(methodName, EventInstanceManager.this);
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
@@ -789,7 +786,7 @@ public class EventInstanceManager {
public void leftParty(final MapleCharacter chr) {
try {
em.getIv().invokeFunction("leftParty", EventInstanceManager.this, chr);
invokeScriptFunction("leftParty", EventInstanceManager.this, chr);
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
@@ -797,7 +794,7 @@ public class EventInstanceManager {
public void disbandParty() {
try {
em.getIv().invokeFunction("disbandParty", EventInstanceManager.this);
invokeScriptFunction("disbandParty", EventInstanceManager.this);
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
@@ -805,7 +802,7 @@ public class EventInstanceManager {
public void clearPQ() {
try {
em.getIv().invokeFunction("clearPQ", EventInstanceManager.this);
invokeScriptFunction("clearPQ", EventInstanceManager.this);
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
@@ -813,7 +810,7 @@ public class EventInstanceManager {
public void removePlayer(final MapleCharacter chr) {
try {
em.getIv().invokeFunction("playerExit", EventInstanceManager.this, chr);
invokeScriptFunction("playerExit", EventInstanceManager.this, chr);
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
@@ -1081,7 +1078,7 @@ public class EventInstanceManager {
eventStarted = true;
try {
em.getIv().invokeFunction("afterSetup", EventInstanceManager.this);
invokeScriptFunction("afterSetup", EventInstanceManager.this);
} catch (ScriptException | NoSuchMethodException ex) {
ex.printStackTrace();
}
+2 -2
View File
@@ -557,7 +557,7 @@ public class CashShop {
return null;
}
public synchronized Item openCashShopSurprise() {
public synchronized Pair<Item, Item> openCashShopSurprise() {
Item css = getCashShopItemByItemid(5222000);
if(css != null) {
@@ -577,7 +577,7 @@ public class CashShop {
Item item = cItem.toItem();
addToInventory(item);
return item;
return new Pair<>(item, css);
} else {
return null;
}
+7 -2
View File
@@ -1107,7 +1107,7 @@ public class MapleStatEffect {
}
private void applyBuffEffect(MapleCharacter applyfrom, MapleCharacter applyto, boolean primary) {
if (!isMonsterRiding() && !isCouponBuff() && !isMysticDoor() && !isHyperBody()) { // last mystic door already dispelled if it has been used before.
if (!isMonsterRiding() && !isCouponBuff() && !isMysticDoor() && !isHyperBody() && !isCombo()) { // last mystic door already dispelled if it has been used before.
applyto.cancelEffect(this, true, -1);
}
@@ -1190,7 +1190,12 @@ public class MapleStatEffect {
List<Pair<MapleBuffStat, Integer>> dsstat = Collections.singletonList(new Pair<>(MapleBuffStat.WIND_WALK, 0));
mbuff = MaplePacketCreator.giveForeignBuff(applyto.getId(), dsstat);
} else if (isCombo()) {
mbuff = MaplePacketCreator.giveForeignBuff(applyto.getId(), statups);
Integer comboCount = applyto.getBuffedValue(MapleBuffStat.COMBO);
if (comboCount == null) comboCount = 0;
List<Pair<MapleBuffStat, Integer>> cbstat = Collections.singletonList(new Pair<>(MapleBuffStat.COMBO, comboCount));
buff = MaplePacketCreator.giveBuff((skill ? sourceid : -sourceid), localDuration, cbstat);
mbuff = MaplePacketCreator.giveForeignBuff(applyto.getId(), cbstat);
} else if (isMonsterRiding()) {
if (sourceid == Corsair.BATTLE_SHIP) {//hp
if (applyto.getBattleshipHp() <= 0) {
+24 -5
View File
@@ -535,15 +535,34 @@ public class MapleMonster extends AbstractLoadedMapleLife {
}
}
private void propagateExperienceGains(Map<MapleCharacter, Float> personalExpReward, Map<MapleCharacter, Float> partyExpReward) {
private static double calcExperienceStandDevThreshold(Map<MapleCharacter, Float> personalExpReward, float exp2) {
float avgExpReward = 0.0f;
for (Float exp : personalExpReward.values()) {
avgExpReward += exp;
}
avgExpReward -= exp2; // clear out the 20% raw exp from last hitting
avgExpReward /= personalExpReward.size();
float varExpReward = 0.0f;
for (Float exp : personalExpReward.values()) {
varExpReward += Math.pow(exp - avgExpReward, 2);
}
varExpReward /= personalExpReward.size();
return avgExpReward + Math.sqrt(varExpReward);
}
private void propagateExperienceGains(Map<MapleCharacter, Float> personalExpReward, Map<MapleCharacter, Float> partyExpReward, float exp2) {
Set<MapleCharacter> expRewardPlayers = new HashSet<>(personalExpReward.keySet());
expRewardPlayers.addAll(partyExpReward.keySet());
double sdevExp = calcExperienceStandDevThreshold(personalExpReward, exp2);
for (MapleCharacter chr : expRewardPlayers) {
Float personalExp = personalExpReward.get(chr);
Float partyExp = partyExpReward.get(chr);
this.giveExpToCharacter(chr, personalExp, partyExp);
this.giveExpToCharacter(chr, personalExp, partyExp, personalExp != null && personalExp >= sdevExp);
}
}
@@ -628,7 +647,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
mc.showUnderleveledInfo(this);
}
propagateExperienceGains(personalExpReward, partyExpReward);
propagateExperienceGains(personalExpReward, partyExpReward, killerLevel != Integer.MAX_VALUE ? exp2 : 0.0f);
}
private float getStatusExpMultiplier(MapleCharacter attacker) {
@@ -663,7 +682,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
return (int) exp;
}
private void giveExpToCharacter(MapleCharacter attacker, Float personalExp, Float partyExp) {
private void giveExpToCharacter(MapleCharacter attacker, Float personalExp, Float partyExp, boolean white) {
if (attacker.isAlive()) {
if (personalExp != null) {
personalExp *= getStatusExpMultiplier(attacker);
@@ -689,7 +708,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
int _partyExp = expValueToInteger(partyExp);
attacker.gainExp(_personalExp, _partyExp, true, false, false);
attacker.gainExp(_personalExp, _partyExp, true, false, white);
attacker.increaseEquipExp(_personalExp);
attacker.updateQuestMobCount(getId());
}
+4 -4
View File
@@ -1069,7 +1069,7 @@ public class MapleMap {
if (chr.needQuestItem(questid, idrop.getItemId())) {
mdrop.lockItem();
try {
c.announce(MaplePacketCreator.dropItemFromMapObject(chr.getParty() != null, mdrop, dropper.getPosition(), dropPos, (byte) 1));
c.announce(MaplePacketCreator.dropItemFromMapObject(chr, mdrop, dropper.getPosition(), dropPos, (byte) 1));
} finally {
mdrop.unlockItem();
}
@@ -1091,7 +1091,7 @@ public class MapleMap {
public void sendPackets(MapleClient c) {
mdrop.lockItem();
try {
c.announce(MaplePacketCreator.dropItemFromMapObject(c.getPlayer().getParty() != null, mdrop, dropper.getPosition(), droppos, (byte) 1));
c.announce(MaplePacketCreator.dropItemFromMapObject(c.getPlayer(), mdrop, dropper.getPosition(), droppos, (byte) 1));
} finally {
mdrop.unlockItem();
}
@@ -2179,7 +2179,7 @@ public class MapleMap {
public void sendPackets(MapleClient c) {
mdrop.lockItem();
try {
c.announce(MaplePacketCreator.dropItemFromMapObject(c.getPlayer().getParty() != null, mdrop, dropper.getPosition(), droppos, (byte) 1));
c.announce(MaplePacketCreator.dropItemFromMapObject(c.getPlayer(), mdrop, dropper.getPosition(), droppos, (byte) 1));
} finally {
mdrop.unlockItem();
}
@@ -2877,7 +2877,7 @@ public class MapleMap {
chrRLock.lock();
try {
for (MapleCharacter chr : characters) {
final byte[] packet = MaplePacketCreator.dropItemFromMapObject(chr.getParty() != null, mdrop, dropperPos, dropPos, mod);
final byte[] packet = MaplePacketCreator.dropItemFromMapObject(chr, mdrop, dropperPos, dropPos, mod);
if (rangeSq < Double.POSITIVE_INFINITY) {
if (rangedFrom.distanceSq(chr.getPosition()) <= rangeSq) {
+20 -2
View File
@@ -23,6 +23,7 @@ package server.maps;
import client.MapleCharacter;
import client.MapleClient;
import client.inventory.Item;
import constants.ServerConstants;
import java.awt.Point;
import java.util.concurrent.locks.Lock;
import tools.MaplePacketCreator;
@@ -35,7 +36,7 @@ public class MapleMapItem extends AbstractMapleMapObject {
protected MapleMapObject dropper;
protected int character_ownerid, party_ownerid, meso, questid = -1;
protected byte type;
protected boolean pickedUp = false, playerDrop;
protected boolean pickedUp = false, playerDrop, partyDrop;
protected long dropTime;
private Lock itemLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.MAP_ITEM);
@@ -45,6 +46,7 @@ public class MapleMapItem extends AbstractMapleMapObject {
this.dropper = dropper;
this.character_ownerid = owner.getId();
this.party_ownerid = owner.getPartyId();
this.partyDrop = this.party_ownerid != -1;
this.ownerClient = owner.getClient();
this.meso = 0;
this.type = type;
@@ -57,6 +59,7 @@ public class MapleMapItem extends AbstractMapleMapObject {
this.dropper = dropper;
this.character_ownerid = owner.getId();
this.party_ownerid = owner.getPartyId();
this.partyDrop = this.party_ownerid != -1;
this.ownerClient = owner.getClient();
this.meso = 0;
this.type = type;
@@ -70,6 +73,7 @@ public class MapleMapItem extends AbstractMapleMapObject {
this.dropper = dropper;
this.character_ownerid = owner.getId();
this.party_ownerid = owner.getPartyId();
this.partyDrop = this.party_ownerid != -1;
this.ownerClient = owner.getClient();
this.meso = meso;
this.type = type;
@@ -105,6 +109,20 @@ public class MapleMapItem extends AbstractMapleMapObject {
party_ownerid = partyid;
}
public final int getClientsideOwnerId(MapleCharacter player) {
if (this.party_ownerid == -1) {
return this.character_ownerid;
} else {
if (!partyDrop && player.getId() == this.character_ownerid) {
return player.getId();
} else if (player.getPartyId() == this.party_ownerid) {
return player.getId();
} else {
return this.party_ownerid;
}
}
}
public final boolean isFFADrop() {
return type == 2 || type == 3 || hasExpiredOwnershipTime();
}
@@ -187,7 +205,7 @@ public class MapleMapItem extends AbstractMapleMapObject {
if (chr.needQuestItem(questid, getItemId())) {
this.lockItem();
try {
client.announce(MaplePacketCreator.dropItemFromMapObject(chr.getParty() != null, this, null, getPosition(), (byte) 2));
client.announce(MaplePacketCreator.dropItemFromMapObject(chr, this, null, getPosition(), (byte) 2));
} finally {
this.unlockItem();
}
+27 -8
View File
@@ -1668,7 +1668,7 @@ public class MaplePacketCreator {
mplew.writeBool(white);
mplew.writeInt(gain);
mplew.writeBool(inChat);
mplew.writeInt(0); // monster book bonus (Bonus Event Exp)
mplew.writeInt(0); // bonus event exp
mplew.write(0); // third monster kill event
mplew.write(0); // RIP byte, this is always a 0
mplew.writeInt(0); //wedding bonus
@@ -1676,9 +1676,7 @@ public class MaplePacketCreator {
mplew.write(0);
}
int mod = ServerConstants.PARTY_EXPERIENCE_MOD != 1 ? ServerConstants.PARTY_EXPERIENCE_MOD * 100 : 0;
mplew.write(mod); //0 = party bonus, 100 = 1x Bonus EXP, 200 = 2x Bonus EXP
mplew.write(0); //0 = party bonus, 100 = 1x Bonus EXP, 200 = 2x Bonus EXP
mplew.writeInt(party); // party bonus
mplew.writeInt(equip); //equip bonus
mplew.writeInt(0); //Internet Cafe Bonus
@@ -1808,15 +1806,15 @@ public class MaplePacketCreator {
return mplew.getPacket();
}
public static byte[] dropItemFromMapObject(boolean recvrInParty, MapleMapItem drop, Point dropfrom, Point dropto, byte mod) {
public static byte[] dropItemFromMapObject(MapleCharacter player, MapleMapItem drop, Point dropfrom, Point dropto, byte mod) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.DROP_ITEM_FROM_MAPOBJECT.getValue());
mplew.write(mod);
mplew.writeInt(drop.getObjectId());
mplew.writeBool(drop.getMeso() > 0); // 1 mesos, 0 item, 2 and above all item meso bag,
mplew.writeInt(drop.getItemId()); // drop object ID
mplew.writeInt(!drop.isFFADrop() ? (recvrInParty ? drop.getPartyOwnerId() : drop.getOwnerId()) : 0); // owner charid/partyid :)
mplew.write(drop.getDropType()); // 0 = timeout for non-owner, 1 = timeout for non-owner's party, 2 = FFA, 3 = explosive/FFA
mplew.writeInt(drop.getClientsideOwnerId(player)); // owner charid/partyid :)
mplew.write(!drop.hasExpiredOwnershipTime() ? drop.getDropType() : 2); // 0 = timeout for non-owner, 1 = timeout for non-owner's party, 2 = FFA, 3 = explosive/FFA
mplew.writePos(dropto);
mplew.writeInt(drop.getDropper().getObjectId()); // dropper oid, found thanks to Li Jixue
@@ -6759,7 +6757,28 @@ public class MaplePacketCreator {
return mplew.getPacket();
}
// Cash Shop Surprise packets found thanks to Arnah (Vertisy)
public static byte[] onCashItemGachaponOpenFailed(){
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.CASHSHOP_CASH_ITEM_GACHAPON_RESULT.getValue());
mplew.write(189);
return mplew.getPacket();
}
public static byte[] onCashGachaponOpenSuccess(int accountid, long sn, int remainingBoxes, Item item, int itemid, int nSelectedItemCount, boolean bJackpot){
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.CASHSHOP_CASH_ITEM_GACHAPON_RESULT.getValue());
mplew.write(190);
mplew.writeLong(sn);// sn of the box used
mplew.writeInt(remainingBoxes);
addCashItemInformation(mplew, item, accountid);
mplew.writeInt(itemid);// the itemid of the liSN?
mplew.write(nSelectedItemCount);// the total count now? o.O
mplew.writeBool(bJackpot);// "CashGachaponJackpot"
return mplew.getPacket();
}
private static void getGuildInfo(final MaplePacketLittleEndianWriter mplew, MapleGuild guild) {
mplew.writeInt(guild.getId());
mplew.writeMapleAsciiString(guild.getName());
@@ -7495,7 +7514,7 @@ public class MaplePacketCreator {
return mplew.getPacket();
}
/*
* 00 = Due to an unknown error, failed
* A4 = Due to an unknown error, failed + warpout