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:
ronancpl
2017-06-19 17:44:01 -03:00
parent 42fe74955d
commit 7f6d420cf1
58 changed files with 345 additions and 220 deletions

View File

@@ -1,4 +1,4 @@
#Sun, 18 Jun 2017 02:53:19 -0300 #Mon, 19 Jun 2017 14:48:35 -0300
C\:\\Nexon\\MapleSolaxia\\MapleSolaxiaV2= C\:\\Nexon\\MapleSolaxia\\MapleSolaxiaV2=

BIN
dist/MapleSolaxia.jar vendored

Binary file not shown.

View File

@@ -320,4 +320,13 @@ Corre
15 - 17 Junho 2017, 15 - 17 Junho 2017,
Correção de bug na função de atribuição de EXP, que não permitia receber valores negativos de EXP. Correção de bug na função de atribuição de EXP, que não permitia receber valores negativos de EXP.
Implementação da GPQ. Implementação da GPQ.
18 Junho 2017,
Correção de problema de concorrência referente às alterações nos rates do server.
Consertado bugs referentes ao comando "level", não reatribuindo rates apropriadamente.
19 Junho 2017,
Consertado cupons não aparecendo apropriadamente na região de buffs.
Consertado alguns problemas de concorrência com cupons.
Consertado alguns problemas de concorrência com character buffs.

View File

@@ -12,15 +12,18 @@
</editor-bookmarks> </editor-bookmarks>
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2"> <open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
<group> <group>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/event/GuildQuest.js</file> <file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/TimerManager.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/npc/9040009.js</file> <file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/channel/handlers/PlayerLoggedinHandler.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/channel/handlers/ChangeMapHandler.java</file> <file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/client/command/Commands.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/npc/9040006.js</file> <file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/MapleStatEffect.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/reactor/2006001.js</file> <file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/Server.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/reactor/9208009.js</file> <file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/CouponWorker.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/client/MapleBuffStat.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/constants/ServerConstants.java</file> <file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/constants/ServerConstants.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/client/MapleCharacter.java</file> <file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/client/MapleCharacter.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/npc/9040001.js</file> <file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/MapleItemInformationProvider.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/client/inventory/MapleInventory.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/tools/MaplePacketCreator.java</file>
</group> </group>
</open-files> </open-files>
</project-private> </project-private>

View File

@@ -62,8 +62,11 @@ function action(mode, type, selection) {
cm.dispose(); cm.dispose();
} }
} else if (status == 3) { } else if (status == 3) {
if (cm.haveItem(4031801)) if (cm.haveItem(4031801)) {
cm.gainItem(4031801, -1); cm.gainItem(4031801, -1);
} else {
cm.gainMeso(-150);
}
cm.warp(104000000); cm.warp(104000000);
cm.dispose(); cm.dispose();
} }

View File

