Autopot & Steal patch + Friendly mob drops + Portal update fix

Adjusted pet autopot to use temporary variables instead of the current player's HP, MP. This seems to have solved a race condition issue where the pet would instantly use up all the pots of the assigned itemid the player had on the inventory.
Steal now uses the effective chance it is supposed to use.
Reworked Steal so that it determines which item to drop accordingly with the drop rates of each available item. It won't drop Quest nor Party Quest items.
Reworked friendly mob drops to act on the same way common mobs drops items.
Fixed issues with scripted portals introduced on the Portal Soundeffect update patch. There is expected to have no more syntax errors on the portal scripts.
Improved quality of the strings used on the Expedition scripts.
New command: reach. Warps the caller to the area where the targeted player is.
This commit is contained in:
ronancpl
2018-02-20 18:37:32 -03:00
parent 8f76e7be25
commit a4973b8254
45 changed files with 517 additions and 210 deletions

View File

@@ -1120,6 +1120,25 @@ public class Commands {
player.dropMessage("Unknown player.");
}
break;
case "reach":
if (sub.length < 2){
player.yellowMessage("Syntax: !reach <playername>");
break;
}
victim = c.getWorldServer().getPlayerStorage().getCharacterByName(sub[1]);
if(victim != null && victim.isLoggedin()) {
if (player.getClient().getChannel() != victim.getClient().getChannel()) {
player.dropMessage("Player '" + victim.getName() + "' is at channel " + victim.getClient().getChannel() + ".");
} else {
MapleMap map = victim.getMap();
player.changeMap(map, map.findClosestPortal(victim.getPosition()));
}
} else {
player.dropMessage("Unknown player.");
}
break;
case "gmshop":
MapleShopFactory.getInstance().getShop(1337).sendShop(c);

View File

