Heal & Summons atk limit + Skills on change job + Java8 scripting fix

Adjusted reactor drops, now performing spray-like for any reactor.
Revised usage of synchronized statements in several methods in the source.
Fixed a quest from the Aran questline using "password" system unpredictedly.
Fixed column name in table "reports".
Fixed commands "startquest" and "completequest" not using the quest's NPC in the talk window.
Fixed HP regen bonuses such as sauna robes and from Endure skill, when applied in maps with improved regen, leading to false-positives (with the heal on the player).
Fixed a recent typo on a property from HenesysPQ.
Fixed "Combat Step" effect showing twice for other players.
Fixed type-cast issues within some script-hubbing methods in some Java classes.
Reactivated an unused flag that ignores level difference when applying EXP gains to party players.
Fixed Gaviota not disappearing after attack, as defined in the description of the skill.
Fixed CPQ1 field 3 & 4 not allowing players to use summons/protectors.
Fixed exped leaders still receiving exped creation packets even though it was dismissed due to failure on starting (daily entry limit, other fail cases).
Fixed a locking issue that would show up due to a infinite loop case within the procedure that makes disappear items immediately if there were already many items on map.
Fixed several summon skills not using buff icons.
Fixed max damage calculation for summons getting extremely low values when either a player doesn't equip a weapon or attack value is too low.
Fixed explosive loots not taking effect at all, although loot drop-types were already implemented.
Fixed NPE cases when trying to update position of summons/dragons server-side.
Reviewed reactor reset of reactors that disappears for a while. They are now supposed to return immediately once issued a reset.
This commit is contained in:
ronancpl
2019-07-28 17:34:52 -03:00
parent 442d45bef2
commit 85812ba489
52 changed files with 475 additions and 283 deletions
+19 -30
View File
@@ -387,9 +387,10 @@ public class MapleMap {
}
public void addMapObject(MapleMapObject mapobject) {
int curOID = getUsableOID();
objectWLock.lock();
try {
int curOID = getUsableOID();
mapobject.setObjectId(curOID);
this.mapobjects.put(curOID, mapobject);
} finally {
@@ -413,11 +414,11 @@ public class MapleMap {
private void spawnAndAddRangedMapObject(MapleMapObject mapobject, DelayedPacketCreation packetbakery, SpawnCondition condition) {
List<MapleCharacter> inRangeCharacters = new LinkedList<>();
int curOID = getUsableOID();
chrRLock.lock();
objectWLock.lock();
try {
int curOID = getUsableOID();
mapobject.setObjectId(curOID);
this.mapobjects.put(curOID, mapobject);
for (MapleCharacter chr : characters) {
@@ -896,15 +897,16 @@ public class MapleMap {
return droppedItemCount.get();
}
private synchronized void instantiateItemDrop(MapleMapItem mdrop) {
private void instantiateItemDrop(MapleMapItem mdrop) {
if(droppedItemCount.get() >= ServerConstants.ITEM_LIMIT_ON_MAP) {
MapleMapObject mapobj;
do {
mapobj = null;
objectWLock.lock();
try {
mapobj = registeredDrops.remove(0).get();
while(mapobj == null) {
while (mapobj == null) {
if (registeredDrops.isEmpty()) {
break;
}
@@ -1576,18 +1578,11 @@ public class MapleMap {
public void destroyReactor(int oid) {
final MapleReactor reactor = getReactorByOid(oid);
broadcastMessage(MaplePacketCreator.destroyReactor(reactor));
reactor.cancelReactorTimeout();
reactor.setAlive(false);
removeMapObject(reactor);
if (reactor.getDelay() > 0) {
registerMapSchedule(new Runnable() {
@Override
public void run() {
respawnReactor(reactor);
}
}, reactor.getDelay());
if (reactor != null) {
if (reactor.destroy()) {
removeMapObject(reactor);
}
}
}
@@ -1611,9 +1606,14 @@ public class MapleMap {
public final void resetReactors(List<MapleReactor> list) {
for (MapleReactor r : list) {
if (r.forceDelayedRespawn()) { // thanks Conrad for suggesting reactor with delay respawning immediately
continue;
}
r.lockReactor();
try {
r.resetReactorActions(0);
r.setAlive(true);
broadcastMessage(MaplePacketCreator.triggerReactor(r, 0));
} finally {
r.unlockReactor();
@@ -1742,7 +1742,7 @@ public class MapleMap {
public void destroyNPC(int npcid) { // assumption: there's at most one of the same NPC in a map.
List<MapleMapObject> npcs = getMapObjectsInRange(new Point(0, 0), Double.POSITIVE_INFINITY, Arrays.asList(MapleMapObjectType.NPC));
chrRLock.lock();
objectWLock.lock();
try {
@@ -2106,19 +2106,6 @@ public class MapleMap {
c.announce(reactor.makeSpawnData());
}
});
}
private void respawnReactor(final MapleReactor reactor) {
reactor.lockReactor();
try {
reactor.resetReactorActions(0);
reactor.setAlive(true);
} finally {
reactor.unlockReactor();
}
spawnReactor(reactor);
}
public void spawnDoor(final MapleDoorObject door) {
@@ -2587,6 +2574,7 @@ public class MapleMap {
break;
}
}
chr.commitExcludedItems(); // thanks OishiiKawaiiDesu for noticing pet item ignore registry erasing upon changing maps
if (chr.getMonsterCarnival() != null) {
chr.getClient().announce(MaplePacketCreator.getClock(chr.getMonsterCarnival().getTimeLeftSeconds()));
@@ -3555,6 +3543,7 @@ public class MapleMap {
reactor.lockReactor();
try {
reactor.resetReactorActions(0);
reactor.setAlive(true);
broadcastMessage(MaplePacketCreator.triggerReactor(reactor, 0));
} finally {
reactor.unlockReactor();
+2 -2
View File
@@ -278,10 +278,10 @@ public class MapleMapFactory {
MapleData mcData = mapData.getChildByPath("monsterCarnival");
if (mcData != null) {
map.setDeathCP(MapleDataTool.getIntConvert("deathCP", mcData, 0));
map.setMaxMobs(MapleDataTool.getIntConvert("mobGenMax", mcData, 0));
map.setMaxMobs(MapleDataTool.getIntConvert("mobGenMax", mcData, Integer.MAX_VALUE)); // thanks Atoot for noticing CPQ1 bf. 3 & 4 not accepting spawns due to undefined limits
map.setTimeDefault(MapleDataTool.getIntConvert("timeDefault", mcData, 0));
map.setTimeExpand(MapleDataTool.getIntConvert("timeExpand", mcData, 0));
map.setMaxReactors(MapleDataTool.getIntConvert("guardianGenMax", mcData, 0));
map.setMaxReactors(MapleDataTool.getIntConvert("guardianGenMax", mcData, Integer.MAX_VALUE));
MapleData guardianGenData = mcData.getChildByPath("guardianGenPos");
for (MapleData node : guardianGenData.getChildren()) {
GuardianSpawnPoint pt = new GuardianSpawnPoint(new Point(MapleDataTool.getIntConvert("x", node), MapleDataTool.getIntConvert("y", node)));
+69 -1
View File
@@ -57,6 +57,7 @@ public class MapleReactor extends AbstractMapleMapObject {
private boolean shouldCollect;
private boolean attackHit;
private ScheduledFuture<?> timeoutTask = null;
private Runnable delayedRespawnRun = null;
private GuardianSpawnPoint guardian = null;
private byte facingDirection = 0;
private Lock reactorLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.REACTOR, true);
@@ -165,7 +166,9 @@ public class MapleReactor extends AbstractMapleMapObject {
@Override
public void sendSpawnData(MapleClient client) {
client.announce(makeSpawnData());
if (this.isAlive()) {
client.announce(makeSpawnData());
}
}
public final byte[] makeSpawnData() {
@@ -318,6 +321,71 @@ public class MapleReactor extends AbstractMapleMapObject {
e.printStackTrace();
}
}
public boolean destroy() {
if (reactorLock.tryLock()) {
try {
boolean alive = this.isAlive();
if (alive) {
this.setAlive(false);
this.cancelReactorTimeout();
if (this.getDelay() > 0) {
this.delayedRespawn();
}
} else if (this.inDelayedRespawn()) {
return false;
} else {
return true; // reactor neither alive nor in delayed respawn, remove map object allowed
}
} finally {
reactorLock.unlock();
}
}
map.broadcastMessage(MaplePacketCreator.destroyReactor(this));
return false;
}
private void respawn() {
this.lockReactor();
try {
this.resetReactorActions(0);
this.setAlive(true);
} finally {
this.unlockReactor();
}
map.broadcastMessage(this.makeSpawnData());
}
public void delayedRespawn() {
Runnable r = new Runnable() {
@Override
public void run() {
delayedRespawnRun = null;
respawn();
}
};
delayedRespawnRun = r;
map.getChannelServer().registerOverallAction(map.getId(), r, this.getDelay());
}
public boolean forceDelayedRespawn() {
Runnable r = delayedRespawnRun;
if (r != null) {
map.getChannelServer().forceRunOverallAction(map.getId(), r);
return true;
} else {
return false;
}
}
public boolean inDelayedRespawn() {
return delayedRespawnRun != null;
}
public Rectangle getArea() {
return new Rectangle(getPosition().x + stats.getTL().x, getPosition().y + stats.getTL().y, stats.getBR().x - stats.getTL().x, stats.getBR().y - stats.getTL().y);