Merge pull request #114 from P0nk/area-boss-debuffs
Make area bosses killable
This commit is contained in:
@@ -46,8 +46,12 @@ function action(mode, type, selection) {
|
||||
}
|
||||
|
||||
if (status == 0) {
|
||||
cm.sendOk("A small focus of light lighting in the immersive darkness.");
|
||||
cm.dispose();
|
||||
cm.sendAcceptDecline("This is a small lamp with a switch. Would you like to turn it on?");
|
||||
return;
|
||||
} else if (status == 1) {
|
||||
cm.weakenAreaBoss(5090000, "You have turned the lamp on. Shade's strength will rapidly weaken due to the light.");
|
||||
}
|
||||
|
||||
cm.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,34 @@
|
||||
Control Device
|
||||
*/
|
||||
|
||||
var status;
|
||||
|
||||
function start() {
|
||||
cm.sendNext("This control device seems to be monitoring something...");
|
||||
cm.dispose();
|
||||
status = -1;
|
||||
action(1, 0, 0);
|
||||
}
|
||||
|
||||
function action(mode, type, selection) {
|
||||
if (mode == -1) {
|
||||
cm.dispose();
|
||||
} else {
|
||||
if (mode == 0 && status == 0) {
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
if (mode == 1) {
|
||||
status++;
|
||||
} else {
|
||||
status--;
|
||||
}
|
||||
|
||||
if (status == 0) {
|
||||
cm.sendAcceptDecline("You can operate the automated security system using the control unit. Would you like to deactivate the automated security system?");
|
||||
return;
|
||||
} else if (status == 1) {
|
||||
cm.weakenAreaBoss(7090000, "The automated security system has been deactivated. The intruder alarm will shut down.");
|
||||
}
|
||||
|
||||
cm.dispose();
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,34 @@
|
||||
Incomplete Magic Square
|
||||
*/
|
||||
|
||||
var status;
|
||||
|
||||
function start() {
|
||||
cm.sendNext("This chalkboard has some hard-founded studies annotated on it...");
|
||||
cm.dispose();
|
||||
status = -1;
|
||||
action(1, 0, 0);
|
||||
}
|
||||
|
||||
function action(mode, type, selection) {
|
||||
if (mode == -1) {
|
||||
cm.dispose();
|
||||
} else {
|
||||
if (mode == 0 && status == 0) {
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
if (mode == 1) {
|
||||
status++;
|
||||
} else {
|
||||
status--;
|
||||
}
|
||||
|
||||
if (status == 0) {
|
||||
cm.sendAcceptDecline("This Magic Pentagram is incomplete. Would you like to finish off the drawing of the Magic Pentagram?");
|
||||
return;
|
||||
} else if (status == 1) {
|
||||
cm.weakenAreaBoss(8090000, "The Magic Pentagram has been completed. The spell to eliminate Deet and Roi has been summoned.");
|
||||
}
|
||||
|
||||
cm.dispose();
|
||||
}
|
||||
}
|
||||
@@ -26,4 +26,6 @@
|
||||
function hit() {
|
||||
var map = rm.getMap();
|
||||
map.moveEnvironment("trap" + rm.getReactor().getName()[5], 1);
|
||||
}
|
||||
}
|
||||
|
||||
function act() {}
|
||||
@@ -19,8 +19,18 @@
|
||||
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/>.
|
||||
*/
|
||||
/**
|
||||
Tombstone in Forest of Dead Trees I
|
||||
MSEA reference: http://mymapleland.blogspot.com/2009/09/kill-lich-at-forest-of-dead-trees-i-to.html
|
||||
*/
|
||||
function hit() {
|
||||
rm.hitMonsterWithReactor(6090000, 14);
|
||||
if (rm.getReactor().getState() !== 0) {
|
||||
return
|
||||
}
|
||||
|
||||
rm.weakenAreaBoss(6090000, "As the tombstone lit up and vanished, Lich lost all his magic abilities.")
|
||||
}
|
||||
|
||||
function act() {}
|
||||
function act() {
|
||||
// If the chest is destroyed before Riche, killing him should yield no exp
|
||||
}
|
||||
@@ -19,8 +19,18 @@
|
||||
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/>.
|
||||
*/
|
||||
/**
|
||||
Tombstone in Forest of Dead Trees II
|
||||
MSEA reference: http://mymapleland.blogspot.com/2009/09/kill-lich-at-forest-of-dead-trees-i-to.html
|
||||
*/
|
||||
function hit() {
|
||||
rm.hitMonsterWithReactor(6090000, 14);
|
||||
if (rm.getReactor().getState() !== 0) {
|
||||
return
|
||||
}
|
||||
|
||||
rm.weakenAreaBoss(6090000, "As the tombstone lit up and vanished, Lich lost all his magic abilities.")
|
||||
}
|
||||
|
||||
function act() {}
|
||||
function act() {
|
||||
// If the chest is destroyed before Riche, killing him should yield no exp
|
||||
}
|
||||
@@ -19,8 +19,18 @@
|
||||
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/>.
|
||||
*/
|
||||
/**
|
||||
Tombstone in Forest of Dead Trees III
|
||||
MSEA reference: http://mymapleland.blogspot.com/2009/09/kill-lich-at-forest-of-dead-trees-i-to.html
|
||||
*/
|
||||
function hit() {
|
||||
rm.hitMonsterWithReactor(6090000, 14);
|
||||
if (rm.getReactor().getState() !== 0) {
|
||||
return
|
||||
}
|
||||
|
||||
rm.weakenAreaBoss(6090000, "As the tombstone lit up and vanished, Lich lost all his magic abilities.")
|
||||
}
|
||||
|
||||
function act() {}
|
||||
function act() {
|
||||
// If the chest is destroyed before Riche, killing him should yield no exp
|
||||
}
|
||||
@@ -19,8 +19,18 @@
|
||||
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/>.
|
||||
*/
|
||||
/**
|
||||
Tombstone in Forest of Dead Trees IV
|
||||
MSEA reference: http://mymapleland.blogspot.com/2009/09/kill-lich-at-forest-of-dead-trees-i-to.html
|
||||
*/
|
||||
function hit() {
|
||||
rm.hitMonsterWithReactor(6090000, 14);
|
||||
if (rm.getReactor().getState() !== 0) {
|
||||
return
|
||||
}
|
||||
|
||||
rm.weakenAreaBoss(6090000, "As the tombstone lit up and vanished, Lich lost all his magic abilities.")
|
||||
}
|
||||
|
||||
function act() {}
|
||||
function act() {
|
||||
// If the chest is destroyed before Riche, killing him should yield no exp
|
||||
}
|
||||
@@ -19,7 +19,6 @@
|
||||
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/>.
|
||||
*/
|
||||
function hit() {
|
||||
rm.hitMonsterWithReactor(6090001, 4);
|
||||
rm.getReactor().setEventState(Math.floor(Math.random() * 3));
|
||||
function act() {
|
||||
rm.weakenAreaBoss(6090001, "The light at the altar appeases the hatred of the Snow Witch. The force of the Witch has weakened.");
|
||||
}
|
||||
@@ -19,7 +19,6 @@
|
||||
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/>.
|
||||
*/
|
||||
function hit() {
|
||||
rm.hitMonsterWithReactor(6090001, 4);
|
||||
rm.getReactor().setEventState(Math.floor(Math.random() * 3));
|
||||
function act() {
|
||||
rm.weakenAreaBoss(6090001, "The light at the altar appeases the hatred of the Snow Witch. The force of the Witch has weakened.");
|
||||
}
|
||||
@@ -19,7 +19,6 @@
|
||||
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/>.
|
||||
*/
|
||||
function hit() {
|
||||
rm.hitMonsterWithReactor(6090001, 4);
|
||||
rm.getReactor().setEventState(Math.floor(Math.random() * 3));
|
||||
function act() {
|
||||
rm.weakenAreaBoss(6090001, "The light at the altar appeases the hatred of the Snow Witch. The force of the Witch has weakened.");
|
||||
}
|
||||
@@ -19,6 +19,6 @@
|
||||
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/>.
|
||||
*/
|
||||
function hit() {
|
||||
rm.hitMonsterWithReactor(6090003, 1);
|
||||
function act() {
|
||||
rm.weakenAreaBoss(6090003, "The grieving Scholar Ghost has been slightly appeased. You may be able to defeat the Scholar Ghost.");
|
||||
}
|
||||
@@ -25,6 +25,6 @@
|
||||
* Neo City Trash Can
|
||||
*/
|
||||
|
||||
function hit() {
|
||||
function act() {
|
||||
rm.dropItems(true, 2, 5, 10, 1);
|
||||
}
|
||||
@@ -25,6 +25,6 @@
|
||||
* Neo City Trash Can
|
||||
*/
|
||||
|
||||
function hit() {
|
||||
function act() {
|
||||
rm.dropItems(true, 2, 5, 10, 1);
|
||||
}
|
||||
@@ -26,4 +26,6 @@
|
||||
|
||||
function hit() {
|
||||
rm.sprayItems();
|
||||
}
|
||||
}
|
||||
|
||||
function act() {}
|
||||
@@ -2,8 +2,6 @@
|
||||
Yulete's Lab: Making the Reagent
|
||||
*/
|
||||
|
||||
function hit() {
|
||||
if (rm.getReactor().getState() == 4) {
|
||||
rm.dropItems();
|
||||
}
|
||||
function act() {
|
||||
rm.dropItems();
|
||||
}
|
||||
@@ -40,4 +40,6 @@ function hit() {
|
||||
rm.getMap().getReactorByName(reactname).hitReactor(rm.getClient());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function act() {}
|
||||
@@ -20,11 +20,11 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*2618000.js - MagatiaPQ Beaker
|
||||
/*2618001.js - MagatiaPQ Door
|
||||
*@author Ronan
|
||||
*/
|
||||
|
||||
function hit() {
|
||||
function act() {
|
||||
var eim = rm.getEventInstance();
|
||||
|
||||
var isAlcadno = eim.getIntProperty("isAlcadno");
|
||||
|
||||
@@ -20,11 +20,11 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*2618000.js - MagatiaPQ Beaker
|
||||
/*2618002.js - MagatiaPQ Door
|
||||
*@author Ronan
|
||||
*/
|
||||
|
||||
function hit() {
|
||||
function act() {
|
||||
var eim = rm.getEventInstance();
|
||||
|
||||
var isAlcadno = eim.getIntProperty("isAlcadno");
|
||||
|
||||
@@ -26,4 +26,9 @@
|
||||
|
||||
function hit() {
|
||||
rm.dropItems();
|
||||
}
|
||||
|
||||
function act() {
|
||||
// There's a timeout of 3 seconds to revert back from state 1 to 0.
|
||||
// Reactor is destroyed (state 2) and triggers this if dropping two Magic Devices at once, which shouldn't really happen.
|
||||
}
|
||||
3
scripts/reactor/2619003.js
Normal file
3
scripts/reactor/2619003.js
Normal file
@@ -0,0 +1,3 @@
|
||||
function act() {
|
||||
rm.weakenAreaBoss(6090004, "Rurumo has been poisoned. It may finally be defeatable!");
|
||||
}
|
||||
3
scripts/reactor/2619004.js
Normal file
3
scripts/reactor/2619004.js
Normal file
@@ -0,0 +1,3 @@
|
||||
function act() {
|
||||
rm.weakenAreaBoss(6090004, "Rurumo has been poisoned. It may finally be defeatable!");
|
||||
}
|
||||
3
scripts/reactor/2619005.js
Normal file
3
scripts/reactor/2619005.js
Normal file
@@ -0,0 +1,3 @@
|
||||
function act() {
|
||||
rm.weakenAreaBoss(6090004, "Rurumo has been poisoned. It may finally be defeatable!");
|
||||
}
|
||||
@@ -39,4 +39,6 @@ function hit() {
|
||||
//spawnJrBoss(mapObj.getMonsterById(8820023));
|
||||
|
||||
mapObj.killMonster(8820000);
|
||||
}
|
||||
}
|
||||
|
||||
function act() {}
|
||||
@@ -257,6 +257,7 @@ public class CommandsExecutor {
|
||||
addCommand("id", 2, IdCommand.class);
|
||||
addCommand("gachalist", GachaListCommand.class);
|
||||
addCommand("loot", LootCommand.class);
|
||||
addCommand("mobskill", MobSkillCommand.class);
|
||||
|
||||
commandsNameDesc.add(levelCommandsCursor);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package client.command.commands.gm2;
|
||||
|
||||
import client.Character;
|
||||
import client.Client;
|
||||
import client.command.Command;
|
||||
import server.life.MobSkill;
|
||||
import server.life.MobSkillFactory;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
public class MobSkillCommand extends Command {
|
||||
{
|
||||
setDescription("Apply a mob skill to all mobs on the map. Args: <mob skill id> <skill level>");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Client client, String[] params) {
|
||||
if (params.length < 2) {
|
||||
throw new IllegalArgumentException("Mob skill command requires two args: mob skill id and level");
|
||||
}
|
||||
|
||||
String skillId = params[0];
|
||||
String skillLevel = params[1];
|
||||
MobSkill mobSkill = MobSkillFactory.getMobSkill(Integer.parseInt(skillId), Integer.parseInt(skillLevel));
|
||||
if (mobSkill == null) {
|
||||
throw new IllegalArgumentException("Mob skill not found. Id: %s, level: %s".formatted(skillId, skillLevel));
|
||||
}
|
||||
|
||||
Character chr = client.getPlayer();
|
||||
chr.getMap().getAllMonsters().forEach(monster -> mobSkill.applyEffect(chr, monster, false, Collections.emptyList()));
|
||||
}
|
||||
}
|
||||
@@ -1185,4 +1185,30 @@ public class AbstractPlayerInteraction {
|
||||
public long getCurrentTime() {
|
||||
return Server.getInstance().getCurrentTime();
|
||||
}
|
||||
|
||||
public void weakenAreaBoss(int monsterId, String message) {
|
||||
MapleMap map = c.getPlayer().getMap();
|
||||
Monster monster = map.getMonsterById(monsterId);
|
||||
if (monster == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
applySealSkill(monster);
|
||||
applyReduceAvoid(monster);
|
||||
sendBlueNotice(map, message);
|
||||
}
|
||||
|
||||
private void applySealSkill(Monster monster) {
|
||||
MobSkill sealSkill = MobSkillFactory.getMobSkill(157, 1);
|
||||
sealSkill.applyEffect(monster);
|
||||
}
|
||||
|
||||
private void applyReduceAvoid(Monster monster) {
|
||||
MobSkill reduceAvoidSkill = MobSkillFactory.getMobSkill(155, 2);
|
||||
reduceAvoidSkill.applyEffect(monster);
|
||||
}
|
||||
|
||||
private void sendBlueNotice(MapleMap map, String message) {
|
||||
map.dropMessage(6, message);
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,6 @@ import client.Client;
|
||||
import client.inventory.Equip;
|
||||
import client.inventory.InventoryType;
|
||||
import client.inventory.Item;
|
||||
import config.YamlConfig;
|
||||
import constants.inventory.ItemConstants;
|
||||
import scripting.AbstractPlayerInteraction;
|
||||
import server.ItemInformationProvider;
|
||||
@@ -34,12 +33,10 @@ import server.TimerManager;
|
||||
import server.life.LifeFactory;
|
||||
import server.life.Monster;
|
||||
import server.maps.MapMonitor;
|
||||
import server.maps.MapleMap;
|
||||
import server.maps.Reactor;
|
||||
import server.maps.ReactorDropEntry;
|
||||
import server.partyquest.CarnivalFactory;
|
||||
import server.partyquest.CarnivalFactory.MCSkill;
|
||||
import tools.PacketCreator;
|
||||
|
||||
import javax.script.Invocable;
|
||||
import java.awt.*;
|
||||
@@ -284,25 +281,6 @@ public class ReactorActionManager extends AbstractPlayerInteraction {
|
||||
spawnNpc(npcId, pos, reactor.getMap());
|
||||
}
|
||||
|
||||
public void hitMonsterWithReactor(int id, int hitsToKill) { // until someone comes with a better solution, why not?
|
||||
int customTime = YamlConfig.config.server.MOB_REACTOR_REFRESH_TIME;
|
||||
if (customTime > 0) {
|
||||
reactor.setDelay(customTime);
|
||||
}
|
||||
|
||||
MapleMap map = reactor.getMap();
|
||||
Monster mm = map.getMonsterById(id);
|
||||
if (mm != null) {
|
||||
int damage = (int) Math.ceil(mm.getMaxHp() / hitsToKill);
|
||||
Character chr = this.getPlayer();
|
||||
|
||||
if (chr != null) {
|
||||
map.damageMonster(chr, mm, damage);
|
||||
map.broadcastMessage(PacketCreator.damageMonster(mm.getObjectId(), damage));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Reactor getReactor() {
|
||||
return reactor;
|
||||
}
|
||||
|
||||
@@ -122,6 +122,10 @@ public class MobSkill {
|
||||
service.registerOverallAction(monster.getMap().getId(), toRun, animationTime);
|
||||
}
|
||||
|
||||
public void applyEffect(Monster monster) {
|
||||
applyEffect(null, monster, false, Collections.emptyList());
|
||||
}
|
||||
|
||||
public void applyEffect(Character player, Monster monster, boolean skill, List<Character> banishPlayers) {
|
||||
Disease disease = null;
|
||||
Map<MonsterStatus, Integer> stats = new ArrayMap<>();
|
||||
@@ -243,6 +247,9 @@ public class MobSkill {
|
||||
case 156:
|
||||
stats.put(MonsterStatus.SPEED, x);
|
||||
break;
|
||||
case 157:
|
||||
stats.put(MonsterStatus.SEAL_SKILL, x);
|
||||
break;
|
||||
case 200: // summon
|
||||
int skillLimit = this.getLimit();
|
||||
MapleMap map = monster.getMap();
|
||||
|
||||
@@ -1448,7 +1448,7 @@ public class Monster extends AbstractLoadedLife {
|
||||
}
|
||||
|
||||
public boolean canUseSkill(MobSkill toUse, boolean apply) {
|
||||
if (toUse == null) {
|
||||
if (toUse == null || isBuffed(MonsterStatus.SEAL_SKILL)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -270,8 +270,11 @@ public class Reactor extends AbstractMapObject {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
state = stats.getNextState(state, b);
|
||||
if (stats.getNextState(state, b) == -1) {//end of reactor
|
||||
|
||||
this.state = stats.getNextState(state, b);
|
||||
byte nextState = stats.getNextState(state, b);
|
||||
boolean isInEndState = nextState < this.state;
|
||||
if (isInEndState) {//end of reactor
|
||||
if (reactorType < 100) {//reactor broken
|
||||
if (delay > 0) {
|
||||
map.destroyReactor(getObjectId());
|
||||
|
||||
Reference in New Issue
Block a user