Vegas's spell + pet/mounts schedule revamp + CafePQ
Added Vega's Spell feature. Refactored mounts and pets schedules (now one thread runs globally updating stats). Fixed Pet Ignore now saving to DB. Fixed Flash Jump animation not appearing for other players just after changing jobs. Fixed 3rd job, now as a proper event with timeout. Introducing Brand-new PQ: CafePQ.
This commit is contained in:
@@ -201,7 +201,7 @@ public enum SendOpcode {
|
||||
MOVE_PET(0xAA),
|
||||
PET_CHAT(0xAB),
|
||||
PET_NAMECHANGE(0xAC),
|
||||
PET_SHOW(0xAD),
|
||||
PET_EXCEPTION_LIST(0xAD),
|
||||
PET_COMMAND(0xAE),
|
||||
SPAWN_SPECIAL_MAPOBJECT(0xAF),
|
||||
REMOVE_SPECIAL_MAPOBJECT(0xB0),
|
||||
@@ -334,7 +334,8 @@ public enum SendOpcode {
|
||||
ENABLE_TV(0x157),
|
||||
MTS_OPERATION2(0x15B),
|
||||
MTS_OPERATION(0x15C),
|
||||
VICIOUS_HAMMER(0x162);
|
||||
VICIOUS_HAMMER(0x162),
|
||||
VEGA_SCROLL(0x166);
|
||||
private int code = -2;
|
||||
|
||||
private SendOpcode(int code) {
|
||||
|
||||
41
src/net/server/MountTirednessWorker.java
Normal file
41
src/net/server/MountTirednessWorker.java
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
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>
|
||||
|
||||
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 net.server;
|
||||
|
||||
import net.server.world.World;
|
||||
|
||||
/**
|
||||
* @author Ronan
|
||||
*/
|
||||
public class MountTirednessWorker implements Runnable {
|
||||
private World wserv;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
wserv.runMountSchedule();
|
||||
}
|
||||
|
||||
public MountTirednessWorker(World world) {
|
||||
wserv = world;
|
||||
}
|
||||
}
|
||||
41
src/net/server/PetFullnessWorker.java
Normal file
41
src/net/server/PetFullnessWorker.java
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
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>
|
||||
|
||||
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 net.server;
|
||||
|
||||
import net.server.world.World;
|
||||
|
||||
/**
|
||||
* @author Ronan
|
||||
*/
|
||||
public class PetFullnessWorker implements Runnable {
|
||||
private World wserv;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
wserv.runPetSchedule();
|
||||
}
|
||||
|
||||
public PetFullnessWorker(World world) {
|
||||
wserv = world;
|
||||
}
|
||||
}
|
||||
@@ -52,12 +52,16 @@ public class AutoAssignHandler extends AbstractMaplePacketHandler {
|
||||
@Override
|
||||
public void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
MapleCharacter chr = c.getPlayer();
|
||||
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 (chr.getRemainingAp() < 1) return;
|
||||
|
||||
if(ServerConstants.USE_ANOTHER_AUTOASSIGNER == true) {
|
||||
// ---------- Ronan Lana's AUTOASSIGNER -------------
|
||||
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.
|
||||
|
||||
int str = 0, dex = 0, luk = 0, int_ = 0;
|
||||
@@ -84,6 +88,11 @@ public class AutoAssignHandler extends AbstractMaplePacketHandler {
|
||||
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());
|
||||
@@ -100,7 +109,7 @@ public class AutoAssignHandler extends AbstractMaplePacketHandler {
|
||||
MapleJob stance = c.getPlayer().getJobStyle();
|
||||
int prStat = 0, scStat = 0, trStat = 0, temp, tempAp = chr.getRemainingAp(), CAP;
|
||||
|
||||
MapleStat primary, secondary, tertiary = MapleStat.INT;
|
||||
MapleStat primary, secondary, tertiary = MapleStat.LUK;
|
||||
switch(stance) {
|
||||
case MAGICIAN:
|
||||
CAP = 165;
|
||||
@@ -124,6 +133,7 @@ public class AutoAssignHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
primary = MapleStat.INT;
|
||||
secondary = MapleStat.LUK;
|
||||
tertiary = MapleStat.DEX;
|
||||
|
||||
break;
|
||||
|
||||
@@ -197,6 +207,7 @@ public class AutoAssignHandler extends AbstractMaplePacketHandler {
|
||||
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);
|
||||
@@ -205,7 +216,6 @@ public class AutoAssignHandler extends AbstractMaplePacketHandler {
|
||||
trStat = Math.min(50 - chr.getStr(), trStat);
|
||||
trStat = Math.min(tempAp, trStat);
|
||||
tempAp -= trStat;
|
||||
tertiary = MapleStat.STR;
|
||||
}
|
||||
|
||||
temp = (20 + (chr.getLevel() / 2)) - Math.max(50, trStat + chr.getStr() + str - eqpStr);
|
||||
@@ -234,6 +244,7 @@ public class AutoAssignHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
primary = MapleStat.LUK;
|
||||
secondary = MapleStat.DEX;
|
||||
tertiary = MapleStat.STR;
|
||||
|
||||
break;
|
||||
|
||||
@@ -289,25 +300,28 @@ public class AutoAssignHandler extends AbstractMaplePacketHandler {
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
int total = 0;
|
||||
|
||||
int extras = 0;
|
||||
|
||||
total += trStat;
|
||||
extras += gainStatByType(chr, tertiary, trStat);
|
||||
extras = gainStatByType(chr, primary, statGain, statEqpd, prStat + extras);
|
||||
extras = gainStatByType(chr, secondary, statGain, statEqpd, scStat + extras);
|
||||
extras = gainStatByType(chr, tertiary, statGain, statEqpd, trStat + extras);
|
||||
|
||||
if(extras > 0) { //redistribute surplus in priority order
|
||||
extras = gainStatByType(chr, primary, statGain, statEqpd, extras);
|
||||
extras = gainStatByType(chr, secondary, statGain, statEqpd, extras);
|
||||
extras = gainStatByType(chr, tertiary, statGain, statEqpd, extras);
|
||||
gainStatByType(chr, getQuaternaryStat(stance), statGain, statEqpd, extras);
|
||||
}
|
||||
|
||||
total += scStat;
|
||||
extras += gainStatByType(chr, secondary, scStat);
|
||||
|
||||
total += prStat;
|
||||
extras += gainStatByType(chr, primary, prStat);
|
||||
|
||||
int remainingAp = (chr.getRemainingAp() - total) + 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: +" + str + "\r\nDEX: +" + dex + "\r\nINT: +" + int_ + "\r\nLUK: +" + luk));
|
||||
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 {
|
||||
int total = 0;
|
||||
@@ -317,6 +331,18 @@ public class AutoAssignHandler extends AbstractMaplePacketHandler {
|
||||
c.disconnect(false, false);
|
||||
return;
|
||||
}
|
||||
|
||||
MapleInventory iv = chr.getInventory(MapleInventoryType.EQUIPPED);
|
||||
Collection<Item> equippedC = iv.list();
|
||||
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();
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
int type = slea.readInt();
|
||||
int tempVal = slea.readInt();
|
||||
@@ -324,8 +350,7 @@ public class AutoAssignHandler extends AbstractMaplePacketHandler {
|
||||
return;
|
||||
}
|
||||
total += tempVal;
|
||||
System.out.println(tempVal);
|
||||
extras += gainStatByType(chr, MapleStat.getBy5ByteEncoding(type), tempVal);
|
||||
extras += gainStatByType(chr, MapleStat.getBy5ByteEncoding(type), statGain, statEqpd, tempVal);
|
||||
}
|
||||
int remainingAp = (chr.getRemainingAp() - total) + extras;
|
||||
chr.setRemainingAp(remainingAp);
|
||||
@@ -334,37 +359,48 @@ public class AutoAssignHandler extends AbstractMaplePacketHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private int gainStatByType(MapleCharacter chr, MapleStat type, int gain) {
|
||||
private int gainStatByType(MapleCharacter chr, MapleStat type, int[] statGain, int[] statEqpd, int gain) {
|
||||
if(gain <= 0) return 0;
|
||||
|
||||
int newVal = 0;
|
||||
if (type.equals(MapleStat.STR)) {
|
||||
newVal = chr.getStr() + gain;
|
||||
newVal = chr.getStr() + statEqpd[0] + gain;
|
||||
if (newVal > ServerConstants.MAX_AP) {
|
||||
chr.setStr(ServerConstants.MAX_AP);
|
||||
statGain[0] += gain - (newVal - ServerConstants.MAX_AP);
|
||||
chr.setStr(ServerConstants.MAX_AP - statEqpd[0]);
|
||||
} else {
|
||||
statGain[0] += gain;
|
||||
chr.setStr(newVal);
|
||||
}
|
||||
} else if (type.equals(MapleStat.INT)) {
|
||||
newVal = chr.getInt() + gain;
|
||||
newVal = chr.getInt() + statEqpd[3] + gain;
|
||||
if (newVal > ServerConstants.MAX_AP) {
|
||||
chr.setInt(ServerConstants.MAX_AP);
|
||||
statGain[3] += gain - (newVal - ServerConstants.MAX_AP);
|
||||
chr.setInt(ServerConstants.MAX_AP - statEqpd[3]);
|
||||
} else {
|
||||
statGain[3] += gain;
|
||||
chr.setInt(newVal);
|
||||
}
|
||||
} else if (type.equals(MapleStat.LUK)) {
|
||||
newVal = chr.getLuk() + gain;
|
||||
newVal = chr.getLuk() + statEqpd[2] + gain;
|
||||
if (newVal > ServerConstants.MAX_AP) {
|
||||
chr.setLuk(ServerConstants.MAX_AP);
|
||||
statGain[2] += gain - (newVal - ServerConstants.MAX_AP);
|
||||
chr.setLuk(ServerConstants.MAX_AP - statEqpd[2]);
|
||||
} else {
|
||||
statGain[2] += gain;
|
||||
chr.setLuk(newVal);
|
||||
}
|
||||
} else if (type.equals(MapleStat.DEX)) {
|
||||
newVal = chr.getDex() + gain;
|
||||
newVal = chr.getDex() + statEqpd[1] + gain;
|
||||
if (newVal > ServerConstants.MAX_AP) {
|
||||
chr.setDex(ServerConstants.MAX_AP);
|
||||
statGain[1] += gain - (newVal - ServerConstants.MAX_AP);
|
||||
chr.setDex(ServerConstants.MAX_AP - statEqpd[1]);
|
||||
} else {
|
||||
statGain[1] += gain;
|
||||
chr.setDex(newVal);
|
||||
}
|
||||
}
|
||||
|
||||
if (newVal > ServerConstants.MAX_AP) {
|
||||
chr.updateSingleStat(type, ServerConstants.MAX_AP);
|
||||
return newVal - ServerConstants.MAX_AP;
|
||||
@@ -372,4 +408,19 @@ public class AutoAssignHandler extends AbstractMaplePacketHandler {
|
||||
chr.updateSingleStat(type, newVal);
|
||||
return 0;
|
||||
}
|
||||
|
||||
private MapleStat getQuaternaryStat(MapleJob stance) {
|
||||
if(stance != MapleJob.MAGICIAN) return MapleStat.INT;
|
||||
return MapleStat.STR;
|
||||
}
|
||||
|
||||
private int getAccumulatedStatGain(int[] statGain) {
|
||||
int acc = 0;
|
||||
|
||||
for(byte i = 0; i < statGain.length; i++) {
|
||||
acc += statGain[i];
|
||||
}
|
||||
|
||||
return acc;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,6 +88,7 @@ public final class ChangeMapHandler extends AbstractMaplePacketHandler {
|
||||
chr.setStance(0);
|
||||
}
|
||||
chr.setHp(50);
|
||||
chr.updatePartyMemberHP();
|
||||
chr.changeMap(to, to.getRandomPlayerSpawnpoint());
|
||||
}
|
||||
} else if (targetid != -1) {
|
||||
|
||||
@@ -30,12 +30,17 @@ import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
public final class CharInfoRequestHandler extends AbstractMaplePacketHandler {
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
slea.readInt();
|
||||
slea.skip(4);
|
||||
int cid = slea.readInt();
|
||||
MapleMapObject target = c.getPlayer().getMap().getMapObject(cid);
|
||||
if (target != null) {
|
||||
if (target instanceof MapleCharacter) {
|
||||
c.announce(MaplePacketCreator.charInfo((MapleCharacter) target));
|
||||
MapleCharacter player = (MapleCharacter) target;
|
||||
|
||||
if(c.getPlayer().getId() != player.getId()) {
|
||||
player.exportExcludedItems(c);
|
||||
}
|
||||
c.announce(MaplePacketCreator.charInfo(player));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,11 @@ public class EnterCashShopHandler extends AbstractMaplePacketHandler {
|
||||
try {
|
||||
MapleCharacter mc = c.getPlayer();
|
||||
|
||||
if (mc.cannotEnterCashShop()) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
if (mc.getCashShop().isOpened()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -22,18 +22,35 @@
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import client.MapleClient;
|
||||
import client.MapleCharacter;
|
||||
import client.inventory.MaplePet;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
//import tools.MaplePacketCreator;
|
||||
|
||||
/**
|
||||
* @author BubblesDev
|
||||
* @author Ronan
|
||||
*/
|
||||
public final class PetExcludeItemsHandler extends AbstractMaplePacketHandler {
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
slea.readLong();
|
||||
final int petId = slea.readInt();
|
||||
slea.skip(4);
|
||||
|
||||
MapleCharacter chr = c.getPlayer();
|
||||
byte petIndex = (byte)chr.getPetIndex(petId);
|
||||
if (petIndex < 0) return;
|
||||
|
||||
final MaplePet pet = chr.getPet(petIndex);
|
||||
if (pet == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
chr.resetExcluded(petId);
|
||||
byte amount = slea.readByte();
|
||||
for (int i = 0; i < amount; i++) {
|
||||
c.getPlayer().addExcluded(slea.readInt());
|
||||
chr.addExcluded(petId, slea.readInt());
|
||||
}
|
||||
chr.commitExcludedItems();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import client.MapleCharacter;
|
||||
import constants.ExpTable;
|
||||
import client.MapleClient;
|
||||
import client.inventory.MapleInventoryType;
|
||||
import client.inventory.MaplePet;
|
||||
@@ -61,7 +60,10 @@ public final class PetFoodHandler extends AbstractMaplePacketHandler {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MaplePet pet = chr.getPet(slot);
|
||||
if(pet == null) return;
|
||||
|
||||
short pos = slea.readShort();
|
||||
int itemId = slea.readInt();
|
||||
Item use = chr.getInventory(MapleInventoryType.USE).getItem(pos);
|
||||
|
||||
@@ -21,10 +21,14 @@
|
||||
*/
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import client.MapleCharacter;
|
||||
import client.MapleClient;
|
||||
import client.inventory.MapleInventoryType;
|
||||
import client.inventory.MaplePet;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import server.maps.MapleMapItem;
|
||||
import server.maps.MapleMapObject;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
@@ -52,6 +56,30 @@ public final class PetLootHandler extends AbstractMaplePacketHandler {
|
||||
slea.skip(13);
|
||||
int oid = slea.readInt();
|
||||
MapleMapObject ob = chr.getMap().getMapObject(oid);
|
||||
if(ob == null) {
|
||||
c.getSession().write(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
if (chr.getInventory(MapleInventoryType.EQUIPPED).findById(1812007) != null) {
|
||||
final Set<Integer> petIgnore = chr.getExcludedItems();
|
||||
MapleMapItem mapitem = (MapleMapItem) ob;
|
||||
|
||||
if(!petIgnore.isEmpty()) {
|
||||
if (chr.getInventory(MapleInventoryType.EQUIPPED).findById(1812000) != null) { // Meso magnet
|
||||
if (mapitem.getMeso() > 0 && petIgnore.contains(Integer.MAX_VALUE)) {
|
||||
c.getSession().write(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
} else if (chr.getInventory(MapleInventoryType.EQUIPPED).findById(1812001) != null) { // Item Pouch
|
||||
if (petIgnore.contains(mapitem.getItem().getItemId())) {
|
||||
c.getSession().write(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
chr.pickupItem(ob, petIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,6 @@ import client.MapleFamily;
|
||||
import client.SkillFactory;
|
||||
import client.inventory.MapleInventoryType;
|
||||
import client.inventory.MaplePet;
|
||||
import client.inventory.PetDataFactory;
|
||||
import constants.GameConstants;
|
||||
import constants.ServerConstants;
|
||||
|
||||
@@ -246,7 +245,7 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
|
||||
if(newcomer) {
|
||||
for(MaplePet pet : player.getPets()) {
|
||||
if(pet != null)
|
||||
player.startFullnessSchedule(PetDataFactory.getHunger(pet.getItemId()), pet, player.getPetIndex(pet));
|
||||
world.registerPetHunger(player, player.getPetIndex(pet));
|
||||
}
|
||||
|
||||
player.reloadQuestExpirations();
|
||||
@@ -261,6 +260,9 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
|
||||
if (GameConstants.hasSPTable(player.getJob()) && player.getJob().getId() != 2001) {
|
||||
player.createDragon();
|
||||
}
|
||||
|
||||
player.commitExcludedItems();
|
||||
|
||||
if (newcomer){
|
||||
/*
|
||||
if (!c.hasVotedAlready()){
|
||||
@@ -279,5 +281,7 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
|
||||
if(ServerConstants.USE_ADD_RATES_BY_LEVEL == true) player.setPlayerRates();
|
||||
player.setWorldRates();
|
||||
player.updateCouponRates();
|
||||
|
||||
player.receivePartyMemberHP();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ public final class ScrollHandler extends AbstractMaplePacketHandler {
|
||||
if (ItemConstants.isCleanSlate(scroll.getItemId()) && !(toScroll.getLevel() + toScroll.getUpgradeSlots() < ii.getEquipStats(toScroll.getItemId()).get("tuc"))) { //upgrade slots can be over because of hammers
|
||||
return;
|
||||
}
|
||||
Equip scrolled = (Equip) ii.scrollEquipWithId(toScroll, scroll.getItemId(), whiteScroll, c.getPlayer().isGM());
|
||||
Equip scrolled = (Equip) ii.scrollEquipWithId(toScroll, scroll.getItemId(), whiteScroll, 0, c.getPlayer().isGM());
|
||||
ScrollResult scrollSuccess = Equip.ScrollResult.FAIL; // fail
|
||||
if (scrolled == null) {
|
||||
scrollSuccess = Equip.ScrollResult.CURSE;
|
||||
|
||||
@@ -24,15 +24,10 @@ package net.server.channel.handlers;
|
||||
import client.MapleCharacter;
|
||||
import java.awt.Point;
|
||||
import java.io.File;
|
||||
import java.sql.PreparedStatement;
|
||||
import client.MapleClient;
|
||||
import client.inventory.MapleInventoryType;
|
||||
import client.inventory.MaplePet;
|
||||
import client.inventory.PetDataFactory;
|
||||
import client.SkillFactory;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import tools.DatabaseConnection;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import provider.MapleDataProvider;
|
||||
import provider.MapleDataProviderFactory;
|
||||
@@ -95,7 +90,8 @@ public final class SpawnPetHandler extends AbstractMaplePacketHandler {
|
||||
chr.getMap().broadcastMessage(c.getPlayer(), MaplePacketCreator.showPet(c.getPlayer(), pet, false, false), true);
|
||||
c.announce(MaplePacketCreator.petStatUpdate(c.getPlayer()));
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
chr.startFullnessSchedule(PetDataFactory.getHunger(pet.getItemId()), pet, chr.getPetIndex(pet));
|
||||
|
||||
chr.getClient().getWorldServer().registerPetHunger(chr, chr.getPetIndex(pet));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,9 +117,6 @@ public final class SpecialMoveHandler extends AbstractMaplePacketHandler {
|
||||
int gain = lose * (ef.getY() / 100);
|
||||
chr.setMp(chr.getMp() + gain);
|
||||
chr.updateSingleStat(MapleStat.MP, chr.getMp());
|
||||
} else if (skillid == Hermit.FLASH_JUMP) {
|
||||
slea.skip(2); // always 0? Also 3rd party FJ effect doesn't seem to work, agh!
|
||||
//chr.getMap().broadcastMessage(c.getPlayer(), MaplePacketCreator.showBuffeffect(chr.getId(), skillid, chr.getSkillLevel(skillid), (byte)0), false);
|
||||
} else if (skillid == Priest.DISPEL || skillid == SuperGM.HEAL_PLUS_DISPEL) {
|
||||
slea.skip((skillid == Priest.DISPEL) ? 10 : 11);
|
||||
chr.getMap().broadcastMessage(c.getPlayer(), MaplePacketCreator.showBuffeffect(chr.getId(), skillid, chr.getSkillLevel(skillid)), false);
|
||||
|
||||
@@ -85,28 +85,32 @@ public final class TakeDamageHandler extends AbstractMaplePacketHandler {
|
||||
return;
|
||||
}
|
||||
if (damage > 0) {
|
||||
loseItems = map.getMonsterById(monsteridfrom).getStats().loseItem();
|
||||
if (loseItems != null) {
|
||||
MapleInventoryType type;
|
||||
final int playerpos = player.getPosition().x;
|
||||
byte d = 1;
|
||||
Point pos = new Point(0, player.getPosition().y);
|
||||
for (loseItem loseItem : loseItems) {
|
||||
type = MapleItemInformationProvider.getInstance().getInventoryType(loseItem.getId());
|
||||
for (byte b = 0; b < loseItem.getX(); b++) {//LOL?
|
||||
if (Randomizer.nextInt(101) >= loseItem.getChance()) {
|
||||
if (player.haveItem(loseItem.getId())) {
|
||||
pos.x = (int) (playerpos + ((d % 2 == 0) ? (25 * (d + 1) / 2) : -(25 * (d / 2))));
|
||||
MapleInventoryManipulator.removeById(c, type, loseItem.getId(), 1, false, false);
|
||||
map.spawnItemDrop(c.getPlayer(), c.getPlayer(), new Item(loseItem.getId(), (short) 0, (short) 1), map.calcDropPos(pos, player.getPosition()), true, true);
|
||||
d++;
|
||||
} else {
|
||||
break;
|
||||
MapleMonster assaulter = map.getMonsterById(monsteridfrom);
|
||||
|
||||
if(assaulter != null) {
|
||||
loseItems = assaulter.getStats().loseItem();
|
||||
if (loseItems != null) {
|
||||
MapleInventoryType type;
|
||||
final int playerpos = player.getPosition().x;
|
||||
byte d = 1;
|
||||
Point pos = new Point(0, player.getPosition().y);
|
||||
for (loseItem loseItem : loseItems) {
|
||||
type = MapleItemInformationProvider.getInstance().getInventoryType(loseItem.getId());
|
||||
for (byte b = 0; b < loseItem.getX(); b++) {//LOL?
|
||||
if (Randomizer.nextInt(101) >= loseItem.getChance()) {
|
||||
if (player.haveItem(loseItem.getId())) {
|
||||
pos.x = (int) (playerpos + ((d % 2 == 0) ? (25 * (d + 1) / 2) : -(25 * (d / 2))));
|
||||
MapleInventoryManipulator.removeById(c, type, loseItem.getId(), 1, false, false);
|
||||
map.spawnItemDrop(c.getPlayer(), c.getPlayer(), new Item(loseItem.getId(), (short) 0, (short) 1), map.calcDropPos(pos, player.getPosition()), true, true);
|
||||
d++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
map.removeMapObject(attacker);
|
||||
}
|
||||
map.removeMapObject(attacker);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -28,9 +28,11 @@ import client.MapleStat;
|
||||
import client.Skill;
|
||||
import client.SkillFactory;
|
||||
import client.inventory.Equip;
|
||||
import client.inventory.Equip.ScrollResult;
|
||||
import client.inventory.Item;
|
||||
import client.inventory.MapleInventoryType;
|
||||
import client.inventory.MaplePet;
|
||||
import client.inventory.ModifyInventory;
|
||||
import constants.ItemConstants;
|
||||
|
||||
import java.sql.SQLException;
|
||||
@@ -56,7 +58,7 @@ public final class UseCashItemHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
MapleCharacter player = c.getPlayer();
|
||||
final MapleCharacter player = c.getPlayer();
|
||||
if (System.currentTimeMillis() - player.getLastUsedCashItem() < 3000) {
|
||||
player.dropMessage(1, "You have used a cash item recently. Wait a moment and try again.");
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
@@ -514,7 +516,65 @@ public final class UseCashItemHandler extends AbstractMaplePacketHandler {
|
||||
c.announce(MaplePacketCreator.sendHammerData(equip.getVicious()));
|
||||
player.forceUpdateItem(equip);
|
||||
} else if (itemType == 561) { //VEGA'S SPELL
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
if (slea.readInt() != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
final byte eSlot = (byte) slea.readInt();
|
||||
final Item eitem = c.getPlayer().getInventory(MapleInventoryType.EQUIP).getItem(eSlot);
|
||||
|
||||
if (slea.readInt() != 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
final byte uSlot = (byte) slea.readInt();
|
||||
final Item uitem = c.getPlayer().getInventory(MapleInventoryType.USE).getItem(uSlot);
|
||||
if (eitem == null || uitem == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
//should have a check here against PE hacks
|
||||
|
||||
Equip toScroll = (Equip) eitem;
|
||||
if (toScroll.getUpgradeSlots() < 1) {
|
||||
c.getSession().write(MaplePacketCreator.getInventoryFull());
|
||||
return;
|
||||
}
|
||||
|
||||
c.getPlayer().toggleBlockCashShop();
|
||||
|
||||
final int curlevel = toScroll.getLevel();
|
||||
c.getSession().write(MaplePacketCreator.sendVegaScroll(0x40));
|
||||
|
||||
final Equip scrolled = (Equip) ii.scrollEquipWithId(toScroll, uitem.getItemId(), false, itemId, c.getPlayer().isGM());
|
||||
c.getSession().write(MaplePacketCreator.sendVegaScroll(scrolled.getLevel() > curlevel ? 0x41 : 0x43));
|
||||
//opcodes 0x42, 0x44: "this item cannot be used"; 0x39, 0x45: crashes
|
||||
|
||||
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.USE, uSlot, (short) 1, false);
|
||||
remove(c, itemId);
|
||||
|
||||
final MapleClient client = c;
|
||||
TimerManager.getInstance().schedule(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if(!player.isLoggedin()) return;
|
||||
|
||||
player.toggleBlockCashShop();
|
||||
|
||||
final List<ModifyInventory> mods = new ArrayList<>();
|
||||
mods.add(new ModifyInventory(3, scrolled));
|
||||
mods.add(new ModifyInventory(0, scrolled));
|
||||
client.announce(MaplePacketCreator.modifyInventory(true, mods));
|
||||
|
||||
ScrollResult scrollResult = scrolled.getLevel() > curlevel ? ScrollResult.SUCCESS : ScrollResult.FAIL;
|
||||
player.getMap().broadcastMessage(MaplePacketCreator.getScrollEffect(player.getId(), scrollResult, false));
|
||||
if (eSlot < 0 && (scrollResult == ScrollResult.SUCCESS)) {
|
||||
player.equipChanged();
|
||||
}
|
||||
|
||||
client.getSession().write(MaplePacketCreator.enableActions());
|
||||
}
|
||||
}, 1000 * 3);
|
||||
} else {
|
||||
System.out.println("NEW CASH ITEM: " + itemType + "\n" + slea.toString());
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
|
||||
@@ -33,6 +33,7 @@ import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.HashMap;
|
||||
@@ -41,7 +42,11 @@ import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
|
||||
import server.TimerManager;
|
||||
import net.server.PetFullnessWorker;
|
||||
import net.server.MountTirednessWorker;
|
||||
import net.server.PlayerStorage;
|
||||
import net.server.Server;
|
||||
import net.server.channel.Channel;
|
||||
@@ -49,7 +54,6 @@ import net.server.channel.CharacterIdChannelPair;
|
||||
import net.server.guild.MapleGuild;
|
||||
import net.server.guild.MapleGuildCharacter;
|
||||
import net.server.guild.MapleGuildSummary;
|
||||
import tools.LogHelper;
|
||||
import tools.DatabaseConnection;
|
||||
import tools.MaplePacketCreator;
|
||||
|
||||
@@ -70,6 +74,14 @@ public class World {
|
||||
private Map<Integer, MapleGuildSummary> gsStore = new HashMap<>();
|
||||
private PlayerStorage players = new PlayerStorage();
|
||||
private Set<Integer> queuedGuilds = new HashSet<>();
|
||||
|
||||
private Map<Integer, Byte> activePets = new LinkedHashMap<>();
|
||||
private ScheduledFuture<?> petsSchedule;
|
||||
private long petUpdate;
|
||||
|
||||
private Map<Integer, Byte> activeMounts = new LinkedHashMap<>();
|
||||
private ScheduledFuture<?> mountsSchedule;
|
||||
private long mountUpdate;
|
||||
|
||||
public World(int world, int flag, String eventmsg, int exprate, int droprate, int mesorate, int bossdroprate) {
|
||||
this.id = world;
|
||||
@@ -81,6 +93,12 @@ public class World {
|
||||
this.bossdroprate = bossdroprate;
|
||||
runningPartyId.set(1);
|
||||
runningMessengerId.set(1);
|
||||
|
||||
petUpdate = System.currentTimeMillis();
|
||||
mountUpdate = petUpdate;
|
||||
|
||||
petsSchedule = TimerManager.getInstance().register(new PetFullnessWorker(this), 60 * 1000, 60 * 1000);
|
||||
mountsSchedule = TimerManager.getInstance().register(new MountTirednessWorker(this), 60 * 1000, 60 * 1000);
|
||||
}
|
||||
|
||||
public List<Channel> getChannels() {
|
||||
@@ -181,7 +199,7 @@ public class World {
|
||||
channels.get(chr.getClient().getChannel() - 1).removePlayer(chr);
|
||||
players.removePlayer(chr.getId());
|
||||
}
|
||||
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
@@ -657,6 +675,100 @@ public class World {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Integer getPetKey(MapleCharacter chr, byte petSlot) { // assuming max 3 pets
|
||||
return (chr.getId() << 2) + petSlot;
|
||||
}
|
||||
|
||||
public void registerPetHunger(MapleCharacter chr, byte petSlot) {
|
||||
if(chr.isGM() && ServerConstants.GM_PETS_NEVER_HUNGRY || ServerConstants.PETS_NEVER_HUNGRY) {
|
||||
return;
|
||||
}
|
||||
|
||||
Integer key = getPetKey(chr, petSlot);
|
||||
synchronized(activePets) {
|
||||
byte initProc;
|
||||
if(System.currentTimeMillis() - petUpdate > 55000) initProc = ServerConstants.PET_EXHAUST_COUNT - 2;
|
||||
else initProc = ServerConstants.PET_EXHAUST_COUNT - 1;
|
||||
|
||||
activePets.put(key, initProc);
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterPetHunger(MapleCharacter chr, byte petSlot) {
|
||||
Integer key = getPetKey(chr, petSlot);
|
||||
synchronized(activePets) {
|
||||
activePets.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
public void runPetSchedule() {
|
||||
Map<Integer, Byte> deployedPets;
|
||||
synchronized(activePets) {
|
||||
petUpdate = System.currentTimeMillis();
|
||||
deployedPets = Collections.unmodifiableMap(activePets);
|
||||
}
|
||||
|
||||
for(Map.Entry<Integer, Byte> dp: deployedPets.entrySet()) {
|
||||
MapleCharacter chr = this.getPlayerStorage().getCharacterById(dp.getKey() / 4);
|
||||
if(chr == null || !chr.isLoggedin()) continue;
|
||||
|
||||
Byte dpVal = (byte)(dp.getValue() + 1);
|
||||
if(dpVal == ServerConstants.PET_EXHAUST_COUNT) {
|
||||
chr.runFullnessSchedule(dp.getKey() % 4);
|
||||
dpVal = 0;
|
||||
}
|
||||
|
||||
synchronized(activePets) {
|
||||
activePets.put(dp.getKey(), dpVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void registerMountHunger(MapleCharacter chr) {
|
||||
if(chr.isGM() && ServerConstants.GM_PETS_NEVER_HUNGRY || ServerConstants.PETS_NEVER_HUNGRY) {
|
||||
return;
|
||||
}
|
||||
|
||||
Integer key = chr.getId();
|
||||
synchronized(activeMounts) {
|
||||
byte initProc;
|
||||
if(System.currentTimeMillis() - mountUpdate > 45000) initProc = ServerConstants.MOUNT_EXHAUST_COUNT - 2;
|
||||
else initProc = ServerConstants.MOUNT_EXHAUST_COUNT - 1;
|
||||
|
||||
activeMounts.put(key, initProc);
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterMountHunger(MapleCharacter chr) {
|
||||
Integer key = chr.getId();
|
||||
synchronized(activeMounts) {
|
||||
activeMounts.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
public void runMountSchedule() {
|
||||
Map<Integer, Byte> deployedMounts;
|
||||
synchronized(activeMounts) {
|
||||
mountUpdate = System.currentTimeMillis();
|
||||
deployedMounts = Collections.unmodifiableMap(activeMounts);
|
||||
}
|
||||
|
||||
for(Map.Entry<Integer, Byte> dp: deployedMounts.entrySet()) {
|
||||
MapleCharacter chr = this.getPlayerStorage().getCharacterById(dp.getKey());
|
||||
if(chr == null || !chr.isLoggedin()) continue;
|
||||
|
||||
Byte dpVal = (byte)(dp.getValue() + 1);
|
||||
if(dpVal == ServerConstants.MOUNT_EXHAUST_COUNT) {
|
||||
chr.runTirednessSchedule();
|
||||
dpVal = 0;
|
||||
}
|
||||
|
||||
synchronized(activeMounts) {
|
||||
activeMounts.put(dp.getKey(), dpVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setServerMessage(String msg) {
|
||||
for (Channel ch : channels) {
|
||||
@@ -674,6 +786,17 @@ public class World {
|
||||
for (Channel ch : getChannels()) {
|
||||
ch.shutdown();
|
||||
}
|
||||
|
||||
if(petsSchedule != null) {
|
||||
petsSchedule.cancel(false);
|
||||
petsSchedule = null;
|
||||
}
|
||||
|
||||
if(mountsSchedule != null) {
|
||||
mountsSchedule.cancel(false);
|
||||
mountsSchedule = null;
|
||||
}
|
||||
|
||||
players.disconnectAll();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user