Water of Life + Fixed GPQ & Buff system

Added Water of Life. Fixed Shuang (GPQ) npc dc'ing the leader when first
trying to enter the waiting area. Fixed some cases with the revamped
buff system, that would not properly check for the best buffs in some
scenarios, and would throw exceptions, caused by not properly protecting
access to critical data.
This commit is contained in:
ronancpl
2017-09-25 02:16:24 -03:00
parent 7bbf512797
commit 28258530e4
47 changed files with 316 additions and 47 deletions

View File

@@ -20,6 +20,11 @@ Server files: https://github.com/ronancpl/MapleSolaxiaV2
Client files & general tools: https://drive.google.com/drive/folders/0BzDsHSr-0V4MYVJ0TWIxd05hYUk Client files & general tools: https://drive.google.com/drive/folders/0BzDsHSr-0V4MYVJ0TWIxd05hYUk
---
### Donation
If you liked what you have seen on the project, donate a little something as a helping hand for my contributions towards Maple development. Paypal: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3K8KVTWRLFBQ4
--- ---
### Preparing the ambient ### Preparing the ambient

View File

@@ -1,4 +1,4 @@
#Fri, 22 Sep 2017 22:54:29 -0300 #Mon, 25 Sep 2017 01:46:09 -0300
C\:\\Nexon\\MapleSolaxia\\MapleSolaxiaV2= C\:\\Nexon\\MapleSolaxia\\MapleSolaxiaV2=

Binary file not shown.

BIN
dist/MapleSolaxia.jar vendored

Binary file not shown.

View File

@@ -32,7 +32,7 @@ Quests:
* Quests can now reward properly items when matching a reward item with the player's job. * Quests can now reward properly items when matching a reward item with the player's job.
* Loads of quests have been patched. * Loads of quests have been patched.
* Quest rewards according to jobs works properly. * Quest rewards according to jobs works properly.
* Rewarding system now checks for stacking opportunities on the inventory before checking for new slots. * Enchanced rewarding system: checks for stacking opportunities on the inventory before checking for new slots.
Player Social Network: Player Social Network:
* Guild and Alliance system fully functional. * Guild and Alliance system fully functional.
@@ -60,6 +60,7 @@ Server potentials:
* Mastery book announcer displays droppers of needed books of a player, by reading underlying DB. * Mastery book announcer displays droppers of needed books of a player, by reading underlying DB.
* Every skill/mastery book is now droppable by mobs. * Every skill/mastery book is now droppable by mobs.
* Inventory auto-gather and auto-sorting feature. * Inventory auto-gather and auto-sorting feature.
* Enhanced buff system: smartly checks for the best available buff effects to be active on the player.
* Enhanced AP auto-assigner: exactly matches AP with the needed for the player's current level, surplus assigned to the primary attribute. * Enhanced AP auto-assigner: exactly matches AP with the needed for the player's current level, surplus assigned to the primary attribute.
* Added Boss HP Bar for dozens of bosses (needs provided custom wz). * Added Boss HP Bar for dozens of bosses (needs provided custom wz).
* If multiple bosses are on the same area, client will prioritize Boss HP bar of the target of the player. * If multiple bosses are on the same area, client will prioritize Boss HP bar of the target of the player.

View File

@@ -545,4 +545,8 @@ Completamente reestruturado sistema de buffs. Nova flag permite perman
22 Setembro 2017, 22 Setembro 2017,
Adicionado buffs para GPQ. Adicionado buffs para GPQ.
Consertado GPQ não iniciando devido a problemas com o script de evento. Consertado GPQ não iniciando devido a problemas com o script de evento.
23 Setembro 2017,
Adicionado Water of Life.
Consertado bug com sistema novo de buffs ao entrar no cash shop e em outros cenários onde não se detectava o melhor buff corretamente.

View File

@@ -2,14 +2,6 @@
<project-private xmlns="http://www.netbeans.org/ns/project-private/1"> <project-private xmlns="http://www.netbeans.org/ns/project-private/1">
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="1"/> <editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="1"/>
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2"> <open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
<group> <group/>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/event/GuildQuest.js</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/npc/9040000.js</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/scripting/event/EventInstanceManager.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/client/MapleCharacter.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/scripting/event/EventManager.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/npc/1052013.js</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/event/AmoriaPQ.js</file>
</group>
</open-files> </open-files>
</project-private> </project-private>

