GuildPQ Queue system + revamped Warp mechanic

Added a queue system for waiting guilds outside the GPQ area. Changed
the way players are transported through maps on non-portal passing
cases: if not defined, a spawn point is chosen randomly for each player.
This commit is contained in:
ronancpl
2017-06-13 20:47:58 -03:00
parent 7a8bba98ca
commit 81f9226286
82 changed files with 669 additions and 375 deletions

View File

@@ -1,4 +1,4 @@
#Mon, 12 Jun 2017 14:40:21 -0300
#Tue, 13 Jun 2017 20:04:33 -0300
C\:\\Nexon\\MapleSolaxia\\MapleSolaxiaV2=

BIN
dist/MapleSolaxia.jar vendored

Binary file not shown.

View File

@@ -309,4 +309,8 @@ Corre
Incrementada a documentação referente aos métodos usados nos scripts de eventos.
12 Junho 2016,
Correção de falha em criação de guilds, não atribuindo corretamente o título de mestre da guild ao criador.
Correção de falha em criação de guilds, não atribuindo corretamente o título de mestre da guild ao criador.
13 Junho 2016,
Mudança nas mecânicas de busca por portais ao transportar cada jogador: quando não for definido, escolhe-se um spawn point aleatoriamente.
Implementação de fila de espera para Guilds na GPQ (funciona em harmonia com o sistema de lobbys).

View File

@@ -5,17 +5,21 @@
<url>src/tools/MaplePacketCreator.java</url>
<bookmark id="1">
<name/>
<line>5939</line>
<line>5937</line>
<key/>
</bookmark>
</file>
</editor-bookmarks>
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
<group>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/event/OrbisPQ.js</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/event/0_EXAMPLE.js</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/event/BossRushPQ.js</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/event/GuildQuest.js</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/event/CWKPQ.js</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/npc/9040000.js</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/scripting/AbstractPlayerInteraction.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/npc/2040034.js</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/client/MapleCharacter.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/scripting/event/EventManager.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/channel/Channel.java</file>
</group>
</open-files>
</project-private>

View File

