Knights' Seal & I. MaxHP + Adherent mob status + Script point-warps
Fixed Seal skill not working for Blaze Wizard. Added a check against Seal skill on bosses. Reviewed improper usage of "random spawn point arrival" at several warps on scripts. Refactored CPQ modules fetching players from the channel storage, this should be unneeded after a recent update on the player object from MPC. Added door objects as a visible map object for the player server-side view component. Fixed a few scenarios where mobs would unexpectedly show up impervious to mob status. Fixed scenario where a player wouldn't receive disease informations from other players after changing maps. Fixed some magic-type skills (such as Magic Claw or Freeze) not displaying damage value for other players when the player is within melee-range from the mob. Added check for whether a given quest is scripted before trying to find the script. Fixed registering items onto MTS leading to loss of a few of its properties (expiration, item level, etc). Fixed "Improved MaxHP" skill gains not working for Thunderbreakers. Refactored pet autopot to also apply on HP/MP consumption by items/skills. Added portal sound effect on Mystic Doors.
This commit is contained in:
@@ -824,6 +824,7 @@ public class MapleStatEffect {
|
||||
break;
|
||||
case ILMage.SEAL:
|
||||
case FPMage.SEAL:
|
||||
case BlazeWizard.SEAL:
|
||||
monsterStatus.put(MonsterStatus.SEAL, Integer.valueOf(1));
|
||||
break;
|
||||
case Hermit.SHADOW_WEB: // shadow web
|
||||
@@ -1200,6 +1201,8 @@ public class MapleStatEffect {
|
||||
MapleMonster monster = (MapleMonster) mo;
|
||||
if (isDispel()) {
|
||||
monster.debuffMob(skill_.getId());
|
||||
} else if (isSeal() && monster.isBoss()) { // thanks IxianMace for noticing seal working on bosses
|
||||
// do nothing
|
||||
} else {
|
||||
if (makeChanceResult()) {
|
||||
monster.applyStatus(applyfrom, new MonsterStatusEffect(getMonsterStati(), skill_, null, false), isPoison(), getDuration());
|
||||
@@ -1705,6 +1708,10 @@ public class MapleStatEffect {
|
||||
private boolean isCrash() {
|
||||
return skill && (sourceid == DragonKnight.POWER_CRASH || sourceid == Crusader.ARMOR_CRASH || sourceid == WhiteKnight.MAGIC_CRASH);
|
||||
}
|
||||
|
||||
private boolean isSeal() {
|
||||
return skill && (sourceid == ILMage.SEAL || sourceid == FPMage.SEAL || sourceid == BlazeWizard.SEAL);
|
||||
}
|
||||
|
||||
private boolean isDispel() {
|
||||
return skill && (sourceid == Priest.DISPEL || sourceid == SuperGM.HEAL_PLUS_DISPEL);
|
||||
|
||||
@@ -101,6 +101,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
private List<Integer> stolenItems = new ArrayList<>(5);
|
||||
private int team;
|
||||
private int parentMobOid = 0;
|
||||
private int spawnEffect = 0;
|
||||
private final HashMap<Integer, AtomicLong> takenDamage = new HashMap<>();
|
||||
private ScheduledFuture<?> monsterItemDrop = null;
|
||||
private Runnable removeAfterAction = null;
|
||||
@@ -138,6 +139,14 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
|
||||
maxHpPlusHeal.set(hp.get());
|
||||
}
|
||||
|
||||
public void setSpawnEffect(int effect) {
|
||||
spawnEffect = effect;
|
||||
}
|
||||
|
||||
public int getSpawnEffect() {
|
||||
return spawnEffect;
|
||||
}
|
||||
|
||||
public void disableDrops() {
|
||||
this.dropsDisabled = true;
|
||||
@@ -1060,6 +1069,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
@Override
|
||||
public void sendDestroyData(MapleClient client) {
|
||||
client.announce(MaplePacketCreator.killMonster(getObjectId(), false));
|
||||
client.announce(MaplePacketCreator.killMonster(getObjectId(), true));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -102,10 +102,12 @@ public class MapleDoor {
|
||||
|
||||
for (MapleCharacter chr : targetChars) {
|
||||
areaDoor.sendDestroyData(chr.getClient());
|
||||
chr.removeVisibleMapObject(areaDoor);
|
||||
}
|
||||
|
||||
for (MapleCharacter chr : townChars) {
|
||||
townDoor.sendDestroyData(chr.getClient());
|
||||
chr.removeVisibleMapObject(townDoor);
|
||||
}
|
||||
|
||||
owner.removePartyDoor(false);
|
||||
@@ -115,6 +117,7 @@ public class MapleDoor {
|
||||
MapleDoor door = chr.getMainTownDoor();
|
||||
if (door != null) {
|
||||
townDoor.sendSpawnData(chr.getClient());
|
||||
chr.addVisibleMapObject(townDoor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,6 +87,8 @@ public class MapleDoorObject extends AbstractMapleMapObject {
|
||||
public void warp(final MapleCharacter chr) {
|
||||
MapleParty party = chr.getParty();
|
||||
if (chr.getId() == ownerId || (party != null && party.getMemberById(ownerId) != null)) {
|
||||
chr.announce(MaplePacketCreator.playPortalSound());
|
||||
|
||||
if(!inTown() && party == null) {
|
||||
chr.changeMap(to, getLinkedPortalId());
|
||||
} else {
|
||||
|
||||
@@ -2063,6 +2063,8 @@ public class MapleMap {
|
||||
|
||||
spos.y--;
|
||||
monster.setPosition(spos);
|
||||
monster.setSpawnEffect(effect);
|
||||
|
||||
spawnAndAddRangedMapObject(monster, new DelayedPacketCreation() {
|
||||
@Override
|
||||
public void sendPackets(MapleClient c) {
|
||||
@@ -2116,7 +2118,11 @@ public class MapleMap {
|
||||
spawnAndAddRangedMapObject(door, new DelayedPacketCreation() {
|
||||
@Override
|
||||
public void sendPackets(MapleClient c) {
|
||||
door.sendSpawnData(c, false);
|
||||
MapleCharacter chr = c.getPlayer();
|
||||
if (chr != null) {
|
||||
door.sendSpawnData(c, false);
|
||||
chr.addVisibleMapObject(door);
|
||||
}
|
||||
}
|
||||
}, new SpawnCondition() {
|
||||
@Override
|
||||
@@ -2465,22 +2471,23 @@ public class MapleMap {
|
||||
chr.setMapId(mapid);
|
||||
chr.updateActiveEffects();
|
||||
|
||||
MapScriptManager msm = MapScriptManager.getInstance();
|
||||
if (chrSize == 1) {
|
||||
if(!hasItemMonitor()) {
|
||||
startItemMonitor();
|
||||
aggroMonitor.startAggroCoordinator();
|
||||
}
|
||||
|
||||
if (onFirstUserEnter.length() != 0 && !chr.hasEntered(onFirstUserEnter, mapid) && MapScriptManager.getInstance().scriptExists(onFirstUserEnter, true)) {
|
||||
chr.enteredScript(onFirstUserEnter, mapid);
|
||||
MapScriptManager.getInstance().runMapScript(chr.getClient(), onFirstUserEnter, true);
|
||||
if (onFirstUserEnter.length() != 0) {
|
||||
msm.runMapScript(chr.getClient(), "onFirstUserEnter/" + onFirstUserEnter, true);
|
||||
}
|
||||
}
|
||||
if (onUserEnter.length() != 0) {
|
||||
if (onUserEnter.equals("cygnusTest") && (mapid < 913040000 || mapid > 913040006)) {
|
||||
chr.saveLocation("INTRO");
|
||||
}
|
||||
MapScriptManager.getInstance().runMapScript(chr.getClient(), onUserEnter, false);
|
||||
|
||||
msm.runMapScript(chr.getClient(), "onUserEnter/" + onUserEnter, false);
|
||||
}
|
||||
if (FieldLimit.CANNOTUSEMOUNTS.check(fieldLimit) && chr.getBuffedValue(MapleBuffStat.MONSTER_RIDING) != null) {
|
||||
chr.cancelEffectFromBuffStat(MapleBuffStat.MONSTER_RIDING);
|
||||
@@ -3020,8 +3027,8 @@ public class MapleMap {
|
||||
}
|
||||
}
|
||||
|
||||
private void sendObjectPlacement(MapleClient mapleClient) {
|
||||
MapleCharacter chr = mapleClient.getPlayer();
|
||||
private void sendObjectPlacement(MapleClient c) {
|
||||
MapleCharacter chr = c.getPlayer();
|
||||
Collection<MapleMapObject> objects;
|
||||
|
||||
objectRLock.lock();
|
||||
@@ -3033,7 +3040,7 @@ public class MapleMap {
|
||||
|
||||
for (MapleMapObject o : objects) {
|
||||
if (isNonRangedType(o.getType())) {
|
||||
o.sendSpawnData(mapleClient);
|
||||
o.sendSpawnData(c);
|
||||
} else if (o.getType() == MapleMapObjectType.MONSTER) {
|
||||
((MapleMonster) o).aggroUpdateController();
|
||||
} else if (o.getType() == MapleMapObjectType.SUMMON) {
|
||||
|
||||
@@ -50,7 +50,7 @@ public class MonsterCarnival {
|
||||
bluePortal = 1;
|
||||
}
|
||||
for (MaplePartyCharacter mpc : p1.getMembers()) {
|
||||
MapleCharacter mc = cs.getPlayerStorage().getCharacterById(mpc.getId());
|
||||
MapleCharacter mc = mpc.getPlayer();
|
||||
if (mc != null) {
|
||||
mc.setMonsterCarnival(this);
|
||||
mc.setTeam(0);
|
||||
@@ -64,7 +64,7 @@ public class MonsterCarnival {
|
||||
}
|
||||
}
|
||||
for (MaplePartyCharacter mpc : p2.getMembers()) {
|
||||
MapleCharacter mc = cs.getPlayerStorage().getCharacterById(mpc.getId());
|
||||
MapleCharacter mc = mpc.getPlayer();
|
||||
if (mc != null) {
|
||||
mc.setMonsterCarnival(this);
|
||||
mc.setTeam(1);
|
||||
@@ -213,7 +213,7 @@ public class MonsterCarnival {
|
||||
out = cs.getMapFactory().getMap(980000010);
|
||||
}
|
||||
for (MaplePartyCharacter mpc : leader1.getParty().getMembers()) {
|
||||
MapleCharacter mc = cs.getPlayerStorage().getCharacterById(mpc.getId());
|
||||
MapleCharacter mc = mpc.getPlayer();
|
||||
if (mc != null) {
|
||||
mc.resetCP();
|
||||
mc.setTeam(-1);
|
||||
@@ -224,7 +224,7 @@ public class MonsterCarnival {
|
||||
}
|
||||
}
|
||||
for (MaplePartyCharacter mpc : leader2.getParty().getMembers()) {
|
||||
MapleCharacter mc = cs.getPlayerStorage().getCharacterById(mpc.getId());
|
||||
MapleCharacter mc = mpc.getPlayer();
|
||||
if (mc != null) {
|
||||
mc.resetCP();
|
||||
mc.setTeam(-1);
|
||||
@@ -269,7 +269,7 @@ public class MonsterCarnival {
|
||||
Channel cs = map.getChannelServer();
|
||||
if (winningTeam == 0) {
|
||||
for (MaplePartyCharacter mpc : leader1.getParty().getMembers()) {
|
||||
MapleCharacter mc = cs.getPlayerStorage().getCharacterById(mpc.getId());
|
||||
MapleCharacter mc = mpc.getPlayer();
|
||||
if (mc != null) {
|
||||
mc.gainFestivalPoints(this.redTotalCP);
|
||||
mc.setMonsterCarnival(null);
|
||||
@@ -283,7 +283,7 @@ public class MonsterCarnival {
|
||||
}
|
||||
}
|
||||
for (MaplePartyCharacter mpc : leader2.getParty().getMembers()) {
|
||||
MapleCharacter mc = cs.getPlayerStorage().getCharacterById(mpc.getId());
|
||||
MapleCharacter mc = mpc.getPlayer();
|
||||
if (mc != null) {
|
||||
mc.gainFestivalPoints(this.blueTotalCP);
|
||||
mc.setMonsterCarnival(null);
|
||||
@@ -298,7 +298,7 @@ public class MonsterCarnival {
|
||||
}
|
||||
} else if (winningTeam == 1) {
|
||||
for (MaplePartyCharacter mpc : leader2.getParty().getMembers()) {
|
||||
MapleCharacter mc = cs.getPlayerStorage().getCharacterById(mpc.getId());
|
||||
MapleCharacter mc = mpc.getPlayer();
|
||||
if (mc != null) {
|
||||
mc.gainFestivalPoints(this.blueTotalCP);
|
||||
mc.setMonsterCarnival(null);
|
||||
@@ -312,7 +312,7 @@ public class MonsterCarnival {
|
||||
}
|
||||
}
|
||||
for (MaplePartyCharacter mpc : leader1.getParty().getMembers()) {
|
||||
MapleCharacter mc = cs.getPlayerStorage().getCharacterById(mpc.getId());
|
||||
MapleCharacter mc = mpc.getPlayer();
|
||||
if (mc != null) {
|
||||
mc.gainFestivalPoints(this.redTotalCP);
|
||||
mc.setMonsterCarnival(null);
|
||||
@@ -393,12 +393,10 @@ public class MonsterCarnival {
|
||||
if (chnl != chnl1) {
|
||||
throw new RuntimeException("Os lideres estao em canais diferentes.");
|
||||
}
|
||||
|
||||
Channel cs = map.getChannelServer();
|
||||
|
||||
map.killAllMonsters();
|
||||
for (MaplePartyCharacter mpc : leader1.getParty().getMembers()) {
|
||||
MapleCharacter mc;
|
||||
mc = cs.getPlayerStorage().getCharacterById(mpc.getId());
|
||||
MapleCharacter mc = mpc.getPlayer();
|
||||
if (mc != null) {
|
||||
if (redWin) {
|
||||
mc.getClient().announce(MaplePacketCreator.showEffect("quest/carnival/win"));
|
||||
@@ -412,8 +410,7 @@ public class MonsterCarnival {
|
||||
}
|
||||
}
|
||||
for (MaplePartyCharacter mpc : leader2.getParty().getMembers()) {
|
||||
MapleCharacter mc;
|
||||
mc = cs.getPlayerStorage().getCharacterById(mpc.getId());
|
||||
MapleCharacter mc = mpc.getPlayer();
|
||||
if (mc != null) {
|
||||
if (!redWin) {
|
||||
mc.getClient().announce(MaplePacketCreator.showEffect("quest/carnival/win"));
|
||||
|
||||
@@ -490,6 +490,8 @@ public class MapleQuest {
|
||||
ret = new BuffExceptRequirement(this, data);
|
||||
break;
|
||||
case SCRIPT:
|
||||
ret = new ScriptRequirement(this, data);
|
||||
break;
|
||||
case NORMAL_AUTO_START:
|
||||
case START:
|
||||
case END:
|
||||
@@ -561,7 +563,6 @@ public class MapleQuest {
|
||||
|
||||
public int getNpcRequirement(boolean complete) {
|
||||
Map<MapleQuestRequirementType, MapleQuestRequirement> reqs = !complete ? startReqs : completeReqs;
|
||||
|
||||
MapleQuestRequirement mqr = reqs.get(MapleQuestRequirementType.NPC);
|
||||
if (mqr != null) {
|
||||
return ((NpcRequirement) mqr).get();
|
||||
@@ -570,6 +571,17 @@ public class MapleQuest {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasScriptRequirement(boolean complete) {
|
||||
Map<MapleQuestRequirementType, MapleQuestRequirement> reqs = !complete ? startReqs : completeReqs;
|
||||
MapleQuestRequirement mqr = reqs.get(MapleQuestRequirementType.SCRIPT);
|
||||
|
||||
if (mqr != null) {
|
||||
return ((ScriptRequirement) mqr).get();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
This file is part of the HeavenMS MapleStory Server
|
||||
Copyleft (L) 2016 - 2018 RonanLana
|
||||
|
||||
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.quest.requirements;
|
||||
|
||||
import client.MapleCharacter;
|
||||
import provider.MapleData;
|
||||
import provider.MapleDataTool;
|
||||
import server.quest.MapleQuest;
|
||||
import server.quest.MapleQuestRequirementType;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Ronan
|
||||
*/
|
||||
public class ScriptRequirement extends MapleQuestRequirement {
|
||||
private boolean reqScript;
|
||||
|
||||
public ScriptRequirement(MapleQuest quest, MapleData data) {
|
||||
super(MapleQuestRequirementType.BUFF);
|
||||
processData(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processData(MapleData data) {
|
||||
reqScript = !MapleDataTool.getString(data, "").isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean check(MapleCharacter chr, Integer npcid) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean get() {
|
||||
return reqScript;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user