Reworked Autoassigner & Hero's Will & Trade + Visual NX + New commands
Reworked autoassigner (improved limits between required secondary and surplus primary stats). Hero's will removes most of diseases, tonic removes slow. Added visual info for collected NX cards. Added commands cake (cake boss with customizable HP) and setgmlevel. Reworked Trade system now checking for slots smartly (instead of just checking for empty slots).
This commit is contained in:
@@ -67,8 +67,8 @@ import java.util.Calendar;
|
||||
import server.quest.MapleQuest;
|
||||
|
||||
public class Server implements Runnable {
|
||||
private final Map<Integer, Integer> couponRates = new LinkedHashMap<>();
|
||||
private final List<Integer> activeCoupons = new LinkedList<>();
|
||||
private static final Map<Integer, Integer> couponRates = new LinkedHashMap<>();
|
||||
private static final List<Integer> activeCoupons = new LinkedList<>();
|
||||
|
||||
private IoAcceptor acceptor;
|
||||
private List<Map<Integer, String>> channels = new LinkedList<>();
|
||||
|
||||
@@ -374,8 +374,11 @@ public final class Channel {
|
||||
mask ^= (1 << slot);
|
||||
|
||||
usedDojo &= mask;
|
||||
if(party != null) dojoParty.remove(party.hashCode());
|
||||
else if(dojoParty.containsValue(slot)) { // they left the dojo before completing it, no party there!
|
||||
if(party != null) {
|
||||
if(dojoParty.remove(party.hashCode()) != null) return;
|
||||
}
|
||||
|
||||
if(dojoParty.containsValue(slot)) { // strange case, no party there!
|
||||
Set<Entry<Integer, Integer>> es = Collections.unmodifiableSet(dojoParty.entrySet());
|
||||
|
||||
for(Entry<Integer, Integer> e: es) {
|
||||
@@ -411,6 +414,20 @@ public final class Channel {
|
||||
}
|
||||
}
|
||||
|
||||
public void freeDojoSectionIfEmpty(int dojoMapId) {
|
||||
final int slot = getDojoSlot(dojoMapId);
|
||||
final int delta = (dojoMapId) % 100;
|
||||
final int stage = (dojoMapId / 100) % 100;
|
||||
final int dojoBaseMap = (dojoMapId >= 925030000) ? 925030000 : 925020000;
|
||||
|
||||
for (int i = 0; i < 5; i++) { //only 32 stages, but 38 maps
|
||||
MapleMap dojoMap = getMapFactory().getMap(dojoBaseMap + (100 * (stage + i)) + delta);
|
||||
if(!dojoMap.getAllPlayers().isEmpty()) return;
|
||||
}
|
||||
|
||||
freeDojoSlot(slot, null);
|
||||
}
|
||||
|
||||
public void startDojoSchedule(final int dojoMapId) {
|
||||
final int slot = getDojoSlot(dojoMapId);
|
||||
final int stage = (dojoMapId / 100) % 100;
|
||||
|
||||
@@ -270,7 +270,7 @@ public abstract class AbstractDealDamageHandler extends AbstractMaplePacketHandl
|
||||
player.checkMonsterAggro(monster);
|
||||
if (player.getBuffedValue(MapleBuffStat.PICKPOCKET) != null && (attack.skill == 0 || attack.skill == Rogue.DOUBLE_STAB || attack.skill == Bandit.SAVAGE_BLOW || attack.skill == ChiefBandit.ASSAULTER || attack.skill == ChiefBandit.BAND_OF_THIEVES || attack.skill == Shadower.ASSASSINATE || attack.skill == Shadower.TAUNT || attack.skill == Shadower.BOOMERANG_STEP)) {
|
||||
Skill pickpocket = SkillFactory.getSkill(ChiefBandit.PICKPOCKET);
|
||||
int picklv = (player.getSkillLevel(pickpocket) > 0 || !ServerConstants.USE_PERMISSIVE_BUFFS) ? player.getSkillLevel(pickpocket) : pickpocket.getMaxLevel();
|
||||
int picklv = (player.isGM()) ? pickpocket.getMaxLevel() : player.getSkillLevel(pickpocket);
|
||||
if(picklv > 0) {
|
||||
int delay = 0;
|
||||
final int maxmeso = player.getBuffedValue(MapleBuffStat.PICKPOCKET).intValue();
|
||||
@@ -650,7 +650,7 @@ public abstract class AbstractDealDamageHandler extends AbstractMaplePacketHandl
|
||||
} else {
|
||||
// Normal Combo
|
||||
int skillLv = chr.getSkillLevel(oid);
|
||||
if(skillLv <= 0 && ServerConstants.USE_PERMISSIVE_BUFFS) skillLv = SkillFactory.getSkill(oid).getMaxLevel();
|
||||
if(skillLv <= 0 || chr.isGM()) skillLv = SkillFactory.getSkill(oid).getMaxLevel();
|
||||
|
||||
if(skillLv > 0) {
|
||||
MapleStatEffect ceffect = SkillFactory.getSkill(oid).getEffect(skillLv);
|
||||
|
||||
@@ -31,27 +31,39 @@ import client.inventory.Equip;
|
||||
import client.inventory.Item;
|
||||
import client.inventory.MapleInventory;
|
||||
import client.inventory.MapleInventoryType;
|
||||
//import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
//import java.util.List;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Generic
|
||||
* @author Generic, Ronan
|
||||
*/
|
||||
public class AutoAssignHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
private static int getNthHighestStat(List<Short> statList, short rank) { // ranks from 0
|
||||
return(statList.size() <= rank ? 0 : statList.get(rank));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
MapleCharacter chr = c.getPlayer();
|
||||
MapleJob stance;
|
||||
|
||||
if(ServerConstants.USE_ANOTHER_AUTOASSIGN == true) {
|
||||
int eqpStr = 0, eqpDex = 0, eqpLuk = 0;
|
||||
slea.skip(8);
|
||||
if (chr.getRemainingAp() < 1) return;
|
||||
|
||||
if(ServerConstants.USE_ANOTHER_AUTOASSIGNER == true) {
|
||||
// ---------- 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;
|
||||
List<Short> eqpStrList = new ArrayList<>();
|
||||
List<Short> eqpDexList = new ArrayList<>();
|
||||
List<Short> eqpLukList = new ArrayList<>();
|
||||
|
||||
MapleInventory iv = chr.getInventory(MapleInventoryType.EQUIPPED);
|
||||
Collection<Item> equippedC = iv.list();
|
||||
@@ -59,29 +71,33 @@ public class AutoAssignHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
for (Item item : equippedC) { //selecting the biggest AP value of each stat from each equipped item.
|
||||
nEquip = (Equip)item;
|
||||
if(nEquip.getStr() > eqpStr) eqpStr = nEquip.getStr();
|
||||
if(nEquip.getStr() > 0) eqpStrList.add(nEquip.getStr());
|
||||
str += nEquip.getStr();
|
||||
|
||||
if(nEquip.getDex() > eqpDex) eqpDex = nEquip.getDex();
|
||||
if(nEquip.getDex() > 0) eqpDexList.add(nEquip.getDex());
|
||||
dex += nEquip.getDex();
|
||||
|
||||
if(nEquip.getLuk() > eqpLuk) eqpLuk = nEquip.getLuk();
|
||||
if(nEquip.getLuk() > 0) eqpLukList.add(nEquip.getLuk());
|
||||
luk += nEquip.getLuk();
|
||||
|
||||
//if(nEquip.getInt() > eqpInt) eqpInt = nEquip.getInt(); //not needed...
|
||||
//if(nEquip.getInt() > 0) eqpIntList.add(nEquip.getInt()); //not needed...
|
||||
int_ += nEquip.getInt();
|
||||
}
|
||||
|
||||
Collections.sort(eqpStrList, Collections.reverseOrder());
|
||||
Collections.sort(eqpDexList, Collections.reverseOrder());
|
||||
Collections.sort(eqpLukList, Collections.reverseOrder());
|
||||
|
||||
//Autoassigner looks up the 1st/2nd placed equips for their stats to calculate the optimal upgrade.
|
||||
int eqpStr = getNthHighestStat(eqpStrList, (short) 0) + getNthHighestStat(eqpStrList, (short) 1);
|
||||
int eqpDex = getNthHighestStat(eqpDexList, (short) 0) + getNthHighestStat(eqpDexList, (short) 1);
|
||||
int eqpLuk = getNthHighestStat(eqpLukList, (short) 0) + getNthHighestStat(eqpLukList, (short) 1);
|
||||
|
||||
//c.getPlayer().message("----------------------------------------SDL: " + eqpStr + eqpDex + eqpLuk + " BASE STATS --> STR: " + chr.getStr() + " DEX: " + chr.getDex() + " INT: " + chr.getInt() + " LUK: " + chr.getLuk());
|
||||
//c.getPlayer().message("----------------------------------------");
|
||||
//c.getPlayer().message("SDL: s" + eqpStr + " d" + eqpDex + " l" + eqpLuk + " BASE STATS --> STR: " + chr.getStr() + " DEX: " + chr.getDex() + " INT: " + chr.getInt() + " LUK: " + chr.getLuk());
|
||||
//c.getPlayer().message("SUM EQUIP STATS -> STR: " + str + " DEX: " + dex + " LUK: " + luk + " INT: " + int_);
|
||||
|
||||
// ---------- Ronan Lana's AUTOASSIGN -------------
|
||||
// This method excels for assigning APs in such a way to cover all equipments AP requirements.
|
||||
if (chr.getRemainingAp() < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
stance = c.getPlayer().getJobStyle();
|
||||
MapleJob stance = c.getPlayer().getJobStyle();
|
||||
int prStat = 0, scStat = 0, trStat = 0, temp, tempAp = chr.getRemainingAp(), CAP;
|
||||
|
||||
MapleStat primary, secondary, tertiary = MapleStat.INT;
|
||||
@@ -294,10 +310,6 @@ public class AutoAssignHandler extends AbstractMaplePacketHandler {
|
||||
c.announce(MaplePacketCreator.serverNotice(1, "Better AP applications detected:\r\nSTR: +" + str + "\r\nDEX: +" + dex + "\r\nINT: +" + int_ + "\r\nLUK: +" + luk));
|
||||
}
|
||||
else {
|
||||
slea.skip(8);
|
||||
if (chr.getRemainingAp() < 1) {
|
||||
return;
|
||||
}
|
||||
int total = 0;
|
||||
int extras = 0;
|
||||
if(slea.available() < 16) {
|
||||
|
||||
@@ -152,7 +152,6 @@ public final class ChangeMapHandler extends AbstractMaplePacketHandler {
|
||||
} else {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
}
|
||||
//chr.setWorldRates();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@@ -73,7 +73,6 @@ public final class CloseRangeDamageHandler extends AbstractDealDamageHandler {
|
||||
if (player.getMap().isDojoMap() && attack.numAttacked > 0) {
|
||||
player.setDojoEnergy(player.getDojoEnergy() + ServerConstants.DOJO_ENERGY_ATK);
|
||||
c.announce(MaplePacketCreator.getEnergy("energy", player.getDojoEnergy()));
|
||||
System.out.println("gauge " + player.getDojoEnergy());
|
||||
}
|
||||
|
||||
player.getMap().broadcastMessage(player, MaplePacketCreator.closeRangeAttack(player, attack.skill, attack.skilllevel, attack.stance, attack.numAttackedAndDamage, attack.allDamage, attack.speed, attack.direction, attack.display), false, true);
|
||||
@@ -97,7 +96,7 @@ public final class CloseRangeDamageHandler extends AbstractDealDamageHandler {
|
||||
ceffect = advcombo.getEffect(advComboSkillLevel);
|
||||
} else {
|
||||
int comboLv = player.getSkillLevel(combo);
|
||||
if(comboLv <= 0 && ServerConstants.USE_PERMISSIVE_BUFFS) comboLv = SkillFactory.getSkill(oid).getMaxLevel();
|
||||
if(comboLv <= 0 || player.isGM()) comboLv = SkillFactory.getSkill(oid).getMaxLevel();
|
||||
|
||||
if(comboLv > 0) ceffect = combo.getEffect(comboLv);
|
||||
else ceffect = null;
|
||||
@@ -168,7 +167,6 @@ public final class CloseRangeDamageHandler extends AbstractDealDamageHandler {
|
||||
player.setDojoEnergy(0);
|
||||
c.announce(MaplePacketCreator.getEnergy("energy", player.getDojoEnergy()));
|
||||
c.announce(MaplePacketCreator.serverNotice(5, "As you used the secret skill, your energy bar has been reset."));
|
||||
System.out.println("gauge " + player.getDojoEnergy());
|
||||
} else if (attack.skill > 0) {
|
||||
Skill skill = SkillFactory.getSkill(attack.skill);
|
||||
MapleStatEffect effect_ = skill.getEffect(player.getSkillLevel(skill));
|
||||
|
||||
@@ -25,7 +25,6 @@ import client.MapleCharacter;
|
||||
import client.MapleClient;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import net.server.Server;
|
||||
import server.MapleTrade;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ public final class GeneralChatHandler extends net.AbstractMaplePacketHandler {
|
||||
return;
|
||||
}
|
||||
char heading = s.charAt(0);
|
||||
if (heading == '/' || heading == '!' || heading == '@') { // client seems to not send command with '/' heading to the server, if not a GM account
|
||||
if (heading == '!' || heading == '@') {
|
||||
String[] sp = s.split(" ");
|
||||
sp[0] = sp[0].toLowerCase().substring(1);
|
||||
|
||||
@@ -59,8 +59,8 @@ public final class GeneralChatHandler extends net.AbstractMaplePacketHandler {
|
||||
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm");
|
||||
FilePrinter.print(FilePrinter.USED_COMMANDS, c.getPlayer().getName() + " used: " + heading + command + "on " + sdf.format(Calendar.getInstance().getTime()) + "\r\n");
|
||||
}
|
||||
} else {
|
||||
}
|
||||
} else if (heading != '/') {
|
||||
int show = slea.readByte();
|
||||
if(chr.getMap().isMuted() && !chr.isGM()) {
|
||||
chr.dropMessage(5, "The map you are in is currently muted. Please try again later.");
|
||||
|
||||
@@ -35,16 +35,17 @@ import tools.data.input.SeekableLittleEndianAccessor;
|
||||
public final class ItemMoveHandler extends AbstractMaplePacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
slea.skip(4);
|
||||
slea.skip(4);
|
||||
if(c.getPlayer().getAutobanManager().getLastSpam(6) + 300 > System.currentTimeMillis()) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
MapleInventoryType type = MapleInventoryType.getByType(slea.readByte());
|
||||
byte src = (byte) slea.readShort();
|
||||
byte action = (byte) slea.readShort();
|
||||
short src = slea.readShort(); //is there any reason to use byte instead of short in src and action?
|
||||
short action = slea.readShort();
|
||||
short quantity = slea.readShort();
|
||||
|
||||
if (src < 0 && action > 0) {
|
||||
MapleInventoryManipulator.unequip(c, src, action);
|
||||
} else if (action < 0) {
|
||||
|
||||
@@ -62,7 +62,6 @@ public final class MagicDamageHandler extends AbstractDealDamageHandler {
|
||||
if (player.getMap().isDojoMap() && attack.numAttacked > 0) {
|
||||
player.setDojoEnergy(player.getDojoEnergy() + + ServerConstants.DOJO_ENERGY_ATK);
|
||||
c.announce(MaplePacketCreator.getEnergy("energy", player.getDojoEnergy()));
|
||||
System.out.println("gauge " + player.getDojoEnergy());
|
||||
}
|
||||
|
||||
int charge = (attack.skill == Evan.FIRE_BREATH || attack.skill == Evan.ICE_BREATH || attack.skill == FPArchMage.BIG_BANG || attack.skill == ILArchMage.BIG_BANG || attack.skill == Bishop.BIG_BANG) ? attack.charge : -1;
|
||||
|
||||
@@ -25,10 +25,7 @@ import client.MapleCharacter;
|
||||
import client.MapleClient;
|
||||
import client.inventory.PetCommand;
|
||||
import client.inventory.PetDataFactory;
|
||||
import client.inventory.Item;
|
||||
import client.inventory.MapleInventoryType;
|
||||
import client.inventory.MaplePet;
|
||||
import constants.ExpTable;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.Randomizer;
|
||||
|
||||
@@ -51,9 +51,6 @@ import client.inventory.MaplePet;
|
||||
import client.inventory.PetDataFactory;
|
||||
import constants.GameConstants;
|
||||
import constants.ServerConstants;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import server.TimerManager;
|
||||
|
||||
public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
@@ -152,7 +149,6 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
|
||||
con.close();
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
//ignore
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
@@ -226,13 +222,17 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
|
||||
player.showNote();
|
||||
if (player.getParty() != null) {
|
||||
MaplePartyCharacter pchar = player.getMPC();
|
||||
|
||||
//Use this in case of enabling party HPbar HUD when logging in, however "you created a party" will appear on chat.
|
||||
//c.announce(MaplePacketCreator.partyCreated(pchar));
|
||||
|
||||
pchar.setChannel(c.getChannel());
|
||||
pchar.setMapId(player.getMapId());
|
||||
pchar.setOnline(true);
|
||||
world.updateParty(player.getParty().getId(), PartyOperation.LOG_ONOFF, pchar);
|
||||
player.updatePartyMemberHP();
|
||||
}
|
||||
player.updatePartyMemberHP();
|
||||
|
||||
|
||||
if (player.getInventory(MapleInventoryType.EQUIPPED).findById(1122017) != null) {
|
||||
player.equipPendantOfSpirit();
|
||||
}
|
||||
@@ -258,7 +258,6 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
|
||||
player.changeSkillLevel(SkillFactory.getSkill(10000000 * player.getJobType() + 12), (byte) (player.getLinkedLevel() / 10), 20, -1);
|
||||
player.checkBerserk(player.isHidden());
|
||||
player.expirationTask();
|
||||
//player.setWorldRates();
|
||||
if (GameConstants.hasSPTable(player.getJob()) && player.getJob().getId() != 2001) {
|
||||
player.createDragon();
|
||||
}
|
||||
@@ -277,7 +276,6 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
|
||||
if (player.getMap().getHPDec() > 0) player.resetHpDecreaseTask();
|
||||
|
||||
player.resetPlayerRates();
|
||||
|
||||
if(ServerConstants.USE_ADD_RATES_BY_LEVEL == true) player.setPlayerRates();
|
||||
player.setWorldRates();
|
||||
player.updateCouponRates();
|
||||
|
||||
@@ -74,7 +74,6 @@ public final class RangedAttackHandler extends AbstractDealDamageHandler {
|
||||
if (player.getMap().isDojoMap() && attack.numAttacked > 0) {
|
||||
player.setDojoEnergy(player.getDojoEnergy() + ServerConstants.DOJO_ENERGY_ATK);
|
||||
c.announce(MaplePacketCreator.getEnergy("energy", player.getDojoEnergy()));
|
||||
System.out.println("gauge " + player.getDojoEnergy());
|
||||
}
|
||||
|
||||
if (attack.skill == Buccaneer.ENERGY_ORB || attack.skill == ThunderBreaker.SPARK || attack.skill == Shadower.TAUNT || attack.skill == NightLord.TAUNT) {
|
||||
|
||||
@@ -236,7 +236,6 @@ public final class TakeDamageHandler extends AbstractMaplePacketHandler {
|
||||
if (GameConstants.isDojo(map.getId())) {
|
||||
player.setDojoEnergy(player.getDojoEnergy() + ServerConstants.DOJO_ENERGY_DMG);
|
||||
c.announce(MaplePacketCreator.getEnergy("energy", player.getDojoEnergy()));
|
||||
System.out.println("gauge " + player.getDojoEnergy());
|
||||
}
|
||||
|
||||
for (MapleCharacter chr : banishPlayers) { // chill, if this list ever gets non-empty an attacker does exist, trust me :)
|
||||
|
||||
@@ -59,6 +59,7 @@ public final class UseItemHandler extends AbstractMaplePacketHandler {
|
||||
return;
|
||||
} else if (itemId == 2050002) {
|
||||
c.getPlayer().dispelDebuff(MapleDisease.WEAKEN);
|
||||
c.getPlayer().dispelDebuff(MapleDisease.SLOW);
|
||||
remove(c, slot);
|
||||
return;
|
||||
} else if (itemId == 2050003) {
|
||||
|
||||
Reference in New Issue
Block a user