diff --git a/config.yaml b/config.yaml
index c6d0e0d6a3..4d7ec5d6d5 100644
--- a/config.yaml
+++ b/config.yaml
@@ -332,7 +332,8 @@ server:
ITEM_EXPIRE_CHECK: 10000 # (10 * 10000) Interval between item expiring tasks on maps, which checks and makes disappear expired items.
ITEM_LIMIT_ON_MAP: 200 #Max number of items allowed on a map.
MAP_VISITED_SIZE: 5 #Max length for last mapids visited by a player. This is used to recover and update drops on these maps accordingly with player actions.
- MAP_DAMAGE_OVERTIME_INTERVAL: 5000 #Interval in milliseconds between map environment damage (e.g. El Nath and Aqua Road surrondings).
+ MAP_DAMAGE_OVERTIME_INTERVAL: 2500 #Interval in milliseconds between map environment damage (e.g. El Nath and Aqua Road surrondings).
+ MAP_DAMAGE_OVERTIME_COUNT: 2
#Channel Mob Disease Monitor Configuration
MOB_STATUS_MONITOR_PROC: 200 #Frequency in milliseconds between each proc on the mob disease monitor schedule.
diff --git a/src/main/java/client/Character.java b/src/main/java/client/Character.java
index 1f8615b7af..c5cd8faf57 100644
--- a/src/main/java/client/Character.java
+++ b/src/main/java/client/Character.java
@@ -251,7 +251,6 @@ public class Character extends AbstractCharacterObject {
private boolean loggedIn = false;
private boolean useCS; //chaos scroll upon crafting item.
private long npcCd;
- private long lastHpDec = 0;
private int newWarpMap = -1;
private boolean canWarpMap = true; //only one "warp" must be used per call, and this will define the right one.
private int canWarpCounter = 0; //counts how many times "inner warps" have been called.
@@ -1720,10 +1719,6 @@ public class Character extends AbstractCharacterObject {
Character.this.getParty().setEnemy(k);
}
silentPartyUpdateInternal(getParty()); // EIM script calls inside
-
- if (getMap().getHPDec() > 0) {
- resetHpDecreaseTask();
- }
} else {
log.warn("Chr {} got stuck when moving to map {}", getName(), map.getId());
client.disconnect(true, false); // thanks BHB for noticing a player storage stuck case here
@@ -2767,31 +2762,12 @@ public class Character extends AbstractCharacterObject {
}
}
- private void doHurtHp() {
+ public void doHurtHp() {
if (!(this.getInventory(InventoryType.EQUIPPED).findById(getMap().getHPDecProtect()) != null || buffMapProtection())) {
addHP(-getMap().getHPDec());
- lastHpDec = Server.getInstance().getCurrentTime();
}
}
- private void startHpDecreaseTask(long lastHpTask) {
- hpDecreaseTask = TimerManager.getInstance().register(new Runnable() {
- @Override
- public void run() {
- doHurtHp();
- }
- }, YamlConfig.config.server.MAP_DAMAGE_OVERTIME_INTERVAL, YamlConfig.config.server.MAP_DAMAGE_OVERTIME_INTERVAL - lastHpTask);
- }
-
- public void resetHpDecreaseTask() {
- if (hpDecreaseTask != null) {
- hpDecreaseTask.cancel(false);
- }
-
- long lastHpTask = Server.getInstance().getCurrentTime() - lastHpDec;
- startHpDecreaseTask((lastHpTask > YamlConfig.config.server.MAP_DAMAGE_OVERTIME_INTERVAL) ? YamlConfig.config.server.MAP_DAMAGE_OVERTIME_INTERVAL : lastHpTask);
- }
-
public void dropMessage(String message) {
dropMessage(0, message);
}
diff --git a/src/main/java/client/Client.java b/src/main/java/client/Client.java
index 5ed36fbcb7..46224343f7 100644
--- a/src/main/java/client/Client.java
+++ b/src/main/java/client/Client.java
@@ -940,6 +940,10 @@ public class Client extends ChannelInboundHandlerAdapter {
if (MapId.isDojo(mapId)) {
this.getChannelServer().freeDojoSectionIfEmpty(mapId);
}
+
+ if (player.getMap().getHPDec() > 0) {
+ getWorldServer().removePlayerHpDecrease(player);
+ }
}
} catch (final Throwable t) {
diff --git a/src/main/java/config/ServerConfig.java b/src/main/java/config/ServerConfig.java
index c3248fa364..cbd771246a 100644
--- a/src/main/java/config/ServerConfig.java
+++ b/src/main/java/config/ServerConfig.java
@@ -180,6 +180,7 @@ public class ServerConfig {
public int ITEM_LIMIT_ON_MAP;
public int MAP_VISITED_SIZE;
public int MAP_DAMAGE_OVERTIME_INTERVAL;
+ public int MAP_DAMAGE_OVERTIME_COUNT;
//Channel Mob Disease Monitor Configuration
public int MOB_STATUS_MONITOR_PROC;
diff --git a/src/main/java/net/server/channel/handlers/ItemMoveHandler.java b/src/main/java/net/server/channel/handlers/ItemMoveHandler.java
index dcb97b90a5..23d95a40d9 100644
--- a/src/main/java/net/server/channel/handlers/ItemMoveHandler.java
+++ b/src/main/java/net/server/channel/handlers/ItemMoveHandler.java
@@ -55,9 +55,6 @@ public final class ItemMoveHandler extends AbstractPacketHandler {
InventoryManipulator.move(c, type, src, action);
}
- if (c.getPlayer().getMap().getHPDec() > 0) {
- c.getPlayer().resetHpDecreaseTask();
- }
c.getPlayer().getAutobanManager().spam(6);
}
}
\ No newline at end of file
diff --git a/src/main/java/net/server/channel/handlers/PlayerLoggedinHandler.java b/src/main/java/net/server/channel/handlers/PlayerLoggedinHandler.java
index 4e261c3a1b..61ccc18149 100644
--- a/src/main/java/net/server/channel/handlers/PlayerLoggedinHandler.java
+++ b/src/main/java/net/server/channel/handlers/PlayerLoggedinHandler.java
@@ -386,10 +386,6 @@ public final class PlayerLoggedinHandler extends AbstractPacketHandler {
player.commitExcludedItems();
showDueyNotification(c, player);
- if (player.getMap().getHPDec() > 0) {
- player.resetHpDecreaseTask();
- }
-
player.resetPlayerRates();
if (YamlConfig.config.server.USE_ADD_RATES_BY_LEVEL) {
player.setPlayerRates();
diff --git a/src/main/java/net/server/task/CharacterHpDecreaseTask.java b/src/main/java/net/server/task/CharacterHpDecreaseTask.java
new file mode 100644
index 0000000000..ed62fb9073
--- /dev/null
+++ b/src/main/java/net/server/task/CharacterHpDecreaseTask.java
@@ -0,0 +1,37 @@
+/*
+ This file is part of the HeavenMS MapleStory Server
+ Copyleft (L) 2016 - 2019 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 .
+*/
+package net.server.task;
+
+import net.server.world.World;
+
+/**
+ * @author Ronan
+ */
+public class CharacterHpDecreaseTask extends BaseTask implements Runnable {
+
+ @Override
+ public void run() {
+ wserv.runPlayerHpDecreaseSchedule();
+ }
+
+ public CharacterHpDecreaseTask(World world) {
+ super(world);
+ }
+}
diff --git a/src/main/java/net/server/world/World.java b/src/main/java/net/server/world/World.java
index 5b41cdf826..f41775ee6b 100644
--- a/src/main/java/net/server/world/World.java
+++ b/src/main/java/net/server/world/World.java
@@ -153,6 +153,7 @@ public class World {
private MonitoredReentrantLock timedMapObjectLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.WORLD_MAPOBJS, true);
private final Map fishingAttempters = Collections.synchronizedMap(new WeakHashMap<>());
+ private Map playerHpDec = Collections.synchronizedMap(new WeakHashMap<>());
private ScheduledFuture> charactersSchedule;
private ScheduledFuture> marriagesSchedule;
@@ -160,6 +161,7 @@ public class World {
private ScheduledFuture> fishingSchedule;
private ScheduledFuture> partySearchSchedule;
private ScheduledFuture> timeoutSchedule;
+ private ScheduledFuture> hpDecSchedule;
public World(int world, int flag, String eventmsg, int exprate, int droprate, int bossdroprate, int mesorate, int questrate, int travelrate, int fishingrate) {
this.id = world;
@@ -194,6 +196,7 @@ public class World {
fishingSchedule = tman.register(new FishingTask(this), SECONDS.toMillis(10), SECONDS.toMillis(10));
partySearchSchedule = tman.register(new PartySearchTask(this), SECONDS.toMillis(10), SECONDS.toMillis(10));
timeoutSchedule = tman.register(new TimeoutTask(this), SECONDS.toMillis(10), SECONDS.toMillis(10));
+ hpDecSchedule = tman.register(new CharacterHpDecreaseTask(this), YamlConfig.config.server.MAP_DAMAGE_OVERTIME_INTERVAL, YamlConfig.config.server.MAP_DAMAGE_OVERTIME_INTERVAL);
if (YamlConfig.config.server.USE_FAMILY_SYSTEM) {
long timeLeft = Server.getTimeLeftForNextDay();
@@ -1715,6 +1718,33 @@ public class World {
r.run();
}
}
+
+ public void addPlayerHpDecrease(Character chr) {
+ playerHpDec.putIfAbsent(chr, 0);
+ }
+
+ public void removePlayerHpDecrease(Character chr) {
+ playerHpDec.remove(chr);
+ }
+
+ public void runPlayerHpDecreaseSchedule() {
+ Map m = new HashMap<>();
+ m.putAll(playerHpDec);
+
+ for (Entry e : m.entrySet()) {
+ Character chr = e.getKey();
+
+ if (!chr.isAwayFromWorld()) {
+ int c = e.getValue();
+ c = (c + 1) % YamlConfig.config.server.MAP_DAMAGE_OVERTIME_COUNT;
+ playerHpDec.replace(chr, c);
+
+ if (c == 0) {
+ chr.doHurtHp();
+ }
+ }
+ }
+ }
public void resetDisabledServerMessages() {
srvMessagesLock.lock();
@@ -2149,6 +2179,11 @@ public class World {
timeoutSchedule.cancel(false);
timeoutSchedule = null;
}
+
+ if(hpDecSchedule != null) {
+ hpDecSchedule.cancel(false);
+ hpDecSchedule = null;
+ }
players.disconnectAll();
players = null;
diff --git a/src/main/java/server/maps/MapleMap.java b/src/main/java/server/maps/MapleMap.java
index 747c906043..50b46fa9c0 100644
--- a/src/main/java/server/maps/MapleMap.java
+++ b/src/main/java/server/maps/MapleMap.java
@@ -2379,6 +2379,12 @@ public class MapleMap {
chr.setMapId(mapid);
chr.updateActiveEffects();
+
+ if (this.getHPDec() > 0) {
+ getWorldServer().addPlayerHpDecrease(chr);
+ } else {
+ getWorldServer().removePlayerHpDecrease(chr);
+ }
MapScriptManager msm = MapScriptManager.getInstance();
if (chrSize == 1) {