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:
ronancpl
2017-09-08 14:36:58 -03:00
parent 74b4ca4132
commit e064d5cbfa
210 changed files with 35382 additions and 46792 deletions
+287 -94
View File
@@ -115,6 +115,7 @@ import client.inventory.MapleInventoryType;
import client.inventory.MaplePet;
import client.inventory.MapleWeaponType;
import client.inventory.ModifyInventory;
import client.inventory.PetDataFactory;
import constants.ExpTable;
import constants.GameConstants;
import constants.ItemConstants;
@@ -254,8 +255,10 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
private ScheduledFuture<?> pendantOfSpirit = null; //1122017
private List<ScheduledFuture<?>> timers = new ArrayList<>();
private Lock chrLock = new ReentrantLock();
private Lock petLock = new ReentrantLock();
private NumberFormat nf = new DecimalFormat("#,###,###,###");
private ArrayList<Integer> excluded = new ArrayList<>();
private Map<Integer, Set<Integer>> excluded = new LinkedHashMap<>();
private Set<Integer> excludedItems = new LinkedHashSet<>();
private List<MapleRing> crushRings = new ArrayList<>();
private List<MapleRing> friendshipRings = new ArrayList<>();
private static String[] ariantroomleader = new String[3];
@@ -266,6 +269,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
private Map<Short, String> area_info = new LinkedHashMap<>();
private AutobanManager autoban;
private boolean isbanned = false;
private boolean blockCashShop = false;
private byte pendantExp = 0, lastmobcount = 0, doorSlot = -1;
private List<Integer> trockmaps = new ArrayList<>();
private List<Integer> viptrockmaps = new ArrayList<>();
@@ -479,10 +483,6 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
}
public void addExcluded(int x) {
excluded.add(x);
}
public void addFame(int famechange) {
this.fame += famechange;
}
@@ -513,11 +513,16 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
public void addPet(MaplePet pet) {
for (int i = 0; i < 3; i++) {
if (pets[i] == null) {
pets[i] = pet;
return;
petLock.lock();
try {
for (int i = 0; i < 3; i++) {
if (pets[i] == null) {
pets[i] = pet;
return;
}
}
} finally {
petLock.unlock();
}
}
@@ -775,6 +780,14 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
public void setLastMobCount(byte count) {
lastmobcount = count;
}
public boolean cannotEnterCashShop() {
return blockCashShop;
}
public void toggleBlockCashShop() {
blockCashShop = !blockCashShop;
}
public void newClient(MapleClient c) {
this.loggedIn = true;
@@ -895,7 +908,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
if (effect.isMonsterRiding()) {
if (effect.getSourceId() != Corsair.BATTLE_SHIP) {
this.getMount().cancelSchedule();
this.getClient().getWorldServer().unregisterMountHunger(this);
this.getMount().setActive(false);
}
}
@@ -962,12 +975,6 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
Hide(!isHidden());
}
private void cancelFullnessSchedule(int petSlot) {
if (fullnessSchedule[petSlot] != null) {
fullnessSchedule[petSlot].cancel(false);
}
}
public void cancelMagicDoor() {
List<MapleBuffStatValueHolder> mbsvhList;
@@ -1028,7 +1035,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
public void setMasteries(int jobId) {
int[] skills = new int[4];
for (int i = 0; i > skills.length; i++) {
skills[i] = 0; //that initalization meng
skills[i] = 0; //that initialization meng
}
if (jobId == 112) {
skills[0] = Hero.ACHILLES;
@@ -1094,6 +1101,9 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
for (Integer skillId : skills) {
if (skillId != 0) {
Skill skill = SkillFactory.getSkill(skillId);
final int skilllevel = getSkillLevel(skill);
if(skilllevel > 0) continue;
changeSkillLevel(skill, (byte) 0, 10, -1);
}
}
@@ -1161,7 +1171,11 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
setMasteries(this.job.getId());
guildUpdate();
getMap().broadcastMessage(this, MaplePacketCreator.removePlayerFromMap(this.getId()), false);
getMap().broadcastMessage(this, MaplePacketCreator.spawnPlayerMapobject(this), false);
getMap().broadcastMessage(this, MaplePacketCreator.showForeignEffect(getId(), 8), false);
if (GameConstants.hasSPTable(newJob) && newJob.getId() != 2001) {
if (getBuffedValue(MapleBuffStat.MONSTER_RIDING) != null) {
cancelBuffStats(MapleBuffStat.MONSTER_RIDING);
@@ -1205,7 +1219,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
return new Pair<>(this.banishMap, this.banishSp);
}
private void clearBanishPlayerData() {
public void clearBanishPlayerData() {
this.banishMap = -1;
this.banishSp = -1;
this.banishTime = 0;
@@ -1316,7 +1330,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
if(mbs.getKey() == MapleBuffStat.MAP_PROTECTION) {
byte value = (byte)mbs.getValue().value;
if(value == 1 && thisMap.getReturnMapId() == 211000000) return true; //protection from cold
if(value == 1 && (thisMap.getReturnMapId() == 211000000 || thisMap.getReturnMapId() == 193000000)) return true; //protection from cold
else if(value == 2 && (thisMap.getReturnMapId() == 211000000 || thisMap.getReturnMapId() == 230000000)) return true; //breathing underwater
else return false;
}
@@ -2738,8 +2752,86 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
return eventInstance;
}
public ArrayList<Integer> getExcluded() {
return excluded;
public void resetExcluded(int petId) {
chrLock.lock();
try {
Set<Integer> petExclude = excluded.get(petId);
if(petExclude != null) petExclude.clear();
else excluded.put(petId, new LinkedHashSet<Integer>());
} finally {
chrLock.unlock();
}
}
public void addExcluded(int petId, int x) {
chrLock.lock();
try {
excluded.get(petId).add(x);
} finally {
chrLock.unlock();
}
}
public void commitExcludedItems() {
Map<Integer, Set<Integer>> petExcluded = this.getExcluded();
chrLock.lock();
try {
excludedItems.clear();
} finally {
chrLock.unlock();
}
for(Map.Entry<Integer, Set<Integer>> pe : petExcluded.entrySet()) {
byte petIndex = this.getPetIndex(pe.getKey());
if(petIndex < 0) continue;
Set<Integer> exclItems = pe.getValue();
if (!exclItems.isEmpty()) {
client.announce(MaplePacketCreator.loadExceptionList(this.getId(), pe.getKey(), petIndex, new ArrayList<>(exclItems)));
chrLock.lock();
try {
for(Integer itemid: exclItems) {
excludedItems.add(itemid);
}
} finally {
chrLock.unlock();
}
}
}
}
public void exportExcludedItems(MapleClient c) {
Map<Integer, Set<Integer>> petExcluded = this.getExcluded();
for(Map.Entry<Integer, Set<Integer>> pe : petExcluded.entrySet()) {
byte petIndex = this.getPetIndex(pe.getKey());
if(petIndex < 0) continue;
Set<Integer> exclItems = pe.getValue();
if (!exclItems.isEmpty()) {
c.announce(MaplePacketCreator.loadExceptionList(this.getId(), pe.getKey(), petIndex, new ArrayList<>(exclItems)));
}
}
}
public Map<Integer, Set<Integer>> getExcluded() {
chrLock.lock();
try {
return Collections.unmodifiableMap(excluded);
} finally {
chrLock.unlock();
}
}
public Set<Integer> getExcludedItems() {
chrLock.lock();
try {
return Collections.unmodifiableSet(excludedItems);
} finally {
chrLock.unlock();
}
}
public int getExp() {
@@ -3177,22 +3269,32 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
public int getNextEmptyPetIndex() {
for (int i = 0; i < 3; i++) {
if (pets[i] == null) {
return i;
petLock.lock();
try {
for (int i = 0; i < 3; i++) {
if (pets[i] == null) {
return i;
}
}
return 3;
} finally {
petLock.unlock();
}
return 3;
}
public int getNoPets() {
int ret = 0;
for (int i = 0; i < 3; i++) {
if (pets[i] != null) {
ret++;
petLock.lock();
try {
int ret = 0;
for (int i = 0; i < 3; i++) {
if (pets[i] != null) {
ret++;
}
}
return ret;
} finally {
petLock.unlock();
}
return ret;
}
public int getNumControlledMonsters() {
@@ -3345,33 +3447,55 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
public MaplePet[] getPets() {
return pets;
petLock.lock();
try {
return Arrays.copyOf(pets, pets.length);
} finally {
petLock.unlock();
}
}
public MaplePet getPet(int index) {
return pets[index];
if(index < 0) return null;
petLock.lock();
try {
return pets[index];
} finally {
petLock.unlock();
}
}
public byte getPetIndex(int petId) {
for (byte i = 0; i < 3; i++) {
if (pets[i] != null) {
if (pets[i].getUniqueId() == petId) {
return i;
petLock.lock();
try {
for (byte i = 0; i < 3; i++) {
if (pets[i] != null) {
if (pets[i].getUniqueId() == petId) {
return i;
}
}
}
return -1;
} finally {
petLock.unlock();
}
return -1;
}
public byte getPetIndex(MaplePet pet) {
for (byte i = 0; i < 3; i++) {
if (pets[i] != null) {
if (pets[i].getUniqueId() == pet.getUniqueId()) {
return i;
petLock.lock();
try {
for (byte i = 0; i < 3; i++) {
if (pets[i] != null) {
if (pets[i].getUniqueId() == pet.getUniqueId()) {
return i;
}
}
}
return -1;
} finally {
petLock.unlock();
}
return -1;
}
public int getPossibleReports() {
@@ -4404,6 +4528,29 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
}
}
PreparedStatement ps2;
ResultSet rs2;
for(byte i = 0; i < 3; i++) {
MaplePet pet = ret.getPet(i);
if(pet == null) continue;
int petId = pet.getUniqueId();
ps2 = con.prepareStatement("SELECT itemid FROM petignores WHERE petid = ?"); // Get pet details..
ps2.setInt(1, petId);
ret.resetExcluded(petId);
rs2 = ps2.executeQuery();
while(rs2.next()) {
ret.addExcluded(petId, rs2.getInt("itemid"));
}
ps2.close();
rs2.close();
}
ret.commitExcludedItems();
if (channelserver) {
MapleMapFactory mapFactory = client.getChannelServer().getMapFactory();
ret.map = mapFactory.getMap(ret.mapid);
@@ -5124,26 +5271,31 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
public void removePet(MaplePet pet, boolean shift_left) {
int slot = -1;
for (int i = 0; i < 3; i++) {
if (pets[i] != null) {
if (pets[i].getUniqueId() == pet.getUniqueId()) {
pets[i] = null;
slot = i;
break;
}
}
}
if (shift_left) {
if (slot > -1) {
for (int i = slot; i < 3; i++) {
if (i != 2) {
pets[i] = pets[i + 1];
} else {
petLock.lock();
try {
int slot = -1;
for (int i = 0; i < 3; i++) {
if (pets[i] != null) {
if (pets[i].getUniqueId() == pet.getUniqueId()) {
pets[i] = null;
slot = i;
break;
}
}
}
if (shift_left) {
if (slot > -1) {
for (int i = slot; i < 3; i++) {
if (i != 2) {
pets[i] = pets[i + 1];
} else {
pets[i] = null;
}
}
}
}
} finally {
petLock.unlock();
}
}
@@ -5484,11 +5636,34 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
if (updateRows < 1) {
throw new RuntimeException("Character not in database (" + id + ")");
}
for (int i = 0; i < 3; i++) {
if (pets[i] != null) {
pets[i].saveToDb();
petLock.lock();
try {
for (int i = 0; i < 3; i++) {
if (pets[i] != null) {
pets[i].saveToDb();
}
}
} finally {
petLock.unlock();
}
for(Entry<Integer, Set<Integer>> es: getExcluded().entrySet()) {
try (PreparedStatement ps2 = con.prepareStatement("DELETE FROM petignores WHERE petid=?")) {
ps2.setInt(1, es.getKey());
ps2.executeUpdate();
}
try (PreparedStatement ps2 = con.prepareStatement("INSERT INTO petignores (petid, itemid) VALUES (?, ?)")) {
ps2.setInt(1, es.getKey());
for(Integer x: es.getValue()) {
ps2.setInt(2, x);
ps2.addBatch();
}
ps2.executeBatch();
}
}
deleteWhereCharacterId(con, "DELETE FROM keymap WHERE characterid = ?");
ps = con.prepareStatement("INSERT INTO keymap (characterid, `key`, `type`, `action`) VALUES (?, ?, ?, ?)");
ps.setInt(1, id);
@@ -6212,10 +6387,15 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
public void shiftPetsRight() {
if (pets[2] == null) {
pets[2] = pets[1];
pets[1] = pets[0];
pets[0] = null;
petLock.lock();
try {
if (pets[2] == null) {
pets[2] = pets[1];
pets[1] = pets[0];
pets[0] = null;
}
} finally {
petLock.unlock();
}
}
@@ -6297,32 +6477,37 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
return coolDowns.containsKey(Integer.valueOf(skillId));
}
public void startFullnessSchedule(final int decrease, final MaplePet pet, int petSlot) {
if(isGM() && ServerConstants.GM_PETS_NEVER_HUNGRY || ServerConstants.PETS_NEVER_HUNGRY) {
return;
}
public void runFullnessSchedule(int petSlot) {
MaplePet pet = getPet(petSlot);
if(pet == null) return;
ScheduledFuture<?> schedule;
schedule = TimerManager.getInstance().register(new Runnable() {
@Override
public void run() {
int newFullness = pet.getFullness() - decrease;
if (newFullness <= 5) {
pet.setFullness(15);
pet.saveToDb();
unequipPet(pet, true);
} else {
pet.setFullness(newFullness);
pet.saveToDb();
Item petz = getInventory(MapleInventoryType.CASH).getItem(pet.getPosition());
if (petz != null) {
forceUpdateItem(petz);
}
}
int newFullness = pet.getFullness() - PetDataFactory.getHunger(pet.getItemId());
if (newFullness <= 5) {
pet.setFullness(15);
pet.saveToDb();
unequipPet(pet, true);
dropMessage(6, "Your pet grew hungry! Treat it some pet food to keep it healthy!");
} else {
pet.setFullness(newFullness);
pet.saveToDb();
Item petz = getInventory(MapleInventoryType.CASH).getItem(pet.getPosition());
if (petz != null) {
forceUpdateItem(petz);
}
}, 180000, 18000);
fullnessSchedule[petSlot] = schedule;
}
}
public void runTirednessSchedule() {
if(maplemount != null) {
int tiredness = maplemount.incrementAndGetTiredness();
this.getMap().broadcastMessage(MaplePacketCreator.updateMount(this.getId(), maplemount, false));
if (tiredness > 99) {
maplemount.setTiredness(99);
this.dispelSkill(this.getJobType() * 10000000 + 1004);
this.dropMessage(6, "Your mount grew tired! Treat it some revitalizer before riding it again!");
}
}
}
public void startMapEffect(String msg, int itemId) {
@@ -6346,8 +6531,9 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
public void unequipAllPets() {
for (int i = 0; i < 3; i++) {
if (pets[i] != null) {
unequipPet(pets[i], true);
MaplePet pet = getPet(i);
if (pet != null) {
unequipPet(pet, true);
}
}
}
@@ -6361,11 +6547,13 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
this.getPet(this.getPetIndex(pet)).setSummoned(false);
this.getPet(this.getPetIndex(pet)).saveToDb();
}
cancelFullnessSchedule(getPetIndex(pet));
this.getClient().getWorldServer().unregisterPetHunger(this, getPetIndex(pet));
getMap().broadcastMessage(this, MaplePacketCreator.showPet(this, pet, true, hunger), true);
removePet(pet, shift_left);
client.announce(MaplePacketCreator.petStatUpdate(this));
client.announce(MaplePacketCreator.enableActions());
removePet(pet, shift_left);
}
public void updateMacros(int position, SkillMacro updateMacro) {
@@ -6832,6 +7020,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
public void showAllEquipFeatures() {
MapleItemInformationProvider mii = MapleItemInformationProvider.getInstance();
String showMsg = "";
for (Item item : getInventory(MapleInventoryType.EQUIPPED).list()) {
Equip nEquip = (Equip) item;
@@ -6840,7 +7029,11 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
continue;
}
nEquip.showEquipFeatures(client);
showMsg += nEquip.showEquipFeatures(client);
}
if(!showMsg.isEmpty()) {
this.showHint("#ePLAYER EQUIPMENTS:#n\r\n\r\n" + showMsg);
}
}
+2 -1
View File
@@ -154,7 +154,7 @@ public class MapleClient {
}
public void sendCharList(int server) {
this.session.write(MaplePacketCreator.getCharList(this, server));
this.announce(MaplePacketCreator.getCharList(this, server));
}
public List<MapleCharacter> loadCharacters(int serverId) {
@@ -1318,6 +1318,7 @@ public class MapleClient {
}
player.getInventory(MapleInventoryType.EQUIPPED).checked(false); //test
player.getMap().removePlayer(player);
player.clearBanishPlayerData();
player.getClient().getChannelServer().removePlayer(player);
player.getClient().updateLoginState(MapleClient.LOGIN_SERVER_TRANSITION);
try {
+5 -37
View File
@@ -21,10 +21,6 @@
*/
package client;
import java.util.concurrent.ScheduledFuture;
import server.TimerManager;
import tools.MaplePacketCreator;
/**
* @author PurpleMadness Patrick :O
*/
@@ -34,7 +30,6 @@ public class MapleMount {
private int tiredness;
private int exp;
private int level;
private ScheduledFuture<?> tirednessSchedule;
private MapleCharacter owner;
private boolean active;
@@ -95,21 +90,10 @@ public class MapleMount {
tiredness = 0;
}
}
private void increaseTiredness() {
if(owner != null) {
this.tiredness++;
owner.getMap().broadcastMessage(MaplePacketCreator.updateMount(owner.getId(), this, false));
if (tiredness > 99) {
this.tiredness = 99;
owner.dispelSkill(owner.getJobType() * 10000000 + 1004);
owner.dropMessage(6, "Your mount grew tired! Treat it some revitalizer before riding it again!");
}
} else {
if(this.tirednessSchedule != null) {
this.tirednessSchedule.cancel(false);
}
}
public int incrementAndGetTiredness() {
this.tiredness++;
return this.tiredness;
}
public void setExp(int newexp) {
@@ -124,21 +108,6 @@ public class MapleMount {
this.itemid = newitemid;
}
public void startSchedule() {
this.tirednessSchedule = TimerManager.getInstance().register(new Runnable() {
@Override
public void run() {
increaseTiredness();
}
}, 60000, 60000);
}
public void cancelSchedule() {
if (this.tirednessSchedule != null) {
this.tirednessSchedule.cancel(false);
}
}
public void setActive(boolean set) {
this.active = set;
}
@@ -148,8 +117,7 @@ public class MapleMount {
}
public void empty() {
cancelSchedule();
this.tirednessSchedule = null;
if(owner != null) owner.getClient().getWorldServer().unregisterMountHunger(owner);
this.owner = null;
}
}
+81 -53
View File
@@ -489,42 +489,41 @@ public class Commands {
case "equiplv":
player.showAllEquipFeatures();
break;
case "rates":
//c.resetVoteTime();
player.yellowMessage("BOSSDROP RATE");
player.message(">>Total BOSSDROP Rate: " + c.getWorldServer().getBossDropRate() + "x");
player.message(">>------------------------------------------------");
case "showrates":
String showMsg = "#eEXP RATE#n" + "\r\n";
showMsg += "Server EXP Rate: #k" + c.getWorldServer().getExpRate() + "x#k" + "\r\n";
showMsg += "Player EXP Rate: #k" + player.getRawExpRate() + "x#k" + "\r\n";
if(player.getCouponExpRate() != 1) showMsg += "Coupon EXP Rate: #k" + player.getCouponExpRate() + "x#k" + "\r\n";
showMsg += "EXP Rate: #e#b" + player.getExpRate() + "x#k#n" + "\r\n";
player.yellowMessage("DROP RATE");
player.message(">>Base DROP Rate: " + c.getWorldServer().getDropRate() + "x");
player.message(">>Your DROP Rate: " + player.getRawDropRate() + "x");
if(player.getCouponDropRate() != 1) player.message(">>Your Coupon DROP Rate: " + player.getCouponDropRate() + "x");
player.message(">>------------------------------------------------");
player.message(">>Total DROP Rate: " + player.getDropRate() + "x");
player.yellowMessage("MESO RATE");
player.message(">>Base MESO Rate: " + c.getWorldServer().getMesoRate() + "x");
player.message(">>Your MESO Rate: " + player.getRawMesoRate() + "x");
if(player.getCouponMesoRate() != 1) player.message(">>Your Coupon MESO Rate: " + player.getCouponMesoRate() + "x");
player.message(">>------------------------------------------------");
player.message(">>Total MESO Rate: " + player.getMesoRate() + "x");
player.yellowMessage("EXP RATE");
player.message(">>Base EXP Rate: " + c.getWorldServer().getExpRate() + "x");
player.message(">>Your EXP Rate: " + player.getRawExpRate() + "x");
if(player.getCouponExpRate() != 1) player.message(">>Your Coupon EXP Rate: " + player.getCouponExpRate() + "x");
player.message(">>------------------------------------------------");
player.message(">>Total EXP Rate: " + player.getExpRate() + "x");
/*if(c.getWorldServer().getExpRate() > ServerConstants.EXP_RATE) {
player.message(">>Event EXP bonus: " + (c.getWorldServer().getExpRate() - ServerConstants.EXP_RATE) + "x");
}
player.message(">>Voted EXP bonus: " + (c.hasVotedAlready() ? "1x" : "0x (If you vote now, you will earn an additional 1x EXP!)"));
if (player.getLevel() < 10) {
player.message("Players under level 10 always have 1x exp.");
}*/
break;
showMsg += "\r\n" + "#eMESO RATE#n" + "\r\n";
showMsg += "Server MESO Rate: #k" + c.getWorldServer().getMesoRate() + "x#k" + "\r\n";
showMsg += "Player MESO Rate: #k" + player.getRawMesoRate() + "x#k" + "\r\n";
if(player.getCouponMesoRate() != 1) showMsg += "Coupon MESO Rate: #k" + player.getCouponMesoRate() + "x#k" + "\r\n";
showMsg += "MESO Rate: #e#b" + player.getMesoRate() + "x#k#n" + "\r\n";
showMsg += "\r\n" + "#eDROP RATE#n" + "\r\n";
showMsg += "Server DROP Rate: #k" + c.getWorldServer().getDropRate() + "x#k" + "\r\n";
showMsg += "Player DROP Rate: #k" + player.getRawDropRate() + "x#k" + "\r\n";
if(player.getCouponDropRate() != 1) showMsg += "Coupon DROP Rate: #k" + player.getCouponDropRate() + "x#k" + "\r\n";
showMsg += "DROP Rate: #e#b" + player.getDropRate() + "x#k#n" + "\r\n";
showMsg += "\r\n" + "#eBOSSDROP RATE#n" + "\r\n";
showMsg += "Server BOSSDROP Rate: #e#b" + c.getWorldServer().getBossDropRate() + "x#k#n" + "\r\n";
player.showHint(showMsg);
break;
case "rates":
String showMsg_ = "#eCHARACTER RATES#n" + "\r\n\r\n";
showMsg_ += "EXP Rate: #e#b" + player.getExpRate() + "x#k#n" + "\r\n";
showMsg_ += "MESO Rate: #e#b" + player.getMesoRate() + "x#k#n" + "\r\n";
showMsg_ += "DROP Rate: #e#b" + player.getDropRate() + "x#k#n" + "\r\n";
showMsg_ += "BOSSDROP Rate: #e#b" + c.getWorldServer().getBossDropRate() + "x#k#n" + "\r\n";
player.showHint(showMsg_);
break;
case "online":
for (Channel ch : Server.getInstance().getChannelsFromWorld(player.getWorld())) {
@@ -788,13 +787,21 @@ public class Commands {
}
if (sub.length == 2) {
player.setRemainingSp(Integer.parseInt(sub[1]));
int newSp = Integer.parseInt(sub[1]);
if(newSp < 0) newSp = 0;
else if(newSp > ServerConstants.MAX_AP) newSp = ServerConstants.MAX_AP;
player.setRemainingSp(newSp);
player.updateSingleStat(MapleStat.AVAILABLESP, player.getRemainingSp());
} else {
victim = c.getChannelServer().getPlayerStorage().getCharacterByName(sub[1]);
if(victim != null) {
victim.setRemainingSp(Integer.parseInt(sub[2]));
int newSp = Integer.parseInt(sub[2]);
if(newSp < 0) newSp = 0;
else if(newSp > ServerConstants.MAX_AP) newSp = ServerConstants.MAX_AP;
victim.setRemainingSp(newSp);
victim.updateSingleStat(MapleStat.AVAILABLESP, player.getRemainingSp());
player.dropMessage(5, "SP given.");
@@ -809,15 +816,23 @@ public class Commands {
player.yellowMessage("Syntax: !ap [<playername>] <newap>");
break;
}
if (sub.length < 3) {
player.setRemainingAp(Integer.parseInt(sub[1]));
int newAp = Integer.parseInt(sub[1]);
if(newAp < 0) newAp = 0;
else if(newAp > ServerConstants.MAX_AP) newAp = ServerConstants.MAX_AP;
player.setRemainingAp(newAp);
player.updateSingleStat(MapleStat.AVAILABLEAP, player.getRemainingAp());
} else {
victim = c.getChannelServer().getPlayerStorage().getCharacterByName(sub[1]);
if(victim != null) {
victim.setRemainingAp(Integer.parseInt(sub[2]));
int newAp = Integer.parseInt(sub[2]);
if(newAp < 0) newAp = 0;
else if(newAp > ServerConstants.MAX_AP) newAp = ServerConstants.MAX_AP;
victim.setRemainingAp(newAp);
victim.updateSingleStat(MapleStat.AVAILABLEAP, victim.getRemainingAp());
} else {
player.message("Player '" + sub[1] + "' could not be found on this channel.");
@@ -1181,15 +1196,28 @@ public class Commands {
break;
case "setstat":
final int x = Short.parseShort(sub[1]);
player.setStr(x);
player.setDex(x);
player.setInt(x);
player.setLuk(x);
player.updateSingleStat(MapleStat.STR, x);
player.updateSingleStat(MapleStat.DEX, x);
player.updateSingleStat(MapleStat.INT, x);
player.updateSingleStat(MapleStat.LUK, x);
if (sub.length < 2){
player.yellowMessage("Syntax: !setstat <newstat>");
break;
}
int x;
try {
x = Integer.parseInt(sub[1]);
if(x > Short.MAX_VALUE) x = Short.MAX_VALUE;
else if(x < 0) x = 0;
player.setStr(x);
player.setDex(x);
player.setInt(x);
player.setLuk(x);
player.updateSingleStat(MapleStat.STR, x);
player.updateSingleStat(MapleStat.DEX, x);
player.updateSingleStat(MapleStat.INT, x);
player.updateSingleStat(MapleStat.LUK, x);
} catch(NumberFormatException nfe) {}
break;
case "maxstat":
@@ -2278,14 +2306,14 @@ public class Commands {
player.getMap().broadcastMessage(MaplePacketCreator.customPacket(joinStringFrom(sub, 1)));
break;
case "debugnearestportal":
case "debugportal":
MaplePortal portal = player.getMap().findClosestPortal(player.getPosition());
if(portal != null) player.dropMessage(6, "Closest portal: " + portal.getId() + " '" + portal.getName() + "' Type: " + portal.getType() + " --> toMap: " + portal.getTargetMapId() + " scriptname: '" + portal.getScriptName() + "' state: " + portal.getPortalState() + ".");
else player.dropMessage(6, "There is no portal on this map.");
break;
case "debugnearestspawnpoint":
case "debugspawnpoint":
SpawnPoint sp = player.getMap().findClosestSpawnpoint(player.getPosition());
if(sp != null) player.dropMessage(6, "Closest mob spawn point: " + " Position: x " + sp.getPosition().getX() + " y " + sp.getPosition().getY() + " Spawns mobid: '" + sp.getMonsterId() + "' --> canSpawn: " + !sp.getDenySpawn() + " canSpawnRightNow: " + sp.shouldSpawn() + ".");
else player.dropMessage(6, "There is no mob spawn point on this map.");
@@ -2381,8 +2409,8 @@ public class Commands {
target.setGMLevel(newLevel);
target.getClient().setGMLevel(newLevel);
target.dropMessage("You are now a level " + newLevel + " GM");
player.dropMessage(target + " is now a level " + newLevel + " GM");
target.dropMessage("You are now a level " + newLevel + " GM. See @commands for a list of available commands.");
player.dropMessage(target + " is now a level " + newLevel + " GM.");
} else {
player.dropMessage("Player '"+ sub[1] +"' was not found on this channel.");
}
+4 -4
View File
@@ -542,14 +542,14 @@ public class Equip extends Item {
return true;
}
public void showEquipFeatures(MapleClient c) {
public String showEquipFeatures(MapleClient c) {
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
if(!ii.isUpgradeable(this.getItemId())) return;
if(!ii.isUpgradeable(this.getItemId())) return "";
String eqpName = ii.getName(getItemId());
String eqpInfo = reachedMaxLevel(eqpName) ? " - MAX LEVEL" : (" EXP: " + itemExp + " / " + ExpTable.getEquipExpNeededForLevel(itemLevel));
String eqpInfo = reachedMaxLevel(eqpName) ? " #e#rMAX LEVEL#k#n" : (" EXP: #e#b" + (int)itemExp + "#k#n / " + ExpTable.getEquipExpNeededForLevel(itemLevel));
c.getPlayer().dropMessage(5, "'" + eqpName + "' -> Level: " + itemLevel + eqpInfo);
return "'" + eqpName + "' -> LV: #e#b" + itemLevel + "#k#n " + eqpInfo + "\r\n";
}
public final void showLevelupMessage(String msg, MapleClient c) {
+8 -4
View File
@@ -44,9 +44,9 @@ public class ServerConstants {
public static final boolean USE_ITEM_SORT_BY_NAME = false; //Item sorting based on name rather than id.
public static final boolean USE_PARTY_SEARCH = false;
public static final boolean USE_AUTOBAN = false; //Commands the server to detect infractors automatically.
public static final boolean USE_ANOTHER_AUTOASSIGNER = true; //Based on distributing AP accordingly to required secondary stat on equipments.
public static final boolean USE_SERVER_AUTOASSIGNER = true; //Server-builtin autoassigner, uses algorithm based on distributing AP accordingly to required secondary stat on equipments.
public static final boolean USE_REFRESH_RANK_MOVE = true;
public static final boolean USE_ENFORCE_MDOOR_POSITION = true; //Forces mystic door to be spawned near spawnpoints. (since things bugs out other way, and this helps players locate the door faster)
public static final boolean USE_ENFORCE_MDOOR_POSITION = true; //Forces mystic door to be spawned near spawnpoints. (since things bugs out other way, and this helps players to locate the door faster)
public static final boolean USE_ERASE_UNTRADEABLE_DROP = true; //Forces flagged untradeable items to disappear when dropped.
//Server Rates And Experience
@@ -58,7 +58,7 @@ public class ServerConstants {
public static final double EQUIP_EXPERIENCE_MOD = 10.0; //Rate for equipment exp needed, grows linearly. Set 1.0 for default (about 100~200 same-level range mobs killed to pass equip from level 1 to 2).
public static final double PQ_BONUS_EXP_MOD = 0.5;
public static final int MAX_AP = 20000; //Max AP allotted on the auto-assigner.
public static final int MAX_AP = 32767; //Max AP allotted on the auto-assigner.
public static final int MAX_EVENT_LEVELS = 8; //Event has different levels of rewarding system.
public static final long BLOCK_NPC_RACE_CONDT = (long)(0.5 * 1000); //Time the player client must wait before reopening a conversation with an NPC.
public static final long PET_LOOT_UPON_ATTACK = (long)(0.7 * 1000); //Time the pet must wait before trying to pick items up.
@@ -66,7 +66,7 @@ public class ServerConstants {
//Dangling Items Configuration
public static final int ITEM_EXPIRE_TIME = 3 * 60 * 1000; //Time before items start disappearing. Recommended to be set up to 3 minutes.
public static final int ITEM_MONITOR_TIME = 5 * 60 * 1000; //Interval between item monitoring tasks on maps, which checks for dangling item objects on the map item history.
public static final int ITEM_LIMIT_ON_MAP = 250; //Max number of items allowed on a map.
public static final int ITEM_LIMIT_ON_MAP = 200; //Max number of items allowed on a map.
//Some Gameplay Enhancing Configurations
//Scroll Configuration
@@ -102,6 +102,10 @@ public class ServerConstants {
public static final double PET_AUTOHP_RATIO = 0.99; //Will automatically consume potions until given ratio of the MaxHP/MaxMP is reached.
public static final double PET_AUTOMP_RATIO = 0.99;
//Pet & Mount Configuration
public static final byte PET_EXHAUST_COUNT = 3; //Number of proc counts (1 per minute) on the exhaust schedule for fullness.
public static final byte MOUNT_EXHAUST_COUNT = 1; //Number of proc counts (1 per minute) on the exhaust schedule for tiredness.
//Dojo Configuration
public static final boolean USE_DEADLY_DOJO = false; //Should bosses really use 1HP,1MP attacks in dojo?
public static final int DOJO_ENERGY_ATK = 100; //Dojo energy gain when deal attack
+3 -2
View File
@@ -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
View 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
View 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());
+125 -2
View File
@@ -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();
}
}
+2 -2
View File
@@ -375,7 +375,7 @@ public class AbstractPlayerInteraction {
getPlayer().getMap().broadcastMessage(c.getPlayer(), MaplePacketCreator.showPet(c.getPlayer(), evolved, false, false), true);
c.announce(MaplePacketCreator.petStatUpdate(c.getPlayer()));
c.announce(MaplePacketCreator.enableActions());
getPlayer().startFullnessSchedule(PetDataFactory.getHunger(evolved.getItemId()), evolved, getPlayer().getPetIndex(evolved));
chr.getClient().getWorldServer().registerPetHunger(chr, chr.getPetIndex(evolved));
*/
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.CASH, target.getPosition(), (short) 1, false);
@@ -452,7 +452,7 @@ public class AbstractPlayerInteraction {
}
if(ServerConstants.USE_ENHANCED_CRAFTING == true && c.getPlayer().getCS() == true)
item = MapleItemInformationProvider.getInstance().scrollEquipWithId(item, 2049100, true, c.getPlayer().isGM());
item = MapleItemInformationProvider.getInstance().scrollEquipWithId(item, 2049100, true, 0, c.getPlayer().isGM());
} else {
item = new Item(id, (short) 0, quantity, petId);
}
@@ -280,7 +280,7 @@ public class NPCConversationManager extends AbstractPlayerInteraction {
public void gainCloseness(int closeness) {
for (MaplePet pet : getPlayer().getPets()) {
pet.gainClosenessFullness(getPlayer(), closeness, 0, 0);
if(pet != null) pet.gainClosenessFullness(getPlayer(), closeness, 0, 0);
}
}
+1 -1
View File
@@ -537,7 +537,7 @@ public class MapleInventoryManipulator {
c.getPlayer().setChalkboard(null);
}
}
if ((!ItemConstants.isRechargable(itemId) && c.getPlayer().getItemQuantity(itemId, true) < quantity) || quantity < 0 || source == null) {
if (source == null || (!ItemConstants.isRechargable(itemId) && source.getQuantity() < quantity) || quantity < 0) {
return;
}
Point dropPos = new Point(c.getPlayer().getPosition());
+9 -2
View File
@@ -559,7 +559,7 @@ public class MapleItemInformationProvider {
return (short)Math.min(Short.MAX_VALUE, value);
}
public Item scrollEquipWithId(Item equip, int scrollId, boolean usingWhiteScroll, boolean isGM) {
public Item scrollEquipWithId(Item equip, int scrollId, boolean usingWhiteScroll, int vegaItemId, boolean isGM) {
if (equip instanceof Equip) {
Equip nEquip = (Equip) equip;
@@ -567,7 +567,14 @@ public class MapleItemInformationProvider {
Map<String, Integer> eqstats = this.getEquipStats(equip.getItemId());
if (((nEquip.getUpgradeSlots() > 0 || ItemConstants.isCleanSlate(scrollId))) || isGM) {
if(isGM || rollSuccessChance((double)stats.get("success"))) {
double prop = (double)stats.get("success");
if (vegaItemId == 5610000) {
prop = 30.0;
} else if (vegaItemId == 5610001) {
prop = 90.0;
}
if(isGM || rollSuccessChance(prop)) {
short flag = nEquip.getFlag();
switch (scrollId) {
case 2040727:
+5 -6
View File
@@ -752,7 +752,7 @@ public class MapleStatEffect {
}
if (isDispel() && makeChanceResult()) {
applyto.dispelDebuffs();
} else if (isHeroWill()) {
} else if (isCureAllAbnormalStatus()) {
applyto.dispelDebuff(MapleDisease.SEDUCE);
applyto.dispelDebuff(MapleDisease.ZOMBIFY);
applyto.dispelDebuffs();
@@ -1042,9 +1042,7 @@ public class MapleStatEffect {
applyto.mount(ridingLevel, sourceid);
}
if(!(ServerConstants.PETS_NEVER_HUNGRY || applyto.isGM() && ServerConstants.GM_PETS_NEVER_HUNGRY)) {
applyto.getMount().startSchedule();
}
applyto.getClient().getWorldServer().registerMountHunger(applyto);
}
if (sourceid == Corsair.BATTLE_SHIP) {
givemount = new MapleMount(applyto, 1932000, sourceid);
@@ -1399,7 +1397,7 @@ public class MapleStatEffect {
return skill && (sourceid == Priest.DISPEL || sourceid == SuperGM.HEAL_PLUS_DISPEL);
}
private boolean isHeroWill() {
private boolean isCureAllAbnormalStatus() {
if (skill) {
switch (sourceid) {
case Hero.HEROS_WILL:
@@ -1418,7 +1416,8 @@ public class MapleStatEffect {
default:
return false;
}
}
} else if (sourceid == 2022544) return true;
return false;
}
+1 -1
View File
@@ -150,7 +150,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
return stats.getExp();
}
int getLevel() {
public int getLevel() {
return stats.getLevel();
}
+39 -2
View File
@@ -99,6 +99,7 @@ public class MapleMap {
private LinkedList<WeakReference<MapleMapObject>> registeredDrops = new LinkedList<>();
private List<Rectangle> areas = new ArrayList<>();
private MapleFootholdTree footholds = null;
private Rectangle mapArea = new Rectangle();
private int mapid;
private AtomicInteger runningOid = new AtomicInteger(100);
private int returnMapId;
@@ -433,7 +434,15 @@ public class MapleMap {
Point ret = calcPointBelow(new Point(initial.x, initial.y - 85));
if (ret == null) {
return fallback;
} else if(!mapArea.contains(ret)) {
if(initial.y > mapArea.y + mapArea.height) return fallback; // found drop pos underneath the map :O
int borderX = (initial.x < mapArea.x) ? mapArea.x : mapArea.x + mapArea.width;
ret = calcPointBelow(new Point(borderX, initial.y - 85));
if(ret == null) return fallback;
}
return ret;
}
@@ -1886,7 +1895,7 @@ public class MapleMap {
}, 30 * 60 * 1000);
}
MaplePet[] pets = chr.getPets();
for (int i = 0; i < chr.getPets().length; i++) {
for (int i = 0; i < pets.length; i++) {
if (pets[i] != null) {
pets[i].setPos(getGroundBelow(chr.getPosition()));
chr.announce(MaplePacketCreator.showPet(chr, pets[i], false, false));
@@ -2314,7 +2323,15 @@ public class MapleMap {
public MapleFootholdTree getFootholds() {
return footholds;
}
public void setMapPointBoundings(int px, int py, int h, int w) {
mapArea.setBounds(px, py, w, h);
}
public void setMapLineBoundings(int vrTop, int vrBottom, int vrLeft, int vrRight) {
mapArea.setBounds(vrLeft, vrTop, vrRight - vrLeft, vrBottom - vrTop);
}
/**
* it's threadsafe, gtfo :D
*
@@ -2667,6 +2684,26 @@ public class MapleMap {
}
}
public void instanceMapForceRespawn() {
if(!allowSummons) return;
final int numShouldSpawn = (short) ((monsterSpawn.size() - spawnedMonstersOnMap.get()));//Fking lol'd
if (numShouldSpawn > 0) {
List<SpawnPoint> randomSpawn = new ArrayList<>(monsterSpawn);
Collections.shuffle(randomSpawn);
int spawned = 0;
for (SpawnPoint spawnPoint : randomSpawn) {
if(spawnPoint.shouldForceSpawn()) {
spawnMonster(spawnPoint.getMonster());
spawned++;
if (spawned >= numShouldSpawn) {
break;
}
}
}
}
}
public void restoreMapSpawnPoints() {
for (SpawnPoint spawnPoint : monsterSpawn) {
spawnPoint.setDenySpawn(false);
+21
View File
@@ -127,6 +127,27 @@ public class MapleMapFactory {
MapleDataTool.getString(timeMob.getChildByPath("message")));
}
int bounds[] = new int[4];
bounds[0] = MapleDataTool.getInt(infoData.getChildByPath("VRTop"));
bounds[1] = MapleDataTool.getInt(infoData.getChildByPath("VRBottom"));
if(bounds[0] == bounds[1]) { // old-style baked map
MapleData minimapData = mapData.getChildByPath("miniMap");
if(minimapData != null) {
bounds[0] = MapleDataTool.getInt(minimapData.getChildByPath("centerX")) * -1;
bounds[1] = MapleDataTool.getInt(minimapData.getChildByPath("centerY")) * -1;
bounds[2] = MapleDataTool.getInt(minimapData.getChildByPath("height"));
bounds[3] = MapleDataTool.getInt(minimapData.getChildByPath("width"));
map.setMapPointBoundings(bounds[0], bounds[1], bounds[2], bounds[3]);
}
} else {
bounds[2] = MapleDataTool.getInt(infoData.getChildByPath("VRLeft"));
bounds[3] = MapleDataTool.getInt(infoData.getChildByPath("VRRight"));
map.setMapLineBoundings(bounds[0], bounds[1], bounds[2], bounds[3]);
}
List<MapleFoothold> allFootholds = new LinkedList<>();
Point lBound = new Point();
Point uBound = new Point();
@@ -58,8 +58,8 @@ public class MinTamenessRequirement extends MapleQuestRequirement {
for(MaplePet pet : chr.getPets()) {
if(pet == null) continue;
if(pet.getCloseness() > curCloseness)
curCloseness = pet.getCloseness();
if(pet.getCloseness() > curCloseness)
curCloseness = pet.getCloseness();
}
return curCloseness >= minTameness;
+31 -1
View File
@@ -83,6 +83,7 @@ import client.MapleCharacter.SkillEntry;
import client.MapleClient;
import client.MapleDisease;
import client.MapleFamilyEntry;
import client.MapleJob;
import client.MapleKeyBinding;
import client.MapleMount;
import client.MapleQuestStatus;
@@ -1823,7 +1824,16 @@ public class MaplePacketCreator {
mplew.writeInt(CHAR_MAGIC_SPAWN);
mplew.writeShort(0);
mplew.write(0);
mplew.writeShort(chr.getJob().getId());
/* replace "mplew.writeShort(chr.getJob().getId())" with this snippet for 3rd party FJ animation on all classes
if (chr.getJob().isA(MapleJob.HERMIT) || chr.getJob().isA(MapleJob.DAWNWARRIOR2) || chr.getJob().isA(MapleJob.NIGHTWALKER2)) {
mplew.writeShort(chr.getJob().getId());
} else {
mplew.writeShort(412);
}*/
addCharLook(mplew, chr, false);
mplew.writeInt(chr.getInventory(MapleInventoryType.CASH).countById(5110000));
mplew.writeInt(chr.getItemEffect());
@@ -2000,7 +2010,7 @@ public class MaplePacketCreator {
mplew.writeShort(SendOpcode.SUMMON_ATTACK.getValue());
mplew.writeInt(cid);
mplew.writeInt(summonOid);
mplew.write(direction);
mplew.write(0); // char level
mplew.write(direction);
mplew.write(allDamage.size());
for (SummonAttackEntry attackEntry : allDamage) {
@@ -4329,6 +4339,19 @@ public class MaplePacketCreator {
mplew.write(0);
return mplew.getPacket();
}
public static final byte[] loadExceptionList(final int cid, final int petId, final byte petIdx, final List<Integer> data) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.PET_EXCEPTION_LIST.getValue());
mplew.writeInt(cid);
mplew.write(petIdx);
mplew.writeLong(petId);
mplew.write(data.size());
for (final Integer ids : data) {
mplew.writeInt(ids);
}
return mplew.getPacket();
}
public static byte[] petStatUpdate(MapleCharacter chr) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
@@ -6884,6 +6907,13 @@ public class MaplePacketCreator {
return mplew.getPacket();
}
public static byte[] sendVegaScroll(int op) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(3);
mplew.writeShort(SendOpcode.VEGA_SCROLL.getValue());
mplew.write(op);
return mplew.getPacket();
}
public static byte[] resetForcedStats() {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(2);
mplew.writeShort(SendOpcode.FORCED_STAT_RESET.getValue());