@@ -19,197 +19,266 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* @Author Lerk
*
* Guild Quest
*/
/**
* @author: Ronan
* @event: Sharenian Guild PQ
*/
var exitMap;
var waitingListCurrent = 0;
importPackage(Packages.world);
importPackage(Packages.client);
importPackage(Packages.server.maps);
importPackage(java.lang);
var isPq = true;
var minPlayers = 1, maxPlayers = 30;
var minLevel = 1, maxLevel = 200;
var entryMap = 990000000;
var exitMap = 990001100;
var recruitMap = 101030104;
var clearMap = 990001101;
var minMapId = 990000000;
var maxMapId = 990001101;
var waitTime = 3;
var eventTime = 90; // 90 minutes
var lobbyRange = [0, 0];
function init() {
em.setProperty("shuffleReactors","false");
em.setProperty("canEnter", "true");
em.setProperty("gpqOpen", "true");
setEventRequirements();
}
function monsterValue(eim, mobId) { //should only trigger on ergoth
if (mobId == 9300028) { //but, just to be safe...
var rubian = new Packages.client.inventory.Item(4001024, 0, 1);
var map = eim.getMapInstance(990000900);
var reactor = map.getReactorByName("boss");
map.spawnItemDrop(reactor, eim.getPlayers().get(0), rubian, reactor.getPosition(), true, false);
}
return -1;
function setLobbyRange() {
return lobbyRange;
}
function setup(eim) {
exitMap = em.getChannelServer().getMapFactory().getMap(990001100); //returning path
function setEventRequirements() {
var reqStr = "";
//shuffle reactors in two maps for stage 3
eim.getMapInstance(990000501).shuffleReactors();
eim.getMapInstance(990000502).shuffleReactors();
reqStr += "\r\n Number of players: ";
if(maxPlayers - minPlayers >= 1) reqStr += minPlayers + " ~ " + maxPlayers;
else reqStr += minPlayers;
//force no-respawn on certain map reactors
eim.getMapInstance(990000611).getReactorByName("").setDelay(-1);
eim.getMapInstance(990000620).getReactorByName("").setDelay(-1);
eim.getMapInstance(990000631).getReactorByName("").setDelay(-1);
eim.getMapInstance(990000641).getReactorByName("").setDelay(-1);
reqStr += "\r\n Level range: ";
if(maxLevel - minLevel >= 1) reqStr += minLevel + " ~ " + maxLevel;
else reqStr += minLevel;
//activate three minutes after start
eim.setProperty("entryTimestamp", Packages.java.lang.System.currentTimeMillis());
eim.setProperty("canEnter","true");
eim.schedule("begin", 60000);
eim.startEventTimer(60000);
reqStr += "\r\n Time limit: ";
reqStr += eventTime + " minutes";
em.setProperty("party", reqStr);
}
function begin(eim) {
eim.setProperty("canEnter","false");
var party = eim.getPlayers();
//if (party.size() < 6) { //not enough to start
// end(eim,"There are no longer enough players to continue, and those remaining shall be warped out.");
//} else {
var iter = party.iterator();
while (iter.hasNext()) {
iter.next().dropMessage(6,"The quest has begun.");
}
eim.startEventTimer(1000 * 60 * 90);
eim.schedule("timeOut", 1000 * 60 * 90);
//}
function setEventExclusives(eim) {
var itemSet = [1032033, 4001024, 4001025, 4001026, 4001027, 4001028, 4001029, 4001030, 4001031, 4001032, 4001033, 4001034, 4001035, 4001037];
eim.setExclusiveItems(itemSet);
}
function afterSetup(eim) {}
function setEventRewards(eim) {
var itemSet, itemQty, evLevel, expStages;
function timeOut(eim) {
end(eim, "Your allotted time to finish the quest has passed.");
evLevel = 1; //Rewards at clear PQ
itemSet = [];
itemQty = [];
eim.setEventRewards(evLevel, itemSet, itemQty);
expStages = []; //bonus exp given on CLEAR stage signal
eim.setEventClearStageExp(expStages);
}
function getEligibleParty(party) { //selects, from the given party, the team that is allowed to attempt this event
var eligible = [];
var hasLeader = false;
var guildId = 0;
if(party.size() > 0) {
var partyList = party.toArray();
for(var i = 0; i < party.size(); i++) {
var ch = partyList[i];
if(ch.isLeader()) {
guildId = ch.getGuildId();
break;
}
}
for(var i = 0; i < party.size(); i++) {
var ch = partyList[i];
if(ch.getMapId() == recruitMap && ch.getLevel() >= minLevel && ch.getLevel() <= maxLevel && ch.getGuildId() == guildId) {
if(ch.isLeader()) hasLeader = true;
eligible.push(ch);
}
}
}
if(!(hasLeader)) eligible = [];
return eligible;
}
function setup(level, lobbyid) {
var eim = em.newInstance("Guild" + lobbyid);
eim.setProperty("level", level);
eim.setProperty("guild", 0);
eim.setProperty("canJoin", 1);
eim.setProperty("statusStg1", -1);
eim.getInstanceMap(990000000).resetPQ(level);
eim.getInstanceMap(990000100).resetPQ(level);
eim.getInstanceMap(990000200).resetPQ(level);
eim.getInstanceMap(990000300).resetPQ(level);
eim.getInstanceMap(990000301).resetPQ(level);
eim.getInstanceMap(990000400).resetPQ(level);
eim.getInstanceMap(990000401).resetPQ(level);
eim.getInstanceMap(990000410).resetPQ(level);
eim.getInstanceMap(990000420).resetPQ(level);
eim.getInstanceMap(990000430).resetPQ(level);
eim.getInstanceMap(990000431).resetPQ(level);
eim.getInstanceMap(990000440).resetPQ(level);
eim.getInstanceMap(990000500).resetPQ(level);
eim.getInstanceMap(990000501).resetPQ(level);
eim.getInstanceMap(990000502).resetPQ(level);
eim.getInstanceMap(990000600).resetPQ(level);
eim.getInstanceMap(990000610).resetPQ(level);
eim.getInstanceMap(990000611).resetPQ(level);
eim.getInstanceMap(990000620).resetPQ(level);
eim.getInstanceMap(990000630).resetPQ(level);
eim.getInstanceMap(990000631).resetPQ(level);
eim.getInstanceMap(990000640).resetPQ(level);
eim.getInstanceMap(990000641).resetPQ(level);
eim.getInstanceMap(990000700).resetPQ(level);
eim.getInstanceMap(990000800).resetPQ(level);
eim.getInstanceMap(990000900).resetPQ(level);
eim.getInstanceMap(990001000).resetPQ(level);
eim.getInstanceMap(990001100).resetPQ(level);
eim.getInstanceMap(990001101).resetPQ(level);
respawnStages(eim);
var ts = Date.now();
ts += (60000 * waitTime);
eim.setProperty("entryTimestamp", "" + ts);
eim.startEventTimer(waitTime * 60000);
setEventRewards(eim);
setEventExclusives(eim);
return eim;
}
/*
function isTeamAllJobs(eim) {
var eventJobs = eim.getEventPlayersJobs();
var rangeJobs = parseInt('111110', 2);
return ((eventJobs & rangeJobs) == rangeJobs);
}
*/
function afterSetup(eim) {
eim.setProperty("guild", "" + eim.getLeader().getGuildId());
}
function respawnStages(eim) {}
function playerEntry(eim, player) {
var map = eim.getMapInstance(990000000);
player.changeMap(map, map.getPortal(0));
var map = eim.getMapInstance(entryMap);
player.changeMap(map, map.getPortal(0));
var texttt = "So, here is the brief. You guys should be warned that, once out on the fortress outskirts, anyone that would not be equipping the #b#t1032033##k will die instantly due to the deteriorated state of the air around there. That being said, once your team move out to the next stage, make sure to #bhit the glowing rocks#k in that region and #bequip the dropped item#k before advancing stages. That will protect you thoroughly from the air sickness. Good luck!";
player.getClient().getSession().write(Packages.tools.MaplePacketCreator.getNPCTalk(9040000, /*(byte)*/ 0, texttt, "00 00", /*(byte)*/ 0));
}
function playerRevive(eim, player) {
var returnMap = 990000200;
if (eim.getProperty("canEnter").equals("true")) {
returnMap = 990000000;
}
player.setHp(50);
player.setStance(0);
player.changeMap(eim.getMapInstance(returnMap), eim.getMapInstance(returnMap).getPortal(0));
return false;
}
function playerDead(eim, player) {
}
function playerDisconnected(eim, player) {
var party = eim.getPlayers();
if (player.getName().equals(eim.getProperty("leader"))) { //check for party leader
//boot all players and end
var iter = party.iterator();
while (iter.hasNext()) {
var pl = iter.next();
pl.dropMessage(6,"The leader of the instance has disconnected, and the remaining players shall be warped out.");
if (pl.equals(player)) {
removePlayer(eim, pl);
}
else {
eim.unregisterPlayer(pl);
pl.changeMap(exitMap, exitMap.getPortal(0));
}
function scheduledTimeout(eim) {
if(eim.getIntProperty("canJoin") == 1) {
eim.setProperty("canJoin", 0);
if(eim.checkEventTeamLacking(true, minPlayers)) {
end(eim);
} else {
eim.startEventTimer(eventTime * 60000);
}
} else {
end(eim);
}
eim.dispose();
}
else { //boot d/ced player and check if enough players left
removePlayer(eim, player);
if (party.size() < 6) { //five after player booted
end(eim,"There are no longer enough players to continue, and those remaining shall be warped out.");
}
}
}
function leftParty(eim, player) { //ignore for GQ
}
function disbandParty(eim) { //ignore for GQ
}
function playerUnregistered(eim, player) {}
function playerExit(eim, player) {
eim.unregisterPlayer(player);
player.changeMap(exitMap, exitMap.getPortal(0));
var party = eim.getPlayers();
if (party.size() < 6) { //five after player booted
end(eim,"There are no longer enough players to continue, and those remaining shall be warped out.");
}
}
function end(eim, msg) {
var iter = eim.getPlayers().iterator();
while (iter.hasNext()) {
var player = iter.next();
player.dropMessage(6,msg);
eim.unregisterPlayer(player);
player.changeMap(exitMap, exitMap.getPortal(0));
}
eim.dispose();
player.changeMap(exitMap, 0);
}
//for offline players
function removePlayer(eim, player) {
eim.unregisterPlayer(player);
player.getMap().removePlayer(player);
player.setMap(exitMap);
function changedMap(eim, player, mapid) {
if (mapid < minMapId || mapid > maxMapId) {
if (eim.isEventTeamLackingNow(true, minPlayers, player) && eim.getIntProperty("canJoin") == 0) {
eim.unregisterPlayer(player);
end(eim);
}
else
eim.unregisterPlayer(player);
}
}
function changedLeader(eim, leader) {}
function playerDead(eim, player) {}
function playerRevive(eim, player) { // player presses ok on the death pop up.
if (eim.isEventTeamLackingNow(true, minPlayers, player) && eim.getIntProperty("canJoin") == 0) {
eim.unregisterPlayer(player);
end(eim);
}
else
eim.unregisterPlayer(player);
}
function playerDisconnected(eim, player) {
if (eim.isEventTeamLackingNow(true, minPlayers, player) && eim.getIntProperty("canJoin") == 0) {
eim.unregisterPlayer(player);
end(eim);
}
else
eim.unregisterPlayer(player);
}
function leftParty(eim, player) {}
function disbandParty(eim) {
end(eim);
}
function monsterValue(eim, mobId) {
return 1;
}
function end(eim) {
var party = eim.getPlayers();
for (var i = 0; i < party.size(); i++) {
playerExit(eim, party.get(i));
}
eim.dispose();
}
function giveRandomEventReward(eim, player) {
eim.giveEventReward(player);
}
function clearPQ(eim) {
var iter = eim.getPlayers().iterator();
var bonusMap = eim.getMapInstance(990001000);
eim.startEventTimer(40000);
while (iter.hasNext()) {
var player = iter.next();
player.changeMap(bonusMap, bonusMap.getPortal(0));
}
eim.schedule("finish", 40000)
}
function finish(eim) {
var iter = eim.getPlayers().iterator();
while (iter.hasNext()) {
var player = iter.next();
eim.unregisterPlayer(player);
player.changeMap(exitMap, exitMap.getPortal(0));
}
eim.dispose();
eim.stopEventTimer();
eim.setEventCleared();
}
function monsterKilled(mob, eim) {}
function allMonstersDead(eim) {}
function cancelSchedule() {
}
function cancelSchedule() {}
function dispose(eim) {
em.schedule("openGPQ", 5000);
em.schedule("reopenGuildQuest", em.getLobbyDelay() * 1.5 * 1000);
}
function openGPQ() {
em.setProperty("gpqOpen", "true");
}
function timeOut() {
function reopenGuildQuest() {
em.attemptStartGuildInstance();
}

View File

@@ -46,6 +46,6 @@ function playerDisconnected(eim, player) {
function cancelSchedule() {}
function dispose() {
em.cancelSchedule();
function dispose(eim) {
eim.cancelSchedule();
}

View File

@@ -38,7 +38,7 @@ function action(mode, type, selection) {
if (status == 0) {
cm.sendNext("Hello, there! I'm Tommy. There's a Pig Town nearby where we're standing. The pigs there are rowdy and uncontrollable to the point where they have stolen numerous weapons from travelers. They were kicked out from their towns, and are currently hiding out at the Pig Town.");
} else if (status == 1) {
if(cm.isLeader()) {
if(cm.isEventLeader()) {
cm.sendYesNo("What do you think about making your way there with your party members and teach those rowdy pigs a lesson?");
}
else {

View File

@@ -35,7 +35,7 @@ function action(mode, type, selection) {
status++;
if (status == 0) {
if (cm.isLeader()) {
if (cm.isEventLeader()) {
cm.sendSimple("Growl! I am Growlie, always ready to protect this place. What brought you here?\r\n#b#L0# Please tell me what this place is all about.#l\r\n#L1# I have brought #t4001101#.#l\r\n#L2# I would like to leave this place.#l");
} else {
cm.sendSimple("Growl! I am Growlie, always ready to protect this place. What brought you here?\r\n#b#L0# Please tell me what this place is all about.#l\r\n#L2# I would like to leave this place.#l");

View File

@@ -44,7 +44,7 @@ function action(mode, type, selection) {
cm.dispose();
return;
}
if (!cm.isLeader()) {
if (!cm.isEventLeader()) {
if(cm.getPlayer().getMapId() == 920010000) {
cm.warp(920010000, 2);
cm.dispose();

View File

@@ -64,7 +64,7 @@ function action(mode, type, selection) {
cm.sendNext("Hurry, goto the next stage, the portal is open!");
}
else {
if (eim.isLeader(cm.getPlayer())) {
if (eim.isEventLeader(cm.getPlayer())) {
var state = eim.getIntProperty("statusStg" + stage);
if(state == -1) { // preamble

View File

@@ -64,7 +64,7 @@ function action(mode, type, selection) {
cm.sendNext("Hurry, goto the next stage, the portal is open!");
}
else {
if (eim.isLeader(cm.getPlayer())) {
if (eim.isEventLeader(cm.getPlayer())) {
var state = eim.getIntProperty("statusStg" + stage);
if(state == -1) { // preamble

View File

@@ -64,7 +64,7 @@ function action(mode, type, selection) {
cm.sendNext("Hurry, goto the next stage, the portal is open!");
}
else {
if (eim.isLeader(cm.getPlayer())) {
if (eim.isEventLeader(cm.getPlayer())) {
var state = eim.getIntProperty("statusStg" + stage);
if(state == -1) { // preamble

View File

@@ -64,7 +64,7 @@ function action(mode, type, selection) {
cm.sendNext("Hurry, goto the next stage, the portal is open!");
}
else {
if (eim.isLeader(cm.getPlayer())) {
if (eim.isEventLeader(cm.getPlayer())) {
var state = eim.getIntProperty("statusStg" + stage);
if(state == -1) { // preamble

View File

@@ -64,7 +64,7 @@ function action(mode, type, selection) {
cm.sendNext("Hurry, goto the next stage, the portal is open!");
}
else {
if (eim.isLeader(cm.getPlayer())) {
if (eim.isEventLeader(cm.getPlayer())) {
var state = eim.getIntProperty("statusStg" + stage);
if(state == -1) { // preamble

View File

@@ -67,7 +67,7 @@ function action(mode, type, selection) {
cm.sendNext("Hurry, goto the next stage, the portal is open!");
}
else {
if (eim.isLeader(cm.getPlayer())) {
if (eim.isEventLeader(cm.getPlayer())) {
var state = eim.getIntProperty("statusStg" + stage);
if(state == -1) { // preamble

View File

@@ -89,7 +89,7 @@ function action(mode, type, selection) {
cm.sendNext("Hurry, goto the next stage, the portal is open!");
}
else {
if (eim.isLeader(cm.getPlayer())) {
if (eim.isEventLeader(cm.getPlayer())) {
var state = eim.getIntProperty("statusStg" + stage);
if(state == -1) { // preamble

View File

@@ -58,7 +58,7 @@ function action(mode, type, selection) {
cm.sendNext("Hurry, goto the next stage, the portal is open!");
}
else {
if (eim.isLeader(cm.getPlayer())) {
if (eim.isEventLeader(cm.getPlayer())) {
var state = eim.getIntProperty("statusStg" + stage);
if(state == -1) { // preamble

View File

@@ -43,7 +43,7 @@ function action(mode, type, selection) {
if(cm.getMapId() == 925100500) {
if (status == 0) {
if(cm.isLeader()) {
if(cm.isEventLeader()) {
cm.sendOk("I have been saved thanks to your efforts! Thank you, guys!");
}
else {

View File

@@ -22,7 +22,7 @@ function action(mode, type, selection) {
return;
}
if (!cm.isLeader()) {
if (!cm.isEventLeader()) {
cm.sendYesNo("I wish for your leader to talk to me. Alternatively, you may be wanting to quit. Are you going to abandon this campaign?");
}
else {

View File

@@ -65,7 +65,7 @@ function action(mode, type, selection) {
cm.getEventInstance().setProperty("clear", "true");
}
if(cm.isLeader()) {
if(cm.isEventLeader()) {
cm.sendOk("Your party completed such an astounding feat coming this far, #byou have defeated all the bosses#k, congratulations! Now I will be handing your reward as you are being transported out...");
}
else {
@@ -73,7 +73,7 @@ function action(mode, type, selection) {
}
}
else if(state == 2) {
if(cm.isLeader()) {
if(cm.isEventLeader()) {
if(cm.getPlayer().getEventInstance().isEventTeamTogether()) {
cm.sendYesNo("Is your party ready to proceed to the next stages? Walk through the portal if you think you're done, the time is now.. Now, do you guys REALLY want to proceed?");
}
@@ -126,7 +126,7 @@ function action(mode, type, selection) {
if (cm.getParty() == null) {
cm.sendOk("You can participate in the party quest only if you are in a party.");
cm.dispose();
} else if(!cm.isLeader()) {
} else if(!cm.isEventLeader()) {
cm.sendOk("Your party leader must talk to me to start this party quest.");
cm.dispose();
} else {

View File

@@ -51,7 +51,7 @@ function action(mode, type, selection) {
if (cm.getParty() == null) {
cm.sendOk("You can participate in the party quest only if you are in a party.");
cm.dispose();
} else if(!cm.isLeader()) {
} else if(!cm.isEventLeader()) {
cm.sendOk("Your party leader must talk to me to start this party quest.");
cm.dispose();
} else {

View File

@@ -136,7 +136,7 @@ function action(mode, type, selection) {
}
}
else if(curMap == 103000800) { // stage 1
if(cm.isLeader()) {
if(cm.isEventLeader()) {
var numpasses = eim.getPlayerCount() - 1; // minus leader
if(cm.hasItem(4001008, numpasses)) {
@@ -184,7 +184,7 @@ function action(mode, type, selection) {
var nthtext = "2nd", nthobj = "ropes", nthverb = "hang", nthpos = "hang on the ropes too low";
var nextStgId = 103000802;
if(!eim.isLeader(cm.getPlayer())) {
if(!eim.isEventLeader(cm.getPlayer())) {
cm.sendOk("Follow the instructions given by your party leader to proceed through this stage.");
}
else if(eim.getProperty(stgProperty) == null) {
@@ -214,7 +214,7 @@ function action(mode, type, selection) {
var nthtext = "3rd", nthobj = "platforms", nthverb = "stand", nthpos = "stand too close to the edges";
var nextStgId = 103000803;
if(!eim.isLeader(cm.getPlayer())) {
if(!eim.isEventLeader(cm.getPlayer())) {
cm.sendOk("Follow the instructions given by your party leader to proceed through this stage.");
}
else if(eim.getProperty(stgProperty) == null) {
@@ -244,7 +244,7 @@ function action(mode, type, selection) {
var nthtext = "4th", nthobj = "barrels", nthverb = "stand", nthpos = "stand too close to the edges";
var nextStgId = 103000804;
if(!eim.isLeader(cm.getPlayer())) {
if(!eim.isEventLeader(cm.getPlayer())) {
cm.sendOk("Follow the instructions given by your party leader to proceed through this stage.");
}
else if(eim.getProperty(stgProperty) == null) {
@@ -267,7 +267,7 @@ function action(mode, type, selection) {
cm.dispose();
} else if(curMap == 103000804) {
if (eim.isLeader(cm.getPlayer())) {
if (eim.isEventLeader(cm.getPlayer())) {
if (cm.haveItem(4001008, 10)) {
cm.sendNext("Here's the portal that leads you to the last, bonus stage. It's a stage that allows you to defeat regular monsters a little easier. You'll be given a set amount of time to hunt as much as possible, but you can always leave the stage in the middle of it through the NPC. Again, congratulations on clearing all the stages. Let your party talk to me to receive their prizes as they are allowed to pass to the bonus stage. Take care...");
cm.gainItem(4001008, -10);

View File

@@ -1,122 +1,106 @@
/*
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/>.
*/
/*
* @Author Lerk
*
* Shuang, Victoria Road: Excavation Site<Camp> (101030104)
*
* Start of Guild Quest
/**
* @author: Ronan
* @npc: Shuang
* @map: Victoria Road: Excavation Site<Camp> (101030104)
* @func: Start Guild PQ
*/
var status = 0;
var GQItems = new Array(1032033, 4001024, 4001025, 4001026, 4001027, 4001028, 4001029, 4001030, 4001031, 4001032, 4001033, 4001034, 4001035, 4001037);
var sel;
var em = null;
function findLobby(guild) {
for (var iterator = em.getInstances().iterator(); iterator.hasNext();) {
var lobby = iterator.next();
if(lobby.getIntProperty("guild") == guild) {
if(lobby.getIntProperty("canJoin") == 1) return lobby;
else return null;
}
}
return null;
}
function start() {
cm.sendSimple("The path to Sharenian starts here. What would you like to do? #b\r\n#L0#Start a Guild Quest#l\r\n#L1#Join your guild's Guild Quest#l");
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 == 1) {
if (selection == 0) { //Start
if (cm.getPlayer().getGuildId() == 0 || cm.getPlayer().getGuildRank() >= 3) { //no guild or not guild master/jr. master
cm.sendNext("Only a Master or Jr. Master of the guild can start an instance.");
cm.dispose();
if (mode == -1) {
cm.dispose();
} else {
if (mode == 0 && status == 0) {
cm.dispose();
return;
}
else {
var em = cm.getEventManager("GuildQuest");
if (em == null)
cm.sendOk("This trial is currently under construction.");
else {
if(em.getProperty("gpqOpen").equals("false")) {
cm.sendOk("Another guild has already registered for the quest. Please try again later.");
} else if (getEimForGuild(em, cm.getPlayer().getGuildId()) != null)
cm.sendOk("Your guild already is already registered.");
else {
var guildId = cm.getPlayer().getGuildId();
var eim = em.newInstance(guildId);
em.startInstance(eim, cm.getPlayer().getName());
em.setProperty("gpqOpen", "false");
var map = eim.getMapInstance(990000000);
map.getPortal(5).setScriptName("guildwaitingenter");
map.getPortal(4).setScriptName("guildwaitingexit");
eim.registerPlayer(cm.getPlayer());
cm.guildMessage(5, "The guild has been entered into the Guild Quest. Please report to Shuang at the Excavation Camp on channel " + cm.getClient().getChannel() + ".");
for (var i = 0; i < GQItems.length; i++)
cm.removeAll(GQItems[i]);
if (mode == 1)
status++;
else
status--;
if (status == 0) {
em = cm.getEventManager("GuildQuest");
if(em == null) {
cm.sendOk("The Guild Quest has encountered an error.");
cm.dispose();
return;
}
}
cm.dispose();
}
}
else if (selection == 1) { //entering existing GQ
if (cm.getPlayer().getGuildId() == 0) { //no guild or not guild master/jr. master
cm.sendNext("You must be in a guild to join an instance.");
cm.dispose();
}
else {
var em = cm.getEventManager("GuildQuest");
if (em == null)
cm.sendOk("This trial is currently under construction.");
else {
var eim = getEimForGuild(em, cm.getPlayer().getGuildId());
if (eim == null)
cm.sendOk("Your guild is currently not registered for the Guild Quest.");
else {
if ("true".equals(eim.getProperty("canEnter"))) {
eim.registerPlayer(cm.getPlayer());
for (var i = 0; i < GQItems.length; i++)
cm.removeAll(GQItems[i]);
}
else
cm.sendOk("I'm sorry, but the guild has gone on without you. Try again later.");
cm.sendSimple("#e#b<Guild Quest: Sharenian Ruins>\r\n#k#n" + em.getProperty("party") + "\r\n\r\nThe path to Sharenian starts here. What would you like to do? #b\r\n#L0#Register your guild for Guild Quest#l\r\n#L1#Join your guild's Guild Quest#l\r\n#L2#I would like to hear more details.#l");
} else if (status == 1) {
sel = selection;
if (selection == 0) {
if(!cm.isGuildLeader()) {
cm.sendOk("Your guild master/jr.master must talk to me to register this guild quest.");
cm.dispose();
} else {
if(em.isQueueFull()) {
cm.sendOk("The queue on this channel is already full. Please be patient and try again after a while, or try on another channel.");
cm.dispose();
} else {
var qsize = em.getQueueSize();
cm.sendYesNo(((qsize > 0) ? "There is currently #r" + qsize + "#k guilds queued on. " : "") + "Do you wish for your guild to join this queue?");
}
}
} else if (selection == 1) {
if(cm.getPlayer().getGuildId() > 0) {
var eim = findLobby(cm.getPlayer().getGuildId());
if(eim == null) {
cm.sendOk("You don't have a guild registered and currently on strategy time to assist on this channel.");
} else {
if(cm.isLeader()) {
em.getEligibleParty(cm.getParty());
eim.registerParty(cm.getPlayer());
} else {
eim.registerPlayer(cm.getPlayer());
}
}
} else {
cm.sendOk("You can't participate in the guild quest if you don't pertain on a guild yourself!");
}
cm.dispose();
} else {
cm.sendOk("#e#b<Guild Quest: Sharenian Ruins>#k#n\r\n Team up with your guild members in an auspicious attempt to recover the Rubian from the skeleton's grasp, with teamwork overcoming many puzzles and challenges awaiting inside the Sharenian tombs. Great rewards can be obtained upon the instance completion, and Guild Points can be racked up for your Guild.");
cm.dispose();
}
}
cm.dispose();
} else if (status == 2) {
if (sel == 0) {
var entry = em.addGuildToQueue(cm.getPlayer().getGuildId(), cm.getPlayer().getId());
if(entry > 0) {
if(entry == 1) {
cm.sendOk("Your guild has been registered successfully. A message will pop on your chat keeping your guild aware about the registration status. Now, #rimportant#k: as the leader of this instance, #ryou must already be present on this channel#k the right moment your guild is called for the strategy time. #bThe missubmission of this action will void#k your guild registration as a whole, and the next guild will be called immediately. Must be noted also, that if you become absent from the end of the strategy time to any point on the duration of the instance, it will render the instance interrupted, and your guild will be moved out instantly, moving again the queue.");
}
} else if(entry == 0) {
cm.sendOk("The queue on this channel is already full. Please be patient and try again after a while, or try on another channel.");
} else {
cm.sendOk("Your guild is already queued on a channel. Please wait for your guild's turn.");
}
}
cm.dispose();
}
}
}
}
}
function getEimForGuild(em, id) {
var stringId = "" + id;
return em.getInstance(stringId);
}
function isGuildQuestOwner(em, id) {
var stringId = "" + id;
if(em.getProperty("curGuild").equals(stringId))
return true;
return false;
}

View File

@@ -51,7 +51,7 @@ function action(mode, type, selection) {
status--;
if (status == 0) {
if(cm.isLeader()) {
if(cm.isEventLeader()) {
if(!cm.getEventInstance().isEventTeamTogether()) {
cm.sendOk("One or more event team members is missing, please wait for them to reach here first.");
cm.dispose();

View File

@@ -19,24 +19,23 @@
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/>.
*/
/* @Author Lerk
/* @Author Lerk, Ronan
*
* Guild Quest Waiting Room - Entry Portal (map 990000000)
*/
function enter(pi) {
if (pi.getPlayer().getEventInstance() == null) {
pi.warp(101030104);
return true;
}
else {
if (pi.getPlayer().getEventInstance().getProperty("canEnter").equals("false")) {
var entryTime = pi.getPlayer().getEventInstance().getProperty("entryTimestamp");
var timeNow = Date.now();
var timeLeft = Math.ceil((entryTime - timeNow) / 1000);
if(timeLeft <= 0) {
pi.warp(990000100);
return true;
}
else { //cannot proceed while allies can still enter
pi.playerMessage(5, "The portal is not open yet.");
pi.playerMessage(5, "The portal will open in about " + timeLeft + " seconds.");
return false;
}
}
}

View File

@@ -20,8 +20,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
function enter(pi) {
if (pi.getPlayer().getEventInstance() != null) {
pi.getPlayer().getEventInstance().removePlayer(pi.getPlayer());
}
pi.warp(101030104);
return true;
}

View File

@@ -1,5 +1,5 @@
function enter(pi) {
if (pi.getPlayer().getParty() != null && pi.isLeader() && pi.haveItem(4001055,1)) {
if (pi.getPlayer().getParty() != null && pi.isEventLeader() && pi.haveItem(4001055,1)) {
pi.getEventInstance().warpEventTeam(920010100);
return true;
} else {

View File

@@ -1,6 +1,6 @@
function enter(pi) {
if ((pi.getMap().getMonsters().size() == 0 || pi.getMap().getMonsterById(9300183) != null) && (pi.getMap().getReactorByName("") == null || pi.getMap().getReactorByName("").getState() == 1)) {
if(pi.isLeader()) {
if(pi.isEventLeader()) {
pi.getEventInstance().clearPQ();
return true;
}

View File

@@ -27,7 +27,7 @@ BossRushPQ - Rest Spot portal
function enter(pi) {
var evLevel = ((pi.getMapId() - 1) % 5) + 1;
if(pi.getPlayer().getEventInstance().isLeader(pi.getPlayer()) && pi.getPlayer().getEventInstance().getPlayerCount() > 1) {
if(pi.getPlayer().getEventInstance().isEventLeader(pi.getPlayer()) && pi.getPlayer().getEventInstance().getPlayerCount() > 1) {
pi.message("Being the party leader, you cannot leave before your teammates leave first or you pass leadership.");
return false;
}

View File

@@ -1124,7 +1124,14 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
public void changeMap(int map) {
changeMap(map, 0);
MapleMap warpMap;
if (getEventInstance() != null) {
warpMap = getEventInstance().getMapInstance(map);
} else {
warpMap = client.getChannelServer().getMapFactory().getMap(map);
}
changeMap(warpMap, warpMap.getRandomPlayerSpawnpoint());
}
public void changeMap(int map, int portal) {
@@ -3343,6 +3350,10 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
public boolean isPartyLeader() {
return party.getLeaderId() == getId();
}
public boolean isGuildLeader() { // true on guild master or jr. master
return guildid > 0 && guildRank < 3;
}
public void leaveMap() {
controlled.clear();

View File

@@ -684,7 +684,7 @@ public class Commands {
case "debugnearestportal":
if(ServerConstants.USE_DEBUG) {
MaplePortal portal = player.getMap().findClosestPortal(player.getPosition());
if(portal != null) player.dropMessage(6, "Closest portal: " + portal.getId() + " '" + portal.getName() + "' --> toMap: " + portal.getTargetMapId() + " scriptname: '" + portal.getScriptName() + "' state: " + portal.getPortalState() + ".");
if(portal != null) player.dropMessage(6, "Closest portal: " + portal.getId() + " '" + portal.getName() + "' Type: " + portal.getType() + " --> toMap: " + portal.getTargetMapId() + " scriptname: '" + portal.getScriptName() + "' state: " + portal.getPortalState() + ".");
else player.dropMessage(6, "There is no portal on this map.");
}
break;
@@ -692,7 +692,7 @@ public class Commands {
case "debugnearestspawnpoint":
if(ServerConstants.USE_DEBUG) {
SpawnPoint sp = player.getMap().findClosestSpawnpoint(player.getPosition());
if(sp != null) player.dropMessage(6, "Closest spawn point: " + " Position: x " + sp.getPosition().getX() + " y " + sp.getPosition().getY() + " Spawns mobid: '" + ((sp.getMonster() != null) ? sp.getMonster().getId() : "null") + "' --> canSpawn: " + !sp.getDenySpawn() + " canSpawnRightNow: " + sp.shouldSpawn() + ".");
if(sp != null) player.dropMessage(6, "Closest mob spawn point: " + " Position: x " + sp.getPosition().getX() + " y " + sp.getPosition().getY() + " Spawns mobid: '" + ((sp.getMonster() != null) ? sp.getMonster().getId() : "null") + "' --> canSpawn: " + !sp.getDenySpawn() + " canSpawnRightNow: " + sp.shouldSpawn() + ".");
else player.dropMessage(6, "There is no mob spawn point on this map.");
}
break;

View File

@@ -57,7 +57,7 @@ public class PlayerStorage {
public MapleCharacter getCharacterByName(String name) {
rlock.lock();
try {
for (MapleCharacter chr : storage.values()) {
for (MapleCharacter chr : storage.values()) {
if (chr.getName().toLowerCase().equals(name.toLowerCase()))
return chr;
}

View File

@@ -296,14 +296,16 @@ public final class Channel {
private static String [] getEvents(){
List<String> events = new ArrayList<String>();
for (File file : new File("scripts/event").listFiles()){
events.add(file.getName().substring(0, file.getName().length() - 3));
events.add(file.getName().substring(0, file.getName().length() - 3));
}
return events.toArray(new String[0]);
}
public int getStoredVar(int key) {
if(storedVars.containsKey(key))
public int getStoredVar(int key) {
if(storedVars.containsKey(key)) {
return storedVars.get(key);
}
return 0;
}

View File

@@ -88,7 +88,7 @@ public final class ChangeMapHandler extends AbstractMaplePacketHandler {
chr.setStance(0);
}
chr.setHp(50);
chr.changeMap(to, to.getPortal(0));
chr.changeMap(to, to.getRandomPlayerSpawnpoint());
}
} else if (targetid != -1 && chr.isGM()) {
MapleMap to = c.getChannelServer().getMapFactory().getMap(targetid);

View File

@@ -37,6 +37,8 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.Set;
import java.util.HashSet;
import net.server.PlayerStorage;
import net.server.Server;
@@ -65,6 +67,7 @@ public class World {
private Map<Integer, MapleFamily> families = new LinkedHashMap<>();
private Map<Integer, MapleGuildSummary> gsStore = new HashMap<>();
private PlayerStorage players = new PlayerStorage();
private Set<Integer> queuedGuilds = new HashSet<>();
public World(int world, int flag, String eventmsg, int exprate, int droprate, int mesorate, int bossdroprate) {
this.id = world;
@@ -300,6 +303,18 @@ public class World {
}
}
public boolean isGuildQueued(int guildId) {
return queuedGuilds.contains(guildId);
}
public void putGuildQueued(int guildId) {
queuedGuilds.add(guildId);
}
public void removeGuildQueued(int guildId) {
queuedGuilds.remove(guildId);
}
public MapleParty createParty(MaplePartyCharacter chrfor) {
int partyid = runningPartyId.getAndIncrement();
MapleParty party = new MapleParty(partyid, chrfor);
@@ -364,13 +379,14 @@ public class World {
party.updateMember(target);
break;
case CHANGE_LEADER:
if(party.getLeader().getPlayer().getEventInstance() != null) {
party.getLeader().getPlayer().getEventInstance().changedLeader(target.getPlayer());
MapleCharacter mc = party.getLeader().getPlayer();
if(mc.getEventInstance() != null && mc.getEventInstance().isEventLeader(mc)) {
mc.getEventInstance().changedLeader(target.getPlayer());
}
party.setLeader(target);
break;
default:
System.out.println("Unhandeled updateParty operation " + operation.name());
System.out.println("Unhandled updateParty operation " + operation.name());
}
updateParty(party, operation, target);
}

View File

@@ -221,7 +221,7 @@ public class WZIMGFile {
System.out.println("Unknown UOL marker: " + uolmarker + " " + entry.getName());
}
} else {
throw new RuntimeException("Unhandeled extended type: " + type);
throw new RuntimeException("Unhandled extended type: " + type);
}
}
}

View File

@@ -528,6 +528,10 @@ public class AbstractPlayerInteraction {
public MapleParty getParty() {
return getPlayer().getParty();
}
public boolean isGuildLeader() {
return getPlayer().isGuildLeader();
}
public boolean isLeader() {
if(getParty() == null)
@@ -535,6 +539,10 @@ public class AbstractPlayerInteraction {
return getParty().getLeaderId() == getPlayer().getId();
}
public boolean isEventLeader() {
return getEventInstance() != null && getPlayer().getId() == getEventInstance().getLeaderId();
}
public void givePartyItems(int id, short quantity, List<MapleCharacter> party) {
for (MapleCharacter chr : party) {

View File

@@ -31,6 +31,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.HashSet;
import java.util.Set;
import java.util.Iterator;
import java.util.Properties;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
@@ -69,7 +70,8 @@ import tools.MaplePacketCreator;
* @author Matze, Ronan
*/
public class EventInstanceManager {
private List<MapleCharacter> chars = new ArrayList<>();
private Map<Integer, MapleCharacter> chars = new HashMap<>();
private int leaderId = -1;
private List<MapleMonster> mobs = new LinkedList<>();
private Map<MapleCharacter, Integer> killCount = new HashMap<>();
private EventManager em;
@@ -103,7 +105,7 @@ public class EventInstanceManager {
// registers all opened gates on the event. Will help late characters to encounter next stages gates already opened
private Set<Integer> openedGates = new HashSet<>();
// forces deletion of items not supposed to be holding out of the event, dealt on a player's leave moment.
// forces deletion of items not supposed to be held outside of the event, dealt on a player's leaving moment.
private Set<Integer> exclusiveItems = new HashSet<>();
public EventInstanceManager(EventManager em, String name) {
@@ -209,7 +211,7 @@ public class EventInstanceManager {
try {
wL.lock();
try {
chars.add(chr);
chars.put(chr.getId(), chr);
}
finally {
wL.unlock();
@@ -238,12 +240,15 @@ public class EventInstanceManager {
timeStarted = System.currentTimeMillis();
eventTime = time;
for(MapleCharacter chr: getPlayers()) chr.announce(MaplePacketCreator.getClock((int) (time / 1000)));
for(MapleCharacter chr: getPlayers()) {
chr.announce(MaplePacketCreator.getClock((int) (time / 1000)));
}
event_schedule = TimerManager.getInstance().schedule(new Runnable() {
public void run() {
try {
em.getIv().invokeFunction("scheduledTimeout", EventInstanceManager.this);
dismissEventTimer();
em.getIv().invokeFunction("scheduledTimeout", EventInstanceManager.this);
} catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
}
@@ -260,8 +265,8 @@ public class EventInstanceManager {
event_schedule = TimerManager.getInstance().schedule(new Runnable() {
public void run() {
try {
em.getIv().invokeFunction("scheduledTimeout", EventInstanceManager.this);
dismissEventTimer();
em.getIv().invokeFunction("scheduledTimeout", EventInstanceManager.this);
} catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
}
@@ -274,14 +279,6 @@ public class EventInstanceManager {
}
}
public void stopEventTimer() {
if(event_schedule != null) {
event_schedule.cancel(false);
event_schedule = null;
}
dismissEventTimer();
}
private void dismissEventTimer() {
for(MapleCharacter chr: getPlayers()) {
chr.getClient().getSession().write(MaplePacketCreator.removeClock());
@@ -292,6 +289,14 @@ public class EventInstanceManager {
timeStarted = 0;
}
public void stopEventTimer() {
if(event_schedule != null) {
event_schedule.cancel(false);
event_schedule = null;
}
dismissEventTimer();
}
public boolean isTimerStarted() {
return eventTime > 0 && timeStarted > 0;
}
@@ -300,6 +305,12 @@ public class EventInstanceManager {
return eventTime - (System.currentTimeMillis() - timeStarted);
}
public void registerParty(MapleCharacter chr) {
if(chr.isPartyLeader()) {
registerParty(chr.getParty(), chr.getMap());
}
}
public void registerParty(MapleParty party, MapleMap map) {
for (MaplePartyCharacter pc : party.getEligibleMembers()) {
MapleCharacter c = map.getCharacterById(pc.getId());
@@ -321,7 +332,7 @@ public class EventInstanceManager {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
}
chars.remove(chr);
chars.remove(chr.getId());
gridRemove(chr);
dropExclusiveItems(chr);
} finally {
@@ -344,7 +355,7 @@ public class EventInstanceManager {
public List<MapleCharacter> getPlayers() {
rL.lock();
try {
return new ArrayList<>(chars);
return new ArrayList<>(chars.values());
}
finally {
rL.unlock();
@@ -354,7 +365,7 @@ public class EventInstanceManager {
private List<MapleCharacter> getPlayerList() {
rL.lock();
try {
return new LinkedList<>(chars);
return new LinkedList<>(chars.values());
} finally {
rL.unlock();
}
@@ -478,7 +489,7 @@ public class EventInstanceManager {
wL.lock();
try {
for(MapleCharacter chr: chars) chr.setEventInstance(null);
for(MapleCharacter chr: chars.values()) chr.setEventInstance(null);
chars.clear();
mobs.clear();
@@ -612,6 +623,10 @@ public class EventInstanceManager {
return (chr.getParty().getLeaderId() == chr.getId());
}
public boolean isEventLeader(MapleCharacter chr) {
return (chr.getId() == getLeaderId());
}
public final MapleMap getInstanceMap(final int mapid) { //gets instance map from the channelserv
if (disposed) {
return getMapFactory().getMap(mapid);
@@ -829,10 +844,27 @@ public class EventInstanceManager {
return eventCleared;
}
private boolean isEventTeamLeaderOn() {
for(MapleCharacter chr: getPlayers()) {
if(chr.getId() == getLeaderId()) return true;
}
return false;
}
public final boolean checkEventTeamLacking(boolean testLeader, int minPlayers) {
if(eventCleared && getPlayerCount() > 1) return false;
if(!eventCleared && testLeader && !isEventTeamLeaderOn()) return true;
if(getPlayerCount() < minPlayers) return true;
return false;
}
public final boolean isEventTeamLackingNow(boolean testLeader, int minPlayers, MapleCharacter quitter) {
if(eventCleared && getPlayerCount() > 1) return false;
if(!eventCleared && testLeader && getLeader().getId() == quitter.getId()) return true;
if(!eventCleared && testLeader && getLeaderId() == quitter.getId()) return true;
if(getPlayerCount() <= minPlayers) return true;
return false;
@@ -842,12 +874,16 @@ public class EventInstanceManager {
rL.lock();
try {
if(chars.size() <= 1) return true;
int mapId = chars.get(0).getMapId();
for(int i = 1; i < chars.size(); i++) {
if(chars.get(i).getMapId() != mapId) return false;
Iterator<MapleCharacter> iterator = chars.values().iterator();
MapleCharacter mc = iterator.next();
int mapId = mc.getMapId();
for (; iterator.hasNext();) {
mc = iterator.next();
if(mc.getMapId() != mapId) return false;
}
return true;
} finally {
rL.unlock();
@@ -888,19 +924,33 @@ public class EventInstanceManager {
}
}
public final MapleCharacter getLeader() {
public final int getLeaderId() {
rL.lock();
try {
for (MapleCharacter chr : chars) {
if(chr.isPartyLeader()) return chr;
}
return null;
return leaderId;
} finally {
rL.unlock();
}
}
public MapleCharacter getLeader() {
rL.lock();
try {
return chars.get(leaderId);
} finally {
rL.unlock();
}
}
public final void setLeader(MapleCharacter chr) {
wL.lock();
try {
leaderId = chr.getId();
} finally {
wL.unlock();
}
}
public final void showWrongEffect() {
MapleMap map = getMapInstance(getLeader().getMapId());
map.broadcastMessage(MaplePacketCreator.showEffect("quest/party/wrong_kor"));

View File

@@ -33,7 +33,10 @@ import java.util.logging.Logger;
import javax.script.Invocable;
import javax.script.ScriptException;
import net.server.Server;
import net.server.world.World;
import net.server.channel.Channel;
import net.server.guild.MapleGuild;
import net.server.world.MapleParty;
import net.server.world.MaplePartyCharacter;
import server.TimerManager;
@@ -43,10 +46,10 @@ import server.life.MapleMonster;
import server.life.MapleLifeFactory;
import client.MapleCharacter;
import java.util.LinkedList;
import java.util.List;
import java.util.ArrayList;
import java.lang.reflect.Array;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@@ -57,20 +60,26 @@ import java.util.concurrent.locks.ReentrantLock;
public class EventManager {
private Invocable iv;
private Channel cserv;
private World wserv;
private Server server;
private Map<String, EventInstanceManager> instances = new HashMap<String, EventInstanceManager>();
private Map<String, Integer> instanceLocks = new HashMap<String, Integer>();
private final Queue<Integer> queuedGuilds = new LinkedList<>();
private final Map<Integer, Integer> queuedGuildLeaders = new HashMap<>();
private List<Boolean> openedLobbys;
private Properties props = new Properties();
private String name;
private ScheduledFuture<?> schedule = null;
private Lock l = new ReentrantLock();
private static final int limitGuilds = 10; // max numbers of guilds in queue for GPQ.
private static final int maxLobbys = 8; // an event manager holds up to this amount of concurrent lobbys
private static final long lobbyDelay = 10; // 10 seconds cooldown before reopening a lobby
public EventManager(Channel cserv, Invocable iv, String name) {
this.server = Server.getInstance();
this.iv = iv;
this.cserv = cserv;
this.wserv = server.getWorld(cserv.getWorld());
this.name = name;
this.openedLobbys = new ArrayList<>();
@@ -92,6 +101,10 @@ public class EventManager {
return intList;
}
public long getLobbyDelay() {
return lobbyDelay;
}
private List<Integer> getLobbyRange() {
try {
return convertToIntegerArray((List<Double>)iv.invokeFunction("setLobbyRange", (Object) null));
@@ -104,12 +117,12 @@ public class EventManager {
}
}
public void schedule(String methodName, long delay) {
schedule(methodName, null, delay);
public ScheduledFuture<?> schedule(String methodName, long delay) {
return schedule(methodName, null, delay);
}
public void schedule(final String methodName, final EventInstanceManager eim, long delay) {
schedule = TimerManager.getInstance().schedule(new Runnable() {
public ScheduledFuture<?> schedule(final String methodName, final EventInstanceManager eim, long delay) {
return TimerManager.getInstance().schedule(new Runnable() {
public void run() {
try {
iv.invokeFunction(methodName, eim);
@@ -120,11 +133,6 @@ public class EventManager {
}, delay);
}
public void cancelSchedule() {
if(schedule != null)
schedule.cancel(false);
}
public ScheduledFuture<?> scheduleAtTimestamp(final String methodName, long timestamp) {
return TimerManager.getInstance().scheduleAtTimestamp(new Runnable() {
public void run() {
@@ -250,9 +258,13 @@ public class EventManager {
public boolean startInstance(MapleExpedition exped) {
return startInstance(-1, exped);
}
public boolean startInstance(int lobbyId, MapleExpedition exped) {
return startInstance(lobbyId, exped, exped.getLeader());
}
//Expedition method: starts an expedition
public boolean startInstance(int lobbyId, MapleExpedition exped) {
public boolean startInstance(int lobbyId, MapleExpedition exped, MapleCharacter leader) {
try {
if(lobbyId == -1) {
lobbyId = availableLobbyInstance();
@@ -269,6 +281,7 @@ public class EventManager {
return false;
}
instanceLocks.put(eim.getName(), lobbyId);
eim.setLeader(leader);
eim.registerExpedition(exped);
exped.start();
@@ -286,6 +299,10 @@ public class EventManager {
}
public boolean startInstance(int lobbyId, MapleCharacter chr) {
return startInstance(lobbyId, chr, chr, 1);
}
public boolean startInstance(int lobbyId, MapleCharacter chr, MapleCharacter leader, int difficulty) {
try {
if(lobbyId == -1) {
lobbyId = availableLobbyInstance();
@@ -296,12 +313,13 @@ public class EventManager {
startLobbyInstance(lobbyId);
}
EventInstanceManager eim = (EventInstanceManager) (iv.invokeFunction("setup", (Object) null));
EventInstanceManager eim = (EventInstanceManager) (iv.invokeFunction("setup", difficulty, (lobbyId > -1) ? lobbyId : leader.getId()));
if(eim == null) {
if(lobbyId > -1) setLockLobby(lobbyId, false);
return false;
}
instanceLocks.put(eim.getName(), lobbyId);
eim.setLeader(leader);
eim.registerPlayer(chr);
iv.invokeFunction("afterSetup", eim);
@@ -318,6 +336,10 @@ public class EventManager {
}
public boolean startInstance(int lobbyId, MapleParty party, MapleMap map) {
return startInstance(lobbyId, party, map, party.getLeader().getPlayer());
}
public boolean startInstance(int lobbyId, MapleParty party, MapleMap map, MapleCharacter leader) {
try {
if(lobbyId == -1) {
lobbyId = availableLobbyInstance();
@@ -334,6 +356,7 @@ public class EventManager {
return false;
}
instanceLocks.put(eim.getName(), lobbyId);
eim.setLeader(leader);
eim.registerParty(party, map);
party.setEligibleMembers(null);
@@ -351,6 +374,10 @@ public class EventManager {
}
public boolean startInstance(int lobbyId, MapleParty party, MapleMap map, int difficulty) {
return startInstance(lobbyId, party, map, difficulty, party.getLeader().getPlayer());
}
public boolean startInstance(int lobbyId, MapleParty party, MapleMap map, int difficulty, MapleCharacter leader) {
try {
if(lobbyId == -1) {
lobbyId = availableLobbyInstance();
@@ -367,6 +394,7 @@ public class EventManager {
return false;
}
instanceLocks.put(eim.getName(), lobbyId);
eim.setLeader(leader);
eim.registerParty(party, map);
party.setEligibleMembers(null);
@@ -379,11 +407,19 @@ public class EventManager {
}
//non-PQ method for starting instance
public boolean startInstance(EventInstanceManager eim, String leader) {
return startInstance(-1, eim, leader);
public boolean startInstance(EventInstanceManager eim, String ldr) {
return startInstance(-1, eim, ldr);
}
public boolean startInstance(int lobbyId, EventInstanceManager eim, String leader) {
public boolean startInstance(EventInstanceManager eim, MapleCharacter ldr) {
return startInstance(-1, eim, ldr.getName(), ldr);
}
public boolean startInstance(int lobbyId, EventInstanceManager eim, String ldr) {
return startInstance(-1, eim, ldr, eim.getEm().getChannelServer().getPlayerStorage().getCharacterByName(ldr)); // things they make me do...
}
public boolean startInstance(int lobbyId, EventInstanceManager eim, String ldr, MapleCharacter leader) {
try {
if(lobbyId == -1) {
lobbyId = availableLobbyInstance();
@@ -399,9 +435,10 @@ public class EventManager {
return false;
}
instanceLocks.put(eim.getName(), lobbyId);
eim.setLeader(leader);
iv.invokeFunction("setup", eim);
eim.setProperty("leader", leader);
eim.setProperty("leader", ldr);
iv.invokeFunction("afterSetup", eim);
} catch (ScriptException | NoSuchMethodException ex) {
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
@@ -448,4 +485,115 @@ public class EventManager {
public MapleMonster getMonster(int mid) {
return(MapleLifeFactory.getMonster(mid));
}
private static String ordinal(int i) {
String[] sufixes = new String[] { "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" };
switch (i % 100) {
case 11:
case 12:
case 13:
return i + "th";
default:
return i + sufixes[i % 10];
}
}
private void exportReadyGuild(Integer guildId) {
MapleGuild mg = server.getGuild(guildId);
String callout = "Your guild has been registered to attend to the Sharenian Guild Quest at channel " + this.getChannelServer().getId()
+ " and JUST STARTED THE STRATEGY PHASE. After 3 minutes, no more guild members will be allowed to join the effort.";
mg.dropMessage(0, callout);
}
private void exportMovedQueueToGuild(Integer guildId, int place) {
MapleGuild mg = server.getGuild(guildId);
String callout = "Your guild has been registered to attend to the Sharenian Guild Quest at channel " + this.getChannelServer().getId()
+ " and is currently on the " + ordinal(place) + " place on the waiting queue.";
mg.dropMessage(0, callout);
}
private List<Integer> getNextGuildQueue() {
synchronized(queuedGuilds) {
Integer guildId = queuedGuilds.poll();
if(guildId == null) return null;
wserv.removeGuildQueued(guildId);
Integer leaderId = queuedGuildLeaders.remove(guildId);
exportReadyGuild(guildId);
int place = 1;
for(Integer i: queuedGuilds) {
exportMovedQueueToGuild(i, place);
place++;
}
List<Integer> list = new ArrayList<>(2);
list.add(guildId); list.add(leaderId);
return list;
}
}
public boolean isQueueFull() {
synchronized(queuedGuilds) {
return queuedGuilds.size() >= limitGuilds;
}
}
public int getQueueSize() {
synchronized(queuedGuilds) {
return queuedGuilds.size();
}
}
public byte addGuildToQueue(Integer guildId, Integer leaderId) {
if(wserv.isGuildQueued(guildId)) return -1;
if(!isQueueFull()) {
boolean canStartAhead;
synchronized(queuedGuilds) {
canStartAhead = queuedGuilds.isEmpty();
queuedGuilds.add(guildId);
wserv.putGuildQueued(guildId);
queuedGuildLeaders.put(guildId, leaderId);
int place = queuedGuilds.size();
exportMovedQueueToGuild(guildId, place);
}
if(canStartAhead) {
if(!attemptStartGuildInstance()) {
synchronized(queuedGuilds) {
queuedGuilds.add(guildId);
wserv.putGuildQueued(guildId);
queuedGuildLeaders.put(guildId, leaderId);
}
} else {
return 2;
}
}
return 1;
} else {
return 0;
}
}
public boolean attemptStartGuildInstance() {
MapleCharacter chr = null;
while(chr == null) {
List<Integer> guildInstance = getNextGuildQueue();
if(guildInstance == null) {
return false;
}
chr = cserv.getPlayerStorage().getCharacterById(guildInstance.get(1));
}
return startInstance(chr);
}
}

View File

@@ -749,7 +749,7 @@ public class MapleStatEffect {
return false;
}
}
applyto.changeMap(target);
applyto.changeMap(target, target.getRandomPlayerSpawnpoint());
} else {
return false;
}

View File

@@ -1640,7 +1640,7 @@ public class MapleMap {
public MaplePortal getRandomPlayerSpawnpoint() {
List<MaplePortal> spawnPoints = new ArrayList<>();
for (MaplePortal portal : portals.values()) {
if (portal.getType() >= 0 && portal.getType() <= 2) {
if (portal.getType() >= 0 && portal.getType() <= 1) {
spawnPoints.add(portal);
}
}
@@ -1653,7 +1653,7 @@ public class MapleMap {
double shortestDistance = Double.POSITIVE_INFINITY;
for (MaplePortal portal : portals.values()) {
double distance = portal.getPosition().distanceSq(from);
if (portal.getType() >= 0 && portal.getType() <= 2 && distance < shortestDistance && portal.getTargetMapId() == 999999999) {
if (portal.getType() >= 0 && portal.getType() <= 1 && distance < shortestDistance && portal.getTargetMapId() == 999999999) {
closest = portal;
shortestDistance = distance;
}

View File

@@ -2790,20 +2790,21 @@
</imgdir>
<imgdir name="4">
<string name="pn" value="st00"/>
<int name="pt" value="2"/>
<int name="pt" value="7"/>
<int name="x" value="428"/>
<int name="y" value="-482"/>
<int name="tm" value="101030104"/>
<string name="tn" value="st00"/>
<string name="script" value=""/>
<int name="tm" value="999999999"/>
<string name="tn" value=""/>
<string name="script" value="guildwaitingexit"/>
</imgdir>
<imgdir name="5">
<string name="pn" value="join00"/>
<int name="pt" value="5"/>
<int name="pt" value="8"/>
<int name="x" value="132"/>
<int name="y" value="161"/>
<int name="tm" value="990000100"/>
<string name="tn" value="st00"/>
<int name="tm" value="999999999"/>
<string name="tn" value=""/>
<string name="script" value="guildwaitingenter"/>
</imgdir>
</imgdir>
</imgdir>