Reactor drops & Looting & Mob HP overhaul + TreasurePQ
Modified coupon rates buff icon to not show up as expirable. Reactor drops now also drops quest items at the border of the dropped items. Added themed drop data for the Cake boss. Reworked the Balrog expedition. Added quest script for the Assassinate skill. Fixed looting system blocking the killer's party from retrieving a loot until the FFA timeout. Fixed a deadlock with the MapleMap class. Refactored damage/heal contabilization on mobs. Fixed issues with HT and status-based damage, providing weird issues with mob HP. New PQ: TreasurePQ, for level 140+.
This commit is contained in:
@@ -1476,7 +1476,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
|
||||
if (ob instanceof MapleMapItem) {
|
||||
MapleMapItem mapitem = (MapleMapItem) ob;
|
||||
if(System.currentTimeMillis() - mapitem.getDropTime() < 900) {
|
||||
if(System.currentTimeMillis() - mapitem.getDropTime() < 900 || !mapitem.canBePickedBy(this)) {
|
||||
client.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
@@ -5629,8 +5629,8 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
i = i.replace("rn", "Rn");
|
||||
i = i.replace("vv", "Vv");
|
||||
i = i.replace("VV", "Vv");
|
||||
|
||||
return i;
|
||||
|
||||
}
|
||||
|
||||
private static class MapleBuffStatValueHolder {
|
||||
@@ -7452,11 +7452,14 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
}
|
||||
announce(MaplePacketCreator.updateQuestInfo((short) quest.getQuest().getId(), quest.getNpc()));
|
||||
} else if (quest.getStatus().equals(MapleQuestStatus.Status.COMPLETED)) {
|
||||
quest_fame += 1;
|
||||
if(ServerConstants.FAME_GAIN_BY_QUEST > 0)
|
||||
fameGainByQuest();
|
||||
short questid = quest.getQuest().getId();
|
||||
if(questid != 3637) {
|
||||
quest_fame += 1;
|
||||
if(ServerConstants.FAME_GAIN_BY_QUEST > 0)
|
||||
fameGainByQuest();
|
||||
}
|
||||
|
||||
announce(MaplePacketCreator.completeQuest((short) quest.getQuest().getId(), quest.getCompletionTime()));
|
||||
announce(MaplePacketCreator.completeQuest(questid, quest.getCompletionTime()));
|
||||
} else if (quest.getStatus().equals(MapleQuestStatus.Status.NOT_STARTED)) {
|
||||
announce(MaplePacketCreator.updateQuest(quest, false));
|
||||
if (quest.getQuest().getInfoNumber() > 0) {
|
||||
|
||||
@@ -1844,8 +1844,9 @@ public class Commands {
|
||||
break;
|
||||
|
||||
case "killall":
|
||||
List<MapleMapObject> monsters = player.getMap().getMapObjectsInRange(player.getPosition(), Double.POSITIVE_INFINITY, Arrays.asList(MapleMapObjectType.MONSTER));
|
||||
MapleMap map = player.getMap();
|
||||
List<MapleMapObject> monsters = map.getMapObjectsInRange(player.getPosition(), Double.POSITIVE_INFINITY, Arrays.asList(MapleMapObjectType.MONSTER));
|
||||
|
||||
for (MapleMapObject monstermo : monsters) {
|
||||
monster = (MapleMonster) monstermo;
|
||||
if (!monster.getStats().isFriendly()) {
|
||||
@@ -2287,12 +2288,7 @@ public class Commands {
|
||||
case "itemvac":
|
||||
List<MapleMapObject> list = player.getMap().getMapObjectsInRange(player.getPosition(), Double.POSITIVE_INFINITY, Arrays.asList(MapleMapObjectType.ITEM));
|
||||
for (MapleMapObject item : list) {
|
||||
MapleMapItem mapItem = (MapleMapItem) item;
|
||||
int ownerId = mapItem.getOwner();
|
||||
|
||||
if(ownerId <= 0 || player.getId() == ownerId || player.isPartyMember(ownerId) || System.currentTimeMillis() - mapItem.getDropTime() >= 15 * 1000) {
|
||||
player.pickupItem(item);
|
||||
}
|
||||
player.pickupItem(item);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2352,7 +2348,7 @@ public class Commands {
|
||||
if(newHp < 0) newHp = Integer.MAX_VALUE;
|
||||
|
||||
monster.getStats().setHp(newHp);
|
||||
monster.setHp(newHp);
|
||||
monster.setStartingHp(newHp);
|
||||
}
|
||||
|
||||
player.getMap().spawnMonsterOnGroundBelow(monster, player.getPosition());
|
||||
|
||||
@@ -39,6 +39,7 @@ import constants.ServerConstants;
|
||||
* @author Ronan
|
||||
*/
|
||||
public final class PetLootHandler extends AbstractMaplePacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
MapleCharacter chr = c.getPlayer();
|
||||
if(System.currentTimeMillis() - chr.getPetLootCd() < ServerConstants.PET_LOOT_UPON_ATTACK) {
|
||||
|
||||
@@ -660,6 +660,7 @@ public class EventInstanceManager {
|
||||
|
||||
cancelSchedule();
|
||||
killCount.clear();
|
||||
mapIds.clear();
|
||||
|
||||
disposeExpedition();
|
||||
|
||||
|
||||
@@ -28,8 +28,7 @@ import client.inventory.Item;
|
||||
import client.inventory.MapleInventoryType;
|
||||
import constants.ItemConstants;
|
||||
import java.awt.Point;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.logging.Level;
|
||||
@@ -107,33 +106,19 @@ public class ReactorActionManager extends AbstractPlayerInteraction {
|
||||
public void dropItems(boolean delayed, int posX, int posY, boolean meso, int mesoChance, final int minMeso, final int maxMeso, int minItems) {
|
||||
if(c.getPlayer() == null) return;
|
||||
|
||||
List<ReactorDropEntry> chances = getDropChances();
|
||||
List<ReactorDropEntry> items = new LinkedList<>();
|
||||
int numItems = 0;
|
||||
if (meso && Math.random() < (1 / (double) mesoChance)) {
|
||||
items.add(new ReactorDropEntry(0, mesoChance, -1));
|
||||
}
|
||||
Iterator<ReactorDropEntry> iter = chances.iterator();
|
||||
while (iter.hasNext()) {
|
||||
ReactorDropEntry d = iter.next();
|
||||
if (Math.random() < (c.getPlayer().getDropRate() / (double) d.chance)) {
|
||||
numItems++;
|
||||
items.add(d);
|
||||
}
|
||||
}
|
||||
while (items.size() < minItems) {
|
||||
items.add(new ReactorDropEntry(0, mesoChance, -1));
|
||||
numItems++;
|
||||
}
|
||||
java.util.Collections.shuffle(items);
|
||||
List<ReactorDropEntry> items = generateDropList(getDropChances(), c.getPlayer().getDropRate(), meso, mesoChance, minItems);
|
||||
|
||||
if(items.size() % 2 == 0) posX -= 12;
|
||||
final Point dropPos = new Point(posX, posY);
|
||||
dropPos.x -= (12 * numItems);
|
||||
|
||||
if(!delayed) {
|
||||
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
||||
|
||||
byte p = 1;
|
||||
for (ReactorDropEntry d : items) {
|
||||
dropPos.x = (int) (posX + ((p % 2 == 0) ? (25 * ((p + 1) / 2)) : -(25 * (p / 2))));
|
||||
p++;
|
||||
|
||||
if (d.itemId == 0) {
|
||||
int range = maxMeso - minMeso;
|
||||
int displayDrop = (int) (Math.random() * range) + minMeso;
|
||||
@@ -148,9 +133,8 @@ public class ReactorActionManager extends AbstractPlayerInteraction {
|
||||
drop = ii.randomizeStats((Equip) ii.getEquipById(d.itemId));
|
||||
}
|
||||
|
||||
reactor.getMap().dropFromReactor(getPlayer(), reactor, drop, dropPos, (short)d.questid);
|
||||
reactor.getMap().dropFromReactor(getPlayer(), reactor, drop, dropPos, (short) d.questid);
|
||||
}
|
||||
dropPos.x += 25;
|
||||
}
|
||||
} else {
|
||||
final MapleCharacter chr = client.getPlayer();
|
||||
@@ -158,6 +142,8 @@ public class ReactorActionManager extends AbstractPlayerInteraction {
|
||||
final List<ReactorDropEntry> dropItems = items;
|
||||
final int worldMesoRate = client.getWorldServer().getMesoRate();
|
||||
|
||||
dropPos.x -= (12 * items.size());
|
||||
|
||||
sprayTask = TimerManager.getInstance().register(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -182,7 +168,7 @@ public class ReactorActionManager extends AbstractPlayerInteraction {
|
||||
drop = ii.randomizeStats((Equip) ii.getEquipById(d.itemId));
|
||||
}
|
||||
|
||||
r.getMap().dropFromReactor(getPlayer(), r, drop, dropPos, (short)d.questid);
|
||||
r.getMap().dropFromReactor(getPlayer(), r, drop, dropPos, (short) d.questid);
|
||||
}
|
||||
|
||||
dropPos.x += 25;
|
||||
@@ -194,6 +180,41 @@ public class ReactorActionManager extends AbstractPlayerInteraction {
|
||||
private List<ReactorDropEntry> getDropChances() {
|
||||
return ReactorScriptManager.getInstance().getDrops(reactor.getId());
|
||||
}
|
||||
|
||||
private static List<ReactorDropEntry> generateDropList(List<ReactorDropEntry> drops, int dropRate, boolean meso, int mesoChance, int minItems) {
|
||||
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
||||
|
||||
List<ReactorDropEntry> items = new ArrayList<>();
|
||||
List<ReactorDropEntry> questItems = new ArrayList<>();
|
||||
int numItems = 0;
|
||||
|
||||
if (meso && Math.random() < (1 / (double) mesoChance)) {
|
||||
items.add(new ReactorDropEntry(0, mesoChance, -1));
|
||||
}
|
||||
|
||||
for(ReactorDropEntry mde : drops) {
|
||||
if (Math.random() < (dropRate / (double) mde.chance)) {
|
||||
if(!ii.isQuestItem(mde.itemId)) {
|
||||
items.add(mde);
|
||||
} else {
|
||||
questItems.add(mde);
|
||||
}
|
||||
|
||||
numItems++;
|
||||
}
|
||||
}
|
||||
|
||||
while (numItems < minItems) {
|
||||
items.add(new ReactorDropEntry(0, mesoChance, -1));
|
||||
numItems++;
|
||||
}
|
||||
|
||||
java.util.Collections.shuffle(items);
|
||||
java.util.Collections.shuffle(questItems);
|
||||
|
||||
items.addAll(questItems);
|
||||
return items;
|
||||
}
|
||||
|
||||
public void spawnMonster(int id) {
|
||||
spawnMonster(id, 1, getPosition());
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
package server.events;
|
||||
import client.MapleCharacter;
|
||||
import java.util.*;
|
||||
import server.life.MapleLifeFactory;
|
||||
import java.awt.Point;
|
||||
import server.maps.MapleMap;
|
||||
import server.TimerManager;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author FateJiki
|
||||
* @Mapid 105100300
|
||||
*/
|
||||
public class BalrogPQ {
|
||||
public static final int[] EasyBalrogParts = {8830002, 8830003, 8830000};
|
||||
public static final int[] HardBalrogParts = {8830000, 8830001, 8830002};
|
||||
public static List<MapleCharacter> candidates = new ArrayList<>();
|
||||
public static boolean hasStarted = false;
|
||||
public static String partyLeader = "undefined";
|
||||
public static boolean balrogSpawned = false;
|
||||
public static long timeStamp = 0;
|
||||
public static byte channel = 1;
|
||||
|
||||
public static void addCandidate(MapleCharacter chr){
|
||||
synchronized(candidates){
|
||||
candidates.add(chr);
|
||||
}
|
||||
}
|
||||
|
||||
public static void warpAllCandidates(){
|
||||
synchronized(candidates){
|
||||
for(MapleCharacter c : candidates){
|
||||
c.changeMap(105100300);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isFull(MapleCharacter chr){
|
||||
return chr.getClient().getChannelServer().getMapFactory().getMap(105100300).getCharacters().size() > 0;
|
||||
}
|
||||
|
||||
public static void warpIn(MapleCharacter chr){
|
||||
if(hasStarted){
|
||||
chr.changeMap(105100300);
|
||||
}
|
||||
}
|
||||
|
||||
public static void scheduleChecks(MapleMap map){
|
||||
final MapleMap fmap = map;
|
||||
TimerManager tMan = TimerManager.getInstance();
|
||||
tMan.schedule(new Runnable(){
|
||||
@Override
|
||||
public void run(){
|
||||
for(MapleCharacter chrs : fmap.getCharacters()){
|
||||
chrs.changeMap(105100100);
|
||||
chrs.message("You did not defeat the balrog in time..");
|
||||
close();
|
||||
}
|
||||
}
|
||||
} , 60 * 60 * 1000);
|
||||
|
||||
tMan.schedule(new Runnable(){
|
||||
@Override
|
||||
public void run(){
|
||||
if(fmap.getCharacters().size() <= 3){
|
||||
if(fmap.getCharacters().size() > 0){
|
||||
for(MapleCharacter chrs : fmap.getCharacters()){
|
||||
chrs.message("[The Order]: What? You're down to that many mercenaries? I need to get you out of there.");
|
||||
chrs.changeMap(105100100);
|
||||
}
|
||||
}
|
||||
fmap.killAllMonsters();
|
||||
close();
|
||||
}
|
||||
}
|
||||
} , 60 * 1000);
|
||||
}
|
||||
|
||||
public static void open(MapleCharacter chr){
|
||||
channel = (byte)chr.getClient().getChannel();
|
||||
hasStarted = true;
|
||||
timeStamp = System.currentTimeMillis();
|
||||
scheduleChecks(chr.getClient().getChannelServer().getMapFactory().getMap(105100300));
|
||||
}
|
||||
|
||||
public static int getSecondsLeft(){ // assuming the thing lasts 60 minutes
|
||||
int hour = 60 * 60; // 3600 seconds = 1hr
|
||||
long elapsed = System.currentTimeMillis() - timeStamp;
|
||||
int secondsLeft = (int)(hour - (elapsed / 1000));
|
||||
return secondsLeft;
|
||||
}
|
||||
|
||||
public static void close(){
|
||||
hasStarted = false;
|
||||
balrogSpawned = false;
|
||||
partyLeader = "undefined";
|
||||
synchronized(candidates){
|
||||
candidates.clear();
|
||||
}
|
||||
timeStamp = 0;
|
||||
}
|
||||
public static void spawnBalrog(int mode, MapleCharacter chr){
|
||||
if(!balrogSpawned){
|
||||
for(int i = 0; i < HardBalrogParts.length; i++){
|
||||
chr.getClient().getChannelServer().getMapFactory().getMap(105100300).spawnMonsterOnGroundBelow(MapleLifeFactory.getMonster(HardBalrogParts[i]), new Point(412, 258));
|
||||
balrogSpawned = true;
|
||||
}
|
||||
} else {
|
||||
// DO NUFFIN'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -132,8 +132,12 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
public int getHp() {
|
||||
return hp.get();
|
||||
}
|
||||
|
||||
public void setHp(int hp) {
|
||||
|
||||
public void addHp(int hp) {
|
||||
this.hp.addAndGet(hp);
|
||||
}
|
||||
|
||||
public void setStartingHp(int hp) {
|
||||
this.hp.set(hp);
|
||||
}
|
||||
|
||||
@@ -208,28 +212,37 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
return stats.getTagBgColor();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param from the player that dealt the damage
|
||||
* @param damage
|
||||
*/
|
||||
public synchronized void damage(MapleCharacter from, int damage) { // may be pointless synchronization
|
||||
if (!isAlive()) {
|
||||
return;
|
||||
}
|
||||
public void setHpZero() { // force HP = 0
|
||||
applyAndGetHpDamage(Integer.MAX_VALUE, false);
|
||||
}
|
||||
|
||||
public synchronized Integer applyAndGetHpDamage(int delta, boolean stayAlive) {
|
||||
int curHp = hp.get();
|
||||
int trueDamage = Math.min(curHp, damage); // since magic happens otherwise B^)
|
||||
|
||||
if(ServerConstants.USE_DEBUG == true) from.dropMessage(5, "Hitted MOB " + this.getId() + ", OID " + this.getObjectId());
|
||||
dispatchMonsterDamaged(from, trueDamage);
|
||||
|
||||
hp.set(curHp - trueDamage);
|
||||
if (!takenDamage.containsKey(from.getId())) {
|
||||
takenDamage.put(from.getId(), new AtomicInteger(trueDamage));
|
||||
} else {
|
||||
takenDamage.get(from.getId()).addAndGet(trueDamage);
|
||||
if (curHp <= 0) { // this monster is already dead
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
if(delta >= 0) {
|
||||
if(stayAlive) curHp--;
|
||||
int trueDamage = Math.min(curHp, delta);
|
||||
|
||||
hp.addAndGet(-trueDamage);
|
||||
return trueDamage;
|
||||
} else {
|
||||
int trueHeal = -delta;
|
||||
int hp2Heal = curHp + trueHeal;
|
||||
int maxHp = getMaxHp();
|
||||
|
||||
if (hp2Heal > maxHp) {
|
||||
trueHeal -= (hp2Heal - maxHp);
|
||||
}
|
||||
|
||||
hp.addAndGet(trueHeal);
|
||||
return trueHeal;
|
||||
}
|
||||
}
|
||||
|
||||
public void broadcastMobHpBar(MapleCharacter from) {
|
||||
if (hasBossHPBar()) {
|
||||
from.setPlayerAggro(this.hashCode());
|
||||
from.getMap().broadcastBossHpMessage(this, this.hashCode(), makeBossHPBarPacket(), getPosition());
|
||||
@@ -248,26 +261,45 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param from the player that dealt the damage
|
||||
* @param damage
|
||||
*/
|
||||
public synchronized void damage(MapleCharacter from, int damage, boolean stayAlive) {
|
||||
Integer trueDamage = applyAndGetHpDamage(damage, stayAlive);
|
||||
if (trueDamage == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(ServerConstants.USE_DEBUG) from.dropMessage(5, "Hitted MOB " + this.getId() + ", OID " + this.getObjectId());
|
||||
dispatchMonsterDamaged(from, trueDamage);
|
||||
|
||||
if (!takenDamage.containsKey(from.getId())) {
|
||||
takenDamage.put(from.getId(), new AtomicInteger(trueDamage));
|
||||
} else {
|
||||
takenDamage.get(from.getId()).addAndGet(trueDamage);
|
||||
}
|
||||
|
||||
broadcastMobHpBar(from);
|
||||
}
|
||||
|
||||
public void heal(int hp, int mp) {
|
||||
int hpHealed = hp;
|
||||
int hp2Heal = getHp() + hp;
|
||||
int mp2Heal = getMp() + mp;
|
||||
Integer hpHealed = applyAndGetHpDamage(-hp, false);
|
||||
if(hpHealed == null) return;
|
||||
|
||||
int maxHp = getMaxHp();
|
||||
int mp2Heal = getMp() + mp;
|
||||
int maxMp = getMaxMp();
|
||||
if (hp2Heal >= maxHp) {
|
||||
hpHealed = hp2Heal - maxHp;
|
||||
hp2Heal = maxHp;
|
||||
}
|
||||
if (mp2Heal >= maxMp) {
|
||||
mp2Heal = maxMp;
|
||||
}
|
||||
setHp(hp2Heal);
|
||||
setMp(mp2Heal);
|
||||
getMap().broadcastMessage(MaplePacketCreator.healMonster(getObjectId(), hp));
|
||||
|
||||
if(hp > 0) getMap().broadcastMessage(MaplePacketCreator.healMonster(getObjectId(), hp));
|
||||
|
||||
maxHpPlusHeal.addAndGet(hpHealed);
|
||||
dispatchMonsterHealed(hpHealed);
|
||||
}
|
||||
|
||||
public boolean isAttackedBy(MapleCharacter chr) {
|
||||
@@ -471,7 +503,25 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
reviveMap.spawnMonster(mob);
|
||||
|
||||
if(mob.getId() >= 8810010 && mob.getId() <= 8810017 && reviveMap.isHorntailDefeated()) {
|
||||
for(int i = 8810018; i >= 8810010; i--)
|
||||
boolean htKilled = false;
|
||||
MapleMonster ht = reviveMap.getMonsterById(8810018);
|
||||
|
||||
if(ht != null) {
|
||||
ht.lockMonster();
|
||||
try {
|
||||
htKilled = ht.isAlive();
|
||||
ht.setHpZero();
|
||||
} finally {
|
||||
ht.unlockMonster();
|
||||
}
|
||||
|
||||
if(htKilled) {
|
||||
reviveMap.killMonster(ht, killer, true);
|
||||
ht.broadcastMobHpBar(killer);
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 8810017; i >= 8810010; i--)
|
||||
reviveMap.killMonster(reviveMap.getMonsterById(i), killer, true);
|
||||
}
|
||||
}
|
||||
@@ -506,6 +556,12 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
listener.monsterDamaged(from, trueDmg);
|
||||
}
|
||||
}
|
||||
|
||||
private void dispatchMonsterHealed(int trueHeal) {
|
||||
for (MonsterListener listener : listeners.toArray(new MonsterListener[listeners.size()])) {
|
||||
listener.monsterHealed(trueHeal);
|
||||
}
|
||||
}
|
||||
|
||||
// should only really be used to determine drop owner
|
||||
private int getHighestDamagerId() {
|
||||
@@ -837,10 +893,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
final Skill skill = SkillFactory.getSkill(status.getSkill().getId());
|
||||
final byte level = from.getSkillLevel(skill);
|
||||
final int damage = (int) ((from.getStr() + from.getLuk()) * (1.5 + (level * 0.05)) * skill.getEffect(level).getDamage());
|
||||
/*if (getHp() - damage <= 1) { make hp 1 betch
|
||||
damage = getHp() - (getHp() - 1);
|
||||
}*/
|
||||
|
||||
|
||||
status.setValue(MonsterStatus.NINJA_AMBUSH, Integer.valueOf(damage));
|
||||
animationTime = broadcastStatusEffect(status);
|
||||
status.setDamageSchedule(timerManager.register(new DamageTask(damage, from, status, cancelTask, 2), 1000, 1000));
|
||||
@@ -1092,20 +1145,19 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
@Override
|
||||
public void run() {
|
||||
int curHp = hp.get();
|
||||
if(curHp <= 0) return;
|
||||
if(curHp <= 1) return;
|
||||
|
||||
int damage = dealDamage;
|
||||
if (damage >= curHp) {
|
||||
damage = curHp - 1;
|
||||
if (type == 1 || type == 2) {
|
||||
map.broadcastMessage(MaplePacketCreator.damageMonster(getObjectId(), damage), getPosition());
|
||||
cancelTask.run();
|
||||
status.getCancelTask().cancel(false);
|
||||
}
|
||||
}
|
||||
if (curHp > 1 && damage > 0) {
|
||||
damage(chr, damage);
|
||||
if (type == 1) {
|
||||
if (damage > 0) {
|
||||
damage(chr, damage, true);
|
||||
if (type == 1 || type == 2) {
|
||||
map.broadcastMessage(MaplePacketCreator.damageMonster(getObjectId(), damage), getPosition());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,4 +5,5 @@ public interface MonsterListener {
|
||||
|
||||
public void monsterKilled(int aniTime);
|
||||
public void monsterDamaged(MapleCharacter from, int trueDmg);
|
||||
public void monsterHealed(int trueHeal);
|
||||
}
|
||||
|
||||
@@ -93,6 +93,9 @@ public class SpawnPoint {
|
||||
|
||||
@Override
|
||||
public void monsterDamaged(MapleCharacter from, int trueDmg) {}
|
||||
|
||||
@Override
|
||||
public void monsterHealed(int trueHeal) {}
|
||||
});
|
||||
if (mobTime == 0) {
|
||||
nextPossibleSpawn = System.currentTimeMillis() + mobInterval;
|
||||
|
||||
@@ -254,6 +254,7 @@ public class MapleMap {
|
||||
}
|
||||
|
||||
public void setReactorState() {
|
||||
chrRLock.lock();
|
||||
objectRLock.lock();
|
||||
try {
|
||||
for (MapleMapObject o : mapobjects.values()) {
|
||||
@@ -272,6 +273,7 @@ public class MapleMap {
|
||||
}
|
||||
} finally {
|
||||
objectRLock.unlock();
|
||||
chrRLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -564,7 +566,7 @@ public class MapleMap {
|
||||
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
||||
|
||||
for(MonsterDropEntry mde : from) {
|
||||
if(mde.itemId == 0 || !ii.isQuestItem(mde.itemId)) {
|
||||
if(!ii.isQuestItem(mde.itemId)) {
|
||||
item.add(mde);
|
||||
} else {
|
||||
quest.add(mde);
|
||||
@@ -585,9 +587,9 @@ public class MapleMap {
|
||||
for (final MonsterDropEntry de : dropEntry) {
|
||||
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))));
|
||||
pos.x = (int) (mobpos + ((d % 2 == 0) ? (40 * ((d + 1) / 2)) : -(40 * (d / 2))));
|
||||
} else {
|
||||
pos.x = (int) (mobpos + ((d % 2 == 0) ? (25 * (d + 1) / 2) : -(25 * (d / 2))));
|
||||
pos.x = (int) (mobpos + ((d % 2 == 0) ? (25 * ((d + 1) / 2)) : -(25 * (d / 2))));
|
||||
}
|
||||
if (de.itemId == 0) { // meso
|
||||
int mesos = Randomizer.nextInt(de.Maximum - de.Minimum) + de.Minimum;
|
||||
@@ -1014,21 +1016,10 @@ public class MapleMap {
|
||||
*/
|
||||
|
||||
if (damage > 0) {
|
||||
monster.damage(chr, damage);
|
||||
monster.damage(chr, damage, false);
|
||||
if (!monster.isAlive()) { // monster just died
|
||||
killed = true;
|
||||
}
|
||||
} else if (monster.getId() >= 8810002 && monster.getId() <= 8810009) {
|
||||
for (MapleMapObject object : chr.getMap().getMapObjects()) {
|
||||
MapleMonster mons = chr.getMap().getMonsterByOid(object.getObjectId());
|
||||
if (mons != null) {
|
||||
if (monster.isAlive() && (monster.getId() >= 8810010 && monster.getId() <= 8810017)) {
|
||||
if (mons.getId() == 8810018) {
|
||||
killMonster(mons, chr, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
monster.unlockMonster();
|
||||
@@ -1055,6 +1046,14 @@ public class MapleMap {
|
||||
return mobs;
|
||||
}
|
||||
|
||||
public void broadcastBalrogVictory(String leaderName) {
|
||||
for (Channel cserv : Server.getInstance().getWorld(world).getChannels()) {
|
||||
for (MapleCharacter player : cserv.getPlayerStorage().getAllCharacters()) {
|
||||
player.dropMessage(6, "[VICTORY] " + leaderName + "'s party has successfully defeated the Balrog! Praise to them, they finished with " + countAlivePlayers() + " players alive.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void broadcastHorntailVictory() {
|
||||
for (Channel cserv : Server.getInstance().getWorld(world).getChannels()) {
|
||||
for (MapleCharacter player : cserv.getPlayerStorage().getAllCharacters()) {
|
||||
@@ -1088,8 +1087,9 @@ public class MapleMap {
|
||||
|
||||
if (chr == null) {
|
||||
spawnedMonstersOnMap.decrementAndGet();
|
||||
monster.setHp(0);
|
||||
monster.setHpZero();
|
||||
removeMapObject(monster);
|
||||
|
||||
monster.dispatchMonsterKilled(false);
|
||||
broadcastMessage(MaplePacketCreator.killMonster(monster.getObjectId(), animation), monster.getPosition());
|
||||
return;
|
||||
@@ -1118,10 +1118,9 @@ public class MapleMap {
|
||||
}
|
||||
|
||||
spawnedMonstersOnMap.decrementAndGet();
|
||||
monster.setHp(0);
|
||||
//if (monster.getStats().selfDestruction() == null) {//FUU BOMBS D:
|
||||
monster.setHpZero();
|
||||
removeMapObject(monster);
|
||||
//}
|
||||
|
||||
if (monster.getCP() > 0 && chr.getCarnival() != null) {
|
||||
chr.getCarnivalParty().addCP(chr, monster.getCP());
|
||||
chr.announce(MaplePacketCreator.updateCP(chr.getCP(), chr.getObtainedCP()));
|
||||
@@ -1141,8 +1140,10 @@ public class MapleMap {
|
||||
}
|
||||
}
|
||||
if (makeZakReal) {
|
||||
MapleMap map = chr.getMap();
|
||||
|
||||
for (MapleMapObject object : objects) {
|
||||
MapleMonster mons = chr.getMap().getMonsterByOid(object.getObjectId());
|
||||
MapleMonster mons = map.getMonsterByOid(object.getObjectId());
|
||||
if (mons != null) {
|
||||
if (mons.getId() == 8800000) {
|
||||
makeMonsterReal(mons);
|
||||
@@ -1178,12 +1179,12 @@ public class MapleMap {
|
||||
this.killMonster(mob, (MapleCharacter) getPlayers().get(0), false);
|
||||
}
|
||||
|
||||
public void killMonster(int monsId) {
|
||||
public void killMonster(int mobId) {
|
||||
List<MapleMapObject> mmoL = new LinkedList(getMapObjects());
|
||||
|
||||
for (MapleMapObject mmo : mmoL) {
|
||||
if (mmo instanceof MapleMonster) {
|
||||
if (((MapleMonster) mmo).getId() == monsId) {
|
||||
if (((MapleMonster) mmo).getId() == mobId) {
|
||||
this.killMonster((MapleMonster) mmo, (MapleCharacter) getPlayers().get(0), false);
|
||||
}
|
||||
}
|
||||
@@ -1205,9 +1206,12 @@ public class MapleMap {
|
||||
if (monster.getStats().isFriendly()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
spawnedMonstersOnMap.decrementAndGet();
|
||||
monster.setHp(0);
|
||||
monster.setHpZero();
|
||||
removeMapObject(monster);
|
||||
|
||||
monster.dispatchMonsterKilled(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1415,10 +1419,10 @@ public class MapleMap {
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<MapleMapObject> getMapObjects() {
|
||||
public List<MapleMapObject> getMapObjects() {
|
||||
objectRLock.lock();
|
||||
try {
|
||||
return Collections.unmodifiableCollection(mapobjects.values());
|
||||
return new LinkedList(mapobjects.values());
|
||||
}
|
||||
finally {
|
||||
objectRLock.unlock();
|
||||
@@ -1446,7 +1450,8 @@ public class MapleMap {
|
||||
|
||||
public void destroyNPC(int npcid) {
|
||||
List<MapleMapObject> npcs = getMapObjectsInRange(new Point(0, 0), Double.POSITIVE_INFINITY, Arrays.asList(MapleMapObjectType.NPC));
|
||||
|
||||
|
||||
chrRLock.lock();
|
||||
objectWLock.lock();
|
||||
try {
|
||||
for (MapleMapObject obj : npcs) {
|
||||
@@ -1459,6 +1464,7 @@ public class MapleMap {
|
||||
}
|
||||
} finally {
|
||||
objectWLock.unlock();
|
||||
chrRLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1582,7 +1588,7 @@ public class MapleMap {
|
||||
|
||||
if (m.getId() == 9300061) {
|
||||
MapleMap.this.riceCakes++;
|
||||
MapleMap.this.broadcastMessage(MaplePacketCreator.serverNotice(6, "The Moon Bunny made rice cake number " + (MapleMap.this.riceCakes)));
|
||||
MapleMap.this.broadcastMessage(MaplePacketCreator.serverNotice(6, "The Moon Bunny made rice cake number " + (MapleMap.this.riceCakes) + "."));
|
||||
}
|
||||
|
||||
dropFromFriendlyMonster(chr, m);
|
||||
@@ -3240,11 +3246,10 @@ public class MapleMap {
|
||||
}
|
||||
|
||||
public void clearDrops(MapleCharacter player) {
|
||||
List<MapleMapObject> items = player.getMap().getMapObjectsInRange(player.getPosition(), Double.POSITIVE_INFINITY, Arrays.asList(MapleMapObjectType.ITEM));
|
||||
for (MapleMapObject i : items) {
|
||||
for (MapleMapObject i : getMapObjectsInRange(player.getPosition(), Double.POSITIVE_INFINITY, Arrays.asList(MapleMapObjectType.ITEM))) {
|
||||
droppedItemCount.decrementAndGet();
|
||||
player.getMap().removeMapObject(i);
|
||||
player.getMap().broadcastMessage(MaplePacketCreator.removeItemFromMap(i.getObjectId(), 0, player.getId()));
|
||||
removeMapObject(i);
|
||||
this.broadcastMessage(MaplePacketCreator.removeItemFromMap(i.getObjectId(), 0, player.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3436,6 +3441,7 @@ public class MapleMap {
|
||||
}
|
||||
|
||||
public void toggleHiddenNPC(int id) {
|
||||
chrRLock.lock();
|
||||
objectRLock.lock();
|
||||
try {
|
||||
for (MapleMapObject obj : mapobjects.values()) {
|
||||
@@ -3452,6 +3458,7 @@ public class MapleMap {
|
||||
}
|
||||
} finally {
|
||||
objectRLock.unlock();
|
||||
chrRLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3531,23 +3538,43 @@ public class MapleMap {
|
||||
TimerManager.getInstance().schedule(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (int x = 8810002; x <= 8810009; x++) {
|
||||
spawnMonsterOnGroundBelow(MapleLifeFactory.getMonster(x), targetPoint);
|
||||
}
|
||||
final MapleMonster ht = MapleLifeFactory.getMonster(8810018);
|
||||
ht.addListener(new MonsterListener() {
|
||||
@Override
|
||||
public void monsterKilled(int aniTime) {}
|
||||
|
||||
spawnMonsterOnGroundBelow(MapleLifeFactory.getMonster(8810018), targetPoint);
|
||||
@Override
|
||||
public void monsterDamaged(MapleCharacter from, int trueDmg) {
|
||||
ht.addHp(trueDmg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void monsterHealed(int trueHeal) {
|
||||
ht.addHp(-trueHeal);
|
||||
}
|
||||
});
|
||||
spawnMonsterOnGroundBelow(ht, targetPoint);
|
||||
|
||||
final MapleMonster ht = getMonsterById(8810018);
|
||||
for(int mobId = 8810002; mobId <= 8810009; mobId++) {
|
||||
getMonsterById(mobId).addListener(new MonsterListener() {
|
||||
for (int x = 8810002; x <= 8810009; x++) {
|
||||
MapleMonster m = MapleLifeFactory.getMonster(x);
|
||||
|
||||
m.addListener(new MonsterListener() {
|
||||
@Override
|
||||
public void monsterKilled(int aniTime) {}
|
||||
|
||||
@Override
|
||||
public void monsterDamaged(MapleCharacter from, int trueDmg) {
|
||||
ht.damage(from, trueDmg);
|
||||
ht.applyAndGetHpDamage(trueDmg, true);
|
||||
ht.broadcastMobHpBar(from);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void monsterHealed(int trueHeal) {
|
||||
ht.addHp(trueHeal);
|
||||
}
|
||||
});
|
||||
|
||||
spawnMonsterOnGroundBelow(m, targetPoint);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -379,13 +379,21 @@ public class MapleMapFactory {
|
||||
} else if (mapid >= 677000000 && mapid < 677100000) {
|
||||
builder.append("Episode1GL");
|
||||
} else if (mapid >= 670000000 && mapid < 682000000) {
|
||||
builder.append("weddingGL");
|
||||
if((mapid >= 674030000 && mapid < 674040000) || (mapid >= 680100000 && mapid < 680200000)) {
|
||||
builder.append("etc");
|
||||
} else {
|
||||
builder.append("weddingGL");
|
||||
}
|
||||
} else if (mapid >= 682000000 && mapid < 683000000) {
|
||||
builder.append("HalloweenGL");
|
||||
} else if (mapid >= 683000000 && mapid < 684000000) {
|
||||
builder.append("event");
|
||||
} else if (mapid >= 800000000 && mapid < 900000000) {
|
||||
builder.append("jp");
|
||||
if((mapid >= 889100000 && mapid < 889200000)) {
|
||||
builder.append("etc");
|
||||
} else {
|
||||
builder.append("jp");
|
||||
}
|
||||
} else {
|
||||
builder.append("etc");
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ public class MapleMapItem extends AbstractMapleMapObject {
|
||||
protected MapleClient ownerClient;
|
||||
protected Item item;
|
||||
protected MapleMapObject dropper;
|
||||
protected int character_ownerid, meso, questid = -1;
|
||||
protected int character_ownerid, party_ownerid, meso, questid = -1;
|
||||
protected byte type;
|
||||
protected boolean pickedUp = false, playerDrop;
|
||||
protected long dropTime;
|
||||
@@ -43,7 +43,8 @@ public class MapleMapItem extends AbstractMapleMapObject {
|
||||
setPosition(position);
|
||||
this.item = item;
|
||||
this.dropper = dropper;
|
||||
this.character_ownerid = owner.getId();
|
||||
this.character_ownerid = owner.getId();
|
||||
this.party_ownerid = owner.getPartyId();
|
||||
this.ownerClient = owner.getClient();
|
||||
this.meso = 0;
|
||||
this.type = type;
|
||||
@@ -54,7 +55,8 @@ public class MapleMapItem extends AbstractMapleMapObject {
|
||||
setPosition(position);
|
||||
this.item = item;
|
||||
this.dropper = dropper;
|
||||
this.character_ownerid = owner.getParty() == null ? owner.getId() : owner.getPartyId();
|
||||
this.character_ownerid = owner.getId();
|
||||
this.party_ownerid = owner.getPartyId();
|
||||
this.ownerClient = owner.getClient();
|
||||
this.meso = 0;
|
||||
this.type = type;
|
||||
@@ -66,8 +68,9 @@ public class MapleMapItem extends AbstractMapleMapObject {
|
||||
setPosition(position);
|
||||
this.item = null;
|
||||
this.dropper = dropper;
|
||||
this.character_ownerid = owner.getParty() == null ? owner.getId() : owner.getPartyId();
|
||||
this.ownerClient = owner.getClient();
|
||||
this.character_ownerid = owner.getId();
|
||||
this.party_ownerid = owner.getPartyId();
|
||||
this.ownerClient = owner.getClient();
|
||||
this.meso = meso;
|
||||
this.type = type;
|
||||
this.playerDrop = playerDrop;
|
||||
@@ -90,10 +93,32 @@ public class MapleMapItem extends AbstractMapleMapObject {
|
||||
return dropper;
|
||||
}
|
||||
|
||||
public final int getOwner() {
|
||||
public final int getOwnerId() {
|
||||
return character_ownerid;
|
||||
}
|
||||
|
||||
public final boolean canBePickedBy(MapleCharacter chr) {
|
||||
if (character_ownerid <= 0) return true;
|
||||
|
||||
if (party_ownerid == -1) {
|
||||
if (chr.getId() == character_ownerid) {
|
||||
return true;
|
||||
} else if (chr.isPartyMember(character_ownerid)) {
|
||||
party_ownerid = chr.getPartyId();
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (chr.getPartyId() == party_ownerid) {
|
||||
return true;
|
||||
} else if (chr.getId() == character_ownerid) {
|
||||
party_ownerid = chr.getPartyId();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return System.currentTimeMillis() - dropTime >= 15 * 1000;
|
||||
}
|
||||
|
||||
public final MapleClient getOwnerClient() {
|
||||
return (ownerClient.isLoggedIn() && !ownerClient.getPlayer().isAwayFromWorld()) ? ownerClient : null;
|
||||
}
|
||||
|
||||
@@ -1711,10 +1711,10 @@ public class MaplePacketCreator {
|
||||
mplew.writeInt(drop.getObjectId());
|
||||
mplew.writeBool(drop.getMeso() > 0); // 1 mesos, 0 item, 2 and above all item meso bag,
|
||||
mplew.writeInt(drop.getItemId()); // drop object ID
|
||||
mplew.writeInt(drop.getOwner()); // owner charid/paryid :)
|
||||
mplew.writeInt(drop.getOwnerId()); // owner charid/partyid :)
|
||||
mplew.write(drop.getDropType()); // 0 = timeout for non-owner, 1 = timeout for non-owner's party, 2 = FFA, 3 = explosive/FFA
|
||||
mplew.writePos(dropto);
|
||||
mplew.writeInt(drop.getDropType() == 0 ? drop.getOwner() : 0); //test
|
||||
mplew.writeInt(drop.getDropType() == 0 ? drop.getOwnerId() : 0); //test
|
||||
|
||||
if (mod != 2) {
|
||||
mplew.writePos(dropfrom);
|
||||
@@ -6668,12 +6668,14 @@ public class MaplePacketCreator {
|
||||
mplew.writeInt(mob.getObjectId());
|
||||
mplew.write(1); // direction ?
|
||||
mplew.writeInt(damage);
|
||||
int remainingHp = mob.getHp() - damage;
|
||||
if (remainingHp <= 1) {
|
||||
remainingHp = 0;
|
||||
mob.getMap().removeMapObject(mob);
|
||||
|
||||
mob.applyAndGetHpDamage(damage, false);
|
||||
int remainingHp = mob.getHp();
|
||||
if(remainingHp <= 0) {
|
||||
remainingHp = 0;
|
||||
mob.getMap().removeMapObject(mob);
|
||||
}
|
||||
mob.setHp(remainingHp);
|
||||
|
||||
mplew.writeInt(remainingHp);
|
||||
mplew.writeInt(mob.getMaxHp());
|
||||
return mplew.getPacket();
|
||||
|
||||
Reference in New Issue
Block a user