Boss Daily Entry + Maker enable actions + Duey Quick Delivery

Fixed Legendary Spirit UI getting stuck when trying to apply scrolls in equipments without upgrade slots available.
Revised map leasing. Players no longer lose ownership when changing maps. Players are allowed to lease one map each time.
Revised expeditions warping players out as soon as the leader leaves the event or the number of players inside gets to be less than the minimum required to enter.
Fixed start/complete quest commands not acting properly for some quests.
Refactored quest loadouts unnecessarily reloading MapleData.
Implemented support for daily boss limit entry, usable on expeditions.
Revised potential exploit cases within chair, face expression, quest action, summon damage and mob damage mob handlers.
Adjusted displayed date in Duey. Value displayed now should be consistent with the expected expiration time.
Refactored damage for friendly mobs getting handled inside packet structure.
Implemented support for Quick Delivery from Duey.
Fixed Horntail specifically not dropping loots after recent updates.
Refactored commands system. All commands are instanced at boot time instead of at every call.
Fixed usage of Maker skill not sending MAKER_RESULT packet to players. This automatically reenables the actions button (such as create) in Maker UI.
Adjusted minidungeons, now using time limits specified in their respective recipes.
Reviewed the "timeLimit" property utilized by maps, which was poised to work on 2 different concepts altogether.
Fixed Gaga space event, should be functional now.
Added RPS minigame, resources implemented by Arnah.
Fixed damage taken from mob auto-destruction not working properly.
This commit is contained in:
ronancpl
2019-06-27 20:34:39 -03:00
parent a39a210c1f
commit fba27fb3b1
82 changed files with 2902 additions and 2611 deletions
+4
View File
@@ -78,6 +78,10 @@ public class DueyPackage {
public long sentTimeInMilliseconds() {
Calendar cal = Calendar.getInstance();
cal.set(year, month, day);
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTimeInMillis();
}
+23 -12
View File
@@ -57,14 +57,19 @@ public class MakerItemFactory {
return makerEntry;
}
public static MakerItemCreateEntry generateLeftoverCrystalEntry(int fromLeftoverid) {
MakerItemCreateEntry ret = new MakerItemCreateEntry(0, 0, 1, 1);
public static MakerItemCreateEntry generateLeftoverCrystalEntry(int fromLeftoverid, int crystalId) {
MakerItemCreateEntry ret = new MakerItemCreateEntry(0, 0, 1);
ret.addReqItem(fromLeftoverid, 100);
ret.addGainItem(crystalId, 1);
return ret;
}
public static MakerItemCreateEntry generateDisassemblyCrystalEntry(int cost, int crystalGain) { // equipment at specific position already taken
MakerItemCreateEntry ret = new MakerItemCreateEntry(cost, 0, 1, crystalGain);
public static MakerItemCreateEntry generateDisassemblyCrystalEntry(int fromEquipid, int cost, List<Pair<Integer, Integer>> gains) { // equipment at specific position already taken
MakerItemCreateEntry ret = new MakerItemCreateEntry(cost, 0, 1);
ret.addReqItem(fromEquipid, 1);
for (Pair<Integer, Integer> p : gains) {
ret.addGainItem(p.getLeft(), p.getRight());
}
return ret;
}
@@ -143,33 +148,35 @@ public class MakerItemFactory {
private double cost;
private int reqCost;
private List<Pair<Integer, Integer>> reqItems = new ArrayList<>(); // itemId / amount
private int toGive;
private List<Pair<Integer, Integer>> gainItems = new ArrayList<>(); // itemId / amount
public MakerItemCreateEntry(int cost, int reqLevel, int reqMakerLevel, int toGive) {
public MakerItemCreateEntry(int cost, int reqLevel, int reqMakerLevel) {
this.cost = cost;
this.reqLevel = reqLevel;
this.reqMakerLevel = reqMakerLevel;
this.toGive = toGive;
}
public MakerItemCreateEntry(MakerItemCreateEntry mi) {
this.cost = mi.cost;
this.reqLevel = mi.reqLevel;
this.reqMakerLevel = mi.reqMakerLevel;
this.toGive = mi.toGive;
for(Pair<Integer, Integer> p : mi.reqItems) {
reqItems.add(p);
}
}
public int getRewardAmount() {
return toGive;
for(Pair<Integer, Integer> p : mi.gainItems) {
gainItems.add(p);
}
}
public List<Pair<Integer, Integer>> getReqItems() {
return reqItems;
}
public List<Pair<Integer, Integer>> getGainItems() {
return gainItems;
}
public int getReqLevel() {
return reqLevel;
@@ -191,6 +198,10 @@ public class MakerItemFactory {
reqItems.add(new Pair<>(itemId, amount));
}
protected void addGainItem(int itemId, int amount) {
gainItems.add(new Pair<>(itemId, amount));
}
public void trimCost() {
reqCost = (int) (cost / 1000);
reqCost *= 1000;
+9 -7
View File
@@ -1968,7 +1968,8 @@ public class MapleItemInformationProvider {
}
ps.close();
rs.close();
makerEntry = new MakerItemCreateEntry(cost, reqLevel, reqMakerLevel, toGive);
makerEntry = new MakerItemCreateEntry(cost, reqLevel, reqMakerLevel);
makerEntry.addGainItem(toCreate, toGive);
ps = con.prepareStatement("SELECT req_item, count FROM makerrecipedata WHERE itemid = ?");
ps.setInt(1, toCreate);
rs = ps.executeQuery();
@@ -2008,17 +2009,18 @@ public class MapleItemInformationProvider {
return -1;
}
public int getMakerDisassembledQuantity(Integer itemId) {
int avail = 0;
public List<Pair<Integer, Integer>> getMakerDisassembledItems(Integer itemId) {
List<Pair<Integer, Integer>> items = new LinkedList<>();
Connection con;
try {
con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("SELECT count FROM makerrecipedata WHERE itemid = ? AND req_item >= 4260000 AND req_item <= 4260008 ORDER BY count DESC");
PreparedStatement ps = con.prepareStatement("SELECT req_item, count FROM makerrecipedata WHERE itemid = ? AND req_item >= 4260000 AND req_item < 4270000");
ps.setInt(1, itemId);
ResultSet rs = ps.executeQuery();
if(rs.next()) {
avail = (int) Math.ceil(rs.getInt("count") / 2); // return to the player half of the crystals needed
while (rs.next()) {
items.add(new Pair<>(rs.getInt("req_item"), rs.getInt("count") / 2)); // return to the player half of the crystals needed
}
rs.close();
@@ -2028,7 +2030,7 @@ public class MapleItemInformationProvider {
e.printStackTrace();
}
return avail;
return items;
}
public int getMakerDisassembledFee(Integer itemId) {
+36 -47
View File
@@ -13,57 +13,46 @@ import client.SkillFactory;
* @author kevintjuh93
*/
public class RescueGaga extends MapleEvents {
private byte fallen;
private int completed;
private int completed;
public RescueGaga(int completed) {
super();
this.completed = completed;
}
public RescueGaga(int completed) {
super();
this.completed = completed;
this.fallen = 0;
}
public int getCompleted() {
return completed;
}
public int fallAndGet() {
fallen++;
if (fallen > 3) {
fallen = 0;
return 4;
}
return fallen;
}
public void complete() {
completed++;
}
public byte getFallen() {
return fallen;
}
public int getCompleted() {
return completed;
}
public void complete() {
completed++;
@Override
public int getInfo() {
return getCompleted();
}
public void giveSkill(MapleCharacter chr) {
int skillid = 0;
switch (chr.getJobType()) {
case 0:
skillid = 1013;
break;
case 1:
case 2:
skillid = 10001014;
}
public int getInfo() {
return getCompleted();
}
public void giveSkill(MapleCharacter chr) {
int skillid = 0;
switch (chr.getJobType()) {
case 0:
skillid = 1013;
break;
case 1:
case 2:
skillid = 10001014;
}
long expiration = (System.currentTimeMillis() + (long) (3600 * 24 * 20 * 1000));//20 days
if (completed < 20) {
chr.changeSkillLevel(SkillFactory.getSkill(skillid), (byte) 1, 1, expiration);
chr.changeSkillLevel(SkillFactory.getSkill(skillid + 1), (byte) 1, 1, expiration);
chr.changeSkillLevel(SkillFactory.getSkill(skillid + 2), (byte) 1, 1, expiration);
} else {
chr.changeSkillLevel(SkillFactory.getSkill(skillid), (byte) 2, 2, chr.getSkillExpiration(skillid));
}
long expiration = (System.currentTimeMillis() + 3600 * 24 * 20 * 1000);//20 days
if (completed < 20) {
chr.changeSkillLevel(SkillFactory.getSkill(skillid), (byte) 1, 1, expiration);
chr.changeSkillLevel(SkillFactory.getSkill(skillid + 1), (byte) 1, 1, expiration);
chr.changeSkillLevel(SkillFactory.getSkill(skillid + 2), (byte) 1, 1, expiration);
} else {
chr.changeSkillLevel(SkillFactory.getSkill(skillid), (byte) 2, 2, chr.getSkillExpiration(skillid));
}
}
}
+25 -2
View File
@@ -46,6 +46,7 @@ import java.util.Properties;
import net.server.audit.locks.MonitoredLockType;
import net.server.audit.locks.MonitoredReentrantLock;
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
import net.server.channel.Channel;
/**
*
@@ -137,7 +138,7 @@ public class MapleExpedition {
@Override
public void run() {
if (registering){
startMap.getChannelServer().removeExpedition(exped);
exped.removeChannelExpedition(startMap.getChannelServer());
if (!silent) startMap.broadcastMessage(MaplePacketCreator.serverNotice(6, "[Expedition] The time limit has been reached. Expedition has been disbanded."));
dispose(false);
@@ -163,6 +164,7 @@ public class MapleExpedition {
public void start(){
finishRegistration();
registerExpeditionAttempt();
broadcastExped(MaplePacketCreator.removeClock());
if (!silent) broadcastExped(MaplePacketCreator.serverNotice(6, "[Expedition] The expedition has started! Good luck, brave heroes!"));
startTime = System.currentTimeMillis();
@@ -180,6 +182,11 @@ public class MapleExpedition {
return "Sorry, this expedition is full!";
}
int channel = this.getRecruitingMap().getChannelServer().getId();
if (!MapleExpeditionBossLog.attemptBoss(player.getId(), channel, this, false)) { // thanks Conrad, Cato for noticing some expeditions have entry limit
return "Sorry, you've already reached the quota of attempts for this expedition! Try again another day...";
}
members.put(player.getId(), player.getName());
player.announce(MaplePacketCreator.getClock((int)(startTime - System.currentTimeMillis()) / 1000));
if (!silent) broadcastExped(MaplePacketCreator.serverNotice(6, "[Expedition] " + player.getName() + " has joined the expedition!"));
@@ -202,13 +209,21 @@ public class MapleExpedition {
if (!silent) broadcastExped(MaplePacketCreator.serverNotice(6, "[Expedition] " + player.getName() + " has joined the expedition!"));
return 0; //"You have registered for the expedition successfully!";
}
private void registerExpeditionAttempt(){
int channel = this.getRecruitingMap().getChannelServer().getId();
for (MapleCharacter chr : getActiveMembers()){
MapleExpeditionBossLog.attemptBoss(chr.getId(), channel, this, true);
}
}
private void broadcastExped(byte[] packet){
for (MapleCharacter chr : getActiveMembers()){
chr.announce(packet);
}
}
public boolean removeMember(MapleCharacter chr) {
if(members.remove(chr.getId()) != null) {
chr.announce(MaplePacketCreator.removeClock());
@@ -359,6 +374,14 @@ public class MapleExpedition {
chr.changeMap(warpTo, toSp);
}
}
public final boolean addChannelExpedition(Channel ch) {
return ch.addExpedition(this);
}
public final void removeChannelExpedition(Channel ch) {
ch.removeExpedition(this);
}
public MapleCharacter getLeader(){
return leader;
@@ -0,0 +1,205 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft (L) 2016 - 2018 RonanLana
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 server.expeditions;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.LinkedList;
import java.util.List;
import tools.DatabaseConnection;
import tools.Pair;
/**
*
* @author Conrad
* @author Ronan
*/
public class MapleExpeditionBossLog {
public enum BossLogEntry {
ZAKUM(2, 1, false),
HORNTAIL(2, 1, false),
PINKBEAN(1, 1, false),
SCARGA(1, 1, false),
PAPULATUS(2, 1, false);
private int entries;
private int timeLength;
private int minChannel, maxChannel;
private boolean week;
private BossLogEntry(int entries, int timeLength, boolean week) {
this(entries, 0, Integer.MAX_VALUE, timeLength, week);
}
private BossLogEntry(int entries, int minChannel, int maxChannel, int timeLength, boolean week) {
this.entries = entries;
this.minChannel = minChannel;
this.maxChannel = maxChannel;
this.timeLength = timeLength;
this.week = week;
}
private static List<Pair<Timestamp, BossLogEntry>> getBossLogResetTimestamps(Calendar timeNow, boolean week) {
List<Pair<Timestamp, BossLogEntry>> resetTimestamps = new LinkedList<>();
for (BossLogEntry b : BossLogEntry.values()) {
if (b.week == week) {
Calendar c = (Calendar) timeNow.clone();
c.roll(Calendar.DAY_OF_MONTH, -1 * (week ? 7 : 1) * b.timeLength);
Timestamp ts = new Timestamp(c.getTime().getTime());
resetTimestamps.add(new Pair<>(ts, b));
}
}
return resetTimestamps;
}
private static BossLogEntry getBossEntryByName(String name) {
for (BossLogEntry b : BossLogEntry.values()) {
if (name.contentEquals(b.name())) {
return b;
}
}
return null;
}
}
public static void resetBossLogTable() {
/*
Boss logs resets 12am, weekly thursday 12AM - thanks Smitty Werbenjagermanjensen (superadlez) - https://www.reddit.com/r/Maplestory/comments/61tiup/about_reset_time/
*/
Calendar thursday = Calendar.getInstance();
thursday.set(Calendar.DAY_OF_WEEK, Calendar.THURSDAY);
thursday.set(Calendar.HOUR, 0);
thursday.set(Calendar.MINUTE, 0);
thursday.set(Calendar.SECOND, 0);
Calendar now = Calendar.getInstance();
long weekLength = 7 * 24 * 60 * 60 * 1000;
long halfDayLength = 12 * 60 * 60 * 1000;
long deltaTime = now.getTime().getTime() - thursday.getTime().getTime(); // 2x time: get Date into millis
deltaTime += halfDayLength;
deltaTime %= weekLength;
deltaTime -= halfDayLength;
if (deltaTime < halfDayLength) {
MapleExpeditionBossLog.resetBossLogTable(true, thursday);
}
now.set(Calendar.HOUR, 0);
now.set(Calendar.MINUTE, 0);
now.set(Calendar.SECOND, 0);
MapleExpeditionBossLog.resetBossLogTable(false, now);
}
private static void resetBossLogTable(boolean week, Calendar c) {
List<Pair<Timestamp, BossLogEntry>> resetTimestamps = BossLogEntry.getBossLogResetTimestamps(c, week);
try {
Connection con = DatabaseConnection.getConnection();
for (Pair<Timestamp, BossLogEntry> p : resetTimestamps) {
PreparedStatement ps = con.prepareStatement("DELETE FROM " + getBossLogTable(week) + " WHERE attempttime <= ? AND bosstype LIKE ?");
ps.setTimestamp(1, p.getLeft());
ps.setString(2, p.getRight().name());
ps.executeUpdate();
ps.close();
}
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
private static String getBossLogTable(boolean week) {
return week ? "bosslog_weekly" : "bosslog_daily";
}
private static int countPlayerEntries(int cid, BossLogEntry boss) {
int ret_count = 0;
try {
Connection con = DatabaseConnection.getConnection();
PreparedStatement ps;
ps = con.prepareStatement("SELECT COUNT(*) FROM " + getBossLogTable(boss.week) + " WHERE characterid = ? AND bosstype LIKE ?");
ps.setInt(1, cid);
ps.setString(2, boss.name());
ResultSet rs = ps.executeQuery();
if (rs.next()) {
ret_count = rs.getInt(1);
} else {
ret_count = -1;
}
rs.close();
ps.close();
con.close();
return ret_count;
} catch (SQLException e) {
e.printStackTrace();
return -1;
}
}
private static void insertPlayerEntry(int cid, BossLogEntry boss) {
try {
Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("INSERT INTO " + getBossLogTable(boss.week) + " (characterid, bosstype) VALUES (?,?)");
ps.setInt(1, cid);
ps.setString(2, boss.name());
ps.executeUpdate();
ps.close();
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static boolean attemptBoss(int cid, int channel, MapleExpedition exped, boolean log) {
BossLogEntry boss = BossLogEntry.getBossEntryByName(exped.getType().name());
if (boss == null) {
return true;
}
if (channel < boss.minChannel || channel > boss.maxChannel) {
return false;
}
if (countPlayerEntries(cid, boss) >= boss.entries) {
return false;
}
if (log) {
insertPlayerEntry(cid, boss);
}
return true;
}
}
+12 -20
View File
@@ -415,7 +415,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
*/
if (damage > 0) {
this.applyDamage(attacker, damage, stayAlive);
this.applyDamage(attacker, damage, stayAlive, false);
if (!this.isAlive()) { // monster just died
lastHit = true;
}
@@ -433,7 +433,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
* @param damage
* @param stayAlive
*/
private void applyDamage(MapleCharacter from, int damage, boolean stayAlive) {
private void applyDamage(MapleCharacter from, int damage, boolean stayAlive, boolean fake) {
Integer trueDamage = applyAndGetHpDamage(damage, stayAlive);
if (trueDamage == null) {
return;
@@ -442,8 +442,11 @@ public class MapleMonster extends AbstractLoadedMapleLife {
if (ServerConstants.USE_DEBUG) {
from.dropMessage(5, "Hitted MOB " + this.getId() + ", OID " + this.getObjectId());
}
dispatchMonsterDamaged(from, trueDamage);
if (!fake) {
dispatchMonsterDamaged(from, trueDamage);
}
if (!takenDamage.containsKey(from.getId())) {
takenDamage.put(from.getId(), new AtomicLong(trueDamage));
} else {
@@ -453,6 +456,10 @@ public class MapleMonster extends AbstractLoadedMapleLife {
broadcastMobHpBar(from);
}
public void applyFakeDamage(MapleCharacter from, int damage, boolean stayAlive) {
applyDamage(from, damage, stayAlive, true);
}
public void heal(int hp, int mp) {
Integer hpHealed = applyAndGetHpDamage(-hp, false);
if (hpHealed == null) {
@@ -744,21 +751,6 @@ public class MapleMonster extends AbstractLoadedMapleLife {
if (toSpawn.contains(timeMob.getLeft())) {
reviveMap.broadcastMessage(MaplePacketCreator.serverNotice(6, timeMob.getRight()));
}
if (timeMob.getLeft() == 9300338 && (reviveMap.getId() >= 922240100 && reviveMap.getId() <= 922240119)) {
if (!reviveMap.containsNPC(9001108)) {
MapleNPC npc = MapleLifeFactory.getNPC(9001108);
npc.setPosition(new Point(172, 9));
npc.setCy(9);
npc.setRx0(172 + 50);
npc.setRx1(172 - 50);
npc.setFh(27);
reviveMap.addMapObject(npc);
reviveMap.broadcastMessage(MaplePacketCreator.spawnNPC(npc));
} else {
reviveMap.toggleHiddenNPC(9001108);
}
}
}
if(toSpawn.size() > 0) {
@@ -1621,7 +1613,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
if (damage > 0) {
lockMonster();
try {
applyDamage(chr, damage, true);
applyDamage(chr, damage, true, false);
} finally {
unlockMonster();
}
+43 -47
View File
@@ -101,6 +101,7 @@ public class MapleMap {
private static final Map<Integer, Pair<Integer, Integer>> dropBoundsCache = new HashMap<>(100);
private Map<Integer, MapleMapObject> mapobjects = new LinkedHashMap<>();
private Set<Integer> selfDestructives = new LinkedHashSet<>();
private Collection<SpawnPoint> monsterSpawn = Collections.synchronizedList(new LinkedList<SpawnPoint>());
private Collection<SpawnPoint> allMonsterSpawn = Collections.synchronizedList(new LinkedList<SpawnPoint>());
private AtomicInteger spawnedMonstersOnMap = new AtomicInteger(0);
@@ -122,6 +123,7 @@ public class MapleMap {
private AtomicInteger runningOid = new AtomicInteger(1000000001);
private int returnMapId;
private int channel, world;
private int seats;
private byte monsterRate;
private boolean clock;
private boolean boat;
@@ -132,7 +134,8 @@ public class MapleMap {
private MapleMapEffect mapEffect = null;
private boolean everlast = false;
private int forcedReturnMap = 999999999;
private long timeLimit;
private int timeLimit;
private long mapTimer;
private int decHP = 0;
private int protectItem = 0;
private boolean town;
@@ -145,7 +148,6 @@ public class MapleMap {
private int fieldLimit = 0;
private int mobCapacity = -1;
private MapleMonsterAggroCoordinator aggroMonitor = null; // aggroMonitor activity in sync with itemMonitor
private ScheduledFuture<?> mapMonitor = null;
private ScheduledFuture<?> itemMonitor = null;
private ScheduledFuture<?> expireItemsTask = null;
private ScheduledFuture<?> mobSpawnLootTask = null;
@@ -307,7 +309,7 @@ public class MapleMap {
this.forcedReturnMap = map;
}
public long getTimeLimit() {
public int getTimeLimit() {
return timeLimit;
}
@@ -316,7 +318,7 @@ public class MapleMap {
}
public int getTimeLeft() {
return (int) ((timeLimit - System.currentTimeMillis()) / 1000);
return (int) ((mapTimer - System.currentTimeMillis()) / 1000);
}
public void setReactorState() {
@@ -398,6 +400,16 @@ public class MapleMap {
}
}
public void addSelfDestructive(MapleMonster mob) {
if (mob.getStats().selfDestruction() != null) {
this.selfDestructives.add(mob.getObjectId());
}
}
public boolean removeSelfDestructive(int mapobjectid) {
return this.selfDestructives.remove(mapobjectid);
}
private void spawnAndAddRangedMapObject(MapleMapObject mapobject, DelayedPacketCreation packetbakery) {
spawnAndAddRangedMapObject(mapobject, packetbakery, null);
}
@@ -1331,9 +1343,11 @@ public class MapleMap {
}
if (monster.isAlive()) {
boolean killed = monster.damage(chr, damage, false);
if (monster.getStats().selfDestruction() != null && monster.getStats().selfDestruction().getHp() > -1) {// should work ;p
if (monster.getHp() <= monster.getStats().selfDestruction().getHp()) {
killMonster(monster, chr, true, monster.getStats().selfDestruction().getAction());
selfDestruction selfDestr = monster.getStats().selfDestruction();
if (selfDestr != null && selfDestr.getHp() > -1) {// should work ;p
if (monster.getHp() <= selfDestr.getHp()) {
killMonster(monster, chr, true, selfDestr.getAction());
return true;
}
}
@@ -1907,7 +1921,6 @@ public class MapleMap {
spawnAndAddRangedMapObject(monster, new DelayedPacketCreation() {
@Override
public void sendPackets(MapleClient c) {
c.announce(MaplePacketCreator.spawnMonster(monster, false));
}
});
@@ -1919,6 +1932,7 @@ public class MapleMap {
}
spawnedMonstersOnMap.incrementAndGet();
addSelfDestructive(monster);
applyRemoveAfter(monster);
}
@@ -2052,6 +2066,7 @@ public class MapleMap {
}
spawnedMonstersOnMap.incrementAndGet();
addSelfDestructive(monster);
applyRemoveAfter(monster); // thanks LightRyuzaki for pointing issues with spawned CWKPQ mobs not applying this
}
@@ -2088,6 +2103,7 @@ public class MapleMap {
}
spawnedMonstersOnMap.incrementAndGet();
addSelfDestructive(monster);
applyRemoveAfter(monster);
}
@@ -2102,6 +2118,7 @@ public class MapleMap {
});
spawnedMonstersOnMap.incrementAndGet();
addSelfDestructive(monster);
}
public void makeMonsterReal(final MapleMonster monster) {
@@ -3812,6 +3829,14 @@ public class MapleMap {
public boolean getDocked() {
return this.docked;
}
public void setSeats(int seats) {
this.seats = seats;
}
public int getSeats() {
return seats;
}
public void broadcastGMMessage(MapleCharacter source, final byte[] packet, boolean repeatToSource) {
broadcastGMMessage(repeatToSource ? null : source, packet, Double.POSITIVE_INFINITY, source.getPosition());
@@ -3904,35 +3929,7 @@ public class MapleMap {
this.broadcastMessage(MaplePacketCreator.removeItemFromMap(i.getObjectId(), 0, 0));
}
}
public void addMapTimer(int time) {
timeLimit = System.currentTimeMillis() + (time * 1000);
broadcastMessage(MaplePacketCreator.getClock(time));
mapMonitor = TimerManager.getInstance().register(new Runnable() {
@Override
public void run() {
if (timeLimit != 0 && timeLimit < System.currentTimeMillis()) {
warpEveryone(getForcedReturnId());
}
if (getCharacters().isEmpty()) {
resetReactors();
killAllMonsters();
clearDrops();
timeLimit = 0;
if (mapid >= 922240100 && mapid <= 922240119) {
toggleHiddenNPC(9001108);
}
if (mapMonitor != null) {
mapMonitor.cancel(true);
mapMonitor = null;
}
}
}
}, 1000);
}
public void setFieldLimit(int fieldLimit) {
this.fieldLimit = fieldLimit;
}
@@ -4079,7 +4076,7 @@ public class MapleMap {
return this.mapid >= 109010000 && this.mapid < 109050000 || this.mapid > 109050001 && this.mapid <= 109090000;
}
public void timeMob(int id, String msg) {
public void setTimeMob(int id, String msg) {
timeMob = new Pair<>(id, msg);
}
@@ -4206,8 +4203,8 @@ public class MapleMap {
@Override
public void monsterDamaged(MapleCharacter from, int trueDmg) {
ht.applyAndGetHpDamage(trueDmg, true);
ht.broadcastMobHpBar(from);
// thanks Halcyon for noticing HT not dropping loots due to propagated damage not registering attacker
ht.applyFakeDamage(from, trueDmg, true);
}
@Override
@@ -4222,7 +4219,9 @@ public class MapleMap {
public boolean claimOwnership(MapleCharacter chr) {
if (mapOwner == null) {
mapOwner = chr;
this.mapOwner = chr;
chr.setOwnedMap(this);
mapOwnerLastActivityTime = Server.getInstance().getCurrentTime();
getChannelServer().registerOwnedMap(this);
@@ -4234,7 +4233,9 @@ public class MapleMap {
public boolean unclaimOwnership(MapleCharacter chr) {
if (mapOwner == chr) {
mapOwner = null;
this.mapOwner = null;
chr.setOwnedMap(null);
mapOwnerLastActivityTime = Long.MAX_VALUE;
getChannelServer().unregisterOwnedMap(this);
@@ -4533,11 +4534,6 @@ public class MapleMap {
portals.clear();
mapEffect = null;
if(mapMonitor != null) {
mapMonitor.cancel(false);
mapMonitor = null;
}
chrWLock.lock();
try {
aggroMonitor.dispose();
+5 -2
View File
@@ -172,8 +172,7 @@ public class MapleMapFactory {
}
MapleData timeMob = infoData.getChildByPath("timeMob");
if (timeMob != null) {
map.timeMob(MapleDataTool.getInt(timeMob.getChildByPath("id")),
MapleDataTool.getString(timeMob.getChildByPath("message")));
map.setTimeMob(MapleDataTool.getInt(timeMob.getChildByPath("id")), MapleDataTool.getString(timeMob.getChildByPath("message")));
}
int bounds[] = new int[4];
@@ -243,6 +242,10 @@ public class MapleMapFactory {
map.addMapleArea(new Rectangle(x1, y1, (x2 - x1), (y2 - y1)));
}
}
if (mapData.getChildByPath("seat") != null) {
int seats = mapData.getChildByPath("seat").getChildren().size();
map.setSeats(seats);
}
if (event == null) {
try {
Connection con = DatabaseConnection.getConnection();
+2 -2
View File
@@ -42,9 +42,9 @@ public class MapleMiniDungeon {
int baseMap;
long expireTime;
public MapleMiniDungeon(int base, int durationMin) {
public MapleMiniDungeon(int base, long timeLimit) {
baseMap = base;
expireTime = durationMin * 60 * 1000;
expireTime = timeLimit * 1000;
timeoutTask = TimerManager.getInstance().schedule(new Runnable() {
@Override
@@ -0,0 +1,84 @@
package server.minigame;
import client.MapleClient;
import client.inventory.Item;
import client.inventory.manipulator.MapleInventoryManipulator;
import tools.MaplePacketCreator;
import tools.Randomizer;
/**
* @Author Arnah
* @Website http://Vertisy.ca/
* @since Aug 15, 2016
*/
public class MapleRockPaperScissor{
private int round = 0;
private boolean ableAnswer = true;
private boolean win = false;
public MapleRockPaperScissor(final MapleClient c, final byte mode){
c.announce(MaplePacketCreator.rpsMode((byte) (9 + mode)));
if(mode == 0){
c.getPlayer().gainMeso(-1000, true, true, true);
}
}
public final boolean answer(final MapleClient c, final int answer){
if(ableAnswer && !win && answer >= 0 && answer <= 2){
final int response = Randomizer.nextInt(3);
if(response == answer){
c.announce(MaplePacketCreator.rpsSelection((byte) response, (byte) round));
// dont do anything. they can still answer once a draw
}else if((answer == 0 && response == 2) || (answer == 1 && response == 0) || (answer == 2 && response == 1)){ // they win
c.announce(MaplePacketCreator.rpsSelection((byte) response, (byte) (round + 1)));
ableAnswer = false;
win = true;
}else{ // they lose
c.announce(MaplePacketCreator.rpsSelection((byte) response, (byte) -1));
ableAnswer = false;
}
return true;
}
reward(c);
return false;
}
public final boolean timeOut(final MapleClient c){
if(ableAnswer && !win){
ableAnswer = false;
c.announce(MaplePacketCreator.rpsMode((byte) 0x0A));
return true;
}
reward(c);
return false;
}
public final boolean nextRound(final MapleClient c){
if(win){
round++;
if(round < 10){
win = false;
ableAnswer = true;
c.announce(MaplePacketCreator.rpsMode((byte) 0x0C));
return true;
} else {
round = 10;
}
}
reward(c);
return false;
}
public final void reward(final MapleClient c){
if(win){
MapleInventoryManipulator.addFromDrop(c, new Item(4031332 + round, (short) 0, (short) 1), true);
}
c.getPlayer().setRPS(null);
}
public final void dispose(final MapleClient c){
reward(c);
c.announce(MaplePacketCreator.rpsMode((byte) 0x0D));
}
}
+1 -1
View File
@@ -272,7 +272,7 @@ public class AriantColiseum {
}
private void enterKingsRoom() {
map.getChannelServer().removeExpedition(exped);
exped.removeChannelExpedition(map.getChannelServer());
cancelAriantSchedules();
for (MapleCharacter chr : map.getAllPlayers()) {
+3 -11
View File
@@ -73,9 +73,9 @@ public class MapleQuest {
private boolean repeatable = false;
private String name = "", parent = "";
private final static MapleDataProvider questData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Quest.wz"));
private static MapleData questInfo;
private static MapleData questAct;
private static MapleData questReq;
private final static MapleData questInfo = questData.getData("QuestInfo.img");
private final static MapleData questAct = questData.getData("Act.img");
private final static MapleData questReq = questData.getData("Check.img");
private MapleQuest(int id) {
this.id = (short) id;
@@ -186,10 +186,6 @@ public class MapleQuest {
public static MapleQuest getInstance(int id) {
MapleQuest ret = quests.get(id);
if (ret == null) {
questInfo = questData.getData("QuestInfo.img");
questReq = questData.getData("Check.img");
questAct = questData.getData("Act.img");
ret = new MapleQuest(id);
quests.put(id, ret);
}
@@ -590,10 +586,6 @@ public class MapleQuest {
}
public static void loadAllQuest() {
questInfo = questData.getData("QuestInfo.img");
questReq = questData.getData("Check.img");
questAct = questData.getData("Act.img");
try {
for(MapleData quest : questInfo.getChildren()) {
int questID = Integer.parseInt(quest.getName());