Reactor Loot + Obstacles damage mob + Static calls from scripts

Revised starting AP, now working out with flags. To supply the 9AP shortage of 4/4/4/4, two options: one giving out 9 AP from the start, other giving 4/5 AP when changing jobs (1st, 2nd). This change would also work with the autoassign for beginners flag.
Refactored several quest scripts, that would be glitching the player when doing quest start/complete and disposing under the same script status.
Cleared some cases with the quest reward system where it would call out a "full inventory" even though new inventory slots could get discovered when doing the quest loot transaction.
Fixed an issue with player stores being deployed overlapping in a few scenarios.
Fixed reduced EXP gain from kills when triggering skill Mortal Blow.
Added "open Duey" functionality when clicking "O" in the incoming package notification.
Fixed packages without messages (a quirk from quick delivery) not accounting visually as a "quick" one.
Fixed certain mounts (non-item skill mounts, such as Yeti or Spaceship) not showing up properly to other players when changing maps.
Added handler for mob damage by environment objects (OrbisPQ jail storage area).
Added a placeholder on mob's stolen items to prevent more steals to be placed as soon as the Steal mechanism is triggered.
Patched boss logs not removing recent entries from the DB tables (the reset method is actually supposed to clear every entry).
Revised a possible memory leak scenario happening due to an exception thrown midway monster kill method.
Improved reactor drops, now placing loots visible for the acting player centered (similar as to how mob loots work).
Refactored several issues in scripts, related to accessing static Java methods through an object, that would start appearing after transitioning to Java 8.
This commit is contained in:
ronancpl
2019-08-14 21:14:15 -03:00
parent 2c16a4d908
commit f958624f6a
233 changed files with 2368 additions and 888 deletions
+5 -5
View File
@@ -157,7 +157,7 @@ public class CashShop {
private static final Map<Integer, CashItem> items = new HashMap<>();
private static final Map<Integer, List<Integer>> packages = new HashMap<>();
private static final List<SpecialCashItem> specialcashitems = new ArrayList<>();
private static final List<Integer> randomitemids = new ArrayList<>();
private static final List<Integer> randomitemsns = new ArrayList<>();
static {
MapleDataProvider etc = MapleDataProviderFactory.getDataProvider(new File("wz/Etc.wz"));
@@ -184,7 +184,7 @@ public class CashShop {
for(Entry<Integer, CashItem> e : items.entrySet()) {
if(e.getValue().isOnSale()) {
randomitemids.add(e.getKey());
randomitemsns.add(e.getKey());
}
}
@@ -212,10 +212,10 @@ public class CashShop {
}
public static CashItem getRandomCashItem() {
if(randomitemids.isEmpty()) return null;
if(randomitemsns.isEmpty()) return null;
int rnd = (int)(Math.random() * randomitemids.size());
return items.get(randomitemids.get(rnd));
int rnd = (int)(Math.random() * randomitemsns.size());
return items.get(randomitemsns.get(rnd));
}
public static CashItem getItem(int sn) {
+8 -6
View File
@@ -29,7 +29,7 @@ public class DueyPackage {
private String sender = null;
private Item item = null;
private int mesos = 0;
private String message = "";
private String message = null;
private Calendar timestamp;
private int packageId = 0;
@@ -96,13 +96,15 @@ public class DueyPackage {
}
}
public void setSentTime(Timestamp ts) {
public void setSentTime(Timestamp ts, boolean quick) {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(ts.getTime());
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
if (quick) {
if (System.currentTimeMillis() - ts.getTime() < 24 * 60 * 60 * 1000) { // thanks inhyuk for noticing quick delivery packages unavailable to retrieve from the get-go
cal.add(Calendar.DATE, -1);
}
}
this.timestamp = cal;
}
+1
View File
@@ -25,6 +25,7 @@ import java.awt.Point;
import client.MapleClient;
public interface MaplePortal {
public final int TELEPORT_PORTAL = 1;
public final int MAP_PORTAL = 2;
public final int DOOR_PORTAL = 6;
public static boolean OPEN = true;
+6 -21
View File
@@ -1288,6 +1288,7 @@ public class MapleStatEffect {
if (mount != null) {
ridingMountId = mount.getItemId();
}
if (sourceid == Corsair.BATTLE_SHIP) {
ridingMountId = 1932000;
} else if (sourceid == Beginner.SPACESHIP || sourceid == Noblesse.SPACESHIP) {
@@ -1300,28 +1301,12 @@ public class MapleStatEffect {
ridingMountId = 1932005;
} else if (sourceid == Beginner.BALROG_MOUNT || sourceid == Noblesse.BALROG_MOUNT || sourceid == Legend.BALROG_MOUNT) {
ridingMountId = 1932010;
} else {
if (applyto.getMount() == null) {
applyto.mount(ridingMountId, sourceid);
}
applyto.getClient().getWorldServer().registerMountHunger(applyto);
}
if (sourceid == Corsair.BATTLE_SHIP) {
givemount = new MapleMount(applyto, 1932000, sourceid);
} else if (sourceid == Beginner.SPACESHIP || sourceid == Noblesse.SPACESHIP) {
givemount = new MapleMount(applyto, 1932000 + applyto.getSkillLevel(sourceid), sourceid);
} else if (sourceid == Beginner.YETI_MOUNT1 || sourceid == Noblesse.YETI_MOUNT1 || sourceid == Legend.YETI_MOUNT1) {
givemount = new MapleMount(applyto, 1932003, sourceid);
} else if (sourceid == Beginner.YETI_MOUNT2 || sourceid == Noblesse.YETI_MOUNT2 || sourceid == Legend.YETI_MOUNT2) {
givemount = new MapleMount(applyto, 1932004, sourceid);
} else if (sourceid == Beginner.WITCH_BROOMSTICK || sourceid == Noblesse.WITCH_BROOMSTICK || sourceid == Legend.WITCH_BROOMSTICK) {
givemount = new MapleMount(applyto, 1932005, sourceid);
} else if (sourceid == Beginner.BALROG_MOUNT || sourceid == Noblesse.BALROG_MOUNT || sourceid == Legend.BALROG_MOUNT) {
givemount = new MapleMount(applyto, 1932010, sourceid);
} else {
givemount = applyto.getMount();
}
// thanks inhyuk for noticing some skill mounts not acting properly for other players when changing maps
givemount = applyto.mount(ridingMountId, sourceid);
applyto.getClient().getWorldServer().registerMountHunger(applyto);
localDuration = sourceid;
localsourceid = ridingMountId;
localstatups = Collections.singletonList(new Pair<>(MapleBuffStat.MONSTER_RIDING, 0));
@@ -65,12 +65,9 @@ public class MapleExpeditionBossLog {
private static List<Pair<Timestamp, BossLogEntry>> getBossLogResetTimestamps(Calendar timeNow, boolean week) {
List<Pair<Timestamp, BossLogEntry>> resetTimestamps = new LinkedList<>();
Timestamp ts = new Timestamp(timeNow.getTime().getTime()); // reset all table entries actually, thanks Conrad
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));
}
}
+1 -1
View File
@@ -97,7 +97,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
private Set<Integer> usedAttacks = new HashSet<>();
private Set<Integer> calledMobOids = null;
private WeakReference<MapleMonster> callerMob = new WeakReference<>(null);
private List<Integer> stolenItems = new ArrayList<>();
private List<Integer> stolenItems = new ArrayList<>(5);
private int team;
private int parentMobOid = 0;
private final HashMap<Integer, AtomicLong> takenDamage = new HashMap<>();
@@ -152,7 +152,7 @@ public class MapleMonsterInformationProvider {
int rnd = Randomizer.rand(mde.Minimum, mde.Maximum);
for (int i = 0; i < rnd - 1; i++) {
extra.add(mde); // this passes copies of the equips' MDE with min/max quantity > 1, but idc it'll be unused anyways
extra.add(mde); // this passes copies of the equips' MDE with min/max quantity > 1, but idc on equips they are unused anyways
}
}
}
+75 -62
View File
@@ -137,6 +137,7 @@ public class MapleMap {
private int timeLimit;
private long mapTimer;
private int decHP = 0;
private float recovery = 1.0f;
private int protectItem = 0;
private boolean town;
private MapleOxQuiz ox;
@@ -1408,81 +1409,85 @@ public class MapleMap {
}
} else {
if (removeKilledMonsterObject(monster)) {
if (monster.getStats().getLevel() >= chr.getLevel() + 30 && !chr.isGM()) {
AutobanFactory.GENERAL.alert(chr, " for killing a " + monster.getName() + " which is over 30 levels higher.");
}
/*if (chr.getQuest(MapleQuest.getInstance(29400)).getStatus().equals(MapleQuestStatus.Status.STARTED)) {
if (chr.getLevel() >= 120 && monster.getStats().getLevel() >= 120) {
//FIX MEDAL SHET
} else if (monster.getStats().getLevel() >= chr.getLevel()) {
}
}*/
if (monster.getCP() > 0 && chr.getMap().isCPQMap()) {
chr.gainCP(monster.getCP());
}
int buff = monster.getBuffToGive();
if (buff > -1) {
MapleItemInformationProvider mii = MapleItemInformationProvider.getInstance();
for (MapleMapObject mmo : this.getPlayers()) {
MapleCharacter character = (MapleCharacter) mmo;
if (character.isAlive()) {
MapleStatEffect statEffect = mii.getItemEffect(buff);
character.getClient().announce(MaplePacketCreator.showOwnBuffEffect(buff, 1));
broadcastMessage(character, MaplePacketCreator.showBuffeffect(character.getId(), buff, 1), false);
statEffect.applyTo(character);
}
try {
if (monster.getStats().getLevel() >= chr.getLevel() + 30 && !chr.isGM()) {
AutobanFactory.GENERAL.alert(chr, " for killing a " + monster.getName() + " which is over 30 levels higher.");
}
}
if (monster.getId() >= 8800003 && monster.getId() <= 8800010) {
boolean makeZakReal = true;
Collection<MapleMapObject> objects = getMapObjects();
for (MapleMapObject object : objects) {
MapleMonster mons = getMonsterByOid(object.getObjectId());
if (mons != null) {
if (mons.getId() >= 8800003 && mons.getId() <= 8800010) {
makeZakReal = false;
break;
/*if (chr.getQuest(MapleQuest.getInstance(29400)).getStatus().equals(MapleQuestStatus.Status.STARTED)) {
if (chr.getLevel() >= 120 && monster.getStats().getLevel() >= 120) {
//FIX MEDAL SHET
} else if (monster.getStats().getLevel() >= chr.getLevel()) {
}
}*/
if (monster.getCP() > 0 && chr.getMap().isCPQMap()) {
chr.gainCP(monster.getCP());
}
int buff = monster.getBuffToGive();
if (buff > -1) {
MapleItemInformationProvider mii = MapleItemInformationProvider.getInstance();
for (MapleMapObject mmo : this.getPlayers()) {
MapleCharacter character = (MapleCharacter) mmo;
if (character.isAlive()) {
MapleStatEffect statEffect = mii.getItemEffect(buff);
character.getClient().announce(MaplePacketCreator.showOwnBuffEffect(buff, 1));
broadcastMessage(character, MaplePacketCreator.showBuffeffect(character.getId(), buff, 1), false);
statEffect.applyTo(character);
}
}
}
if (makeZakReal) {
MapleMap map = chr.getMap();
if (monster.getId() >= 8800003 && monster.getId() <= 8800010) {
boolean makeZakReal = true;
Collection<MapleMapObject> objects = getMapObjects();
for (MapleMapObject object : objects) {
MapleMonster mons = map.getMonsterByOid(object.getObjectId());
MapleMonster mons = getMonsterByOid(object.getObjectId());
if (mons != null) {
if (mons.getId() == 8800000) {
makeMonsterReal(mons);
mons.aggroUpdateController();
if (mons.getId() >= 8800003 && mons.getId() <= 8800010) {
makeZakReal = false;
break;
}
}
}
}
}
if (makeZakReal) {
MapleMap map = chr.getMap();
MapleCharacter dropOwner = monster.killBy(chr);
if (withDrops && !monster.dropsDisabled()) {
if (dropOwner == null) {
dropOwner = chr;
}
dropFromMonster(dropOwner, monster, false);
}
if (monster.hasBossHPBar()) {
for(MapleCharacter mc : this.getAllPlayers()) {
if(mc.getTargetHpBarHash() == monster.hashCode()) {
mc.resetPlayerAggro();
for (MapleMapObject object : objects) {
MapleMonster mons = map.getMonsterByOid(object.getObjectId());
if (mons != null) {
if (mons.getId() == 8800000) {
makeMonsterReal(mons);
mons.aggroUpdateController();
break;
}
}
}
}
}
}
monster.dispatchMonsterKilled(true);
broadcastMessage(MaplePacketCreator.killMonster(monster.getObjectId(), animation), monster.getPosition());
MapleCharacter dropOwner = monster.killBy(chr);
if (withDrops && !monster.dropsDisabled()) {
if (dropOwner == null) {
dropOwner = chr;
}
dropFromMonster(dropOwner, monster, false);
}
if (monster.hasBossHPBar()) {
for(MapleCharacter mc : this.getAllPlayers()) {
if(mc.getTargetHpBarHash() == monster.hashCode()) {
mc.resetPlayerAggro();
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally { // thanks resinate for pointing out a memory leak possibly from an exception thrown
monster.dispatchMonsterKilled(true);
broadcastMessage(MaplePacketCreator.killMonster(monster.getObjectId(), animation), monster.getPosition());
}
}
}
}
@@ -2707,12 +2712,12 @@ public class MapleMap {
return portal != null ? portal : getPortal(0);
}
public MaplePortal findClosestWarpPortal(Point from) {
public MaplePortal findClosestTeleportPortal(Point from) {
MaplePortal closest = null;
double shortestDistance = Double.POSITIVE_INFINITY;
for (MaplePortal portal : portals.values()) {
double distance = portal.getPosition().distanceSq(from);
if (portal.getType() == MaplePortal.MAP_PORTAL && distance < shortestDistance && portal.getTargetMapId() == 999999999) {
if (portal.getType() == MaplePortal.TELEPORT_PORTAL && distance < shortestDistance && portal.getTargetMapId() != 999999999) {
closest = portal;
shortestDistance = distance;
}
@@ -3777,6 +3782,14 @@ public class MapleMap {
public void setHPDecProtect(int delta) {
this.protectItem = delta;
}
public float getRecovery() {
return recovery;
}
public void setRecovery(float recRate) {
recovery = recRate;
}
private int hasBoat() {
return !boat ? 0 : (docked ? 1 : 2);
+3 -11
View File
@@ -31,7 +31,6 @@ import java.sql.SQLException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import provider.MapleData;
import provider.MapleDataProvider;
import provider.MapleDataProviderFactory;
@@ -49,8 +48,6 @@ import tools.StringUtil;
public class MapleMapFactory {
private static Map<Integer, Float> mapRecoveryRateCache = new HashMap<>();
private static MapleData nameData;
private static MapleDataProvider mapSource;
@@ -336,11 +333,10 @@ public class MapleMapFactory {
map.setTimeLimit(MapleDataTool.getIntConvert("timeLimit", infoData, -1));
map.setFieldType(MapleDataTool.getIntConvert("fieldType", infoData, 0));
map.setMobCapacity(MapleDataTool.getIntConvert("fixedMobCapacity", infoData, 500));//Is there a map that contains more than 500 mobs?
MapleData recData = infoData.getChildByPath("recovery");
if (recData != null) {
float recoveryRate = MapleDataTool.getFloat(recData);
mapRecoveryRateCache.put(mapid, recoveryRate);
map.setRecovery(MapleDataTool.getFloat(recData));
}
HashMap<Integer, Integer> backTypes = new HashMap<>();
@@ -438,9 +434,5 @@ public class MapleMapFactory {
builder.append("/").append(mapid);
return builder.toString();
}
public static float getMapRecoveryRate(int mapid) {
Float recRate = mapRecoveryRateCache.get(mapid);
return recRate != null ? recRate : 1.0f;
}
}
-3
View File
@@ -139,7 +139,4 @@ public class MapleMapManager {
this.event = null;
}
public static float getMapRecoveryRate(int mapid) {
return MapleMapFactory.getMapRecoveryRate(mapid);
}
}
+2 -1
View File
@@ -28,6 +28,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import client.MapleCharacter;
import client.MapleCharacter.DelayedQuestUpdate;
import client.MapleQuestStatus;
import client.MapleQuestStatus.Status;
import constants.ServerConstants;
@@ -337,7 +338,7 @@ public class MapleQuest {
if(pid >= 8200000 && pid <= 8200012) {
String pr = StringUtil.getLeftPaddedStr(Integer.toString(setProg), '0', 3);
newStatus.setProgress(pid, pr);
c.announce(MaplePacketCreator.updateQuest(newStatus, false));
c.announceUpdateQuest(DelayedQuestUpdate.UPDATE, newStatus, false);
}
}
}
+29 -6
View File
@@ -109,6 +109,7 @@ public class ItemAction extends MapleQuestAction {
if (!canGetItem(iEntry, chr)) {
continue;
}
if(iEntry.getProp() != null) {
if(iEntry.getProp() == -1) {
if(extSelection != extNum++)
@@ -181,11 +182,11 @@ public class ItemAction extends MapleQuestAction {
}
} else {
if(item.getCount() > 0) {
// Make sure they can hold the item.
Item toItem = new Item(item.getId(), (short) 0, (short) item.getCount());
gainList.add(new Pair<>(toItem, type));
} else {
// Make sure they can hold the item.
Item toItem = new Item(item.getId(), (short) 0, (short) item.getCount());
gainList.add(new Pair<>(toItem, type));
if(item.getCount() < 0) {
// Make sure they actually have the item.
int quantity = item.getCount() * -1;
@@ -229,12 +230,34 @@ public class ItemAction extends MapleQuestAction {
gainList.add(selected);
}
if (!MapleInventory.checkSpots(chr, gainList, allSlotUsed, false)) {
if (!canHold(chr, gainList)) {
chr.dropMessage(1, "Please check if you have enough space in your inventory.");
return false;
}
return true;
}
private boolean canHold(MapleCharacter chr, List<Pair<Item, MapleInventoryType>> gainList) {
List<Integer> toAddItemids = new LinkedList<>();
List<Integer> toAddQuantity = new LinkedList<>();
List<Integer> toRemoveItemids = new LinkedList<>();
List<Integer> toRemoveQuantity = new LinkedList<>();
for (Pair<Item, MapleInventoryType> item : gainList) {
Item it = item.getLeft();
if (it.getQuantity() > 0) {
toAddItemids.add(it.getItemId());
toAddQuantity.add((int) it.getQuantity());
} else {
toRemoveItemids.add(it.getItemId());
toRemoveQuantity.add(-1 * ((int) it.getQuantity()));
}
}
// thanks onechord for noticing quests unnecessarily giving out "full inventory" from quests that also takes items from players
return chr.getClient().getAbstractPlayerInteraction().canHoldAllAfterRemoving(toAddItemids, toAddQuantity, toRemoveItemids, toRemoveQuantity);
}
private boolean canGetItem(ItemData item, MapleCharacter chr) {
if (item.getGender() != 2 && item.getGender() != chr.getGender()) {