@@ -25,7 +25,7 @@ function start() {
function action(mode, type, selection) { function action(mode, type, selection) {
if(mode == 1) { if(mode == 1) {
cm.warp(990001100); cm.warp(101030104);
} }
cm.dispose(); cm.dispose();
} }

View File

@@ -22,42 +22,48 @@
package client; package client;
public enum MapleBuffStat { public enum MapleBuffStat {
//SLOW(0x1), //SLOW(0x1L),
MORPH(0x2), MORPH(0x2L),
RECOVERY(0x4), RECOVERY(0x4L),
MAPLE_WARRIOR(0x8), MAPLE_WARRIOR(0x8L),
STANCE(0x10), STANCE(0x10L),
SHARP_EYES(0x20), SHARP_EYES(0x20L),
MANA_REFLECTION(0x40), MANA_REFLECTION(0x40L),
//ALWAYS_RIGHT(0X80), //ALWAYS_RIGHT(0X80L),
//------ bgn EDITED SLOT (was unused before) -------- //------ bgn EDITED SLOT (was unused before) --------
MAP_PROTECTION(0x100000000000000L), MAP_PROTECTION(0x100000000000000L),
//------ end EDITED SLOT ---------------------------- //------ end EDITED SLOT ----------------------------
SHADOW_CLAW(0x100), SHADOW_CLAW(0x100L),
INFINITY(0x200), INFINITY(0x200L),
HOLY_SHIELD(0x400), HOLY_SHIELD(0x400L),
HAMSTRING(0x800), HAMSTRING(0x800L),
BLIND(0x1000), BLIND(0x1000L),
CONCENTRATE(0x2000), CONCENTRATE(0x2000L),
//4000 //4000L
ECHO_OF_HERO(0x8000), ECHO_OF_HERO(0x8000L),
//10000 //10000L
GHOST_MORPH(0x20000), GHOST_MORPH(0x20000L),
AURA(0x40000), AURA(0x40000L),
CONFUSE(0x80000), CONFUSE(0x80000L),
//100000
//200000 // ---- COUPON feature (was unused anyway) ----
//400000
//800000 COUPON_EXP1(0x100000L),
//1000000 COUPON_EXP2(0x200000L),
//2000000 COUPON_EXP3(0x400000L),
//4000000 COUPON_EXP4(0x800000L),
BERSERK_FURY(0x8000000), COUPON_DRP1(0x1000000L),
DIVINE_BODY(0x10000000), COUPON_DRP2(0x2000000L),
COUPON_DRP3(0x4000000L),
// ---- end COUPON feature ----
BERSERK_FURY(0x8000000L),
DIVINE_BODY(0x10000000L),
SPARK(0x20000000L), SPARK(0x20000000L),
//40000000 //40000000L
FINALATTACK(0x80000000L), FINALATTACK(0x80000000L),
BATTLESHIP(0xA00000040L), // weird one BATTLESHIP(0xA00000040L), // weird one
WATK(0x100000000L), WATK(0x100000000L),

View File

@@ -46,6 +46,8 @@ import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
//import java.util.TimeZone; //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.ScheduledFuture;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@@ -257,6 +259,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
private ScheduledFuture<?> expiretask; private ScheduledFuture<?> expiretask;
private ScheduledFuture<?> recoveryTask; private ScheduledFuture<?> recoveryTask;
private List<ScheduledFuture<?>> timers = new ArrayList<>(); private List<ScheduledFuture<?>> timers = new ArrayList<>();
private Lock couponLock = new ReentrantLock();
private NumberFormat nf = new DecimalFormat("#,###,###,###"); private NumberFormat nf = new DecimalFormat("#,###,###,###");
private ArrayList<Integer> excluded = new ArrayList<>(); private ArrayList<Integer> excluded = new ArrayList<>();
private MonsterBook monsterbook; 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); List<MapleBuffStat> buffStatList = Arrays.asList(stat);
deregisterBuffStats(buffStatList); dropBuffStats(deregisterBuffStats(buffStatList));
cancelPlayerBuffs(buffStatList); cancelPlayerBuffs(buffStatList);
} }
@@ -789,7 +792,15 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
cancelEffect(MapleItemInformationProvider.getInstance().getItemEffect(itemId), false, -1); 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; List<MapleBuffStat> buffstats;
if (!overwrite) { if (!overwrite) {
buffstats = getBuffStats(effect, startTime); buffstats = getBuffStats(effect, startTime);
@@ -800,7 +811,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
buffstats.add(statup.getLeft()); buffstats.add(statup.getLeft());
} }
} }
deregisterBuffStats(buffstats); List<MapleBuffStatValueHolder> toCancel = deregisterBuffStats(buffstats);
if (effect.isMagicDoor()) { if (effect.isMagicDoor()) {
if (!getDoors().isEmpty()) { if (!getDoors().isEmpty()) {
MapleDoor door = getDoors().iterator().next(); MapleDoor door = getDoors().iterator().next();
@@ -842,6 +853,8 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
if (!overwrite) { if (!overwrite) {
cancelPlayerBuffs(buffstats); cancelPlayerBuffs(buffstats);
} }
return toCancel;
} }
public void cancelEffectFromBuffStat(MapleBuffStat stat) { public void cancelEffectFromBuffStat(MapleBuffStat stat) {
@@ -1745,60 +1758,63 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
} }
} }
private void deregisterBuffStats(List<MapleBuffStat> stats) { private void dropBuffStats(List<MapleBuffStatValueHolder> effectsToCancel) {
synchronized (stats) { for (MapleBuffStatValueHolder cancelEffectCancelTasks : effectsToCancel) {
List<MapleBuffStatValueHolder> effectsToCancel = new ArrayList<>(stats.size()); if (cancelEffectCancelTasks.schedule != null) {
for (MapleBuffStat stat : stats) { cancelEffectCancelTasks.schedule.cancel(false);
MapleBuffStatValueHolder mbsvh = effects.get(stat); this.cancelEffect(cancelEffectCancelTasks.effect, false, -1, false);
if (mbsvh != null) { }
effects.remove(stat); }
boolean addMbsvh = true; }
for (MapleBuffStatValueHolder contained : effectsToCancel) {
if (mbsvh.startTime == contained.startTime && contained.effect == mbsvh.effect) { private List<MapleBuffStatValueHolder> deregisterBuffStats(List<MapleBuffStat> stats) {
addMbsvh = false; List<MapleBuffStatValueHolder> effectsToCancel = new ArrayList<>(stats.size());
} for (MapleBuffStat stat : stats) {
} MapleBuffStatValueHolder mbsvh = effects.get(stat);
if (addMbsvh) { if (mbsvh != null) {
effectsToCancel.add(mbsvh); effects.remove(stat);
} boolean addMbsvh = true;
if (stat == MapleBuffStat.RECOVERY) { for (MapleBuffStatValueHolder contained : effectsToCancel) {
if (recoveryTask != null) { if (mbsvh.startTime == contained.startTime && contained.effect == mbsvh.effect) {
recoveryTask.cancel(false); addMbsvh = 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;
} }
} }
} if (addMbsvh) {
for (MapleBuffStatValueHolder cancelEffectCancelTasks : effectsToCancel) { effectsToCancel.add(mbsvh);
if (cancelEffectCancelTasks.schedule != null) { }
cancelEffectCancelTasks.schedule.cancel(false); if (stat == MapleBuffStat.RECOVERY) {
this.cancelEffect(cancelEffectCancelTasks.effect, false, -1); 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() { public void disableDoor() {
@@ -2015,6 +2031,9 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
expiretask = TimerManager.getInstance().register(new Runnable() { expiretask = TimerManager.getInstance().register(new Runnable() {
@Override @Override
public void run() { public void run() {
MapleItemInformationProvider miip = MapleItemInformationProvider.getInstance();
boolean deletedCoupon = false;
long expiration, currenttime = System.currentTimeMillis(); long expiration, currenttime = System.currentTimeMillis();
Set<Skill> keys = getSkills().keySet(); Set<Skill> keys = getSkills().keySet();
for (Iterator<Skill> i = keys.iterator(); i.hasNext();) { for (Iterator<Skill> i = keys.iterator(); i.hasNext();) {
@@ -2038,12 +2057,19 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
} else if (expiration != -1 && expiration < currenttime) { } else if (expiration != -1 && expiration < currenttime) {
client.announce(MaplePacketCreator.itemExpired(item.getItemId())); client.announce(MaplePacketCreator.itemExpired(item.getItemId()));
toberemove.add(item); toberemove.add(item);
if(miip.isRateCoupon(item.getItemId())) {
deletedCoupon = true;
}
} }
} }
for (Item item : toberemove) { for (Item item : toberemove) {
MapleInventoryManipulator.removeFromSlot(client, inv.getType(), item.getPosition(), item.getQuantity(), true); MapleInventoryManipulator.removeFromSlot(client, inv.getType(), item.getPosition(), item.getQuantity(), true);
} }
toberemove.clear(); toberemove.clear();
if(deletedCoupon) {
updateCouponRates();
}
} }
} }
}, 60000); }, 60000);
@@ -2378,10 +2404,6 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
return new ArrayList<>(doors); return new ArrayList<>(doors);
} }
public int getDropRate() {
return dropRate;
}
public int getEnergyBar() { public int getEnergyBar() {
return energybar; return energybar;
} }
@@ -2405,6 +2427,38 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
public int getExpRate() { public int getExpRate() {
return expRate; 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() { public int getFace() {
return face; return face;
@@ -2675,10 +2729,6 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
return merchantmeso; return merchantmeso;
} }
public int getMesoRate() {
return mesoRate;
}
public int getMesosTraded() { public int getMesosTraded() {
return mesosTraded; return mesosTraded;
} }
@@ -3511,12 +3561,12 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
for (byte i = 1; i < 5; i++) { for (byte i = 1; i < 5; i++) {
gainSlots(i, 4, true); gainSlots(i, 4, true);
} }
}
this.yellowMessage("You reached level " + level + ". Congratulations! As a token of your success, your inventory has been expanded a little bit.");
this.yellowMessage("We see 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 if (level % 20 == 0 && ServerConstants.USE_ADD_RATES_BY_LEVEL == true) { //For the drop & meso rate
revertPlayerRates(); revertLastPlayerRates();
setPlayerRates(); setPlayerRates();
this.yellowMessage("You managed to get level " + level + "! Getting experience and items seems a little easier now, huh?"); 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.expRate *= GameConstants.getPlayerBonusExpRate(this.level / 20);
this.mesoRate *= GameConstants.getPlayerBonusMesoRate(this.level / 20); this.mesoRate *= GameConstants.getPlayerBonusMesoRate(this.level / 20);
this.dropRate *= GameConstants.getPlayerBonusDropRate(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.expRate /= GameConstants.getPlayerBonusExpRate((this.level - 1) / 20);
this.mesoRate /= GameConstants.getPlayerBonusMesoRate((this.level - 1) / 20); this.mesoRate /= GameConstants.getPlayerBonusMesoRate((this.level - 1) / 20);
this.dropRate /= GameConstants.getPlayerBonusDropRate((this.level - 1) / 20); this.dropRate /= GameConstants.getPlayerBonusDropRate((this.level - 1) / 20);
} }
public void revertWorldRates() { public void revertPlayerRates() {
World worldz = Server.getInstance().getWorld(world); this.expRate /= GameConstants.getPlayerBonusExpRate(this.level / 20);
this.mesoRate /= GameConstants.getPlayerBonusMesoRate(this.level / 20);
this.expRate /= worldz.getExpRate(); this.dropRate /= GameConstants.getPlayerBonusDropRate(this.level / 20);
this.mesoRate /= worldz.getMesoRate();
this.dropRate /= worldz.getDropRate();
} }
public void setWorldRates() { public void setWorldRates() {
@@ -3653,13 +3701,30 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
this.dropRate *= worldz.getDropRate(); 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(); revertCouponsEffects();
} }
public void setCouponRates() { public void updateCouponRates() {
setActiveCoupons(); try {
activateCouponsEffects(); couponLock.lock();
revertCouponRates();
setCouponRates();
} finally {
couponLock.unlock();
}
} }
public void resetPlayerRates() { public void resetPlayerRates() {
@@ -4508,6 +4573,8 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}, buffInterval, buffInterval); }, buffInterval, buffInterval);
} }
} else if (effect.isRecovery()) { } else if (effect.isRecovery()) {
int healInterval = (ServerConstants.USE_ULTRA_RECOVERY) ? 2500 : 5000;
final byte heal = (byte) effect.getX(); final byte heal = (byte) effect.getX();
recoveryTask = TimerManager.getInstance().register(new Runnable() { recoveryTask = TimerManager.getInstance().register(new Runnable() {
@Override @Override
@@ -4516,12 +4583,12 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
client.announce(MaplePacketCreator.showOwnRecovery(heal)); client.announce(MaplePacketCreator.showOwnRecovery(heal));
getMap().broadcastMessage(MapleCharacter.this, MaplePacketCreator.showRecovery(id, heal), false); 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> //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()) { 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(); recalcLocalStats();
} }

View File

@@ -522,19 +522,22 @@ public class Commands {
player.yellowMessage("DROP RATE"); player.yellowMessage("DROP RATE");
player.message(">>Base DROP Rate: " + c.getWorldServer().getDropRate() + "x"); 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(">>------------------------------------------------");
player.message(">>Total DROP Rate: " + player.getDropRate() + "x"); player.message(">>Total DROP Rate: " + player.getDropRate() + "x");
player.yellowMessage("MESO RATE"); player.yellowMessage("MESO RATE");
player.message(">>Base MESO Rate: " + c.getWorldServer().getMesoRate() + "x"); 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(">>------------------------------------------------");
player.message(">>Total MESO Rate: " + player.getMesoRate() + "x"); player.message(">>Total MESO Rate: " + player.getMesoRate() + "x");
player.yellowMessage("EXP RATE"); player.yellowMessage("EXP RATE");
player.message(">>Base EXP Rate: " + c.getWorldServer().getExpRate() + "x"); 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(">>------------------------------------------------");
player.message(">>Total EXP Rate: " + player.getExpRate() + "x"); player.message(">>Total EXP Rate: " + player.getExpRate() + "x");
/*if(c.getWorldServer().getExpRate() > ServerConstants.EXP_RATE) { /*if(c.getWorldServer().getExpRate() > ServerConstants.EXP_RATE) {
@@ -1386,8 +1389,12 @@ public class Commands {
return true; 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); player.levelUp(false);
} else if (sub[0].equals("levelpro")) { } else if (sub[0].equals("levelpro")) {
if (sub.length < 2){ if (sub.length < 2){
@@ -1402,7 +1409,9 @@ public class Commands {
final String[] s = {"setall", String.valueOf(Short.MAX_VALUE)}; final String[] s = {"setall", String.valueOf(Short.MAX_VALUE)};
executeGMCommand(c, s, heading); executeGMCommand(c, s, heading);
player.loseExp(player.getExp(), false, false); player.loseExp(player.getExp(), false, false);
player.revertPlayerRates();
player.setLevel(255); player.setLevel(255);
player.setPlayerRates();
player.setFame(13337); player.setFame(13337);
player.setMaxHp(30000); player.setMaxHp(30000);
player.setMaxMp(30000); player.setMaxMp(30000);
@@ -1410,8 +1419,6 @@ public class Commands {
player.updateSingleStat(MapleStat.FAME, 13337); player.updateSingleStat(MapleStat.FAME, 13337);
player.updateSingleStat(MapleStat.MAXHP, 30000); player.updateSingleStat(MapleStat.MAXHP, 30000);
player.updateSingleStat(MapleStat.MAXMP, 30000); player.updateSingleStat(MapleStat.MAXMP, 30000);
player.revertPlayerRates();
player.setPlayerRates();
player.yellowMessage("Stats maxed out."); player.yellowMessage("Stats maxed out.");
} else if (sub[0].equals("maxskills")) { } else if (sub[0].equals("maxskills")) {
for (MapleData skill_ : MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/" + "String.wz")).getData("Skill.img").getChildren()) { for (MapleData skill_ : MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/" + "String.wz")).getData("Skill.img").getChildren()) {

View File

@@ -199,8 +199,7 @@ public class MapleInventory implements Iterable<Item> {
inventory.put(slot, item); inventory.put(slot, item);
if(MapleItemInformationProvider.getInstance().isRateCoupon(item.getItemId())) { if(MapleItemInformationProvider.getInstance().isRateCoupon(item.getItemId())) {
owner.revertCouponRates(); owner.updateCouponRates();
owner.setCouponRates();
} }
} }
@@ -208,8 +207,7 @@ public class MapleInventory implements Iterable<Item> {
Item item = inventory.remove(slot); Item item = inventory.remove(slot);
if(item != null && MapleItemInformationProvider.getInstance().isRateCoupon(item.getItemId())) { if(item != null && MapleItemInformationProvider.getInstance().isRateCoupon(item.getItemId())) {
owner.revertCouponRates(); owner.updateCouponRates();
owner.setCouponRates();
} }
} }

View File

@@ -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_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_MTS = false;
public static final boolean USE_FAMILY_SYSTEM = 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_DUEY = true;
public static final boolean USE_ITEM_SORT = 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. public static final boolean USE_ITEM_SORT_BY_NAME = false; //Item sorting based on name rather than id.

View File

@@ -19,21 +19,11 @@
You should have received a copy of the GNU Affero General Public License 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/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package net.server; 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 java.sql.SQLException;
import tools.FilePrinter;
import constants.ServerConstants;
import tools.DatabaseConnection;
import net.server.world.World;
import client.MapleCharacter;
/** /**
* @author Ronan * @author Ronan
@@ -46,7 +36,7 @@ public class CouponWorker implements Runnable {
Server.getInstance().updateActiveCoupons(); Server.getInstance().updateActiveCoupons();
Server.getInstance().commitActiveCoupons(); Server.getInstance().commitActiveCoupons();
} catch(SQLException sqle) { } catch(SQLException sqle) {
sqle.printStackTrace(); FilePrinter.printError(FilePrinter.EXCEPTION_CAUGHT, "Unexpected SQL error: " + sqle.getMessage() + "\n\n");
} }
} }
} }

View File

@@ -167,8 +167,7 @@ public class Server implements Runnable {
for(MapleCharacter chr: world.getPlayerStorage().getAllCharacters()) { for(MapleCharacter chr: world.getPlayerStorage().getAllCharacters()) {
if(!chr.isLoggedin()) continue; if(!chr.isLoggedin()) continue;
chr.revertCouponRates(); chr.updateCouponRates();
chr.setCouponRates();
} }
} }
} }

View File

@@ -32,21 +32,21 @@ import client.MapleClient;
* @author Matze * @author Matze
*/ */
public final class MesoDropHandler extends AbstractMaplePacketHandler {//FIX public final class MesoDropHandler extends AbstractMaplePacketHandler {//FIX
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) { public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
MapleCharacter player = c.getPlayer(); MapleCharacter player = c.getPlayer();
if (!player.isAlive()) { if (!player.isAlive()) {
c.announce(MaplePacketCreator.enableActions()); c.announce(MaplePacketCreator.enableActions());
return; 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);
}
}
} }

View File

@@ -269,11 +269,10 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
if (player.getMap().getHPDec() > 0) player.resetHpDecreaseTask(); if (player.getMap().getHPDec() > 0) player.resetHpDecreaseTask();
player.dispelBuffCoupons();
player.resetPlayerRates(); player.resetPlayerRates();
if(ServerConstants.USE_ADD_RATES_BY_LEVEL == true) player.setPlayerRates(); if(ServerConstants.USE_ADD_RATES_BY_LEVEL == true) player.setPlayerRates();
player.setWorldRates(); player.setWorldRates();
player.setCouponRates(); player.updateCouponRates();
} }
} }

