Show HH/CT damage + Miniroom patch + Removed redundant skillbook drops
Added a server flag to allow solo expeditions. Added a server flag that allows short-lengthened cooldown on Hero's Will skill. Added recipes for Advanced Mob Crystal 2 and 3 (level 120 and 130) within Etc Maker. Fixed Heaven's Hammer and Combo Tempest not displaying damage dealt value. Fixed some minor PE exploits with players being allowed to create minirooms while dead or inside an event. Adjusted item dropped from mobs to now allow visible quest items appear before not-visible ones, thus showing no "empty spaces" when the mob has multiple quest drops. Fixed Horntail not attributing quest progress for "The Last Hour of Horntail" quest. Attribution only happens inside the expedition. Removed unnecessary skill books from the drop data, since quests for them were recently implemented.
This commit is contained in:
@@ -198,7 +198,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
private int expRate = 1, mesoRate = 1, dropRate = 1, expCoupon = 1, mesoCoupon = 1, dropCoupon = 1;
|
||||
private int omokwins, omokties, omoklosses, matchcardwins, matchcardties, matchcardlosses;
|
||||
private int owlSearch;
|
||||
private long lastfametime, lastUsedCashItem, lastHealed, lastBuyback, lastDeathtime, lastMesoDrop = -1, jailExpiration = -1;
|
||||
private long lastfametime, lastUsedCashItem, lastHealed, lastBuyback = 0, lastDeathtime, lastMesoDrop = -1, jailExpiration = -1;
|
||||
private transient int localmaxhp, localmaxmp, localstr, localdex, localluk, localint_, magic, watk;
|
||||
private boolean hidden, canDoor = true, berserk, hasMerchant, hasSandboxItem = false, whiteChat = false;
|
||||
private int linkedLevel = 0;
|
||||
@@ -1729,14 +1729,17 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
if (mesosamm > 50000 * this.getMesoRate()) {
|
||||
return;
|
||||
}
|
||||
|
||||
MapleMap thisMap = this.getMap();
|
||||
int partynum = 0;
|
||||
for (MaplePartyCharacter partymem : this.party.getMembers()) {
|
||||
if (partymem.isOnline() && partymem.getMapId() == this.getMap().getId() && partymem.getChannel() == client.getChannel()) {
|
||||
Collection<MaplePartyCharacter> mpcs = this.party.getMembers();
|
||||
for (MaplePartyCharacter partymem : mpcs) {
|
||||
if (partymem.getPlayer().isLoggedinWorld() && partymem.getMapId() == thisMap.getId() && partymem.getChannel() == client.getChannel()) {
|
||||
partynum++;
|
||||
}
|
||||
}
|
||||
for (MaplePartyCharacter partymem : this.party.getMembers()) {
|
||||
if (partymem.isOnline() && partymem.getMapId() == this.getMap().getId()) {
|
||||
for (MaplePartyCharacter partymem : mpcs) {
|
||||
if (partymem.getPlayer().isLoggedinWorld() && partymem.getMapId() == thisMap.getId()) {
|
||||
MapleCharacter somecharacter = client.getChannelServer().getPlayerStorage().getCharacterById(partymem.getId());
|
||||
if (somecharacter != null) {
|
||||
somecharacter.gainMeso(mesosamm / partynum, true, true, false);
|
||||
@@ -5213,6 +5216,10 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
}
|
||||
}
|
||||
|
||||
private long getNextBuybackTime() {
|
||||
return lastBuyback + ServerConstants.BUYBACK_COOLDOWN_MINUTES * 60 * 1000;
|
||||
}
|
||||
|
||||
public boolean couldBuyback() { // Ronan's buyback system
|
||||
long timeNow = System.currentTimeMillis();
|
||||
|
||||
@@ -5221,7 +5228,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
return false;
|
||||
}
|
||||
|
||||
long nextBuybacktime = lastBuyback + ServerConstants.BUYBACK_COOLDOWN_MINUTES * 60 * 1000;
|
||||
long nextBuybacktime = getNextBuybackTime();
|
||||
if(timeNow < nextBuybacktime) {
|
||||
long timeLeft = nextBuybacktime - timeNow;
|
||||
int seconds = (int) Math.floor(timeLeft / 1000) % 60;
|
||||
@@ -5840,14 +5847,15 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
ret.mgc = new MapleGuildCharacter(ret);
|
||||
int buddyCapacity = rs.getInt("buddyCapacity");
|
||||
ret.buddylist = new BuddyList(buddyCapacity);
|
||||
|
||||
ret.getInventory(MapleInventoryType.EQUIP).setSlotLimit(rs.getByte("equipslots"));
|
||||
ret.getInventory(MapleInventoryType.USE).setSlotLimit(rs.getByte("useslots"));
|
||||
ret.getInventory(MapleInventoryType.SETUP).setSlotLimit(rs.getByte("setupslots"));
|
||||
ret.getInventory(MapleInventoryType.ETC).setSlotLimit(rs.getByte("etcslots"));
|
||||
|
||||
byte sandboxCheck = 0x0;
|
||||
for (Pair<Item, MapleInventoryType> item : ItemFactory.INVENTORY.loadItems(ret.id, !channelserver)) {
|
||||
if(MapleInventoryManipulator.isSandboxItem(item.getLeft())) {
|
||||
ret.setHasSandboxItem();
|
||||
}
|
||||
sandboxCheck |= item.getLeft().getFlag();
|
||||
|
||||
ret.getInventory(item.getRight()).addFromDB(item.getLeft());
|
||||
Item itemz = item.getLeft();
|
||||
@@ -5872,6 +5880,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
}
|
||||
}
|
||||
}
|
||||
if((sandboxCheck & ItemConstants.SANDBOX) == ItemConstants.SANDBOX) ret.setHasSandboxItem();
|
||||
|
||||
World wserv = Server.getInstance().getWorld(ret.world);
|
||||
|
||||
@@ -6072,10 +6081,11 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
ps = con.prepareStatement("SELECT SkillID,StartTime,length FROM cooldowns WHERE charid = ?");
|
||||
ps.setInt(1, ret.getId());
|
||||
rs = ps.executeQuery();
|
||||
long curTime = System.currentTimeMillis();
|
||||
while (rs.next()) {
|
||||
final int skillid = rs.getInt("SkillID");
|
||||
final long length = rs.getLong("length"), startTime = rs.getLong("StartTime");
|
||||
if (skillid != 5221999 && (length + startTime < System.currentTimeMillis())) {
|
||||
if (skillid != 5221999 && (length + startTime < curTime)) {
|
||||
continue;
|
||||
}
|
||||
ret.giveCoolDowns(skillid, startTime, length);
|
||||
|
||||
@@ -75,6 +75,7 @@ public class ServerConstants {
|
||||
public static final boolean USE_MULTIPLE_SAME_EQUIP_DROP = true;//Enables multiple drops by mobs of the same equipment, number of possible drops based on the quantities provided at the drop data.
|
||||
public static final boolean USE_BANISHABLE_TOWN_SCROLL = true; //Enables town scrolls to act as if it's a "player banish", rendering the antibanish scroll effect available.
|
||||
public static final boolean USE_OLD_GMS_STYLED_PQ_NPCS = true; //Enables PQ NPCs with similar behaviour to old GMS style, that skips info about the PQs and immediately tries to register the party in.
|
||||
public static final boolean USE_ENABLE_SOLO_EXPEDITIONS = true; //Enables start expeditions with any number of players. This will also bypass all the Zakum prequest.
|
||||
|
||||
//Announcement Configuration
|
||||
public static final boolean USE_ANNOUNCE_SHOPITEMSOLD = false; //Automatic message sent to owner when an item from the Player Shop or Hired Merchant is sold.
|
||||
@@ -137,6 +138,9 @@ public class ServerConstants {
|
||||
public static final boolean USE_ULTRA_RECOVERY = true; //Massive recovery amounts overtime.
|
||||
public static final boolean USE_ULTRA_THREE_SNAILS = true; //Massive damage on shell toss.
|
||||
|
||||
//Other Skills Configuration
|
||||
public static final boolean USE_FAST_REUSE_HERO_WILL = true;//Greatly reduce cooldown on Hero's Will.
|
||||
|
||||
//Character Configuration
|
||||
public static final boolean USE_ADD_SLOTS_BY_LEVEL = true; //Slots are added each 20 levels.
|
||||
public static final boolean USE_ADD_RATES_BY_LEVEL = true; //Rates are added each 20 levels.
|
||||
|
||||
@@ -487,17 +487,17 @@ public abstract class AbstractDealDamageHandler extends AbstractMaplePacketHandl
|
||||
}
|
||||
if (attack.skill == Paladin.HEAVENS_HAMMER) {
|
||||
if(!monster.isBoss()) {
|
||||
map.damageMonster(player, monster, monster.getHp() - 1);
|
||||
damageMonsterWithSkill(player, map, monster, monster.getHp() - 1, attack.skill, 1777);
|
||||
} else {
|
||||
int HHDmg = (player.calculateMaxBaseDamage(player.getTotalWatk()) * (SkillFactory.getSkill(Paladin.HEAVENS_HAMMER).getEffect(player.getSkillLevel(SkillFactory.getSkill(Paladin.HEAVENS_HAMMER))).getDamage() / 100));
|
||||
map.damageMonster(player, monster, (int) (Math.floor(Math.random() * (HHDmg / 5) + HHDmg * .8)));
|
||||
damageMonsterWithSkill(player, map, monster, (int) (Math.floor(Math.random() * (HHDmg / 5) + HHDmg * .8)), attack.skill, 1777);
|
||||
}
|
||||
} else if (attack.skill == Aran.COMBO_TEMPEST) {
|
||||
if(!monster.isBoss()) {
|
||||
map.damageMonster(player, monster, monster.getHp());
|
||||
damageMonsterWithSkill(player, map, monster, monster.getHp(), attack.skill, 0);
|
||||
} else {
|
||||
int TmpDmg = (player.calculateMaxBaseDamage(player.getTotalWatk()) * (SkillFactory.getSkill(Aran.COMBO_TEMPEST).getEffect(player.getSkillLevel(SkillFactory.getSkill(Aran.COMBO_TEMPEST))).getDamage() / 100));
|
||||
map.damageMonster(player, monster, (int) (Math.floor(Math.random() * (TmpDmg / 5) + TmpDmg * .8)));
|
||||
damageMonsterWithSkill(player, map, monster, (int) (Math.floor(Math.random() * (TmpDmg / 5) + TmpDmg * .8)), attack.skill, 0);
|
||||
}
|
||||
} else {
|
||||
if(attack.skill == Aran.BODY_PRESSURE) {
|
||||
@@ -534,6 +534,26 @@ public abstract class AbstractDealDamageHandler extends AbstractMaplePacketHandl
|
||||
}
|
||||
}
|
||||
|
||||
private static void damageMonsterWithSkill(final MapleCharacter attacker, final MapleMap map, final MapleMonster monster, final int damage, int skillid, int fixedTime) {
|
||||
int animationTime;
|
||||
|
||||
if(fixedTime == 0) animationTime = SkillFactory.getSkill(skillid).getAnimationTime();
|
||||
else animationTime = fixedTime;
|
||||
|
||||
if(animationTime > 0) { // be sure to only use LIMITED ATTACKS with animation time here
|
||||
TimerManager.getInstance().schedule(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
map.broadcastMessage(MaplePacketCreator.damageMonster(monster.getObjectId(), damage), monster.getPosition());
|
||||
map.damageMonster(attacker, monster, damage);
|
||||
}
|
||||
}, animationTime);
|
||||
} else {
|
||||
map.broadcastMessage(MaplePacketCreator.damageMonster(monster.getObjectId(), damage), monster.getPosition());
|
||||
map.damageMonster(attacker, monster, damage);
|
||||
}
|
||||
}
|
||||
|
||||
protected AttackInfo parseDamage(LittleEndianAccessor lea, MapleCharacter chr, boolean ranged, boolean magic) {
|
||||
//2C 00 00 01 91 A1 12 00 A5 57 62 FC E2 75 99 10 00 47 80 01 04 01 C6 CC 02 DD FF 5F 00
|
||||
AttackInfo ret = new AttackInfo();
|
||||
|
||||
@@ -117,6 +117,16 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
|
||||
final MapleCharacter chr = c.getPlayer();
|
||||
|
||||
if (mode == Action.CREATE.getCode()) {
|
||||
if(!chr.isAlive()) { // thanks GabrielSin for pointing this
|
||||
chr.getClient().announce(MaplePacketCreator.getMiniRoomError(4));
|
||||
return;
|
||||
}
|
||||
|
||||
if(chr.getEventInstance() != null) {
|
||||
chr.getClient().announce(MaplePacketCreator.getMiniRoomError(5));
|
||||
return;
|
||||
}
|
||||
|
||||
byte createType = slea.readByte();
|
||||
if (createType == 3) {// trade
|
||||
MapleTrade.startTrade(chr);
|
||||
@@ -585,8 +595,9 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
|
||||
} else if (mode == Action.BAN_PLAYER.getCode()) {
|
||||
slea.skip(1);
|
||||
|
||||
if (chr.getPlayerShop() != null && chr.getPlayerShop().isOwner(chr)) {
|
||||
chr.getPlayerShop().banPlayer(slea.readMapleAsciiString());
|
||||
MaplePlayerShop shop = chr.getPlayerShop();
|
||||
if (shop != null && shop.isOwner(chr)) {
|
||||
shop.banPlayer(slea.readMapleAsciiString());
|
||||
}
|
||||
} else if (mode == Action.EXPEL.getCode()) {
|
||||
MapleMiniGame miniGame = chr.getMiniGame();
|
||||
|
||||
@@ -36,6 +36,7 @@ import client.MapleStat;
|
||||
import client.Skill;
|
||||
import client.SkillFactory;
|
||||
import constants.GameConstants;
|
||||
import constants.ServerConstants;
|
||||
import constants.skills.Brawler;
|
||||
import constants.skills.Corsair;
|
||||
import constants.skills.DarkKnight;
|
||||
@@ -82,8 +83,13 @@ public final class SpecialMoveHandler extends AbstractMaplePacketHandler {
|
||||
if (chr.skillIsCooling(skillid)) {
|
||||
return;
|
||||
} else if (skillid != Corsair.BATTLE_SHIP) {
|
||||
c.announce(MaplePacketCreator.skillCooldown(skillid, effect.getCooldown()));
|
||||
chr.addCooldown(skillid, System.currentTimeMillis(), effect.getCooldown() * 1000);
|
||||
int cooldownTime = effect.getCooldown();
|
||||
if(MapleStatEffect.isHerosWill(skillid) && ServerConstants.USE_FAST_REUSE_HERO_WILL) {
|
||||
cooldownTime /= 60;
|
||||
}
|
||||
|
||||
c.announce(MaplePacketCreator.skillCooldown(skillid, cooldownTime));
|
||||
chr.addCooldown(skillid, System.currentTimeMillis(), cooldownTime * 1000);
|
||||
}
|
||||
}
|
||||
if (skillid == Hero.MONSTER_MAGNET || skillid == Paladin.MONSTER_MAGNET || skillid == DarkKnight.MONSTER_MAGNET) { // Monster Magnet
|
||||
|
||||
@@ -1444,27 +1444,32 @@ public class MapleStatEffect {
|
||||
|
||||
private boolean isCureAllAbnormalStatus() {
|
||||
if (skill) {
|
||||
switch (sourceid) {
|
||||
case Hero.HEROS_WILL:
|
||||
case Paladin.HEROS_WILL:
|
||||
case DarkKnight.HEROS_WILL:
|
||||
case FPArchMage.HEROS_WILL:
|
||||
case ILArchMage.HEROS_WILL:
|
||||
case Bishop.HEROS_WILL:
|
||||
case Bowmaster.HEROS_WILL:
|
||||
case Marksman.HEROS_WILL:
|
||||
case NightLord.HEROS_WILL:
|
||||
case Shadower.HEROS_WILL:
|
||||
case Buccaneer.PIRATES_RAGE:
|
||||
case Aran.HEROS_WILL:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return isHerosWill(sourceid);
|
||||
} else if (sourceid == 2022544) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isHerosWill(int skillid) {
|
||||
switch(skillid) {
|
||||
case Hero.HEROS_WILL:
|
||||
case Paladin.HEROS_WILL:
|
||||
case DarkKnight.HEROS_WILL:
|
||||
case FPArchMage.HEROS_WILL:
|
||||
case ILArchMage.HEROS_WILL:
|
||||
case Bishop.HEROS_WILL:
|
||||
case Bowmaster.HEROS_WILL:
|
||||
case Marksman.HEROS_WILL:
|
||||
case NightLord.HEROS_WILL:
|
||||
case Shadower.HEROS_WILL:
|
||||
case Buccaneer.PIRATES_RAGE:
|
||||
case Aran.HEROS_WILL:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isDash() {
|
||||
return skill && (sourceid == Pirate.DASH || sourceid == ThunderBreaker.DASH || sourceid == Beginner.SPACE_DASH || sourceid == Noblesse.SPACE_DASH);
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
|
||||
package server.expeditions;
|
||||
|
||||
import constants.ServerConstants;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author SharpAceX(Alan)
|
||||
@@ -55,7 +57,7 @@ public enum MapleExpeditionType {
|
||||
}
|
||||
|
||||
public int getMinSize() {
|
||||
return minSize;
|
||||
return !ServerConstants.USE_ENABLE_SOLO_EXPEDITIONS ? minSize : 1;
|
||||
}
|
||||
|
||||
public int getMaxSize() {
|
||||
|
||||
@@ -583,14 +583,18 @@ public class MapleMap {
|
||||
return new Pair<>(getRoundedCoordinate(angle), Integer.valueOf((int)distn));
|
||||
}
|
||||
|
||||
private static void sortDropEntries(List<MonsterDropEntry> from, List<MonsterDropEntry> item, List<MonsterDropEntry> quest) {
|
||||
private static void sortDropEntries(List<MonsterDropEntry> from, List<MonsterDropEntry> item, List<MonsterDropEntry> visibleQuest, List<MonsterDropEntry> otherQuest, MapleCharacter chr) {
|
||||
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
||||
|
||||
for(MonsterDropEntry mde : from) {
|
||||
if(!ii.isQuestItem(mde.itemId)) {
|
||||
item.add(mde);
|
||||
} else {
|
||||
quest.add(mde);
|
||||
if(chr.needQuestItem(mde.questid, mde.itemId)) {
|
||||
visibleQuest.add(mde);
|
||||
} else {
|
||||
otherQuest.add(mde);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -690,8 +694,9 @@ public class MapleMap {
|
||||
final MapleMonsterInformationProvider mi = MapleMonsterInformationProvider.getInstance();
|
||||
|
||||
final List<MonsterDropEntry> dropEntry = new ArrayList<>();
|
||||
final List<MonsterDropEntry> questEntry = new ArrayList<>();
|
||||
sortDropEntries(mi.retrieveEffectiveDrop(mob.getId()), dropEntry, questEntry);
|
||||
final List<MonsterDropEntry> visibleQuestEntry = new ArrayList<>();
|
||||
final List<MonsterDropEntry> otherQuestEntry = new ArrayList<>();
|
||||
sortDropEntries(mi.retrieveEffectiveDrop(mob.getId()), dropEntry, visibleQuestEntry, otherQuestEntry, chr);
|
||||
|
||||
// Normal Drops
|
||||
d = dropItemsFromMonsterOnMap(dropEntry, pos, d, chRate, droptype, mobpos, chr, mob);
|
||||
@@ -701,7 +706,8 @@ public class MapleMap {
|
||||
d = dropGlobalItemsFromMonsterOnMap(globalEntry, pos, d, droptype, mobpos, chr, mob);
|
||||
|
||||
// Quest Drops
|
||||
dropItemsFromMonsterOnMap(questEntry, pos, d, chRate, droptype, mobpos, chr, mob);
|
||||
d = dropItemsFromMonsterOnMap(visibleQuestEntry, pos, d, chRate, droptype, mobpos, chr, mob);
|
||||
dropItemsFromMonsterOnMap(otherQuestEntry, pos, d, chRate, droptype, mobpos, chr, mob);
|
||||
}
|
||||
|
||||
public void dropItemsFromMonster(List<MonsterDropEntry> list, final MapleCharacter chr, final MapleMonster mob) {
|
||||
|
||||
Reference in New Issue
Block a user