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:
ronancpl
2019-09-13 03:04:44 -03:00
parent 259c2e5ba1
commit e169971384
115 changed files with 783 additions and 540 deletions
+7
View File
@@ -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);
+10
View File
@@ -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
+3
View File
@@ -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);
}
}
}
+2
View File
@@ -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 {
+15 -8
View File
@@ -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) {
+11 -14
View File
@@ -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"));
+13 -1
View File
@@ -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;
}
}