View File

@@ -25,7 +25,7 @@
*/ */
var isPq = true; var isPq = true;
var minPlayers = 1, maxPlayers = 30; var minPlayers = 6, maxPlayers = 30;
var minLevel = 1, maxLevel = 255; var minLevel = 1, maxLevel = 255;
var entryMap = 990000000; var entryMap = 990000000;
var exitMap = 990001100; var exitMap = 990001100;
@@ -201,10 +201,10 @@ function scheduledTimeout(eim) {
} else { } else {
eim.startEventTimer(eventTime * 60000); eim.startEventTimer(eventTime * 60000);
//if(isTeamAllJobs(eim)) { if(isTeamAllJobs(eim)) {
var rnd = Math.floor(Math.random() * 4); var rnd = Math.floor(Math.random() * 4);
eim.applyEventPlayersItemBuff(2023000 + rnd); eim.applyEventPlayersItemBuff(2023000 + rnd);
//} }
} }
} else { } else {
end(eim); end(eim);

View File

@@ -104,7 +104,7 @@ function action(mode, type, selection) {
} }
} else if (status == 2) { } else if (status == 2) {
if (selection == 0) { if (selection == 0) {
MapleInventoryManipulator.removeFromSlot(cm.getC(), MapleInventoryType.CASH, 1, 1, true); MapleInventoryManipulator.removeFromSlot(cm.getClient(), MapleInventoryType.CASH, 1, 1, true);
cm.sendOk("Your cash first slot is removed."); cm.sendOk("Your cash first slot is removed.");
} else if (selection == 1) { } else if (selection == 1) {
if (cm.haveItem(5000029, 2)) { if (cm.haveItem(5000029, 2)) {

View File

@@ -0,0 +1,95 @@
/*
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/>.
*/
/* Mar the Fairy
Handles Water of Life
*/
importPackage(Packages.client.inventory);
importPackage(Packages.server);
var status;
var dList;
function start() {
status = -1;
dList = cm.getDriedPets();
if(dList.size() == 0) {
cm.playerMessage(5, "You currently do not own a pet that needs to be treated with Water of Life.");
cm.dispose();
return;
}
action(1, 0, 0);
}
function action(mode, type, selection) {
if (mode == -1) {
cm.dispose();
} else {
if (mode == 0 && type > 0) {
cm.dispose();
return;
}
if (mode == 1)
status++;
else
status--;
if (status == 0) {
cm.sendYesNo("I am Mar the Fairy. You have the #bWater of Life#k... With this, I can bring a doll back to life with my magic. What do you think? Do you want to use this item and reawaken your pet ...?");
} else if (status == 1) {
var talkStr = "So which pet you want to reawaken? Please choose the pet you'd most like to reawaken...\r\n\r\n";
var listStr = "";
var i = 0;
var dIter = dList.iterator();
while (dIter.hasNext()){
var dPet = dIter.next();
listStr += "#b#L" + i + "# " + dPet.getName() + " #k - Lv " + dPet.getLevel() + " Closeness " + dPet.getCloseness();
listStr += "#l\r\n";
i++;
}
cm.sendSimple(talkStr + listStr);
} else if (status == 2) {
var sPet = dList.get(selection);
if(sPet != null) {
cm.sendNext("Your doll has now reawaken as your pet! However, my magic isn't perfect, so I can't promise an eternal life for your pet... Please take care of that pet before the Water of Life dries. Well then, good bye...");
var it = cm.getPlayer().getInventory(MapleInventoryType.CASH).getItem(sPet.getPosition());
it.setExpiration(Date.now() + (1000 * 60 * 60 * 24 * 90));
cm.getPlayer().forceUpdateItem(it);
cm.gainItem(5180000, -1);
} else {
cm.sendNext("Oh, well then. Good bye...");
}
cm.dispose();
}
}
}

View File

@@ -92,7 +92,7 @@ function end(mode, type, selection) {
name = MapleItemInformationProvider.getInstance().getName(after); name = MapleItemInformationProvider.getInstance().getName(after);
} */ } */
//qm.unequipPet(qm.getC()); //qm.unequipPet(qm.getClient());
qm.gainItem(5380000, -1); qm.gainItem(5380000, -1);
qm.gainMeso(-10000); qm.gainMeso(-10000);
qm.evolvePet(i, after); qm.evolvePet(i, after);

View File

@@ -19820,6 +19820,15 @@ USE `maplesolaxia`;
(9420501, 1492005, 1, 1, 0, 2000), (9420501, 1492005, 1, 1, 0, 2000),
(8820001, 2388043, 1, 1, 0, 24000); (8820001, 2388043, 1, 1, 0, 24000);
# zhelms, pink bean customs
DELETE FROM temp_data WHERE itemid=1002357;
INSERT IGNORE INTO temp_data (`dropperid`, `itemid`, `minimum_quantity`, `maximum_quantity`, `questid`, `chance`) VALUES
(8800002, 1002357, 1, 1, 0, 300000),
(8800002, 1002390, 1, 1, 0, 80000),
(8800002, 1002430, 1, 1, 0, 40000),
(8820001, 1002971, 1, 1, 0, 80000),
(8820001, 1052202, 1, 1, 0, 80000);
# delete item drops from bosses in inactive form # delete item drops from bosses in inactive form
DELETE FROM temp_data WHERE dropperid=4220001; DELETE FROM temp_data WHERE dropperid=4220001;
DELETE FROM temp_data WHERE dropperid=5220001; DELETE FROM temp_data WHERE dropperid=5220001;

View File

@@ -151,11 +151,12 @@ import scripting.item.ItemScriptManager;
import server.maps.MapleMapItem; import server.maps.MapleMapItem;
public class MapleCharacter extends AbstractAnimatedMapleMapObject { public class MapleCharacter extends AbstractAnimatedMapleMapObject {
private static NumberFormat nf = new DecimalFormat("#,###,###,###");
private static final String LEVEL_200 = "[Congrats] %s has reached Level 200! Congratulate %s on such an amazing achievement!"; private static final String LEVEL_200 = "[Congrats] %s has reached Level 200! Congratulate %s on such an amazing achievement!";
private static final String[] BLOCKED_NAMES = {"admin", "owner", "moderator", "intern", "donor", "administrator", "help", "helper", "alert", "notice", "maplestory", "Solaxia", "fuck", "wizet", "fucking", "negro", "fuk", "fuc", "penis", "pussy", "asshole", "gay", private static final String[] BLOCKED_NAMES = {"admin", "owner", "moderator", "intern", "donor", "administrator", "help", "helper", "alert", "notice", "maplestory", "Solaxia", "fuck", "wizet", "fucking", "negro", "fuk", "fuc", "penis", "pussy", "asshole", "gay",
"nigger", "homo", "suck", "cum", "shit", "shitty", "condom", "security", "official", "rape", "nigga", "sex", "tit", "boner", "orgy", "clit", "asshole", "fatass", "bitch", "support", "gamemaster", "cock", "gaay", "gm", "nigger", "homo", "suck", "cum", "shit", "shitty", "condom", "security", "official", "rape", "nigga", "sex", "tit", "boner", "orgy", "clit", "asshole", "fatass", "bitch", "support", "gamemaster", "cock", "gaay", "gm",
"operate", "master", "sysop", "party", "GameMaster", "community", "message", "event", "test", "meso", "Scania", "renewal", "yata", "AsiaSoft", "henesys"}; "operate", "master", "sysop", "party", "GameMaster", "community", "message", "event", "test", "meso", "Scania", "renewal", "yata", "AsiaSoft", "henesys"};
private int world; private int world;
private int accountid, id; private int accountid, id;
private int rank, rankMove, jobRank, jobRankMove; private int rank, rankMove, jobRank, jobRankMove;
@@ -260,7 +261,6 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
private Lock chrLock = new ReentrantLock(); private Lock chrLock = new ReentrantLock();
private Lock effLock = new ReentrantLock(); private Lock effLock = new ReentrantLock();
private Lock petLock = new ReentrantLock(); private Lock petLock = new ReentrantLock();
private NumberFormat nf = new DecimalFormat("#,###,###,###");
private Map<Integer, Set<Integer>> excluded = new LinkedHashMap<>(); private Map<Integer, Set<Integer>> excluded = new LinkedHashMap<>();
private Set<Integer> excludedItems = new LinkedHashSet<>(); private Set<Integer> excludedItems = new LinkedHashSet<>();
private List<MapleRing> crushRings = new ArrayList<>(); private List<MapleRing> crushRings = new ArrayList<>();
@@ -2095,22 +2095,26 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
@Override @Override
public void run() { public void run() {
Set<Entry<Integer, Long>> es; Set<Entry<Integer, Long>> es;
List<MapleBuffStatValueHolder> toCancel = new ArrayList<>();
effLock.lock(); effLock.lock();
chrLock.lock(); chrLock.lock();
try { try {
es = new LinkedHashSet<>(buffExpires.entrySet()); es = new LinkedHashSet<>(buffExpires.entrySet());
long curTime = System.currentTimeMillis();
for(Entry<Integer, Long> bel : es) {
if(curTime >= bel.getValue()) {
toCancel.add(buffEffects.get(bel.getKey()).entrySet().iterator().next().getValue()); //rofl
}
}
} finally { } finally {
chrLock.unlock(); chrLock.unlock();
effLock.unlock(); effLock.unlock();
} }
long curTime = System.currentTimeMillis(); for(MapleBuffStatValueHolder mbsvh : toCancel) {
for(Entry<Integer, Long> bel : es) { cancelEffect(mbsvh.effect, false, mbsvh.startTime);
if(curTime >= bel.getValue()) {
MapleBuffStatValueHolder mbsvh = buffEffects.get(bel.getKey()).entrySet().iterator().next().getValue(); // rofl
cancelEffect(mbsvh.effect, false, mbsvh.startTime);
}
} }
} }
}, 1500); }, 1500);
@@ -2181,6 +2185,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
for (MapleInventory inv : inventory) { for (MapleInventory inv : inventory) {
for (Item item : inv.list()) { for (Item item : inv.list()) {
expiration = item.getExpiration(); expiration = item.getExpiration();
if (expiration != -1 && (expiration < currenttime) && ((item.getFlag() & ItemConstants.LOCK) == ItemConstants.LOCK)) { if (expiration != -1 && (expiration < currenttime) && ((item.getFlag() & ItemConstants.LOCK) == ItemConstants.LOCK)) {
byte aids = item.getFlag(); byte aids = item.getFlag();
aids &= ~(ItemConstants.LOCK); aids &= ~(ItemConstants.LOCK);
@@ -2188,10 +2193,15 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
item.setExpiration(-1); item.setExpiration(-1);
forceUpdateItem(item); //TEST :3 forceUpdateItem(item); //TEST :3
} else if (expiration != -1 && expiration < currenttime) { } else if (expiration != -1 && expiration < currenttime) {
client.announce(MaplePacketCreator.itemExpired(item.getItemId())); if(!ItemConstants.isPet(item.getItemId()) || ServerConstants.USE_ERASE_PET_ON_EXPIRATION) {
toberemove.add(item); client.announce(MaplePacketCreator.itemExpired(item.getItemId()));
if(ItemConstants.isRateCoupon(item.getItemId())) { toberemove.add(item);
deletedCoupon = true; if(ItemConstants.isRateCoupon(item.getItemId())) {
deletedCoupon = true;
}
} else {
item.setExpiration(-1);
forceUpdateItem(item);
} }
} }
} }
@@ -2472,7 +2482,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
effLock.lock(); effLock.lock();
chrLock.lock(); chrLock.lock();
try { try {
return buffEffects.keySet(); return new LinkedHashSet<>(buffEffects.keySet());
} finally { } finally {
chrLock.unlock(); chrLock.unlock();
effLock.unlock(); effLock.unlock();
@@ -2500,12 +2510,14 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
effLock.lock(); effLock.lock();
chrLock.lock(); chrLock.lock();
try { try {
long curtime = System.currentTimeMillis();
Map<Integer, PlayerBuffValueHolder> ret = new LinkedHashMap<>(); Map<Integer, PlayerBuffValueHolder> ret = new LinkedHashMap<>();
for(Map<MapleBuffStat, MapleBuffStatValueHolder> bel : buffEffects.values()) { for(Map<MapleBuffStat, MapleBuffStatValueHolder> bel : buffEffects.values()) {
for(MapleBuffStatValueHolder mbsvh : bel.values()) { for(MapleBuffStatValueHolder mbsvh : bel.values()) {
int srcid = mbsvh.effect.getBuffSourceId(); int srcid = mbsvh.effect.getBuffSourceId();
if(!ret.containsKey(srcid)) { if(!ret.containsKey(srcid)) {
ret.put(srcid, new PlayerBuffValueHolder(mbsvh.startTime, mbsvh.effect)); ret.put(srcid, new PlayerBuffValueHolder((int)(curtime - mbsvh.startTime), mbsvh.effect));
} }
} }
} }
@@ -2826,16 +2838,32 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
chrLock.lock(); chrLock.lock();
try { try {
Map<Integer, Pair<MapleStatEffect, Long>> retrievedEffects = new LinkedHashMap<>(); Map<Integer, Pair<MapleStatEffect, Long>> retrievedEffects = new LinkedHashMap<>();
Map<MapleBuffStat, Pair<Integer, Integer>> maxStatups = new LinkedHashMap<>();
for(Entry<Integer, Map<MapleBuffStat, MapleBuffStatValueHolder>> bel : buffEffects.entrySet()) { for(Entry<Integer, Map<MapleBuffStat, MapleBuffStatValueHolder>> bel : buffEffects.entrySet()) {
for(Entry<MapleBuffStat, MapleBuffStatValueHolder> belv : bel.getValue().entrySet()) { for(Entry<MapleBuffStat, MapleBuffStatValueHolder> belv : bel.getValue().entrySet()) {
if(removedStats.contains(belv.getKey())) { if(removedStats.contains(belv.getKey())) {
retrievedEffects.put(bel.getKey(), new Pair<>(belv.getValue().effect, belv.getValue().startTime)); if(!retrievedEffects.containsKey(bel.getKey())) {
retrievedEffects.put(bel.getKey(), new Pair<>(belv.getValue().effect, belv.getValue().startTime));
}
Pair<Integer, Integer> thisStat = maxStatups.get(belv.getKey());
if(thisStat == null || belv.getValue().value > thisStat.getRight()) {
maxStatups.put(belv.getKey(), new Pair<>(bel.getKey(), belv.getValue().value));
}
} }
} }
} }
for(Entry<Integer, Pair<MapleStatEffect, Long>> lmse: retrievedEffects.entrySet()) { Map<Integer, Pair<MapleStatEffect, Long>> bestEffects = new LinkedHashMap<>();
for(Entry<MapleBuffStat, Pair<Integer, Integer>> lmse: maxStatups.entrySet()) {
Integer srcid = lmse.getValue().getLeft();
if(!bestEffects.containsKey(srcid)) {
bestEffects.put(srcid, retrievedEffects.get(srcid));
}
}
for(Entry<Integer, Pair<MapleStatEffect, Long>> lmse: bestEffects.entrySet()) {
lmse.getValue().getLeft().updateBuffEffect(this, getActiveStatupsFromSourceid(lmse.getKey()), lmse.getValue().getRight()); lmse.getValue().getLeft().updateBuffEffect(this, getActiveStatupsFromSourceid(lmse.getKey()), lmse.getValue().getRight());
} }
} finally { } finally {
@@ -6933,9 +6961,10 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
setHp(getHp(), true); setHp(getHp(), true);
} }
public void silentGiveBuffs(List<PlayerBuffValueHolder> buffs) { public void silentGiveBuffs(List<Pair<Long, PlayerBuffValueHolder>> buffs) {
for (PlayerBuffValueHolder mbsvh : buffs) { for (Pair<Long, PlayerBuffValueHolder> mbsv : buffs) {
mbsvh.effect.silentApplyBuff(this, mbsvh.startTime); PlayerBuffValueHolder mbsvh = mbsv.getRight();
mbsvh.effect.silentApplyBuff(this, mbsv.getLeft());
} }
} }

View File

@@ -49,6 +49,7 @@ public class ServerConstants {
public static final boolean USE_REFRESH_RANK_MOVE = true; 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 to 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. public static final boolean USE_ERASE_UNTRADEABLE_DROP = true; //Forces flagged untradeable items to disappear when dropped.
public static final boolean USE_ERASE_PET_ON_EXPIRATION = false;//Forces pets to be removed from inventory when expire time comes, rather than converting it to a doll.
public static final boolean USE_BUFF_MOST_SIGNIFICANT = true; //When applying buffs, the player will stick with the highest stat boost among the listed, rather than overwriting stats. public static final boolean USE_BUFF_MOST_SIGNIFICANT = true; //When applying buffs, the player will stick with the highest stat boost among the listed, rather than overwriting stats.
//Server Rates And Experience //Server Rates And Experience

View File

@@ -245,6 +245,7 @@ public final class PacketProcessor {
registerHandler(RecvOpcode.MONSTER_CARNIVAL, new MonsterCarnivalHandler()); registerHandler(RecvOpcode.MONSTER_CARNIVAL, new MonsterCarnivalHandler());
registerHandler(RecvOpcode.REMOTE_STORE, new RemoteStoreHandler()); registerHandler(RecvOpcode.REMOTE_STORE, new RemoteStoreHandler());
registerHandler(RecvOpcode.WEDDING_ACTION, new WeddingHandler()); registerHandler(RecvOpcode.WEDDING_ACTION, new WeddingHandler());
registerHandler(RecvOpcode.WATER_OF_LIFE, new UseWaterOfLifeHandler());
registerHandler(RecvOpcode.ADMIN_CHAT, new AdminChatHandler()); registerHandler(RecvOpcode.ADMIN_CHAT, new AdminChatHandler());
registerHandler(RecvOpcode.MOVE_DRAGON, new MoveDragonHandler()); registerHandler(RecvOpcode.MOVE_DRAGON, new MoveDragonHandler());
} }

View File

@@ -116,6 +116,7 @@ public enum RecvOpcode {
USE_ITEM_REWARD(0x70), USE_ITEM_REWARD(0x70),
MAKER_SKILL(0x71), MAKER_SKILL(0x71),
USE_REMOTE(0x74), USE_REMOTE(0x74),
WATER_OF_LIFE(0x75),
ADMIN_CHAT(0x76), ADMIN_CHAT(0x76),
PARTYCHAT(0x77), PARTYCHAT(0x77),
WHISPER(0x78), WHISPER(0x78),

View File

@@ -28,11 +28,11 @@ import server.MapleStatEffect;
* @author Danny * @author Danny
*/ */
public class PlayerBuffValueHolder { public class PlayerBuffValueHolder {
public long startTime; public int usedTime;
public MapleStatEffect effect; public MapleStatEffect effect;
public PlayerBuffValueHolder(long startTime, MapleStatEffect effect) { public PlayerBuffValueHolder(int usedTime, MapleStatEffect effect) {
this.startTime = startTime; this.usedTime = usedTime;
this.effect = effect; this.effect = effect;
} }
} }

View File

@@ -41,7 +41,6 @@ public final class CancelBuffHandler extends AbstractMaplePacketHandler implemen
@Override @Override
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) { public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
int sourceid = slea.readInt(); int sourceid = slea.readInt();
if(sourceid < 0) sourceid = -sourceid; //oh my...
switch (sourceid) { switch (sourceid) {
case FPArchMage.BIG_BANG: case FPArchMage.BIG_BANG:

View File

@@ -25,6 +25,7 @@ import java.sql.Connection;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import net.AbstractMaplePacketHandler; import net.AbstractMaplePacketHandler;
@@ -39,9 +40,11 @@ import net.server.world.PartyOperation;
import net.server.world.World; import net.server.world.World;
import tools.DatabaseConnection; import tools.DatabaseConnection;
import tools.MaplePacketCreator; import tools.MaplePacketCreator;
import tools.Pair;
import tools.data.input.SeekableLittleEndianAccessor; import tools.data.input.SeekableLittleEndianAccessor;
import client.BuddylistEntry; import client.BuddylistEntry;
import client.CharacterNameAndId; import client.CharacterNameAndId;
import client.MapleBuffStat;
import client.MapleCharacter; import client.MapleCharacter;
import client.MapleClient; import client.MapleClient;
import client.MapleFamily; import client.MapleFamily;
@@ -50,6 +53,8 @@ import client.inventory.MapleInventoryType;
import client.inventory.MaplePet; import client.inventory.MaplePet;
import constants.GameConstants; import constants.GameConstants;
import constants.ServerConstants; import constants.ServerConstants;
import java.util.Collections;
import java.util.Comparator;
public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler { public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
@@ -107,7 +112,8 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
List<PlayerBuffValueHolder> buffs = server.getPlayerBuffStorage().getBuffsFromStorage(cid); List<PlayerBuffValueHolder> buffs = server.getPlayerBuffStorage().getBuffsFromStorage(cid);
if (buffs != null) { if (buffs != null) {
player.silentGiveBuffs(buffs); List<Pair<Long, PlayerBuffValueHolder>> timedBuffs = getLocalStartTimes(buffs);
player.silentGiveBuffs(timedBuffs);
} }
Connection con = null; Connection con = null;
PreparedStatement ps = null; PreparedStatement ps = null;
@@ -286,4 +292,22 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
player.receivePartyMemberHP(); player.receivePartyMemberHP();
} }
private List<Pair<Long, PlayerBuffValueHolder>> getLocalStartTimes(List<PlayerBuffValueHolder> lpbvl) {
List<Pair<Long, PlayerBuffValueHolder>> timedBuffs = new ArrayList<>();
long curtime = System.currentTimeMillis();
for(PlayerBuffValueHolder pb : lpbvl) {
timedBuffs.add(new Pair<>(curtime - pb.usedTime, pb));
}
Collections.sort(timedBuffs, new Comparator<Pair<Long, PlayerBuffValueHolder>>() {
@Override
public int compare(Pair<Long, PlayerBuffValueHolder> p1, Pair<Long, PlayerBuffValueHolder> p2) {
return p1.getLeft().compareTo(p2.getLeft());
}
});
return timedBuffs;
}
} }

View File

@@ -0,0 +1,34 @@
/*
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.channel.handlers;
import client.MapleClient;
import net.AbstractMaplePacketHandler;
import tools.data.input.SeekableLittleEndianAccessor;
public final class UseWaterOfLifeHandler extends AbstractMaplePacketHandler {
@Override
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
c.getAbstractPlayerInteraction().openNpc(1032102, "waterOfLife");
}
}

View File

@@ -901,4 +901,21 @@ public class AbstractPlayerInteraction {
public long getJailTimeLeft() { public long getJailTimeLeft() {
return getPlayer().getJailExpirationTimeLeft(); return getPlayer().getJailExpirationTimeLeft();
} }
public List<MaplePet> getDriedPets() {
List<MaplePet> list = new LinkedList<>();
long curTime = System.currentTimeMillis();
for(Item it : getPlayer().getInventory(MapleInventoryType.CASH).list()) {
if(ItemConstants.isPet(it.getItemId()) && it.getExpiration() < curTime) {
MaplePet pet = it.getPet();
if (pet != null) {
list.add(pet);
}
}
}
return list;
}
} }

View File

@@ -978,16 +978,14 @@ public class MapleStatEffect {
Rectangle bounds = new Rectangle(mylt.x, mylt.y, myrb.x - mylt.x, myrb.y - mylt.y); Rectangle bounds = new Rectangle(mylt.x, mylt.y, myrb.x - mylt.x, myrb.y - mylt.y);
return bounds; return bounds;
} }
public void silentApplyBuff(MapleCharacter chr, long starttime) { public void silentApplyBuff(MapleCharacter chr, long localStartTime) {
int localDuration = duration; int localDuration = duration;
localDuration = alchemistModifyVal(chr, localDuration, false); localDuration = alchemistModifyVal(chr, localDuration, false);
//CancelEffectAction cancelAction = new CancelEffectAction(chr, this, starttime); //CancelEffectAction cancelAction = new CancelEffectAction(chr, this, starttime);
//ScheduledFuture<?> schedule = TimerManager.getInstance().schedule(cancelAction, ((starttime + localDuration) - System.currentTimeMillis())); //ScheduledFuture<?> schedule = TimerManager.getInstance().schedule(cancelAction, ((starttime + localDuration) - System.currentTimeMillis()));
if(starttime + localDuration <= System.currentTimeMillis()) return; chr.registerEffect(this, localStartTime, localStartTime + localDuration, true);
chr.registerEffect(this, starttime, (starttime + localDuration), true);
SummonMovementType summonMovementType = getSummonMovementType(); SummonMovementType summonMovementType = getSummonMovementType();
if (summonMovementType != null) { if (summonMovementType != null) {
final MapleSummon tosummon = new MapleSummon(chr, sourceid, chr.getPosition(), summonMovementType); final MapleSummon tosummon = new MapleSummon(chr, sourceid, chr.getPosition(), summonMovementType);

View File

@@ -83731,7 +83731,7 @@
</imgdir> </imgdir>
<imgdir name="8166"> <imgdir name="8166">
<int name="SN" value="60000002"/> <int name="SN" value="60000002"/>
<int name="ItemId" value="5000014"/> <int name="ItemId" value="5000015"/>
<int name="Count" value="1"/> <int name="Count" value="1"/>
<int name="Price" value="6700"/> <int name="Price" value="6700"/>
<int name="Period" value="0"/> <int name="Period" value="0"/>
@@ -91605,6 +91605,16 @@
<int name="Period" value="90"/> <int name="Period" value="90"/>
<int name="OnSale" value="0"/> <int name="OnSale" value="0"/>
</imgdir> </imgdir>
<imgdir name="8941">
<int name="Count" value="1"/>
<int name="Gender" value="2"/>
<int name="ItemId" value="5000013"/>
<int name="OnSale" value="1"/>
<int name="Period" value="90"/>
<int name="Price" value="5900"/>
<int name="Priority" value="7"/>
<int name="SN" value="60001000"/>
</imgdir>
<imgdir name="8940"> <imgdir name="8940">
<int name="SN" value="92000020"/> <int name="SN" value="92000020"/>
<int name="ItemId" value="5041000"/> <int name="ItemId" value="5041000"/>
@@ -91612,4 +91622,53 @@
<int name="Period" value="90"/> <int name="Period" value="90"/>
<int name="OnSale" value="0"/> <int name="OnSale" value="0"/>
</imgdir> </imgdir>
<imgdir name="8946">
<int name="Count" value="1"/>
<int name="Gender" value="2"/>
<int name="ItemId" value="5000060"/>
<int name="OnSale" value="1"/>
<int name="Price" value="20000"/>
<int name="Priority" value="6"/>
<int name="SN" value="60001005"/>
</imgdir>
<imgdir name="8945">
<int name="Count" value="1"/>
<int name="Gender" value="2"/>
<int name="ItemId" value="5000034"/>
<int name="OnSale" value="1"/>
<int name="Period" value="90"/>
<int name="Price" value="5800"/>
<int name="Priority" value="7"/>
<int name="SN" value="60001004"/>
</imgdir>
<imgdir name="8944">
<int name="Count" value="1"/>
<int name="Gender" value="2"/>
<int name="ItemId" value="5000045"/>
<int name="OnSale" value="1"/>
<int name="Period" value="90"/>
<int name="Price" value="5600"/>
<int name="Priority" value="7"/>
<int name="SN" value="60001003"/>
</imgdir>
<imgdir name="8943">
<int name="Count" value="1"/>
<int name="Gender" value="2"/>
<int name="ItemId" value="5000044"/>
<int name="OnSale" value="1"/>
<int name="Period" value="90"/>
<int name="Price" value="6900"/>
<int name="Priority" value="7"/>
<int name="SN" value="60001002"/>
</imgdir>
<imgdir name="8942">
<int name="Count" value="1"/>
<int name="Gender" value="2"/>
<int name="ItemId" value="5000039"/>
<int name="OnSale" value="1"/>
<int name="Period" value="90"/>
<int name="Price" value="5800"/>
<int name="Priority" value="7"/>
<int name="SN" value="60001001"/>
</imgdir>
</imgdir> </imgdir>