Dynamic World/Channel shutdown + Equip levels on Duey + AP/SP patch

Implemented dynamic world/channel shutdown, coupling with the dynamic deployment from last commit rendering on a fully automated world/channel management.
Fixed some spawned mobs not being properly registered on events.
Implemented a respawn mechanic sensitive to number of players on map. More mobs will spawn the greater the number of players is. Server flag: USE_ENABLE_FULL_RESPAWN = false.
Implemented a mechanic for delayed mob loot drops, on which the delay is determined by the death animation duration. Server flag: USE_SPAWN_LOOT_ON_ANIMATION = true.
Fixed EIM being disposed incorrectly when the dispose is called through scripts.
Protected concurrently AP and SP distribution handlers.
Slightly improved HealOvertimeHandler performance.
Fixed Duey not propagating equipment level and experience when transfering items.
Buyback now has a short grace period, granting the returning player time for decision making (players won't die right away, rather sticks at 1HP).
Reviewed item monitor task not properly protected concurrently.
Fixed some issues with ropes on some Kampung Village maps.
Fixed "maxhpmp" command allowing to pass negative values.
This commit is contained in:
ronancpl
2018-07-28 22:00:52 -03:00
parent 8aadf7c369
commit cc541f39d5
77 changed files with 33492 additions and 32661 deletions

View File

@@ -157,7 +157,7 @@ import net.server.channel.handlers.PartyOperationHandler;
import scripting.item.ItemScriptManager;
import server.maps.MapleMapItem;
import net.server.audit.locks.MonitoredLockType;
import net.server.audit.locks.MonitoredReentrantLock;
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
public class MapleCharacter extends AbstractAnimatedMapleMapObject {
private static MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
@@ -275,10 +275,10 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
private ScheduledFuture<?> extraRecoveryTask = null;
private ScheduledFuture<?> chairRecoveryTask = null;
private ScheduledFuture<?> pendantOfSpirit = null; //1122017
private Lock chrLock = new MonitoredReentrantLock(MonitoredLockType.CHARACTER_CHR, true);
private Lock effLock = new MonitoredReentrantLock(MonitoredLockType.CHARACTER_EFF, true);
private Lock petLock = new MonitoredReentrantLock(MonitoredLockType.CHARACTER_PET, true); // for quest tasks as well
private Lock prtLock = new MonitoredReentrantLock(MonitoredLockType.CHARACTER_PRT);
private Lock chrLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CHARACTER_CHR, true);
private Lock effLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CHARACTER_EFF, true);
private Lock petLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CHARACTER_PET, true); // for quest tasks as well
private Lock prtLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CHARACTER_PRT);
private Map<Integer, Set<Integer>> excluded = new LinkedHashMap<>();
private Set<Integer> excludedItems = new LinkedHashSet<>();
private static String[] ariantroomleader = new String[3];
@@ -445,8 +445,27 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
return awayFromWorld.get();
}
public void setAwayFromWorld(boolean away) {
awayFromWorld.set(away);
public void setEnteredChannelWorld() {
awayFromWorld.set(false);
client.getChannelServer().removePlayerAway(id);
}
public void setAwayFromChannelWorld() {
setAwayFromChannelWorld(false);
}
public void setDisconnectedFromChannelWorld() {
setAwayFromChannelWorld(true);
}
private void setAwayFromChannelWorld(boolean disconnect) {
awayFromWorld.set(true);
if(!disconnect) {
client.getChannelServer().insertPlayerAway(id);
} else {
client.getChannelServer().removePlayerAway(id);
}
}
public long getPetLootCd() {
@@ -1548,9 +1567,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
// if this map has obstacle components moving, make it do so for this client
for(Entry<String, Integer> e: map.getEnvironment().entrySet()) {
announce(MaplePacketCreator.environmentMove(e.getKey(), e.getValue()));
}
announce(MaplePacketCreator.environmentMoveList(map.getEnvironment().entrySet()));
}
}
@@ -5273,6 +5290,10 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
return lastBuyback + ServerConstants.BUYBACK_COOLDOWN_MINUTES * 60 * 1000;
}
private boolean isBuybackInvincible() {
return Server.getInstance().getCurrentTime() - lastBuyback < 4200;
}
private int getBuybackFee() {
float fee = ServerConstants.BUYBACK_FEE;
int grade = Math.min(Math.max(level, 30), 120) - 30;
@@ -5282,10 +5303,10 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
public boolean couldBuyback() { // Ronan's buyback system
long timeNow = System.currentTimeMillis();
long timeNow = Server.getInstance().getCurrentTime();
if(timeNow - lastDeathtime > ServerConstants.BUYBACK_RETURN_MINUTES * 60 * 1000) {
this.dropMessage(5, "You are unable to buyback now since the time available to decide has expired.");
this.dropMessage(5, "The time available to decide has expired, therefore you are unable to buyback now.");
return false;
}
@@ -7621,7 +7642,11 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
updatePartyMemberHP();
}
if (oldHp > hp && !isAlive()) {
playerDead();
if(!isBuybackInvincible()) {
playerDead();
} else {
this.hp = 1;
}
}
}

View File

