Code Coupons + Worldmap update + Mini-games + Player Interaction wrap
Fixed several cases on the Cash Shop that would freeze some player actions when triggered, requiring exit Cash Shop to unstuck. Implemented Code Coupons, supporting several items bundled on the same code, and also devised a way to automate code generation. Added a current status on-demand option on the Buyback command. Info such as "current fee" or "time remaining" are available now. Reviewed several cases where non-owned items would get stacked with owner-tagged items. Added Door support for Happyville, Crimsonwood Keep. Added worldmap tooltip support for some maps in Masteria's C. Keep and H. House. Added Masteria region to the world map. C. Keep interiors no longer relocates players to entrance after actions such as logout. Overhauled minigame mechanics: from player boxes tooltip and in-match improvements to deploy different minigame types, accordingly with item description or player choice. Fixed Amoria outskirts not relocating players to city after getting KO'ed. Fixed issues with pets, rings and cash items being assigned the same cash unique ids leading to some quirks on the cash shop inventory. Fixed an issue with the recently added HP/MP ratio update, arbitrarily taking off 1 point in certain cases. Answer positions on the explorer's 3rd job quiz are now randomed. Fixed several issues that showed up when the bcrypt system is disabled. DOT from maps such as El Nath and Aqua Road now procs at a 5sec interval, GMS-like. Improved performance of Whodrops and Search commands. Concurrently protected player interaction handlers, thus mitigating several exploits on these lines. Adjusted several expedition timers, such as Horntail, now having a more sane deadline. Concurrently protected chair modules. Fixed "seduce" debuff not working on chairs.
This commit is contained in:
@@ -582,4 +582,9 @@ public class CashShop {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Item generateCouponItem(int itemId, short quantity) {
|
||||
CashItem it = new CashItem(77777777, itemId, 7777, ItemConstants.isPet(itemId) ? 30 : 0, quantity, true);
|
||||
return it.toItem();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -373,6 +373,7 @@ public class MapleItemInformationProvider {
|
||||
private static short getExtraSlotMaxFromPlayer(MapleClient c, int itemId) {
|
||||
short ret = 0;
|
||||
|
||||
// thanks GMChuck for detecting player sensitive data being cached into getSlotMax
|
||||
if (ItemConstants.isThrowingStar(itemId)) {
|
||||
if(c.getPlayer().getJob().isA(MapleJob.NIGHTWALKER1)) {
|
||||
ret += c.getPlayer().getSkillLevel(SkillFactory.getSkill(NightWalker.CLAW_MASTERY)) * 10;
|
||||
@@ -658,11 +659,11 @@ public class MapleItemInformationProvider {
|
||||
}
|
||||
|
||||
private static short getMaximumShortMaxIfOverflow(int value1, int value2) {
|
||||
return (short)Math.min(Short.MAX_VALUE, Math.max(value1, value2));
|
||||
return (short) Math.min(Short.MAX_VALUE, Math.max(value1, value2));
|
||||
}
|
||||
|
||||
private static short getShortMaxIfOverflow(int value) {
|
||||
return (short)Math.min(Short.MAX_VALUE, value);
|
||||
return (short) Math.min(Short.MAX_VALUE, value);
|
||||
}
|
||||
|
||||
private static short chscrollRandomizedStat(int range) {
|
||||
|
||||
@@ -94,12 +94,12 @@ public class MapleShop {
|
||||
if (c.getPlayer().getMeso() >= amount) {
|
||||
if (MapleInventoryManipulator.checkSpace(c, itemId, quantity, "")) {
|
||||
if (!ItemConstants.isRechargeable(itemId)) { //Pets can't be bought from shops
|
||||
MapleInventoryManipulator.addById(c, itemId, quantity);
|
||||
MapleInventoryManipulator.addById(c, itemId, quantity, "", -1);
|
||||
c.getPlayer().gainMeso(-amount, false);
|
||||
} else {
|
||||
short slotMax = ii.getSlotMax(c, item.getItemId());
|
||||
quantity = slotMax;
|
||||
MapleInventoryManipulator.addById(c, itemId, quantity);
|
||||
MapleInventoryManipulator.addById(c, itemId, quantity, "", -1);
|
||||
c.getPlayer().gainMeso(-item.getPrice(), false);
|
||||
}
|
||||
c.announce(MaplePacketCreator.shopTransaction((byte) 0));
|
||||
@@ -115,12 +115,12 @@ public class MapleShop {
|
||||
if (c.getPlayer().getInventory(MapleInventoryType.ETC).countById(4310000) >= amount) {
|
||||
if (MapleInventoryManipulator.checkSpace(c, itemId, quantity, "")) {
|
||||
if (!ItemConstants.isRechargeable(itemId)) {
|
||||
MapleInventoryManipulator.addById(c, itemId, quantity);
|
||||
MapleInventoryManipulator.addById(c, itemId, quantity, "", -1);
|
||||
MapleInventoryManipulator.removeById(c, MapleInventoryType.ETC, 4310000, amount, false, false);
|
||||
} else {
|
||||
short slotMax = ii.getSlotMax(c, item.getItemId());
|
||||
quantity = slotMax;
|
||||
MapleInventoryManipulator.addById(c, itemId, quantity);
|
||||
MapleInventoryManipulator.addById(c, itemId, quantity, "", -1);
|
||||
MapleInventoryManipulator.removeById(c, MapleInventoryType.ETC, 4310000, amount, false, false);
|
||||
}
|
||||
c.announce(MaplePacketCreator.shopTransaction((byte) 0));
|
||||
@@ -138,9 +138,9 @@ public class MapleShop {
|
||||
if (MapleInventoryManipulator.checkSpace(c, itemId, quantity, "")) {
|
||||
if (ItemConstants.isPet(itemId)) {
|
||||
int petid = MaplePet.createPet(itemId);
|
||||
MapleInventoryManipulator.addById(c, itemId, quantity, null, petid, -1);
|
||||
MapleInventoryManipulator.addById(c, itemId, quantity, "", petid, -1);
|
||||
} else {
|
||||
MapleInventoryManipulator.addById(c, itemId, quantity);
|
||||
MapleInventoryManipulator.addById(c, itemId, quantity, "", -1, -1);
|
||||
}
|
||||
c.getPlayer().gainMeso(diff, false);
|
||||
} else {
|
||||
|
||||
@@ -376,7 +376,7 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
|
||||
if (mpsi.getItem().getInventoryType().equals(MapleInventoryType.EQUIP)) {
|
||||
MapleInventoryManipulator.addFromDrop(c, mpsi.getItem(), false);
|
||||
} else {
|
||||
MapleInventoryManipulator.addById(c, mpsi.getItem().getItemId(), (short) (mpsi.getBundles() * mpsi.getItem().getQuantity()), null, -1, mpsi.getItem().getFlag(), mpsi.getItem().getExpiration());
|
||||
MapleInventoryManipulator.addById(c, mpsi.getItem().getItemId(), (short) (mpsi.getBundles() * mpsi.getItem().getQuantity()), mpsi.getItem().getOwner(), -1, mpsi.getItem().getFlag(), mpsi.getItem().getExpiration());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,12 +43,12 @@ public class MapleKite extends AbstractMapleMapObject {
|
||||
|
||||
@Override
|
||||
public void sendDestroyData(MapleClient client) {
|
||||
client.getSession().write(makeDestroyData());
|
||||
client.announce(makeDestroyData());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendSpawnData(MapleClient client) {
|
||||
client.getSession().write(makeSpawnData());
|
||||
client.announce(makeSpawnData());
|
||||
}
|
||||
|
||||
public final byte[] makeSpawnData() {
|
||||
|
||||
@@ -3882,7 +3882,7 @@ public class MapleMap {
|
||||
|
||||
public void spawnHorntailOnGroundBelow(final Point targetPoint) { // ayy lmao
|
||||
MapleMonster htIntro = MapleLifeFactory.getMonster(8810026);
|
||||
spawnMonsterOnGroundBelow(htIntro, targetPoint);
|
||||
spawnMonsterOnGroundBelow(htIntro, targetPoint); // htintro spawn animation converting into horntail detected thanks to Arnah
|
||||
|
||||
final MapleMonster ht = MapleLifeFactory.getMonster(8810018);
|
||||
ht.setParentMobOid(htIntro.getObjectId());
|
||||
|
||||
@@ -427,21 +427,14 @@ public class MapleMapFactory {
|
||||
public Map<Integer, MapleMap> getMaps() {
|
||||
mapsRLock.lock();
|
||||
try {
|
||||
return Collections.unmodifiableMap(maps);
|
||||
return new HashMap<>(maps);
|
||||
} finally {
|
||||
mapsRLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
Collection<MapleMap> mapValues;
|
||||
|
||||
mapsRLock.lock();
|
||||
try {
|
||||
mapValues = maps.values();
|
||||
} finally {
|
||||
mapsRLock.unlock();
|
||||
}
|
||||
Collection<MapleMap> mapValues = getMaps().values();
|
||||
|
||||
for(MapleMap map: mapValues) {
|
||||
map.dispose();
|
||||
|
||||
@@ -23,6 +23,7 @@ package server.maps;
|
||||
|
||||
import client.MapleCharacter;
|
||||
import client.MapleClient;
|
||||
import net.server.Server;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -31,23 +32,25 @@ import tools.MaplePacketCreator;
|
||||
/**
|
||||
*
|
||||
* @author Matze
|
||||
* @author Ronan (refactored String GameType to enum MiniGameType)
|
||||
* @author Ronan (HeavenMS)
|
||||
*/
|
||||
public class MapleMiniGame extends AbstractMapleMapObject {
|
||||
private MapleCharacter owner;
|
||||
private MapleCharacter visitor;
|
||||
private String password;
|
||||
private MiniGameType GameType = MiniGameType.UNDEFINED;
|
||||
private int piecetype;
|
||||
private int inprogress = 0;
|
||||
private int[] piece = new int[250];
|
||||
private List<Integer> list4x3 = new ArrayList<>();
|
||||
private List<Integer> list5x4 = new ArrayList<>();
|
||||
private List<Integer> list6x5 = new ArrayList<>();
|
||||
private String description;
|
||||
private int loser = 1;
|
||||
private int piecetype;
|
||||
private int firstslot = 0;
|
||||
private int visitorpoints = 0;
|
||||
private int ownerpoints = 0;
|
||||
private int visitorpoints = 0, visitorscore = 0, visitorforfeits = 0, lastvisitor = -1;
|
||||
private int ownerpoints = 0, ownerscore = 0, ownerforfeits = 0;
|
||||
private long nextavailabletie = 0;
|
||||
private int matchestowin = 0;
|
||||
|
||||
public static enum MiniGameType {
|
||||
@@ -91,12 +94,21 @@ public class MapleMiniGame extends AbstractMapleMapObject {
|
||||
|
||||
public void addVisitor(MapleCharacter challenger) {
|
||||
visitor = challenger;
|
||||
if (lastvisitor != challenger.getId()) {
|
||||
ownerscore = 0;
|
||||
ownerforfeits = 0;
|
||||
|
||||
visitorscore = 0;
|
||||
visitorforfeits = 0;
|
||||
lastvisitor = challenger.getId();
|
||||
}
|
||||
|
||||
MapleCharacter owner = this.getOwner();
|
||||
if (GameType == MiniGameType.OMOK) {
|
||||
owner.announce(MaplePacketCreator.getMiniGameNewVisitor(challenger, 1));
|
||||
owner.announce(MaplePacketCreator.getMiniGameNewVisitor(this, challenger, 1));
|
||||
owner.getMap().broadcastMessage(MaplePacketCreator.addOmokBox(owner, 2, 0));
|
||||
} else if (GameType == MiniGameType.MATCH_CARD) {
|
||||
owner.announce(MaplePacketCreator.getMatchCardNewVisitor(challenger, 1));
|
||||
owner.announce(MaplePacketCreator.getMatchCardNewVisitor(this, challenger, 1));
|
||||
owner.getMap().broadcastMessage(MaplePacketCreator.addMatchCardBox(owner, 2, 0));
|
||||
}
|
||||
}
|
||||
@@ -117,6 +129,13 @@ public class MapleMiniGame extends AbstractMapleMapObject {
|
||||
return visitor == challenger;
|
||||
}
|
||||
|
||||
public void broadcastToOwner(final byte[] packet) {
|
||||
MapleClient c = owner.getClient();
|
||||
if (c != null && c.getSession() != null) {
|
||||
c.announce(packet);
|
||||
}
|
||||
}
|
||||
|
||||
public void broadcastToVisitor(final byte[] packet) {
|
||||
if (visitor != null) {
|
||||
visitor.getClient().announce(packet);
|
||||
@@ -131,15 +150,83 @@ public class MapleMiniGame extends AbstractMapleMapObject {
|
||||
return firstslot;
|
||||
}
|
||||
|
||||
private void updateMiniGameBox() {
|
||||
this.getOwner().getMap().broadcastMessage(MaplePacketCreator.addOmokBox(owner, visitor != null ? 2 : 1, inprogress));
|
||||
}
|
||||
|
||||
private void minigameMatchFinished() {
|
||||
inprogress = 0;
|
||||
updateMiniGameBox();
|
||||
}
|
||||
|
||||
public void minigameMatchStarted() {
|
||||
inprogress = 1;
|
||||
}
|
||||
|
||||
public boolean isMatchInProgress() {
|
||||
return inprogress != 0;
|
||||
}
|
||||
|
||||
public void denyTie(MapleCharacter chr) {
|
||||
if (this.isOwner(chr)) {
|
||||
inprogress |= (1 << 1);
|
||||
} else {
|
||||
inprogress |= (1 << 2);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isTieDenied(MapleCharacter chr) {
|
||||
if (this.isOwner(chr)) {
|
||||
return ((inprogress >> 1) % 2) == 1;
|
||||
} else {
|
||||
return ((inprogress >> 2) % 2) == 1;
|
||||
}
|
||||
}
|
||||
|
||||
public void minigameMatchOwnerWins(boolean forfeit) {
|
||||
owner.setMiniGamePoints(visitor, 1, this.isOmok());
|
||||
if (visitorforfeits < 4 || !forfeit) ownerscore += 50;
|
||||
visitorscore += (15 * (forfeit ? -1 : 1));
|
||||
if (forfeit) visitorforfeits++;
|
||||
|
||||
this.broadcast(MaplePacketCreator.getMiniGameOwnerWin(this, forfeit));
|
||||
minigameMatchFinished();
|
||||
}
|
||||
|
||||
public void minigameMatchVisitorWins(boolean forfeit) {
|
||||
owner.setMiniGamePoints(visitor, 2, this.isOmok());
|
||||
if (ownerforfeits < 4 || !forfeit) visitorscore += 50;
|
||||
ownerscore += (15 * (forfeit ? -1 : 1));
|
||||
if (forfeit) ownerforfeits++;
|
||||
|
||||
this.broadcast(MaplePacketCreator.getMiniGameVisitorWin(this, forfeit));
|
||||
minigameMatchFinished();
|
||||
}
|
||||
|
||||
public void minigameMatchDraw() {
|
||||
owner.setMiniGamePoints(visitor, 3, this.isOmok());
|
||||
|
||||
long timeNow = Server.getInstance().getCurrentTime();
|
||||
if (nextavailabletie <= timeNow) {
|
||||
visitorscore += 10;
|
||||
ownerscore += 10;
|
||||
|
||||
nextavailabletie = timeNow + 5 * 60 * 1000;
|
||||
}
|
||||
|
||||
this.broadcast(MaplePacketCreator.getMiniGameTie(this));
|
||||
minigameMatchFinished();
|
||||
}
|
||||
|
||||
public void setOwnerPoints() {
|
||||
ownerpoints++;
|
||||
if (ownerpoints + visitorpoints == matchestowin) {
|
||||
if (ownerpoints == visitorpoints) {
|
||||
this.broadcast(MaplePacketCreator.getMatchCardTie(this));
|
||||
minigameMatchDraw();
|
||||
} else if (ownerpoints > visitorpoints) {
|
||||
this.broadcast(MaplePacketCreator.getMatchCardOwnerWin(this));
|
||||
minigameMatchOwnerWins(false);
|
||||
} else {
|
||||
this.broadcast(MaplePacketCreator.getMatchCardVisitorWin(this));
|
||||
minigameMatchVisitorWins(false);
|
||||
}
|
||||
ownerpoints = 0;
|
||||
visitorpoints = 0;
|
||||
@@ -150,11 +237,11 @@ public class MapleMiniGame extends AbstractMapleMapObject {
|
||||
visitorpoints++;
|
||||
if (ownerpoints + visitorpoints == matchestowin) {
|
||||
if (ownerpoints > visitorpoints) {
|
||||
this.broadcast(MaplePacketCreator.getMiniGameOwnerWin(this));
|
||||
minigameMatchOwnerWins(false);
|
||||
} else if (visitorpoints > ownerpoints) {
|
||||
this.broadcast(MaplePacketCreator.getMiniGameVisitorWin(this));
|
||||
minigameMatchVisitorWins(false);
|
||||
} else {
|
||||
this.broadcast(MaplePacketCreator.getMiniGameTie(this));
|
||||
minigameMatchDraw();
|
||||
}
|
||||
ownerpoints = 0;
|
||||
visitorpoints = 0;
|
||||
@@ -198,6 +285,10 @@ public class MapleMiniGame extends AbstractMapleMapObject {
|
||||
public MiniGameType getGameType() {
|
||||
return GameType;
|
||||
}
|
||||
|
||||
public boolean isOmok() {
|
||||
return GameType.equals(MiniGameType.OMOK);
|
||||
}
|
||||
|
||||
public void shuffleList() {
|
||||
if (matchestowin == 6) {
|
||||
@@ -212,11 +303,11 @@ public class MapleMiniGame extends AbstractMapleMapObject {
|
||||
public int getCardId(int slot) {
|
||||
int cardid;
|
||||
if (matchestowin == 6) {
|
||||
cardid = list4x3.get(slot - 1);
|
||||
cardid = list4x3.get(slot);
|
||||
} else if (matchestowin == 10) {
|
||||
cardid = list5x4.get(slot - 1);
|
||||
cardid = list5x4.get(slot);
|
||||
} else {
|
||||
cardid = list6x5.get(slot - 1);
|
||||
cardid = list6x5.get(slot);
|
||||
}
|
||||
return cardid;
|
||||
}
|
||||
@@ -234,10 +325,7 @@ public class MapleMiniGame extends AbstractMapleMapObject {
|
||||
}
|
||||
|
||||
public void broadcast(final byte[] packet) {
|
||||
MapleClient c = owner.getClient();
|
||||
if (c != null && c.getSession() != null) {
|
||||
c.announce(packet);
|
||||
}
|
||||
broadcastToOwner(packet);
|
||||
broadcastToVisitor(packet);
|
||||
}
|
||||
|
||||
@@ -270,10 +358,10 @@ public class MapleMiniGame extends AbstractMapleMapObject {
|
||||
for (int x = 0; x < 11; x++) {
|
||||
if (searchCombo(x, y, type)) {
|
||||
if (this.isOwner(chr)) {
|
||||
this.broadcast(MaplePacketCreator.getMiniGameOwnerWin(this));
|
||||
this.minigameMatchOwnerWins(false);
|
||||
this.setLoser(0);
|
||||
} else {
|
||||
this.broadcast(MaplePacketCreator.getMiniGameVisitorWin(this));
|
||||
this.minigameMatchVisitorWins(false);
|
||||
this.setLoser(1);
|
||||
}
|
||||
for (int y2 = 0; y2 < 15; y2++) {
|
||||
@@ -289,10 +377,10 @@ public class MapleMiniGame extends AbstractMapleMapObject {
|
||||
for (int x = 4; x < 15; x++) {
|
||||
if (searchCombo2(x, y, type)) {
|
||||
if (this.isOwner(chr)) {
|
||||
this.broadcast(MaplePacketCreator.getMiniGameOwnerWin(this));
|
||||
this.minigameMatchOwnerWins(false);
|
||||
this.setLoser(0);
|
||||
} else {
|
||||
this.broadcast(MaplePacketCreator.getMiniGameVisitorWin(this));
|
||||
this.minigameMatchVisitorWins(false);
|
||||
this.setLoser(1);
|
||||
}
|
||||
for (int y2 = 0; y2 < 15; y2++) {
|
||||
@@ -351,14 +439,20 @@ public class MapleMiniGame extends AbstractMapleMapObject {
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendDestroyData(MapleClient client) {
|
||||
|
||||
public int getOwnerScore() {
|
||||
return ownerscore;
|
||||
}
|
||||
|
||||
public int getVisitorScore() {
|
||||
return visitorscore;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendSpawnData(MapleClient client) {
|
||||
}
|
||||
public void sendDestroyData(MapleClient client) {}
|
||||
|
||||
@Override
|
||||
public void sendSpawnData(MapleClient client) {}
|
||||
|
||||
@Override
|
||||
public MapleMapObjectType getType() {
|
||||
|
||||
@@ -354,7 +354,7 @@ public class MapleQuest {
|
||||
newStatus.setCompletionTime(System.currentTimeMillis());
|
||||
c.updateQuest(newStatus);
|
||||
|
||||
c.getClient().getSession().write(MaplePacketCreator.showSpecialEffect(9)); // Quest completion
|
||||
c.announce(MaplePacketCreator.showSpecialEffect(9)); // Quest completion
|
||||
c.getMap().broadcastMessage(c, MaplePacketCreator.showForeignEffect(c.getId(), 9), false); //use 9 instead of 12 for both
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ public class ItemAction extends MapleQuestAction {
|
||||
}
|
||||
|
||||
for(Pair<Integer, Integer> iPair: giveItem) {
|
||||
MapleInventoryManipulator.addById(chr.getClient(), iPair.getLeft(), (short) iPair.getRight().shortValue());
|
||||
MapleInventoryManipulator.addById(chr.getClient(), iPair.getLeft(), (short) iPair.getRight().shortValue(), "", -1);
|
||||
chr.announce(MaplePacketCreator.getShowItemGain(iPair.getLeft(), (short) iPair.getRight().shortValue(), true));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user