GMS-like Wedding + Scissors of Karma + Maple Life + Buyback

Properly developed the Marriage feature in the source.
Added TRAVEL_RATE server flag, a modifier for the travel frequency rate.
Corrected stance for players in 3rd party view when entering a map to work similarly as GMS.
Fixed mobs spamming skills incoherently.
Added code support for old GMS-like PQ NPCs, where party leaders just need to click once to start a new PQ.
Implemented podium system for the Hall of Fame PlayerNPCs.
Improved character load-out system, now using way less queries to the DB in the process.
Fixed birthday field for accounts not being read correctly.
Further implemented the incomplete yet-existing Scissors of Karma mechanic.
Fixed Duey not propagating item flags when packaging an item.
Added a custom buyback system.
Refactored the character creation system, now offering support for Maple Life.
Fixed some issues with the PlayerNPC positioning system.
Added server flag allowing AP assignment for novices (beginners under level 11).
Fixed Strategy Time (GPQ) announcement being sent twice to guilds in certain cases.
Tweaked mount EXP system now awarding it accordingly with the amount of tiredness healed.
Removed the randomness aspect of closeness gain when feeding the pet, now acting accordingly with amount of fullness gained.
Fixed an exploit with Arwen script.
Fixed travel-back from Florina forcefully sending players to Lith Harbor in certain situations.
Thoroughly reviewed job skill questlines for Explorers and Aran.
Localhost edit: removed MTS block in certain maps (useful for the buyback system).
Localhost edit: removed party blocks for novices.
Localhost edit: removed AP assigning block for novices.
Localhost edit: removed speed cap.
Localhost edit: removed Maker block popping up when inputting ATK gems on non-weapons.
This commit is contained in:
ronancpl
2018-06-05 02:40:53 -03:00
230 changed files with 11509 additions and 3590 deletions
+341 -100
View File
@@ -29,8 +29,6 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
@@ -55,7 +53,6 @@ import java.util.regex.Pattern;
import net.server.PlayerBuffValueHolder;
import net.server.PlayerCoolDownValueHolder;
import net.server.Server;
import net.server.channel.Channel;
import net.server.guild.MapleAlliance;
import net.server.guild.MapleGuild;
import net.server.guild.MapleGuildCharacter;
@@ -67,7 +64,7 @@ import net.server.world.PartyOperation;
import net.server.world.World;
import scripting.event.EventInstanceManager;
import server.CashShop;
import server.MapleInventoryManipulator;
import client.inventory.manipulator.MapleInventoryManipulator;
import server.MapleItemInformationProvider;
import server.MaplePortal;
import server.MapleShop;
@@ -107,7 +104,9 @@ import tools.MaplePacketCreator;
import tools.Pair;
import tools.Randomizer;
import tools.locks.MonitoredReentrantLock;
import tools.packets.Wedding;
import client.autoban.AutobanManager;
import client.creator.CharacterFactoryRecipe;
import client.inventory.Equip;
import client.inventory.Item;
import client.inventory.ItemFactory;
@@ -159,7 +158,6 @@ import server.maps.MapleMapItem;
import tools.locks.MonitoredLockType;
public class MapleCharacter extends AbstractAnimatedMapleMapObject {
private static NumberFormat nf = new DecimalFormat("#,###,###,###");
private static MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
private static final String LEVEL_200 = "[Congrats] %s has reached Level 200! Congratulate %s on such an amazing achievement!";
private static final String[] BLOCKED_NAMES = {"admin", "owner", "moderator", "intern", "donor", "administrator", "help", "helper", "alert", "notice", "maplestory", "fuck", "wizet", "fucking", "negro", "fuk", "fuc", "penis", "pussy", "asshole", "gay",
@@ -200,12 +198,13 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
private int expRate = 1, mesoRate = 1, dropRate = 1, expCoupon = 1, mesoCoupon = 1, dropCoupon = 1;
private int omokwins, omokties, omoklosses, matchcardwins, matchcardties, matchcardlosses;
private int owlSearch;
private long lastfametime, lastUsedCashItem, lastHealed, lastMesoDrop = -1, jailExpiration = -1;
private long lastfametime, lastUsedCashItem, lastHealed, lastBuyback, lastDeathtime, lastMesoDrop = -1, jailExpiration = -1;
private transient int localmaxhp, localmaxmp, localstr, localdex, localluk, localint_, magic, watk;
private boolean hidden, canDoor = true, berserk, hasMerchant, whiteChat = false;
private int linkedLevel = 0;
private String linkedName = null;
private boolean finishedDojoTutorial;
private boolean usedStorage = false;
private String name;
private String chalktext;
private String dataString;
@@ -237,7 +236,6 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
private MapleStorage storage = null;
private MapleTrade trade = null;
private MonsterBook monsterbook;
private MapleRing marriageRing;
private CashShop cashshop;
private Set<NewYearCardRecord> newyears = new LinkedHashSet<>();
private SavedLocation savedLocations[];
@@ -280,8 +278,6 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
private Lock prtLock = new MonitoredReentrantLock(MonitoredLockType.PRT);
private Map<Integer, Set<Integer>> excluded = new LinkedHashMap<>();
private Set<Integer> excludedItems = new LinkedHashSet<>();
private List<MapleRing> crushRings = new ArrayList<>();
private List<MapleRing> friendshipRings = new ArrayList<>();
private static String[] ariantroomleader = new String[3];
private static int[] ariantroomslot = new int[3];
private long portaldelay = 0, lastcombo = 0;
@@ -296,8 +292,13 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
private List<Integer> viptrockmaps = new ArrayList<>();
private Map<String, MapleEvents> events = new LinkedHashMap<>();
private PartyQuest partyQuest = null;
private boolean loggedIn = false;
private MapleDragon dragon = null;
private MapleRing marriageRing;
private int marriageItemid = -1;
private int partnerId = -1;
private List<MapleRing> crushRings = new ArrayList<>();
private List<MapleRing> friendshipRings = new ArrayList<>();
private boolean loggedIn = false;
private boolean useCS; //chaos scroll upon crafting item.
private long npcCd;
private long petLootCd;
@@ -503,12 +504,54 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
return ring;
}
}
if (getMarriageRing().getRingId() == id) {
return getMarriageRing();
if(marriageRing != null) {
if (marriageRing.getRingId() == id) {
return marriageRing;
}
}
return null;
}
public int getMarriageItemId() {
return marriageItemid;
}
public void setMarriageItemId(int itemid) {
marriageItemid = itemid;
}
public int getPartnerId() {
return partnerId;
}
public void setPartnerId(int partnerid) {
partnerId = partnerid;
}
public int getRelationshipId() {
return client.getWorldServer().getRelationshipId(id);
}
public boolean isMarried() {
return marriageRing != null && partnerId > 0;
}
public boolean hasJustMarried() {
EventInstanceManager eim = getEventInstance();
if(eim != null) {
String prop = eim.getProperty("groomId");
if(prop != null) {
if((Integer.parseInt(prop) == id || eim.getIntProperty("brideId") == id) && (mapid == 680000110 || mapid == 680000210)) {
return true;
}
}
}
return false;
}
public int addDojoPointsByMap(int mapid) {
int pts = 0;
@@ -547,6 +590,10 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
public void addFriendshipRing(MapleRing r) {
friendshipRings.add(r);
}
public void addMarriageRing(MapleRing r) {
marriageRing = r;
}
public void addHP(int delta) {
setHp(hp + delta);
@@ -877,7 +924,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
public void toggleHide(boolean login) {
Hide(!isHidden());
Hide(!hidden);
}
public void cancelMagicDoor() {
@@ -1012,6 +1059,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
if (newJob == null) {
return;//the fuck you doing idiot!
}
this.job = newJob;
remainingSp[GameConstants.getSkillBook(newJob.getId())] += 1;
if (GameConstants.hasSPTable(newJob)) {
@@ -1388,7 +1436,16 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
petLock.unlock();
}
}
public void notifyMapTransferToPartner(int mapid) {
if(partnerId > 0) {
final MapleCharacter partner = client.getWorldServer().getPlayerStorage().getCharacterById(partnerId);
if(partner != null && !partner.isAwayFromWorld()) {
partner.announce(Wedding.OnNotifyWeddingPartnerTransfer(id, mapid));
}
}
}
private void changeMapInternal(final MapleMap to, final Point pos, final byte[] warpPacket) {
if(!canWarpMap) return;
@@ -1425,6 +1482,8 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
FilePrinter.printError(FilePrinter.MAPLE_MAP, "Character " + this.getName() + " got stuck when moving to map " + map.getId() + ".");
}
notifyMapTransferToPartner(map.getId());
//alas, new map has been specified when a warping was being processed...
if(newWarpMap != -1) {
canWarpMap = true;
@@ -1532,10 +1591,6 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
}
public void clearSavedLocation(SavedLocationType type) {
savedLocations[type.ordinal()] = null;
}
public void controlMonster(MapleMonster monster, boolean aggro) {
monster.setController(this);
controlled.add(monster);
@@ -2305,10 +2360,6 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
client.announce(MaplePacketCreator.serverNotice(type, message));
}
public String emblemCost() {
return nf.format(MapleGuild.CHANGE_EMBLEM_COST);
}
private void enforceMaxHpMp() {
List<Pair<MapleStat, Integer>> stats = new ArrayList<>(2);
if (getMp() > getCurrentMaxMp()) {
@@ -2565,7 +2616,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
public void gainExp(int gain, boolean show, boolean inChat, boolean white) {
gainExp(gain, 0, show, inChat, white);
}
public void gainExp(int gain, int party, boolean show, boolean inChat, boolean white) {
if (hasDisease(MapleDisease.CURSE)) {
gain *= 0.5;
@@ -2574,9 +2625,9 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
if(gain < 0) gain = Integer.MAX_VALUE; // integer overflow, heh.
if(party < 0) party = Integer.MAX_VALUE; // integer overflow, heh.
int equip = (int)Math.min((long)((gain / 10) * pendantExp), Integer.MAX_VALUE);
int equip = (int) Math.min((long)(gain / 10) * pendantExp, Integer.MAX_VALUE);
long total = (long)gain + equip + party;
long total = (long) gain + equip + party;
gainExpInternal(total, equip, party, show, inChat, white);
}
@@ -2595,11 +2646,11 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
long leftover = 0;
long nextExp = exp.get() + total;
if (nextExp > (long)Integer.MAX_VALUE) {
if (nextExp > (long) Integer.MAX_VALUE) {
total = Integer.MAX_VALUE - exp.get();
leftover = nextExp - Integer.MAX_VALUE;
}
updateSingleStat(MapleStat.EXP, exp.addAndGet((int)total));
updateSingleStat(MapleStat.EXP, exp.addAndGet((int) total));
if (show && gain != 0) {
client.announce(MaplePacketCreator.getShowExpGain((int)Math.min(gain, Integer.MAX_VALUE), equip, party, inChat, white));
}
@@ -3860,7 +3911,11 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
public boolean getFinishedDojoTutorial() {
return finishedDojoTutorial;
}
public void setUsedStorage() {
usedStorage = true;
}
public List<MapleRing> getFriendshipRings() {
Collections.sort(friendshipRings);
return friendshipRings;
@@ -4100,7 +4155,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
public MapleRing getMarriageRing() {
return marriageRing;
return partnerId > 0 ? marriageRing : null;
}
public int getMasterLevel(Skill skill) {
@@ -4611,15 +4666,22 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
return remainingSp;
}
public int getSavedLocation(String type) {
private void clearSavedLocation(SavedLocationType type) {
savedLocations[type.ordinal()] = null;
}
public int peekSavedLocation(String type) {
SavedLocation sl = savedLocations[SavedLocationType.fromString(type).ordinal()];
if (sl == null) {
return -1;
}
int m = sl.getMapId();
if (!SavedLocationType.fromString(type).equals(SavedLocationType.WORLDTOUR)) {
clearSavedLocation(SavedLocationType.fromString(type));
}
return sl.getMapId();
}
public int getSavedLocation(String type) {
int m = peekSavedLocation(type);
clearSavedLocation(SavedLocationType.fromString(type));
return m;
}
@@ -4801,10 +4863,6 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
return gmLevel;
}
public String guildCost() {
return nf.format(MapleGuild.CREATE_GUILD_COST);
}
private void guildUpdate() {
mgc.setLevel(level);
mgc.setJobId(job.getId());
@@ -4959,6 +5017,50 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
public boolean isAlive() {
return hp > 0;
}
private boolean canBuyback(int fee, boolean usingMesos) {
return (usingMesos ? this.getMeso() : cashshop.getCash(1)) >= fee;
}
private void applyBuybackFee(int fee, boolean usingMesos) {
if(usingMesos) {
this.gainMeso(-fee);
} else {
cashshop.gainCash(1, -fee);
}
}
public boolean couldBuyback() { // Ronan's buyback system
long timeNow = System.currentTimeMillis();
if(timeNow - lastDeathtime > ServerConstants.BUYBACK_RETURN_MINUTES * 60 * 1000) {
this.dropMessage(5, "You are unable to buyback now since the time available to decide has expired.");
return false;
}
long nextBuybacktime = lastBuyback + ServerConstants.BUYBACK_COOLDOWN_MINUTES * 60 * 1000;
if(timeNow < nextBuybacktime) {
long timeLeft = nextBuybacktime - timeNow;
int seconds = (int) Math.floor(timeLeft / 1000) % 60;
int minutes = (int) Math.floor(timeLeft / (1000*60)) % 60;
this.dropMessage(5, "Next buyback available in " + (minutes > 0 ? (String.format("%02d", minutes) + " minutes, ") : "") + String.format("%02d", seconds) + " seconds.");
return false;
}
boolean usingMesos = ServerConstants.USE_BUYBACK_WITH_MESOS;
int fee = ServerConstants.BUYBACK_FEE;
if(usingMesos) fee *= ServerConstants.BUYBACK_MESO_MULTIPLIER;
if(!canBuyback(fee, usingMesos)) {
this.dropMessage(5, "You don't have " + fee + " " + (usingMesos ? "mesos" : "NX") + " to buyback.");
return false;
}
lastBuyback = timeNow;
applyBuybackFee(fee, usingMesos);
return true;
}
public boolean isBuffFrom(MapleBuffStat stat, Skill skill) {
effLock.lock();
@@ -5032,9 +5134,10 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
int improvingMaxHPLevel = 0;
int improvingMaxMPLevel = 0;
if (isBeginnerJob() && getLevel() < 11) {
boolean isBeginner = isBeginnerJob();
if (ServerConstants.USE_AUTOASSIGN_STARTERS_AP && isBeginner && level < 11) {
remainingAp = 0;
if (getLevel() < 6) {
if (level < 6) {
str += 5;
} else {
str += 4;
@@ -5042,11 +5145,12 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
} else {
remainingAp += 5;
if (isCygnus() && level < 70) {
if (isCygnus() && level > 10 && level < 70) {
remainingAp++;
}
}
if (job == MapleJob.BEGINNER || job == MapleJob.NOBLESSE || job == MapleJob.LEGEND) {
if (isBeginner) {
maxhp += Randomizer.rand(12, 16);
maxmp += Randomizer.rand(10, 12);
} else if (job.isA(MapleJob.WARRIOR) || job.isA(MapleJob.DAWNWARRIOR1)) {
@@ -5464,6 +5568,17 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
}
public void addPlayerRing(MapleRing ring) {
int ringItemId = ring.getItemId();
if (ItemConstants.isWeddingRing(ringItemId)) {
this.addMarriageRing(ring);
} else if (ring.getItemId() > 1112012) {
this.addFriendshipRing(ring);
} else {
this.addCrushRing(ring);
}
}
public static MapleCharacter loadCharFromDB(int charid, MapleClient client, boolean channelserver) throws SQLException {
try {
MapleCharacter ret = new MapleCharacter();
@@ -5565,15 +5680,23 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
if (item.getRight().equals(MapleInventoryType.EQUIPPED)) {
ring.equip();
}
if (ring.getItemId() > 1112012) {
ret.addFriendshipRing(ring);
} else {
ret.addCrushRing(ring);
}
ret.addPlayerRing(ring);
}
}
}
World wserv = Server.getInstance().getWorld(ret.world);
ret.partnerId = rs.getInt("partnerId");
ret.marriageItemid = rs.getInt("marriageItemId");
if(ret.marriageItemid > 0 && ret.partnerId <= 0) {
ret.marriageItemid = -1;
} else if(ret.partnerId > 0 && wserv.getRelationshipId(ret.id) <= 0) {
ret.marriageItemid = -1;
ret.partnerId = -1;
}
NewYearCardRecord.loadPlayerNewYearCards(ret);
PreparedStatement ps2, ps3;
@@ -5617,7 +5740,6 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
ret.setPosition(portal.getPosition());
int partyid = rs.getInt("party");
World wserv = Server.getInstance().getWorld(ret.world);
MapleParty party = wserv.getParty(partyid);
if (party != null) {
ret.mpc = party.getMemberById(ret.id);
@@ -5693,7 +5815,6 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
ps.close();
ret.cashshop = new CashShop(ret.accountid, ret.id, ret.getJobType());
ret.autoban = new AutobanManager(ret);
ret.marriageRing = null; //for now
ps = con.prepareStatement("SELECT name, level FROM characters WHERE accountid = ? AND id != ? ORDER BY level DESC limit 1");
ps.setInt(1, ret.accountid);
ps.setInt(2, charid);
@@ -5708,41 +5829,56 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
ps = con.prepareStatement("SELECT * FROM queststatus WHERE characterid = ?");
ps.setInt(1, charid);
rs = ps.executeQuery();
PreparedStatement psf;
try (PreparedStatement pse = con.prepareStatement("SELECT * FROM questprogress WHERE queststatusid = ?")) {
psf = con.prepareStatement("SELECT mapid FROM medalmaps WHERE queststatusid = ?");
while (rs.next()) {
MapleQuest q = MapleQuest.getInstance(rs.getShort("quest"));
MapleQuestStatus status = new MapleQuestStatus(q, MapleQuestStatus.Status.getById(rs.getInt("status")));
long cTime = rs.getLong("time");
if (cTime > -1) {
status.setCompletionTime(cTime * 1000);
}
long eTime = rs.getLong("expires");
if (eTime > 0) {
status.setExpirationTime(eTime);
}
status.setForfeited(rs.getInt("forfeited"));
ret.quests.put(q.getId(), status);
pse.setInt(1, rs.getInt("queststatusid"));
try (ResultSet rsProgress = pse.executeQuery()) {
while (rsProgress.next()) {
status.setProgress(rsProgress.getInt("progressid"), rsProgress.getString("progress"));
}
}
psf.setInt(1, rs.getInt("queststatusid"));
try (ResultSet medalmaps = psf.executeQuery()) {
while (medalmaps.next()) {
status.addMedalMap(medalmaps.getInt("mapid"));
}
Map<Integer, MapleQuestStatus> loadedQuestStatus = new LinkedHashMap<>();
while (rs.next()) {
MapleQuest q = MapleQuest.getInstance(rs.getShort("quest"));
MapleQuestStatus status = new MapleQuestStatus(q, MapleQuestStatus.Status.getById(rs.getInt("status")));
long cTime = rs.getLong("time");
if (cTime > -1) {
status.setCompletionTime(cTime * 1000);
}
long eTime = rs.getLong("expires");
if (eTime > 0) {
status.setExpirationTime(eTime);
}
status.setForfeited(rs.getInt("forfeited"));
ret.quests.put(q.getId(), status);
loadedQuestStatus.put(rs.getInt("queststatusid"), status);
}
rs.close();
ps.close();
// opportunity for improvement on questprogress/medalmaps calls to DB
try (PreparedStatement pse = con.prepareStatement("SELECT * FROM questprogress WHERE characterid = ?")) {
pse.setInt(1, charid);
try (ResultSet rsProgress = pse.executeQuery()) {
while(rsProgress.next()) {
MapleQuestStatus status = loadedQuestStatus.get(rsProgress.getInt("queststatusid"));
status.setProgress(rsProgress.getInt("progressid"), rsProgress.getString("progress"));
}
}
rs.close();
ps.close();
}
psf.close();
try (PreparedStatement pse = con.prepareStatement("SELECT * FROM medalmaps WHERE characterid = ?")) {
pse.setInt(1, charid);
try (ResultSet rsMedalMaps = pse.executeQuery()) {
while(rsMedalMaps.next()) {
MapleQuestStatus status = loadedQuestStatus.get(rsMedalMaps.getInt("queststatusid"));
status.addMedalMap(rsMedalMaps.getInt("mapid"));
}
}
}
for(MapleQuestStatus mqs : loadedQuestStatus.values()) {
mqs.resetUpdated();
}
loadedQuestStatus.clear();
ps = con.prepareStatement("SELECT skillid,skilllevel,masterlevel,expiration FROM skills WHERE characterid = ?");
ps.setInt(1, charid);
rs = ps.executeQuery();
@@ -5927,6 +6063,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
private void playerDead() {
cancelAllBuffs(false);
dispelDebuffs();
lastDeathtime = System.currentTimeMillis();
EventInstanceManager eim = getEventInstance();
if (eim != null) {
@@ -6218,6 +6355,10 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
public void resetStats() {
if(!ServerConstants.USE_AUTOASSIGN_STARTERS_AP) {
return;
}
List<Pair<MapleStat, Integer>> statup = new ArrayList<>(5);
int tap = 0, tsp = 1;
int tstr = 4, tdex = 4, tint = 4, tluk = 4;
@@ -6336,8 +6477,33 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
MaplePortal closest = map.findClosestPortal(getPosition());
savedLocations[SavedLocationType.fromString(type).ordinal()] = new SavedLocation(getMapId(), closest != null ? closest.getId() : 0);
}
public final boolean insertNewChar(CharacterFactoryRecipe recipe) {
str = recipe.getStr();
dex = recipe.getDex();
int_ = recipe.getInt();
luk = recipe.getLuk();
maxhp = recipe.getMaxHp();
maxmp = recipe.getMaxMp();
hp = maxhp;
mp = maxmp;
level = recipe.getLevel();
remainingAp = recipe.getRemainingAp();
remainingSp[GameConstants.getSkillBook(job.getId())] = recipe.getRemainingSp();
mapid = recipe.getMap();
meso.set(recipe.getMeso());
public final boolean insertNewChar() {
List<Pair<Skill, Integer>> startingSkills = recipe.getStartingSkillLevel();
for(Pair<Skill, Integer> skEntry : startingSkills) {
Skill skill = skEntry.getLeft();
this.changeSkillLevel(skill, skEntry.getRight().byteValue(), skill.getMaxLevel(), -1);
}
List<Pair<Item, MapleInventoryType>> itemsWithType = recipe.getStartingItems();
for(Pair<Item, MapleInventoryType> itEntry : itemsWithType) {
this.getInventory(itEntry.getRight()).addItem(itEntry.getLeft());
}
Connection con = null;
PreparedStatement ps = null;
@@ -6346,11 +6512,11 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
con.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
con.setAutoCommit(false);
ps = con.prepareStatement("INSERT INTO characters (str, dex, luk, `int`, gm, skincolor, gender, job, hair, face, map, meso, spawnpoint, accountid, name, world) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS);
ps.setInt(1, 12);
ps.setInt(2, 5);
ps.setInt(3, 4);
ps.setInt(4, 4);
ps = con.prepareStatement("INSERT INTO characters (str, dex, luk, `int`, gm, skincolor, gender, job, hair, face, map, meso, spawnpoint, accountid, name, world, hp, mp, maxhp, maxmp, level, ap, sp) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS);
ps.setInt(1, str);
ps.setInt(2, dex);
ps.setInt(3, luk);
ps.setInt(4, int_);
ps.setInt(5, gmLevel);
ps.setInt(6, skinColor.getId());
ps.setInt(7, gender);
@@ -6363,6 +6529,20 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
ps.setInt(14, accountid);
ps.setString(15, name);
ps.setInt(16, world);
ps.setInt(17, hp);
ps.setInt(18, mp);
ps.setInt(19, maxhp);
ps.setInt(20, maxmp);
ps.setInt(21, level);
ps.setInt(22, remainingAp);
StringBuilder sps = new StringBuilder();
for (int i = 0; i < remainingSp.length; i++) {
sps.append(remainingSp[i]);
sps.append(",");
}
String sp = sps.toString();
ps.setString(23, sp.substring(0, sp.length() - 1));
int updateRows = ps.executeUpdate();
if (updateRows < 1) {
@@ -6408,8 +6588,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
ps.close();
final List<Pair<Item, MapleInventoryType>> itemsWithType = new ArrayList<>();
itemsWithType = new ArrayList<>();
for (MapleInventory iv : inventory) {
for (Item item : iv.list()) {
itemsWithType.add(new Pair<>(item, iv.getType()));
@@ -6417,6 +6596,21 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
ItemFactory.INVENTORY.saveItems(itemsWithType, id, con);
if(!skills.isEmpty()) {
ps = con.prepareStatement("INSERT INTO skills (characterid, skillid, skilllevel, masterlevel, expiration) VALUES (?, ?, ?, ?, ?)");
ps.setInt(1, id);
for (Entry<Skill, SkillEntry> skill : skills.entrySet()) {
ps.setInt(2, skill.getKey().getId());
ps.setInt(3, skill.getValue().skillevel);
ps.setInt(4, skill.getValue().masterlevel);
ps.setLong(5, skill.getValue().expiration);
ps.addBatch();
}
ps.executeBatch();
ps.close();
}
con.commit();
return true;
} catch (Throwable t) {
@@ -6457,6 +6651,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
}
//ItemFactory saveItems and monsterbook.saveCards are the most time consuming here.
public synchronized void saveToDB(boolean notAutosave) {
if(!loggedIn) return;
@@ -6471,7 +6666,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
con.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
con.setAutoCommit(false);
PreparedStatement ps;
ps = con.prepareStatement("UPDATE characters SET level = ?, fame = ?, str = ?, dex = ?, luk = ?, `int` = ?, exp = ?, gachaexp = ?, hp = ?, mp = ?, maxhp = ?, maxmp = ?, sp = ?, ap = ?, gm = ?, skincolor = ?, gender = ?, job = ?, hair = ?, face = ?, map = ?, meso = ?, hpMpUsed = ?, spawnpoint = ?, party = ?, buddyCapacity = ?, messengerid = ?, messengerposition = ?, mountlevel = ?, mountexp = ?, mounttiredness= ?, equipslots = ?, useslots = ?, setupslots = ?, etcslots = ?, monsterbookcover = ?, vanquisherStage = ?, dojoPoints = ?, lastDojoStage = ?, finishedDojoTutorial = ?, vanquisherKills = ?, matchcardwins = ?, matchcardlosses = ?, matchcardties = ?, omokwins = ?, omoklosses = ?, omokties = ?, dataString = ?, fquest = ?, jailexpire = ? WHERE id = ?", Statement.RETURN_GENERATED_KEYS);
ps = con.prepareStatement("UPDATE characters SET level = ?, fame = ?, str = ?, dex = ?, luk = ?, `int` = ?, exp = ?, gachaexp = ?, hp = ?, mp = ?, maxhp = ?, maxmp = ?, sp = ?, ap = ?, gm = ?, skincolor = ?, gender = ?, job = ?, hair = ?, face = ?, map = ?, meso = ?, hpMpUsed = ?, spawnpoint = ?, party = ?, buddyCapacity = ?, messengerid = ?, messengerposition = ?, mountlevel = ?, mountexp = ?, mounttiredness= ?, equipslots = ?, useslots = ?, setupslots = ?, etcslots = ?, monsterbookcover = ?, vanquisherStage = ?, dojoPoints = ?, lastDojoStage = ?, finishedDojoTutorial = ?, vanquisherKills = ?, matchcardwins = ?, matchcardlosses = ?, matchcardties = ?, omokwins = ?, omoklosses = ?, omokties = ?, dataString = ?, fquest = ?, jailexpire = ?, partnerId = ?, marriageItemId = ? WHERE id = ?", Statement.RETURN_GENERATED_KEYS);
if (gmLevel < 1 && level > 199) {
ps.setInt(1, isCygnus() ? 120 : 200);
} else {
@@ -6555,9 +6750,9 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
for (int i = 1; i < 5; i++) {
ps.setInt(i + 31, getSlots(i));
}
monsterbook.saveCards(getId());
ps.setInt(36, bookCover);
ps.setInt(37, vanquisherStage);
ps.setInt(38, dojoPoints);
@@ -6573,9 +6768,13 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
ps.setString(48, dataString);
ps.setInt(49, quest_fame);
ps.setLong(50, jailExpiration);
ps.setInt(51, id);
ps.setInt(51, partnerId);
ps.setInt(52, marriageItemid);
ps.setInt(53, id);
int updateRows = ps.executeUpdate();
ps.close();
if (updateRows < 1) {
throw new RuntimeException("Character not in database (" + id + ")");
}
@@ -6619,6 +6818,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
ps.addBatch();
}
ps.executeBatch();
ps.close();
deleteWhereCharacterId(con, "DELETE FROM skillmacros WHERE characterid = ?");
ps = con.prepareStatement("INSERT INTO skillmacros (characterid, skill1, skill2, skill3, name, shout, position) VALUES (?, ?, ?, ?, ?, ?, ?)");
@@ -6636,6 +6836,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
}
ps.executeBatch();
ps.close();
List<Pair<Item, MapleInventoryType>> itemsWithType = new ArrayList<>();
for (MapleInventory iv : inventory) {
@@ -6643,8 +6844,9 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
itemsWithType.add(new Pair<>(item, iv.getType()));
}
}
ItemFactory.INVENTORY.saveItems(itemsWithType, id, con);
deleteWhereCharacterId(con, "DELETE FROM skills WHERE characterid = ?");
ps = con.prepareStatement("INSERT INTO skills (characterid, skillid, skilllevel, masterlevel, expiration) VALUES (?, ?, ?, ?, ?)");
ps.setInt(1, id);
@@ -6656,6 +6858,8 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
ps.addBatch();
}
ps.executeBatch();
ps.close();
deleteWhereCharacterId(con, "DELETE FROM savedlocations WHERE characterid = ?");
ps = con.prepareStatement("INSERT INTO savedlocations (characterid, `locationtype`, `map`, `portal`) VALUES (?, ?, ?, ?)");
ps.setInt(1, id);
@@ -6668,6 +6872,8 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
}
ps.executeBatch();
ps.close();
deleteWhereCharacterId(con, "DELETE FROM trocklocations WHERE characterid = ?");
ps = con.prepareStatement("INSERT INTO trocklocations(characterid, mapid, vip) VALUES (?, ?, 0)");
for (int i = 0; i < getTrockSize(); i++) {
@@ -6678,6 +6884,8 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
}
ps.executeBatch();
ps.close();
ps = con.prepareStatement("INSERT INTO trocklocations(characterid, mapid, vip) VALUES (?, ?, 1)");
for (int i = 0; i < getVipTrockSize(); i++) {
if (viptrockmaps.get(i) != 999999999) {
@@ -6687,6 +6895,8 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
}
ps.executeBatch();
ps.close();
deleteWhereCharacterId(con, "DELETE FROM buddies WHERE characterid = ? AND pending = 0");
ps = con.prepareStatement("INSERT INTO buddies (characterid, `buddyid`, `pending`, `group`) VALUES (?, ?, 0, ?)");
ps.setInt(1, id);
@@ -6698,6 +6908,8 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
}
ps.executeBatch();
ps.close();
deleteWhereCharacterId(con, "DELETE FROM area_info WHERE charid = ?");
ps = con.prepareStatement("INSERT INTO area_info (id, charid, area, info) VALUES (DEFAULT, ?, ?, ?)");
ps.setInt(1, id);
@@ -6707,9 +6919,12 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
ps.addBatch();
}
ps.executeBatch();
ps.close();
deleteWhereCharacterId(con, "DELETE FROM eventstats WHERE characterid = ?");
deleteQuestProgressWhereCharacterId(con, id);
ps = con.prepareStatement("INSERT INTO queststatus (`queststatusid`, `characterid`, `quest`, `status`, `time`, `expires`, `forfeited`) VALUES (DEFAULT, ?, ?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS);
PreparedStatement psf;
try (PreparedStatement pse = con.prepareStatement("INSERT INTO questprogress VALUES (DEFAULT, ?, ?, ?, ?)")) {
@@ -6718,6 +6933,8 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
synchronized (quests) {
for (MapleQuestStatus q : quests.values()) {
if(!q.wasUpdated()) continue;
ps.setInt(2, q.getQuest().getId());
ps.setInt(3, q.getStatus().getId());
ps.setInt(4, (int) (q.getCompletionTime() / 1000));
@@ -6744,23 +6961,31 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
}
}
}
psf.close();
ps.close();
ps = con.prepareStatement("UPDATE accounts SET gm = ? WHERE id = ?");
ps.setInt(1, gmLevel > 1 ? 1 : 0);
ps.setInt(2, client.getAccID());
ps.executeUpdate();
ps.close();
con.commit();
con.setAutoCommit(true);
if (cashshop != null) {
cashshop.save(con);
}
if (storage != null) {
if (storage != null && usedStorage) {
storage.saveToDB(con);
usedStorage = false;
}
} catch (SQLException | RuntimeException t) {
FilePrinter.printError(FilePrinter.SAVE_CHAR, t, "Error saving " + name + " Level: " + level + " Job: " + job.getId());
try {
@@ -6973,7 +7198,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
int newAmount;
try {
newAmount = (int)Math.min((long)merchantmeso + add, Integer.MAX_VALUE);
newAmount = (int) Math.min((long) merchantmeso + add, Integer.MAX_VALUE);
Connection con = DatabaseConnection.getConnection();
try (PreparedStatement ps = con.prepareStatement("UPDATE characters SET MerchantMesos = ? WHERE id = ?", Statement.RETURN_GENERATED_KEYS)) {
@@ -7303,9 +7528,14 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
if (item == null){ //Basic check
return(0);
}
if (ItemConstants.isRechargeable(item.getItemId())) {
int itemid = item.getItemId();
if (ItemConstants.isRechargeable(itemid)) {
quantity = item.getQuantity();
} else if (ItemConstants.isWeddingToken(itemid) || ItemConstants.isWeddingRing(itemid)) {
return(0);
}
if (quantity < 0) {
return(0);
}
@@ -7316,7 +7546,6 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
if (quantity <= iQuant && iQuant > 0) {
MapleInventoryManipulator.removeFromSlot(c, type, (byte) slot, quantity, false);
int itemid = item.getItemId();
int recvMesos = ii.getPrice(itemid, quantity);
if (recvMesos > 0) {
gainMeso(recvMesos, false);
@@ -8168,6 +8397,18 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
this.showHint("#ePLAYER EQUIPMENTS:#n\r\n\r\n" + showMsg, 400);
}
}
public void broadcastMarriageMessage() {
MapleGuild guild = this.getGuild();
if(guild != null) {
guild.broadcast(MaplePacketCreator.marriageMessage(0, name));
}
MapleFamily family = this.getFamily();
if(family != null) {
family.broadcast(MaplePacketCreator.marriageMessage(1, name));
}
}
public Map<String, MapleEvents> getEvents() {
return events;
+10 -7
View File
@@ -736,7 +736,7 @@ public class MapleClient {
public int getLoginState() { // 0 = LOGIN_NOTLOGGEDIN, 1= LOGIN_SERVER_TRANSITION, 2 = LOGIN_LOGGEDIN
try {
Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("SELECT loggedin, lastlogin, UNIX_TIMESTAMP(birthday) as birthday FROM accounts WHERE id = ?");
PreparedStatement ps = con.prepareStatement("SELECT loggedin, lastlogin, birthday FROM accounts WHERE id = ?");
ps.setInt(1, getAccID());
ResultSet rs = ps.executeQuery();
if (!rs.next()) {
@@ -744,11 +744,12 @@ public class MapleClient {
ps.close();
throw new RuntimeException("getLoginState - MapleClient");
}
birthday = Calendar.getInstance();
long blubb = rs.getLong("birthday");
if (blubb > 0) {
birthday.setTimeInMillis(blubb * 1000);
}
try {
birthday.setTime(rs.getDate("birthday"));
} catch(SQLException e) {}
int state = rs.getInt("loggedin");
if (state == LOGIN_SERVER_TRANSITION) {
// Arnah's note: lastlogin is a date-type, in case of login and game servers being of different timezones this becomes broken
@@ -783,12 +784,13 @@ public class MapleClient {
}
public boolean checkBirthDate(Calendar date) {
return date.get(Calendar.YEAR) == birthday.get(Calendar.YEAR) && date.get(Calendar.MONTH) == birthday.get(Calendar.MONTH) && date.get(Calendar.DAY_OF_MONTH) == birthday.get(Calendar.DAY_OF_MONTH);
return date.get(Calendar.YEAR) == birthday.get(Calendar.YEAR) && date.get(Calendar.MONTH) == birthday.get(Calendar.MONTH) && date.get(Calendar.DAY_OF_MONTH) == birthday.get(Calendar.DAY_OF_MONTH);
}
private void removePlayer() {
try {
player.setAwayFromWorld(true);
player.notifyMapTransferToPartner(-1);
player.cancelAllBuffs(true);
player.cancelAllDebuffs();
@@ -1167,7 +1169,7 @@ public class MapleClient {
return characterSlots;
}
public boolean gainCharacterSlot() {
public synchronized boolean gainCharacterSlot() {
if (characterSlots < 15) {
Connection con = null;
try {
@@ -1301,6 +1303,7 @@ public class MapleClient {
server.getPlayerBuffStorage().addBuffsToStorage(player.getId(), player.getAllBuffs());
server.getPlayerBuffStorage().addDiseasesToStorage(player.getId(), player.getAllDiseases());
player.setAwayFromWorld(true);
player.notifyMapTransferToPartner(-1);
player.cancelAllBuffs(true);
player.cancelAllDebuffs();
player.cancelBuffExpireTask();
+4
View File
@@ -92,4 +92,8 @@ public class MapleFamily {
public Map<Integer, MapleFamilyEntry> getMembers() {
return members;
}
public void broadcast(byte[] packet) {
// family currently not developed
}
}
+22 -2
View File
@@ -60,8 +60,9 @@ public class MapleQuestStatus {
}
private short questID;
private Status status;
private Map<Integer, String> progress = new LinkedHashMap<Integer, String>();
private List<Integer> medalProgress = new LinkedList<Integer>();
private boolean updated;
private final Map<Integer, String> progress = new LinkedHashMap<Integer, String>();
private final List<Integer> medalProgress = new LinkedList<Integer>();
private int npc;
private long completionTime, expirationTime;
private int forfeited = 0;
@@ -72,6 +73,7 @@ public class MapleQuestStatus {
this.setStatus(status);
this.completionTime = System.currentTimeMillis();
this.expirationTime = 0;
this.updated = true;
if (status == Status.STARTED)
registerMobs();
}
@@ -82,6 +84,7 @@ public class MapleQuestStatus {
this.setNpc(npc);
this.completionTime = System.currentTimeMillis();
this.expirationTime = 0;
this.updated = true;
if (status == Status.STARTED) {
registerMobs();
}
@@ -102,6 +105,18 @@ public class MapleQuestStatus {
public final void setStatus(Status status) {
this.status = status;
}
public boolean wasUpdated() {
return updated;
}
public void setUpdated() {
this.updated = true;
}
public void resetUpdated() {
this.updated = false;
}
public int getNpc() {
return npc;
@@ -115,11 +130,13 @@ public class MapleQuestStatus {
for (int i : MapleQuest.getInstance(questID).getRelevantMobs()) {
progress.put(i, "000");
}
this.setUpdated();
}
public boolean addMedalMap(int mapid) {
if (medalProgress.contains(mapid)) return false;
medalProgress.add(mapid);
this.setUpdated();
return true;
}
@@ -136,6 +153,7 @@ public class MapleQuestStatus {
int current = Integer.parseInt(progress.get(id));
String str = StringUtil.getLeftPaddedStr(Integer.toString(current + 1), '0', 3);
progress.put(id, str);
this.setUpdated();
return true;
}
return false;
@@ -143,6 +161,7 @@ public class MapleQuestStatus {
public void setProgress(int id, String pr) {
progress.put(id, pr);
this.setUpdated();
}
public boolean madeProgress() {
@@ -202,6 +221,7 @@ public class MapleQuestStatus {
public void setInfo(String newInfo) {
progress.put(0, newInfo);
this.setUpdated();
}
public void setForfeited(int forfeited) {
+34
View File
@@ -68,6 +68,40 @@ public class MapleRing implements Comparable<MapleRing> {
}
}
public static void removeRing(final MapleRing ring) {
try {
if (ring == null) {
return;
}
Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("DELETE FROM rings WHERE id=?");
ps.setInt(1, ring.getRingId());
ps.addBatch();
ps.setInt(1, ring.getPartnerRingId());
ps.addBatch();
ps.executeBatch();
ps.close();
ps = con.prepareStatement("UPDATE inventoryequipment SET ringid=-1 WHERE ringid=?");
ps.setInt(1, ring.getRingId());
ps.addBatch();
ps.setInt(1, ring.getPartnerRingId());
ps.addBatch();
ps.executeBatch();
ps.close();
con.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
public static int createRing(int itemid, final MapleCharacter partner1, final MapleCharacter partner2) {
try {
if (partner1 == null) {
+42 -17
View File
@@ -31,12 +31,15 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.Semaphore;
import tools.locks.MonitoredReentrantLock;
import tools.DatabaseConnection;
import tools.MaplePacketCreator;
import tools.locks.MonitoredLockType;
public final class MonsterBook {
private static final Semaphore semaphore = new Semaphore(10);
private int specialCard = 0;
private int normalCard = 0;
private int bookLevel = 1;
@@ -171,6 +174,43 @@ public final class MonsterBook {
calculateLevel();
}
private static int saveStringConcat(char[] data, int pos, Integer i) {
return saveStringConcat(data, pos, i.toString());
}
private static int saveStringConcat(char[] data, int pos, String s) {
int len = s.length();
for(int j = 0; j < len; j++) {
data[pos + j] = s.charAt(j);
}
return pos + len;
}
private static String getSaveString(Integer charid, Set<Entry<Integer, Integer>> cardSet) {
semaphore.acquireUninterruptibly();
try {
char[] save = new char[400000]; // 500 * 10 * 10 * 8
int i = 0;
i = saveStringConcat(save, i, "INSERT INTO monsterbook VALUES ");
for (Entry<Integer, Integer> all : cardSet) { // assuming maxsize 500 unique cards
i = saveStringConcat(save, i, "(");
i = saveStringConcat(save, i, charid); //10 chars
i = saveStringConcat(save, i, ", ");
i = saveStringConcat(save, i, all.getKey()); //10 chars
i = saveStringConcat(save, i, ", ");
i = saveStringConcat(save, i, all.getValue()); //1 char due to being 0 ~ 5
i = saveStringConcat(save, i, "),");
}
return new String(save, 0, i - 1);
} finally {
semaphore.release();
}
}
public void saveCards(final int charid) {
Set<Entry<Integer, Integer>> cardSet = getCardSet();
@@ -183,23 +223,8 @@ public final class MonsterBook {
ps.setInt(1, charid);
ps.execute();
ps.close();
boolean first = true;
StringBuilder query = new StringBuilder();
for (Entry<Integer, Integer> all : cardSet) {
if (first) {
query.append("INSERT INTO monsterbook VALUES (");
first = false;
} else {
query.append(",(");
}
query.append(charid);
query.append(", ");
query.append(all.getKey());
query.append(", ");
query.append(all.getValue());
query.append(")");
}
ps = con.prepareStatement(query.toString());
ps = con.prepareStatement(getSaveString(charid, cardSet));
ps.execute();
ps.close();
con.close();
+64 -63
View File
@@ -45,6 +45,7 @@ import java.util.List;
import java.util.Properties;
import java.util.TimeZone;
import client.inventory.manipulator.MapleInventoryManipulator;
import net.MaplePacketHandler;
import net.PacketProcessor;
import net.server.Server;
@@ -56,7 +57,6 @@ import provider.MapleDataProviderFactory;
import provider.MapleDataTool;
import scripting.npc.NPCScriptManager;
import scripting.portal.PortalScriptManager;
import server.MapleInventoryManipulator;
import server.MapleItemInformationProvider;
import server.MaplePortal;
import server.MapleShopFactory;
@@ -102,6 +102,7 @@ import client.inventory.Equip;
import client.inventory.MapleInventory;
import client.inventory.MapleInventoryType;
import client.inventory.MaplePet;
import client.processor.BuybackProcessor;
import constants.ItemConstants;
import constants.ServerConstants;
import java.util.ArrayList;
@@ -351,22 +352,6 @@ public class Commands {
MapleCharacter player = c.getPlayer();
switch(sub[0]) {
case "wow":
MaplePlayerNPC.multicastSpawnPlayerNPC(player.getMapId(), player.getWorld());
break;
case "out":
MaplePlayerNPC.removeAllPlayerNPC();
break;
case "er":
MaplePlayerNPC.spawnPlayerNPC(player.getMapId(), player);
break;
case "re":
MaplePlayerNPC.removePlayerNPC(player);
break;
case "help":
case "commands":
case "playercommands":
@@ -383,6 +368,10 @@ public class Commands {
break;
case "buyback":
BuybackProcessor.processBuyback(c);
break;
case "time":
DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
dateFormat.setTimeZone(TimeZone.getTimeZone(ServerConstants.TIMEZONE));
@@ -1222,7 +1211,7 @@ public class Commands {
case "item":
case "drop":
if (sub.length < 2){
if (sub.length < 2) {
player.yellowMessage("Syntax: !item <itemid> <quantity>");
break;
}
@@ -2613,13 +2602,24 @@ public class Commands {
player.getMap().spawnMonsterOnGroundBelow(monster, player.getPosition());
break;
case "pnpcremove":
if (sub.length < 2) {
player.yellowMessage("Syntax: !pnpcremove <playername>");
break;
}
MaplePlayerNPC.removePlayerNPC(c.getChannelServer().getPlayerStorage().getCharacterByName(sub[1]));
break;
case "playernpc":
if (sub.length < 3){
if (sub.length < 2) {
player.yellowMessage("Syntax: !playernpc <playername>");
break;
}
MaplePlayerNPC.spawnPlayerNPC(player.getMapId(), player.getPosition(), c.getChannelServer().getPlayerStorage().getCharacterByName(sub[1]));
if(!MaplePlayerNPC.spawnPlayerNPC(player.getMapId(), player.getPosition(), c.getChannelServer().getPlayerStorage().getCharacterByName(sub[1]))) {
player.dropMessage(5, "Could not deploy PlayerNPC. Either there's no room available here or depleted out scriptids to use.");
}
break;
default:
@@ -2634,53 +2634,48 @@ public class Commands {
MapleMonster monster;
switch(sub[0]) {
case "debugmonster":
case "debugmonster":
List<MapleMapObject> monsters = player.getMap().getMapObjectsInRange(player.getPosition(), Double.POSITIVE_INFINITY, Arrays.asList(MapleMapObjectType.MONSTER));
for (MapleMapObject monstermo : monsters) {
monster = (MapleMonster) monstermo;
player.message("Monster ID: " + monster.getId() + " Aggro target: " + ((monster.getController() != null) ? monster.getController().getName() : "<none>"));
}
break;
break;
case "debugpacket":
case "debugpacket":
player.getMap().broadcastMessage(MaplePacketCreator.customPacket(joinStringFrom(sub, 1)));
break;
case "debugportal":
case "debugportal":
MaplePortal portal = player.getMap().findClosestPortal(player.getPosition());
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;
case "debugspawnpoint":
case "debugspawnpoint":
SpawnPoint sp = player.getMap().findClosestSpawnpoint(player.getPosition());
if(sp != null) player.dropMessage(6, "Closest mob spawn point: " + " Position: x " + sp.getPosition().getX() + " y " + sp.getPosition().getY() + " Spawns mobid: '" + sp.getMonsterId() + "' --> canSpawn: " + !sp.getDenySpawn() + " canSpawnRightNow: " + sp.shouldSpawn() + ".");
else player.dropMessage(6, "There is no mob spawn point on this map.");
break;
case "debugpos":
case "debugpos":
player.dropMessage(6, "Current map position: (" + player.getPosition().getX() + ", " + player.getPosition().getY() + ").");
break;
case "debugmap":
case "debugmap":
player.dropMessage(6, "Current map id " + player.getMap().getId() + ", event: '" + ((player.getMap().getEventInstance() != null) ? player.getMap().getEventInstance().getName() : "null") + "'; Players: " + player.getMap().getAllPlayers().size() + ", Mobs: " + player.getMap().countMonsters() + ", Reactors: " + player.getMap().countReactors() + ", Items: " + player.getMap().countItems() + ", Objects: " + player.getMap().getMapObjects().size() + ".");
break;
case "debugmobsp":
case "debugmobsp":
player.getMap().reportMonsterSpawnPoints(player);
break;
case "debugevent":
case "debugevent":
if(player.getEventInstance() == null) player.dropMessage(6, "Player currently not in an event.");
else player.dropMessage(6, "Current event name: " + player.getEventInstance().getName() + ".");
break;
case "debugareas":
case "debugareas":
player.dropMessage(6, "Configured areas on map " + player.getMapId() + ":");
byte index = 0;
@@ -2688,54 +2683,52 @@ public class Commands {
player.dropMessage(6, "Id: " + index + " -> posX: " + rect.getX() + " posY: '" + rect.getY() + "' dX: " + rect.getWidth() + " dY: " + rect.getHeight() + ".");
index++;
}
break;
case "debugreactors":
case "debugreactors":
player.dropMessage(6, "Current reactor states on map " + player.getMapId() + ":");
for(MapleMapObject mmo: player.getMap().getReactors()) {
MapleReactor mr = (MapleReactor) mmo;
player.dropMessage(6, "Id: " + mr.getId() + " Oid: " + mr.getObjectId() + " name: '" + mr.getName() + "' -> Type: " + mr.getReactorType() + " State: " + mr.getState() + " Event State: " + mr.getEventState() + " Position: x " + mr.getPosition().getX() + " y " + mr.getPosition().getY() + ".");
}
break;
case "debugservercoupons":
case "debugcoupons":
case "debugservercoupons":
case "debugcoupons":
String s = "Currently active SERVER coupons: ";
for(Integer i : Server.getInstance().getActiveCoupons()) {
s += (i + " ");
}
player.dropMessage(6, s);
break;
case "debugplayercoupons":
case "debugplayercoupons":
String st = "Currently active PLAYER coupons: ";
for(Integer i : player.getActiveCoupons()) {
st += (i + " ");
}
player.dropMessage(6, st);
break;
case "debugtimer":
case "debugtimer":
TimerManager tMan = TimerManager.getInstance();
player.dropMessage(6, "Total Task: " + tMan.getTaskCount() + " Current Task: " + tMan.getQueuedTasks() + " Active Task: " + tMan.getActiveCount() + " Completed Task: " + tMan.getCompletedTaskCount());
break;
break;
case "set":
case "debugmarriage":
c.getChannelServer().debugMarriageStatus();
break;
case "set":
for(int i = 0; i < sub.length - 1; i++) {
ServerConstants.DEBUG_VALUES[i] = Integer.parseInt(sub[i + 1]);
}
break;
default:
default:
return false;
}
@@ -2747,7 +2740,7 @@ public class Commands {
MapleCharacter victim;
switch(sub[0]) {
case "setgmlevel":
case "setgmlevel":
if (sub.length < 3){
player.yellowMessage("Syntax: !setgmlevel <playername> <newlevel>");
break;
@@ -2766,7 +2759,7 @@ public class Commands {
}
break;
case "warpworld":
case "warpworld":
if (sub.length < 2){
player.yellowMessage("Syntax: !warpworld <worldid>");
break;
@@ -2793,7 +2786,7 @@ public class Commands {
}
break;
case "saveall":
case "saveall":
for (World world : Server.getInstance().getWorlds()) {
for (MapleCharacter chr : world.getPlayerStorage().getAllCharacters()) {
chr.saveToDB();
@@ -2804,7 +2797,7 @@ public class Commands {
player.message("All players saved successfully.");
break;
case "dcall":
case "dcall":
for (World world : Server.getInstance().getWorlds()) {
for (MapleCharacter chr : world.getPlayerStorage().getAllCharacters()) {
if (!chr.isGM()) {
@@ -2815,7 +2808,7 @@ public class Commands {
player.message("All players successfully disconnected.");
break;
case "mapplayers":
case "mapplayers":
String names = "";
int map = player.getMapId();
for (World world : Server.getInstance().getWorlds()) {
@@ -2832,7 +2825,7 @@ public class Commands {
player.message("These b lurkin: " + names);
break;
case "getacc":
case "getacc":
if (sub.length < 2){
player.yellowMessage("Syntax: !getacc <playername>");
break;
@@ -2845,8 +2838,8 @@ public class Commands {
}
break;
case "shutdown":
case "shutdownnow":
case "shutdown":
case "shutdownnow":
int time = 60000;
if (sub[0].equals("shutdownnow")) {
time = 1;
@@ -2877,12 +2870,12 @@ public class Commands {
TimerManager.getInstance().schedule(Server.getInstance().shutdown(false), time);
break;
case "clearquestcache":
case "clearquestcache":
MapleQuest.clearCache();
player.dropMessage(5, "Quest Cache Cleared.");
break;
case "clearquest":
case "clearquest":
if(sub.length < 1) {
player.dropMessage(5, "Please include a quest ID.");
break;
@@ -2891,11 +2884,19 @@ public class Commands {
player.dropMessage(5, "Quest Cache for quest " + sub[1] + " cleared.");
break;
case "fred":
case "fred":
c.announce(MaplePacketCreator.fredrickMessage(Byte.valueOf(sub[1])));
break;
default:
case "spawnallpnpcs":
MaplePlayerNPC.multicastSpawnPlayerNPC(player.getMapId(), player.getWorld());
break;
case "eraseallpnpcs":
MaplePlayerNPC.removeAllPlayerNPC();
break;
default:
return false;
}
@@ -2942,7 +2943,7 @@ public class Commands {
else return true;
}
public static boolean executeHeavenMSPlayerCommand(MapleClient c, String[] sub, char heading) {
public static boolean executeHeavenMsPlayerCommand(MapleClient c, String[] sub, char heading) {
Channel cserv = c.getChannelServer();
Server srv = Server.getInstance();
+94
View File
@@ -0,0 +1,94 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft (L) 2016 - 2018 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client.creator;
import client.MapleClient;
import client.MapleCharacter;
import client.MapleSkinColor;
import client.inventory.Item;
import client.inventory.MapleInventory;
import client.inventory.MapleInventoryType;
import net.server.Server;
import server.MapleItemInformationProvider;
import tools.MaplePacketCreator;
/**
*
* @author RonanLana
*/
public abstract class CharacterFactory {
protected synchronized static int createNewCharacter(MapleClient c, String name, int face, int hair, int skin, int gender, CharacterFactoryRecipe recipe) {
if (!MapleCharacter.canCreateChar(name)) {
return -1;
}
MapleCharacter newchar = MapleCharacter.getDefault(c);
newchar.setWorld(c.getWorld());
newchar.setSkinColor(MapleSkinColor.getById(skin));
newchar.setGender(gender);
newchar.setName(name);
newchar.setHair(hair);
newchar.setFace(face);
newchar.setLevel(recipe.getLevel());
newchar.setJob(recipe.getJob());
newchar.setMapId(recipe.getMap());
MapleInventory equipped = newchar.getInventory(MapleInventoryType.EQUIPPED);
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
int top = recipe.getTop(), bottom = recipe.getBottom(), shoes = recipe.getShoes(), weapon = recipe.getWeapon();
if(top > 0) {
Item eq_top = ii.getEquipById(top);
eq_top.setPosition((byte) -5);
equipped.addFromDB(eq_top);
}
if(bottom > 0) {
Item eq_bottom = ii.getEquipById(bottom);
eq_bottom.setPosition((byte) -6);
equipped.addFromDB(eq_bottom);
}
if(shoes > 0) {
Item eq_shoes = ii.getEquipById(shoes);
eq_shoes.setPosition((byte) -7);
equipped.addFromDB(eq_shoes);
}
if(weapon > 0) {
Item eq_weapon = ii.getEquipById(weapon);
eq_weapon.setPosition((byte) -11);
equipped.addFromDB(eq_weapon.copy());
}
if (!newchar.insertNewChar(recipe)) {
return -2;
}
c.announce(MaplePacketCreator.addNewCharEntry(newchar));
Server.getInstance().createCharacterid(newchar.getAccountID(), newchar.getId(), newchar.getWorld());
Server.getInstance().broadcastGMMessage(c.getWorld(), MaplePacketCreator.sendYellowTip("[NEW CHAR]: " + c.getAccountName() + " has created a new character with IGN " + name));
return 0;
}
}
@@ -0,0 +1,184 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft (L) 2016 - 2018 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client.creator;
import client.MapleJob;
import client.Skill;
import client.inventory.Item;
import client.inventory.MapleInventoryType;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import tools.Pair;
/**
*
* @author RonanLana
*/
public class CharacterFactoryRecipe {
private MapleJob job;
private int level, map, top, bottom, shoes, weapon;
private int str = 4, dex = 4, int_ = 4, luk = 4;
private int maxHp = 50, maxMp = 5;
private int ap = 0, sp = 0;
private int meso = 0;
private List<Pair<Skill, Integer>> skills = new LinkedList<>();
private List<Pair<Item, MapleInventoryType>> itemsWithType = new LinkedList<>();
private Map<MapleInventoryType, AtomicInteger> runningTypePosition = new LinkedHashMap<>();
public CharacterFactoryRecipe(MapleJob job, int level, int map, int top, int bottom, int shoes, int weapon) {
this.job = job;
this.level = level;
this.map = map;
this.top = top;
this.bottom = bottom;
this.shoes = shoes;
this.weapon = weapon;
}
public void setStr(int v) {
str = v;
}
public void setDex(int v) {
dex = v;
}
public void setInt(int v) {
int_ = v;
}
public void setLuk(int v) {
luk = v;
}
public void setMaxHp(int v) {
maxHp = v;
}
public void setMaxMp(int v) {
maxMp = v;
}
public void setRemainingAp(int v) {
ap = v;
}
public void setRemainingSp(int v) {
sp = v;
}
public void setMeso(int v) {
meso = v;
}
public void addStartingSkillLevel(Skill skill, int level) {
skills.add(new Pair<>(skill, level));
}
public void addStartingEquipment(Item eqpItem) {
itemsWithType.add(new Pair<>(eqpItem, MapleInventoryType.EQUIP));
}
public void addStartingItem(int itemid, int quantity, MapleInventoryType itemType) {
AtomicInteger p = runningTypePosition.get(itemType);
if(p == null) {
p = new AtomicInteger(0);
runningTypePosition.put(itemType, p);
}
itemsWithType.add(new Pair<>(new Item(itemid, (short) p.getAndIncrement(), (short) quantity), itemType));
}
public MapleJob getJob() {
return job;
}
public int getLevel() {
return level;
}
public int getMap() {
return map;
}
public int getTop() {
return top;
}
public int getBottom() {
return bottom;
}
public int getShoes() {
return shoes;
}
public int getWeapon() {
return weapon;
}
public int getStr() {
return str;
}
public int getDex() {
return dex;
}
public int getInt() {
return int_;
}
public int getLuk() {
return luk;
}
public int getMaxHp() {
return maxHp;
}
public int getMaxMp() {
return maxMp;
}
public int getRemainingAp() {
return ap;
}
public int getRemainingSp() {
return sp;
}
public int getMeso() {
return meso;
}
public List<Pair<Skill, Integer>> getStartingSkillLevel() {
return skills;
}
public List<Pair<Item, MapleInventoryType>> getStartingItems() {
return itemsWithType;
}
}
@@ -0,0 +1,48 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft (L) 2016 - 2018 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client.creator.novice;
import client.MapleClient;
import client.MapleJob;
import client.creator.CharacterFactory;
import client.creator.CharacterFactoryRecipe;
import client.inventory.MapleInventoryType;
/**
*
* @author RonanLana
*/
public class BeginnerCreator extends CharacterFactory {
private static CharacterFactoryRecipe createRecipe(MapleJob job, int level, int map, int top, int bottom, int shoes, int weapon) {
CharacterFactoryRecipe recipe = new CharacterFactoryRecipe(job, level, map, top, bottom, shoes, weapon);
giveItem(recipe, 4161001, 1, MapleInventoryType.ETC);
return recipe;
}
private static void giveItem(CharacterFactoryRecipe recipe, int itemid, int quantity, MapleInventoryType itemType) {
recipe.addStartingItem(itemid, quantity, itemType);
}
public static int createCharacter(MapleClient c, String name, int face, int hair, int skin, int top, int bottom, int shoes, int weapon, int gender) {
int status = createNewCharacter(c, name, face, hair, skin, gender, createRecipe(MapleJob.BEGINNER, 1, 10000, top, bottom, shoes, weapon));
return status;
}
}
@@ -0,0 +1,48 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft (L) 2016 - 2018 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client.creator.novice;
import client.MapleClient;
import client.MapleJob;
import client.creator.CharacterFactory;
import client.creator.CharacterFactoryRecipe;
import client.inventory.MapleInventoryType;
/**
*
* @author RonanLana
*/
public class LegendCreator extends CharacterFactory {
private static CharacterFactoryRecipe createRecipe(MapleJob job, int level, int map, int top, int bottom, int shoes, int weapon) {
CharacterFactoryRecipe recipe = new CharacterFactoryRecipe(job, level, map, top, bottom, shoes, weapon);
giveItem(recipe, 4161048, 1, MapleInventoryType.ETC);
return recipe;
}
private static void giveItem(CharacterFactoryRecipe recipe, int itemid, int quantity, MapleInventoryType itemType) {
recipe.addStartingItem(itemid, quantity, itemType);
}
public static int createCharacter(MapleClient c, String name, int face, int hair, int skin, int top, int bottom, int shoes, int weapon, int gender) {
int status = createNewCharacter(c, name, face, hair, skin, gender, createRecipe(MapleJob.LEGEND, 1, 914000000, top, bottom, shoes, weapon));
return status;
}
}
@@ -0,0 +1,48 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft (L) 2016 - 2018 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client.creator.novice;
import client.MapleClient;
import client.MapleJob;
import client.creator.CharacterFactory;
import client.creator.CharacterFactoryRecipe;
import client.inventory.MapleInventoryType;
/**
*
* @author RonanLana
*/
public class NoblesseCreator extends CharacterFactory {
private static CharacterFactoryRecipe createRecipe(MapleJob job, int level, int map, int top, int bottom, int shoes, int weapon) {
CharacterFactoryRecipe recipe = new CharacterFactoryRecipe(job, level, map, top, bottom, shoes, weapon);
giveItem(recipe, 4161047, 1, MapleInventoryType.ETC);
return recipe;
}
private static void giveItem(CharacterFactoryRecipe recipe, int itemid, int quantity, MapleInventoryType itemType) {
recipe.addStartingItem(itemid, quantity, itemType);
}
public static int createCharacter(MapleClient c, String name, int face, int hair, int skin, int top, int bottom, int shoes, int weapon, int gender) {
int status = createNewCharacter(c, name, face, hair, skin, gender, createRecipe(MapleJob.NOBLESSE, 1, 130030000, top, bottom, shoes, weapon));
return status;
}
}
@@ -0,0 +1,75 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft (L) 2016 - 2018 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client.creator.veteran;
import client.MapleClient;
import client.MapleJob;
import client.creator.CharacterFactory;
import client.creator.CharacterFactoryRecipe;
import client.inventory.Item;
import client.inventory.MapleInventoryType;
import server.MapleItemInformationProvider;
/**
*
* @author RonanLana
*/
public class BowmanCreator extends CharacterFactory {
private static int[] equips = {1040067, 1041054, 1060056, 1061050, 1072081};
private static int[] weapons = {1452005, 1462000};
private static int[] startingHpMp = {797, 404};
private static CharacterFactoryRecipe createRecipe(MapleJob job, int level, int map, int top, int bottom, int shoes, int weapon) {
CharacterFactoryRecipe recipe = new CharacterFactoryRecipe(job, level, map, top, bottom, shoes, weapon);
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
recipe.setDex(25);
recipe.setRemainingAp(133);
recipe.setRemainingSp(61);
recipe.setMaxHp(startingHpMp[0]);
recipe.setMaxMp(startingHpMp[1]);
recipe.setMeso(100000);
for(int i = 1; i < weapons.length; i++) {
giveEquipment(recipe, ii, weapons[i]);
}
giveItem(recipe, 2000002, 100, MapleInventoryType.USE);
giveItem(recipe, 2000003, 100, MapleInventoryType.USE);
giveItem(recipe, 3010000, 1, MapleInventoryType.SETUP);
return recipe;
}
private static void giveEquipment(CharacterFactoryRecipe recipe, MapleItemInformationProvider ii, int equipid) {
Item nEquip = ii.getEquipById(equipid);
recipe.addStartingEquipment(nEquip);
}
private static void giveItem(CharacterFactoryRecipe recipe, int itemid, int quantity, MapleInventoryType itemType) {
recipe.addStartingItem(itemid, quantity, itemType);
}
public static int createCharacter(MapleClient c, String name, int face, int hair, int skin, int gender, int improveSp) {
return createNewCharacter(c, name, face, hair, skin, gender, createRecipe(MapleJob.BOWMAN, 30, 100000000, equips[gender], equips[2 + gender], equips[4], weapons[0]));
}
}
@@ -0,0 +1,98 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft (L) 2016 - 2018 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client.creator.veteran;
import client.MapleClient;
import client.MapleJob;
import client.Skill;
import client.SkillFactory;
import client.creator.CharacterFactory;
import client.creator.CharacterFactoryRecipe;
import client.inventory.Item;
import client.inventory.MapleInventoryType;
import constants.skills.Magician;
import server.MapleItemInformationProvider;
/**
*
* @author RonanLana
*/
public class MagicianCreator extends CharacterFactory {
private static int[] equips = {0, 1041041, 0, 1061034, 1072075};
private static int[] weapons = {1372003, 1382017};
private static int[] startingHpMp = {405, 729};
private static int[] mpGain = {0, 40, 80, 118, 156, 194, 230, 266, 302, 336, 370};
private static CharacterFactoryRecipe createRecipe(MapleJob job, int level, int map, int top, int bottom, int shoes, int weapon, int gender, int improveSp) {
CharacterFactoryRecipe recipe = new CharacterFactoryRecipe(job, level, map, top, bottom, shoes, weapon);
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
recipe.setInt(20);
recipe.setRemainingAp(138);
recipe.setRemainingSp(67);
recipe.setMaxHp(startingHpMp[0]);
recipe.setMaxMp(startingHpMp[1] + mpGain[improveSp]);
recipe.setMeso(100000);
if(gender == 0) {
giveEquipment(recipe, ii, 1050003);
}
for(int i = 1; i < weapons.length; i++) {
giveEquipment(recipe, ii, weapons[i]);
}
giveItem(recipe, 2000001, 100, MapleInventoryType.USE);
giveItem(recipe, 2000006, 100, MapleInventoryType.USE);
giveItem(recipe, 3010000, 1, MapleInventoryType.SETUP);
if(improveSp > 0) {
improveSp += 5;
recipe.setRemainingSp(recipe.getRemainingSp() - improveSp);
int toUseSp = 5;
Skill improveMpRec = SkillFactory.getSkill(Magician.IMPROVED_MP_RECOVERY);
recipe.addStartingSkillLevel(improveMpRec, toUseSp);
improveSp -= toUseSp;
if(improveSp > 0) {
Skill improveMaxMp = SkillFactory.getSkill(Magician.IMPROVED_MAX_MP_INCREASE);
recipe.addStartingSkillLevel(improveMaxMp, improveSp);
}
}
return recipe;
}
private static void giveEquipment(CharacterFactoryRecipe recipe, MapleItemInformationProvider ii, int equipid) {
Item nEquip = ii.getEquipById(equipid);
recipe.addStartingEquipment(nEquip);
}
private static void giveItem(CharacterFactoryRecipe recipe, int itemid, int quantity, MapleInventoryType itemType) {
recipe.addStartingItem(itemid, quantity, itemType);
}
public static int createCharacter(MapleClient c, String name, int face, int hair, int skin, int gender, int improveSp) {
return createNewCharacter(c, name, face, hair, skin, gender, createRecipe(MapleJob.MAGICIAN, 30, 101000000, equips[gender], equips[2 + gender], equips[4], weapons[0], gender, improveSp));
}
}
@@ -0,0 +1,79 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft (L) 2016 - 2018 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client.creator.veteran;
import client.MapleClient;
import client.MapleJob;
import client.creator.CharacterFactory;
import client.creator.CharacterFactoryRecipe;
import client.inventory.Item;
import client.inventory.MapleInventoryType;
import server.MapleItemInformationProvider;
/**
*
* @author RonanLana
*/
public class PirateCreator extends CharacterFactory {
private static int[] equips = {0, 0, 0, 0, 1072294};
private static int[] weapons = {1482004, 1492004};
private static int[] startingHpMp = {846, 503};
private static CharacterFactoryRecipe createRecipe(MapleJob job, int level, int map, int top, int bottom, int shoes, int weapon) {
CharacterFactoryRecipe recipe = new CharacterFactoryRecipe(job, level, map, top, bottom, shoes, weapon);
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
recipe.setDex(20);
recipe.setRemainingAp(138);
recipe.setRemainingSp(61);
recipe.setMaxHp(startingHpMp[0]);
recipe.setMaxMp(startingHpMp[1]);
recipe.setMeso(100000);
giveEquipment(recipe, ii, 1052107);
for(int i = 1; i < weapons.length; i++) {
giveEquipment(recipe, ii, weapons[i]);
}
giveItem(recipe, 2330000, 800, MapleInventoryType.USE);
giveItem(recipe, 2000002, 100, MapleInventoryType.USE);
giveItem(recipe, 2000003, 100, MapleInventoryType.USE);
giveItem(recipe, 3010000, 1, MapleInventoryType.SETUP);
return recipe;
}
private static void giveEquipment(CharacterFactoryRecipe recipe, MapleItemInformationProvider ii, int equipid) {
Item nEquip = ii.getEquipById(equipid);
recipe.addStartingEquipment(nEquip);
}
private static void giveItem(CharacterFactoryRecipe recipe, int itemid, int quantity, MapleInventoryType itemType) {
recipe.addStartingItem(itemid, quantity, itemType);
}
public static int createCharacter(MapleClient c, String name, int face, int hair, int skin, int gender, int improveSp) {
return createNewCharacter(c, name, face, hair, skin, gender, createRecipe(MapleJob.PIRATE, 30, 120000000, equips[gender], equips[2 + gender], equips[4], weapons[0]));
}
}
@@ -0,0 +1,77 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft (L) 2016 - 2018 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client.creator.veteran;
import client.MapleClient;
import client.MapleJob;
import client.creator.CharacterFactory;
import client.creator.CharacterFactoryRecipe;
import client.inventory.Item;
import client.inventory.MapleInventoryType;
import server.MapleItemInformationProvider;
/**
*
* @author RonanLana
*/
public class ThiefCreator extends CharacterFactory {
private static int[] equips = {1040057, 1041047, 1060043, 1061043, 1072032};
private static int[] weapons = {1472008, 1332012};
private static int[] startingHpMp = {794, 407};
private static CharacterFactoryRecipe createRecipe(MapleJob job, int level, int map, int top, int bottom, int shoes, int weapon) {
CharacterFactoryRecipe recipe = new CharacterFactoryRecipe(job, level, map, top, bottom, shoes, weapon);
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
recipe.setDex(25);
recipe.setRemainingAp(133);
recipe.setRemainingSp(61);
recipe.setMaxHp(startingHpMp[0]);
recipe.setMaxMp(startingHpMp[1]);
recipe.setMeso(100000);
for(int i = 1; i < weapons.length; i++) {
giveEquipment(recipe, ii, weapons[i]);
}
giveItem(recipe, 2070000, 500, MapleInventoryType.USE);
giveItem(recipe, 2000002, 100, MapleInventoryType.USE);
giveItem(recipe, 2000003, 100, MapleInventoryType.USE);
giveItem(recipe, 3010000, 1, MapleInventoryType.SETUP);
return recipe;
}
private static void giveEquipment(CharacterFactoryRecipe recipe, MapleItemInformationProvider ii, int equipid) {
Item nEquip = ii.getEquipById(equipid);
recipe.addStartingEquipment(nEquip);
}
private static void giveItem(CharacterFactoryRecipe recipe, int itemid, int quantity, MapleInventoryType itemType) {
recipe.addStartingItem(itemid, quantity, itemType);
}
public static int createCharacter(MapleClient c, String name, int face, int hair, int skin, int gender, int improveSp) {
return createNewCharacter(c, name, face, hair, skin, gender, createRecipe(MapleJob.THIEF, 30, 103000000, equips[gender], equips[2 + gender], equips[4], weapons[0]));
}
}
@@ -0,0 +1,98 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft (L) 2016 - 2018 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client.creator.veteran;
import client.MapleClient;
import client.MapleJob;
import client.Skill;
import client.SkillFactory;
import client.creator.CharacterFactory;
import client.creator.CharacterFactoryRecipe;
import client.inventory.Item;
import client.inventory.MapleInventoryType;
import constants.skills.Warrior;
import server.MapleItemInformationProvider;
/**
*
* @author RonanLana
*/
public class WarriorCreator extends CharacterFactory {
private static int[] equips = {1040021, 0, 1060016, 0, 1072039};
private static int[] weapons = {1302008, 1442001, 1422001, 1312005};
private static int[] startingHpMp = {905, 208};
private static int[] hpGain = {0, 72, 144, 212, 280, 348, 412, 476, 540, 600, 660};
private static CharacterFactoryRecipe createRecipe(MapleJob job, int level, int map, int top, int bottom, int shoes, int weapon, int gender, int improveSp) {
CharacterFactoryRecipe recipe = new CharacterFactoryRecipe(job, level, map, top, bottom, shoes, weapon);
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
recipe.setStr(35);
recipe.setRemainingAp(123);
recipe.setRemainingSp(61);
recipe.setMaxHp(startingHpMp[0] + hpGain[improveSp]);
recipe.setMaxMp(startingHpMp[1]);
recipe.setMeso(100000);
if(gender == 1) {
giveEquipment(recipe, ii, 1051010);
}
for(int i = 1; i < weapons.length; i++) {
giveEquipment(recipe, ii, weapons[i]);
}
if(improveSp > 0) {
improveSp += 5;
recipe.setRemainingSp(recipe.getRemainingSp() - improveSp);
int toUseSp = 5;
Skill improveHpRec = SkillFactory.getSkill(Warrior.IMPROVED_HPREC);
recipe.addStartingSkillLevel(improveHpRec, toUseSp);
improveSp -= toUseSp;
if(improveSp > 0) {
Skill improveMaxHp = SkillFactory.getSkill(Warrior.IMPROVED_MAXHP);
recipe.addStartingSkillLevel(improveMaxHp, improveSp);
}
}
giveItem(recipe, 2000002, 100, MapleInventoryType.USE);
giveItem(recipe, 2000003, 100, MapleInventoryType.USE);
giveItem(recipe, 3010000, 1, MapleInventoryType.SETUP);
return recipe;
}
private static void giveEquipment(CharacterFactoryRecipe recipe, MapleItemInformationProvider ii, int equipid) {
Item nEquip = ii.getEquipById(equipid);
recipe.addStartingEquipment(nEquip);
}
private static void giveItem(CharacterFactoryRecipe recipe, int itemid, int quantity, MapleInventoryType itemType) {
recipe.addStartingItem(itemid, quantity, itemType);
}
public static int createCharacter(MapleClient c, String name, int face, int hair, int skin, int gender, int improveSp) {
return createNewCharacter(c, name, face, hair, skin, gender, createRecipe(MapleJob.WARRIOR, 30, 102000000, equips[gender], equips[2 + gender], equips[4], weapons[0], gender, improveSp));
}
}
-1
View File
@@ -26,7 +26,6 @@ import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import server.MapleItemInformationProvider;
public class Item implements Comparable<Item> {
+1 -1
View File
@@ -39,7 +39,7 @@ import client.MapleCharacter;
import client.MapleClient;
import constants.ItemConstants;
import server.MapleItemInformationProvider;
import server.MapleInventoryManipulator;
import client.inventory.manipulator.MapleInventoryManipulator;
import tools.FilePrinter;
import tools.locks.MonitoredLockType;
+6 -8
View File
@@ -209,14 +209,12 @@ public class MaplePet extends Item {
enjoyed = true;
} else {
if (incCloseness > 0) {
int newCloseness = closeness - 1;
if (newCloseness < 0) newCloseness = 0;
closeness = newCloseness;
if (level > 1 && newCloseness < ExpTable.getClosenessNeededForLevel(level - 1)) {
level -= 1;
}
int newCloseness = closeness - 1;
if (newCloseness < 0) newCloseness = 0;
closeness = newCloseness;
if (level > 1 && newCloseness < ExpTable.getClosenessNeededForLevel(level - 1)) {
level -= 1;
}
enjoyed = false;
@@ -0,0 +1,628 @@
/*
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/>.
*/
package client.inventory.manipulator;
import client.MapleBuffStat;
import client.MapleClient;
import client.inventory.Equip;
import client.inventory.Item;
import client.inventory.MapleInventory;
import client.inventory.MapleInventoryType;
import client.inventory.ModifyInventory;
import client.newyear.NewYearCardRecord;
import constants.ItemConstants;
import constants.ServerConstants;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import server.MapleItemInformationProvider;
import tools.FilePrinter;
import tools.MaplePacketCreator;
/**
*
* @author Matze
*/
public class MapleInventoryManipulator {
public static boolean addById(MapleClient c, int itemId, short quantity) {
return addById(c, itemId, quantity, null, -1, -1);
}
public static boolean addById(MapleClient c, int itemId, short quantity, long expiration) {
return addById(c, itemId, quantity, null, -1, (byte) 0, expiration);
}
public static boolean addById(MapleClient c, int itemId, short quantity, String owner, int petid) {
return addById(c, itemId, quantity, owner, petid, -1);
}
public static boolean addById(MapleClient c, int itemId, short quantity, String owner, int petid, long expiration) {
return addById(c, itemId, quantity, owner, petid, (byte) 0, expiration);
}
public static boolean addById(MapleClient c, int itemId, short quantity, String owner, int petid, byte flag, long expiration) {
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
MapleInventoryType type = ItemConstants.getInventoryType(itemId);
if (!type.equals(MapleInventoryType.EQUIP)) {
short slotMax = ii.getSlotMax(c, itemId);
List<Item> existing = c.getPlayer().getInventory(type).listById(itemId);
if (!ItemConstants.isRechargeable(itemId) && petid == -1) {
if (existing.size() > 0) { // first update all existing slots to slotMax
Iterator<Item> i = existing.iterator();
while (quantity > 0) {
if (i.hasNext()) {
Item eItem = (Item) i.next();
short oldQ = eItem.getQuantity();
if (oldQ < slotMax && (eItem.getOwner().equals(owner) || owner == null)) {
short newQ = (short) Math.min(oldQ + quantity, slotMax);
quantity -= (newQ - oldQ);
eItem.setQuantity(newQ);
eItem.setExpiration(expiration);
c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(1, eItem))));
}
} else {
break;
}
}
}
while (quantity > 0 || ItemConstants.isRechargeable(itemId)) {
short newQ = (short) Math.min(quantity, slotMax);
if (newQ != 0) {
quantity -= newQ;
Item nItem = new Item(itemId, (short) 0, newQ, petid);
nItem.setFlag(flag);
nItem.setExpiration(expiration);
short newSlot = c.getPlayer().getInventory(type).addItem(nItem);
if (newSlot == -1) {
c.announce(MaplePacketCreator.getInventoryFull());
c.announce(MaplePacketCreator.getShowInventoryFull());
return false;
}
if (owner != null) {
nItem.setOwner(owner);
}
c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(0, nItem))));
if ((ItemConstants.isRechargeable(itemId)) && quantity == 0) {
break;
}
} else {
c.announce(MaplePacketCreator.enableActions());
return false;
}
}
} else {
Item nItem = new Item(itemId, (short) 0, quantity, petid);
nItem.setFlag(flag);
nItem.setExpiration(expiration);
short newSlot = c.getPlayer().getInventory(type).addItem(nItem);
if (newSlot == -1) {
c.announce(MaplePacketCreator.getInventoryFull());
c.announce(MaplePacketCreator.getShowInventoryFull());
return false;
}
c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(0, nItem))));
}
} else if (quantity == 1) {
Item nEquip = ii.getEquipById(itemId);
nEquip.setFlag(flag);
nEquip.setExpiration(expiration);
if (owner != null) {
nEquip.setOwner(owner);
}
short newSlot = c.getPlayer().getInventory(type).addItem(nEquip);
if (newSlot == -1) {
c.announce(MaplePacketCreator.getInventoryFull());
c.announce(MaplePacketCreator.getShowInventoryFull());
return false;
}
c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(0, nEquip))));
} else {
throw new RuntimeException("Trying to create equip with non-one quantity");
}
return true;
}
public static boolean addFromDrop(MapleClient c, Item item) {
return addFromDrop(c, item, true);
}
public static boolean addFromDrop(MapleClient c, Item item, boolean show) {
return addFromDrop(c, item, show, item.getPetId());
}
public static boolean addFromDrop(MapleClient c, Item item, boolean show, int petId) {
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
MapleInventoryType type = item.getInventoryType();
if (ii.isPickupRestricted(item.getItemId()) && c.getPlayer().haveItemWithId(item.getItemId(), true)) {
c.announce(MaplePacketCreator.getInventoryFull());
c.announce(MaplePacketCreator.showItemUnavailable());
return false;
}
short quantity = item.getQuantity();
if (!type.equals(MapleInventoryType.EQUIP)) {
short slotMax = ii.getSlotMax(c, item.getItemId());
List<Item> existing = c.getPlayer().getInventory(type).listById(item.getItemId());
if (!ItemConstants.isRechargeable(item.getItemId()) && petId == -1) {
if (existing.size() > 0) { // first update all existing slots to slotMax
Iterator<Item> i = existing.iterator();
while (quantity > 0) {
if (i.hasNext()) {
Item eItem = (Item) i.next();
short oldQ = eItem.getQuantity();
if (oldQ < slotMax && item.getOwner().equals(eItem.getOwner())) {
short newQ = (short) Math.min(oldQ + quantity, slotMax);
quantity -= (newQ - oldQ);
eItem.setQuantity(newQ);
c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(1, eItem))));
}
} else {
break;
}
}
}
while (quantity > 0) {
short newQ = (short) Math.min(quantity, slotMax);
quantity -= newQ;
Item nItem = new Item(item.getItemId(), (short) 0, newQ, petId);
nItem.setExpiration(item.getExpiration());
nItem.setOwner(item.getOwner());
nItem.setFlag(item.getFlag());
short newSlot = c.getPlayer().getInventory(type).addItem(nItem);
if (newSlot == -1) {
c.announce(MaplePacketCreator.getInventoryFull());
c.announce(MaplePacketCreator.getShowInventoryFull());
item.setQuantity((short) (quantity + newQ));
return false;
}
c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(0, nItem))));
}
} else {
Item nItem = new Item(item.getItemId(), (short) 0, quantity, petId);
nItem.setExpiration(item.getExpiration());
short newSlot = c.getPlayer().getInventory(type).addItem(nItem);
if (newSlot == -1) {
c.announce(MaplePacketCreator.getInventoryFull());
c.announce(MaplePacketCreator.getShowInventoryFull());
return false;
}
c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(0, nItem))));
c.announce(MaplePacketCreator.enableActions());
}
} else if (quantity == 1) {
short newSlot = c.getPlayer().getInventory(type).addItem(item);
if (newSlot == -1) {
c.announce(MaplePacketCreator.getInventoryFull());
c.announce(MaplePacketCreator.getShowInventoryFull());
return false;
}
c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(0, item))));
} else {
FilePrinter.printError(FilePrinter.ITEM, "Tried to pickup Equip id " + item.getItemId() + " containing more than 1 quantity --> " + quantity);
c.announce(MaplePacketCreator.getInventoryFull());
c.announce(MaplePacketCreator.showItemUnavailable());
return false;
}
if (show) {
c.announce(MaplePacketCreator.getShowItemGain(item.getItemId(), item.getQuantity()));
}
return true;
}
private static boolean haveItemWithId(MapleInventory inv, int itemid) {
return inv.findById(itemid) != null;
}
public static boolean checkSpace(MapleClient c, int itemid, int quantity, String owner) {
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
MapleInventoryType type = ItemConstants.getInventoryType(itemid);
if(ii.isPickupRestricted(itemid) && haveItemWithId(c.getPlayer().getInventory(type), itemid)) {
return false;
}
if (!type.equals(MapleInventoryType.EQUIP)) {
short slotMax = ii.getSlotMax(c, itemid);
List<Item> existing = c.getPlayer().getInventory(type).listById(itemid);
if (!ItemConstants.isRechargeable(itemid)) {
if (existing.size() > 0) // first update all existing slots to slotMax
{
for (Item eItem : existing) {
short oldQ = eItem.getQuantity();
if (oldQ < slotMax && owner.equals(eItem.getOwner())) {
short newQ = (short) Math.min(oldQ + quantity, slotMax);
quantity -= (newQ - oldQ);
}
if (quantity <= 0) {
break;
}
}
}
}
final int numSlotsNeeded;
if (slotMax > 0) {
numSlotsNeeded = (int) (Math.ceil(((double) quantity) / slotMax));
} else if (ItemConstants.isRechargeable(itemid)) {
numSlotsNeeded = 1;
} else {
numSlotsNeeded = 1;
}
return !c.getPlayer().getInventory(type).isFull(numSlotsNeeded - 1);
} else {
return !c.getPlayer().getInventory(type).isFull();
}
}
public static int checkSpaceProgressively(MapleClient c, int itemid, int quantity, String owner, int usedSlots) {
// return value --> bit0: if has space for this one;
// value after: new slots filled;
// assumption: equipments always have slotMax == 1.
int returnValue;
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
MapleInventoryType type = ItemConstants.getInventoryType(itemid);
if(ii.isPickupRestricted(itemid) && haveItemWithId(c.getPlayer().getInventory(type), itemid)) {
return 0;
}
if (!type.equals(MapleInventoryType.EQUIP)) {
short slotMax = ii.getSlotMax(c, itemid);
if (!ItemConstants.isRechargeable(itemid)) {
List<Item> existing = c.getPlayer().getInventory(type).listById(itemid);
if (existing.size() > 0) // first update all existing slots to slotMax
{
for (Item eItem : existing) {
short oldQ = eItem.getQuantity();
if (oldQ < slotMax && owner.equals(eItem.getOwner())) {
short newQ = (short) Math.min(oldQ + quantity, slotMax);
quantity -= (newQ - oldQ);
}
if (quantity <= 0) {
break;
}
}
}
}
final int numSlotsNeeded;
if (slotMax > 0) {
numSlotsNeeded = (int) (Math.ceil(((double) quantity) / slotMax));
} else if (ItemConstants.isRechargeable(itemid)) {
numSlotsNeeded = 1;
} else {
numSlotsNeeded = 1;
}
returnValue = ((numSlotsNeeded + usedSlots) << 1);
returnValue += (numSlotsNeeded == 0 || !c.getPlayer().getInventory(type).isFullAfterSomeItems(numSlotsNeeded - 1, usedSlots)) ? 1 : 0;
//System.out.print(" needed " + numSlotsNeeded + " used " + usedSlots + " rval " + returnValue);
} else {
returnValue = ((quantity + usedSlots) << 1);
returnValue += (!c.getPlayer().getInventory(type).isFullAfterSomeItems(0, usedSlots)) ? 1 : 0;
//System.out.print(" eqpneeded " + 1 + " used " + usedSlots + " rval " + returnValue);
}
return returnValue;
}
public static void removeFromSlot(MapleClient c, MapleInventoryType type, short slot, short quantity, boolean fromDrop) {
removeFromSlot(c, type, slot, quantity, fromDrop, false);
}
public static void removeFromSlot(MapleClient c, MapleInventoryType type, short slot, short quantity, boolean fromDrop, boolean consume) {
Item item = c.getPlayer().getInventory(type).getItem(slot);
boolean allowZero = consume && ItemConstants.isRechargeable(item.getItemId());
c.getPlayer().getInventory(type).removeItem(slot, quantity, allowZero);
if (item.getQuantity() == 0 && !allowZero) {
c.announce(MaplePacketCreator.modifyInventory(fromDrop, Collections.singletonList(new ModifyInventory(3, item))));
} else {
c.announce(MaplePacketCreator.modifyInventory(fromDrop, Collections.singletonList(new ModifyInventory(1, item))));
}
}
public static void removeById(MapleClient c, MapleInventoryType type, int itemId, int quantity, boolean fromDrop, boolean consume) {
int removeQuantity = quantity;
MapleInventory inv = c.getPlayer().getInventory(type);
int slotLimit = type == MapleInventoryType.EQUIPPED ? 128 : inv.getSlotLimit();
for (short i = 0; i <= slotLimit; i++) {
Item item = inv.getItem((short) (type == MapleInventoryType.EQUIPPED ? -i : i));
if (item != null) {
if (item.getItemId() == itemId || item.getCashId() == itemId) {
if (removeQuantity <= item.getQuantity()) {
removeFromSlot(c, type, item.getPosition(), (short) removeQuantity, fromDrop, consume);
removeQuantity = 0;
break;
} else {
removeQuantity -= item.getQuantity();
removeFromSlot(c, type, item.getPosition(), item.getQuantity(), fromDrop, consume);
}
}
}
}
if (removeQuantity > 0) {
throw new RuntimeException("[HACK] Not enough items available of Item:" + itemId + ", Quantity (After Quantity/Over Current Quantity): " + (quantity - removeQuantity) + "/" + quantity);
}
}
private static boolean isSameOwner(Item source, Item target) {
return source.getOwner().equals(target.getOwner());
}
public static void move(MapleClient c, MapleInventoryType type, short src, short dst) {
if (src < 0 || dst < 0) {
return;
}
if(dst > c.getPlayer().getInventory(type).getSlotLimit()) {
return;
}
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
Item source = c.getPlayer().getInventory(type).getItem(src);
Item initialTarget = c.getPlayer().getInventory(type).getItem(dst);
if (source == null) {
return;
}
short olddstQ = -1;
if (initialTarget != null) {
olddstQ = initialTarget.getQuantity();
}
short oldsrcQ = source.getQuantity();
short slotMax = ii.getSlotMax(c, source.getItemId());
c.getPlayer().getInventory(type).move(src, dst, slotMax);
final List<ModifyInventory> mods = new ArrayList<>();
if (!(type.equals(MapleInventoryType.EQUIP) || type.equals(MapleInventoryType.CASH)) && initialTarget != null && initialTarget.getItemId() == source.getItemId() && !ItemConstants.isRechargeable(source.getItemId()) && isSameOwner(source, initialTarget)) {
if ((olddstQ + oldsrcQ) > slotMax) {
mods.add(new ModifyInventory(1, source));
mods.add(new ModifyInventory(1, initialTarget));
} else {
mods.add(new ModifyInventory(3, source));
mods.add(new ModifyInventory(1, initialTarget));
}
} else {
mods.add(new ModifyInventory(2, source, src));
}
c.announce(MaplePacketCreator.modifyInventory(true, mods));
}
public static void equip(MapleClient c, short src, short dst) {
Equip source = (Equip) c.getPlayer().getInventory(MapleInventoryType.EQUIP).getItem(src);
if (source == null || !MapleItemInformationProvider.getInstance().canWearEquipment(c.getPlayer(), source, dst)) {
c.announce(MaplePacketCreator.enableActions());
return;
} else if ((((source.getItemId() >= 1902000 && source.getItemId() <= 1902002) || source.getItemId() == 1912000) && c.getPlayer().isCygnus()) || ((source.getItemId() >= 1902005 && source.getItemId() <= 1902007) || source.getItemId() == 1912005) && !c.getPlayer().isCygnus()) {// Adventurer taming equipment
return;
}
boolean itemChanged = false;
if (MapleItemInformationProvider.getInstance().isUntradeableOnEquip(source.getItemId())) {
source.setFlag((byte) ItemConstants.UNTRADEABLE);
itemChanged = true;
}
if (source.getRingId() > -1) {
c.getPlayer().getRingById(source.getRingId()).equip();
}
if (dst == -6) { // unequip the overall
Item top = c.getPlayer().getInventory(MapleInventoryType.EQUIPPED).getItem((short) -5);
if (top != null && ItemConstants.isOverall(top.getItemId())) {
if (c.getPlayer().getInventory(MapleInventoryType.EQUIP).isFull()) {
c.announce(MaplePacketCreator.getInventoryFull());
c.announce(MaplePacketCreator.getShowInventoryFull());
return;
}
unequip(c, (byte) -5, c.getPlayer().getInventory(MapleInventoryType.EQUIP).getNextFreeSlot());
}
} else if (dst == -5) {
final Item bottom = c.getPlayer().getInventory(MapleInventoryType.EQUIPPED).getItem((short) -6);
if (bottom != null && ItemConstants.isOverall(source.getItemId())) {
if (c.getPlayer().getInventory(MapleInventoryType.EQUIP).isFull()) {
c.announce(MaplePacketCreator.getInventoryFull());
c.announce(MaplePacketCreator.getShowInventoryFull());
return;
}
unequip(c, (byte) -6, c.getPlayer().getInventory(MapleInventoryType.EQUIP).getNextFreeSlot());
}
} else if (dst == -10) {// check if weapon is two-handed
Item weapon = c.getPlayer().getInventory(MapleInventoryType.EQUIPPED).getItem((short) -11);
if (weapon != null && MapleItemInformationProvider.getInstance().isTwoHanded(weapon.getItemId())) {
if (c.getPlayer().getInventory(MapleInventoryType.EQUIP).isFull()) {
c.announce(MaplePacketCreator.getInventoryFull());
c.announce(MaplePacketCreator.getShowInventoryFull());
return;
}
unequip(c, (byte) -11, c.getPlayer().getInventory(MapleInventoryType.EQUIP).getNextFreeSlot());
}
} else if (dst == -11) {
Item shield = c.getPlayer().getInventory(MapleInventoryType.EQUIPPED).getItem((short) -10);
if (shield != null && MapleItemInformationProvider.getInstance().isTwoHanded(source.getItemId())) {
if (c.getPlayer().getInventory(MapleInventoryType.EQUIP).isFull()) {
c.announce(MaplePacketCreator.getInventoryFull());
c.announce(MaplePacketCreator.getShowInventoryFull());
return;
}
unequip(c, (byte) -10, c.getPlayer().getInventory(MapleInventoryType.EQUIP).getNextFreeSlot());
}
}
if (dst == -18) {
if (c.getPlayer().getMount() != null) {
c.getPlayer().getMount().setItemId(source.getItemId());
}
}
if (source.getItemId() == 1122017) {
c.getPlayer().equipPendantOfSpirit();
}
//1112413, 1112414, 1112405 (Lilin's Ring)
source = (Equip) c.getPlayer().getInventory(MapleInventoryType.EQUIP).getItem(src);
Equip target = (Equip) c.getPlayer().getInventory(MapleInventoryType.EQUIPPED).getItem(dst);
c.getPlayer().getInventory(MapleInventoryType.EQUIP).removeSlot(src);
if (target != null) {
c.getPlayer().getInventory(MapleInventoryType.EQUIPPED).removeSlot(dst);
}
final List<ModifyInventory> mods = new ArrayList<>();
if (itemChanged) {
mods.add(new ModifyInventory(3, source));
mods.add(new ModifyInventory(0, source.copy()));//to prevent crashes
}
source.setPosition(dst);
c.getPlayer().getInventory(MapleInventoryType.EQUIPPED).addFromDB(source);
if (target != null) {
target.setPosition(src);
c.getPlayer().getInventory(MapleInventoryType.EQUIP).addFromDB(target);
}
if (c.getPlayer().getBuffedValue(MapleBuffStat.BOOSTER) != null && ItemConstants.isWeapon(source.getItemId())) {
c.getPlayer().cancelBuffStats(MapleBuffStat.BOOSTER);
}
mods.add(new ModifyInventory(2, source, src));
c.announce(MaplePacketCreator.modifyInventory(true, mods));
c.getPlayer().equipChanged();
}
public static void unequip(MapleClient c, short src, short dst) {
Equip source = (Equip) c.getPlayer().getInventory(MapleInventoryType.EQUIPPED).getItem(src);
Equip target = (Equip) c.getPlayer().getInventory(MapleInventoryType.EQUIP).getItem(dst);
if (dst < 0) {
return;
}
if (source == null) {
return;
}
if (target != null && src <= 0) {
c.announce(MaplePacketCreator.getInventoryFull());
return;
}
if (source.getItemId() == 1122017) {
c.getPlayer().unequipPendantOfSpirit();
}
if (source.getRingId() > -1) {
c.getPlayer().getRingById(source.getRingId()).unequip();
}
c.getPlayer().getInventory(MapleInventoryType.EQUIPPED).removeSlot(src);
if (target != null) {
c.getPlayer().getInventory(MapleInventoryType.EQUIP).removeSlot(dst);
}
source.setPosition(dst);
c.getPlayer().getInventory(MapleInventoryType.EQUIP).addFromDB(source);
if (target != null) {
target.setPosition(src);
c.getPlayer().getInventory(MapleInventoryType.EQUIPPED).addFromDB(target);
}
c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(2, source, src))));
c.getPlayer().equipChanged();
}
public static void drop(MapleClient c, MapleInventoryType type, short src, short quantity) {
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
if (src < 0) {
type = MapleInventoryType.EQUIPPED;
}
Item source = c.getPlayer().getInventory(type).getItem(src);
if (c.getPlayer().getTrade() != null || c.getPlayer().getMiniGame() != null || source == null) { //Only check needed would prob be merchants (to see if the player is in one)
return;
}
int itemId = source.getItemId();
if (ItemConstants.isPet(itemId)) {
return;
}
if (type == MapleInventoryType.EQUIPPED && itemId == 1122017) {
c.getPlayer().unequipPendantOfSpirit();
}
if (c.getPlayer().getItemEffect() == itemId && source.getQuantity() == 1) {
c.getPlayer().setItemEffect(0);
c.getPlayer().getMap().broadcastMessage(MaplePacketCreator.itemEffect(c.getPlayer().getId(), 0));
} else if (itemId == 5370000 || itemId == 5370001) {
if (c.getPlayer().getItemQuantity(itemId, false) == 1) {
c.getPlayer().setChalkboard(null);
}
}
if ((!ItemConstants.isRechargeable(itemId) && source.getQuantity() < quantity) || quantity < 0) {
return;
}
Point dropPos = new Point(c.getPlayer().getPosition());
if (quantity < source.getQuantity() && !ItemConstants.isRechargeable(itemId)) {
Item target = source.copy();
target.setQuantity(quantity);
source.setQuantity((short) (source.getQuantity() - quantity));
c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(1, source))));
if(ItemConstants.isNewYearCardEtc(itemId)) {
if(itemId == 4300000) {
NewYearCardRecord.removeAllNewYearCard(true, c.getPlayer());
c.getAbstractPlayerInteraction().removeAll(4300000);
} else {
NewYearCardRecord.removeAllNewYearCard(false, c.getPlayer());
c.getAbstractPlayerInteraction().removeAll(4301000);
}
} else if (ItemConstants.isWeddingRing(source.getItemId())) {
c.getPlayer().getMap().disappearingItemDrop(c.getPlayer(), c.getPlayer(), target, dropPos);
} else if (c.getPlayer().getMap().getEverlast()) {
if (ii.isDropRestricted(target.getItemId()) || ii.isCash(target.getItemId()) || isDroppedItemRestricted(target)) {
c.getPlayer().getMap().disappearingItemDrop(c.getPlayer(), c.getPlayer(), target, dropPos);
} else {
c.getPlayer().getMap().spawnItemDrop(c.getPlayer(), c.getPlayer(), target, dropPos, true, true);
}
} else if (ii.isDropRestricted(target.getItemId()) || ii.isCash(target.getItemId()) || isDroppedItemRestricted(target)) {
c.getPlayer().getMap().disappearingItemDrop(c.getPlayer(), c.getPlayer(), target, dropPos);
} else {
c.getPlayer().getMap().spawnItemDrop(c.getPlayer(), c.getPlayer(), target, dropPos, true, true);
}
} else {
c.getPlayer().getInventory(type).removeSlot(src);
c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(3, source))));
if (src < 0) {
c.getPlayer().equipChanged();
} else if(ItemConstants.isNewYearCardEtc(itemId)) {
if(itemId == 4300000) {
NewYearCardRecord.removeAllNewYearCard(true, c.getPlayer());
c.getAbstractPlayerInteraction().removeAll(4300000);
} else {
NewYearCardRecord.removeAllNewYearCard(false, c.getPlayer());
c.getAbstractPlayerInteraction().removeAll(4301000);
}
}
if (c.getPlayer().getMap().getEverlast()) {
if (ii.isDropRestricted(itemId) || ii.isCash(itemId) || isDroppedItemRestricted(source)) {
c.getPlayer().getMap().disappearingItemDrop(c.getPlayer(), c.getPlayer(), source, dropPos);
} else {
c.getPlayer().getMap().spawnItemDrop(c.getPlayer(), c.getPlayer(), source, dropPos, true, true);
}
} else if (ii.isDropRestricted(itemId) || ii.isCash(itemId) || isDroppedItemRestricted(source)) {
c.getPlayer().getMap().disappearingItemDrop(c.getPlayer(), c.getPlayer(), source, dropPos);
} else {
c.getPlayer().getMap().spawnItemDrop(c.getPlayer(), c.getPlayer(), source, dropPos, true, true);
}
}
}
private static boolean isDroppedItemRestricted(Item it) {
return ServerConstants.USE_ERASE_UNTRADEABLE_DROP && ((it.getFlag() & ItemConstants.UNTRADEABLE) == ItemConstants.UNTRADEABLE);
}
}
@@ -0,0 +1,64 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft (L) 2016 - 2018 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client.inventory.manipulator;
import constants.ItemConstants;
import client.inventory.Item;
/**
*
* @author RonanLana
*/
public class MapleKarmaManipulator {
private static int getKarmaFlag(Item item) {
return item.getItemType() == 1 ? ItemConstants.KARMA_EQP : ItemConstants.KARMA_USE;
}
public static boolean hasKarmaFlag(Item item) {
int karmaFlag = getKarmaFlag(item);
return (item.getFlag() & karmaFlag) == karmaFlag;
}
public static boolean hasUsedKarmaFlag(Item item) {
int karmaFlag = ItemConstants.KARMA_UNTRADEABLE;
return (item.getFlag() & karmaFlag) == karmaFlag;
}
public static void toggleKarmaFlagToUntradeable(Item item) {
int karmaFlag = getKarmaFlag(item);
int flag = item.getFlag();
if ((flag & karmaFlag) == karmaFlag) {
flag ^= karmaFlag;
flag |= ItemConstants.UNTRADEABLE;
flag |= ItemConstants.KARMA_UNTRADEABLE;
item.setFlag((byte) flag);
}
}
public static void setKarmaFlag(Item item) {
int karmaFlag = getKarmaFlag(item);
int flag = item.getFlag();
flag |= karmaFlag;
item.setFlag((byte) flag);
}
}
+104
View File
@@ -0,0 +1,104 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft (L) 2016 - 2018 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client.processor;
import client.MapleClient;
import client.MapleCharacter;
import client.MapleStat;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import server.maps.MapleMap;
import server.movement.AbsoluteLifeMovement;
import server.movement.LifeMovementFragment;
import tools.MaplePacketCreator;
import tools.Pair;
/**
*
* @author RonanLana
*/
public class BuybackProcessor {
public static void processBuyback(MapleClient c) {
MapleCharacter chr = c.getPlayer();
boolean buyback;
c.lockClient();
try {
buyback = !chr.isAlive() && chr.couldBuyback();
} finally {
c.unlockClient();
}
if(buyback) {
String jobString;
switch(chr.getJobStyle()) {
case WARRIOR:
jobString = "warrior";
break;
case MAGICIAN:
jobString = "magician";
break;
case BOWMAN:
jobString = "bowman";
break;
case THIEF:
jobString = "thief";
break;
case BRAWLER:
case GUNSLINGER:
jobString = "pirate";
break;
default:
jobString = "beginner";
}
chr.setStance(0);
chr.setHp(chr.getMaxHp());
chr.setMp(chr.getMaxMp());
List<Pair<MapleStat, Integer>> hpmpupdate = new ArrayList<>(2);
hpmpupdate.add(new Pair<>(MapleStat.HP, Integer.valueOf(chr.getHp())));
hpmpupdate.add(new Pair<>(MapleStat.MP, Integer.valueOf(chr.getMp())));
c.announce(MaplePacketCreator.updatePlayerStats(hpmpupdate, true, chr));
AbsoluteLifeMovement alm = new AbsoluteLifeMovement(0, chr.getPosition(), 0, 0);
alm.setPixelsPerSecond(new Point(0, 0));
List<LifeMovementFragment> moveUpdate = Collections.singletonList((LifeMovementFragment) alm);
MapleMap map = chr.getMap();
map.broadcastMessage(chr, MaplePacketCreator.movePlayer(c.getPlayer().getId(), moveUpdate), false);
map.broadcastMessage(MaplePacketCreator.playSound("Buyback/" + jobString));
map.broadcastMessage(MaplePacketCreator.earnTitleMessage(chr.getName() + " just bought back into the game!"));
chr.announce(MaplePacketCreator.showBuybackEffect());
map.broadcastMessage(chr, MaplePacketCreator.showForeignBuybackEffect(chr.getId()), false);
}
}
}
+39 -28
View File
@@ -29,6 +29,8 @@ import client.autoban.AutobanFactory;
import client.inventory.Equip;
import client.inventory.Item;
import client.inventory.MapleInventoryType;
import client.inventory.manipulator.MapleInventoryManipulator;
import client.inventory.manipulator.MapleKarmaManipulator;
import constants.ItemConstants;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -39,7 +41,6 @@ import java.util.LinkedList;
import java.util.List;
import net.server.channel.Channel;
import server.DueyPackages;
import server.MapleInventoryManipulator;
import server.MapleItemInformationProvider;
import tools.DatabaseConnection;
import tools.FilePrinter;
@@ -163,10 +164,12 @@ public class DueyProcessor {
eq.setHands((short) rs.getInt("hands"));
eq.setSpeed((short) rs.getInt("speed"));
eq.setJump((short) rs.getInt("jump"));
eq.setFlag((byte) rs.getInt("flag"));
eq.setOwner(rs.getString("owner"));
dueypack = new DueyPackages(rs.getInt("PackageId"), eq);
} else if (rs.getInt("type") == 2) {
Item newItem = new Item(rs.getInt("itemid"), (short) 0, (short) rs.getInt("quantity"));
newItem.setFlag((byte) rs.getInt("flag"));
newItem.setOwner(rs.getString("owner"));
dueypack = new DueyPackages(rs.getInt("PackageId"), newItem);
} else {
@@ -186,13 +189,13 @@ public class DueyProcessor {
ResultSet rs = null;
try {
con = DatabaseConnection.getConnection();
ps = con.prepareStatement("SELECT Mesos FROM dueypackages WHERE RecieverId = ? and Checked = 1");
ps = con.prepareStatement("SELECT Mesos FROM dueypackages WHERE ReceiverId = ? and Checked = 1");
ps.setInt(1, player.getId());
rs = ps.executeQuery();
if (rs.next()) {
try {
Connection con2 = DatabaseConnection.getConnection();
pss = con2.prepareStatement("UPDATE dueypackages SET Checked = 0 where RecieverId = ?");
pss = con2.prepareStatement("UPDATE dueypackages SET Checked = 0 where ReceiverId = ?");
pss.setInt(1, player.getId());
pss.executeUpdate();
pss.close();
@@ -225,31 +228,33 @@ public class DueyProcessor {
}
}
private static int getFee(int meso) {
int fee = 0;
if (meso >= 10000000) {
fee = meso / 25;
private static int getFee(long meso) {
long fee = 0;
if (meso >= 100000000) {
fee = (meso * 6) / 100;
} else if (meso >= 25000000) {
fee = (meso * 5) / 100;
} else if (meso >= 10000000) {
fee = (meso * 4) / 100;
} else if (meso >= 5000000) {
fee = meso * 3 / 100;
fee = (meso * 3) / 100;
} else if (meso >= 1000000) {
fee = meso / 50;
fee = (meso * 18) / 1000;
} else if (meso >= 100000) {
fee = meso / 100;
} else if (meso >= 50000) {
fee = meso / 200;
fee = (meso * 8) / 1000;
}
return fee;
return (int) fee;
}
private static void addMesoToDB(int mesos, String sName, int recipientID) {
addItemToDB(null, 1, mesos, sName, recipientID);
}
private static void addItemToDB(Item item, int quantity, int mesos, String sName, int recipientID) {
public static void addItemToDB(Item item, int quantity, int mesos, String sName, int recipientID) {
Connection con = null;
try {
con = DatabaseConnection.getConnection();
try (PreparedStatement ps = con.prepareStatement("INSERT INTO dueypackages (RecieverId, SenderName, Mesos, TimeStamp, Checked, Type) VALUES (?, ?, ?, ?, ?, ?)")) {
try (PreparedStatement ps = con.prepareStatement("INSERT INTO dueypackages (ReceiverId, SenderName, Mesos, TimeStamp, Checked, Type) VALUES (?, ?, ?, ?, ?, ?)")) {
ps.setInt(1, recipientID);
ps.setString(2, sName);
ps.setInt(3, mesos);
@@ -266,7 +271,7 @@ public class DueyProcessor {
rs.next();
PreparedStatement ps2;
if (item.getInventoryType().equals(MapleInventoryType.EQUIP)) {
ps2 = con.prepareStatement("INSERT INTO dueyitems (PackageId, itemid, quantity, upgradeslots, level, str, dex, `int`, luk, hp, mp, watk, matk, wdef, mdef, acc, avoid, hands, speed, jump, owner) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
ps2 = con.prepareStatement("INSERT INTO dueyitems (PackageId, itemid, quantity, upgradeslots, level, str, dex, `int`, luk, hp, mp, watk, matk, wdef, mdef, acc, avoid, hands, speed, jump, flag, owner) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
Equip eq = (Equip) item;
ps2.setInt(2, eq.getItemId());
ps2.setInt(3, 1);
@@ -287,12 +292,14 @@ public class DueyProcessor {
ps2.setInt(18, eq.getHands());
ps2.setInt(19, eq.getSpeed());
ps2.setInt(20, eq.getJump());
ps2.setString(21, eq.getOwner());
ps2.setInt(21, eq.getFlag());
ps2.setString(22, eq.getOwner());
} else {
ps2 = con.prepareStatement("INSERT INTO dueyitems (PackageId, itemid, quantity, owner) VALUES (?, ?, ?, ?)");
ps2 = con.prepareStatement("INSERT INTO dueyitems (PackageId, itemid, quantity, flag, owner) VALUES (?, ?, ?, ?, ?)");
ps2.setInt(2, item.getItemId());
ps2.setInt(3, quantity);
ps2.setString(4, item.getOwner());
ps2.setInt(4, item.getFlag());
ps2.setString(5, item.getOwner());
}
ps2.setInt(1, rs.getInt(1));
ps2.executeUpdate();
@@ -312,7 +319,7 @@ public class DueyProcessor {
Connection con = null;
try {
con = DatabaseConnection.getConnection();
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM dueypackages dp LEFT JOIN dueyitems di ON dp.PackageId=di.PackageId WHERE RecieverId = ?")) {
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM dueypackages dp LEFT JOIN dueyitems di ON dp.PackageId=di.PackageId WHERE ReceiverId = ?")) {
ps.setInt(1, chr.getId());
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
@@ -337,13 +344,14 @@ public class DueyProcessor {
c.lockClient();
try {
final int fee = 5000;
if (mesos < 0 || ((long) mesos + fee + getFee(mesos)) > Integer.MAX_VALUE || (amount < 1 && mesos == 0)) {
final long sendMesos = (long) mesos + fee;
if (mesos < 0 || sendMesos > Integer.MAX_VALUE || (amount < 1 && mesos == 0)) {
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit with duey.");
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to use duey with mesos " + mesos + " and amount " + amount + "\r\n");
c.disconnect(true, false);
return;
}
int finalcost = mesos + fee + getFee(mesos);
int finalcost = mesos + fee;
boolean send = false;
if (c.getPlayer().getMeso() >= finalcost) {
int accid = getAccIdFromCNAME(recipient, true);
@@ -382,7 +390,8 @@ public class DueyProcessor {
MapleInventoryManipulator.removeFromSlot(c, inv, itemPos, amount, true, false);
}
addItemToDB(item, amount, mesos, c.getPlayer().getName(), getAccIdFromCNAME(recipient, false));
MapleKarmaManipulator.toggleKarmaFlagToUntradeable(item);
addItemToDB(item, amount, mesos - getFee(mesos), c.getPlayer().getName(), getAccIdFromCNAME(recipient, false));
} else {
if (item != null) {
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_INCORRECT_REQUEST.getCode()));
@@ -393,7 +402,7 @@ public class DueyProcessor {
c.getPlayer().gainMeso(-finalcost, false);
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_SUCCESSFULLY_SENT.getCode()));
addMesoToDB(mesos, c.getPlayer().getName(), getAccIdFromCNAME(recipient, false));
addMesoToDB(mesos - getFee(mesos), c.getPlayer().getName(), getAccIdFromCNAME(recipient, false));
}
if (rClient != null && rClient.isLoggedIn() && !rClient.getPlayer().isAwayFromWorld()) {
@@ -460,14 +469,16 @@ public class DueyProcessor {
}
}
long gainmesos = 0;
long totalmesos = (long) dp.getMesos() + (long) c.getPlayer().getMeso();
long gainmesos;
long totalmesos = (long) dp.getMesos() + c.getPlayer().getMeso();
if (totalmesos < 0 || dp.getMesos() < 0) gainmesos = 0;
else {
if (totalmesos < 0 || dp.getMesos() < 0) {
gainmesos = 0;
} else {
totalmesos = Math.min(totalmesos, Integer.MAX_VALUE);
gainmesos = totalmesos - c.getPlayer().getMeso();
}
c.getPlayer().gainMeso((int)gainmesos, false);
removeItemFromDB(packageid);
+1 -1
View File
@@ -33,7 +33,7 @@ import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
import server.MapleInventoryManipulator;
import client.inventory.manipulator.MapleInventoryManipulator;
import server.MapleItemInformationProvider;
import server.maps.MapleHiredMerchant;
import tools.DatabaseConnection;
+476
View File
@@ -0,0 +1,476 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft (L) 2016 - 2018 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client.processor;
import client.MapleClient;
import client.inventory.Equip;
import client.inventory.Item;
import client.inventory.MapleInventoryType;
import constants.ItemConstants;
import constants.ServerConstants;
import client.inventory.manipulator.MapleInventoryManipulator;
import constants.EquipType;
import constants.GameConstants;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import server.MakerItemFactory;
import server.MapleItemInformationProvider;
import tools.FilePrinter;
import tools.MaplePacketCreator;
import tools.Pair;
import tools.data.input.SeekableLittleEndianAccessor;
/**
*
* @author Ronan
*/
public class MakerProcessor {
private static MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
public static void makerAction(SeekableLittleEndianAccessor slea, MapleClient c) {
c.lockClient();
try {
int type = slea.readInt();
int toCreate = slea.readInt();
int toDisassemble = -1, pos = -1;
boolean makerSucceeded = true;
MakerItemFactory.MakerItemCreateEntry recipe;
Map<Integer, Short> reagentids = new LinkedHashMap<>();
int stimulantid = -1;
if(type == 3) { // building monster crystal
int fromLeftover = toCreate;
toCreate = ii.getMakerCrystalFromLeftover(toCreate);
if(toCreate == -1) {
c.announce(MaplePacketCreator.serverNotice(1, ii.getName(toCreate) + " is unavailable for Monster Crystal conversion."));
return;
}
recipe = MakerItemFactory.generateLeftoverCrystalEntry(fromLeftover);
} else if(type == 4) { // disassembling
slea.readInt(); // 1... probably inventory type
pos = slea.readInt();
Item it = c.getPlayer().getInventory(MapleInventoryType.EQUIP).getItem((short) pos);
if(it != null && it.getItemId() == toCreate) {
Pair<Integer, Integer> p;
if((p = generateDisassemblyInfo(toCreate)) != null) {
recipe = MakerItemFactory.generateDisassemblyCrystalEntry(p.getLeft(), p.getRight());
toDisassemble = toCreate;
toCreate = ii.getMakerCrystalFromEquip(toCreate);
} else {
c.announce(MaplePacketCreator.serverNotice(1, ii.getName(toCreate) + " is unavailable for Monster Crystal disassembly."));
return;
}
} else {
c.announce(MaplePacketCreator.serverNotice(1, "An unknown error occurred when trying to apply that item for disassembly."));
return;
}
} else {
if(ItemConstants.isEquipment(toCreate)) { // only equips uses stimulant and reagents
if(slea.readByte() != 0) { // stimulant
stimulantid = getMakerStimulant(toCreate);
if(!c.getAbstractPlayerInteraction().haveItem(stimulantid)) {
stimulantid = -1;
}
}
int reagents = Math.min(slea.readInt(), getMakerReagentSlots(toCreate));
for(int i = 0; i < reagents; i++) { // crystals
int reagentid = slea.readInt();
if(ItemConstants.isMakerReagent(reagentid)) {
Short rs = reagentids.get(reagentid);
if(rs == null) {
reagentids.put(reagentid, (short) 1);
} else {
reagentids.put(reagentid, (short) (rs + 1));
}
}
}
List<Pair<Integer, Short>> toUpdate = new LinkedList<>();
for(Map.Entry<Integer, Short> r : reagentids.entrySet()) {
int qty = c.getAbstractPlayerInteraction().getItemQuantity(r.getKey());
if(qty < r.getValue()) {
toUpdate.add(new Pair<>(r.getKey(), (short) qty));
}
}
// remove those not present on player inventory
if(!toUpdate.isEmpty()) {
for(Pair<Integer, Short> rp : toUpdate) {
if(rp.getRight() > 0) {
reagentids.put(rp.getLeft(), rp.getRight());
} else {
reagentids.remove(rp.getLeft());
}
}
}
if(!reagentids.isEmpty()) {
if(!removeOddMakerReagents(toCreate, reagentids)) {
c.announce(MaplePacketCreator.serverNotice(1, "You can only use WATK and MATK Strengthening Gems on weapon items."));
return;
}
}
}
recipe = MakerItemFactory.getItemCreateEntry(toCreate, stimulantid, reagentids);
}
short createStatus = getCreateStatus(c, recipe);
switch(createStatus) {
case -1:// non-available for Maker itemid has been tried to forge
FilePrinter.printError(FilePrinter.EXPLOITS, "Player " + c.getPlayer().getName() + " tried to craft itemid " + toCreate + " using the Maker skill.");
c.announce(MaplePacketCreator.serverNotice(1, "The requested item could not be crafted on this operation."));
break;
case 1: // no items
c.announce(MaplePacketCreator.serverNotice(1, "You don't have all required items in your inventory to make " + recipe.getRewardAmount() + " " + ii.getName(toCreate) + "."));
break;
case 2: // no meso
c.announce(MaplePacketCreator.serverNotice(1, "You don't have enough mesos (" + GameConstants.numberWithCommas(recipe.getCost()) + ") to complete this operation."));
break;
case 3: // no req level
c.announce(MaplePacketCreator.serverNotice(1, "You don't have enough level to complete this operation."));
break;
case 4: // no req skill level
c.announce(MaplePacketCreator.serverNotice(1, "You don't have enough Maker level to complete this operation."));
break;
default:
if (MapleInventoryManipulator.checkSpace(c, toCreate, (short) recipe.getRewardAmount(), "")) {
for (Pair<Integer, Integer> p : recipe.getReqItems()) {
c.getAbstractPlayerInteraction().gainItem(p.getLeft(), (short) -p.getRight());
}
if(toDisassemble != -1) {
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.EQUIP, (short) pos, (short) 1, false);
c.announce(MaplePacketCreator.getShowItemGain(toDisassemble, (short) -1, true));
}
int cost = recipe.getCost();
if(stimulantid == -1 && reagentids.isEmpty()) {
if(cost > 0) c.getPlayer().gainMeso(-cost);
c.getPlayer().setCS(true);
c.getAbstractPlayerInteraction().gainItem(toCreate, (short) recipe.getRewardAmount());
c.getPlayer().setCS(false);
} else {
if(stimulantid != -1) c.getAbstractPlayerInteraction().gainItem(stimulantid, (short) -1);
if(!reagentids.isEmpty()) {
for(Map.Entry<Integer, Short> r : reagentids.entrySet()) {
c.getAbstractPlayerInteraction().gainItem(r.getKey(), (short) (-1 * r.getValue()));
}
}
if(cost > 0) c.getPlayer().gainMeso(-cost);
makerSucceeded = addBoostedMakerItem(c, toCreate, stimulantid, reagentids);
}
if(makerSucceeded) c.announce(MaplePacketCreator.serverNotice(1, "You have successfully created " + recipe.getRewardAmount() + " " + ii.getName(toCreate) + "."));
else c.getPlayer().dropMessage(5, "The Maker skill lights up, but the skill winds up as if nothing happened.");
c.announce(MaplePacketCreator.showMakerEffect(makerSucceeded));
c.getPlayer().getMap().broadcastMessage(c.getPlayer(), MaplePacketCreator.showForeignMakerEffect(c.getPlayer().getId(), makerSucceeded), false);
if(toCreate == 4260003 && c.getPlayer().getQuestStatus(6033) == 1) {
c.getAbstractPlayerInteraction().setQuestProgress(6033, 1);
}
} else {
c.announce(MaplePacketCreator.serverNotice(1, "Your inventory is full."));
}
}
} finally {
c.unlockClient();
}
}
// checks and prevents hackers from PE'ing Maker operations with invalid operations
private static boolean removeOddMakerReagents(int toCreate, Map<Integer, Short> reagentids) {
Map<Integer, Integer> reagentType = new LinkedHashMap<>();
List<Integer> toRemove = new LinkedList<>();
boolean isWeapon = ItemConstants.isWeapon(toCreate) || ServerConstants.USE_MAKER_PERMISSIVE_ATKUP;
for(Map.Entry<Integer, Short> r : reagentids.entrySet()) {
int curRid = r.getKey();
int type = r.getKey() / 100;
if(type < 42502 && !isWeapon) { // only weapons should gain w.att/m.att from these.
return false; //toRemove.add(curRid);
} else {
Integer tableRid = reagentType.get(type);
if(tableRid != null) {
if(tableRid < curRid) {
toRemove.add(tableRid);
reagentType.put(type, curRid);
} else {
toRemove.add(curRid);
}
} else {
reagentType.put(type, curRid);
}
}
}
// removing less effective gems of repeated type
for(Integer i : toRemove) {
reagentids.remove(i);
}
// only quantity 1 of each gem will be accepted by the Maker skill
for(Integer i : reagentids.keySet()) {
reagentids.put(i, (short) 1);
}
return true;
}
private static int getMakerReagentSlots(int itemId) {
try {
int eqpLevel = ii.getEquipStats(itemId).get("reqLevel");
if(eqpLevel < 78) {
return 1;
} else if(eqpLevel >= 78 && eqpLevel < 108) {
return 2;
} else {
return 3;
}
} catch(NullPointerException npe) {
return 0;
}
}
private static int getMakerStimulant(int itemId) {
EquipType et = EquipType.getEquipTypeById(itemId);
switch(et) {
case GLOVES:
return 4130000;
case SHOES:
return 4130001;
case SWORD:
return 4130002;
case AXE:
return 4130003;
case MACE:
return 4130004;
case SWORD_2H:
return 4130005;
case AXE_2H:
return 4130006;
case MACE_2H:
return 4130007;
case SPEAR:
return 4130008;
case POLEARM:
return 4130009;
case WAND:
return 4130010;
case STAFF:
return 4130011;
case BOW:
return 4130012;
case CROSSBOW:
return 4130013;
case DAGGER:
return 4130014;
case CLAW:
return 4130015;
case KNUCKLER:
return 4130016;
case PISTOL:
return 4130017;
case CAP:
return 4130018;
case COAT:
return 4130019;
case PANTS:
return 4130020;
case LONGCOAT:
return 4130021;
case SHIELD:
return 4130022;
default:
return -1;
}
}
private static Pair<Integer, Integer> generateDisassemblyInfo(int itemId) {
int recvFee = ii.getMakerDisassembledFee(itemId);
if(recvFee > -1) {
int recvQty = ii.getMakerDisassembledQuantity(itemId);
if(recvQty > 0) {
return new Pair<>(recvFee, recvQty);
}
}
return null;
}
private static short getCreateStatus(MapleClient c, MakerItemFactory.MakerItemCreateEntry recipe) {
if(recipe == null) {
return -1;
}
if(!hasItems(c, recipe)) {
return 1;
}
if(c.getPlayer().getMeso() < recipe.getCost()) {
return 2;
}
if(c.getPlayer().getLevel() < recipe.getReqLevel()) {
return 3;
}
if(c.getPlayer().getSkillLevel((c.getPlayer().getJob().getId() / 1000) * 10000000 + 1007) < recipe.getReqSkillLevel()) {
return 4;
}
return 0;
}
private static boolean hasItems(MapleClient c, MakerItemFactory.MakerItemCreateEntry recipe) {
for (Pair<Integer, Integer> p : recipe.getReqItems()) {
int itemId = p.getLeft();
if (c.getPlayer().getInventory(ItemConstants.getInventoryType(itemId)).countById(itemId) < p.getRight()) {
return false;
}
}
return true;
}
private static boolean addBoostedMakerItem(MapleClient c, int itemid, int stimulantid, Map<Integer, Short> reagentids) {
if(stimulantid != -1 && !ii.rollSuccessChance(90.0)) {
return false;
}
Item item = ii.getEquipById(itemid);
if(item == null) return false;
Equip eqp = (Equip)item;
if(ItemConstants.isAccessory(item.getItemId()) && eqp.getUpgradeSlots() <= 0) eqp.setUpgradeSlots(3);
if(ServerConstants.USE_ENHANCED_CRAFTING == true) {
if(!(c.getPlayer().isGM() && ServerConstants.USE_PERFECT_GM_SCROLL)) {
eqp.setUpgradeSlots((byte)(eqp.getUpgradeSlots() + 1));
}
item = MapleItemInformationProvider.getInstance().scrollEquipWithId(eqp, 2049100, true, 2049100, c.getPlayer().isGM());
}
if(!reagentids.isEmpty()) {
Map<String, Integer> stats = new LinkedHashMap<>();
List<Short> randOption = new LinkedList<>();
List<Short> randStat = new LinkedList<>();
for(Map.Entry<Integer, Short> r : reagentids.entrySet()) {
Pair<String, Integer> reagentBuff = ii.getMakerReagentStatUpgrade(r.getKey());
if(reagentBuff != null) {
String s = reagentBuff.getLeft();
if(s.substring(0, 4).contains("rand")) {
if(s.substring(4).equals("Stat")) {
randStat.add((short) (reagentBuff.getRight() * r.getValue()));
} else {
randOption.add((short) (reagentBuff.getRight() * r.getValue()));
}
} else {
String stat = s.substring(3);
if(!stat.equals("ReqLevel")) { // improve req level... really?
switch (stat) {
case "MaxHP":
stat = "MHP";
break;
case "MaxMP":
stat = "MMP";
break;
}
Integer d = stats.get(stat);
if(d == null) {
stats.put(stat, reagentBuff.getRight() * r.getValue());
} else {
stats.put(stat, d + (reagentBuff.getRight() * r.getValue()));
}
}
}
}
}
ii.improveEquipStats(eqp, stats);
for(Short sh : randStat) {
ii.scrollOptionEquipWithChaos(eqp, sh, false);
}
for(Short sh : randOption) {
ii.scrollOptionEquipWithChaos(eqp, sh, true);
}
}
if(stimulantid != -1) {
eqp = ii.randomizeUpgradeStats(eqp);
}
MapleInventoryManipulator.addFromDrop(c, item, false, -1);
c.announce(MaplePacketCreator.getShowItemGain(itemid, (short) 1, true));
return true;
}
}
+173
View File
@@ -0,0 +1,173 @@
/*
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/>.
*/
package client.processor;
import client.MapleClient;
import client.MapleCharacter;
import client.autoban.AutobanFactory;
import client.inventory.Item;
import client.inventory.MapleInventory;
import client.inventory.MapleInventoryType;
import client.inventory.manipulator.MapleKarmaManipulator;
import constants.ItemConstants;
import constants.ServerConstants;
import client.inventory.manipulator.MapleInventoryManipulator;
import server.MapleItemInformationProvider;
import server.MapleStorage;
import tools.FilePrinter;
import tools.MaplePacketCreator;
import tools.data.input.SeekableLittleEndianAccessor;
/**
*
* @author Matze
*/
public class StorageProcessor {
public static void storageAction(SeekableLittleEndianAccessor slea, MapleClient c) {
MapleCharacter chr = c.getPlayer();
MapleStorage storage = chr.getStorage();
byte mode = slea.readByte();
if (chr.getLevel() < 15){
chr.dropMessage(1, "You may only use the storage once you have reached level 15.");
c.announce(MaplePacketCreator.enableActions());
return;
}
c.lockClient();
try {
if (mode == 4) { // take out
byte type = slea.readByte();
byte slot = slea.readByte();
if (slot < 0 || slot > storage.getSlots()) { // removal starts at zero
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit with storage.");
FilePrinter.print(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to work with storage slot " + slot + "\r\n");
c.disconnect(true, false);
return;
}
slot = storage.getSlot(MapleInventoryType.getByType(type), slot);
Item item = storage.getItem(slot);
if (item != null) {
if (MapleItemInformationProvider.getInstance().isPickupRestricted(item.getItemId()) && chr.haveItemWithId(item.getItemId(), true)) {
c.announce(MaplePacketCreator.getStorageError((byte) 0x0C));
return;
}
if (chr.getMap().getId() == 910000000) {
if (chr.getMeso() < 1000) {
c.announce(MaplePacketCreator.getStorageError((byte) 0x0B));
return;
} else {
chr.gainMeso(-1000, false);
}
}
if (MapleInventoryManipulator.checkSpace(c, item.getItemId(), item.getQuantity(), item.getOwner())) {
item = storage.takeOut(slot);//actually the same but idc
String itemName = MapleItemInformationProvider.getInstance().getName(item.getItemId());
FilePrinter.print(FilePrinter.STORAGE + c.getAccountName() + ".txt", c.getPlayer().getName() + " took out " + item.getQuantity() + " " + itemName + " (" + item.getItemId() + ")\r\n");
chr.setUsedStorage();
MapleKarmaManipulator.toggleKarmaFlagToUntradeable(item);
MapleInventoryManipulator.addFromDrop(c, item, false);
storage.sendTakenOut(c, item.getInventoryType());
} else {
c.announce(MaplePacketCreator.getStorageError((byte) 0x0A));
}
}
} else if (mode == 5) { // store
short slot = slea.readShort();
int itemId = slea.readInt();
short quantity = slea.readShort();
MapleInventoryType slotType = ItemConstants.getInventoryType(itemId);
MapleInventory Inv = chr.getInventory(slotType);
if (slot < 1 || slot > Inv.getSlotLimit()) { //player inv starts at one
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit with storage.");
FilePrinter.print(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to store item at slot " + slot + "\r\n");
c.disconnect(true, false);
return;
}
if (quantity < 1 || chr.getItemQuantity(itemId, false) < quantity) {
c.announce(MaplePacketCreator.enableActions());
return;
}
if (storage.isFull()) {
c.announce(MaplePacketCreator.getStorageError((byte) 0x11));
return;
}
short meso = (short) (chr.getMap().getId() == 910000000 ? -500 : -100);
if (chr.getMeso() < meso) {
c.announce(MaplePacketCreator.getStorageError((byte) 0x0B));
} else {
MapleInventoryType invType = ItemConstants.getInventoryType(itemId);
Item item = chr.getInventory(invType).getItem(slot).copy();
if (item.getItemId() == itemId && (item.getQuantity() >= quantity || ItemConstants.isRechargeable(itemId))) {
if (ItemConstants.isRechargeable(itemId)) {
quantity = item.getQuantity();
}
chr.gainMeso(meso, false, true, false);
MapleKarmaManipulator.toggleKarmaFlagToUntradeable(item);
MapleInventoryManipulator.removeFromSlot(c, invType, slot, quantity, false);
item.setQuantity(quantity);
storage.store(item);
storage.sendStored(c, ItemConstants.getInventoryType(itemId));
String itemName = MapleItemInformationProvider.getInstance().getName(item.getItemId());
FilePrinter.print(FilePrinter.STORAGE + c.getAccountName() + ".txt", c.getPlayer().getName() + " stored " + item.getQuantity() + " " + itemName + " (" + item.getItemId() + ")\r\n");
chr.setUsedStorage();
}
}
} else if (mode == 6) { // arrange items
if(ServerConstants.USE_STORAGE_ITEM_SORT) storage.arrangeItems(c);
c.announce(MaplePacketCreator.enableActions());
} else if (mode == 7) { // meso
int meso = slea.readInt();
int storageMesos = storage.getMeso();
int playerMesos = chr.getMeso();
if ((meso > 0 && storageMesos >= meso) || (meso < 0 && playerMesos >= -meso)) {
if (meso < 0 && (storageMesos - meso) < 0) {
meso = -2147483648 + storageMesos;
if (meso < playerMesos) {
c.announce(MaplePacketCreator.enableActions());
return;
}
} else if (meso > 0 && (playerMesos + meso) < 0) {
meso = 2147483647 - playerMesos;
if (meso > storageMesos) {
c.announce(MaplePacketCreator.enableActions());
return;
}
}
storage.setMeso(storageMesos - meso);
chr.gainMeso(meso, false, true, false);
FilePrinter.print(FilePrinter.STORAGE + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + (meso > 0 ? " took out " : " stored ") + Math.abs(meso) + " mesos\r\n");
chr.setUsedStorage();
} else {
c.announce(MaplePacketCreator.enableActions());
return;
}
storage.sendMeso(c);
} else if (mode == 8) {// close
storage.close();
}
} finally {
c.unlockClient();
}
}
}