@@ -75,7 +75,7 @@ import server.maps.*;
import server.quest.MapleQuest;
import net.server.audit.locks.MonitoredLockType;
import net.server.audit.locks.MonitoredReentrantLock;
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
public class MapleClient {
@@ -107,9 +107,9 @@ public class MapleClient {
private int picattempt = 0;
private byte gender = -1;
private boolean disconnecting = false;
private final Lock lock = new MonitoredReentrantLock(MonitoredLockType.CLIENT, true);
private final Lock encoderLock = new MonitoredReentrantLock(MonitoredLockType.CLIENT_ENCODER, true);
private static final Lock loginLock = new MonitoredReentrantLock(MonitoredLockType.CLIENT_LOGIN, true);
private final Lock lock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CLIENT, true);
private final Lock encoderLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CLIENT_ENCODER, true);
private static final Lock loginLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CLIENT_LOGIN, true);
private int votePoints;
private int voteTime = -1;
private long lastNpcClick;
@@ -792,7 +792,7 @@ public class MapleClient {
private void removePlayer() {
try {
player.setAwayFromWorld(true);
player.setDisconnectedFromChannelWorld();
player.notifyMapTransferToPartner(-1);
player.cancelAllBuffs(true);
player.cancelAllDebuffs();
@@ -836,10 +836,13 @@ public class MapleClient {
player.cancelMagicDoor();
final World wserv = getWorldServer();
if (channel == -1 || shutdown) {
if(chrg != null) chrg.setCharacter(null);
if(wserv != null) wserv.removePlayer(player);
removePlayer();
player.saveCooldowns();
player.saveCharToDB(true);
@@ -849,12 +852,11 @@ public class MapleClient {
removePlayer();
final World worlda = getWorldServer();
try {
if (!cashshop) {
if (!this.serverTransition) { // meaning not changing channels
if (messengerid > 0) {
worlda.leaveMessenger(messengerid, chrm);
wserv.leaveMessenger(messengerid, chrm);
}
/*
if (fid > 0) {
@@ -877,7 +879,7 @@ public class MapleClient {
}
if (party != null) {
chrp.setOnline(false);
worlda.updateParty(party.getId(), PartyOperation.LOG_ONOFF, chrp);
wserv.updateParty(party.getId(), PartyOperation.LOG_ONOFF, chrp);
if (map != null && party.getLeader().getId() == idz) {
MaplePartyCharacter lchr = null;
for (MaplePartyCharacter pchr : party.getMembers()) {
@@ -886,19 +888,19 @@ public class MapleClient {
}
}
if (lchr != null) {
worlda.updateParty(party.getId(), PartyOperation.CHANGE_LEADER, lchr);
wserv.updateParty(party.getId(), PartyOperation.CHANGE_LEADER, lchr);
}
}
}
if (bl != null) {
worlda.loggedOff(player.getName(), player.getId(), channel, player.getBuddylist().getBuddyIds());
wserv.loggedOff(player.getName(), player.getId(), channel, player.getBuddylist().getBuddyIds());
}
}
} else {
if (!this.serverTransition) { // if dc inside of cash shop.
if (party != null) {
chrp.setOnline(false);
worlda.updateParty(party.getId(), PartyOperation.LOG_ONOFF, chrp);
wserv.updateParty(party.getId(), PartyOperation.LOG_ONOFF, chrp);
if (map != null && party.getLeader().getId() == idz) {
MaplePartyCharacter lchr = null;
for (MaplePartyCharacter pchr : party.getMembers()) {
@@ -907,12 +909,12 @@ public class MapleClient {
}
}
if (lchr != null) {
worlda.updateParty(party.getId(), PartyOperation.CHANGE_LEADER, lchr);
wserv.updateParty(party.getId(), PartyOperation.CHANGE_LEADER, lchr);
}
}
}
if (bl != null) {
worlda.loggedOff(player.getName(), player.getId(), channel, player.getBuddylist().getBuddyIds());
wserv.loggedOff(player.getName(), player.getId(), channel, player.getBuddylist().getBuddyIds());
}
}
}
@@ -920,7 +922,7 @@ public class MapleClient {
FilePrinter.printError(FilePrinter.ACCOUNT_STUCK, e);
} finally {
if (!this.serverTransition) {
worlda.removePlayer(player);
wserv.removePlayer(player);
//getChannelServer().removePlayer(player); already being done
player.saveCooldowns();
@@ -1309,7 +1311,15 @@ public class MapleClient {
return;
}
String[] socket = Server.getInstance().getIP(getWorld(), channel).split(":");
String[] socket;
try {
socket = Server.getInstance().getIP(getWorld(), channel).split(":");
} catch (Exception e) {
announce(MaplePacketCreator.serverNotice(1, "Channel " + channel + " is currently disabled. Try another channel."));
announce(MaplePacketCreator.enableActions());
return;
}
if (player.getTrade() != null) {
MapleTrade.cancelTrade(getPlayer());
}
@@ -1325,7 +1335,7 @@ public class MapleClient {
player.unregisterChairBuff();
server.getPlayerBuffStorage().addBuffsToStorage(player.getId(), player.getAllBuffs());
server.getPlayerBuffStorage().addDiseasesToStorage(player.getId(), player.getAllDiseases());
player.setAwayFromWorld(true);
player.setDisconnectedFromChannelWorld();
player.notifyMapTransferToPartner(-1);
player.cancelAllBuffs(true);
player.cancelAllDebuffs();

View File

@@ -32,10 +32,10 @@ import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.Semaphore;
import net.server.audit.locks.MonitoredReentrantLock;
import tools.DatabaseConnection;
import tools.MaplePacketCreator;
import net.server.audit.locks.MonitoredLockType;
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
public final class MonsterBook {
private static final Semaphore semaphore = new Semaphore(10);
@@ -44,7 +44,7 @@ public final class MonsterBook {
private int normalCard = 0;
private int bookLevel = 1;
private Map<Integer, Integer> cards = new LinkedHashMap<>();
private Lock lock = new MonitoredReentrantLock(MonitoredLockType.BOOK);
private Lock lock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.BOOK);
private Set<Entry<Integer, Integer>> getCardSet() {
lock.lock();

View File

@@ -1804,29 +1804,31 @@ public class Commands {
if (sub.length >= 3) {
victim = c.getWorldServer().getPlayerStorage().getCharacterByName(sub[1]);
statUpdate = Integer.valueOf(sub[2]);
statUpdate = Math.max(1, Integer.valueOf(sub[2]));
} else if(sub.length == 2) {
statUpdate = Integer.valueOf(sub[1]);
statUpdate = Math.max(1, Integer.valueOf(sub[1]));
} else {
player.yellowMessage("Syntax: !maxhpmp [<playername>] <value>");
}
if(victim != null) {
List<Pair<MapleStat, Integer>> statup = new ArrayList<>(4);
if(victim.getHp() > statUpdate) {
victim.setHp(statUpdate);
victim.updateSingleStat(MapleStat.HP, statUpdate);
statup.add(new Pair<>(MapleStat.HP, statUpdate));
}
statup.add(new Pair<>(MapleStat.MAXHP, statUpdate));
if(victim.getMp() > statUpdate) {
victim.setMp(statUpdate);
victim.updateSingleStat(MapleStat.MP, statUpdate);
statup.add(new Pair<>(MapleStat.MP, statUpdate));
}
statup.add(new Pair<>(MapleStat.MAXMP, statUpdate));
c.announce(MaplePacketCreator.updatePlayerStats(statup, victim));
victim.setMaxHp(statUpdate);
victim.setMaxMp(statUpdate);
victim.updateSingleStat(MapleStat.MAXHP, statUpdate);
victim.updateSingleStat(MapleStat.MAXMP, statUpdate);
victim.checkBerserk(victim.isHidden());
} else {
player.message("Player '" + sub[1] + "' could not be found on this world.");
@@ -2895,7 +2897,6 @@ public class Commands {
break;
/*
case "removechannel":
if (sub.length < 2) {
player.dropMessage(5, "Syntax: @removechannel <worldid>");
@@ -2929,7 +2930,6 @@ public class Commands {
}
break;
*/
case "shutdown":
case "shutdownnow":

View File

@@ -28,10 +28,10 @@ import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Lock;
import net.server.audit.locks.MonitoredReentrantLock;
import tools.DatabaseConnection;
import tools.Pair;
import net.server.audit.locks.MonitoredLockType;
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
/**
*
@@ -47,7 +47,7 @@ public enum ItemFactory {
MERCHANT(6, false);
private final int value;
private final boolean account;
private static final Lock lock = new MonitoredReentrantLock(MonitoredLockType.ITEM, true);
private static final Lock lock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.ITEM, true);
private ItemFactory(int value, boolean account) {
this.value = value;

View File

@@ -32,7 +32,7 @@ import java.util.List;
import java.util.Map.Entry;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import net.server.audit.locks.MonitoredReentrantLock;
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
import tools.Pair;
import client.MapleCharacter;
@@ -53,7 +53,7 @@ public class MapleInventory implements Iterable<Item> {
protected byte slotLimit;
protected MapleInventoryType type;
protected boolean checked = false;
protected Lock lock = new MonitoredReentrantLock(MonitoredLockType.INVENTORY, true);
protected Lock lock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.INVENTORY, true);
public MapleInventory(MapleCharacter mc, MapleInventoryType type, byte slotLimit) {
this.owner = mc;

View File

@@ -0,0 +1,881 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
Copyleft (L) 2016 - 2018 RonanLana (HeavenMS)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
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 client.processor;
import client.MapleCharacter;
import client.MapleClient;
import client.MapleJob;
import client.MapleStat;
import client.Skill;
import client.SkillFactory;
import client.autoban.AutobanFactory;
import client.inventory.Equip;
import client.inventory.Item;
import client.inventory.MapleInventoryType;
import constants.ServerConstants;
import constants.skills.BlazeWizard;
import constants.skills.Brawler;
import constants.skills.DawnWarrior;
import constants.skills.Magician;
import constants.skills.Warrior;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import tools.MaplePacketCreator;
import tools.Pair;
import tools.Randomizer;
import tools.data.input.SeekableLittleEndianAccessor;
/**
*
* @author RonanLana (synchronization of AP transaction modules)
*/
public class AssignAPProcessor {
public static void APAutoAssignAction(SeekableLittleEndianAccessor slea, MapleClient c) {
MapleCharacter chr = c.getPlayer();
if (chr.getRemainingAp() < 1) return;
Collection<Item> equippedC = chr.getInventory(MapleInventoryType.EQUIPPED).list();
c.lockClient();
try {
int[] statGain = new int[4];
int[] statEqpd = new int[4];
statGain[0] = 0; statGain[1] = 0; statGain[2] = 0; statGain[3] = 0;
slea.skip(8);
if(ServerConstants.USE_SERVER_AUTOASSIGNER) {
// --------- Ronan Lana's AUTOASSIGNER ---------
// This method excels for assigning APs in such a way to cover all equipments AP requirements.
byte opt = slea.readByte(); // useful for pirate autoassigning
int str = 0, dex = 0, luk = 0, int_ = 0;
List<Short> eqpStrList = new ArrayList<>();
List<Short> eqpDexList = new ArrayList<>();
List<Short> eqpLukList = new ArrayList<>();
Equip nEquip;
for (Item item : equippedC) { //selecting the biggest AP value of each stat from each equipped item.
nEquip = (Equip)item;
if(nEquip.getStr() > 0) eqpStrList.add(nEquip.getStr());
str += nEquip.getStr();
if(nEquip.getDex() > 0) eqpDexList.add(nEquip.getDex());
dex += nEquip.getDex();
if(nEquip.getLuk() > 0) eqpLukList.add(nEquip.getLuk());
luk += nEquip.getLuk();
//if(nEquip.getInt() > 0) eqpIntList.add(nEquip.getInt()); //not needed...
int_ += nEquip.getInt();
}
statEqpd[0] = str;
statEqpd[1] = dex;
statEqpd[2] = luk;
statEqpd[3] = int_;
Collections.sort(eqpStrList, Collections.reverseOrder());
Collections.sort(eqpDexList, Collections.reverseOrder());
Collections.sort(eqpLukList, Collections.reverseOrder());
//Autoassigner looks up the 1st/2nd placed equips for their stats to calculate the optimal upgrade.
int eqpStr = getNthHighestStat(eqpStrList, (short) 0) + getNthHighestStat(eqpStrList, (short) 1);
int eqpDex = getNthHighestStat(eqpDexList, (short) 0) + getNthHighestStat(eqpDexList, (short) 1);
int eqpLuk = getNthHighestStat(eqpLukList, (short) 0) + getNthHighestStat(eqpLukList, (short) 1);
//c.getPlayer().message("----------------------------------------");
//c.getPlayer().message("SDL: s" + eqpStr + " d" + eqpDex + " l" + eqpLuk + " BASE STATS --> STR: " + chr.getStr() + " DEX: " + chr.getDex() + " INT: " + chr.getInt() + " LUK: " + chr.getLuk());
//c.getPlayer().message("SUM EQUIP STATS -> STR: " + str + " DEX: " + dex + " LUK: " + luk + " INT: " + int_);
MapleJob stance = c.getPlayer().getJobStyle(opt);
int prStat = 0, scStat = 0, trStat = 0, temp, tempAp = chr.getRemainingAp(), CAP;
if (tempAp < 1) return;
MapleStat primary, secondary, tertiary = MapleStat.LUK;
switch(stance) {
case MAGICIAN:
CAP = 165;
scStat = (chr.getLevel() + 3) - (chr.getLuk() + luk - eqpLuk);
if(scStat < 0) scStat = 0;
scStat = Math.min(scStat, tempAp);
if(tempAp > scStat) tempAp -= scStat;
else tempAp = 0;
prStat = tempAp;
int_ = prStat;
luk = scStat;
str = 0; dex = 0;
if(luk + chr.getLuk() > CAP) {
temp = luk + chr.getLuk() - CAP;
luk -= temp;
int_ += temp;
}
primary = MapleStat.INT;
secondary = MapleStat.LUK;
tertiary = MapleStat.DEX;
break;
case BOWMAN:
CAP = 125;
scStat = (chr.getLevel() + 5) - (chr.getStr() + str - eqpStr);
if(scStat < 0) scStat = 0;
scStat = Math.min(scStat, tempAp);
if(tempAp > scStat) tempAp -= scStat;
else tempAp = 0;
prStat = tempAp;
dex = prStat;
str = scStat;
int_ = 0; luk = 0;
if(str + chr.getStr() > CAP) {
temp = str + chr.getStr() - CAP;
str -= temp;
dex += temp;
}
primary = MapleStat.DEX;
secondary = MapleStat.STR;
break;
case GUNSLINGER:
case CROSSBOWMAN:
CAP = 120;
scStat = chr.getLevel() - (chr.getStr() + str - eqpStr);
if(scStat < 0) scStat = 0;
scStat = Math.min(scStat, tempAp);
if(tempAp > scStat) tempAp -= scStat;
else tempAp = 0;
prStat = tempAp;
dex = prStat;
str = scStat;
int_ = 0; luk = 0;
if(str + chr.getStr() > CAP) {
temp = str + chr.getStr() - CAP;
str -= temp;
dex += temp;
}
primary = MapleStat.DEX;
secondary = MapleStat.STR;
break;
case THIEF:
CAP = 160;
scStat = 0;
if(chr.getDex() < 80) {
scStat = (2 * chr.getLevel()) - (chr.getDex() + dex - eqpDex);
if(scStat < 0) scStat = 0;
scStat = Math.min(80 - chr.getDex(), scStat);
scStat = Math.min(tempAp, scStat);
tempAp -= scStat;
}
temp = (chr.getLevel() + 40) - Math.max(80, scStat + chr.getDex() + dex - eqpDex);
if(temp < 0) temp = 0;
temp = Math.min(tempAp, temp);
scStat += temp;
tempAp -= temp;
// thieves will upgrade STR as well only if a level-based threshold is reached.
if(chr.getStr() >= Math.max(13, (int)(0.4 * chr.getLevel()))) {
if(chr.getStr() < 50) {
trStat = (chr.getLevel() - 10) - (chr.getStr() + str - eqpStr);
if(trStat < 0) trStat = 0;
trStat = Math.min(50 - chr.getStr(), trStat);
trStat = Math.min(tempAp, trStat);
tempAp -= trStat;
}
temp = (20 + (chr.getLevel() / 2)) - Math.max(50, trStat + chr.getStr() + str - eqpStr);
if(temp < 0) temp = 0;
temp = Math.min(tempAp, temp);
trStat += temp;
tempAp -= temp;
}
prStat = tempAp;
luk = prStat;
dex = scStat;
str = trStat;
int_ = 0;
if(dex + chr.getDex() > CAP) {
temp = dex + chr.getDex() - CAP;
dex -= temp;
luk += temp;
}
if(str + chr.getStr() > CAP) {
temp = str + chr.getStr() - CAP;
str -= temp;
luk += temp;
}
primary = MapleStat.LUK;
secondary = MapleStat.DEX;
tertiary = MapleStat.STR;
break;
case BRAWLER:
CAP = 120;
scStat = chr.getLevel() - (chr.getDex() + dex - eqpDex);
if(scStat < 0) scStat = 0;
scStat = Math.min(scStat, tempAp);
if(tempAp > scStat) tempAp -= scStat;
else tempAp = 0;
prStat = tempAp;
str = prStat;
dex = scStat;
int_ = 0; luk = 0;
if(dex + chr.getDex() > CAP) {
temp = dex + chr.getDex() - CAP;
dex -= temp;
str += temp;
}
primary = MapleStat.STR;
secondary = MapleStat.DEX;
break;
default: //warrior, beginner, ...
CAP = 80;
scStat = ((2 * chr.getLevel()) / 3) - (chr.getDex() + dex - eqpDex);
if(scStat < 0) scStat = 0;
scStat = Math.min(scStat, tempAp);
if(tempAp > scStat) tempAp -= scStat;
else tempAp = 0;
prStat = tempAp;
str = prStat;
dex = scStat;
int_ = 0; luk = 0;
if(dex + chr.getDex() > CAP) {
temp = dex + chr.getDex() - CAP;
dex -= temp;
str += temp;
}
primary = MapleStat.STR;
secondary = MapleStat.DEX;
}
//-------------------------------------------------------------------------------------
int extras = 0;
extras = gainStatByType(chr, primary, statGain, prStat + extras);
extras = gainStatByType(chr, secondary, statGain, scStat + extras);
extras = gainStatByType(chr, tertiary, statGain, trStat + extras);
if(extras > 0) { //redistribute surplus in priority order
extras = gainStatByType(chr, primary, statGain, extras);
extras = gainStatByType(chr, secondary, statGain, extras);
extras = gainStatByType(chr, tertiary, statGain, extras);
gainStatByType(chr, getQuaternaryStat(stance), statGain, extras);
}
int remainingAp = (chr.getRemainingAp() - getAccumulatedStatGain(statGain));
chr.setRemainingAp(remainingAp);
chr.updateSingleStat(MapleStat.AVAILABLEAP, remainingAp);
c.announce(MaplePacketCreator.enableActions());
//----------------------------------------------------------------------------------------
c.announce(MaplePacketCreator.serverNotice(1, "Better AP applications detected:\r\nSTR: +" + statGain[0] + "\r\nDEX: +" + statGain[1] + "\r\nINT: +" + statGain[3] + "\r\nLUK: +" + statGain[2]));
} else {
if(slea.available() < 16) {
AutobanFactory.PACKET_EDIT.alert(chr, "Didn't send full packet for Auto Assign.");
final MapleClient client = c;
Thread t = new Thread(new Runnable() {
@Override
public void run() {
client.disconnect(false, false);
}
});
t.start();
return;
}
for (Item item : equippedC) { //selecting the biggest AP value of each stat from each equipped item.
Equip nEquip = (Equip)item;
statEqpd[0] += nEquip.getStr();
statEqpd[1] += nEquip.getDex();
statEqpd[2] += nEquip.getLuk();
statEqpd[3] += nEquip.getInt();
}
int total = 0;
int extras = 0;
for (int i = 0; i < 2; i++) {
int type = slea.readInt();
int tempVal = slea.readInt();
if (tempVal < 0 || tempVal > chr.getRemainingAp()) {
return;
}
total += tempVal;
extras += gainStatByType(chr, MapleStat.getBy5ByteEncoding(type), statGain, tempVal);
}
int remainingAp = (chr.getRemainingAp() - total) + extras;
chr.setRemainingAp(remainingAp);
chr.updateSingleStat(MapleStat.AVAILABLEAP, remainingAp);
c.announce(MaplePacketCreator.enableActions());
}
} finally {
c.unlockClient();
}
}
private static int getNthHighestStat(List<Short> statList, short rank) { // ranks from 0
return(statList.size() <= rank ? 0 : statList.get(rank));
}
private static int gainStatByType(MapleCharacter chr, MapleStat type, int[] statGain, int gain) {
if(gain <= 0) return 0;
int newVal = 0;
if (type.equals(MapleStat.STR)) {
newVal = chr.getStr() + gain;
if (newVal > ServerConstants.MAX_AP) {
statGain[0] += (gain - (newVal - ServerConstants.MAX_AP));
chr.setStr(ServerConstants.MAX_AP);
} else {
statGain[0] += gain;
chr.setStr(newVal);
}
} else if (type.equals(MapleStat.INT)) {
newVal = chr.getInt() + gain;
if (newVal > ServerConstants.MAX_AP) {
statGain[3] += (gain - (newVal - ServerConstants.MAX_AP));
chr.setInt(ServerConstants.MAX_AP);
} else {
statGain[3] += gain;
chr.setInt(newVal);
}
} else if (type.equals(MapleStat.LUK)) {
newVal = chr.getLuk() + gain;
if (newVal > ServerConstants.MAX_AP) {
statGain[2] += (gain - (newVal - ServerConstants.MAX_AP));
chr.setLuk(ServerConstants.MAX_AP);
} else {
statGain[2] += gain;
chr.setLuk(newVal);
}
} else if (type.equals(MapleStat.DEX)) {
newVal = chr.getDex() + gain;
if (newVal > ServerConstants.MAX_AP) {
statGain[1] += (gain - (newVal - ServerConstants.MAX_AP));
chr.setDex(ServerConstants.MAX_AP);
} else {
statGain[1] += gain;
chr.setDex(newVal);
}
}
if (newVal > ServerConstants.MAX_AP) {
chr.updateSingleStat(type, ServerConstants.MAX_AP);
return newVal - ServerConstants.MAX_AP;
}
chr.updateSingleStat(type, newVal);
return 0;
}
private static MapleStat getQuaternaryStat(MapleJob stance) {
if(stance != MapleJob.MAGICIAN) return MapleStat.INT;
return MapleStat.STR;
}
private static int getAccumulatedStatGain(int[] statGain) {
int acc = 0;
for(byte i = 0; i < statGain.length; i++) {
acc += statGain[i];
}
return acc;
}
public static boolean APResetAction(MapleClient c, int APFrom, int APTo) {
c.lockClient();
try {
List<Pair<MapleStat, Integer>> statupdate = new ArrayList<>(2);
MapleCharacter player = c.getPlayer();
switch (APFrom) {
case 64: // str
if (player.getStr() < 5) {
player.message("You don't have the minimum STR required to swap.");
c.announce(MaplePacketCreator.enableActions());
return false;
}
player.addStat(1, -1);
break;
case 128: // dex
if (player.getDex() < 5) {
player.message("You don't have the minimum DEX required to swap.");
c.announce(MaplePacketCreator.enableActions());
return false;
}
player.addStat(2, -1);
break;
case 256: // int
if (player.getInt() < 5) {
player.message("You don't have the minimum INT required to swap.");
c.announce(MaplePacketCreator.enableActions());
return false;
}
player.addStat(3, -1);
break;
case 512: // luk
if (player.getLuk() < 5) {
player.message("You don't have the minimum LUK required to swap.");
c.announce(MaplePacketCreator.enableActions());
return false;
}
player.addStat(4, -1);
break;
case 2048: // HP
if(ServerConstants.USE_ENFORCE_HPMP_SWAP) {
if (APTo != 8192) {
player.message("You can only swap HP ability points to MP.");
c.announce(MaplePacketCreator.enableActions());
return false;
}
}
if (player.getHpMpApUsed() < 1) {
player.message("You don't have enough HPMP stat points to spend on AP Reset.");
c.announce(MaplePacketCreator.enableActions());
return false;
}
int hp = player.getMaxHp();
int level_ = player.getLevel();
boolean canWash_ = true;
if (hp < level_ * 14 + 148) {
canWash_ = false;
}
if (!canWash_) {
player.message("You don't have the minimum HP pool required to swap.");
c.announce(MaplePacketCreator.enableActions());
return false;
}
player.setHpMpApUsed(player.getHpMpApUsed() - 1);
int hplose = -takeHp(player.getJob());
int nextHp = Math.max(1, player.getHp() + hplose), nextMaxHp = Math.max(50, player.getMaxHp() + hplose);
player.setHp(nextHp);
player.setMaxHp(nextMaxHp);
statupdate.add(new Pair<>(MapleStat.HP, nextHp));
statupdate.add(new Pair<>(MapleStat.MAXHP, nextMaxHp));
break;
case 8192: // MP
if(ServerConstants.USE_ENFORCE_HPMP_SWAP) {
if (APTo != 2048) {
player.message("You can only swap MP ability points to HP.");
c.announce(MaplePacketCreator.enableActions());
return false;
}
}
if (player.getHpMpApUsed() < 1) {
player.message("You don't have enough HPMP stat points to spend on AP Reset.");
c.announce(MaplePacketCreator.enableActions());
return false;
}
int mp = player.getMaxMp();
int level = player.getLevel();
MapleJob job = player.getJob();
boolean canWash = true;
if (job.isA(MapleJob.SPEARMAN) && mp < 4 * level + 156) {
canWash = false;
} else if (job.isA(MapleJob.FIGHTER) && mp < 4 * level + 56) {
canWash = false;
} else if (job.isA(MapleJob.THIEF) && job.getId() % 100 > 0 && mp < level * 14 - 4) {
canWash = false;
} else if (mp < level * 14 + 148) {
canWash = false;
}
if (!canWash) {
player.message("You don't have the minimum MP pool required to swap.");
c.announce(MaplePacketCreator.enableActions());
return false;
}
player.setHpMpApUsed(player.getHpMpApUsed() - 1);
int mplose = -takeMp(job);
int nextMp = Math.max(0, player.getMp() + mplose), nextMaxMp = Math.max(5, player.getMaxMp() + mplose);
player.setMp(nextMp);
player.setMaxMp(nextMaxMp);
statupdate.add(new Pair<>(MapleStat.MP, nextMp));
statupdate.add(new Pair<>(MapleStat.MAXMP, nextMaxMp));
break;
default:
c.announce(MaplePacketCreator.updatePlayerStats(MaplePacketCreator.EMPTY_STATUPDATE, true, player));
return false;
}
addStat(c, APTo, true);
c.announce(MaplePacketCreator.updatePlayerStats(statupdate, true, player));
return true;
} finally {
c.unlockClient();
}
}
public static void APAssignAction(MapleClient c, int num) {
c.lockClient();
try {
if (c.getPlayer().getRemainingAp() > 0) {
if (addStat(c, num, false)) {
c.getPlayer().setRemainingAp(c.getPlayer().getRemainingAp() - 1);
c.getPlayer().updateSingleStat(MapleStat.AVAILABLEAP, c.getPlayer().getRemainingAp());
}
}
c.announce(MaplePacketCreator.enableActions());
} finally {
c.unlockClient();
}
}
private static boolean addStat(MapleClient c, int apTo, boolean usedAPReset) {
switch (apTo) {
case 64: // Str
if (c.getPlayer().getStr() >= 32767) {
return false;
}
c.getPlayer().addStat(1, 1);
break;
case 128: // Dex
if (c.getPlayer().getDex() >= 32767) {
return false;
}
c.getPlayer().addStat(2, 1);
break;
case 256: // Int
if (c.getPlayer().getInt() >= 32767) {
return false;
}
c.getPlayer().addStat(3, 1);
break;
case 512: // Luk
if (c.getPlayer().getLuk() >= 32767) {
return false;
}
c.getPlayer().addStat(4, 1);
break;
case 2048: // HP
addHP(c.getPlayer(), addHP(c, usedAPReset));
break;
case 8192: // MP
addMP(c.getPlayer(), addMP(c, usedAPReset));
break;
default:
c.announce(MaplePacketCreator.updatePlayerStats(MaplePacketCreator.EMPTY_STATUPDATE, true, c.getPlayer()));
return false;
}
return true;
}
private static int addHP(MapleClient c, boolean usedAPReset) {
MapleCharacter player = c.getPlayer();
MapleJob job = player.getJob();
int MaxHP = player.getMaxHp();
if (player.getHpMpApUsed() > 9999 || MaxHP >= 30000) {
return MaxHP;
}
return MaxHP + calcHpChange(player, job, usedAPReset);
}
private static int calcHpChange(MapleCharacter player, MapleJob job, boolean usedAPReset) {
int MaxHP = 0;
if (job.isA(MapleJob.WARRIOR) || job.isA(MapleJob.DAWNWARRIOR1)) {
if(!usedAPReset) {
Skill increaseHP = SkillFactory.getSkill(job.isA(MapleJob.DAWNWARRIOR1) ? DawnWarrior.MAX_HP_INCREASE : Warrior.IMPROVED_MAXHP);
int sLvl = player.getSkillLevel(increaseHP);
if(sLvl > 0)
MaxHP += increaseHP.getEffect(sLvl).getY();
}
if(ServerConstants.USE_RANDOMIZE_HPMP_GAIN) {
if (usedAPReset) {
MaxHP += 20;
} else {
MaxHP += Randomizer.rand(18, 22);
}
} else {
MaxHP += 20;
}
} else if(job.isA(MapleJob.ARAN1)) {
if(ServerConstants.USE_RANDOMIZE_HPMP_GAIN) {
if (usedAPReset) {
MaxHP += 20;
} else {
MaxHP += Randomizer.rand(26, 30);
}
} else {
MaxHP += 28;
}
} else if (job.isA(MapleJob.MAGICIAN) || job.isA(MapleJob.BLAZEWIZARD1)) {
if(ServerConstants.USE_RANDOMIZE_HPMP_GAIN) {
if (usedAPReset) {
MaxHP += 6;
} else {
MaxHP += Randomizer.rand(5, 9);
}
} else {
MaxHP += 6;
}
} else if (job.isA(MapleJob.THIEF) || job.isA(MapleJob.NIGHTWALKER1)) {
if(ServerConstants.USE_RANDOMIZE_HPMP_GAIN) {
if (usedAPReset) {
MaxHP += 16;
} else {
MaxHP += Randomizer.rand(14, 18);
}
} else {
MaxHP += 16;
}
} else if(job.isA(MapleJob.BOWMAN) || job.isA(MapleJob.WINDARCHER1)) {
if(ServerConstants.USE_RANDOMIZE_HPMP_GAIN) {
if (usedAPReset) {
MaxHP += 16;
} else {
MaxHP += Randomizer.rand(14, 18);
}
} else {
MaxHP += 16;
}
} else if (job.isA(MapleJob.PIRATE) || job.isA(MapleJob.THUNDERBREAKER1)) {
if(!usedAPReset) {
Skill increaseHP = SkillFactory.getSkill(Brawler.IMPROVE_MAX_HP);
int sLvl = player.getSkillLevel(increaseHP);
if(sLvl > 0)
MaxHP += increaseHP.getEffect(sLvl).getY();
}
if(ServerConstants.USE_RANDOMIZE_HPMP_GAIN) {
if (usedAPReset) {
MaxHP += 18;
} else {
MaxHP += Randomizer.rand(16, 20);
}
} else {
MaxHP += 18;
}
} else if (usedAPReset) {
MaxHP += 8;
} else {
if(ServerConstants.USE_RANDOMIZE_HPMP_GAIN) {
MaxHP += Randomizer.rand(8, 12);
} else {
MaxHP += 10;
}
}
return MaxHP;
}
private static int addMP(MapleClient c, boolean usedAPReset) {
MapleCharacter player = c.getPlayer();
int MaxMP = player.getMaxMp();
MapleJob job = player.getJob();
if (player.getHpMpApUsed() > 9999 || player.getMaxMp() >= 30000) {
return MaxMP;
}
return MaxMP + calcMpChange(player, job, usedAPReset);
}
private static int calcMpChange(MapleCharacter player, MapleJob job, boolean usedAPReset) {
int MaxMP = 0;
if (job.isA(MapleJob.WARRIOR) || job.isA(MapleJob.DAWNWARRIOR1) || job.isA(MapleJob.ARAN1)) {
if(ServerConstants.USE_RANDOMIZE_HPMP_GAIN) {
if(!usedAPReset) {
MaxMP += (Randomizer.rand(2, 4) + (player.getInt() / 10));
} else {
MaxMP += 2;
}
} else {
MaxMP += 3;
}
} else if (job.isA(MapleJob.MAGICIAN) || job.isA(MapleJob.BLAZEWIZARD1)) {
if(!usedAPReset) {
Skill increaseMP = SkillFactory.getSkill(job.isA(MapleJob.BLAZEWIZARD1) ? BlazeWizard.INCREASING_MAX_MP : Magician.IMPROVED_MAX_MP_INCREASE);
int sLvl = player.getSkillLevel(increaseMP);
if(sLvl > 0)
MaxMP += increaseMP.getEffect(sLvl).getY();
}
if(ServerConstants.USE_RANDOMIZE_HPMP_GAIN) {
if(!usedAPReset) {
MaxMP += (Randomizer.rand(12, 16) + (player.getInt() / 20));
} else {
MaxMP += 18;
}
} else {
MaxMP += 18;
}
} else if (job.isA(MapleJob.BOWMAN) || job.isA(MapleJob.WINDARCHER1)) {
if(ServerConstants.USE_RANDOMIZE_HPMP_GAIN) {
if(!usedAPReset) {
MaxMP += (Randomizer.rand(6, 8) + (player.getInt() / 10));
} else {
MaxMP += 10;
}
} else {
MaxMP += 10;
}
} else if(job.isA(MapleJob.THIEF) || job.isA(MapleJob.NIGHTWALKER1)) {
if(ServerConstants.USE_RANDOMIZE_HPMP_GAIN) {
if(!usedAPReset) {
MaxMP += (Randomizer.rand(6, 8) + (player.getInt() / 10));
} else {
MaxMP += 10;
}
} else {
MaxMP += 10;
}
} else if (job.isA(MapleJob.PIRATE) || job.isA(MapleJob.THUNDERBREAKER1)) {
if(ServerConstants.USE_RANDOMIZE_HPMP_GAIN) {
if(!usedAPReset) {
MaxMP += (Randomizer.rand(7, 9) + (player.getInt() / 10));
} else {
MaxMP += 14;
}
} else {
MaxMP += 14;
}
} else {
if(ServerConstants.USE_RANDOMIZE_HPMP_GAIN) {
if(!usedAPReset) {
MaxMP += (Randomizer.rand(4, 6) + (player.getInt() / 10));
} else {
MaxMP += 6;
}
} else {
MaxMP += 6;
}
}
return MaxMP;
}
private static void addHP(MapleCharacter player, int MaxHP) {
MaxHP = Math.min(30000, MaxHP);
player.setHpMpApUsed(player.getHpMpApUsed() + 1);
player.setMaxHp(MaxHP);
player.updateSingleStat(MapleStat.MAXHP, MaxHP);
}
private static void addMP(MapleCharacter player, int MaxMP) {
MaxMP = Math.min(30000, MaxMP);
player.setHpMpApUsed(player.getHpMpApUsed() + 1);
player.setMaxMp(MaxMP);
player.updateSingleStat(MapleStat.MAXMP, MaxMP);
}
private static int takeHp(MapleJob job) {
int MaxHP = 0;
if (job.isA(MapleJob.WARRIOR) || job.isA(MapleJob.DAWNWARRIOR1) || job.isA(MapleJob.ARAN1)) {
MaxHP += 54;
} else if (job.isA(MapleJob.MAGICIAN) || job.isA(MapleJob.BLAZEWIZARD1)) {
MaxHP += 10;
} else if (job.isA(MapleJob.THIEF) || job.isA(MapleJob.NIGHTWALKER1)) {
MaxHP += 20;
} else if(job.isA(MapleJob.BOWMAN) || job.isA(MapleJob.WINDARCHER1)) {
MaxHP += 20;
} else if (job.isA(MapleJob.PIRATE) || job.isA(MapleJob.THUNDERBREAKER1)) {
MaxHP += 42;
} else {
MaxHP += 12;
}
return MaxHP;
}
private static int takeMp(MapleJob job) {
int MaxMP = 0;
if (job.isA(MapleJob.WARRIOR) || job.isA(MapleJob.DAWNWARRIOR1) || job.isA(MapleJob.ARAN1)) {
MaxMP += 4;
} else if (job.isA(MapleJob.MAGICIAN) || job.isA(MapleJob.BLAZEWIZARD1)) {
MaxMP += 31;
} else if (job.isA(MapleJob.BOWMAN) || job.isA(MapleJob.WINDARCHER1)) {
MaxMP += 12;
} else if(job.isA(MapleJob.THIEF) || job.isA(MapleJob.NIGHTWALKER1)) {
MaxMP += 12;
} else if (job.isA(MapleJob.PIRATE) || job.isA(MapleJob.THUNDERBREAKER1)) {
MaxMP += 16;
} else {
MaxMP += 8;
}
return MaxMP;
}
}

View File

@@ -0,0 +1,100 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
Copyleft (L) 2016 - 2018 RonanLana (HeavenMS)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
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 client.processor;
import client.MapleCharacter;
import client.MapleClient;
import client.MapleStat;
import client.Skill;
import client.SkillFactory;
import client.autoban.AutobanFactory;
import constants.GameConstants;
import constants.skills.Aran;
import tools.FilePrinter;
import tools.MaplePacketCreator;
/**
*
* @author RonanLana (synchronization of SP transaction modules)
*/
public class AssignSPProcessor {
public static void SPAssignAction(MapleClient c, int skillid) {
c.lockClient();
try {
if (skillid == Aran.HIDDEN_FULL_DOUBLE || skillid == Aran.HIDDEN_FULL_TRIPLE || skillid == Aran.HIDDEN_OVER_DOUBLE || skillid == Aran.HIDDEN_OVER_TRIPLE) {
c.getSession().write(MaplePacketCreator.enableActions());
return;
}
MapleCharacter player = c.getPlayer();
int remainingSp = player.getRemainingSpBySkill(GameConstants.getSkillBook(skillid/10000));
boolean isBeginnerSkill = false;
if ((!GameConstants.isPqSkillMap(player.getMapId()) && GameConstants.isPqSkill(skillid)) || (!player.isGM() && GameConstants.isGMSkills(skillid)) || (!GameConstants.isInJobTree(skillid, player.getJob().getId()) && !player.isGM())) {
AutobanFactory.PACKET_EDIT.alert(player, "tried to packet edit in distributing sp.");
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to use skill " + skillid + " without it being in their job.\r\n");
final MapleClient client = c;
Thread t = new Thread(new Runnable() {
@Override
public void run() {
client.disconnect(true, false);
}
});
t.start();
return;
}
if (skillid % 10000000 > 999 && skillid % 10000000 < 1003) {
int total = 0;
for (int i = 0; i < 3; i++) {
total += player.getSkillLevel(SkillFactory.getSkill(player.getJobType() * 10000000 + 1000 + i));
}
remainingSp = Math.min((player.getLevel() - 1), 6) - total;
isBeginnerSkill = true;
}
Skill skill = SkillFactory.getSkill(skillid);
int curLevel = player.getSkillLevel(skill);
if ((remainingSp > 0 && curLevel + 1 <= (skill.isFourthJob() ? player.getMasterLevel(skill) : skill.getMaxLevel()))) {
if (!isBeginnerSkill) {
player.setRemainingSp(player.getRemainingSpBySkill(GameConstants.getSkillBook(skillid/10000)) - 1, GameConstants.getSkillBook(skillid/10000));
}
player.updateSingleStat(MapleStat.AVAILABLESP, player.getRemainingSpBySkill(GameConstants.getSkillBook(skillid/10000)));
if (skill.getId() == Aran.FULL_SWING) {
player.changeSkillLevel(skill, (byte) (curLevel + 1), player.getMasterLevel(skill), player.getSkillExpiration(skill));
player.changeSkillLevel(SkillFactory.getSkill(Aran.HIDDEN_FULL_DOUBLE), (byte) player.getSkillLevel(skill), player.getMasterLevel(skill), player.getSkillExpiration(skill));
player.changeSkillLevel(SkillFactory.getSkill(Aran.HIDDEN_FULL_TRIPLE), (byte) player.getSkillLevel(skill), player.getMasterLevel(skill), player.getSkillExpiration(skill));
} else if (skill.getId() == Aran.OVER_SWING) {
player.changeSkillLevel(skill, (byte) (curLevel + 1), player.getMasterLevel(skill), player.getSkillExpiration(skill));
player.changeSkillLevel(SkillFactory.getSkill(Aran.HIDDEN_OVER_DOUBLE), (byte) player.getSkillLevel(skill), player.getMasterLevel(skill), player.getSkillExpiration(skill));
player.changeSkillLevel(SkillFactory.getSkill(Aran.HIDDEN_OVER_TRIPLE), (byte) player.getSkillLevel(skill), player.getMasterLevel(skill), player.getSkillExpiration(skill));
} else {
player.changeSkillLevel(skill, (byte) (curLevel + 1), player.getMasterLevel(skill), player.getSkillExpiration(skill));
}
}
} finally {
c.unlockClient();
}
}
}

View File

@@ -149,6 +149,8 @@ public class DueyProcessor {
Equip eq = new Equip(rs.getInt("itemid"), (byte) 0, -1);
eq.setUpgradeSlots((byte) rs.getInt("upgradeslots"));
eq.setLevel((byte) rs.getInt("level"));
eq.setItemLevel((byte) rs.getInt("itemlevel"));
eq.setItemExp(rs.getInt("itemexp"));
eq.setStr((short) rs.getInt("str"));
eq.setDex((short) rs.getInt("dex"));
eq.setInt((short) rs.getInt("int"));
@@ -271,29 +273,31 @@ public class DueyProcessor {
rs.next();
PreparedStatement ps2;
if (item.getInventoryType().equals(MapleInventoryType.EQUIP)) {
ps2 = con.prepareStatement("INSERT INTO dueyitems (PackageId, itemid, quantity, upgradeslots, level, str, dex, `int`, luk, hp, mp, watk, matk, wdef, mdef, acc, avoid, hands, speed, jump, flag, owner) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
ps2 = con.prepareStatement("INSERT INTO dueyitems (PackageId, itemid, quantity, upgradeslots, level, itemlevel, itemexp, str, dex, `int`, luk, hp, mp, watk, matk, wdef, mdef, acc, avoid, hands, speed, jump, flag, owner) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
Equip eq = (Equip) item;
ps2.setInt(2, eq.getItemId());
ps2.setInt(3, 1);
ps2.setInt(4, eq.getUpgradeSlots());
ps2.setInt(5, eq.getLevel());
ps2.setInt(6, eq.getStr());
ps2.setInt(7, eq.getDex());
ps2.setInt(8, eq.getInt());
ps2.setInt(9, eq.getLuk());
ps2.setInt(10, eq.getHp());
ps2.setInt(11, eq.getMp());
ps2.setInt(12, eq.getWatk());
ps2.setInt(13, eq.getMatk());
ps2.setInt(14, eq.getWdef());
ps2.setInt(15, eq.getMdef());
ps2.setInt(16, eq.getAcc());
ps2.setInt(17, eq.getAvoid());
ps2.setInt(18, eq.getHands());
ps2.setInt(19, eq.getSpeed());
ps2.setInt(20, eq.getJump());
ps2.setInt(21, eq.getFlag());
ps2.setString(22, eq.getOwner());
ps2.setInt(6, eq.getItemLevel());
ps2.setInt(7, eq.getItemExp());
ps2.setInt(8, eq.getStr());
ps2.setInt(9, eq.getDex());
ps2.setInt(10, eq.getInt());
ps2.setInt(11, eq.getLuk());
ps2.setInt(12, eq.getHp());
ps2.setInt(13, eq.getMp());
ps2.setInt(14, eq.getWatk());
ps2.setInt(15, eq.getMatk());
ps2.setInt(16, eq.getWdef());
ps2.setInt(17, eq.getMdef());
ps2.setInt(18, eq.getAcc());
ps2.setInt(19, eq.getAvoid());
ps2.setInt(20, eq.getHands());
ps2.setInt(21, eq.getSpeed());
ps2.setInt(22, eq.getJump());
ps2.setInt(23, eq.getFlag());
ps2.setString(24, eq.getOwner());
} else {
ps2 = con.prepareStatement("INSERT INTO dueyitems (PackageId, itemid, quantity, flag, owner) VALUES (?, ?, ?, ?, ?)");
ps2.setInt(2, item.getItemId());