Attempt on Mystic Doors

Partially fixed Mystic Doors.
This commit is contained in:
ronancpl
2017-07-09 20:00:31 -03:00
parent b3734cbaf7
commit b7c0bb6c07
83 changed files with 443 additions and 241 deletions

View File

@@ -1,4 +1,4 @@
#Tue, 04 Jul 2017 15:35:40 -0300
#Sun, 09 Jul 2017 19:55:31 -0300
C\:\\Nexon\\MapleSolaxia\\MapleSolaxiaV2=

Binary file not shown.

Binary file not shown.

BIN
dist/MapleSolaxia.jar vendored

Binary file not shown.

View File

@@ -4,9 +4,15 @@
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
<group>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/SendOpcode.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/maps/MapleMapObjectType.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/maps/MapleSummon.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/channel/handlers/DamageSummonHandler.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/maps/MapleDoor.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/MapleStatEffect.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/world/MaplePartyCharacter.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/channel/handlers/DoorHandler.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/client/MapleBuffStat.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/maps/MapleMap.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/maps/MapleDoorObject.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/client/MapleCharacter.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/client/MapleClient.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/tools/MaplePacketCreator.java</file>
</group>
</open-files>

View File

@@ -250,7 +250,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
private Map<Integer, MapleSummon> summons = new LinkedHashMap<>();
private Map<Integer, MapleCoolDownValueHolder> coolDowns = new LinkedHashMap<>(50);
private EnumMap<MapleDisease, DiseaseValueHolder> diseases = new EnumMap<>(MapleDisease.class);
private List<MapleDoor> doors = new ArrayList<>();
private Map<Integer, MapleDoor> doors = new LinkedHashMap<>();
private ScheduledFuture<?> dragonBloodSchedule;
private ScheduledFuture<?> mapTimeLimitTask = null;
private ScheduledFuture<?>[] fullnessSchedule = new ScheduledFuture<?>[3];
@@ -462,8 +462,12 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
return pts;
}
public void addDoor(MapleDoor door) {
doors.add(door);
public void addDoor(Integer owner, MapleDoor door) {
doors.put(owner, door);
}
public void removeDoor(Integer owner) {
doors.remove(owner);
}
public void addExcluded(int x) {
@@ -656,40 +660,38 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
public int calculateMaxBaseDamage(int watk) {
int maxbasedamage;
Item weapon_item = getInventory(MapleInventoryType.EQUIPPED).getItem((short) -11);
if (weapon_item != null) {
MapleWeaponType weapon = MapleItemInformationProvider.getInstance().getWeaponType(weapon_item.getItemId());
int mainstat;
int secondarystat;
if (getJob().isA(MapleJob.THIEF) && weapon == MapleWeaponType.DAGGER_OTHER) {
weapon = MapleWeaponType.DAGGER_THIEVES;
}
Item weapon_item = getInventory(MapleInventoryType.EQUIPPED).getItem((short) -11);
if (weapon_item != null) {
MapleWeaponType weapon = MapleItemInformationProvider.getInstance().getWeaponType(weapon_item.getItemId());
int mainstat, secondarystat;
if (getJob().isA(MapleJob.THIEF) && weapon == MapleWeaponType.DAGGER_OTHER) {
weapon = MapleWeaponType.DAGGER_THIEVES;
}
if (weapon == MapleWeaponType.BOW || weapon == MapleWeaponType.CROSSBOW || weapon == MapleWeaponType.GUN) {
mainstat = localdex;
secondarystat = localstr;
} else if (weapon == MapleWeaponType.CLAW || weapon == MapleWeaponType.DAGGER_THIEVES) {
mainstat = localluk;
secondarystat = localdex + localstr;
} else {
mainstat = localstr;
secondarystat = localdex;
}
maxbasedamage = (int) (((weapon.getMaxDamageMultiplier() * mainstat + secondarystat) / 100.0) * watk);
} else {
if (weapon == MapleWeaponType.BOW || weapon == MapleWeaponType.CROSSBOW || weapon == MapleWeaponType.GUN) {
mainstat = localdex;
secondarystat = localstr;
} else if (weapon == MapleWeaponType.CLAW || weapon == MapleWeaponType.DAGGER_THIEVES) {
mainstat = localluk;
secondarystat = localdex + localstr;
} else {
mainstat = localstr;
secondarystat = localdex;
}
maxbasedamage = (int) (((weapon.getMaxDamageMultiplier() * mainstat + secondarystat) / 100.0) * watk);
} else {
if (job.isA(MapleJob.PIRATE) || job.isA(MapleJob.THUNDERBREAKER1)) {
double weapMulti = 3;
double weapMulti = 3;
if (job.getId() % 100 != 0) {
weapMulti = 4.2;
weapMulti = 4.2;
}
int attack = (int) Math.min(Math.floor((2 * getLevel() + 31) / 3), 31);
maxbasedamage = (int) (localstr * weapMulti + localdex) * attack / 100;
} else {
maxbasedamage = 1;
}
}
int attack = (int) Math.min(Math.floor((2 * getLevel() + 31) / 3), 31);
maxbasedamage = (int) (localstr * weapMulti + localdex) * attack / 100;
} else {
maxbasedamage = 1;
}
}
return maxbasedamage;
}
@@ -811,31 +813,33 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
buffstats.add(statup.getLeft());
}
}
List<MapleBuffStatValueHolder> toCancel = deregisterBuffStats(buffstats);
if (effect.isMagicDoor()) {
if (!getDoors().isEmpty()) {
MapleDoor door = getDoors().iterator().next();
for (MapleCharacter chr : door.getTarget().getCharacters()) {
door.sendDestroyData(chr.client);
MapleDoor destroyDoor = doors.remove(this.getId());
if (destroyDoor != null) {
destroyDoor.freeAllocatedPortal();
destroyDoor.getTarget().removeMapObject(destroyDoor.getAreaDoor());
destroyDoor.getTown().removeMapObject(destroyDoor.getTownDoor());
for (MapleCharacter chr : destroyDoor.getTarget().getCharacters()) {
destroyDoor.getAreaDoor().sendDestroyData(chr.getClient());
}
for (MapleCharacter chr : door.getTown().getCharacters()) {
door.sendDestroyData(chr.client);
}
for (MapleDoor destroyDoor : getDoors()) {
door.getTarget().removeMapObject(destroyDoor);
door.getTown().removeMapObject(destroyDoor);
for (MapleCharacter chr : destroyDoor.getTown().getCharacters()) {
destroyDoor.getTownDoor().sendDestroyData(chr.getClient());
}
if (party != null) {
for (MaplePartyCharacter partyMembers : getParty().getMembers()) {
partyMembers.getPlayer().getDoors().remove(door);
partyMembers.getDoors().remove(door);
partyMembers.getPlayer().removeDoor(this.getId());
partyMembers.removeDoor(this.getId());
}
silentPartyUpdate();
} else {
clearDoors();
}
}
}
List<MapleBuffStatValueHolder> toCancel = deregisterBuffStats(buffstats);
if (effect.getSourceId() == Spearman.HYPER_BODY || effect.getSourceId() == GM.HYPER_BODY || effect.getSourceId() == SuperGM.HYPER_BODY) {
List<Pair<MapleStat, Integer>> statup = new ArrayList<>(4);
statup.add(new Pair<>(MapleStat.HP, Math.min(hp, maxhp)));
@@ -1335,10 +1339,6 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
}
public void clearDoors() {
doors.clear();
}
public void clearSavedLocation(SavedLocationType type) {
savedLocations[type.ordinal()] = null;
}
@@ -2412,8 +2412,8 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
return dojoStage;
}
public List<MapleDoor> getDoors() {
return new ArrayList<>(doors);
public Map<Integer, MapleDoor> getDoors() {
return Collections.unmodifiableMap(doors);
}
public int getEnergyBar() {
@@ -3870,6 +3870,10 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
}
}
public Set<Integer> getActiveCoupons() {
return Collections.unmodifiableSet(activeCoupons.keySet());
}
public static MapleCharacter loadCharFromDB(int charid, MapleClient client, boolean channelserver) throws SQLException {
try {

View File

@@ -1196,8 +1196,8 @@ public class MapleClient {
}
server.getPlayerBuffStorage().addBuffsToStorage(player.getId(), player.getAllBuffs());
player.cancelBuffEffects();
player.cancelMagicDoor();
//Canceling mounts? Noty
//Cancelling magicdoor? Nope
//Cancelling mounts? Noty
if (player.getBuffedValue(MapleBuffStat.PUPPET) != null) {
player.cancelEffectFromBuffStat(MapleBuffStat.PUPPET);
}

View File

@@ -27,12 +27,12 @@ import server.MapleStatEffect;
import server.life.Element;
public class Skill {
public int id;
public List<MapleStatEffect> effects = new ArrayList<>();
public Element element;
public int animationTime;
public int job;
public boolean action;
private int id;
private List<MapleStatEffect> effects = new ArrayList<>();
private Element element;
private int animationTime;
private int job;
private boolean action;
public Skill(int id) {
this.id = id;
@@ -61,6 +61,10 @@ public class Skill {
return job % 10 == 2;
}
public void setElement(Element elem) {
element = elem;
}
public Element getElement() {
return element;
}
@@ -68,12 +72,28 @@ public class Skill {
public int getAnimationTime() {
return animationTime;
}
public void setAnimationTime(int time) {
animationTime = time;
}
public void incAnimationTime(int time) {
animationTime += time;
}
public boolean isBeginnerSkill() {
return id % 10000000 < 10000;
}
public void setAction(boolean act) {
action = act;
}
public boolean getAction() {
return action;
}
public void addLevelEffect(MapleStatEffect effect) {
effects.add(effect);
}
}

View File

@@ -74,7 +74,9 @@ import constants.skills.WhiteKnight;
import constants.skills.WindArcher;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import provider.MapleData;
@@ -122,9 +124,9 @@ public class SkillFactory {
int skillType = MapleDataTool.getInt("skillType", data, -1);
String elem = MapleDataTool.getString("elemAttr", data, null);
if (elem != null) {
ret.element = Element.getFromChar(elem.charAt(0));
ret.setElement(Element.getFromChar(elem.charAt(0)));
} else {
ret.element = Element.NEUTRAL;
ret.setElement(Element.NEUTRAL);
}
MapleData effect = data.getChildByPath("effect");
if (skillType != -1) {
@@ -148,7 +150,7 @@ public class SkillFactory {
} else {
action = true;
}
ret.action = action;
ret.setAction(action);
MapleData hit = data.getChildByPath("hit");
MapleData ball = data.getChildByPath("ball");
isBuff = effect != null && hit == null && ball == null;
@@ -371,12 +373,12 @@ public class SkillFactory {
}
for (MapleData level : data.getChildByPath("level")) {
ret.effects.add(MapleStatEffect.loadSkillEffectFromData(level, id, isBuff));
ret.addLevelEffect(MapleStatEffect.loadSkillEffectFromData(level, id, isBuff));
}
ret.animationTime = 0;
ret.setAnimationTime(0);
if (effect != null) {
for (MapleData effectEntry : effect) {
ret.animationTime += MapleDataTool.getIntConvert("delay", effectEntry, 0);
ret.incAnimationTime(MapleDataTool.getIntConvert("delay", effectEntry, 0));
}
}
return ret;

View File

@@ -709,7 +709,7 @@ public class Commands {
case "debugmap":
if(ServerConstants.USE_DEBUG) {
player.dropMessage(6, "Current map id " + player.getMap().getId() + ", event: '" + ((player.getMap().getEventInstance() != null) ? player.getMap().getEventInstance().getName() : "null") + "'; Players: " + player.getMap().getAllPlayers().size() + ", Mobs: " + player.getMap().countMonsters() + ", Reactors: " + player.getMap().countReactors() + ", Items: " + player.getMap().countItems() + ".");
player.dropMessage(6, "Current map id " + player.getMap().getId() + ", event: '" + ((player.getMap().getEventInstance() != null) ? player.getMap().getEventInstance().getName() : "null") + "'; Players: " + player.getMap().getAllPlayers().size() + ", Mobs: " + player.getMap().countMonsters() + ", Reactors: " + player.getMap().countReactors() + ", Items: " + player.getMap().countItems() + ", Objects: " + player.getMap().getMapObjects().size() + ".");
}
break;
@@ -764,7 +764,7 @@ public class Commands {
case "debugplayercoupons":
if(ServerConstants.USE_DEBUG) {
String s = "Currently active PLAYER coupons: ";
for(Integer i : Server.getInstance().getActiveCoupons()) {
for(Integer i : player.getActiveCoupons()) {
s += (i + " ");
}

View File

@@ -23,22 +23,22 @@ package net.server.channel.handlers;
import client.MapleClient;
import net.AbstractMaplePacketHandler;
import server.maps.MapleDoor;
import server.maps.MapleDoorObject;
import server.maps.MapleMapObject;
import tools.data.input.SeekableLittleEndianAccessor;
/**
*
* @author Matze
* @author Matze, Ronan
*/
public final class DoorHandler extends AbstractMaplePacketHandler {
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
int oid = slea.readInt();
int ownerid = slea.readInt();
boolean mode = (slea.readByte() == 0); // specifies if backwarp or not, 1 town to target, 0 target to town
for (MapleMapObject obj : c.getPlayer().getMap().getMapObjects()) {
if (obj instanceof MapleDoor) {
MapleDoor door = (MapleDoor) obj;
if (door.getOwner().getId() == oid) {
if (obj instanceof MapleDoorObject) {
MapleDoorObject door = (MapleDoorObject) obj;
if (door.getOwnerId() == ownerid) {
door.warp(c.getPlayer(), mode);
return;
}

View File

@@ -116,12 +116,12 @@ public final class SpecialMoveHandler extends AbstractMaplePacketHandler {
if (slea.available() == 5) {
pos = new Point(slea.readShort(), slea.readShort());
}
if (skill.getId() == Priest.MYSTIC_DOOR && !chr.isGM()) {
c.announce(MaplePacketCreator.enableActions());
return;
}
if (chr.isAlive()) {
if (skill.getId() != Priest.MYSTIC_DOOR || chr.canDoor()) {
if (skill.getId() != Priest.MYSTIC_DOOR) {
skill.getEffect(skillLevel).applyTo(c.getPlayer(), pos);
} else if(chr.canDoor()) {
//update door lists
chr.cancelMagicDoor();
skill.getEffect(skillLevel).applyTo(c.getPlayer(), pos);
} else {
chr.message("Please wait 5 seconds before casting Mystic Door again.");

View File

@@ -21,12 +21,16 @@
*/
package net.server.world;
import java.util.ArrayList;
import java.util.Map;
import java.util.Map.Entry;
import java.util.LinkedHashMap;
import java.util.Collection;
import server.maps.MapleDoor;
import server.MapleStatEffect;
import client.MapleCharacter;
import client.MapleJob;
import java.util.Collections;
public class MaplePartyCharacter {
private String name;
@@ -35,7 +39,7 @@ public class MaplePartyCharacter {
private int channel, world;
private int jobid;
private int mapid;
private ArrayList<MapleDoor> door = new ArrayList<MapleDoor>();
private Map<Integer, MapleDoor> doors = new LinkedHashMap<>();
private boolean online;
private MapleJob job;
private MapleCharacter character;
@@ -51,8 +55,8 @@ public class MaplePartyCharacter {
this.mapid = maplechar.getMapId();
this.online = true;
this.job = maplechar.getJob();
for (MapleDoor doors : maplechar.getDoors()) {
this.door.add(doors);
for (Entry<Integer, MapleDoor> entry : maplechar.getDoors().entrySet()) {
doors.put(entry.getKey(), entry.getValue());
}
}
@@ -116,12 +120,16 @@ public class MaplePartyCharacter {
return character.getGuildId();
}
public void updateDoor(MapleDoor door) {
this.door.add(door);
public void addDoor(Integer owner, MapleDoor door) {
this.doors.put(owner, door);
}
public void removeDoor(Integer owner) {
this.doors.remove(owner);
}
public Collection<MapleDoor> getDoors() {
return door;
return Collections.unmodifiableCollection(doors.values());
}
@Override

View File

@@ -839,33 +839,30 @@ public class MapleStatEffect {
}
}
if (isMagicDoor() && !FieldLimit.DOOR.check(applyto.getMap().getFieldLimit())) { // Magic Door
int y = applyto.getFh();
if (y == 0) {
y = applyto.getPosition().y;
}
int y = applyto.getFh();
if (y == 0) {
y = applyto.getPosition().y;
}
Point doorPosition = new Point(applyto.getPosition().x, y);
MapleDoor door = new MapleDoor(applyto, doorPosition);
if (applyto.getParty() != null) {// out of town door
for (MaplePartyCharacter partyMembers : applyto.getParty().getMembers()) {
partyMembers.getPlayer().addDoor(door);
partyMembers.updateDoor(door);
MapleDoor door = new MapleDoor(applyto, doorPosition);
if(door.getOwnerId() != -1) {
if (applyto.getParty() != null) {
for (MaplePartyCharacter partyMember : applyto.getParty().getMembers()) {
partyMember.getPlayer().addDoor(door.getOwnerId(), door);
partyMember.addDoor(door.getOwnerId(), door);
}
applyto.silentPartyUpdate();
} else {
applyto.addDoor(door.getOwnerId(), door);
}
applyto.silentPartyUpdate();
door.getTarget().spawnDoor(door.getAreaDoor());
door.getTown().spawnDoor(door.getTownDoor());
} else {
applyto.addDoor(door);
}
applyto.getMap().spawnDoor(door);
door = new MapleDoor(door); //The town door
if (applyto.getParty() != null) {// update town doors
for (MaplePartyCharacter partyMembers : applyto.getParty().getMembers()) {
partyMembers.getPlayer().addDoor(door);
partyMembers.updateDoor(door);
}
applyto.silentPartyUpdate();
} else {
applyto.addDoor(door);
}
door.getTown().spawnDoor(door);
applyto.dropMessage(5, "There are no door portals available for the town at this moment. Try again later.");
applyto.cancelBuffStats(MapleBuffStat.SOULARROW); // cancel door buff
}
applyto.disableDoor();
} else if (isMist()) {
Rectangle bounds = calculateBoundingBox(sourceid == NightWalker.POISON_BOMB ? pos : applyfrom.getPosition(), applyfrom.isFacingLeft());
@@ -966,7 +963,7 @@ public class MapleStatEffect {
}
private void applyBuffEffect(MapleCharacter applyfrom, MapleCharacter applyto, boolean primary) {
if (!isMonsterRiding() && !isCouponBuff()) {
if (!isMonsterRiding() && !isCouponBuff() && !isMysticDoor()) { // last mystic door already dispelled if it has been used before.
applyto.cancelEffect(this, true, -1);
}
@@ -1295,6 +1292,10 @@ public class MapleStatEffect {
return MapleItemInformationProvider.getInstance().isRateCoupon(sourceid);
}
private boolean isMysticDoor() {
return skill && sourceid == Priest.MYSTIC_DOOR;
}
public boolean isMonsterRiding() {
return skill && (sourceid % 10000000 == 1004 || sourceid == Corsair.BATTLE_SHIP || sourceid == Beginner.SPACESHIP || sourceid == Noblesse.SPACESHIP
|| sourceid == Beginner.YETI_MOUNT1 || sourceid == Beginner.YETI_MOUNT2 || sourceid == Beginner.WITCH_BROOMSTICK || sourceid == Beginner.BALROG_MOUNT
@@ -1432,7 +1433,7 @@ public class MapleStatEffect {
public boolean hasNoIcon() {
return (sourceid == 3111002 || sourceid == 3211002 || + // puppet, puppet
sourceid == 3211005 || sourceid == 2311002 || + // golden eagle, mystic door
sourceid == 3211005 || + // golden eagle
sourceid == 2121005 || sourceid == 2221005 || + // elquines, ifrit
sourceid == 2321003 || sourceid == 3121006 || + // bahamut, phoenix
sourceid == 3221005 || sourceid == 3111005 || + // frostprey, silver hawk

View File

@@ -22,117 +22,77 @@
package server.maps;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import server.MaplePortal;
import tools.MaplePacketCreator;
import client.MapleCharacter;
import client.MapleClient;
/**
*
* @author Matze
* @author Matze, Ronan
*/
public class MapleDoor extends AbstractMapleMapObject {
private MapleCharacter owner;
public class MapleDoor {
private int ownerId;
private MapleMap town;
private MaplePortal townPortal;
private MapleMap target;
private Point targetPosition;
private MapleDoorObject townDoor;
private MapleDoorObject areaDoor;
public MapleDoor(MapleCharacter owner, Point targetPosition) {
super();
this.owner = owner;
this.ownerId = owner.getId();
this.target = owner.getMap();
this.targetPosition = targetPosition;
setPosition(this.targetPosition);
this.town = this.target.getReturnMap();
this.townPortal = getFreePortal();
}
public MapleDoor(MapleDoor origDoor) {
super();
this.owner = origDoor.owner;
this.town = origDoor.town;
this.townPortal = origDoor.townPortal;
this.target = origDoor.target;
this.targetPosition = origDoor.targetPosition;
this.townPortal = origDoor.townPortal;
setPosition(this.townPortal.getPosition());
}
private MaplePortal getFreePortal() {
List<MaplePortal> freePortals = new ArrayList<MaplePortal>();
for (MaplePortal port : town.getPortals()) {
if (port.getType() == 6) {
freePortals.add(port);
}
}
Collections.sort(freePortals, new Comparator<MaplePortal>() {
public int compare(MaplePortal o1, MaplePortal o2) {
if (o1.getId() < o2.getId()) {
return -1;
} else if (o1.getId() == o2.getId()) {
return 0;
} else {
return 1;
}
}
});
for (MapleMapObject obj : town.getMapObjects()) {
if (obj instanceof MapleDoor) {
MapleDoor door = (MapleDoor) obj;
if (door.getOwner().getParty() != null && door.getOwner().getParty().containsMembers(door.getOwner().getMPC())) {
freePortals.remove(door.getTownPortal());
}
}
}
return freePortals.iterator().next();
}
@Override
public void sendSpawnData(MapleClient client) {
if (target.getId() == client.getPlayer().getMapId() || owner == client.getPlayer() && owner.getParty() == null) {
client.announce(MaplePacketCreator.spawnDoor(owner.getId(), town.getId() == client.getPlayer().getMapId() ? townPortal.getPosition() : targetPosition, true));
if (owner.getParty() != null && (owner == client.getPlayer() || owner.getParty().containsMembers(client.getPlayer().getMPC()))) {
client.announce(MaplePacketCreator.partyPortal(town.getId(), target.getId(), targetPosition));
}
}
if (owner.getId() != client.getPlayer().getId()) {
client.announce(MaplePacketCreator.spawnPortal(town.getId(), target.getId(), targetPosition));
}
}
@Override
public void sendDestroyData(MapleClient client) {
if (target.getId() == client.getPlayer().getMapId() || owner == client.getPlayer() || owner.getParty() != null && owner.getParty().containsMembers(client.getPlayer().getMPC())) {
if (owner.getParty() != null && (owner == client.getPlayer() || owner.getParty().containsMembers(client.getPlayer().getMPC()))) {
client.announce(MaplePacketCreator.partyPortal(999999999, 999999999, new Point(-1, -1)));
}
client.announce(MaplePacketCreator.removeDoor(owner.getId(), false));
client.announce(MaplePacketCreator.removeDoor(owner.getId(), true));
}
}
public void warp(MapleCharacter chr, boolean toTown) {
if (chr == owner || owner.getParty() != null && owner.getParty().containsMembers(chr.getMPC())) {
if (!toTown) {
chr.changeMap(target, targetPosition);
} else {
chr.changeMap(town, townPortal);
}
this.townPortal = allocateFreePortal();
if(townPortal != null) {
this.areaDoor = new MapleDoorObject(ownerId, town, target, false, targetPosition, townPortal.getPosition());
this.townDoor = new MapleDoorObject(ownerId, target, town, true, townPortal.getPosition(), targetPosition);
this.areaDoor.setPairOid(this.townDoor.getObjectId());
this.townDoor.setPairOid(this.areaDoor.getObjectId());
} else {
chr.getClient().announce(MaplePacketCreator.enableActions());
this.ownerId = -1;
}
}
public MapleCharacter getOwner() {
return owner;
public void freeAllocatedPortal() {
if(townPortal != null) {
town.setDisposeDoorPortal(townPortal);
}
}
private MaplePortal allocateFreePortal() {
List<MaplePortal> availablePortals = town.getAvailableDoorPortals();
if(availablePortals.isEmpty() || !town.getNotUsingDoorPortal()) return null;
Collections.shuffle(availablePortals);
while(!availablePortals.isEmpty()) {
MaplePortal port = availablePortals.remove(0);
if(town.setUsingDoorPortal(port)) {
return port;
}
}
return null;
}
public int getOwnerId() {
return ownerId;
}
public MapleDoorObject getTownDoor() {
return townDoor;
}
public MapleDoorObject getAreaDoor() {
return areaDoor;
}
public MapleMap getTown() {
return town;
}
@@ -145,13 +105,4 @@ public class MapleDoor extends AbstractMapleMapObject {
return target;
}
public Point getTargetPosition() {
return targetPosition;
}
@Override
public MapleMapObjectType getType() {
return MapleMapObjectType.DOOR;
}
}

View File

@@ -0,0 +1,130 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package server.maps;
import client.MapleCharacter;
import java.awt.Point;
import tools.MaplePacketCreator;
import client.MapleClient;
/**
*
* @author Ronan
*/
public class MapleDoorObject extends AbstractMapleMapObject {
private int ownerId;
private int pairOid;
private boolean isTown;
private MapleMap from;
private MapleMap to;
private Point toPos;
public MapleDoorObject(int owner, MapleMap destination, MapleMap origin, boolean town, Point targetPosition, Point toPosition) {
super();
setPosition(targetPosition);
ownerId = owner;
isTown = town;
from = origin;
to = destination;
toPos = toPosition;
}
public void warp(MapleCharacter chr, boolean toTown) {
if (chr.getId() == ownerId || (chr.getParty() != null && chr.getParty().getMemberById(ownerId) != null)) {
chr.changeMap(to, toPos);
} else {
chr.getClient().announce(MaplePacketCreator.blockedMessage(6));
chr.getClient().announce(MaplePacketCreator.enableActions());
}
}
@Override
public void sendSpawnData(MapleClient client) {
if (from.getId() == client.getPlayer().getMapId()) {
client.announce(MaplePacketCreator.spawnPortal(this.getFrom().getId(), this.getTo().getId(), this.toPosition()));
if(!this.inTown()) client.announce(MaplePacketCreator.spawnDoor(this.getOwnerId(), this.getPosition(), true));
if (client.getPlayer().getParty() != null && (ownerId == client.getPlayer().getId() || client.getPlayer().getParty().getMemberById(ownerId) != null)) {
client.announce(MaplePacketCreator.partyPortal(this.getTown().getId(), this.getArea().getId(), this.getAreaPosition()));
}
}
}
@Override
public void sendDestroyData(MapleClient client) {
if (from.getId() == client.getPlayer().getMapId()) {
if (client.getPlayer().getParty() != null && (ownerId == client.getPlayer().getId() || client.getPlayer().getParty().getMemberById(ownerId) != null)) {
client.announce(MaplePacketCreator.partyPortal(999999999, 999999999, new Point(-1, -1)));
}
client.announce(MaplePacketCreator.removeDoor(ownerId, isTown));
}
}
public int getOwnerId() {
return ownerId;
}
public void setPairOid(int oid) {
this.pairOid = oid;
}
public int getPairOid() {
return pairOid;
}
public boolean inTown() {
return isTown;
}
public MapleMap getFrom() {
return from;
}
public MapleMap getTo() {
return to;
}
public MapleMap getTown() {
return isTown ? from : to;
}
public MapleMap getArea() {
return !isTown ? from : to;
}
public Point getAreaPosition() {
return !isTown ? getPosition() : toPos;
}
public Point toPosition() {
return toPos;
}
@Override
public MapleMapObjectType getType() {
return MapleMapObjectType.DOOR;
}
}

View File

@@ -45,6 +45,8 @@ import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
@@ -94,6 +96,7 @@ public class MapleMap {
private Map<Integer, MaplePortal> portals = new HashMap<>();
private Map<Integer, Integer> backgroundTypes = new HashMap<>();
private Map<String, Integer> environment = new LinkedHashMap<String, Integer>();
private Set<Integer> usedDoors = new HashSet<>();
private List<Rectangle> areas = new ArrayList<>();
private MapleFootholdTree footholds = null;
private int mapid;
@@ -1360,24 +1363,74 @@ public class MapleMap {
spawnReactor(reactor);
}
public void spawnDoor(final MapleDoor door) {
public void spawnDoor(final MapleDoorObject door) {
spawnAndAddRangedMapObject(door, new DelayedPacketCreation() {
@Override
public void sendPackets(MapleClient c) {
c.announce(MaplePacketCreator.spawnDoor(door.getOwner().getId(), door.getTargetPosition(), false));
if (door.getOwner().getParty() != null && (door.getOwner() == c.getPlayer() || door.getOwner().getParty().containsMembers(c.getPlayer().getMPC()))) {
c.announce(MaplePacketCreator.partyPortal(door.getTown().getId(), door.getTarget().getId(), door.getTargetPosition()));
if (door.getFrom().getId() == c.getPlayer().getMapId()) {
c.announce(MaplePacketCreator.spawnPortal(door.getFrom().getId(), door.getTo().getId(), door.toPosition()));
if(!door.inTown()) c.announce(MaplePacketCreator.spawnDoor(door.getOwnerId(), door.getPosition(), false));
if (c.getPlayer().getParty() != null && (door.getOwnerId() == c.getPlayer().getId() || c.getPlayer().getParty().getMemberById(door.getOwnerId()) != null)) {
c.announce(MaplePacketCreator.partyPortal(door.getTown().getId(), door.getArea().getId(), door.getAreaPosition()));
}
}
c.announce(MaplePacketCreator.spawnPortal(door.getTown().getId(), door.getTarget().getId(), door.getTargetPosition()));
c.announce(MaplePacketCreator.enableActions());
}
}, new SpawnCondition() {
@Override
public boolean canSpawn(MapleCharacter chr) {
return chr.getMapId() == door.getTarget().getId() || chr == door.getOwner() && chr.getParty() == null;
return chr.getMapId() == door.getFrom().getId();
}
});
}
public boolean setUsingDoorPortal(MaplePortal port) {
objectWLock.lock();
try {
if(usedDoors.contains(port.getId())) return false;
usedDoors.add(port.getId());
return true;
} finally {
objectWLock.unlock();
}
}
public void setDisposeDoorPortal(MaplePortal port) {
objectWLock.lock();
try {
usedDoors.remove(port.getId());
} finally {
objectWLock.unlock();
}
}
public boolean getNotUsingDoorPortal() {
objectRLock.lock();
try {
return usedDoors.isEmpty();
} finally {
objectRLock.unlock();
}
}
public List<MaplePortal> getAvailableDoorPortals() {
objectRLock.lock();
try {
List<MaplePortal> availablePortals = new ArrayList<>();
for (MaplePortal port : getPortals()) {
if (port.getType() == MaplePortal.DOOR_PORTAL && !usedDoors.contains(port.getId())) {
availablePortals.add(port);
}
}
return availablePortals;
} finally {
objectRLock.unlock();
}
}
public void spawnSummon(final MapleSummon summon) {
@@ -2095,7 +2148,7 @@ public class MapleMap {
}
private void updateMapObjectVisibility(MapleCharacter chr, MapleMapObject mo) {
if (!chr.isMapObjectVisible(mo)) { // monster entered view range
if (!chr.isMapObjectVisible(mo)) { // item entered view range
if (mo.getType() == MapleMapObjectType.SUMMON || mo.getPosition().distanceSq(chr.getPosition()) <= getRangedDistance()) {
chr.addVisibleMapObject(mo);
mo.sendSpawnData(chr.getClient());

View File

@@ -64,6 +64,7 @@ import server.life.MapleNPC;
import server.life.MobSkill;
import server.maps.HiredMerchant;
import server.maps.MapleDoor;
import server.maps.MapleDoorObject;
import server.maps.MapleDragon;
import server.maps.MapleMap;
import server.maps.MapleMapItem;
@@ -1056,24 +1057,22 @@ public class MaplePacketCreator {
mplew.writeShort(SendOpcode.SPAWN_PORTAL.getValue());
mplew.writeInt(townId);
mplew.writeInt(targetId);
if (pos != null) {
mplew.writePos(pos);
}
mplew.writePos(pos);
return mplew.getPacket();
}
/**
* Gets a packet to spawn a door.
*
* @param oid The door's object ID.
* @param oid The door's owner ID.
* @param pos The position of the door.
* @param town
* @param launched Already deployed the door.
* @return The remove door packet.
*/
public static byte[] spawnDoor(int oid, Point pos, boolean town) {
public static byte[] spawnDoor(int oid, Point pos, boolean launched) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(11);
mplew.writeShort(SendOpcode.SPAWN_DOOR.getValue());
mplew.writeBool(town);
mplew.writeBool(launched);
mplew.writeInt(oid);
mplew.writePos(pos);
return mplew.getPacket();
@@ -3230,11 +3229,25 @@ public class MaplePacketCreator {
mplew.writeShort(0x8b);
mplew.writeShort(1);
if (partychar.getDoors().size() > 0) {
for (MapleDoor doors : partychar.getDoors()) {
mplew.writeInt(doors.getTown().getId());
mplew.writeInt(doors.getTarget().getId());
mplew.writeInt(doors.getPosition().x);
mplew.writeInt(doors.getPosition().y);
boolean deployedPortal = false;
for (MapleDoor door : partychar.getDoors()) {
if(door.getOwnerId() == partychar.getId()) {
MapleDoorObject mdo = door.getTownDoor();
mplew.writeInt(mdo.getTo().getId());
mplew.writeInt(mdo.getFrom().getId());
mplew.writeInt(mdo.getPosition().x);
mplew.writeInt(mdo.getPosition().y);
deployedPortal = true;
}
}
if(!deployedPortal) {
mplew.writeInt(999999999);
mplew.writeInt(999999999);
mplew.writeInt(0);
mplew.writeInt(0);
}
} else {
mplew.writeInt(999999999);
@@ -3322,11 +3335,25 @@ public class MaplePacketCreator {
for (MaplePartyCharacter partychar : partymembers) {
if (partychar.getChannel() == forchannel && !leaving) {
if (partychar.getDoors().size() > 0) {
for (MapleDoor doors : partychar.getDoors()) {
lew.writeInt(doors.getTown().getId());
lew.writeInt(doors.getTarget().getId());
lew.writeInt(doors.getPosition().x);
lew.writeInt(doors.getPosition().y);
boolean deployedPortal = false;
for (MapleDoor door : partychar.getDoors()) {
if(door.getOwnerId() == partychar.getId()) {
MapleDoorObject mdo = door.getTownDoor();
lew.writeInt(mdo.getTown().getId());
lew.writeInt(mdo.getArea().getId());
lew.writeInt(mdo.getPosition().x);
lew.writeInt(mdo.getPosition().y);
deployedPortal = true;
}
}
if(!deployedPortal) {
lew.writeInt(999999999);
lew.writeInt(999999999);
lew.writeInt(0);
lew.writeInt(0);
}
} else {
lew.writeInt(999999999);