@@ -295,21 +295,24 @@ public abstract class AbstractDealDamageHandler extends AbstractMaplePacketHandl
} else if (attack.skill == Bandit.STEAL) {
Skill steal = SkillFactory.getSkill(Bandit.STEAL);
if (monster.getStolen().size() < 1) { // One steal per mob <3
if (Math.random() < 0.3 && steal.getEffect(player.getSkillLevel(steal)).makeChanceResult()) { //Else it drops too many cool stuff :(
List<MonsterDropEntry> toSteals = MapleMonsterInformationProvider.getInstance().retrieveDrop(monster.getId());
Collections.shuffle(toSteals);
int toSteal = toSteals.get(rand(0, (toSteals.size() - 1))).itemId;
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
Item item;
if (ItemConstants.getInventoryType(toSteal).equals(MapleInventoryType.EQUIP)) {
item = ii.randomizeStats((Equip) ii.getEquipById(toSteal));
} else {
item = new Item(toSteal, (byte) 0, (short) 1, -1);
if (steal.getEffect(player.getSkillLevel(steal)).makeChanceResult()) {
MapleMonsterInformationProvider mi = MapleMonsterInformationProvider.getInstance();
List<Integer> dropPool = mi.retrieveDropPool(monster.getId());
if(!dropPool.isEmpty()) {
Integer rndPool = (int) Math.floor(Math.random() * dropPool.get(dropPool.size() - 1));
int i = 0;
while(rndPool >= dropPool.get(i)) i++;
List<MonsterDropEntry> toSteal = new ArrayList<>();
toSteal.add(mi.retrieveDrop(monster.getId()).get(i));
player.getMap().dropItemsFromMonster(toSteal, player, monster);
monster.addStolen(toSteal.get(0).itemId);
}
player.getMap().spawnItemDrop(monster, player, item, monster.getPosition(), false, false);
monster.addStolen(toSteal);
}
}
}
} else if (attack.skill == FPArchMage.FIRE_DEMON) {
monster.setTempEffectiveness(Element.ICE, ElementalEffectiveness.WEAK, SkillFactory.getSkill(FPArchMage.FIRE_DEMON).getEffect(player.getSkillLevel(SkillFactory.getSkill(FPArchMage.FIRE_DEMON))).getDuration() * 1000);
} else if (attack.skill == ILArchMage.ICE_DEMON) {

View File

@@ -35,6 +35,7 @@ import client.MapleClient;
*/
public final class MobDamageMobFriendlyHandler extends AbstractMaplePacketHandler {
@Override
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
int attacker = slea.readInt();
slea.readInt();
@@ -66,12 +67,12 @@ public final class MobDamageMobFriendlyHandler extends AbstractMaplePacketHandle
}
c.getPlayer().getMap().killFriendlies(monster);
} else {
if (monster.getId() == 9300061) {
MapleMap map = c.getPlayer().getEventInstance().getMapInstance(monster.getMap().getId());
map.addBunnyHit();
}
}
if (monster.getId() == 9300061) {
MapleMap map = c.getPlayer().getEventInstance().getMapInstance(monster.getMap().getId());
map.addBunnyHit();
}
c.getPlayer().getMap().broadcastMessage(MaplePacketCreator.MobDamageMobFriendly(monster, damage), monster.getPosition());
c.announce(MaplePacketCreator.enableActions());

View File

@@ -49,6 +49,10 @@ public final class PetAutoPotHandler extends AbstractMaplePacketHandler {
boolean hasMpGain;
short maxHp;
short maxMp;
short incHp;
short incMp;
int curHp;
int curMp;
@Override
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
@@ -91,14 +95,27 @@ public final class PetAutoPotHandler extends AbstractMaplePacketHandler {
maxHp = maxHpMp.left;
maxMp = maxHpMp.right;
incHp = stat.getHp();
if(incHp <= 0 && hasHpGain) incHp = (short)((maxHp * stat.getHpRate()) / 100.0);
incMp = stat.getMp();
if(incMp <= 0 && hasMpGain) incMp = (short)((maxMp * stat.getMpRate()) / 100.0);
curHp = chr.getHp();
curMp = chr.getMp();
//System.out.println("\n-------------------\n");
while(true) {
do {
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.USE, slot, (short) 1, false);
stat.applyTo(chr);
curHp += incHp;
curMp += incMp;
//System.out.println();
//System.out.println("hp: " + hasHpGain + " player hp " + chr.getHp() + " maxhp " + maxHp);
//System.out.println("mp: " + hasMpGain + " player mp " + chr.getMp() + " maxmp " + maxMp);
//System.out.println("hp: " + hasHpGain + " player hp " + curHp + " maxhp " + maxHp);
//System.out.println("mp: " + hasMpGain + " player mp " + curMp + " maxmp " + maxMp);
//System.out.println("redo? " + (shouldReusePot(chr) && toUse.getQuantity() > 0));
} while(shouldReusePot(chr) && toUse.getQuantity() > 0);
@@ -154,6 +171,6 @@ public final class PetAutoPotHandler extends AbstractMaplePacketHandler {
}
private boolean shouldReusePot(MapleCharacter chr) {
return (hasHpGain && chr.getHp() < ServerConstants.PET_AUTOHP_RATIO * maxHp) || (hasMpGain && chr.getMp() < ServerConstants.PET_AUTOMP_RATIO * maxMp);
return (hasHpGain && curHp < ServerConstants.PET_AUTOHP_RATIO * maxHp) || (hasMpGain && curMp < ServerConstants.PET_AUTOMP_RATIO * maxMp);
}
}

View File

@@ -111,6 +111,7 @@ public class MapleItemInformationProvider {
protected List<Pair<Integer, String>> itemNameCache = new ArrayList<>();
protected Map<Integer, Boolean> consumeOnPickupCache = new HashMap<>();
protected Map<Integer, Boolean> isQuestItemCache = new HashMap<>();
protected Map<Integer, Boolean> isPartyQuestItemCache = new HashMap<>();
protected Map<Integer, String> equipmentSlotCache = new HashMap<>();
protected Map<Integer, Boolean> noCancelMouseCache = new HashMap<>();
protected Map<Integer, Integer> mobCrystalMakerCache = new HashMap<>();
@@ -129,6 +130,9 @@ public class MapleItemInformationProvider {
etcStringData = stringData.getData("Etc.img");
insStringData = stringData.getData("Ins.img");
petStringData = stringData.getData("Pet.img");
isQuestItemCache.put(0, false);
isPartyQuestItemCache.put(0, false);
}
public static MapleItemInformationProvider getInstance() {
@@ -1231,6 +1235,16 @@ public class MapleItemInformationProvider {
isQuestItemCache.put(itemId, questItem);
return questItem;
}
public boolean isPartyQuestItem(int itemId) {
if (isPartyQuestItemCache.containsKey(itemId)) {
return isPartyQuestItemCache.get(itemId);
}
MapleData data = getItemData(itemId);
boolean partyquestItem = (data != null && MapleDataTool.getIntConvert("info/pquest", data, 0) == 1);
isPartyQuestItemCache.put(itemId, partyquestItem);
return partyquestItem;
}
public int getQuestIdFromItem(int itemId) {
MapleData data = getItemData(itemId);

View File

@@ -96,7 +96,8 @@ public class MapleExpedition {
private void beginRegistration() {
registering = true;
leader.announce(MaplePacketCreator.getClock(type.getRegistrationTime() * 60));
startMap.broadcastMessage(MaplePacketCreator.serverNotice(6, "[Expedition] " + leader.getName() + " has been declared the expedition captain. Please register for the expedition."));
startMap.broadcastMessage(leader, MaplePacketCreator.serverNotice(6, "[Expedition] " + leader.getName() + " has been declared the expedition captain. Please register for the expedition."), false);
leader.announce(MaplePacketCreator.serverNotice(6, "[Expedition] You have become the expedition captain. Gather enough people for your team then talk to the NPC to start."));
scheduleRegistrationEnd();
}

View File

@@ -34,6 +34,7 @@ import provider.MapleData;
import provider.MapleDataProvider;
import provider.MapleDataProviderFactory;
import provider.MapleDataTool;
import server.MapleItemInformationProvider;
import tools.DatabaseConnection;
import tools.Pair;
@@ -43,6 +44,8 @@ public class MapleMonsterInformationProvider {
private static final MapleMonsterInformationProvider instance = new MapleMonsterInformationProvider();
private final Map<Integer, List<MonsterDropEntry>> drops = new HashMap<>();
private final List<MonsterGlobalDropEntry> globaldrops = new ArrayList<>();
private final Map<Integer, List<Integer>> dropsChancePool = new HashMap<>(); // thanks to ronan
protected MapleMonsterInformationProvider() {
retrieveGlobal();
@@ -148,6 +151,31 @@ public class MapleMonsterInformationProvider {
drops.put(monsterId, ret);
return ret;
}
public final List<Integer> retrieveDropPool(final int monsterId) { // ignores Quest and Party Quest items
if (dropsChancePool.containsKey(monsterId)) {
return dropsChancePool.get(monsterId);
}
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
List<MonsterDropEntry> dropList = retrieveDrop(monsterId);
List<Integer> ret = new ArrayList<>();
int accProp = 0;
for(MonsterDropEntry mde : dropList) {
if(!ii.isQuestItem(mde.itemId) && !ii.isPartyQuestItem(mde.itemId)) {
accProp += mde.chance;
}
ret.add(accProp);
}
if(accProp == 0) ret.clear(); // don't accept mobs dropping no relevant items
dropsChancePool.put(monsterId, ret);
return ret;
}
public static ArrayList<Pair<Integer, String>> getMobsIDsFromName(String search)
{
@@ -206,6 +234,7 @@ public class MapleMonsterInformationProvider {
public final void clearDrops() {
drops.clear();
dropsChancePool.clear();
globaldrops.clear();
retrieveGlobal();
}

View File

@@ -583,7 +583,7 @@ public class MapleMap {
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
for (final MonsterDropEntry de : dropEntry) {
if (Randomizer.nextInt(999999) < de.chance * chRate) {
if (Randomizer.nextInt(999999) < (long) de.chance * chRate) {
if (droptype == 3) {
pos.x = (int) (mobpos + (d % 2 == 0 ? (40 * (d + 1) / 2) : -(40 * (d / 2))));
} else {
@@ -644,7 +644,7 @@ public class MapleMap {
return d;
}
private void dropFromMonster(final MapleCharacter chr, final MapleMonster mob) {
private void dropFromMonster(final MapleCharacter chr, final MapleMonster mob, final boolean useBaseRate) {
if (mob.dropsDisabled() || !dropsOn) {
return;
}
@@ -658,6 +658,8 @@ public class MapleMap {
if (stati != null) {
chRate *= (stati.getStati().get(MonsterStatus.SHOWDOWN).doubleValue() / 100.0 + 1.0);
}
if(useBaseRate) chRate = 1;
final MapleMonsterInformationProvider mi = MapleMonsterInformationProvider.getInstance();
@@ -676,6 +678,24 @@ public class MapleMap {
dropItemsFromMonsterOnMap(questEntry, pos, d, chRate, droptype, mobpos, chr, mob);
}
public void dropItemsFromMonster(List<MonsterDropEntry> list, final MapleCharacter chr, final MapleMonster mob) {
if (mob.dropsDisabled() || !dropsOn) {
return;
}
final byte droptype = (byte) (chr.getParty() != null ? 1 : 0);
final int mobpos = mob.getPosition().x;
int chRate = 1000000; // guaranteed item drop
byte d = 1;
Point pos = new Point(0, mob.getPosition().y);
dropItemsFromMonsterOnMap(list, pos, d, chRate, droptype, mobpos, chr, mob);
}
public void dropFromFriendlyMonster(final MapleCharacter chr, final MapleMonster mob) {
dropFromMonster(chr, mob, true);
}
public void dropFromReactor(final MapleCharacter chr, final MapleReactor reactor, Item drop, Point dropPos, short questid) {
spawnDrop(drop, this.calcDropPos(dropPos, reactor.getPosition()), reactor, chr, (byte)(chr.getParty() != null ? 1 : 0), questid);
}
@@ -1139,7 +1159,7 @@ public class MapleMap {
if (dropOwner == null) {
dropOwner = chr;
}
dropFromMonster(dropOwner, monster);
dropFromMonster(dropOwner, monster, false);
}
if (monster.hasBossHPBar()) {
@@ -1551,16 +1571,21 @@ public class MapleMap {
}
}
private void monsterItemDrop(final MapleMonster m, final Item item, long delay) {
private void monsterItemDrop(final MapleMonster m, long delay) {
final ScheduledFuture<?> monsterItemDrop = TimerManager.getInstance().register(new Runnable() {
@Override
public void run() {
if (m.isAlive() && !MapleMap.this.getPlayers().isEmpty()) {
if (item.getItemId() == 4001101) {
List<MapleMapObject> chrList = MapleMap.this.getPlayers();
if (m.isAlive() && !chrList.isEmpty()) {
MapleCharacter chr = (MapleCharacter) chrList.get(0);
if (m.getId() == 9300061) {
MapleMap.this.riceCakes++;
MapleMap.this.broadcastMessage(MaplePacketCreator.serverNotice(6, "The Moon Bunny made rice cake number " + (MapleMap.this.riceCakes)));
}
spawnItemDrop(m, (MapleCharacter) getPlayers().get(0), item, m.getPosition(), false, false);
dropFromFriendlyMonster(chr, m);
}
}
}, delay, delay);
@@ -1643,11 +1668,11 @@ public class MapleMap {
if (monster.getDropPeriodTime() > 0) { //9300102 - Watchhog, 9300061 - Moon Bunny (HPQ), 9300093 - Tylus
if (monster.getId() == 9300102) {
monsterItemDrop(monster, new Item(4031507, (short) 0, (short) 1), monster.getDropPeriodTime());
monsterItemDrop(monster, monster.getDropPeriodTime());
} else if (monster.getId() == 9300061) {
monsterItemDrop(monster, new Item(4001101, (short) 0, (short) 1), monster.getDropPeriodTime() / 3);
monsterItemDrop(monster, monster.getDropPeriodTime() / 3);
} else if (monster.getId() == 9300093) {
monsterItemDrop(monster, new Item(4031495, (short) 0, (short) 1), monster.getDropPeriodTime());
monsterItemDrop(monster, monster.getDropPeriodTime());
} else {
FilePrinter.printError(FilePrinter.UNHANDLED_EVENT, "UNCODED TIMED MOB DETECTED: " + monster.getId() + "\r\n");
}
@@ -1947,7 +1972,7 @@ public class MapleMap {
for(final MapleMapItem drop : list) {
final Item item = drop.getItem();
if (reactItem == item.getItemId() && reactQty == item.getQuantity()) {
if (item != null && reactItem == item.getItemId() && reactQty == item.getQuantity()) {
if (reactArea.contains(drop.getPosition())) {
MapleClient owner = drop.getOwnerClient();
if(owner != null) {

View File

@@ -248,8 +248,10 @@ public class MapleMapFactory {
map.setMapName(MapleDataTool.getString("mapName", nameData.getChildByPath(getMapStringName(omapid)), ""));
map.setStreetName(MapleDataTool.getString("streetName", nameData.getChildByPath(getMapStringName(omapid)), ""));
} catch (Exception e) {
e.printStackTrace();
System.err.println("Not found mapid " + omapid);
if(omapid / 1000 != 1020) { // explorer job introducion scenes
e.printStackTrace();
System.err.println("Not found mapid " + omapid);
}
map.setMapName("");
map.setStreetName("");