Coupon buff fix + concurrency fixes
Fixed coupon buff icon not showing properly. Fixed some cases involving coupons and buff removal not dealing properly with concurrent access.
This commit is contained in:
@@ -22,42 +22,48 @@
|
||||
package client;
|
||||
|
||||
public enum MapleBuffStat {
|
||||
//SLOW(0x1),
|
||||
MORPH(0x2),
|
||||
RECOVERY(0x4),
|
||||
MAPLE_WARRIOR(0x8),
|
||||
STANCE(0x10),
|
||||
SHARP_EYES(0x20),
|
||||
MANA_REFLECTION(0x40),
|
||||
//ALWAYS_RIGHT(0X80),
|
||||
//SLOW(0x1L),
|
||||
MORPH(0x2L),
|
||||
RECOVERY(0x4L),
|
||||
MAPLE_WARRIOR(0x8L),
|
||||
STANCE(0x10L),
|
||||
SHARP_EYES(0x20L),
|
||||
MANA_REFLECTION(0x40L),
|
||||
//ALWAYS_RIGHT(0X80L),
|
||||
|
||||
//------ bgn EDITED SLOT (was unused before) --------
|
||||
MAP_PROTECTION(0x100000000000000L),
|
||||
//------ end EDITED SLOT ----------------------------
|
||||
|
||||
SHADOW_CLAW(0x100),
|
||||
INFINITY(0x200),
|
||||
HOLY_SHIELD(0x400),
|
||||
HAMSTRING(0x800),
|
||||
BLIND(0x1000),
|
||||
CONCENTRATE(0x2000),
|
||||
//4000
|
||||
ECHO_OF_HERO(0x8000),
|
||||
//10000
|
||||
GHOST_MORPH(0x20000),
|
||||
AURA(0x40000),
|
||||
CONFUSE(0x80000),
|
||||
//100000
|
||||
//200000
|
||||
//400000
|
||||
//800000
|
||||
//1000000
|
||||
//2000000
|
||||
//4000000
|
||||
BERSERK_FURY(0x8000000),
|
||||
DIVINE_BODY(0x10000000),
|
||||
SHADOW_CLAW(0x100L),
|
||||
INFINITY(0x200L),
|
||||
HOLY_SHIELD(0x400L),
|
||||
HAMSTRING(0x800L),
|
||||
BLIND(0x1000L),
|
||||
CONCENTRATE(0x2000L),
|
||||
//4000L
|
||||
ECHO_OF_HERO(0x8000L),
|
||||
//10000L
|
||||
GHOST_MORPH(0x20000L),
|
||||
AURA(0x40000L),
|
||||
CONFUSE(0x80000L),
|
||||
|
||||
// ---- COUPON feature (was unused anyway) ----
|
||||
|
||||
COUPON_EXP1(0x100000L),
|
||||
COUPON_EXP2(0x200000L),
|
||||
COUPON_EXP3(0x400000L),
|
||||
COUPON_EXP4(0x800000L),
|
||||
COUPON_DRP1(0x1000000L),
|
||||
COUPON_DRP2(0x2000000L),
|
||||
COUPON_DRP3(0x4000000L),
|
||||
|
||||
// ---- end COUPON feature ----
|
||||
|
||||
BERSERK_FURY(0x8000000L),
|
||||
DIVINE_BODY(0x10000000L),
|
||||
SPARK(0x20000000L),
|
||||
//40000000
|
||||
//40000000L
|
||||
FINALATTACK(0x80000000L),
|
||||
BATTLESHIP(0xA00000040L), // weird one
|
||||
WATK(0x100000000L),
|
||||
|
||||
@@ -46,6 +46,8 @@ import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
//import java.util.TimeZone;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -257,6 +259,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
private ScheduledFuture<?> expiretask;
|
||||
private ScheduledFuture<?> recoveryTask;
|
||||
private List<ScheduledFuture<?>> timers = new ArrayList<>();
|
||||
private Lock couponLock = new ReentrantLock();
|
||||
private NumberFormat nf = new DecimalFormat("#,###,###,###");
|
||||
private ArrayList<Integer> excluded = new ArrayList<>();
|
||||
private MonsterBook monsterbook;
|
||||
@@ -700,9 +703,9 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
}
|
||||
}
|
||||
|
||||
public void cancelBuffStats(MapleBuffStat stat) {
|
||||
public synchronized void cancelBuffStats(MapleBuffStat stat) {
|
||||
List<MapleBuffStat> buffStatList = Arrays.asList(stat);
|
||||
deregisterBuffStats(buffStatList);
|
||||
dropBuffStats(deregisterBuffStats(buffStatList));
|
||||
cancelPlayerBuffs(buffStatList);
|
||||
}
|
||||
|
||||
@@ -789,7 +792,15 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
cancelEffect(MapleItemInformationProvider.getInstance().getItemEffect(itemId), false, -1);
|
||||
}
|
||||
|
||||
public void cancelEffect(MapleStatEffect effect, boolean overwrite, long startTime) {
|
||||
public synchronized void cancelEffect(MapleStatEffect effect, boolean overwrite, long startTime) {
|
||||
cancelEffect(effect, overwrite, startTime, true);
|
||||
}
|
||||
|
||||
private void cancelEffect(MapleStatEffect effect, boolean overwrite, long startTime, boolean firstCancel) {
|
||||
dropBuffStats(cancelEffectInternal(effect, overwrite, startTime));
|
||||
}
|
||||
|
||||
private List<MapleBuffStatValueHolder> cancelEffectInternal(MapleStatEffect effect, boolean overwrite, long startTime) {
|
||||
List<MapleBuffStat> buffstats;
|
||||
if (!overwrite) {
|
||||
buffstats = getBuffStats(effect, startTime);
|
||||
@@ -800,7 +811,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
buffstats.add(statup.getLeft());
|
||||
}
|
||||
}
|
||||
deregisterBuffStats(buffstats);
|
||||
List<MapleBuffStatValueHolder> toCancel = deregisterBuffStats(buffstats);
|
||||
if (effect.isMagicDoor()) {
|
||||
if (!getDoors().isEmpty()) {
|
||||
MapleDoor door = getDoors().iterator().next();
|
||||
@@ -842,6 +853,8 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
if (!overwrite) {
|
||||
cancelPlayerBuffs(buffstats);
|
||||
}
|
||||
|
||||
return toCancel;
|
||||
}
|
||||
|
||||
public void cancelEffectFromBuffStat(MapleBuffStat stat) {
|
||||
@@ -1745,60 +1758,63 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
}
|
||||
}
|
||||
|
||||
private void deregisterBuffStats(List<MapleBuffStat> stats) {
|
||||
synchronized (stats) {
|
||||
List<MapleBuffStatValueHolder> effectsToCancel = new ArrayList<>(stats.size());
|
||||
for (MapleBuffStat stat : stats) {
|
||||
MapleBuffStatValueHolder mbsvh = effects.get(stat);
|
||||
if (mbsvh != null) {
|
||||
effects.remove(stat);
|
||||
boolean addMbsvh = true;
|
||||
for (MapleBuffStatValueHolder contained : effectsToCancel) {
|
||||
if (mbsvh.startTime == contained.startTime && contained.effect == mbsvh.effect) {
|
||||
addMbsvh = false;
|
||||
}
|
||||
}
|
||||
if (addMbsvh) {
|
||||
effectsToCancel.add(mbsvh);
|
||||
}
|
||||
if (stat == MapleBuffStat.RECOVERY) {
|
||||
if (recoveryTask != null) {
|
||||
recoveryTask.cancel(false);
|
||||
recoveryTask = null;
|
||||
}
|
||||
} else if (stat == MapleBuffStat.SUMMON || stat == MapleBuffStat.PUPPET) {
|
||||
int summonId = mbsvh.effect.getSourceId();
|
||||
|
||||
MapleSummon summon = summons.get(summonId);
|
||||
if (summon != null) {
|
||||
getMap().broadcastMessage(MaplePacketCreator.removeSummon(summon, true), summon.getPosition());
|
||||
getMap().removeMapObject(summon);
|
||||
removeVisibleMapObject(summon);
|
||||
summons.remove(summonId);
|
||||
}
|
||||
if (summon.getSkill() == DarkKnight.BEHOLDER) {
|
||||
if (beholderHealingSchedule != null) {
|
||||
beholderHealingSchedule.cancel(false);
|
||||
beholderHealingSchedule = null;
|
||||
}
|
||||
if (beholderBuffSchedule != null) {
|
||||
beholderBuffSchedule.cancel(false);
|
||||
beholderBuffSchedule = null;
|
||||
}
|
||||
}
|
||||
} else if (stat == MapleBuffStat.DRAGONBLOOD) {
|
||||
dragonBloodSchedule.cancel(false);
|
||||
dragonBloodSchedule = null;
|
||||
private void dropBuffStats(List<MapleBuffStatValueHolder> effectsToCancel) {
|
||||
for (MapleBuffStatValueHolder cancelEffectCancelTasks : effectsToCancel) {
|
||||
if (cancelEffectCancelTasks.schedule != null) {
|
||||
cancelEffectCancelTasks.schedule.cancel(false);
|
||||
this.cancelEffect(cancelEffectCancelTasks.effect, false, -1, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<MapleBuffStatValueHolder> deregisterBuffStats(List<MapleBuffStat> stats) {
|
||||
List<MapleBuffStatValueHolder> effectsToCancel = new ArrayList<>(stats.size());
|
||||
for (MapleBuffStat stat : stats) {
|
||||
MapleBuffStatValueHolder mbsvh = effects.get(stat);
|
||||
if (mbsvh != null) {
|
||||
effects.remove(stat);
|
||||
boolean addMbsvh = true;
|
||||
for (MapleBuffStatValueHolder contained : effectsToCancel) {
|
||||
if (mbsvh.startTime == contained.startTime && contained.effect == mbsvh.effect) {
|
||||
addMbsvh = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (MapleBuffStatValueHolder cancelEffectCancelTasks : effectsToCancel) {
|
||||
if (cancelEffectCancelTasks.schedule != null) {
|
||||
cancelEffectCancelTasks.schedule.cancel(false);
|
||||
this.cancelEffect(cancelEffectCancelTasks.effect, false, -1);
|
||||
if (addMbsvh) {
|
||||
effectsToCancel.add(mbsvh);
|
||||
}
|
||||
if (stat == MapleBuffStat.RECOVERY) {
|
||||
if (recoveryTask != null) {
|
||||
recoveryTask.cancel(false);
|
||||
recoveryTask = null;
|
||||
}
|
||||
} else if (stat == MapleBuffStat.SUMMON || stat == MapleBuffStat.PUPPET) {
|
||||
int summonId = mbsvh.effect.getSourceId();
|
||||
|
||||
MapleSummon summon = summons.get(summonId);
|
||||
if (summon != null) {
|
||||
getMap().broadcastMessage(MaplePacketCreator.removeSummon(summon, true), summon.getPosition());
|
||||
getMap().removeMapObject(summon);
|
||||
removeVisibleMapObject(summon);
|
||||
summons.remove(summonId);
|
||||
}
|
||||
if (summon.getSkill() == DarkKnight.BEHOLDER) {
|
||||
if (beholderHealingSchedule != null) {
|
||||
beholderHealingSchedule.cancel(false);
|
||||
beholderHealingSchedule = null;
|
||||
}
|
||||
if (beholderBuffSchedule != null) {
|
||||
beholderBuffSchedule.cancel(false);
|
||||
beholderBuffSchedule = null;
|
||||
}
|
||||
}
|
||||
} else if (stat == MapleBuffStat.DRAGONBLOOD) {
|
||||
dragonBloodSchedule.cancel(false);
|
||||
dragonBloodSchedule = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return effectsToCancel;
|
||||
}
|
||||
|
||||
public void disableDoor() {
|
||||
@@ -2015,6 +2031,9 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
expiretask = TimerManager.getInstance().register(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
MapleItemInformationProvider miip = MapleItemInformationProvider.getInstance();
|
||||
boolean deletedCoupon = false;
|
||||
|
||||
long expiration, currenttime = System.currentTimeMillis();
|
||||
Set<Skill> keys = getSkills().keySet();
|
||||
for (Iterator<Skill> i = keys.iterator(); i.hasNext();) {
|
||||
@@ -2038,12 +2057,19 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
} else if (expiration != -1 && expiration < currenttime) {
|
||||
client.announce(MaplePacketCreator.itemExpired(item.getItemId()));
|
||||
toberemove.add(item);
|
||||
if(miip.isRateCoupon(item.getItemId())) {
|
||||
deletedCoupon = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Item item : toberemove) {
|
||||
MapleInventoryManipulator.removeFromSlot(client, inv.getType(), item.getPosition(), item.getQuantity(), true);
|
||||
}
|
||||
toberemove.clear();
|
||||
|
||||
if(deletedCoupon) {
|
||||
updateCouponRates();
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 60000);
|
||||
@@ -2378,10 +2404,6 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
return new ArrayList<>(doors);
|
||||
}
|
||||
|
||||
public int getDropRate() {
|
||||
return dropRate;
|
||||
}
|
||||
|
||||
public int getEnergyBar() {
|
||||
return energybar;
|
||||
}
|
||||
@@ -2405,6 +2427,38 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
public int getExpRate() {
|
||||
return expRate;
|
||||
}
|
||||
|
||||
public int getCouponExpRate() {
|
||||
return expCoupon;
|
||||
}
|
||||
|
||||
public int getRawExpRate() {
|
||||
return expRate / (expCoupon * client.getWorldServer().getExpRate());
|
||||
}
|
||||
|
||||
public int getDropRate() {
|
||||
return dropRate;
|
||||
}
|
||||
|
||||
public int getCouponDropRate() {
|
||||
return dropCoupon;
|
||||
}
|
||||
|
||||
public int getRawDropRate() {
|
||||
return dropRate / (dropCoupon * client.getWorldServer().getDropRate());
|
||||
}
|
||||
|
||||
public int getMesoRate() {
|
||||
return mesoRate;
|
||||
}
|
||||
|
||||
public int getCouponMesoRate() {
|
||||
return mesoCoupon;
|
||||
}
|
||||
|
||||
public int getRawMesoRate() {
|
||||
return mesoRate / (mesoCoupon * client.getWorldServer().getMesoRate());
|
||||
}
|
||||
|
||||
public int getFace() {
|
||||
return face;
|
||||
@@ -2675,10 +2729,6 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
return merchantmeso;
|
||||
}
|
||||
|
||||
public int getMesoRate() {
|
||||
return mesoRate;
|
||||
}
|
||||
|
||||
public int getMesosTraded() {
|
||||
return mesosTraded;
|
||||
}
|
||||
@@ -3511,12 +3561,12 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
for (byte i = 1; i < 5; i++) {
|
||||
gainSlots(i, 4, true);
|
||||
}
|
||||
}
|
||||
|
||||
this.yellowMessage("We see you reached level " + level + ". Congratulations! As a token of your success, your inventory has been expanded a little bit.");
|
||||
|
||||
this.yellowMessage("You reached level " + level + ". Congratulations! As a token of your success, your inventory has been expanded a little bit.");
|
||||
}
|
||||
}
|
||||
if (level % 20 == 0 && ServerConstants.USE_ADD_RATES_BY_LEVEL == true) { //For the drop & meso rate
|
||||
revertPlayerRates();
|
||||
revertLastPlayerRates();
|
||||
setPlayerRates();
|
||||
this.yellowMessage("You managed to get level " + level + "! Getting experience and items seems a little easier now, huh?");
|
||||
}
|
||||
@@ -3626,24 +3676,22 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
}
|
||||
}
|
||||
|
||||
public void setPlayerRates() {
|
||||
public void setPlayerRates() {
|
||||
this.expRate *= GameConstants.getPlayerBonusExpRate(this.level / 20);
|
||||
this.mesoRate *= GameConstants.getPlayerBonusMesoRate(this.level / 20);
|
||||
this.dropRate *= GameConstants.getPlayerBonusDropRate(this.level / 20);
|
||||
}
|
||||
|
||||
public void revertPlayerRates() {
|
||||
public void revertLastPlayerRates() {
|
||||
this.expRate /= GameConstants.getPlayerBonusExpRate((this.level - 1) / 20);
|
||||
this.mesoRate /= GameConstants.getPlayerBonusMesoRate((this.level - 1) / 20);
|
||||
this.dropRate /= GameConstants.getPlayerBonusDropRate((this.level - 1) / 20);
|
||||
}
|
||||
|
||||
public void revertWorldRates() {
|
||||
World worldz = Server.getInstance().getWorld(world);
|
||||
|
||||
this.expRate /= worldz.getExpRate();
|
||||
this.mesoRate /= worldz.getMesoRate();
|
||||
this.dropRate /= worldz.getDropRate();
|
||||
public void revertPlayerRates() {
|
||||
this.expRate /= GameConstants.getPlayerBonusExpRate(this.level / 20);
|
||||
this.mesoRate /= GameConstants.getPlayerBonusMesoRate(this.level / 20);
|
||||
this.dropRate /= GameConstants.getPlayerBonusDropRate(this.level / 20);
|
||||
}
|
||||
|
||||
public void setWorldRates() {
|
||||
@@ -3653,13 +3701,30 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
this.dropRate *= worldz.getDropRate();
|
||||
}
|
||||
|
||||
public void revertCouponRates() {
|
||||
public void revertWorldRates() {
|
||||
World worldz = Server.getInstance().getWorld(world);
|
||||
this.expRate /= worldz.getExpRate();
|
||||
this.mesoRate /= worldz.getMesoRate();
|
||||
this.dropRate /= worldz.getDropRate();
|
||||
}
|
||||
|
||||
private void setCouponRates() {
|
||||
setActiveCoupons();
|
||||
activateCouponsEffects();
|
||||
}
|
||||
|
||||
private void revertCouponRates() {
|
||||
revertCouponsEffects();
|
||||
}
|
||||
|
||||
public void setCouponRates() {
|
||||
setActiveCoupons();
|
||||
activateCouponsEffects();
|
||||
public void updateCouponRates() {
|
||||
try {
|
||||
couponLock.lock();
|
||||
revertCouponRates();
|
||||
setCouponRates();
|
||||
} finally {
|
||||
couponLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void resetPlayerRates() {
|
||||
@@ -4508,6 +4573,8 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
}, buffInterval, buffInterval);
|
||||
}
|
||||
} else if (effect.isRecovery()) {
|
||||
int healInterval = (ServerConstants.USE_ULTRA_RECOVERY) ? 2500 : 5000;
|
||||
|
||||
final byte heal = (byte) effect.getX();
|
||||
recoveryTask = TimerManager.getInstance().register(new Runnable() {
|
||||
@Override
|
||||
@@ -4516,12 +4583,12 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
client.announce(MaplePacketCreator.showOwnRecovery(heal));
|
||||
getMap().broadcastMessage(MapleCharacter.this, MaplePacketCreator.showRecovery(id, heal), false);
|
||||
}
|
||||
}, 5000, 5000);
|
||||
}, healInterval, healInterval);
|
||||
}
|
||||
|
||||
//is it possible to maintain a list of statup effects of the same type concurrently? Pair<MapleBuffStat, Itemid>
|
||||
for (Pair<MapleBuffStat, Integer> statup : effect.getStatups()) {
|
||||
effects.put(statup.getLeft(), new MapleBuffStatValueHolder(effect, starttime, schedule, statup.getRight().intValue()));
|
||||
effects.put(statup.getLeft(), new MapleBuffStatValueHolder(effect, starttime, schedule, statup.getRight()));
|
||||
}
|
||||
recalcLocalStats();
|
||||
}
|
||||
|
||||
@@ -522,19 +522,22 @@ public class Commands {
|
||||
|
||||
player.yellowMessage("DROP RATE");
|
||||
player.message(">>Base DROP Rate: " + c.getWorldServer().getDropRate() + "x");
|
||||
player.message(">>Your DROP Rate: " + player.getDropRate() / c.getWorldServer().getDropRate() + "x");
|
||||
player.message(">>Your DROP Rate: " + player.getRawDropRate() + "x");
|
||||
if(player.getCouponDropRate() != 1) player.message(">>Your Coupon DROP Rate: " + player.getCouponDropRate() + "x");
|
||||
player.message(">>------------------------------------------------");
|
||||
player.message(">>Total DROP Rate: " + player.getDropRate() + "x");
|
||||
|
||||
player.yellowMessage("MESO RATE");
|
||||
player.message(">>Base MESO Rate: " + c.getWorldServer().getMesoRate() + "x");
|
||||
player.message(">>Your MESO Rate: " + player.getMesoRate() / c.getWorldServer().getMesoRate() + "x");
|
||||
player.message(">>Your MESO Rate: " + player.getRawMesoRate() + "x");
|
||||
if(player.getCouponMesoRate() != 1) player.message(">>Your Coupon MESO Rate: " + player.getCouponMesoRate() + "x");
|
||||
player.message(">>------------------------------------------------");
|
||||
player.message(">>Total MESO Rate: " + player.getMesoRate() + "x");
|
||||
|
||||
player.yellowMessage("EXP RATE");
|
||||
player.message(">>Base EXP Rate: " + c.getWorldServer().getExpRate() + "x");
|
||||
player.message(">>Your EXP Rate: " + player.getExpRate() / c.getWorldServer().getExpRate() + "x");
|
||||
player.message(">>Your EXP Rate: " + player.getRawExpRate() + "x");
|
||||
if(player.getCouponExpRate() != 1) player.message(">>Your Coupon EXP Rate: " + player.getCouponExpRate() + "x");
|
||||
player.message(">>------------------------------------------------");
|
||||
player.message(">>Total EXP Rate: " + player.getExpRate() + "x");
|
||||
/*if(c.getWorldServer().getExpRate() > ServerConstants.EXP_RATE) {
|
||||
@@ -1386,8 +1389,12 @@ public class Commands {
|
||||
return true;
|
||||
}
|
||||
|
||||
player.setLevel(Integer.parseInt(sub[1]) - 1);
|
||||
player.loseExp(player.getExp(), false, false);
|
||||
player.loseExp(player.getExp(), false, false);
|
||||
|
||||
player.revertPlayerRates();
|
||||
player.setLevel(Math.min(Integer.parseInt(sub[1]), player.getMaxLevel()) - 1);
|
||||
player.setPlayerRates();
|
||||
|
||||
player.levelUp(false);
|
||||
} else if (sub[0].equals("levelpro")) {
|
||||
if (sub.length < 2){
|
||||
@@ -1402,7 +1409,9 @@ public class Commands {
|
||||
final String[] s = {"setall", String.valueOf(Short.MAX_VALUE)};
|
||||
executeGMCommand(c, s, heading);
|
||||
player.loseExp(player.getExp(), false, false);
|
||||
player.revertPlayerRates();
|
||||
player.setLevel(255);
|
||||
player.setPlayerRates();
|
||||
player.setFame(13337);
|
||||
player.setMaxHp(30000);
|
||||
player.setMaxMp(30000);
|
||||
@@ -1410,8 +1419,6 @@ public class Commands {
|
||||
player.updateSingleStat(MapleStat.FAME, 13337);
|
||||
player.updateSingleStat(MapleStat.MAXHP, 30000);
|
||||
player.updateSingleStat(MapleStat.MAXMP, 30000);
|
||||
player.revertPlayerRates();
|
||||
player.setPlayerRates();
|
||||
player.yellowMessage("Stats maxed out.");
|
||||
} else if (sub[0].equals("maxskills")) {
|
||||
for (MapleData skill_ : MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/" + "String.wz")).getData("Skill.img").getChildren()) {
|
||||
|
||||
@@ -199,8 +199,7 @@ public class MapleInventory implements Iterable<Item> {
|
||||
inventory.put(slot, item);
|
||||
|
||||
if(MapleItemInformationProvider.getInstance().isRateCoupon(item.getItemId())) {
|
||||
owner.revertCouponRates();
|
||||
owner.setCouponRates();
|
||||
owner.updateCouponRates();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,8 +207,7 @@ public class MapleInventory implements Iterable<Item> {
|
||||
Item item = inventory.remove(slot);
|
||||
|
||||
if(item != null && MapleItemInformationProvider.getInstance().isRateCoupon(item.getItemId())) {
|
||||
owner.revertCouponRates();
|
||||
owner.setCouponRates();
|
||||
owner.updateCouponRates();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ public class ServerConstants {
|
||||
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;
|
||||
public static final boolean USE_FAMILY_SYSTEM = false;
|
||||
public static final boolean USE_PERMISSIVE_BUFFS = true; //WARNING: Allows players that does not have increased certain buff-type skills to use it's effect. Used mainly on buff-cast commands, however making this active may generate a source for possible client-edited exploits.
|
||||
public static final boolean USE_PERMISSIVE_BUFFS = false; //WARNING: Allows players that does not have increased certain buff-type skills to use it's effect. Used mainly on buff-cast commands, however making this active may generate a source for possible client-edited exploits.
|
||||
public static final boolean USE_DUEY = true;
|
||||
public static final boolean USE_ITEM_SORT = true;
|
||||
public static final boolean USE_ITEM_SORT_BY_NAME = false; //Item sorting based on name rather than id.
|
||||
|
||||
@@ -19,21 +19,11 @@
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.server;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import constants.ServerConstants;
|
||||
import tools.DatabaseConnection;
|
||||
|
||||
import net.server.world.World;
|
||||
import client.MapleCharacter;
|
||||
import tools.FilePrinter;
|
||||
|
||||
/**
|
||||
* @author Ronan
|
||||
@@ -46,7 +36,7 @@ public class CouponWorker implements Runnable {
|
||||
Server.getInstance().updateActiveCoupons();
|
||||
Server.getInstance().commitActiveCoupons();
|
||||
} catch(SQLException sqle) {
|
||||
sqle.printStackTrace();
|
||||
FilePrinter.printError(FilePrinter.EXCEPTION_CAUGHT, "Unexpected SQL error: " + sqle.getMessage() + "\n\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,8 +167,7 @@ public class Server implements Runnable {
|
||||
for(MapleCharacter chr: world.getPlayerStorage().getAllCharacters()) {
|
||||
if(!chr.isLoggedin()) continue;
|
||||
|
||||
chr.revertCouponRates();
|
||||
chr.setCouponRates();
|
||||
chr.updateCouponRates();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,21 +32,21 @@ import client.MapleClient;
|
||||
* @author Matze
|
||||
*/
|
||||
public final class MesoDropHandler extends AbstractMaplePacketHandler {//FIX
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
MapleCharacter player = c.getPlayer();
|
||||
if (!player.isAlive()) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
MapleCharacter player = c.getPlayer();
|
||||
if (!player.isAlive()) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
if (!player.canDropMeso()){
|
||||
player.announce(MaplePacketCreator.serverNotice(5, "Fast meso drop has been patched, cut that out. ;)"));
|
||||
return;
|
||||
}
|
||||
slea.skip(4);
|
||||
int meso = slea.readInt();
|
||||
if (meso <= player.getMeso() && meso > 9 && meso < 50001) {
|
||||
player.gainMeso(-meso, false, true, false);
|
||||
player.getMap().spawnMesoDrop(meso, player.getPosition(), player, player, true, (byte) 2);
|
||||
}
|
||||
}
|
||||
if (!player.canDropMeso()){
|
||||
player.announce(MaplePacketCreator.serverNotice(5, "Fast meso drop has been patched, cut that out. ;)"));
|
||||
return;
|
||||
}
|
||||
slea.skip(4);
|
||||
int meso = slea.readInt();
|
||||
if (meso <= player.getMeso() && meso > 9 && meso < 50001) {
|
||||
player.gainMeso(-meso, false, true, false);
|
||||
player.getMap().spawnMesoDrop(meso, player.getPosition(), player, player, true, (byte) 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -269,11 +269,10 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
if (player.getMap().getHPDec() > 0) player.resetHpDecreaseTask();
|
||||
|
||||
player.dispelBuffCoupons();
|
||||
player.resetPlayerRates();
|
||||
|
||||
if(ServerConstants.USE_ADD_RATES_BY_LEVEL == true) player.setPlayerRates();
|
||||
player.setWorldRates();
|
||||
player.setCouponRates();
|
||||
player.updateCouponRates();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,9 +32,10 @@ import constants.ServerConstants;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.Set;
|
||||
@@ -114,12 +115,15 @@ public class World {
|
||||
}
|
||||
|
||||
public void setExpRate(int exp) {
|
||||
//System.out.println("Setting server EXP Rate to " + exp * ServerConstants.EXP_RATE + "x.");
|
||||
for(MapleCharacter chr : getPlayerStorage().getAllCharacters()) {
|
||||
List<MapleCharacter> list = new LinkedList<>(getPlayerStorage().getAllCharacters());
|
||||
|
||||
for(MapleCharacter chr : list) {
|
||||
if(!chr.isLoggedin()) continue;
|
||||
chr.revertWorldRates();
|
||||
}
|
||||
this.exprate = exp;
|
||||
for(MapleCharacter chr : getPlayerStorage().getAllCharacters()) {
|
||||
for(MapleCharacter chr : list) {
|
||||
if(!chr.isLoggedin()) continue;
|
||||
chr.setWorldRates();
|
||||
}
|
||||
}
|
||||
@@ -129,11 +133,15 @@ public class World {
|
||||
}
|
||||
|
||||
public void setDropRate(int drop) {
|
||||
for(MapleCharacter chr : getPlayerStorage().getAllCharacters()) {
|
||||
List<MapleCharacter> list = new LinkedList<>(getPlayerStorage().getAllCharacters());
|
||||
|
||||
for(MapleCharacter chr : list) {
|
||||
if(!chr.isLoggedin()) continue;
|
||||
chr.revertWorldRates();
|
||||
}
|
||||
this.droprate = drop;
|
||||
for(MapleCharacter chr : getPlayerStorage().getAllCharacters()) {
|
||||
for(MapleCharacter chr : list) {
|
||||
if(!chr.isLoggedin()) continue;
|
||||
chr.setWorldRates();
|
||||
}
|
||||
}
|
||||
@@ -143,11 +151,15 @@ public class World {
|
||||
}
|
||||
|
||||
public void setMesoRate(int meso) {
|
||||
for(MapleCharacter chr : getPlayerStorage().getAllCharacters()) {
|
||||
List<MapleCharacter> list = new LinkedList<>(getPlayerStorage().getAllCharacters());
|
||||
|
||||
for(MapleCharacter chr : list) {
|
||||
if(!chr.isLoggedin()) continue;
|
||||
chr.revertWorldRates();
|
||||
}
|
||||
this.mesorate = meso;
|
||||
for(MapleCharacter chr : getPlayerStorage().getAllCharacters()) {
|
||||
for(MapleCharacter chr : list) {
|
||||
if(!chr.isLoggedin()) continue;
|
||||
chr.setWorldRates();
|
||||
}
|
||||
}
|
||||
@@ -157,13 +169,7 @@ public class World {
|
||||
}
|
||||
|
||||
public void setBossDropRate(int bossdrop) {
|
||||
for(MapleCharacter chr : getPlayerStorage().getAllCharacters()) {
|
||||
chr.revertWorldRates();
|
||||
}
|
||||
this.bossdroprate = bossdrop;
|
||||
for(MapleCharacter chr : getPlayerStorage().getAllCharacters()) {
|
||||
chr.setWorldRates();
|
||||
}
|
||||
}
|
||||
|
||||
public PlayerStorage getPlayerStorage() {
|
||||
|
||||
@@ -223,6 +223,40 @@ public class MapleStatEffect {
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.JUMP, Integer.valueOf(ret.jump));
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.PYRAMID_PQ, Integer.valueOf(ret.berserk));
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.BOOSTER, Integer.valueOf(ret.booster));
|
||||
|
||||
if(MapleItemInformationProvider.getInstance().isRateCoupon(sourceid)) {
|
||||
switch(MapleDataTool.getInt("expR", source, 0)) {
|
||||
case 1:
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.COUPON_EXP1, 1);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.COUPON_EXP2, 1);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.COUPON_EXP3, 1);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.COUPON_EXP4, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
switch(MapleDataTool.getInt("drpR", source, 0)) {
|
||||
case 1:
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.COUPON_DRP1, 1);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.COUPON_DRP2, 1);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.COUPON_DRP3, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
MapleData ltd = source.getChildByPath("lt");
|
||||
if (ltd != null) {
|
||||
@@ -928,7 +962,7 @@ public class MapleStatEffect {
|
||||
}
|
||||
|
||||
private void applyBuffEffect(MapleCharacter applyfrom, MapleCharacter applyto, boolean primary) {
|
||||
if (!isMonsterRiding()) {
|
||||
if (!isMonsterRiding() && !isCouponBuff()) {
|
||||
applyto.cancelEffect(this, true, -1);
|
||||
}
|
||||
|
||||
@@ -1253,6 +1287,10 @@ public class MapleStatEffect {
|
||||
return skill && sourceid == ChiefBandit.CHAKRA;
|
||||
}
|
||||
|
||||
private boolean isCouponBuff() {
|
||||
return MapleItemInformationProvider.getInstance().isRateCoupon(sourceid);
|
||||
}
|
||||
|
||||
public boolean isMonsterRiding() {
|
||||
return skill && (sourceid % 10000000 == 1004 || sourceid == Corsair.BATTLE_SHIP || sourceid == Beginner.SPACESHIP || sourceid == Noblesse.SPACESHIP
|
||||
|| sourceid == Beginner.YETI_MOUNT1 || sourceid == Beginner.YETI_MOUNT2 || sourceid == Beginner.WITCH_BROOMSTICK || sourceid == Beginner.BALROG_MOUNT
|
||||
|
||||
Reference in New Issue
Block a user