View File

@@ -32,9 +32,10 @@ import constants.ServerConstants;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.Set; import java.util.Set;
@@ -114,12 +115,15 @@ public class World {
} }
public void setExpRate(int exp) { public void setExpRate(int exp) {
//System.out.println("Setting server EXP Rate to " + exp * ServerConstants.EXP_RATE + "x."); List<MapleCharacter> list = new LinkedList<>(getPlayerStorage().getAllCharacters());
for(MapleCharacter chr : getPlayerStorage().getAllCharacters()) {
for(MapleCharacter chr : list) {
if(!chr.isLoggedin()) continue;
chr.revertWorldRates(); chr.revertWorldRates();
} }
this.exprate = exp; this.exprate = exp;
for(MapleCharacter chr : getPlayerStorage().getAllCharacters()) { for(MapleCharacter chr : list) {
if(!chr.isLoggedin()) continue;
chr.setWorldRates(); chr.setWorldRates();
} }
} }
@@ -129,11 +133,15 @@ public class World {
} }
public void setDropRate(int drop) { 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(); chr.revertWorldRates();
} }
this.droprate = drop; this.droprate = drop;
for(MapleCharacter chr : getPlayerStorage().getAllCharacters()) { for(MapleCharacter chr : list) {
if(!chr.isLoggedin()) continue;
chr.setWorldRates(); chr.setWorldRates();
} }
} }
@@ -143,11 +151,15 @@ public class World {
} }
public void setMesoRate(int meso) { 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(); chr.revertWorldRates();
} }
this.mesorate = meso; this.mesorate = meso;
for(MapleCharacter chr : getPlayerStorage().getAllCharacters()) { for(MapleCharacter chr : list) {
if(!chr.isLoggedin()) continue;
chr.setWorldRates(); chr.setWorldRates();
} }
} }
@@ -157,13 +169,7 @@ public class World {
} }
public void setBossDropRate(int bossdrop) { public void setBossDropRate(int bossdrop) {
for(MapleCharacter chr : getPlayerStorage().getAllCharacters()) {
chr.revertWorldRates();
}
this.bossdroprate = bossdrop; this.bossdroprate = bossdrop;
for(MapleCharacter chr : getPlayerStorage().getAllCharacters()) {
chr.setWorldRates();
}
} }
public PlayerStorage getPlayerStorage() { public PlayerStorage getPlayerStorage() {

View File

@@ -223,6 +223,40 @@ public class MapleStatEffect {
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.JUMP, Integer.valueOf(ret.jump)); addBuffStatPairToListIfNotZero(statups, MapleBuffStat.JUMP, Integer.valueOf(ret.jump));
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.PYRAMID_PQ, Integer.valueOf(ret.berserk)); addBuffStatPairToListIfNotZero(statups, MapleBuffStat.PYRAMID_PQ, Integer.valueOf(ret.berserk));
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.BOOSTER, Integer.valueOf(ret.booster)); 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"); MapleData ltd = source.getChildByPath("lt");
if (ltd != null) { if (ltd != null) {
@@ -928,7 +962,7 @@ public class MapleStatEffect {
} }
private void applyBuffEffect(MapleCharacter applyfrom, MapleCharacter applyto, boolean primary) { private void applyBuffEffect(MapleCharacter applyfrom, MapleCharacter applyto, boolean primary) {
if (!isMonsterRiding()) { if (!isMonsterRiding() && !isCouponBuff()) {
applyto.cancelEffect(this, true, -1); applyto.cancelEffect(this, true, -1);
} }
@@ -1253,6 +1287,10 @@ public class MapleStatEffect {
return skill && sourceid == ChiefBandit.CHAKRA; return skill && sourceid == ChiefBandit.CHAKRA;
} }
private boolean isCouponBuff() {
return MapleItemInformationProvider.getInstance().isRateCoupon(sourceid);
}
public boolean isMonsterRiding() { public boolean isMonsterRiding() {
return skill && (sourceid % 10000000 == 1004 || sourceid == Corsair.BATTLE_SHIP || sourceid == Beginner.SPACESHIP || sourceid == Noblesse.SPACESHIP 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 || sourceid == Beginner.YETI_MOUNT1 || sourceid == Beginner.YETI_MOUNT2 || sourceid == Beginner.WITCH_BROOMSTICK || sourceid == Beginner.BALROG_MOUNT

View File

@@ -22,8 +22,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="2"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05211004"> <imgdir name="05211004">
@@ -46,8 +46,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05211005"> <imgdir name="05211005">
@@ -70,8 +70,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05211006"> <imgdir name="05211006">
@@ -94,8 +94,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05211007"> <imgdir name="05211007">
@@ -118,8 +118,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05211008"> <imgdir name="05211008">
@@ -142,8 +142,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05211009"> <imgdir name="05211009">
@@ -163,8 +163,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05211010"> <imgdir name="05211010">
@@ -184,8 +184,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05211011"> <imgdir name="05211011">
@@ -205,8 +205,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05211012"> <imgdir name="05211012">
@@ -226,8 +226,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05211013"> <imgdir name="05211013">
@@ -247,8 +247,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05211014"> <imgdir name="05211014">
@@ -273,8 +273,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="2"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05211015"> <imgdir name="05211015">
@@ -299,8 +299,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="2"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05211016"> <imgdir name="05211016">
@@ -325,8 +325,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="2"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05211017"> <imgdir name="05211017">
@@ -351,8 +351,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="2"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05211018"> <imgdir name="05211018">
@@ -377,8 +377,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="2"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05211037"> <imgdir name="05211037">
@@ -401,8 +401,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05211038"> <imgdir name="05211038">
@@ -422,8 +422,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05211039"> <imgdir name="05211039">
@@ -448,8 +448,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="2"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05211040"> <imgdir name="05211040">
@@ -472,8 +472,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05211041"> <imgdir name="05211041">
@@ -493,8 +493,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05211042"> <imgdir name="05211042">
@@ -519,8 +519,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="2"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05211043"> <imgdir name="05211043">
@@ -543,8 +543,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05211044"> <imgdir name="05211044">
@@ -564,8 +564,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05211045"> <imgdir name="05211045">
@@ -590,8 +590,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="2"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05211046"> <imgdir name="05211046">
@@ -616,8 +616,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="3"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05211048"> <imgdir name="05211048">
@@ -642,8 +642,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="3"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05211049"> <imgdir name="05211049">
@@ -668,8 +668,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="3"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05211052"> <imgdir name="05211052">
@@ -695,8 +695,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="3"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05211060"> <imgdir name="05211060">
@@ -722,8 +722,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="expR" value="4"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
</imgdir> </imgdir>

View File

@@ -22,8 +22,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="drpR" value="1"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05360001"> <imgdir name="05360001">
@@ -48,8 +48,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="drpR" value="2"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05360002"> <imgdir name="05360002">
@@ -74,8 +74,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="drpR" value="2"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05360003"> <imgdir name="05360003">
@@ -100,8 +100,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="drpR" value="2"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05360004"> <imgdir name="05360004">
@@ -126,8 +126,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="drpR" value="2"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05360005"> <imgdir name="05360005">
@@ -152,8 +152,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="drpR" value="2"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05360006"> <imgdir name="05360006">
@@ -178,8 +178,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="drpR" value="2"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05360007"> <imgdir name="05360007">
@@ -204,8 +204,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="drpR" value="2"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05360008"> <imgdir name="05360008">
@@ -230,8 +230,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="drpR" value="2"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="05360042"> <imgdir name="05360042">
@@ -256,8 +256,8 @@
</imgdir> </imgdir>
</imgdir> </imgdir>
<imgdir name="spec"> <imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/> <int name="time" value="2100000"/>
<int name="drpR" value="3"/>
</imgdir> </imgdir>
</imgdir> </imgdir>
</imgdir> </imgdir>