Boss Rush PQ Rewarding System + minor patches
Introducing BRPQ rewarding system (KPQ/LPQ clear-like) and patched issues regarding "no apparent party leader" after party leader disconnects and reconnects.
This commit is contained in:
@@ -1667,6 +1667,10 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
public void gainGachaExp(int gain) {
|
||||
updateSingleStat(MapleStat.GACHAEXP, gachaexp.addAndGet(gain));
|
||||
}
|
||||
|
||||
public void gainExp(int gain) {
|
||||
gainExp(gain, true, true);
|
||||
}
|
||||
|
||||
public void gainExp(int gain, boolean show, boolean inChat) {
|
||||
gainExp(gain, 0, show, inChat, true);
|
||||
@@ -2730,6 +2734,14 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
public boolean haveItem(int itemid) {
|
||||
return getItemQuantity(itemid, false) > 0;
|
||||
}
|
||||
|
||||
public boolean hasEmptySlot(int itemId) {
|
||||
return getInventory(MapleItemInformationProvider.getInstance().getInventoryType(itemId)).getNextFreeSlot() > -1;
|
||||
}
|
||||
|
||||
public boolean hasEmptySlot(byte invType) {
|
||||
return getInventory(MapleInventoryType.getByType(invType)).getNextFreeSlot() > -1;
|
||||
}
|
||||
|
||||
public void increaseGuildCapacity() { //hopefully nothing is null
|
||||
if (getMeso() < getGuild().getIncreaseGuildCost(getGuild().getCapacity())) {
|
||||
@@ -2787,7 +2799,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
}
|
||||
|
||||
public boolean isPartyLeader() {
|
||||
return party.getLeader() == party.getMemberById(getId());
|
||||
return party.getLeaderId() == getId();
|
||||
}
|
||||
|
||||
public void leaveMap() {
|
||||
|
||||
@@ -803,10 +803,12 @@ public class MapleClient {
|
||||
if (messengerid > 0) {
|
||||
worlda.leaveMessenger(messengerid, chrm);
|
||||
}
|
||||
/* if (fid > 0) {
|
||||
final MapleFamily family = worlda.getFamily(fid);
|
||||
family.
|
||||
}*/
|
||||
/*
|
||||
if (fid > 0) {
|
||||
final MapleFamily family = worlda.getFamily(fid);
|
||||
family.
|
||||
}
|
||||
*/
|
||||
for (MapleQuestStatus status : player.getStartedQuests()) { //This is for those quests that you have to stay logged in for a certain amount of time
|
||||
MapleQuest quest = status.getQuest();
|
||||
if (quest.getTimeLimit() > 0) {
|
||||
|
||||
@@ -37,6 +37,7 @@ public class ServerConstants {
|
||||
public static final boolean USE_REFRESH_RANK_MOVE = true;
|
||||
|
||||
public static final int MAX_AP = 999;
|
||||
public static final int MAX_EVENT_LEVELS = 8; //event has different levels of rewarding system
|
||||
public static final long BLOCK_DUEY_RACE_COND = (long)(0.5 * 1000);
|
||||
public static final long PET_LOOT_UPON_ATTACK = (long)(0.7 * 1000); //time the pet must wait before trying to pick items up.
|
||||
|
||||
@@ -57,8 +58,7 @@ public class ServerConstants {
|
||||
public static final double PET_AUTOHP_RATIO = 0.99; //will automatically consume potions until given ratio of the MaxHP/MaxMP is reached.
|
||||
public static final double PET_AUTOMP_RATIO = 0.99;
|
||||
|
||||
//Should bosses really use 1HP,1MP attacks in dojo?
|
||||
public static final boolean USE_DEADLY_DOJO = false;
|
||||
public static final boolean USE_DEADLY_DOJO = false; //Should bosses really use 1HP,1MP attacks in dojo?
|
||||
|
||||
//Rates
|
||||
public static final int EXP_RATE = 10;
|
||||
|
||||
@@ -27,14 +27,14 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class MapleParty {
|
||||
private MaplePartyCharacter leader;
|
||||
private int leaderId;
|
||||
private List<MaplePartyCharacter> members = new LinkedList<MaplePartyCharacter>();
|
||||
private List<MaplePartyCharacter> pqMembers = null;
|
||||
private int id;
|
||||
|
||||
public MapleParty(int id, MaplePartyCharacter chrfor) {
|
||||
this.leader = chrfor;
|
||||
this.members.add(this.leader);
|
||||
this.leaderId = chrfor.getId();
|
||||
this.members.add(chrfor);
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ public class MapleParty {
|
||||
}
|
||||
|
||||
public void setLeader(MaplePartyCharacter victim) {
|
||||
this.leader = victim;
|
||||
this.leaderId = victim.getId();
|
||||
}
|
||||
|
||||
public void updateMember(MaplePartyCharacter member) {
|
||||
@@ -95,9 +95,19 @@ public class MapleParty {
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getLeaderId() {
|
||||
return leaderId;
|
||||
}
|
||||
|
||||
public MaplePartyCharacter getLeader() {
|
||||
return leader;
|
||||
for(MaplePartyCharacter mpc: members) {
|
||||
if(mpc.getId() == leaderId) {
|
||||
return mpc;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -531,7 +531,7 @@ public class AbstractPlayerInteraction {
|
||||
if(getParty() == null)
|
||||
return false;
|
||||
|
||||
return getParty().getLeader().equals(getPlayer().getMPC());
|
||||
return getParty().getLeaderId() == getPlayer().getId();
|
||||
}
|
||||
|
||||
public void givePartyItems(int id, short quantity, List<MapleCharacter> party) {
|
||||
|
||||
@@ -46,13 +46,16 @@ import server.maps.MapleMap;
|
||||
import server.maps.MapleMapFactory;
|
||||
import tools.DatabaseConnection;
|
||||
import client.MapleCharacter;
|
||||
import constants.ItemConstants;
|
||||
import constants.ServerConstants;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import scripting.AbstractPlayerInteraction;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Matze
|
||||
* @author Matze, Ronan
|
||||
*/
|
||||
public class EventInstanceManager {
|
||||
private List<MapleCharacter> chars = new ArrayList<>();
|
||||
@@ -72,7 +75,12 @@ public class EventInstanceManager {
|
||||
private final WriteLock wL = mutex.writeLock();
|
||||
private ScheduledFuture<?> event_schedule = null;
|
||||
private boolean disposed = false;
|
||||
|
||||
|
||||
// multi-leveled PQ rewards!
|
||||
private Map<Integer, List<Integer>> collectionSet = new HashMap<>(ServerConstants.MAX_EVENT_LEVELS);
|
||||
private Map<Integer, List<Integer>> collectionQty = new HashMap<>(ServerConstants.MAX_EVENT_LEVELS);
|
||||
private Map<Integer, Integer> collectionExp = new HashMap<>(ServerConstants.MAX_EVENT_LEVELS);
|
||||
|
||||
public EventInstanceManager(EventManager em, String name) {
|
||||
this.em = em;
|
||||
this.name = name;
|
||||
@@ -144,16 +152,51 @@ public class EventInstanceManager {
|
||||
eventTime = time;
|
||||
|
||||
event_schedule = TimerManager.getInstance().schedule(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
em.getIv().invokeFunction("scheduledTimeout", EventInstanceManager.this);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
|
||||
public void run() {
|
||||
try {
|
||||
em.getIv().invokeFunction("scheduledTimeout", EventInstanceManager.this);
|
||||
dismissEventTimer();
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, time);
|
||||
}
|
||||
|
||||
public void addEventTimer(long time) {
|
||||
if(event_schedule != null) {
|
||||
if(event_schedule.cancel(false)) {
|
||||
long nextTime = getTimeLeft() + time;
|
||||
eventTime += time;
|
||||
|
||||
event_schedule = TimerManager.getInstance().schedule(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
em.getIv().invokeFunction("scheduledTimeout", EventInstanceManager.this);
|
||||
dismissEventTimer();
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
}, nextTime);
|
||||
}
|
||||
}
|
||||
else {
|
||||
startEventTimer(time);
|
||||
}
|
||||
}
|
||||
|
||||
public void cancelEventTimer() {
|
||||
if(event_schedule != null) event_schedule.cancel(false);
|
||||
dismissEventTimer();
|
||||
}
|
||||
|
||||
private void dismissEventTimer() {
|
||||
event_schedule = null;
|
||||
eventTime = 0;
|
||||
timeStarted = 0;
|
||||
}
|
||||
|
||||
public boolean isTimerStarted() {
|
||||
return eventTime > 0 && timeStarted > 0;
|
||||
}
|
||||
@@ -318,7 +361,7 @@ public class EventInstanceManager {
|
||||
wL.unlock();
|
||||
}
|
||||
|
||||
if(event_schedule != null) event_schedule.cancel(true);
|
||||
if(event_schedule != null) event_schedule.cancel(false);
|
||||
|
||||
mobs.clear();
|
||||
killCount.clear();
|
||||
@@ -388,9 +431,9 @@ public class EventInstanceManager {
|
||||
return props.getProperty(key);
|
||||
}
|
||||
|
||||
public Properties getProperties(){
|
||||
return props;
|
||||
}
|
||||
public Properties getProperties(){
|
||||
return props;
|
||||
}
|
||||
|
||||
public void leftParty(MapleCharacter chr) {
|
||||
try {
|
||||
@@ -425,7 +468,7 @@ public class EventInstanceManager {
|
||||
}
|
||||
|
||||
public boolean isLeader(MapleCharacter chr) {
|
||||
return (chr.getParty().getLeader().getId() == chr.getId());
|
||||
return (chr.getParty().getLeaderId() == chr.getId());
|
||||
}
|
||||
|
||||
public final MapleMap setInstanceMap(final int mapid) { //gets instance map from the channelserv
|
||||
@@ -468,4 +511,106 @@ public class EventInstanceManager {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private List<Integer> convertToIntegerArray(List<Double> list) {
|
||||
List<Integer> intList = new ArrayList<>();
|
||||
for(Double d: list) intList.add(d.intValue());
|
||||
|
||||
return intList;
|
||||
}
|
||||
|
||||
public final void setEventRewards(List<Double> rwds, List<Double> qtys) {
|
||||
setEventRewards(1, rwds, qtys);
|
||||
}
|
||||
|
||||
public final void setEventRewards(int eventLevel, List<Double> rwds, List<Double> qtys) {
|
||||
setEventRewards(eventLevel, rwds, qtys, 0);
|
||||
}
|
||||
|
||||
public final void setEventRewards(int eventLevel, List<Double> rwds, List<Double> qtys, int expGiven) {
|
||||
// fixed EXP will be rewarded at the same time the random item is given
|
||||
|
||||
if(eventLevel <= 0 || eventLevel > ServerConstants.MAX_EVENT_LEVELS) return;
|
||||
eventLevel--; //event level starts from 1
|
||||
|
||||
List<Integer> rewardIds = convertToIntegerArray(rwds);
|
||||
List<Integer> rewardQtys = convertToIntegerArray(qtys);
|
||||
|
||||
//rewardsSet and rewardsQty hold temporary values
|
||||
collectionSet.put(eventLevel, rewardIds);
|
||||
collectionQty.put(eventLevel, rewardQtys);
|
||||
collectionExp.put(eventLevel, expGiven);
|
||||
}
|
||||
|
||||
private byte getRewardListRequirements(int level) {
|
||||
if(level >= collectionSet.size()) return 0;
|
||||
|
||||
byte rewardTypes = 0;
|
||||
List<Integer> list = collectionSet.get(level);
|
||||
|
||||
for (Integer itemId : list) {
|
||||
rewardTypes |= (1 << ItemConstants.getInventoryType(itemId).getType());
|
||||
}
|
||||
|
||||
return rewardTypes;
|
||||
}
|
||||
|
||||
private boolean hasRewardSlot(MapleCharacter player, int eventLevel) {
|
||||
byte listReq = getRewardListRequirements(eventLevel); //gets all types of items present in the event reward list
|
||||
|
||||
//iterating over all valid inventory types
|
||||
for(byte type = 1; type <= 5; type++) {
|
||||
if((listReq >> type) % 2 == 1 && !player.hasEmptySlot(type))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public final boolean giveEventReward(MapleCharacter player) {
|
||||
return giveEventReward(player, 1);
|
||||
}
|
||||
|
||||
//gives out EXP & a random item in a similar fashion of when clearing KPQ, LPQ, etc.
|
||||
public final boolean giveEventReward(MapleCharacter player, int eventLevel) {
|
||||
eventLevel--; //event level starts counting from 1
|
||||
if(eventLevel >= collectionSet.size()) return true;
|
||||
|
||||
List<Integer> rewardsSet = collectionSet.get(eventLevel);
|
||||
List<Integer> rewardsQty = collectionQty.get(eventLevel);
|
||||
|
||||
Integer rewardExp = collectionExp.get(eventLevel);
|
||||
if(rewardExp == null) rewardExp = 0;
|
||||
|
||||
if(rewardsSet == null || rewardsSet.isEmpty()) {
|
||||
if(rewardExp > 0) player.gainExp(rewardExp);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!hasRewardSlot(player, eventLevel)) return false;
|
||||
|
||||
AbstractPlayerInteraction api = new AbstractPlayerInteraction(player.getClient());
|
||||
int rnd = (int)Math.floor(Math.random() * rewardsSet.size());
|
||||
|
||||
api.gainItem(rewardsSet.get(rnd), rewardsQty.get(rnd).shortValue());
|
||||
if(rewardExp > 0) player.gainExp(rewardExp);
|
||||
return true;
|
||||
}
|
||||
|
||||
public final boolean isEventTeamTogether() {
|
||||
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;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public final void warpEventTeam(int warpTo) {
|
||||
for (MapleCharacter chr : chars) {
|
||||
chr.changeMap(warpTo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ public class EventManager {
|
||||
|
||||
public void cancelSchedule() {
|
||||
if(schedule != null)
|
||||
schedule.cancel(true);
|
||||
schedule.cancel(false);
|
||||
}
|
||||
|
||||
public ScheduledFuture<?> scheduleAtTimestamp(final String methodName, long timestamp) {
|
||||
|
||||
Reference in New Issue
Block a user