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:
@@ -1340,7 +1340,7 @@ public class MapleStatEffect {
|
||||
if (localstatups.size() > 0) {
|
||||
byte[] buff = null;
|
||||
byte[] mbuff = null;
|
||||
if (getSummonMovementType() == null && this.isActive(applyto)) {
|
||||
if (this.isActive(applyto)) {
|
||||
buff = MaplePacketCreator.giveBuff((skill ? sourceid : -sourceid), localDuration, localstatups);
|
||||
}
|
||||
if (isDash()) {
|
||||
@@ -1390,11 +1390,10 @@ public class MapleStatEffect {
|
||||
}
|
||||
|
||||
if (buff != null) {
|
||||
if (!hasNoIcon()) { //Thanks flav for such a simple release! :)
|
||||
applyto.announce(buff);
|
||||
} else {
|
||||
System.out.println("<Error> NO buff icon for id " + sourceid);
|
||||
}
|
||||
//Thanks flav for such a simple release! :)
|
||||
//Thanks Conrad, Atoot for noticing summons not using buff icon
|
||||
|
||||
applyto.announce(buff);
|
||||
}
|
||||
|
||||
long starttime = Server.getInstance().getCurrentTime();
|
||||
@@ -1820,16 +1819,6 @@ public class MapleStatEffect {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean hasNoIcon() {
|
||||
return (sourceid == 3111002 || sourceid == 3211002 || + // puppet, puppet
|
||||
sourceid == 3211005 || + // golden eagle
|
||||
sourceid == 2121005 || sourceid == 2221005 || + // elquines, ifrit
|
||||
sourceid == 2321003 || sourceid == 3121006 || + // bahamut, phoenix
|
||||
sourceid == 3221005 || sourceid == 3111005 || + // frostprey, silver hawk
|
||||
sourceid == 2311006 || sourceid == 5220002 || + // summon dragon, wrath of the octopi
|
||||
sourceid == 5211001 || sourceid == 5211002); // octopus, gaviota
|
||||
}
|
||||
|
||||
public boolean isSkill() {
|
||||
return skill;
|
||||
}
|
||||
|
||||
@@ -109,7 +109,6 @@ public class MapleExpedition {
|
||||
minSize = (minPlayers != 0) ? minPlayers : type.getMinSize();
|
||||
maxSize = (maxPlayers != 0) ? maxPlayers : type.getMaxSize();
|
||||
bossLogs = new CopyOnWriteArrayList<>();
|
||||
beginRegistration();
|
||||
}
|
||||
|
||||
public int getMinSize() {
|
||||
@@ -120,7 +119,7 @@ public class MapleExpedition {
|
||||
return maxSize;
|
||||
}
|
||||
|
||||
private void beginRegistration() {
|
||||
public void beginRegistration() {
|
||||
registering = true;
|
||||
leader.announce(MaplePacketCreator.getClock(type.getRegistrationTime() * 60));
|
||||
if (!silent) {
|
||||
|
||||
@@ -548,14 +548,21 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
int totalPartyLevel = 0;
|
||||
|
||||
// thanks G h o s t, Alfred, Vcoc, BHB for poiting out a bug in detecting party members after membership transactions in a party took place
|
||||
for (MapleCharacter member : partyParticipation.keySet().iterator().next().getPartyMembersOnSameMap()) {
|
||||
if (!leechInterval.inInterval(member.getLevel())) {
|
||||
underleveled.add(member);
|
||||
continue;
|
||||
if (!ServerConstants.USE_ENFORCE_MOB_LEVEL_RANGE) {
|
||||
for (MapleCharacter member : partyParticipation.keySet().iterator().next().getPartyMembersOnSameMap()) {
|
||||
if (!leechInterval.inInterval(member.getLevel())) {
|
||||
underleveled.add(member);
|
||||
continue;
|
||||
}
|
||||
|
||||
totalPartyLevel += member.getLevel();
|
||||
expMembers.add(member);
|
||||
}
|
||||
} else { // thanks Ari for noticing unused server flag after EXP system overhaul
|
||||
for (MapleCharacter member : partyParticipation.keySet().iterator().next().getPartyMembersOnSameMap()) {
|
||||
totalPartyLevel += member.getLevel();
|
||||
expMembers.add(member);
|
||||
}
|
||||
|
||||
totalPartyLevel += member.getLevel();
|
||||
expMembers.add(member);
|
||||
}
|
||||
|
||||
int membersSize = expMembers.size();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -94,7 +94,7 @@ public class MonsterCarnival {
|
||||
public void run() {
|
||||
timeUp();
|
||||
}
|
||||
}, (map.getTimeDefault() - 10) * 1000);
|
||||
}, map.getTimeDefault() * 1000); // thanks Atoot for noticing an irregular "event extended" issue here
|
||||
effectTimer = TimerManager.getInstance().schedule(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
Reference in New Issue
Block a user