Source for my MapleSolaxiaV2 (v83 MapleStory).
This commit is contained in:
ronancpl
2015-11-02 23:17:21 -02:00
parent 324982e94f
commit 972517e7b2
1675 changed files with 261831 additions and 0 deletions

465
src/server/CashShop.java Normal file
View File

@@ -0,0 +1,465 @@
/*
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 server;
import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import provider.MapleData;
import provider.MapleDataProvider;
import provider.MapleDataProviderFactory;
import provider.MapleDataTool;
import tools.DatabaseConnection;
import tools.Pair;
import client.inventory.Equip;
import client.inventory.Item;
import client.inventory.ItemFactory;
import client.inventory.MapleInventoryType;
import client.inventory.MaplePet;
import constants.ItemConstants;
/*
* @author Flav
*/
public class CashShop {
public static class CashItem {
private int sn, itemId, price;
private long period;
private short count;
private boolean onSale;
private CashItem(int sn, int itemId, int price, long period, short count, boolean onSale) {
this.sn = sn;
this.itemId = itemId;
this.price = price;
this.period = (period == 0 ? 90 : period);
this.count = count;
this.onSale = onSale;
}
public int getSN() {
return sn;
}
public int getItemId() {
return itemId;
}
public int getPrice() {
return price;
}
public short getCount() {
return count;
}
public boolean isOnSale() {
return onSale;
}
public Item toItem() {
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
Item item;
int petid = -1;
if (ItemConstants.isPet(itemId))
petid = MaplePet.createPet(itemId);
if (ii.getInventoryType(itemId).equals(MapleInventoryType.EQUIP)) {
item = ii.getEquipById(itemId);
} else {
item = new Item(itemId, (byte) 0, count, petid);
}
if (ItemConstants.EXPIRING_ITEMS)
if(itemId == 5211048 || itemId == 5360042) { // 4 Hour 2X coupons, the period is 1, but we don't want them to last a day.
item.setExpiration(System.currentTimeMillis() + (1000 * 60 * 60 * 4));
} else {
item.setExpiration(System.currentTimeMillis() + (1000 * 60 * 60 * 24 * period));
}
item.setSN(sn);
return item;
}
}
public static class SpecialCashItem {
private int sn, modifier;
private byte info; //?
public SpecialCashItem(int sn, int modifier, byte info) {
this.sn = sn;
this.modifier = modifier;
this.info = info;
}
public int getSN() {
return sn;
}
public int getModifier() {
return modifier;
}
public byte getInfo() {
return info;
}
}
public static class CashItemFactory {
private static final Map<Integer, CashItem> items = new HashMap<>();
private static final Map<Integer, List<Integer>> packages = new HashMap<>();
private static final List<SpecialCashItem> specialcashitems = new ArrayList<>();
static {
MapleDataProvider etc = MapleDataProviderFactory.getDataProvider(new File("wz/Etc.wz"));
for (MapleData item : etc.getData("Commodity.img").getChildren()) {
int sn = MapleDataTool.getIntConvert("SN", item);
int itemId = MapleDataTool.getIntConvert("ItemId", item);
int price = MapleDataTool.getIntConvert("Price", item, 0);
long period = MapleDataTool.getIntConvert("Period", item, 1);
short count = (short) MapleDataTool.getIntConvert("Count", item, 1);
boolean onSale = MapleDataTool.getIntConvert("OnSale", item, 0) == 1;
items.put(sn, new CashItem(sn, itemId, price, period, count, onSale));
}
for (MapleData cashPackage : etc.getData("CashPackage.img").getChildren()) {
List<Integer> cPackage = new ArrayList<>();
for (MapleData item : cashPackage.getChildByPath("SN").getChildren()) {
cPackage.add(Integer.parseInt(item.getData().toString()));
}
packages.put(Integer.parseInt(cashPackage.getName()), cPackage);
}
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = DatabaseConnection.getConnection().prepareStatement("SELECT * FROM specialcashitems");
rs = ps.executeQuery();
while (rs.next()) {
specialcashitems.add(new SpecialCashItem(rs.getInt("sn"), rs.getInt("modifier"), rs.getByte("info")));
}
} catch (SQLException ex) {
ex.printStackTrace();
} finally {
try {
if (rs != null) rs.close();
if (ps != null) ps.close();
} catch (SQLException ex) {
}
}
}
public static CashItem getItem(int sn) {
return items.get(sn);
}
public static List<Item> getPackage(int itemId) {
List<Item> cashPackage = new ArrayList<>();
for (int sn : packages.get(itemId)) {
cashPackage.add(getItem(sn).toItem());
}
return cashPackage;
}
public static boolean isPackage(int itemId) {
return packages.containsKey(itemId);
}
public static List<SpecialCashItem> getSpecialCashItems() {
return specialcashitems;
}
public static void reloadSpecialCashItems() {//Yay?
specialcashitems.clear();
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = DatabaseConnection.getConnection().prepareStatement("SELECT * FROM specialcashitems");
rs = ps.executeQuery();
while (rs.next()) {
specialcashitems.add(new SpecialCashItem(rs.getInt("sn"), rs.getInt("modifier"), rs.getByte("info")));
}
} catch (SQLException ex) {
ex.printStackTrace();
} finally {
try {
if (rs != null) rs.close();
if (ps != null) ps.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
}
private int accountId, characterId, nxCredit, maplePoint, nxPrepaid;
private boolean opened;
private ItemFactory factory;
private List<Item> inventory = new ArrayList<>();
private List<Integer> wishList = new ArrayList<>();
private int notes = 0;
public CashShop(int accountId, int characterId, int jobType) throws SQLException {
this.accountId = accountId;
this.characterId = characterId;
if (jobType == 0) {
factory = ItemFactory.CASH_EXPLORER;
} else if (jobType == 1) {
factory = ItemFactory.CASH_CYGNUS;
} else if (jobType == 2) {
factory = ItemFactory.CASH_ARAN;
}
Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = con.prepareStatement("SELECT `nxCredit`, `maplePoint`, `nxPrepaid` FROM `accounts` WHERE `id` = ?");
ps.setInt(1, accountId);
rs = ps.executeQuery();
if (rs.next()) {
this.nxCredit = rs.getInt("nxCredit");
this.maplePoint = rs.getInt("maplePoint");
this.nxPrepaid = rs.getInt("nxPrepaid");
}
rs.close();
ps.close();
for (Pair<Item, MapleInventoryType> item : factory.loadItems(accountId, false)) {
inventory.add(item.getLeft());
}
ps = con.prepareStatement("SELECT `sn` FROM `wishlists` WHERE `charid` = ?");
ps.setInt(1, characterId);
rs = ps.executeQuery();
while (rs.next()) {
wishList.add(rs.getInt("sn"));
}
rs.close();
ps.close();
} finally {
if (ps != null) ps.close();
if (rs != null) rs.close();
}
}
public int getCash(int type) {
switch (type) {
case 1:
return nxCredit;
case 2:
return maplePoint;
case 4:
return nxPrepaid;
}
return 0;
}
public void gainCash(int type, int cash) {
switch (type) {
case 1:
nxCredit += cash;
break;
case 2:
maplePoint += cash;
break;
case 4:
nxPrepaid += cash;
break;
}
}
public boolean isOpened() {
return opened;
}
public void open(boolean b) {
opened = b;
}
public List<Item> getInventory() {
return inventory;
}
public Item findByCashId(int cashId) {
boolean isRing = false;
Equip equip = null;
for (Item item : inventory) {
if (item.getType() == 1) {
equip = (Equip) item;
isRing = equip.getRingId() > -1;
}
if ((item.getPetId() > -1 ? item.getPetId() : isRing ? equip.getRingId() : item.getCashId()) == cashId) {
return item;
}
}
return null;
}
public void addToInventory(Item item) {
inventory.add(item);
}
public void removeFromInventory(Item item) {
inventory.remove(item);
}
public List<Integer> getWishList() {
return wishList;
}
public void clearWishList() {
wishList.clear();
}
public void addToWishList(int sn) {
wishList.add(sn);
}
public void gift(int recipient, String from, String message, int sn) {
gift(recipient, from, message, sn, -1);
}
public void gift(int recipient, String from, String message, int sn, int ringid) {
PreparedStatement ps = null;
try {
ps = DatabaseConnection.getConnection().prepareStatement("INSERT INTO `gifts` VALUES (DEFAULT, ?, ?, ?, ?, ?)");
ps.setInt(1, recipient);
ps.setString(2, from);
ps.setString(3, message);
ps.setInt(4, sn);
ps.setInt(5, ringid);
ps.executeUpdate();
} catch (SQLException sqle) {
sqle.printStackTrace();
} finally {
try {
if (ps != null) ps.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
public List<Pair<Item, String>> loadGifts() {
List<Pair<Item, String>> gifts = new ArrayList<>();
Connection con = DatabaseConnection.getConnection();
try {
PreparedStatement ps = con.prepareStatement("SELECT * FROM `gifts` WHERE `to` = ?");
ps.setInt(1, characterId);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
notes++;
CashItem cItem = CashItemFactory.getItem(rs.getInt("sn"));
Item item = cItem.toItem();
Equip equip = null;
item.setGiftFrom(rs.getString("from"));
if (item.getType() == MapleInventoryType.EQUIP.getType()) {
equip = (Equip) item;
equip.setRingId(rs.getInt("ringid"));
gifts.add(new Pair<Item, String>(equip, rs.getString("message")));
} else
gifts.add(new Pair<>(item, rs.getString("message")));
if (CashItemFactory.isPackage(cItem.getItemId())) { //Packages never contains a ring
for (Item packageItem : CashItemFactory.getPackage(cItem.getItemId())) {
packageItem.setGiftFrom(rs.getString("from"));
addToInventory(packageItem);
}
} else {
addToInventory(equip == null ? item : equip);
}
}
rs.close();
ps.close();
ps = con.prepareStatement("DELETE FROM `gifts` WHERE `to` = ?");
ps.setInt(1, characterId);
ps.executeUpdate();
ps.close();
} catch (SQLException sqle) {
sqle.printStackTrace();
}
return gifts;
}
public int getAvailableNotes() {
return notes;
}
public void decreaseNotes() {
notes--;
}
public void save(Connection con) throws SQLException {
PreparedStatement ps = con.prepareStatement("UPDATE `accounts` SET `nxCredit` = ?, `maplePoint` = ?, `nxPrepaid` = ? WHERE `id` = ?");
ps.setInt(1, nxCredit);
ps.setInt(2, maplePoint);
ps.setInt(3, nxPrepaid);
ps.setInt(4, accountId);
ps.executeUpdate();
ps.close();
List<Pair<Item, MapleInventoryType>> itemsWithType = new ArrayList<>();
for (Item item : inventory) {
itemsWithType.add(new Pair<>(item, MapleItemInformationProvider.getInstance().getInventoryType(item.getItemId())));
}
factory.saveItems(itemsWithType, accountId, con);
ps = con.prepareStatement("DELETE FROM `wishlists` WHERE `charid` = ?");
ps.setInt(1, characterId);
ps.executeUpdate();
ps.close();
ps = con.prepareStatement("INSERT INTO `wishlists` VALUES (DEFAULT, ?, ?)");
ps.setInt(1, characterId);
for (int sn : wishList) {
ps.setInt(2, sn);
ps.executeUpdate();
}
ps.close();
}
}

View File

@@ -0,0 +1,80 @@
/*
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 server;
import client.inventory.Item;
import java.util.Calendar;
public class DueyPackages {
private String sender = null;
private Item item = null;
private int mesos = 0;
private int day;
private int month;
private int year;
private int packageId = 0;
public DueyPackages(int pId, Item item) {
this.item = item;
packageId = pId;
}
public DueyPackages(int pId) { // Meso only package.
this.packageId = pId;
}
public String getSender() {
return sender;
}
public void setSender(String name) {
sender = name;
}
public Item getItem() {
return item;
}
public int getMesos() {
return mesos;
}
public void setMesos(int set) {
mesos = set;
}
public int getPackageId() {
return packageId;
}
public long sentTimeInMilliseconds() {
Calendar cal = Calendar.getInstance();
cal.set(year, month, day);
return cal.getTimeInMillis();
}
public void setSentTime(String sentTime) {
day = Integer.parseInt(sentTime.substring(0, 2));
month = Integer.parseInt(sentTime.substring(3, 5));
year = Integer.parseInt(sentTime.substring(6, 10));
}
}

View File

@@ -0,0 +1,73 @@
/*
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 server;
import client.inventory.Item;
import java.util.Calendar;
/**
*
* @author Traitor
*/
public class MTSItemInfo {
private int price;
private Item item;
private String seller;
private int id;
private int year, month, day = 1;
public MTSItemInfo(Item item, int price, int id, int cid, String seller, String date) {
this.item = item;
this.price = price;
this.seller = seller;
this.id = id;
this.year = Integer.parseInt(date.substring(0, 4));
this.month = Integer.parseInt(date.substring(5, 7));
this.day = Integer.parseInt(date.substring(8, 10));
}
public Item getItem() {
return item;
}
public int getPrice() {
return price;
}
public int getTaxes() {
return 100 + price / 10;
}
public int getID() {
return id;
}
public long getEndingDate() {
Calendar now = Calendar.getInstance();
now.set(year, month - 1, day);
return now.getTimeInMillis();
}
public String getSeller() {
return seller;
}
}

View File

@@ -0,0 +1,116 @@
/*
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 server;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import tools.DatabaseConnection;
import tools.Pair;
/**
*
* @author Jay Estrella
*/
public class MakerItemFactory {
private static Map<Integer, MakerItemCreateEntry> createCache = new HashMap<Integer, MakerItemCreateEntry>();
public static MakerItemCreateEntry getItemCreateEntry(int toCreate) {
if (createCache.get(toCreate) != null) {
return createCache.get(toCreate);
} else {
try {
Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("SELECT req_level, req_maker_level, req_meso, quantity FROM makercreatedata WHERE itemid = ?");
ps.setInt(1, toCreate);
ResultSet rs = ps.executeQuery();
int reqLevel = 0;
int reqMakerLevel = 0;
int cost = 0;
int toGive = 0;
if (rs.next()) {
reqLevel = rs.getInt("req_level");
reqMakerLevel = rs.getInt("req_maker_level");
cost = rs.getInt("req_meso");
toGive = rs.getInt("quantity");
}
ps.close();
rs.close();
MakerItemCreateEntry ret = new MakerItemCreateEntry(cost, reqLevel, reqMakerLevel, toGive);
ps = con.prepareStatement("SELECT req_item, count FROM makerrecipedata WHERE itemid = ?");
ps.setInt(1, toCreate);
rs = ps.executeQuery();
while (rs.next()) {
ret.addReqItem(rs.getInt("req_item"), rs.getInt("count"));
}
rs.close();
ps.close();
createCache.put(toCreate, ret);
} catch (SQLException sqle) {
}
}
return createCache.get(toCreate);
}
public static class MakerItemCreateEntry {
private int reqLevel, reqMakerLevel;
private int cost;
private List<Pair<Integer, Integer>> reqItems = new ArrayList<Pair<Integer, Integer>>(); // itemId / amount
private int toGive;
private MakerItemCreateEntry(int cost, int reqLevel, int reqMakerLevel, int toGive) {
this.cost = cost;
this.reqLevel = reqLevel;
this.reqMakerLevel = reqMakerLevel;
this.toGive = toGive;
}
public int getRewardAmount() {
return toGive;
}
public List<Pair<Integer, Integer>> getReqItems() {
return reqItems;
}
public int getReqLevel() {
return reqLevel;
}
public int getReqSkillLevel() {
return reqMakerLevel;
}
public int getCost() {
return cost;
}
protected void addReqItem(int itemId, int amount) {
reqItems.add(new Pair<Integer, Integer>(itemId, amount));
}
}
}

View File

@@ -0,0 +1,535 @@
/*
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 server;
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 constants.ItemConstants;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
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 = ii.getInventoryType(itemId);
if (!type.equals(MapleInventoryType.EQUIP)) {
short slotMax = ii.getSlotMax(c, itemId);
List<Item> existing = c.getPlayer().getInventory(type).listById(itemId);
if (!ItemConstants.isRechargable(itemId)) {
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.isRechargable(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.isRechargable(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, boolean show) {
return addFromDrop(c, item, show, -1);
}
public static boolean addFromDrop(MapleClient c, Item item, boolean show, int petId) {
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
MapleInventoryType type = ii.getInventoryType(item.getItemId());
if (ii.isPickupRestricted(item.getItemId()) && c.getPlayer().getItemQuantity(item.getItemId(), true) > 0) {
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.isRechargable(item.getItemId())) {
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);
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 {
return false;
}
if (show) {
c.announce(MaplePacketCreator.getShowItemGain(item.getItemId(), item.getQuantity()));
}
return true;
}
public static boolean checkSpace(MapleClient c, int itemid, int quantity, String owner) {
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
MapleInventoryType type = ii.getInventoryType(itemid);
if (!type.equals(MapleInventoryType.EQUIP)) {
short slotMax = ii.getSlotMax(c, itemid);
List<Item> existing = c.getPlayer().getInventory(type).listById(itemid);
if (!ItemConstants.isRechargable(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.isRechargable(itemid)) {
numSlotsNeeded = 1;
} else {
numSlotsNeeded = 1;
}
return !c.getPlayer().getInventory(type).isFull(numSlotsNeeded - 1);
} else {
return !c.getPlayer().getInventory(type).isFull();
}
}
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.isRechargable(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);
}
}
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) && initialTarget != null && initialTarget.getItemId() == source.getItemId() && !ItemConstants.isRechargable(source.getItemId())) {
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 && 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 && 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 && 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 (itemId >= 5000000 && itemId <= 5000100) {
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.isRechargable(itemId) && c.getPlayer().getItemQuantity(itemId, true) < quantity) || quantity < 0 || source == null) {
return;
}
Point dropPos = new Point(c.getPlayer().getPosition());
if (quantity < source.getQuantity() && !ItemConstants.isRechargable(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))));
boolean weddingRing = source.getItemId() == 1112803 || source.getItemId() == 1112806 || source.getItemId() == 1112807 || source.getItemId() == 1112809;
if (weddingRing) {
c.getPlayer().getMap().disappearingItemDrop(c.getPlayer(), c.getPlayer(), target, dropPos);
} else if (c.getPlayer().getMap().getEverlast()) {
if (ii.isDropRestricted(target.getItemId()) || MapleItemInformationProvider.getInstance().isCash(target.getItemId())) {
c.getPlayer().getMap().disappearingItemDrop(c.getPlayer(), c.getPlayer(), target, dropPos);
} else {
c.getPlayer().getMap().spawnItemDrop(c.getPlayer(), c.getPlayer(), target, dropPos, true, false);
}
} else if (ii.isDropRestricted(target.getItemId()) || MapleItemInformationProvider.getInstance().isCash(target.getItemId())) {
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();
}
if (c.getPlayer().getMap().getEverlast()) {
if (ii.isDropRestricted(itemId) || ii.isCash(itemId)) {
c.getPlayer().getMap().disappearingItemDrop(c.getPlayer(), c.getPlayer(), source, dropPos);
} else {
c.getPlayer().getMap().spawnItemDrop(c.getPlayer(), c.getPlayer(), source, dropPos, true, false);
}
} else if (ii.isDropRestricted(itemId) || ii.isCash(itemId)) {
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 isOverall(int itemId) {
return itemId / 10000 == 105;
}
private static boolean isWeapon(int itemId) {
return itemId >= 1302000 && itemId < 1492024;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,341 @@
/*
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 server;
import client.MapleCharacter;
import client.MapleClient;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import server.maps.AbstractMapleMapObject;
import server.maps.MapleMapObjectType;
import tools.MaplePacketCreator;
/**
*
* @author Matze
*/
public class MapleMiniGame extends AbstractMapleMapObject {
private MapleCharacter owner;
private MapleCharacter visitor;
private String GameType = null;
private int[] piece = new int[250];
private List<Integer> list4x3 = new ArrayList<>();
private List<Integer> list5x4 = new ArrayList<>();
private List<Integer> list6x5 = new ArrayList<>();
private String description;
private int loser = 1;
private int piecetype;
private int firstslot = 0;
private int visitorpoints = 0;
private int ownerpoints = 0;
private int matchestowin = 0;
public MapleMiniGame(MapleCharacter owner, String description) {
this.owner = owner;
this.description = description;
}
public boolean hasFreeSlot() {
return visitor == null;
}
public boolean isOwner(MapleCharacter c) {
return owner.equals(c);
}
public void addVisitor(MapleCharacter challenger) {
visitor = challenger;
if (GameType.equals("omok")) {
this.getOwner().getClient().announce(MaplePacketCreator.getMiniGameNewVisitor(challenger, 1));
this.getOwner().getMap().broadcastMessage(MaplePacketCreator.addOmokBox(owner, 2, 0));
}
if (GameType.equals("matchcard")) {
this.getOwner().getClient().announce(MaplePacketCreator.getMatchCardNewVisitor(challenger, 1));
this.getOwner().getMap().broadcastMessage(MaplePacketCreator.addMatchCardBox(owner, 2, 0));
}
}
public void removeVisitor(MapleCharacter challenger) {
if (visitor == challenger) {
visitor = null;
this.getOwner().getClient().announce(MaplePacketCreator.getMiniGameRemoveVisitor());
if (GameType.equals("omok")) {
this.getOwner().getMap().broadcastMessage(MaplePacketCreator.addOmokBox(owner, 1, 0));
}
if (GameType.equals("matchcard")) {
this.getOwner().getMap().broadcastMessage(MaplePacketCreator.addMatchCardBox(owner, 1, 0));
}
}
}
public boolean isVisitor(MapleCharacter challenger) {
return visitor == challenger;
}
public void broadcastToVisitor(final byte[] packet) {
if (visitor != null) {
visitor.getClient().announce(packet);
}
}
public void setFirstSlot(int type) {
firstslot = type;
}
public int getFirstSlot() {
return firstslot;
}
public void setOwnerPoints() {
ownerpoints++;
if (ownerpoints + visitorpoints == matchestowin) {
if (ownerpoints == visitorpoints) {
this.broadcast(MaplePacketCreator.getMatchCardTie(this));
} else if (ownerpoints > visitorpoints) {
this.broadcast(MaplePacketCreator.getMatchCardOwnerWin(this));
} else {
this.broadcast(MaplePacketCreator.getMatchCardVisitorWin(this));
}
ownerpoints = 0;
visitorpoints = 0;
}
}
public void setVisitorPoints() {
visitorpoints++;
if (ownerpoints + visitorpoints == matchestowin) {
if (ownerpoints > visitorpoints) {
this.broadcast(MaplePacketCreator.getMiniGameOwnerWin(this));
} else if (visitorpoints > ownerpoints) {
this.broadcast(MaplePacketCreator.getMiniGameVisitorWin(this));
} else {
this.broadcast(MaplePacketCreator.getMiniGameTie(this));
}
ownerpoints = 0;
visitorpoints = 0;
}
}
public void setMatchesToWin(int type) {
matchestowin = type;
}
public void setPieceType(int type) {
piecetype = type;
}
public int getPieceType() {
return piecetype;
}
public void setGameType(String game) {
GameType = game;
if (game.equals("matchcard")) {
if (matchestowin == 6) {
for (int i = 0; i < 6; i++) {
list4x3.add(i);
list4x3.add(i);
}
} else if (matchestowin == 10) {
for (int i = 0; i < 10; i++) {
list5x4.add(i);
list5x4.add(i);
}
} else {
for (int i = 0; i < 15; i++) {
list6x5.add(i);
list6x5.add(i);
}
}
}
}
public String getGameType() {
return GameType;
}
public void shuffleList() {
if (matchestowin == 6) {
Collections.shuffle(list4x3);
} else if (matchestowin == 10) {
Collections.shuffle(list5x4);
} else {
Collections.shuffle(list6x5);
}
}
public int getCardId(int slot) {
int cardid;
if (matchestowin == 6) {
cardid = list4x3.get(slot - 1);
} else if (matchestowin == 10) {
cardid = list5x4.get(slot - 1);
} else {
cardid = list6x5.get(slot - 1);
}
return cardid;
}
public int getMatchesToWin() {
return matchestowin;
}
public void setLoser(int type) {
loser = type;
}
public int getLoser() {
return loser;
}
public void broadcast(final byte[] packet) {
if (owner.getClient() != null && owner.getClient().getSession() != null) {
owner.getClient().announce(packet);
}
broadcastToVisitor(packet);
}
public void chat(MapleClient c, String chat) {
broadcast(MaplePacketCreator.getPlayerShopChat(c.getPlayer(), chat, isOwner(c.getPlayer())));
}
public void sendOmok(MapleClient c, int type) {
c.announce(MaplePacketCreator.getMiniGame(c, this, isOwner(c.getPlayer()), type));
}
public void sendMatchCard(MapleClient c, int type) {
c.announce(MaplePacketCreator.getMatchCard(c, this, isOwner(c.getPlayer()), type));
}
public MapleCharacter getOwner() {
return owner;
}
public MapleCharacter getVisitor() {
return visitor;
}
public void setPiece(int move1, int move2, int type, MapleCharacter chr) {
int slot = move2 * 15 + move1 + 1;
if (piece[slot] == 0) {
piece[slot] = type;
this.broadcast(MaplePacketCreator.getMiniGameMoveOmok(this, move1, move2, type));
for (int y = 0; y < 15; y++) {
for (int x = 0; x < 11; x++) {
if (searchCombo(x, y, type)) {
if (this.isOwner(chr)) {
this.broadcast(MaplePacketCreator.getMiniGameOwnerWin(this));
this.setLoser(0);
} else {
this.broadcast(MaplePacketCreator.getMiniGameVisitorWin(this));
this.setLoser(1);
}
for (int y2 = 0; y2 < 15; y2++) {
for (int x2 = 0; x2 < 15; x2++) {
int slot2 = (y2 * 15 + x2 + 1);
piece[slot2] = 0;
}
}
}
}
}
for (int y = 0; y < 15; y++) {
for (int x = 4; x < 15; x++) {
if (searchCombo2(x, y, type)) {
if (this.isOwner(chr)) {
this.broadcast(MaplePacketCreator.getMiniGameOwnerWin(this));
this.setLoser(0);
} else {
this.broadcast(MaplePacketCreator.getMiniGameVisitorWin(this));
this.setLoser(1);
}
for (int y2 = 0; y2 < 15; y2++) {
for (int x2 = 0; x2 < 15; x2++) {
int slot2 = (y2 * 15 + x2 + 1);
piece[slot2] = 0;
}
}
}
}
}
}
}
private boolean searchCombo(int x, int y, int type) {
int slot = y * 15 + x + 1;
for (int i = 0; i < 5; i++) {
if (piece[slot + i] == type) {
if (i == 4) {
return true;
}
} else {
break;
}
}
for (int j = 15; j < 17; j++) {
for (int i = 0; i < 5; i++) {
if (piece[slot + i * j] == type) {
if (i == 4) {
return true;
}
} else {
break;
}
}
}
return false;
}
private boolean searchCombo2(int x, int y, int type) {
int slot = y * 15 + x + 1;
for (int j = 14; j < 15; j++) {
for (int i = 0; i < 5; i++) {
if (piece[slot + i * j] == type) {
if (i == 4) {
return true;
}
} else {
break;
}
}
}
return false;
}
public String getDescription() {
return description;
}
@Override
public void sendDestroyData(MapleClient client) {
}
@Override
public void sendSpawnData(MapleClient client) {
}
@Override
public MapleMapObjectType getType() {
return MapleMapObjectType.MINI_GAME;
}
}

View File

@@ -0,0 +1,272 @@
/*
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 server;
import client.MapleCharacter;
import client.MapleClient;
import client.inventory.Item;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import net.SendOpcode;
import server.maps.AbstractMapleMapObject;
import server.maps.MapleMapObjectType;
import tools.MaplePacketCreator;
import tools.data.output.MaplePacketLittleEndianWriter;
/**
*
* @author Matze
*/
public class MaplePlayerShop extends AbstractMapleMapObject {
private MapleCharacter owner;
private MapleCharacter[] visitors = new MapleCharacter[3];
private List<MaplePlayerShopItem> items = new ArrayList<>();
private MapleCharacter[] slot = {null, null, null};
private String description;
private int boughtnumber = 0;
private List<String> bannedList = new ArrayList<>();
public MaplePlayerShop(MapleCharacter owner, String description) {
this.setPosition(owner.getPosition());
this.owner = owner;
this.description = description;
}
public boolean hasFreeSlot() {
return visitors[0] == null || visitors[1] == null || visitors[2] == null;
}
public boolean isOwner(MapleCharacter c) {
return owner.equals(c);
}
public void addVisitor(MapleCharacter visitor) {
for (int i = 0; i < 3; i++) {
if (visitors[i] == null) {
visitors[i] = visitor;
if (this.getSlot(0) == null) {
this.setSlot(visitor, 0);
this.broadcast(MaplePacketCreator.getPlayerShopNewVisitor(visitor, 1));
} else if (this.getSlot(1) == null) {
this.setSlot(visitor, 1);
this.broadcast(MaplePacketCreator.getPlayerShopNewVisitor(visitor, 2));
} else if (this.getSlot(2) == null) {
this.setSlot(visitor, 2);
this.broadcast(MaplePacketCreator.getPlayerShopNewVisitor(visitor, 3));
visitor.getMap().broadcastMessage(MaplePacketCreator.addCharBox(this.getOwner(), 1));
}
break;
}
}
}
public void removeVisitor(MapleCharacter visitor) {
if (visitor == owner) {
owner.getMap().removeMapObject(this);
owner.setPlayerShop(null);
}
for (int i = 0; i < 3; i++) {
if (visitors[i] != null && visitors[i].getId() == visitor.getId()) {
int slot_ = visitor.getSlot();
visitors[i] = null;
this.setSlot(null, i);
visitor.setSlot(-1);
this.broadcast(MaplePacketCreator.getPlayerShopRemoveVisitor(slot_ + 1));
return;
}
}
}
public boolean isVisitor(MapleCharacter visitor) {
return visitors[0] == visitor || visitors[1] == visitor || visitors[2] == visitor;
}
public void addItem(MaplePlayerShopItem item) {
items.add(item);
}
public void removeItem(int item) {
items.remove(item);
}
/**
* no warnings for now o.op
* @param c
* @param item
* @param quantity
*/
public void buy(MapleClient c, int item, short quantity) {
if (isVisitor(c.getPlayer())) {
MaplePlayerShopItem pItem = items.get(item);
Item newItem = pItem.getItem().copy();
newItem.setQuantity(newItem.getQuantity());
if (quantity < 1 || pItem.getBundles() < 1 || newItem.getQuantity() > pItem.getBundles() || !pItem.isExist()) {
return;
} else if (newItem.getType() == 1 && newItem.getQuantity() > 1) {
return;
}
synchronized (c.getPlayer()) {
if (c.getPlayer().getMeso() >= (long) pItem.getPrice() * quantity) {
if (MapleInventoryManipulator.addFromDrop(c, newItem, false)) {
c.getPlayer().gainMeso(-pItem.getPrice() * quantity, true);
owner.gainMeso(pItem.getPrice() * quantity, true);
pItem.setBundles((short) (pItem.getBundles() - quantity));
if (pItem.getBundles() < 1) {
pItem.setDoesExist(false);
if (++boughtnumber == items.size()) {
owner.setPlayerShop(null);
owner.getMap().broadcastMessage(MaplePacketCreator.removeCharBox(owner));
this.removeVisitors();
owner.dropMessage(1, "Your items are sold out, and therefore your shop is closed.");
}
}
} else {
c.getPlayer().dropMessage(1, "Your inventory is full. Please clean a slot before buying this item.");
}
}
}
}
}
public void broadcastToVisitors(final byte[] packet) {
for (int i = 0; i < 3; i++) {
if (visitors[i] != null) {
visitors[i].getClient().announce(packet);
}
}
}
public void removeVisitors() {
try {
for (int i = 0; i < 3; i++) {
if (visitors[i] != null) {
visitors[i].getClient().announce(MaplePacketCreator.shopErrorMessage(10, 1));
removeVisitor(visitors[i]);
}
}
} catch (Exception e) {
e.printStackTrace();
}
if (owner != null) {
removeVisitor(getOwner());
}
}
public static byte[] shopErrorMessage(int error, int type) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue());
mplew.write(0x0A);
mplew.write(type);
mplew.write(error);
return mplew.getPacket();
}
public void broadcast(final byte[] packet) {
if (owner.getClient() != null && owner.getClient().getSession() != null) {
owner.getClient().announce(packet);
}
broadcastToVisitors(packet);
}
public void chat(MapleClient c, String chat) {
byte s = 0;
for (MapleCharacter mc : getVisitors()) {
s++;
if (mc != null) {
if (mc.getName().equalsIgnoreCase(c.getPlayer().getName())) {
break;
}
} else if (s == 3) {
s = 0;
}
}
broadcast(MaplePacketCreator.getPlayerShopChat(c.getPlayer(), chat, s));
}
public void sendShop(MapleClient c) {
c.announce(MaplePacketCreator.getPlayerShop(c, this, isOwner(c.getPlayer())));
}
public MapleCharacter getOwner() {
return owner;
}
public MapleCharacter[] getVisitors() {
return visitors;
}
public MapleCharacter getSlot(int s) {
return slot[s];
}
private void setSlot(MapleCharacter person, int s) {
slot[s] = person;
if (person != null) {
person.setSlot(s);
}
}
public List<MaplePlayerShopItem> getItems() {
return Collections.unmodifiableList(items);
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public void banPlayer(String name) {
if (!bannedList.contains(name)) {
bannedList.add(name);
}
for (int i = 0; i < 3; i++) {
if (visitors[i] != null && visitors[i].getName().equals(name)) {
visitors[i].getClient().announce(MaplePacketCreator.shopErrorMessage(5, 1));
removeVisitor(visitors[i]);
return; //I'm guessing this was the intended action
}
}
}
public boolean isBanned(String name) {
return bannedList.contains(name);
}
@Override
public void sendDestroyData(MapleClient client) {
client.announce(MaplePacketCreator.removeCharBox(this.getOwner()));
}
@Override
public void sendSpawnData(MapleClient client) {
client.announce(MaplePacketCreator.addCharBox(this.getOwner(), 4));
}
@Override
public MapleMapObjectType getType() {
return MapleMapObjectType.SHOP;
}
}

View File

@@ -0,0 +1,66 @@
/*
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 server;
import client.inventory.Item;
/**
*
* @author Matze
*/
public class MaplePlayerShopItem {
private Item item;
private short bundles;
private int price;
private boolean doesExist;
public MaplePlayerShopItem(Item item, short bundles, int price) {
this.item = item;
this.bundles = bundles;
this.price = price;
this.doesExist = true;
}
public void setDoesExist(boolean tf) {
this.doesExist = tf;
}
public boolean isExist() {
return doesExist;
}
public Item getItem() {
return item;
}
public short getBundles() {
return bundles;
}
public int getPrice() {
return price;
}
public void setBundles(short bundles) {
this.bundles = bundles;
}
}

View File

@@ -0,0 +1,45 @@
/*
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 server;
import java.awt.Point;
import client.MapleClient;
public interface MaplePortal {
public final int MAP_PORTAL = 2;
public final int DOOR_PORTAL = 6;
public static boolean OPEN = true;
public static boolean CLOSED = false;
int getType();
int getId();
Point getPosition();
String getName();
String getTarget();
String getScriptName();
void setScriptName(String newName);
void setPortalStatus(boolean newStatus);
boolean getPortalStatus();
int getTargetMapId();
void enterPortal(MapleClient c);
void setPortalState(boolean state);
boolean getPortalState();
}

271
src/server/MapleShop.java Normal file
View File

@@ -0,0 +1,271 @@
/*
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 server;
import client.MapleClient;
import client.inventory.Item;
import client.inventory.MapleInventoryType;
import client.inventory.MaplePet;
import constants.ItemConstants;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import tools.DatabaseConnection;
import tools.MaplePacketCreator;
/**
*
* @author Matze
*/
public class MapleShop {
private static final Set<Integer> rechargeableItems = new LinkedHashSet<>();
private int id;
private int npcId;
private List<MapleShopItem> items;
private int tokenvalue = 1000000000;
private int token = 4000313;
static {
for (int i = 2070000; i < 2070017; i++) {
rechargeableItems.add(i);
}
rechargeableItems.add(2331000);//Blaze Capsule
rechargeableItems.add(2332000);//Glaze Capsule
rechargeableItems.add(2070018);
rechargeableItems.remove(2070014); // doesn't exist
for (int i = 2330000; i <= 2330005; i++) {
rechargeableItems.add(i);
}
}
private MapleShop(int id, int npcId) {
this.id = id;
this.npcId = npcId;
items = new ArrayList<>();
}
private void addItem(MapleShopItem item) {
items.add(item);
}
public void sendShop(MapleClient c) {
c.getPlayer().setShop(this);
c.announce(MaplePacketCreator.getNPCShop(c, getNpcId(), items));
}
public void buy(MapleClient c, short slot, int itemId, short quantity) {
MapleShopItem item = findBySlot(slot);
if (item != null) {
if (item.getItemId() != itemId) {
System.out.println("Wrong slot number in shop " + id);
return;
}
} else {
return;
}
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
if (item != null && item.getPrice() > 0) {
if (c.getPlayer().getMeso() >= (long) item.getPrice() * quantity) {
if (MapleInventoryManipulator.checkSpace(c, itemId, quantity, "")) {
if (!ItemConstants.isRechargable(itemId)) { //Pets can't be bought from shops
MapleInventoryManipulator.addById(c, itemId, quantity);
c.getPlayer().gainMeso(-(item.getPrice() * quantity), false);
} else {
short slotMax = ii.getSlotMax(c, item.getItemId());
quantity = slotMax;
MapleInventoryManipulator.addById(c, itemId, quantity);
c.getPlayer().gainMeso(-item.getPrice(), false);
}
c.announce(MaplePacketCreator.shopTransaction((byte) 0));
} else
c.announce(MaplePacketCreator.shopTransaction((byte) 3));
} else
c.announce(MaplePacketCreator.shopTransaction((byte) 2));
} else if (item != null && item.getPitch() > 0) {
if (c.getPlayer().getInventory(MapleInventoryType.ETC).countById(4310000) >= (long) item.getPitch() * quantity) {
if (MapleInventoryManipulator.checkSpace(c, itemId, quantity, "")) {
if (!ItemConstants.isRechargable(itemId)) {
MapleInventoryManipulator.addById(c, itemId, quantity);
MapleInventoryManipulator.removeById(c, MapleInventoryType.ETC, 4310000, item.getPitch() * quantity, false, false);
} else {
short slotMax = ii.getSlotMax(c, item.getItemId());
quantity = slotMax;
MapleInventoryManipulator.addById(c, itemId, quantity);
MapleInventoryManipulator.removeById(c, MapleInventoryType.ETC, 4310000, item.getPitch() * quantity, false, false);
}
c.announce(MaplePacketCreator.shopTransaction((byte) 0));
} else
c.announce(MaplePacketCreator.shopTransaction((byte) 3));
}
} else if (c.getPlayer().getInventory(MapleInventoryType.CASH).countById(token) != 0) {
int amount = c.getPlayer().getInventory(MapleInventoryType.CASH).countById(token);
int value = amount * tokenvalue;
int cost = item.getPrice() * quantity;
if (c.getPlayer().getMeso() + value >= cost) {
int cardreduce = value - cost;
int diff = cardreduce + c.getPlayer().getMeso();
if (MapleInventoryManipulator.checkSpace(c, itemId, quantity, "")) {
if (itemId >= 5000000 && itemId <= 5000100) {
int petid = MaplePet.createPet(itemId);
MapleInventoryManipulator.addById(c, itemId, quantity, null, petid, -1);
} else {
MapleInventoryManipulator.addById(c, itemId, quantity);
}
c.getPlayer().gainMeso(diff, false);
} else {
c.announce(MaplePacketCreator.shopTransaction((byte) 3));
}
c.announce(MaplePacketCreator.shopTransaction((byte) 0));
} else
c.announce(MaplePacketCreator.shopTransaction((byte) 2));
}
}
public void sell(MapleClient c, MapleInventoryType type, short slot, short quantity) {
if (quantity == 0xFFFF || quantity == 0) {
quantity = 1;
}
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
Item item = c.getPlayer().getInventory(type).getItem((short) slot);
if (item == null){ //Basic check
return;
}
if (ItemConstants.isRechargable(item.getItemId())) {
quantity = item.getQuantity();
}
if (quantity < 0) {
return;
}
short iQuant = item.getQuantity();
if (iQuant == 0xFFFF) {
iQuant = 1;
}
if (quantity <= iQuant && iQuant > 0) {
MapleInventoryManipulator.removeFromSlot(c, type, (byte) slot, quantity, false);
double price;
if (ItemConstants.isRechargable(item.getItemId())) {
price = ii.getWholePrice(item.getItemId()) / (double) ii.getSlotMax(c, item.getItemId());
} else {
price = ii.getPrice(item.getItemId());
}
int recvMesos = (int) Math.max(Math.ceil(price * quantity), 0);
if (price != -1 && recvMesos > 0) {
c.getPlayer().gainMeso(recvMesos, false);
}
c.announce(MaplePacketCreator.shopTransaction((byte) 0x8));
}
}
public void recharge(MapleClient c, short slot) {
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
Item item = c.getPlayer().getInventory(MapleInventoryType.USE).getItem(slot);
if (item == null || !ItemConstants.isRechargable(item.getItemId())) {
return;
}
short slotMax = ii.getSlotMax(c, item.getItemId());
if (item.getQuantity() < 0) {
return;
}
if (item.getQuantity() < slotMax) {
int price = (int) Math.round(ii.getPrice(item.getItemId()) * (slotMax - item.getQuantity()));
if (c.getPlayer().getMeso() >= price) {
item.setQuantity(slotMax);
c.getPlayer().forceUpdateItem(item);
c.getPlayer().gainMeso(-price, false, true, false);
c.announce(MaplePacketCreator.shopTransaction((byte) 0x8));
} else {
c.announce(MaplePacketCreator.serverNotice(1, "You do not have enough mesos."));
c.announce(MaplePacketCreator.enableActions());
}
}
}
private MapleShopItem findBySlot(short slot) {
return items.get(slot);
}
public static MapleShop createFromDB(int id, boolean isShopId) {
MapleShop ret = null;
int shopId;
try {
Connection con = DatabaseConnection.getConnection();
PreparedStatement ps;
if (isShopId) {
ps = con.prepareStatement("SELECT * FROM shops WHERE shopid = ?");
} else {
ps = con.prepareStatement("SELECT * FROM shops WHERE npcid = ?");
}
ps.setInt(1, id);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
shopId = rs.getInt("shopid");
ret = new MapleShop(shopId, rs.getInt("npcid"));
rs.close();
ps.close();
} else {
rs.close();
ps.close();
return null;
}
ps = con.prepareStatement("SELECT * FROM shopitems WHERE shopid = ? ORDER BY position DESC");
ps.setInt(1, shopId);
rs = ps.executeQuery();
List<Integer> recharges = new ArrayList<>(rechargeableItems);
while (rs.next()) {
if (ItemConstants.isRechargable(rs.getInt("itemid"))) {
MapleShopItem starItem = new MapleShopItem((short) 1, rs.getInt("itemid"), rs.getInt("price"), rs.getInt("pitch"));
ret.addItem(starItem);
if (rechargeableItems.contains(starItem.getItemId())) {
recharges.remove(Integer.valueOf(starItem.getItemId()));
}
} else {
ret.addItem(new MapleShopItem((short) 1000, rs.getInt("itemid"), rs.getInt("price"), rs.getInt("pitch")));
}
}
for (Integer recharge : recharges) {
ret.addItem(new MapleShopItem((short) 1000, recharge.intValue(), 0, 0));
}
rs.close();
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
return ret;
}
public int getNpcId() {
return npcId;
}
public int getId() {
return id;
}
}

View File

@@ -0,0 +1,70 @@
/*
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 server;
import java.util.HashMap;
import java.util.Map;
/**
*
* @author Matze
*/
public class MapleShopFactory {
private Map<Integer, MapleShop> shops = new HashMap<Integer, MapleShop>();
private Map<Integer, MapleShop> npcShops = new HashMap<Integer, MapleShop>();
private static MapleShopFactory instance = new MapleShopFactory();
public static MapleShopFactory getInstance() {
return instance;
}
public void reloadShops() {
shops.clear();
}
private MapleShop loadShop(int id, boolean isShopId) {
MapleShop ret = MapleShop.createFromDB(id, isShopId);
if (ret != null) {
shops.put(ret.getId(), ret);
npcShops.put(ret.getNpcId(), ret);
} else if (isShopId) {
shops.put(id, null);
} else {
npcShops.put(id, null);
}
return ret;
}
public MapleShop getShop(int shopId) {
if (shops.containsKey(shopId)) {
return shops.get(shopId);
}
return loadShop(shopId, true);
}
public MapleShop getShopForNPC(int npcId) {
if (npcShops.containsKey(npcId)) {
npcShops.get(npcId);
}
return loadShop(npcId, false);
}
}

View File

@@ -0,0 +1,56 @@
/*
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 server;
/**
*
* @author Matze
*/
public class MapleShopItem {
private short buyable;
private int itemId;
private int price;
private int pitch;
public MapleShopItem(short buyable, int itemId, int price, int pitch) {
this.buyable = buyable;
this.itemId = itemId;
this.price = price;
this.pitch = pitch;
}
public short getBuyable() {
return buyable;
}
public int getItemId() {
return itemId;
}
public int getPrice() {
return price;
}
public int getPitch() {
return pitch;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,234 @@
/*
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 server;
import client.MapleClient;
import client.inventory.Item;
import client.inventory.ItemFactory;
import client.inventory.MapleInventoryType;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import tools.DatabaseConnection;
import tools.MaplePacketCreator;
import tools.Pair;
/**
*
* @author Matze
*/
public class MapleStorage {
private int id;
private List<Item> items;
private int meso;
private byte slots;
private Map<MapleInventoryType, List<Item>> typeItems = new HashMap<>();
private MapleStorage(int id, byte slots, int meso) {
this.id = id;
this.slots = slots;
this.items = new LinkedList<>();
this.meso = meso;
}
private static MapleStorage create(int id, int world) {
try {
try (PreparedStatement ps = DatabaseConnection.getConnection().prepareStatement("INSERT INTO storages (accountid, world, slots, meso) VALUES (?, ?, 4, 0)")) {
ps.setInt(1, id);
ps.setInt(2, world);
ps.executeUpdate();
}
} catch (Exception e) {
e.printStackTrace();
}
return loadOrCreateFromDB(id, world);
}
public static MapleStorage loadOrCreateFromDB(int id, int world) {
MapleStorage ret = null;
int storeId;
try {
Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("SELECT storageid, slots, meso FROM storages WHERE accountid = ? AND world = ?");
ps.setInt(1, id);
ps.setInt(2, world);
ResultSet rs = ps.executeQuery();
if (!rs.next()) {
rs.close();
ps.close();
return create(id, world);
} else {
storeId = rs.getInt("storageid");
ret = new MapleStorage(storeId, (byte) rs.getInt("slots"), rs.getInt("meso"));
rs.close();
ps.close();
for (Pair<Item, MapleInventoryType> item : ItemFactory.STORAGE.loadItems(ret.id, false)) {
ret.items.add(item.getLeft());
}
}
} catch (SQLException ex) {
ex.printStackTrace();
}
return ret;
}
public byte getSlots() {
return slots;
}
public boolean gainSlots(int slots) {
slots += this.slots;
if (slots <= 48) {
this.slots = (byte) slots;
return true;
}
return false;
}
public void setSlots(byte set) {
this.slots = set;
}
public void saveToDB(Connection con) {
try {
try (PreparedStatement ps = con.prepareStatement("UPDATE storages SET slots = ?, meso = ? WHERE storageid = ?")) {
ps.setInt(1, slots);
ps.setInt(2, meso);
ps.setInt(3, id);
ps.executeUpdate();
}
List<Pair<Item, MapleInventoryType>> itemsWithType = new ArrayList<>();
for (Item item : items) {
itemsWithType.add(new Pair<>(item, MapleItemInformationProvider.getInstance().getInventoryType(item.getItemId())));
}
ItemFactory.STORAGE.saveItems(itemsWithType, id, con);
} catch (SQLException ex) {
ex.printStackTrace();
}
}
public Item getItem(byte slot) {
return items.get(slot);
}
public Item takeOut(byte slot) {
Item ret = items.remove(slot);
MapleInventoryType type = MapleItemInformationProvider.getInstance().getInventoryType(ret.getItemId());
typeItems.put(type, new ArrayList<>(filterItems(type)));
return ret;
}
public void store(Item item) {
items.add(item);
MapleInventoryType type = MapleItemInformationProvider.getInstance().getInventoryType(item.getItemId());
typeItems.put(type, new ArrayList<>(filterItems(type)));
}
public List<Item> getItems() {
return Collections.unmodifiableList(items);
}
private List<Item> filterItems(MapleInventoryType type) {
List<Item> ret = new LinkedList<>();
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
for (Item item : items) {
if (ii.getInventoryType(item.getItemId()) == type) {
ret.add(item);
}
}
return ret;
}
public byte getSlot(MapleInventoryType type, byte slot) {
byte ret = 0;
for (Item item : items) {
if (item == typeItems.get(type).get(slot)) {
return ret;
}
ret++;
}
return -1;
}
public void sendStorage(MapleClient c, int npcId) {
final MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
Collections.sort(items, new Comparator<Item>() {
@Override
public int compare(Item o1, Item o2) {
if (ii.getInventoryType(o1.getItemId()).getType() < ii.getInventoryType(o2.getItemId()).getType()) {
return -1;
} else if (ii.getInventoryType(o1.getItemId()) == ii.getInventoryType(o2.getItemId())) {
return 0;
}
return 1;
}
});
for (MapleInventoryType type : MapleInventoryType.values()) {
typeItems.put(type, new ArrayList<>(items));
}
c.announce(MaplePacketCreator.getStorage(npcId, slots, items, meso));
}
public void sendStored(MapleClient c, MapleInventoryType type) {
c.announce(MaplePacketCreator.storeStorage(slots, type, typeItems.get(type)));
}
public void sendTakenOut(MapleClient c, MapleInventoryType type) {
c.announce(MaplePacketCreator.takeOutStorage(slots, type, typeItems.get(type)));
}
public int getMeso() {
return meso;
}
public void setMeso(int meso) {
if (meso < 0) {
throw new RuntimeException();
}
this.meso = meso;
}
public void sendMeso(MapleClient c) {
c.announce(MaplePacketCreator.mesoStorage(slots, meso));
}
public boolean isFull() {
return items.size() >= slots;
}
public void close() {
typeItems.clear();
}
}

308
src/server/MapleTrade.java Normal file
View File

@@ -0,0 +1,308 @@
/*
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 server;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import tools.LogHelper;
import tools.MaplePacketCreator;
import client.MapleCharacter;
import client.inventory.Item;
import client.inventory.MapleInventoryType;
import constants.ItemConstants;
/**
*
* @author Matze
*/
public class MapleTrade {
private MapleTrade partner = null;
private List<Item> items = new ArrayList<>();
private List<Item> exchangeItems;
private int meso = 0;
private int exchangeMeso;
boolean locked = false;
private MapleCharacter chr;
private byte number;
private boolean fullTrade = false;
public MapleTrade(byte number, MapleCharacter c) {
chr = c;
this.number = number;
}
private static int getFee(int meso) {
int fee = 0;
if (meso >= 100000000) {
fee = (int) Math.round(0.06 * meso);
} else if (meso >= 25000000) {
fee = meso / 20;
} else if (meso >= 10000000) {
fee = meso / 25;
} else if (meso >= 5000000) {
fee = (int) Math.round(.03 * meso);
} else if (meso >= 1000000) {
fee = (int) Math.round(.018 * meso);
} else if (meso >= 100000) {
fee = meso / 125;
}
return fee;
}
private void lock() {
locked = true;
partner.getChr().getClient().announce(MaplePacketCreator.getTradeConfirmation());
}
private void complete1() {
exchangeItems = partner.getItems();
exchangeMeso = partner.getMeso();
}
private void complete2() {
items.clear();
meso = 0;
for (Item item : exchangeItems) {
if ((item.getFlag() & ItemConstants.KARMA) == ItemConstants.KARMA)
item.setFlag((byte) (item.getFlag() ^ ItemConstants.KARMA)); //items with scissors of karma used on them are reset once traded
else if (item.getType() == 2 && (item.getFlag() & ItemConstants.SPIKES) == ItemConstants.SPIKES)
item.setFlag((byte) (item.getFlag() ^ ItemConstants.SPIKES));
MapleInventoryManipulator.addFromDrop(chr.getClient(), item, true);
}
if (exchangeMeso > 0) {
chr.gainMeso(exchangeMeso - getFee(exchangeMeso), true, true, true);
}
exchangeMeso = 0;
if (exchangeItems != null) {
exchangeItems.clear();
}
chr.getClient().announce(MaplePacketCreator.getTradeCompletion(number));
}
private void cancel() {
for (Item item : items) {
MapleInventoryManipulator.addFromDrop(chr.getClient(), item, true);
}
if (meso > 0) {
chr.gainMeso(meso, true, true, true);
}
meso = 0;
if (items != null) {
items.clear();
}
exchangeMeso = 0;
if (exchangeItems != null) {
exchangeItems.clear();
}
chr.getClient().announce(MaplePacketCreator.getTradeCancel(number));
}
private boolean isLocked() {
return locked;
}
private int getMeso() {
return meso;
}
public void setMeso(int meso) {
if (locked) {
throw new RuntimeException("Trade is locked.");
}
if (meso < 0) {
System.out.println("[h4x] " + chr.getName() + " Trying to trade < 0 mesos");
return;
}
if (chr.getMeso() >= meso) {
chr.gainMeso(-meso, false, true, false);
this.meso += meso;
chr.getClient().announce(MaplePacketCreator.getTradeMesoSet((byte) 0, this.meso));
if (partner != null) {
partner.getChr().getClient().announce(MaplePacketCreator.getTradeMesoSet((byte) 1, this.meso));
}
} else {
}
}
public void addItem(Item item) {
items.add(item);
chr.getClient().announce(MaplePacketCreator.getTradeItemAdd((byte) 0, item));
if (partner != null) {
partner.getChr().getClient().announce(MaplePacketCreator.getTradeItemAdd((byte) 1, item));
}
}
public void chat(String message) {
chr.getClient().announce(MaplePacketCreator.getTradeChat(chr, message, true));
if (partner != null) {
partner.getChr().getClient().announce(MaplePacketCreator.getTradeChat(chr, message, false));
}
}
public MapleTrade getPartner() {
return partner;
}
public void setPartner(MapleTrade partner) {
if (locked) {
return;
}
this.partner = partner;
}
public MapleCharacter getChr() {
return chr;
}
public List<Item> getItems() {
return new LinkedList<>(items);
}
public int getExchangeMesos(){
return exchangeMeso;
}
private boolean fitsInInventory() {
MapleItemInformationProvider mii = MapleItemInformationProvider.getInstance();
Map<MapleInventoryType, Integer> neededSlots = new LinkedHashMap<>();
for (Item item : exchangeItems) {
MapleInventoryType type = mii.getInventoryType(item.getItemId());
if (neededSlots.get(type) == null) {
neededSlots.put(type, 1);
} else {
neededSlots.put(type, neededSlots.get(type) + 1);
}
}
for (Map.Entry<MapleInventoryType, Integer> entry : neededSlots.entrySet()) {
if (chr.getInventory(entry.getKey()).isFull(entry.getValue() - 1)) {
return false;
}
}
return true;
}
public static void completeTrade(MapleCharacter c) {
c.getTrade().lock();
MapleTrade local = c.getTrade();
MapleTrade partner = local.getPartner();
if (partner.isLocked()) {
local.complete1();
partner.complete1();
if (!local.fitsInInventory() || !partner.fitsInInventory()) {
cancelTrade(c);
c.message("There is not enough inventory space to complete the trade.");
partner.getChr().message("There is not enough inventory space to complete the trade.");
return;
}
if (local.getChr().getLevel() < 15) {
if (local.getChr().getMesosTraded() + local.exchangeMeso > 1000000) {
cancelTrade(c);
local.getChr().getClient().announce(MaplePacketCreator.serverNotice(1, "Characters under level 15 may not trade more than 1 million mesos per day."));
return;
} else {
local.getChr().addMesosTraded(local.exchangeMeso);
}
} else if (c.getTrade().getChr().getLevel() < 15) {
if (c.getMesosTraded() + c.getTrade().exchangeMeso > 1000000) {
cancelTrade(c);
c.getClient().announce(MaplePacketCreator.serverNotice(1, "Characters under level 15 may not trade more than 1 million mesos per day."));
return;
} else {
c.addMesosTraded(local.exchangeMeso);
}
}
LogHelper.logTrade(local, partner);
local.complete2();
partner.complete2();
partner.getChr().setTrade(null);
c.setTrade(null);
}
}
public static void cancelTrade(MapleCharacter c) {
c.getTrade().cancel();
if (c.getTrade().getPartner() != null) {
c.getTrade().getPartner().cancel();
c.getTrade().getPartner().getChr().setTrade(null);
}
c.setTrade(null);
}
public static void startTrade(MapleCharacter c) {
if (c.getTrade() == null) {
c.setTrade(new MapleTrade((byte) 0, c));
c.getClient().announce(MaplePacketCreator.getTradeStart(c.getClient(), c.getTrade(), (byte) 0));
} else {
c.message("You are already in a trade.");
}
}
public static void inviteTrade(MapleCharacter c1, MapleCharacter c2) {
if (c2.getTrade() == null) {
c2.setTrade(new MapleTrade((byte) 1, c2));
c2.getTrade().setPartner(c1.getTrade());
c1.getTrade().setPartner(c2.getTrade());
c2.getClient().announce(MaplePacketCreator.getTradeInvite(c1));
} else {
c1.message("The other player is already trading with someone else.");
cancelTrade(c1);
}
}
public static void visitTrade(MapleCharacter c1, MapleCharacter c2) {
if (c1.getTrade() != null && c1.getTrade().getPartner() == c2.getTrade() && c2.getTrade() != null && c2.getTrade().getPartner() == c1.getTrade()) {
c2.getClient().announce(MaplePacketCreator.getTradePartnerAdd(c1));
c1.getClient().announce(MaplePacketCreator.getTradeStart(c1.getClient(), c1.getTrade(), (byte) 1));
c1.getTrade().setFullTrade(true);
c2.getTrade().setFullTrade(true);
} else {
c1.message("The other player has already closed the trade.");
}
}
public static void declineTrade(MapleCharacter c) {
MapleTrade trade = c.getTrade();
if (trade != null) {
if (trade.getPartner() != null) {
MapleCharacter other = trade.getPartner().getChr();
other.getTrade().cancel();
other.setTrade(null);
other.message(c.getName() + " has declined your trade request.");
}
trade.cancel();
c.setTrade(null);
}
}
public boolean isFullTrade() {
return fullTrade;
}
public void setFullTrade(boolean fullTrade) {
this.fullTrade = fullTrade;
}
}

View File

@@ -0,0 +1,68 @@
/*
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 server;
import java.awt.Point;
import provider.MapleData;
import provider.MapleDataTool;
import server.maps.MapleGenericPortal;
import server.maps.MapleMapPortal;
public class PortalFactory {
private int nextDoorPortal;
public PortalFactory() {
nextDoorPortal = 0x80;
}
public MaplePortal makePortal(int type, MapleData portal) {
MapleGenericPortal ret = null;
if (type == MaplePortal.MAP_PORTAL) {
ret = new MapleMapPortal();
} else {
ret = new MapleGenericPortal(type);
}
loadPortal(ret, portal);
return ret;
}
private void loadPortal(MapleGenericPortal myPortal, MapleData portal) {
myPortal.setName(MapleDataTool.getString(portal.getChildByPath("pn")));
myPortal.setTarget(MapleDataTool.getString(portal.getChildByPath("tn")));
myPortal.setTargetMapId(MapleDataTool.getInt(portal.getChildByPath("tm")));
int x = MapleDataTool.getInt(portal.getChildByPath("x"));
int y = MapleDataTool.getInt(portal.getChildByPath("y"));
myPortal.setPosition(new Point(x, y));
String script = MapleDataTool.getString("script", portal, null);
if (script != null && script.equals("")) {
script = null;
}
myPortal.setScriptName(script);
if (myPortal.getType() == MaplePortal.DOOR_PORTAL) {
myPortal.setId(nextDoorPortal);
nextDoorPortal++;
} else {
myPortal.setId(Integer.parseInt(portal.getName()));
}
}
}

View File

@@ -0,0 +1,149 @@
/*
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 server;
import java.lang.management.ManagementFactory;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import tools.FilePrinter;
public class TimerManager implements TimerManagerMBean {
private static TimerManager instance = new TimerManager();
private ScheduledThreadPoolExecutor ses;
private TimerManager() {
MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
try {
mBeanServer.registerMBean(this, new ObjectName("server:type=TimerManger"));
} catch (Exception e) {
}
}
public static TimerManager getInstance() {
return instance;
}
public void start() {
if (ses != null && !ses.isShutdown() && !ses.isTerminated()) {
return;
}
ScheduledThreadPoolExecutor stpe = new ScheduledThreadPoolExecutor(4, new ThreadFactory() {
private final AtomicInteger threadNumber = new AtomicInteger(1);
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("TimerManager-Worker-" + threadNumber.getAndIncrement());
return t;
}
});
//this is a no-no, it actually does nothing..then why the fuck are you doing it?
stpe.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
stpe.setRemoveOnCancelPolicy(true);
stpe.setKeepAliveTime(5, TimeUnit.MINUTES);
stpe.allowCoreThreadTimeOut(true);
ses = stpe;
}
public void stop() {
ses.shutdownNow();
}
public Runnable purge() {//Yay?
return new Runnable() {
public void run() {
ses.purge();
}
};
}
public ScheduledFuture<?> register(Runnable r, long repeatTime, long delay) {
return ses.scheduleAtFixedRate(new LoggingSaveRunnable(r), delay, repeatTime, TimeUnit.MILLISECONDS);
}
public ScheduledFuture<?> register(Runnable r, long repeatTime) {
return ses.scheduleAtFixedRate(new LoggingSaveRunnable(r), 0, repeatTime, TimeUnit.MILLISECONDS);
}
public ScheduledFuture<?> schedule(Runnable r, long delay) {
return ses.schedule(new LoggingSaveRunnable(r), delay, TimeUnit.MILLISECONDS);
}
public ScheduledFuture<?> scheduleAtTimestamp(Runnable r, long timestamp) {
return schedule(r, timestamp - System.currentTimeMillis());
}
@Override
public long getActiveCount() {
return ses.getActiveCount();
}
@Override
public long getCompletedTaskCount() {
return ses.getCompletedTaskCount();
}
@Override
public int getQueuedTasks() {
return ses.getQueue().toArray().length;
}
@Override
public long getTaskCount() {
return ses.getTaskCount();
}
@Override
public boolean isShutdown() {
return ses.isShutdown();
}
@Override
public boolean isTerminated() {
return ses.isTerminated();
}
private static class LoggingSaveRunnable implements Runnable {
Runnable r;
public LoggingSaveRunnable(Runnable r) {
this.r = r;
}
@Override
public void run() {
try {
r.run();
} catch (Throwable t) {
FilePrinter.printError(FilePrinter.EXCEPTION_CAUGHT, t);
}
}
}
}

View File

@@ -0,0 +1,31 @@
/*
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 server;
public interface TimerManagerMBean {
public boolean isTerminated();
public boolean isShutdown();
public long getCompletedTaskCount();
public long getActiveCount();
public long getTaskCount();
public int getQueuedTasks();
}

View File

@@ -0,0 +1,32 @@
/*
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 server.events;
/**
* @author kevintjuh93
*/
public class MapleEvents {
public MapleEvents() {
}
}

View File

@@ -0,0 +1,65 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package server.events;
import client.MapleCharacter;
import client.SkillFactory;
/**
*
* @author kevintjuh93
*/
public class RescueGaga extends MapleEvents {
private byte fallen;
private int completed;
public RescueGaga(int completed) {
super();
this.completed = completed;
this.fallen = 0;
}
public int fallAndGet() {
fallen++;
if (fallen > 3) {
fallen = 0;
return 4;
}
return fallen;
}
public byte getFallen() {
return fallen;
}
public int getCompleted() {
return completed;
}
public void complete() {
completed++;
}
public void giveSkill(MapleCharacter chr) {
int skillid = 0;
switch (chr.getJobType()) {
case 0:
skillid = 1013;
break;
case 1:
case 2:
skillid = 10001014;
}
long expiration = (System.currentTimeMillis() + (long) (3600 * 24 * 20 * 1000));//20 days
if (completed < 20) {
chr.changeSkillLevel(SkillFactory.getSkill(skillid), (byte) 1, 1, expiration);
chr.changeSkillLevel(SkillFactory.getSkill(skillid + 1), (byte) 1, 1, expiration);
chr.changeSkillLevel(SkillFactory.getSkill(skillid + 2), (byte) 1, 1, expiration);
} else {
chr.changeSkillLevel(SkillFactory.getSkill(skillid), (byte) 2, 2, chr.getSkillExpiration(skillid));
}
}
}

View File

@@ -0,0 +1,206 @@
/*
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 server.events.gm;
import client.MapleCharacter;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import server.TimerManager;
import server.maps.MapleMap;
import tools.MaplePacketCreator;
/**
*
* @author kevintjuh93
*/
//Make them better :)
public class MapleCoconut extends MapleEvent {
private MapleMap map = null;
private int MapleScore = 0;
private int StoryScore = 0;
private int countBombing = 80;
private int countFalling = 401;
private int countStopped = 20;
private List<MapleCoconuts> coconuts = new LinkedList<MapleCoconuts>();
public MapleCoconut(MapleMap map) {
super(1, 50);
this.map = map;
}
public void startEvent() {
map.startEvent();
for (int i = 0; i < 506; i++) {
coconuts.add(new MapleCoconuts(i));
}
map.broadcastMessage(MaplePacketCreator.hitCoconut(true, 0, 0));
setCoconutsHittable(true);
map.broadcastMessage(MaplePacketCreator.getClock(300));
TimerManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
if (map.getId() == 109080000) {
if (getMapleScore() == getStoryScore()) {
bonusTime();
} else if (getMapleScore() > getStoryScore()) {
for (MapleCharacter chr : map.getCharacters()) {
if (chr.getTeam() == 0) {
chr.getClient().announce(MaplePacketCreator.showEffect("event/coconut/victory"));
chr.getClient().announce(MaplePacketCreator.playSound("Coconut/Victory"));
} else {
chr.getClient().announce(MaplePacketCreator.showEffect("event/coconut/lose"));
chr.getClient().announce(MaplePacketCreator.playSound("Coconut/Failed"));
}
}
warpOut();
} else {
for (MapleCharacter chr : map.getCharacters()) {
if (chr.getTeam() == 1) {
chr.getClient().announce(MaplePacketCreator.showEffect("event/coconut/victory"));
chr.getClient().announce(MaplePacketCreator.playSound("Coconut/Victory"));
} else {
chr.getClient().announce(MaplePacketCreator.showEffect("event/coconut/lose"));
chr.getClient().announce(MaplePacketCreator.playSound("Coconut/Failed"));
}
}
warpOut();
}
}
}
}, 300000);
}
public void bonusTime() {
map.broadcastMessage(MaplePacketCreator.getClock(120));
TimerManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
if (getMapleScore() == getStoryScore()) {
for (MapleCharacter chr : map.getCharacters()) {
chr.getClient().announce(MaplePacketCreator.showEffect("event/coconut/lose"));
chr.getClient().announce(MaplePacketCreator.playSound("Coconut/Failed"));
}
warpOut();
} else if (getMapleScore() > getStoryScore()) {
for (MapleCharacter chr : map.getCharacters()) {
if (chr.getTeam() == 0) {
chr.getClient().announce(MaplePacketCreator.showEffect("event/coconut/victory"));
chr.getClient().announce(MaplePacketCreator.playSound("Coconut/Victory"));
} else {
chr.getClient().announce(MaplePacketCreator.showEffect("event/coconut/lose"));
chr.getClient().announce(MaplePacketCreator.playSound("Coconut/Failed"));
}
}
warpOut();
} else {
for (MapleCharacter chr : map.getCharacters()) {
if (chr.getTeam() == 1) {
chr.getClient().announce(MaplePacketCreator.showEffect("event/coconut/victory"));
chr.getClient().announce(MaplePacketCreator.playSound("Coconut/Victory"));
} else {
chr.getClient().announce(MaplePacketCreator.showEffect("event/coconut/lose"));
chr.getClient().announce(MaplePacketCreator.playSound("Coconut/Failed"));
}
}
warpOut();
}
}
}, 120000);
}
public void warpOut() {
setCoconutsHittable(false);
TimerManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
List<MapleCharacter> chars = new ArrayList<>(map.getCharacters());
for (MapleCharacter chr : chars) {
if ((getMapleScore() > getStoryScore() && chr.getTeam() == 0) || (getStoryScore() > getMapleScore() && chr.getTeam() == 1)) {
chr.changeMap(109050000);
} else {
chr.changeMap(109050001);
}
}
map.setCoconut(null);
}
}, 12000);
}
public int getMapleScore() {
return MapleScore;
}
public int getStoryScore() {
return StoryScore;
}
public void addMapleScore() {
this.MapleScore += 1;
}
public void addStoryScore() {
this.StoryScore += 1;
}
public int getBombings() {
return countBombing;
}
public void bombCoconut() {
countBombing--;
}
public int getFalling() {
return countFalling;
}
public void fallCoconut() {
countFalling--;
}
public int getStopped() {
return countStopped;
}
public void stopCoconut() {
countStopped--;
}
public MapleCoconuts getCoconut(int id) {
return coconuts.get(id);
}
public List<MapleCoconuts> getAllCoconuts() {
return coconuts;
}
public void setCoconutsHittable(boolean hittable) {
for (MapleCoconuts nut : coconuts) {
nut.setHittable(hittable);
}
}
}

View File

@@ -0,0 +1,63 @@
/*
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 server.events.gm;
/**
*
* @author kevintjuh93
*/
public class MapleCoconuts {
private int id;
private int hits = 0;
private boolean hittable = false;
private long hittime = System.currentTimeMillis();
public MapleCoconuts(int id) {
this.id = id;
}
public void hit() {
this.hittime = System.currentTimeMillis() + 750;
hits++;
}
public int getHits() {
return hits;
}
public void resetHits() {
hits = 0;
}
public boolean isHittable() {
return hittable;
}
public void setHittable(boolean hittable) {
this.hittable = hittable;
}
public long getHitTime() {
return hittime;
}
}

View File

@@ -0,0 +1,53 @@
/*
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 server.events.gm;
/**
*
* @author kevintjuh93
*/
public class MapleEvent {
private int mapid;
private int limit;
public MapleEvent(int mapid, int limit) {
this.mapid = mapid;
this.limit = limit;
}
public int getMapId() {
return mapid;
}
public int getLimit() {
return limit;
}
public void minusLimit() {
this.limit--;
}
public void addLimit() {
this.limit++;
}
}

View File

@@ -0,0 +1,133 @@
/*
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 server.events.gm;
import client.MapleCharacter;
import java.util.concurrent.ScheduledFuture;
import server.TimerManager;
import tools.MaplePacketCreator;
/**
*
* @author kevintjuh93
*/
public class MapleFitness {
private MapleCharacter chr;
private long time = 0;
private long timeStarted = 0;
private ScheduledFuture<?> schedule = null;
private ScheduledFuture<?> schedulemsg = null;
public MapleFitness(final MapleCharacter chr) {
this.chr = chr;
this.schedule = TimerManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
if (chr.getMapId() >= 109040000 && chr.getMapId() <= 109040004)
chr.changeMap(chr.getMap().getReturnMap());
}
}, 900000);
}
public void startFitness() {
chr.getMap().startEvent();
chr.getClient().announce(MaplePacketCreator.getClock(900));
this.timeStarted = System.currentTimeMillis();
this.time = 900000;
checkAndMessage();
chr.getMap().getPortal("join00").setPortalStatus(true);
chr.getClient().announce(MaplePacketCreator.serverNotice(0, "The portal has now opened. Press the up arrow key at the portal to enter."));
}
public boolean isTimerStarted() {
return time > 0 && timeStarted > 0;
}
public long getTime() {
return time;
}
public void resetTimes() {
this.time = 0;
this.timeStarted = 0;
schedule.cancel(false);
schedulemsg.cancel(false);
}
public long getTimeLeft() {
return time - (System.currentTimeMillis() - timeStarted);
}
public void checkAndMessage() {
this.schedulemsg = TimerManager.getInstance().register(new Runnable() {
@Override
public void run() {
if (chr.getFitness() == null) {
resetTimes();
}
if (chr.getMap().getId() >= 109040000 && chr.getMap().getId() <= 109040004) {
if (getTimeLeft() > 9000 && getTimeLeft() < 11000) {
chr.getClient().announce(MaplePacketCreator.serverNotice(0, "You have 10 sec left. Those of you unable to beat the game, we hope you beat it next time! Great job everyone!! See you later~"));
} else if (getTimeLeft() > 99000 && getTimeLeft() < 101000) {
chr.getClient().announce(MaplePacketCreator.serverNotice(0, "Alright, you don't have much time remaining. Please hurry up a little!"));
} else if (getTimeLeft() > 239000 && getTimeLeft() < 241000) {
chr.getClient().announce(MaplePacketCreator.serverNotice(0, "The 4th stage is the last one for [The Maple Physical Fitness Test]. Please don't give up at the last minute and try your best. The reward is waiting for you at the very top!"));
} else if (getTimeLeft() > 299000 && getTimeLeft() < 301000) {
chr.getClient().announce(MaplePacketCreator.serverNotice(0, "The 3rd stage offers traps where you may see them, but you won't be able to step on them. Please be careful of them as you make your way up."));
} else if (getTimeLeft() > 359000 && getTimeLeft() < 361000) {
chr.getClient().announce(MaplePacketCreator.serverNotice(0, "For those who have heavy lags, please make sure to move slowly to avoid falling all the way down because of lags."));
} else if (getTimeLeft() > 499000 && getTimeLeft() < 501000) {
chr.getClient().announce(MaplePacketCreator.serverNotice(0, "Please remember that if you die during the event, you'll be eliminated from the game. If you're running out of HP, either take a potion or recover HP first before moving on."));
} else if (getTimeLeft() > 599000 && getTimeLeft() < 601000) {
chr.getClient().announce(MaplePacketCreator.serverNotice(0, "The most important thing you'll need to know to avoid the bananas thrown by the monkeys is *Timing* Timing is everything in this!"));
} else if (getTimeLeft() > 659000 && getTimeLeft() < 661000) {
chr.getClient().announce(MaplePacketCreator.serverNotice(0, "The 2nd stage offers monkeys throwing bananas. Please make sure to avoid them by moving along at just the right timing."));
} else if (getTimeLeft() > 699000 && getTimeLeft() < 701000) {
chr.getClient().announce(MaplePacketCreator.serverNotice(0, "Please remember that if you die during the event, you'll be eliminated from the game. You still have plenty of time left, so either take a potion or recover HP first before moving on."));
} else if (getTimeLeft() > 779000 && getTimeLeft() < 781000) {
chr.getClient().announce(MaplePacketCreator.serverNotice(0, "Everyone that clears [The Maple Physical Fitness Test] on time will be given an item, regardless of the order of finish, so just relax, take your time, and clear the 4 stages."));
} else if (getTimeLeft() > 839000 && getTimeLeft() < 841000) {
chr.getClient().announce(MaplePacketCreator.serverNotice(0, "There may be a heavy lag due to many users at stage 1 all at once. It won't be difficult, so please make sure not to fall down because of heavy lag."));
} else if (getTimeLeft() > 869000 && getTimeLeft() < 871000) {
chr.getClient().announce(MaplePacketCreator.serverNotice(0, "[MapleStory Physical Fitness Test] consists of 4 stages, and if you happen to die during the game, you'll be eliminated from the game, so please be careful of that."));
}
} else {
resetTimes();
}
}
}, 5000, 29500);
}
// 14:30 [Notice][MapleStory Physical Fitness Test] consists of 4 stages, and if you happen to die during the game, you'll be eliminated from the game, so please be careful of that.
// 14:00 [Notice]There may be a heavy lag due to many users at stage 1 all at once. It won't be difficult, so please make sure not to fall down because of heavy lag.
// 13:00 [Notice]Everyone that clears [The Maple Physical Fitness Test] on time will be given an item, regardless of the order of finish, so just relax, take your time, and clear the 4 stages.
// 11:40 [Notice]Please remember that if you die during the event, you'll be eliminated from the game. You still have plenty of time left, so either take a potion or recover HP first before moving on.
// 11:00 [Notice]The 2nd stage offers monkeys throwing bananas. Please make sure to avoid them by moving along at just the right timing.
// 10:00 [Notice]The most important thing you'll need to know to avoid the bananas thrown by the monkeys is *Timing* Timing is everything in this!
// 8:20 [Notice]Please remember that if you die during the event, you'll be eliminated from the game. If you're running out of HP, either take a potion or recover HP first before moving on.
// 6:00 [Notice]For those who have heavy lags, please make sure to move slowly to avoid falling all the way down because of lags.
// 5:00 [Notice]The 3rd stage offers traps where you may see them, but you won't be able to step on them. Please be careful of them as you make your way up.
// 4:00 [Notice]The 4th stage is the last one for [The Maple Physical Fitness Test]. Please don't give up at the last minute and try your best. The reward is waiting for you at the very top!
// 1:40 [Notice]Alright, you don't have much time remaining. Please hurry up a little!
// 0:10 [Notice]You have 10 sec left. Those of you unable to beat the game, we hope you beat it next time! Great job everyone!! See you later~
}

View File

@@ -0,0 +1,78 @@
/*
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 server.events.gm;
import client.MapleCharacter;
import java.util.concurrent.ScheduledFuture;
import server.TimerManager;
import tools.MaplePacketCreator;
/**
*
* @author kevintjuh93
*/
public class MapleOla {
private MapleCharacter chr;
private long time = 0;
private long timeStarted = 0;
private ScheduledFuture<?> schedule = null;
public MapleOla(final MapleCharacter chr) {
this.chr = chr;
this.schedule = TimerManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
if (chr.getMapId() >= 109030001 && chr.getMapId() <= 109030303)
chr.changeMap(chr.getMap().getReturnMap());
resetTimes();
}
}, 360000);
}
public void startOla() { // TODO: Messages
chr.getMap().startEvent();
chr.getClient().announce(MaplePacketCreator.getClock(360));
this.timeStarted = System.currentTimeMillis();
this.time = 360000;
chr.getMap().getPortal("join00").setPortalStatus(true);
chr.getClient().announce(MaplePacketCreator.serverNotice(0, "The portal has now opened. Press the up arrow key at the portal to enter."));
}
public boolean isTimerStarted() {
return time > 0 && timeStarted > 0;
}
public long getTime() {
return time;
}
public void resetTimes() {
this.time = 0;
this.timeStarted = 0;
schedule.cancel(false);
}
public long getTimeLeft() {
return time - (System.currentTimeMillis() - timeStarted);
}
}

View File

@@ -0,0 +1,111 @@
/*
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 server.events.gm;
import client.MapleCharacter;
import tools.Randomizer;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import provider.MapleDataProvider;
import provider.MapleDataProviderFactory;
import provider.MapleDataTool;
import server.TimerManager;
import server.maps.MapleMap;
import tools.MaplePacketCreator;
/**
*
* @author FloppyDisk
*/
public final class MapleOxQuiz {
private int round = 1;
private int question = 1;
private MapleMap map = null;
private int expGain = 200;
private static MapleDataProvider stringData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Etc.wz"));
public MapleOxQuiz(MapleMap map) {
this.map = map;
this.round = Randomizer.nextInt(9);
this.question = 1;
}
private boolean isCorrectAnswer(MapleCharacter chr, int answer) {
double x = chr.getPosition().getX();
double y = chr.getPosition().getY();
if ((x > -234 && y > -26 && answer == 0) || (x < -234 && y > -26 && answer == 1)) {
chr.dropMessage("Correct!");
return true;
}
return false;
}
public void sendQuestion() {
int gm = 0;
for (MapleCharacter mc : map.getCharacters()) {
if (mc.gmLevel() > 0) {
gm++;
}
}
final int number = gm;
map.broadcastMessage(MaplePacketCreator.showOXQuiz(round, question, true));
TimerManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
map.broadcastMessage(MaplePacketCreator.showOXQuiz(round, question, true));
List<MapleCharacter> chars = new ArrayList<>(map.getCharacters());
for (MapleCharacter chr : chars) {
if (chr != null) // make sure they aren't null... maybe something can happen in 12 seconds.
{
if (!isCorrectAnswer(chr, getOXAnswer(round, question)) && !chr.isGM()) {
chr.changeMap(chr.getMap().getReturnMap());
} else {
chr.gainExp(expGain, true, true);
}
}
}
//do question
if ((round == 1 && question == 29) || ((round == 2 || round == 3) && question == 17) || ((round == 4 || round == 8) && question == 12) || (round == 5 && question == 26) || (round == 9 && question == 44) || ((round == 6 || round == 7) && question == 16)) {
question = 100;
} else {
question++;
}
//send question
if (map.getCharacters().size() - number <= 2) {
map.broadcastMessage(MaplePacketCreator.serverNotice(6, "The event has ended"));
map.getPortal("join00").setPortalStatus(true);
map.setOx(null);
map.setOxQuiz(false);
//prizes here
return;
}
sendQuestion();
}
}, 30000); // Time to answer = 30 seconds ( Ox Quiz packet shows a 30 second timer.
}
private static int getOXAnswer(int imgdir, int id) {
return MapleDataTool.getInt(stringData.getData("OXQuiz.img").getChildByPath("" + imgdir + "").getChildByPath("" + id + "").getChildByPath("a"));
}
}

View File

@@ -0,0 +1,165 @@
/*
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 server.events.gm;
import client.MapleCharacter;
import java.util.LinkedList;
import java.util.List;
import server.TimerManager;
import server.maps.MapleMap;
import tools.MaplePacketCreator;
/**
*
* @author kevintjuh93
*/
public class MapleSnowball {
private MapleMap map;
private int position = 0;
private int hits = 3;
private int snowmanhp = 1000;
private boolean hittable = false;
private int team;
private boolean winner = false;
List<MapleCharacter> characters = new LinkedList<MapleCharacter>();
public MapleSnowball(int team, MapleMap map) {
this.map = map;
this.team = team;
for (MapleCharacter chr : map.getCharacters()) {
if (chr.getTeam() == team)
characters.add(chr);
}
}
public void startEvent() {
if (hittable == true) return;
for (MapleCharacter chr : characters) {
if (chr != null) {
chr.announce(MaplePacketCreator.rollSnowBall(false, 1, map.getSnowball(0), map.getSnowball(1)));
chr.announce(MaplePacketCreator.getClock(600));
}
}
hittable = true;
TimerManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
if (map.getSnowball(team).getPosition() > map.getSnowball(team == 0 ? 1 : 0).getPosition()) {
for (MapleCharacter chr : characters) {
if (chr != null)
chr.announce(MaplePacketCreator.rollSnowBall(false, 3, map.getSnowball(0), map.getSnowball(0)));
}
winner = true;
} else if (map.getSnowball(team == 0 ? 1 : 0).getPosition() > map.getSnowball(team).getPosition()) {
for (MapleCharacter chr : characters) {
if (chr != null)
chr.announce(MaplePacketCreator.rollSnowBall(false, 4, map.getSnowball(0), map.getSnowball(0)));
}
winner = true;
} //Else
warpOut();
}
}, 600000);
}
public boolean isHittable() {
return hittable;
}
public void setHittable(boolean hit) {
this.hittable = hit;
}
public int getPosition() {
return position;
}
public int getSnowmanHP() {
return snowmanhp;
}
public void setSnowmanHP(int hp) {
this.snowmanhp = hp;
}
public void hit(int what, int damage) {
if (what < 2)
if (damage > 0)
this.hits--;
else {
if (this.snowmanhp - damage < 0) {
this.snowmanhp = 0;
TimerManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
setSnowmanHP(7500);
message(5);
}
}, 10000);
} else
this.snowmanhp -= damage;
map.broadcastMessage(MaplePacketCreator.rollSnowBall(false, 1, map.getSnowball(0), map.getSnowball(1)));
}
if (this.hits == 0) {
this.position += 1;
if (this.position == 45)
map.getSnowball(team == 0 ? 1 : 0).message(1);
else if (this.position == 290)
map.getSnowball(team == 0 ? 1 : 0).message(2);
else if (this.position == 560)
map.getSnowball(team == 0 ? 1 : 0).message(3);
this.hits = 3;
map.broadcastMessage(MaplePacketCreator.rollSnowBall(false, 0, map.getSnowball(0), map.getSnowball(1)));
map.broadcastMessage(MaplePacketCreator.rollSnowBall(false, 1, map.getSnowball(0), map.getSnowball(1)));
}
map.broadcastMessage(MaplePacketCreator.hitSnowBall(what, damage));
}
public void message(int message) {
for (MapleCharacter chr : characters) {
if (chr != null)
chr.announce(MaplePacketCreator.snowballMessage(team, message));
}
}
public void warpOut() {
TimerManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
if (winner == true)
map.warpOutByTeam(team, 109050000);
else
map.warpOutByTeam(team, 109050001);
map.setSnowball(team, null);
}
}, 10000);
}
}

View File

@@ -0,0 +1,218 @@
/*
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 server.expeditions;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ScheduledFuture;
import net.server.Server;
import server.TimerManager;
import server.life.MapleMonster;
import server.maps.MapleMap;
import tools.LogHelper;
import tools.MaplePacketCreator;
import client.MapleCharacter;
/**
*
* @author SharpAceX(Alan)
*/
public class MapleExpedition {
private static final int [] EXPEDITION_BOSSES = {
8800000,// - Zakum's first body
8800001,// - Zakum's second body
8800002,// - Zakum's third body
8800003,// - Zakum's Arm 1
8800004,// - Zakum's Arm 2
8800005,// - Zakum's Arm 3
8800006,// - Zakum's Arm 4
8800007,// - Zakum's Arm 5
8800008,// - Zakum's Arm 6
8800009,// - Zakum's Arm 7
8800010,// - Zakum's Arm 8
8810000,// - Horntail's Left Head
8810001,// - Horntail's Right Head
8810002,// - Horntail's Head A
8810003,// - Horntail's Head B
8810004,// - Horntail's Head C
8810005,// - Horntail's Left Hand
8810006,// - Horntail's Right Hand
8810007,// - Horntail's Wings
8810008,// - Horntail's Legs
8810009,// - Horntail's Tails
9420546,// - Scarlion Boss
9420547,// - Scarlion Boss
9420548,// - Angry Scarlion Boss
9420549,// - Furious Scarlion Boss
9420541,// - Targa
9420542,// - Targa
9420543,// - Angry Targa
9420544,// - Furious Targa
};
private MapleCharacter leader;
private MapleExpeditionType type;
private boolean registering;
private MapleMap startMap;
private ArrayList<String> bossLogs;
private ScheduledFuture<?> schedule;
private List<MapleCharacter> members = new ArrayList<MapleCharacter>();
private List<MapleCharacter> banned = new ArrayList<MapleCharacter>();
private long startTime;
public MapleExpedition(MapleCharacter player, MapleExpeditionType met) {
leader = player;
members.add(leader);
startMap = player.getMap();
type = met;
bossLogs = new ArrayList<String>();
beginRegistration();
}
private void beginRegistration() {
registering = true;
startMap.broadcastMessage(MaplePacketCreator.getClock(type.getRegistrationTime() * 60));
startMap.broadcastMessage(MaplePacketCreator.serverNotice(6, leader.getName() + " has been declared the expedition captain. Please register for the expedition."));
scheduleRegistrationEnd();
}
private void scheduleRegistrationEnd() {
final MapleExpedition exped = this;
schedule = TimerManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
if (registering){
leader.getClient().getChannelServer().getExpeditions().remove(exped);
startMap.broadcastMessage(MaplePacketCreator.serverNotice(6, "Time limit has been reached. Expedition has been disbanded."));
}
dispose(false);
}
}, type.getRegistrationTime() * 60 * 1000);
}
public void dispose(boolean log){
if (schedule != null){
schedule.cancel(false);
}
if (log && !registering){
LogHelper.logExpedition(this);
}
}
public void start(){
registering = false;
startMap.broadcastMessage(MaplePacketCreator.removeClock());
broadcastExped(MaplePacketCreator.serverNotice(6, "The expedition has started! The expedition leader is waiting inside!"));
startTime = System.currentTimeMillis();
Server.getInstance().broadcastGMMessage(MaplePacketCreator.serverNotice(6, type.toString() + " Expedition started with leader: " + leader.getName()));
}
public String addMember(MapleCharacter player) {
if (!registering){
return "Sorry, this expedition is already underway. Registration is closed!";
}
if (banned.contains(player)){
return "Sorry, you've been banned from this expedition by #b" + leader.getName() + "#k.";
}
if (members.size() >= type.getMaxSize()){ //Would be a miracle if anybody ever saw this
return "Sorry, this expedition is full!";
}
if (members.add(player)){
broadcastExped(MaplePacketCreator.serverNotice(6, player.getName() + " has joined the expedition!"));
return "You have registered for the expedition successfully!";
}
return "Sorry, something went really wrong. Report this on the forum with a screenshot!";
}
private void broadcastExped(byte [] data){
for (MapleCharacter member : members){
member.getClient().announce(data);
}
}
public boolean removeMember(MapleCharacter chr) {
return members.remove(chr);
}
public MapleExpeditionType getType() {
return type;
}
public List<MapleCharacter> getMembers() {
return members;
}
public MapleCharacter getLeader(){
return leader;
}
public boolean contains(MapleCharacter player) {
for (MapleCharacter member : members){
if (member.getId() == player.getId()){
return true;
}
}
return false;
}
public boolean isLeader(MapleCharacter player) {
return leader.equals(player);
}
public boolean isRegistering(){
return registering;
}
public boolean isInProgress(){
return !registering;
}
public void ban(MapleCharacter player) {
if (!banned.contains(player)) {
banned.add(player);
members.remove(player);
}
}
public long getStartTime(){
return startTime;
}
public ArrayList<String> getBossLogs(){
return bossLogs;
}
public void monsterKilled(MapleCharacter chr, MapleMonster mob) {
for (int i = 0; i < EXPEDITION_BOSSES.length; i++){
if (mob.getId() == EXPEDITION_BOSSES[i]){ //If the monster killed was a boss
String timeStamp = new SimpleDateFormat("HH:mm:ss").format(new Date());
bossLogs.add(">" + mob.getName() + " was killed after " + LogHelper.getTimeString(startTime) + " - " + timeStamp + "\r\n");
return;
}
}
}
}

View File

@@ -0,0 +1,75 @@
/*
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 server.expeditions;
/**
*
* @author SharpAceX(Alan)
*/
public enum MapleExpeditionType {
BALROG_EASY(3, 30, 50, 255, 5),
BALROG_NORMAL(6, 30, 50, 255, 5),
SCARGA(3, 6, 100, 255, 5),
ZAKUM(6, 30, 50, 255, 5),
HORNTAIL(6, 30, 80, 255,5),
CHAOS_ZAKUM(6, 30, 120, 255, 5),
CHAOS_HORNTAIL(6, 30, 120, 255, 5),
PINKBEAN(6, 30, 120, 255, 5),
CWKPQ(6, 30, 100, 255, 5);
private int minSize;
private int maxSize;
private int minLevel;
private int maxLevel;
private int registrationTime;
private MapleExpeditionType(int minSize, int maxSize, int minLevel, int maxLevel, int minutes) {
this.minSize = minSize;
this.maxSize = maxSize;
this.minLevel = minLevel;
this.maxLevel = maxLevel;
this.registrationTime = minutes;
}
public int getMinSize() {
return minSize;
}
public int getMaxSize() {
return maxSize;
}
public int getMinLevel() {
return minLevel;
}
public int getMaxLevel() {
return maxLevel;
}
public int getRegistrationTime(){
return registrationTime;
}
}

View File

@@ -0,0 +1,104 @@
package server.gachapon;
/**
*
* @author SharpAceX(Alan)
*/
public class Ellinia extends GachaponItems {
@Override
public int[] getCommonItems() {
return new int[] {
//warriorEquips = {
1082025, 1060028, 1051011, 1060016, 1051001,
1422001, 1002025, 1082000, 1302002, 1412012,
//magicianEquips = {
1002013, 1002016, 1002017, 1002034, 1002035,
1002036, 1002037, 1002038, 1002064, 1002065,
1002072, 1002073, 1002074, 1002075, 1002102,
1002103, 1002104, 1002105, 1002106, 1002141,
1002142, 1002143, 1002144, 1002145, 1002151,
1002152, 1002153, 1002154, 1002155, 1002215,
1002216, 1002217, 1002218, 1002242, 1002243,
1002244, 1002245, 1002246, 1002252, 1002253,
1002254, 1002271, 1002272, 1002273, 1002274,
1002363, 1002364, 1002365, 1002366, 1002398,
1002399, 1002400, 1002401, 1002579, 1002773,
1040004, 1040017, 1040018,
1040019, 1040020, 1041015, 1041016, 1041017,
1041018, 1041025, 1041026, 1041029, 1041030,
1041031, 1041041, 1041042, 1041043, 1041051,
1041052, 1041053, 1050001, 1050002, 1050003,
1050008, 1050009, 1050010, 1050023, 1050024,
1050025, 1050026, 1050027, 1050028, 1050029,
1050030, 1050031, 1050035, 1050036, 1050037,
1050038, 1050039, 1050045, 1050046, 1050047,
1050048, 1050049, 1050053, 1050054, 1050055,
1050056, 1050067, 1050068, 1050069, 1050070,
1050072, 1050073, 1050074, 1050092, 1050093,
1050094, 1050095, 1050102, 1050103, 1050104,
1050105, 1051003, 1051004, 1051005, 1051023,
1051024, 1051025, 1051026, 1051027, 1051030,
1051031, 1051032, 1051033, 1051034, 1051044,
1051045, 1051046, 1051047, 1051052, 1051053,
1051054, 1051055, 1051056, 1051057, 1051058,
1051094, 1051095, 1051096, 1051097, 1051101,
1051102, 1051103, 1051104, 1052076,
1060012, 1060013, 1060014, 1060015,
1061010, 1061011, 1061012, 1061013, 1061021,
1061022, 1061027, 1061028, 1061034, 1061035,
1061036, 1061047, 1061048, 1061049, 1072006,
1072019, 1072020, 1072021, 1072023, 1072024,
1072044, 1072045, 1072072, 1072073, 1072074,
1072075, 1072076, 1072077, 1072078, 1072089,
1072090, 1072091, 1072114, 1072115, 1072116,
1072117, 1072136, 1072137, 1072138, 1072139,
1072140, 1072141, 1072142, 1072143, 1072157,
1072158, 1072159, 1072160, 1072169, 1072177,
1072178, 1072179, 1072206, 1072207, 1072208,
1072209, 1072223, 1072224, 1072225, 1072226,
1072268, 1082019, 1082020,
1082021, 1082022, 1082026, 1082027, 1082028,
1082051, 1082052, 1082053, 1082054, 1082055,
1082056, 1082062, 1082063, 1082064, 1082080,
1082081, 1082082, 1082086, 1082087, 1082088,
1082098, 1082099, 1082100, 1082121, 1082122,
1082123, 1082131, 1082132, 1082133, 1082134,
1082151, 1082152, 1082153, 1082154, 1082164,
1092021, 1092029, 1092057,
1372000, 1372001, 1372002, 1372003, 1372004,
1372007, 1372008, 1372009, 1372010, 1372011,
1372012, 1372014, 1372015, 1372016, 1372032,
1382000, 1382001, 1382002, 1382003, 1382004,
1382005, 1382006, 1382007, 1382008, 1382010,
1382011, 1382014, 1382015, 1382016, 1382017,
1382018, 1382019, 1382035, 1382036, 1382037,
1382041, 1382053, 1382054, 1382055, 1382056,
1382060,
//bowmanEquips = {
1040003, 1462005, 1002157, 1002119, 1062002,
1062004, 1041083, 1061082, 1082017, 1041061,
//thiefEquips = {
1002174, 1040063, 1072108, 1082044, 1061071,
1060052, 1072029, 1472002, 1082031, 1060023,
//pirateEquips = {
1002625, 1002616, 1482005, 1052098, 1482003,
1482001, 1492004, 1002622, 1492005, 1082195,
};
}
@Override
public int[] getUncommonItems() {
return new int [] { 1372035, 1372036, 1372037, 1372038, 1372039,
1372040, 1372041, 1372042, 1382045, 1382046,
1382047, 1382048, 1382049, 1382050, 1382051,
1382052, };
}
@Override
public int[] getRareItems() {
return new int [] {1382059, 1382057, 1072362, 1002791, 1052161, 1082240};
}
}

View File

@@ -0,0 +1,47 @@
/*
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 server.gachapon;
/**
*
* @author SharpAceX(Alan)
*/
public abstract class GachaponItems {
public abstract int [] getCommonItems();
public abstract int [] getUncommonItems();
public abstract int [] getRareItems();
public int[] getItems(int tier) {
if (tier == 0){
return getCommonItems();
} else if (tier == 1){
return getUncommonItems();
} else if (tier == 2){
return getRareItems();
}
return null;
}
}

View File

@@ -0,0 +1,60 @@
package server.gachapon;
/**
*
* @author SharpAceX(Alan)
*/
public class Global extends GachaponItems {
@Override
public int[] getCommonItems() {
return new int[] {
/* Gloves */ 1082002, 1082147, 1082148, 1082146, 1082145, 1082150,
/* Capes */ 1102040, 1102043, 1102087, 1102079, 1102080, 1102081, 1102082, 1102083, 1102053, 1102054,
1102055, 1102056, 1102176, 1102177, 1102178, 1102179, 1102000, 1102001, 1102002, 1102003,
1102004, 1102011, 1102012, 1102013, 1102014, 1102015, 1102016, 1102017, 1102018, 1102021,
1102022, 1102023, 1102024, 1102026, 1102027, 1102028,
/* Tube Eqp */ 1322026, 1322025, 1322024, 1322022, 1322021,
/* Umbrellas */ 1302026, 1302027, 1302028, 1302017,
/* Snowboards */ 1442017, 1442016, 1442014, 1442012,
/* Skis */ 1432017, 1432016, 1432015,
/* Beginner Eqp */ 1442018, 1422011,
/* Potions */ 2000004, 2000005, 2001002, 2001001, 2020012, 2020013, 2020014, 2020015, 2022182, 2022245,
2022284, 2022285, 2022439,
/* Other Scrolls */ 2049000, 2049001, 2049002, 2041058, 2040727,
/* 10% Scrolls */ 2041002, 2040402, 2040702, 2040805, 2040026, 2040031, 2040318, 2040323, 2040328, 2040419,
2040422, 2040427, 2040534, 2040619, 2040622, 2040627, 2040825, 2040925, 2040928, 2040933,
2040016,
/* 60% Scrolls */ 2040001, 2040321, 2040425, 2040625, 2040931, 2048013, 2040025, 2040326, 2040532, 2040824,
2048010, 2040029, 2040418, 2040618, 2040924, 2048011, 2040317, 2040421, 2040621, 2040927,
2048012,
/* 100% Scrolls */ 2040923, 2040027, 2040417, 2040617, 2040000, 2040202, 2040400, 2040512, 2040700, 2040803,
2041000, 2041012, 2048000, 2040926, 2040316, 2040420, 2040620, 2040003, 2040207, 2040414,
2040515, 2040703, 2040818, 2041003, 2041015, 2048003, 2040929, 2040319, 2040423, 2040623,
2040102, 2040300, 2040500, 2040600, 2040706, 2040900, 2041006, 2041018, 2040024, 2040324,
2040530, 2040823, 2040107, 2040312, 2040503, 2040614, 2040800, 2040918, 2041009, 2041021
};
}
@Override
public int[] getUncommonItems() {
return new int[] {
/* Capes */ 1102180,
/* Potions */ 2022179, 2022273, 2022282, 2022283,
/* Scrolls */ 2049003,
/* Skis */ 1432018
};
}
@Override
public int[] getRareItems() {
return new int[] {
/* Gloves */ 1082149,
/* Capes */ 1102041, 1102042, 1102084, 1102085,
/* Scrolls */ 2049100, 2340000,
/* Chairs */ 3010046, 3010047
};
}
}

View File

@@ -0,0 +1,40 @@
package server.gachapon;
/**
*
* @author SharpAceX(Alan)
*/
public class Henesys extends GachaponItems {
@Override
public int[] getCommonItems() {
return new int [] {
/* Common Eqps */ 1432009, 1302022, 1322027, 1062000, 1002033, 1092022, 1302021, 1322009, 1002012, 1322012,
/* Warrior Eqps */ 1312007, 1002093, 1051016, 1040030, 1060009, 1060000, 1082025, 1402002, 1092000, 1072041,
/* Mage Equips */ 1051023, 1002035, 1061028, 1040019, 1002152, 1002155, 1041018, 1050031, 1002102, 1082028,
/* Bowman Equips */ 1002010, 1002057, 1002112, 1002113, 1002114, 1002115, 1002116, 1002117, 1002118, 1002119,
1002120, 1002121, 1002135, 1002136, 1002137, 1002138, 1002139, 1002156, 1002157, 1002158,
1002159, 1002160, 1002161, 1002162, 1002163, 1002164, 1002165, 1002166, 1002167, 1002168,
1002169, 1002170, 1002211, 1002212, 1002213, 1002214, 1002267, 1002268, 1002269, 1002270,
1002275, 1002276, 1002277, 1002278, 1002286, 1002287, 1002288, 1002289, 1002402, 1002403,
1002404, 1002405, 1002406, 1002407, 1002408, 1002580, 1002749
};
}
@Override
public int[] getUncommonItems() {
return new int[] {
/* 110 Equips */ 1002547
};
}
@Override
public int[] getRareItems() {
return new int[] {
/* Reverse Eqps */ 1002792,
1462052, 1462053, 1462054, 1462055,
};
}
}

View File

@@ -0,0 +1,121 @@
package server.gachapon;
/**
*
* @author SharpAceX(Alan)
*/
public class KerningCity extends GachaponItems {
@Override
public int[] getCommonItems() {
return new int [] {
//warriorEquips = {
1002023, 1082001, 1041084, 1060017, 1422008,
1402018, 1060019, 1072047, 1040009, 1060060,
//magicianEquips = {
1050029, 1072045, 1050028, 1372001, 1051024,
1061049, 1072091, 1041030, 1041042, 1002036,
//bowmanEquips = {
1072103, 1072034, 1072069, 1062004, 1082050,
1040003, 1061064, 1040074, 1061051, 1040079,
//thiefEquips = {
1002107, 1002108, 1002109, 1002110, 1002111,
1002122, 1002123, 1002124, 1002125, 1002126,
1002127, 1002128, 1002129, 1002130, 1002131,
1002146, 1002147, 1002148, 1002149, 1002150,
1002171, 1002172, 1002173, 1002174, 1002175,
1002176, 1002177, 1002178, 1002179, 1002180,
1002181, 1002182, 1002183, 1002184, 1002185,
1002207, 1002208, 1002209, 1002210, 1002247,
1002248, 1002249, 1002281, 1002282, 1002283,
1002284, 1002285, 1002323, 1002324, 1002325,
1002326, 1002327, 1002328, 1002329, 1002330,
1002380, 1002381, 1002382, 1002383, 1002550,
1002577, 1002656, 1002750,
1040031, 1040032, 1040033, 1040034, 1040035,
1040042, 1040043, 1040044, 1040048, 1040049,
1040050, 1040057, 1040058, 1040059, 1040060,
1040061, 1040062, 1040063, 1040082, 1040083,
1040084, 1040094, 1040095, 1040096, 1040097,
1040098, 1040099, 1040100, 1040105, 1040106,
1040107, 1040108, 1040109, 1040110, 1040115,
1040116, 1040117, 1040118, 1041003, 1041036,
1041037, 1041038, 1041039, 1041040, 1041044,
1041045, 1041047, 1041048, 1041049, 1041050,
1041057, 1041058, 1041059, 1041060, 1041074,
1041075, 1041076, 1041077, 1041078, 1041079,
1041080, 1041094, 1041095, 1041096, 1041100,
1041101, 1041102, 1041103, 1041105, 1041106,
1041107, 1041115, 1041116, 1041117, 1041118,
1050096, 1050097, 1050098, 1050099, 1051006,
1051007, 1051008, 1051009, 1051090, 1051091,
1051092, 1051093, 1052072, 1052163,
1060021, 1060022, 1060023, 1060024, 1060025,
1060031, 1060032, 1060033, 1060037, 1060038,
1060039, 1060043, 1060044, 1060045, 1060046,
1060050, 1060051, 1060052, 1060071, 1060072,
1060073, 1060083, 1060084, 1060085, 1060086,
1060087, 1060088, 1060089, 1060093, 1060094,
1060095, 1060097, 1060098, 1060099, 1060104,
1060105, 1060106, 1060107, 1061003, 1061029,
1061030, 1061031, 1061032, 1061033, 1061037,
1061038, 1061040, 1061041, 1061042, 1061043,
1061044, 1061045, 1061046, 1061053, 1061054,
1061055, 1061056, 1061069, 1061070, 1061071,
1061076, 1061077, 1061078, 1061079, 1061093,
1061094, 1061095, 1061099, 1061100, 1061101,
1061102, 1061104, 1061105, 1061106, 1061114,
1061115, 1061116, 1061117, 1072022, 1072028,
1072029, 1072030, 1072031, 1072032, 1072033,
1072035, 1072036, 1072065, 1072066, 1072070,
1072071, 1072084, 1072085, 1072086, 1072087,
1072104, 1072105, 1072106, 1072107, 1072108,
1072109, 1072110, 1072128, 1072129, 1072130,
1072131, 1072150, 1072151, 1072152, 1072161,
1072162, 1072163, 1072171, 1072172, 1072173,
1072174, 1072192, 1072193, 1072194, 1072195,
1072213, 1072214, 1072215, 1072216, 1072272,
1072346, 1082029, 1082030,
1082031, 1082032, 1082033, 1082034, 1082037,
1082038, 1082039, 1082042, 1082043, 1082044,
1082045, 1082046, 1082047, 1082065, 1082066,
1082067, 1082074, 1082075, 1082076, 1082092,
1082093, 1082094, 1082095, 1082096, 1082097,
1082118, 1082119, 1082120, 1082135, 1082136,
1082137, 1082138, 1082142, 1082143, 1082144,
1082167, 1082242, 1092018, 1092019,
1092020, 1302001,
1312002, 1332000, 1332001, 1332002, 1332003,
1332004, 1332011, 1332012, 1332013, 1332014,
1332015, 1332018, 1332023, 1332024, 1332027,
1332031, 1332050, 1332052, 1332054,
1332067, 1332068, 1332069, 1332070, 1332071,
1332072, 1332077,
1472000, 1472001, 1472002,
1472003, 1472004, 1472005, 1472006, 1472007,
1472008, 1472009, 1472010, 1472011, 1472012,
1472013, 1472014, 1472015, 1472016, 1472017,
1472018, 1472019, 1472020, 1472021, 1472022,
1472023, 1472024, 1472025, 1472026, 1472027,
1472028, 1472029, 1472031, 1472033, 1472051,
1472052,
1472069, 1472072, 1472074,
1472075,
///pirateEquips = {
1082192, 1072288, 1492003, 1052113, 1052104,
1492002, 1052095, 1492001, 1002613, 1492004,
};
}
@Override
public int[] getUncommonItems() {
return new int[] {1472053, 1332064, 1092050, 1472054};
}
@Override
public int[] getRareItems() {
return new int[] {1472073, 1092049, 1002793, 1332079, 1072364, 1472062, 1332078, 1332080};
}
}

View File

@@ -0,0 +1,121 @@
/*
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 server.gachapon;
import tools.Randomizer;
/**
*
* @author SharpAceX(Alan)
*/
public class MapleGachapon {
private static final MapleGachapon instance = new MapleGachapon();
public enum Gachapon {
GLOBAL(-1, -1, -1, -1, new Global()),
HENESYS(9100100, 90, 8, 2, new Henesys()),
ELLINIA(9100101, 90, 8, 2, new Ellinia()),
PERION(9100102, 90, 8, 2, new Perion()),
KERNING_CITY(9100103, 90, 8, 2, new KerningCity()),
SLEEPYWOOD(9100104, 90, 8, 2, new Sleepywood()),
MUSHROOM_SHRINE(9100105, 90, 8, 2, new MushroomShrine()),
SHOWA_SPA_MALE(9100106, 90, 8, 2, new ShowaSpaMale()),
SHOWA_SPA_FEMALE(9100107, 90, 8, 2, new ShowaSpaFemale()),
NEW_LEAF_CITY(9100109, 90, 8, 2, new NewLeafCity()),
NAUTILUS_HARBOR(9100117, 90, 8, 2, new NautilusHarbor());
private GachaponItems gachapon;
private int npcId;
private int common;
private int uncommon;
private int rare;
private Gachapon(int npcid, int c, int u, int r, GachaponItems g) {
npcId = npcid;
gachapon = g;
common = c;
uncommon = u;
rare = r;
}
private int getTier() {
int chance = Randomizer.nextInt(common + uncommon + rare) + 1;
if (chance > common + uncommon) {
return 2; //Rare
} else if (chance > common) {
return 1; //Uncommon
}
return 0; //Common
}
public int [] getItems(int tier){
return gachapon.getItems(tier);
}
public int getItem(int tier) {
int[] gacha = getItems(tier);
int[] global = GLOBAL.getItems(tier);
int chance = Randomizer.nextInt(gacha.length + global.length);
return chance < gacha.length ? gacha[chance] : global[chance - gacha.length];
}
public static Gachapon getByNpcId(int npcId) {
for (Gachapon gacha : Gachapon.values()) {
if (npcId == gacha.npcId) {
return gacha;
}
}
return null;
}
}
public static MapleGachapon getInstance() {
return instance;
}
public MapleGachaponItem process(int npcId) {
Gachapon gacha = Gachapon.getByNpcId(npcId);
int tier = gacha.getTier();
int item = gacha.getItem(tier);
return new MapleGachaponItem(tier, item);
}
public class MapleGachaponItem {
private int id;
private int tier;
public MapleGachaponItem(int t, int i) {
id = i;
tier = t;
}
public int getTier() {
return tier;
}
public int getId() {
return id;
}
}
}

View File

@@ -0,0 +1,40 @@
package server.gachapon;
/**
*
* @author SharpAceX(Alan)
*/
public class MushroomShrine extends GachaponItems {
@Override
public int[] getCommonItems() {
return new int []{
1382011, 1332024, 1302022, 1302021, 1462006, 1402009, 1402010, 1322012, 1312013, 1472008,
1432008, 1050100, 1051098,
};
}
@Override
public int[] getUncommonItems() {
//All Scrolls
return new int [] {
2043015, 2043017, 2043019, 2044000, 2044001, 2044002, 2044004, 2044005, 2044010, 2044012,
2044014, 2043200, 2043201, 2043202, 2043204, 2043205, 2043210, 2043212, 2043214, 2044200,
2044201, 2044202, 2044204, 2044205, 2044210, 2044212, 2044214, 2044300, 2044301, 2044302,
2044304, 2044305, 2044310, 2044312, 2044314, 2044400, 2044401, 2044402, 2044404, 2044405,
2044410, 2044412, 2044414,
2043800, 2043801, 2043802, 2043804, 2043805, 2043700, 2043701, 2043702, 2043704, 2043705,
2044605, 2044604, 2044602, 2044601, 2044600, 2044505, 2044504, 2044502, 2044501, 2044500,
2044700, 2044701, 2044702, 2044704, 2044705, 2043300, 2043301, 2043302, 2043304, 2043305,
2044800, 2044801, 2044802, 2044803, 2044804, 2044805, 2044807, 2044809, 2044900, 2044901,
2044902, 2044903, 2044904,
};
}
@Override
public int[] getRareItems() {
return new int [] {};
}
}

View File

@@ -0,0 +1,49 @@
package server.gachapon;
/**
*
* @author SharpAceX(Alan)
*/
public class NautilusHarbor extends GachaponItems {
@Override
public int[] getCommonItems() {
return new int[] {
/* Warrior Equips*/ 1060017, 1302008, 1002055, 1041064, 1072127, 1072047, 1072002, 1040028, 1072041, 1092000,
/* Mage Equips */ 1050010, 1072006, 1061022, 1051003, 1072074, 1050008, 1082053, 1051026, 1382015, 1002013,
/* Bowman Equips */ 1082048, 1041056, 1002157, 1462048, 1041054, 1061061, 1002161, 1002162, 1002158, 1002120,
/* Thief Equips */ 1040061, 1072031, 1051009, 1072036, 1002182, 1060073, 1472013, 1472009, 1002184, 1061055,
/* Pirate Equips */ 1002610, 1002616, 1002622, 1002628, 1002634, 1002640, 1002646, 1052095, 1052101, 1052107,
1052113, 1052119, 1052125, 1052131, 1072285, 1072291, 1072297, 1072303, 1072309, 1072315,
1082180, 1082186, 1082192, 1082198, 1082204, 1082210, 1482001, 1482003, 1482005, 1482007,
1482009, 1482011, 1492000, 1492002, 1492004, 1492006, 1492008, 1492010, 1492012, 1002613,
1002619, 1002625, 1002631, 1002637, 1002643, 1052098, 1052104, 1052110, 1052116, 1052122,
1052128, 1072288, 1072294, 1072300, 1072306, 1072312, 1072318, 1072338, 1082183, 1082189,
1082195, 1082201, 1082207, 1082213, 1482000, 1482002, 1482004, 1482006, 1482008, 1482010,
1482012, 1492001, 1492003, 1492005, 1492007, 1492009, 1492011,
/*KnucklerScrolls*/ 2044800, 2044801, 2044802, 2044803, 2044804, 2044805, 2044806, 2044807, 2044808, 2044809,
/* Gun Scrolls */ 2044900, 2044901, 2044902, 2044903, 2044904,
/* Bullets */ 2330005, 2330004
};
}
@Override
public int[] getUncommonItems() {
return new int[] {
/* Pirate Equips */ 1072321, 1082216, 1482013, 1002649, 1052134, 1492013,
/* Mastery Books */ 2290097, 2290098, 2290099, 2290100, 2290101, 2290102, 2290103, 2290104, 2290105, 2290106,
2290107, 2290108, 2290110, 2290111, 2290111, 2290113, 2290114, 2290115, 2290116, 2290117,
2290118, 2290119, 2290120, 2290121, 2290122, 2290123, 2290124
};
}
@Override
public int[] getRareItems() {
return new int[] {
/* Pirate Equips */ 1082243, 1482024, 1002794, 1052164, 1072365,
1482034, 1492025
};
}
}

View File

@@ -0,0 +1,66 @@
package server.gachapon;
/**
*
* @author SharpAceX(Alan)
*/
public class NewLeafCity extends GachaponItems {
@Override
public int[] getCommonItems() {
return new int[] {
/* Warrior Equips*/ 1002338, 1002339, 1002340, 1002377, 1002378, 1002379, 1002528, 1002529, 1002530, 1002531,
1002532, 1040111, 1040112, 1040113, 1040120, 1040121, 1040122, 1041119, 1041120, 1041121,
1041122, 1041123, 1041124, 1050080, 1050081, 1050082, 1050083, 1051077, 1051078, 1051079,
1051080, 1060100, 1060101, 1060102, 1060109, 1060110, 1060111, 1061118, 1061119, 1061120,
1061121, 1061122, 1061123, 1072196, 1072197, 1072198, 1072210, 1072211, 1072212, 1072220,
1072221, 1072222, 1082114, 1082115, 1082116, 1082117, 1082128, 1082129, 1082130, 1082139,
1082140, 1082141, 1092023, 1092024, 1092025, 1092026, 1092027, 1092028, 1092036, 1092037,
1092038, 1092061, 1302018, 1302023, 1302056, 1312011, 1312015, 1312030, 1322020, 1322028,
1322029, 1322045, 1402004, 1402005, 1402015, 1402016, 1402035,
1412009, 1412010, 1412021, 1412040, 1422012, 1422013, 1422027, 1432010,
1432011, 1432030, 1432056, 1442019, 1442020, 1442044,
/* Mage Equips */ 1002271, 1002272, 1002273, 1002274, 1002363, 1002364, 1002365, 1002366, 1002398, 1002399,
1002400, 1002401, 1050072, 1050073, 1050074, 1050092, 1050093, 1050094, 1050095, 1050102,
1050103, 1050104, 1050105, 1051056, 1051057, 1051058, 1051094, 1051095, 1051096, 1051097,
1051101, 1051102, 1051103, 1051104, 1072177, 1072178, 1072179, 1072206, 1072207, 1072208,
1072209, 1072223, 1072224, 1072225, 1072226, 1082121, 1082122, 1082123, 1082131, 1082132,
1082133, 1082134, 1082151, 1082152, 1082153, 1082154, 1372009, 1372010, 1372016, 1382008,
1382010, 1382016, 1382035, 1382056, 1382060,
/* Bowman Equips */ 1002275, 1002276, 1002277, 1002275, 1002278, 1002402, 1002403, 1002404, 1002405, 1002406,
1002407, 1002408, 1050075, 1050076, 1050077, 1050078, 1050088, 1050089, 1050090, 1050091,
1050106, 1050107, 1050108, 1002275, 1051066, 1051067, 1051068, 1051069, 1051082, 1051083,
1051084, 1051085, 1051105, 1051106, 1051107, 1072182, 1072183, 1072184, 1072185, 1072203,
1072204, 1072205, 1072227, 1072228, 1072229, 1082109, 1082110, 1082111, 1082112, 1082125,
1082126, 1082127, 1082158, 1082159, 1082160, 1452012, 1452013, 1452014, 1452015, 1452017,
1452019, 1452020, 1452021, 1452025, 1452026, 1452060, 1462010, 1452017, 1462011, 1462012,
1462013, 1462015, 1462016, 1462017, 1462018, 1462021, 1462022, 1462049,
/* Thief Equips */ 1002323, 1002324, 1002325, 1002326, 1002327, 1002328, 1002329, 1002330, 1002380, 1002381,
1002382, 1002383, 1040108, 1040109, 1040110, 1040115, 1040117, 1040118, 1041105, 1041106,
1041107, 1041115, 1041116, 1041117, 1041118, 1050096, 1050097, 1050098, 1050099, 1051090,
1051091, 1051092, 1051093, 1060097, 1060098, 1060099, 1060104, 1060105, 1060106, 1060107,
1061104, 1061105, 1061106, 1061114, 1061115, 1061116, 1061117, 1072172, 1072173, 1072174,
1072192, 1072193, 1072194, 1072195, 1072213, 1072214, 1072215, 1072216, 1082118, 1082119,
1082120, 1082135, 1082136, 1082137, 1082138, 1082143, 1082144, 1092050, 1332023, 1332027,
1332052, 1332069, 1332072, 1472031, 1472033, 1472053,
/* Pirate Equips */ 1002640, 1002643, 1002646, 1052125, 1052128, 1052131, 1072312, 1072315, 1072318, 1082207,
1082210, 1082213, 1482010, 1482011, 1002640, 1482012, 1492010, 1492011, 1492012
};
}
@Override
public int[] getUncommonItems() {
return new int[] {
2022179
};
}
@Override
public int[] getRareItems() {
return new int[] {
2049100
};
}
}

View File

@@ -0,0 +1,137 @@
package server.gachapon;
/**
*
* @author SharpAceX(Alan)
*/
public class Perion extends GachaponItems {
@Override
public int[] getCommonItems() {
return new int [] {
//warriorEquips = {
1002002, 1002003, 1002004, 1002005, 1002007,
1002009, 1002011, 1002021, 1002022, 1002023,
1002024, 1002025, 1002027, 1002028, 1002029,
1002030, 1002039, 1002040, 1002043, 1002044,
1002045, 1002046, 1002047, 1002048, 1002049,
1002050, 1002051, 1002052, 1002055, 1002056,
1002058, 1002059, 1002084, 1002085, 1002086,
1002087, 1002088, 1002091, 1002092, 1002093,
1002094, 1002095, 1002098, 1002099, 1002100,
1002101, 1002338, 1002339, 1002340, 1002377,
1002378, 1002379, 1002528, 1002529, 1002530,
1002531, 1002532, 1002551, 1002578,
1002790, 1040000, 1040009, 1040012, 1040015,
1040016, 1040021, 1040026, 1040028, 1040029,
1040030, 1040037, 1040038, 1040039, 1040040,
1040041, 1040085, 1040086, 1040087, 1040088,
1040089, 1040090, 1040091, 1040092, 1040093,
1040102, 1040103, 1040104, 1040111, 1040112,
1040113, 1040120, 1040121, 1040122, 1041014,
1041019, 1041020, 1041021, 1041022, 1041023,
1041024, 1041064, 1041084, 1041085, 1041086,
1041087, 1041088, 1041089, 1041091, 1041092,
1041093, 1041097, 1041098, 1041099, 1041119,
1041120, 1041121, 1041122, 1041123, 1041124,
1050000, 1050005, 1050006, 1050007, 1050011,
1050021, 1050022, 1050080, 1050081, 1050082,
1050083, 1051000, 1051001, 1051010, 1051011,
1051012, 1051013, 1051014, 1051015, 1051016,
1051077, 1051078, 1051079, 1051080, 1052075,
1052160, 1060000, 1060008, 1060009,
1060010, 1060011, 1060016, 1060017, 1060018,
1060019, 1060020, 1060027, 1060028, 1060029,
1060030, 1060060, 1060074, 1060075, 1060076,
1060077, 1060078, 1060079, 1060080, 1060081,
1060082, 1060090, 1060091, 1060092, 1060100,
1060101, 1060102, 1060109, 1060110, 1060111,
1061014, 1061015, 1061016, 1061017, 1061018,
1061019, 1061020, 1061023, 1061083, 1061084,
1061085, 1061086, 1061087, 1061088, 1061090,
1061091, 1061092, 1061096, 1061097, 1061098,
1061118, 1061119, 1061120, 1061121, 1061122,
1061123, 1072000, 1072002, 1072003, 1072007,
1072009, 1072011, 1072039, 1072040, 1072041,
1072046, 1072047, 1072050, 1072051, 1072052,
1072053, 1072112, 1072113, 1072126, 1072127,
1072132, 1072133, 1072134, 1072135, 1072147,
1072148, 1072149, 1072154, 1072155, 1072156,
1072168, 1072196, 1072197, 1072198, 1072210,
1072211, 1072212, 1072220, 1072221, 1072222,
1072273, 1082000, 1082001,
1082003, 1082004, 1082005, 1082006, 1082007,
1082008, 1082009, 1082010, 1082011, 1082023,
1082024, 1082025, 1082035, 1082036, 1082059,
1082060, 1082061, 1082103, 1082104, 1082105,
1082114, 1082115, 1082116, 1082117, 1082128,
1082129, 1082130, 1082139, 1082140, 1082141,
1082168, 1082218, 1082239, 1092000,
1092001, 1092002, 1092004, 1092005, 1092006,
1092007, 1092009, 1092010, 1092011, 1092012,
1092013, 1092014, 1092015, 1092016, 1092017,
1092023, 1092024, 1092025, 1092026, 1092027,
1092028, 1092036, 1092037, 1092038,
1092060, 1092061, 1302002, 1302004, 1302005,
1302008, 1302009, 1302010, 1302011, 1302012,
1302015, 1302018, 1302019, 1302023, 1302037,
1302056, 1302059, 1302068, 1302079,
1312001, 1312003, 1312005,
1312006, 1312007, 1312008, 1312009, 1312010,
1312011, 1312015, 1312016, 1312030, 1312031,
1322014, 1322015,
1322016, 1322017, 1322018, 1322019, 1322020,
1322028, 1322029, 1322045, 1322052, 1322059,
1322062, 1402000,
1402002, 1402003, 1402004, 1402005, 1402006,
1402007, 1402008, 1402011, 1402012, 1402015,
1402016, 1402017, 1402018, 1402035, 1402036,
1412000, 1412002,
1412003, 1412004, 1412005, 1412006, 1412007,
1412008, 1412009, 1412010, 1412012, 1412021,
1412026, 1412032, 1412040,
1422001, 1422002, 1422003, 1422005,
1422007, 1422008, 1422009, 1422010, 1422012,
1422013, 1422027, 1422028, 1422030, 1422031,
1422038, 1422044, 1432002, 1432003,
1432004, 1432005, 1432006, 1432007, 1432010,
1432011, 1432030, 1432038, 1432045,
1432048, 1432056, 1442001, 1442002,
1442003, 1442005, 1442006, 1442007, 1442008,
1442009, 1442010, 1442019, 1442020, 1442044,
1442045, 1442060, 1442067,
//magicianEquips = {
1002075, 1050035, 1002151, 1051023, 1072089,
1072115, 1072076, 1040018, 1382017, 1072072,
//bowmanEquips = {
1040011, 1041061, 1040076, 1040003, 1072059,
1082017, 1002114, 1041066, 1060057, 1040007,
//thiefEquips = {
1072032, 1472011, 1082037, 1040059, 1040084,
1040043, 1072085, 1040031, 1332031, 1082075,
//pirateEquips = {
1482001, 1492002, 1052113, 1002616, 1072294,
1492004, 1482006, 1082192, 1082189, 1082195,
};
}
@Override
public int[] getUncommonItems() {
//All Scrolls
return new int [] {
2043000, 2043001, 2043002, 2043004, 2043005, 2043006, 2043007, 2043008, 2043009, 2043010,
2043015, 2043017, 2043019, 2044000, 2044001, 2044002, 2044004, 2044005, 2044010, 2044012,
2044014, 2043200, 2043201, 2043202, 2043204, 2043205, 2043210, 2043212, 2043214, 2044200,
2044201, 2044202, 2044204, 2044205, 2044210, 2044212, 2044214, 2044300, 2044301, 2044302,
2044304, 2044305, 2044310, 2044312, 2044314, 2044400, 2044401, 2044402, 2044404, 2044405,
2044410, 2044412, 2044414,
};
}
@Override
public int[] getRareItems() {
return new int [] {1402037, 1402049, 1072361, 1402048, 1402049, 1402050, 1402051};
}
}

View File

@@ -0,0 +1,25 @@
package server.gachapon;
/**
*
* @author SharpAceX(Alan)
*/
public class ShowaSpaFemale extends GachaponItems {
@Override
public int[] getCommonItems() {
return new int [] {};
}
@Override
public int[] getUncommonItems() {
return new int [] {};
}
@Override
public int[] getRareItems() {
return new int [] {1022082, 1022060};
}
}

View File

@@ -0,0 +1,25 @@
package server.gachapon;
/**
*
* @author SharpAceX(Alan)
*/
public class ShowaSpaMale extends GachaponItems {
@Override
public int[] getCommonItems() {
return new int [] {};
}
@Override
public int[] getUncommonItems() {
return new int [] {};
}
@Override
public int[] getRareItems() {
return new int [] {1022082, 1022060};
}
}

View File

@@ -0,0 +1,106 @@
package server.gachapon;
/**
*
* @author SharpAceX(Alan)
*/
public class Sleepywood extends GachaponItems {
@Override
public int[] getCommonItems() {
return new int [] {
//warriorEquips = {
1002022, 1002024, 1002028, 1002029, 1002030,
1002045, 1002046, 1002084, 1002085, 1002086,
1002091, 1002094, 1002095, 1002100, 1002101,
1040087, 1040088, 1040089, 1040090, 1040091,
1040092, 1040093, 1040102, 1040103, 1040104,
1041087, 1041088, 1041089, 1041091, 1041092,
1041093, 1041097, 1041098, 1041099, 1060076,
1060077, 1060078, 1060079, 1060080, 1060081,
1060082, 1060090, 1060091, 1060092, 1061086,
1061087, 1061088, 1061090, 1061091, 1061092,
1061096, 1061097, 1061098, 1072132, 1072133,
1072134, 1072135, 1072147, 1072148, 1072149,
1072154, 1072155, 1072156, 1082009, 1082010,
1082011, 1082059, 1082060, 1082061, 1082103,
1082104, 1082105, 1082218, 1092004, 1092009,
1092010, 1092011, 1092015, 1092016, 1092017,
1302010, 1302011, 1302012, 1302015, 1302019,
1302037, 1302079, 1312008, 1312009,
1312010, 1322017, 1322018, 1322019, 1322059,
1402003, 1402011, 1402012, 1402017, 1412003,
1412007, 1412008, 1412032, 1422005, 1422009,
1422010, 1432004, 1432006, 1432007, 1432045,
1442005, 1442008, 1442010, 1442060,
//magicianEquips = {
1002215, 1002216, 1002217, 1002218, 1002242,
1002243, 1002244, 1002245, 1002246, 1002252,
1002253, 1002254, 1050045, 1050046, 1050047,
1050048, 1050049, 1050053, 1050054, 1050055,
1050056, 1050067, 1050068, 1050069, 1050070,
1051030, 1051031, 1051032, 1051033, 1051034,
1051044, 1051045, 1051046, 1051047, 1051052,
1051053, 1051054, 1051055, 1072136, 1072137,
1072138, 1072139, 1072140, 1072141, 1072142,
1072143, 1072157, 1072158, 1072159, 1072160,
1082080, 1082081, 1082082, 1082086, 1082087,
1082088, 1082098, 1082099, 1082100, 1372007,
1372008, 1372011, 1372014, 1372015, 1372035,
1372036, 1372037, 1372038, 1382001, 1382006,
1382007, 1382011, 1382014, 1382041,
//bowmanEquips = {
1002211, 1002212, 1002213, 1002214, 1002267,
1002268, 1002269, 1002270, 1002286, 1002287,
1002288, 1002289, 1002749, 1050051, 1050052,
1050058, 1050059, 1050060, 1050061, 1050062,
1050063, 1050064, 1051037, 1051038, 1051039,
1051041, 1051042, 1051043, 1051062, 1051063,
1051064, 1051065, 1072122, 1072123, 1072124,
1072125, 1072144, 1072145, 1072146, 1072164,
1072165, 1072166, 1072167, 1072345, 1082083,
1082084, 1082085, 1082089, 1082090, 1082091,
1082106, 1082107, 1082108, 1452004, 1452008,
1452009, 1452010, 1452011, 1452018, 1452023,
1452052, 1462006, 1462007, 1462008, 1462009,
1462046,
//thiefEquips = {
1002207, 1002208, 1002209, 1002210, 1002247,
1002248, 1002249, 1002281, 1002282, 1002283,
1002284, 1002285, 1002656, 1002750, 1040094,
1040095, 1040096, 1040097, 1040098, 1040099,
1040100, 1040105, 1040106, 1040107, 1041077,
1041078, 1041079, 1041080, 1041094, 1041095,
1041096, 1041100, 1041101, 1041102, 1041103,
1060083, 1060084, 1060085, 1060086, 1060087,
1060088, 1060089, 1060093, 1060094, 1060095,
1061076, 1061077, 1061078, 1061079, 1061093,
1061094, 1061095, 1061099, 1061100, 1061101,
1061102, 1072128, 1072129, 1072130, 1072131,
1072150, 1072151, 1072152, 1072161, 1072162,
1072163, 1072346, 1082065, 1082066, 1082067,
1082092, 1082093, 1082094, 1082095, 1082096,
1082097, 1332003, 1332015, 1332018, 1332024,
1332054, 1332064, 1472018, 1472019, 1472020,
1472021, 1472022, 1472023, 1472024, 1472025,
1472026, 1472027, 1472028, 1472029, 1472054,
1472062,
//pirateEquips = {
1002631, 1002634, 1002637, 1052116, 1052119,
1052122, 1072303, 1072306, 1072309, 1082198,
1082201, 1082204, 1482007, 1482008, 1482009,
};
}
@Override
public int[] getUncommonItems() {
return new int [] {};
}
@Override
public int[] getRareItems() {
return new int [] {1302068, 2070007, 1022082, 1022058};
}
}

View File

@@ -0,0 +1,106 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package server.life;
import server.maps.AbstractAnimatedMapleMapObject;
public abstract class AbstractLoadedMapleLife extends AbstractAnimatedMapleMapObject {
private final int id;
private int f;
private boolean hide;
private int fh;
private int start_fh;
private int cy;
private int rx0;
private int rx1;
public AbstractLoadedMapleLife(int id) {
this.id = id;
}
public AbstractLoadedMapleLife(AbstractLoadedMapleLife life) {
this(life.getId());
this.f = life.f;
this.hide = life.hide;
this.fh = life.fh;
this.start_fh = life.fh;
this.cy = life.cy;
this.rx0 = life.rx0;
this.rx1 = life.rx1;
}
public int getF() {
return f;
}
public void setF(int f) {
this.f = f;
}
public boolean isHidden() {
return hide;
}
public void setHide(boolean hide) {
this.hide = hide;
}
public int getFh() {
return fh;
}
public void setFh(int fh) {
this.fh = fh;
}
public int getStartFh() {
return start_fh;
}
public int getCy() {
return cy;
}
public void setCy(int cy) {
this.cy = cy;
}
public int getRx0() {
return rx0;
}
public void setRx0(int rx0) {
this.rx0 = rx0;
}
public int getRx1() {
return rx1;
}
public void setRx1(int rx1) {
this.rx1 = rx1;
}
public int getId() {
return id;
}
}

View File

@@ -0,0 +1,46 @@
/*
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 server.life;
public enum Element {
NEUTRAL, FIRE, ICE, LIGHTING, POISON, HOLY, DARK;
public static Element getFromChar(char c) {
switch (Character.toUpperCase(c)) {
case 'F':
return FIRE;
case 'I':
return ICE;
case 'L':
return LIGHTING;
case 'S':
return POISON;
case 'H':
return HOLY;
case 'D':
return DARK;
case 'P':
return NEUTRAL;
}
throw new IllegalArgumentException("unknown elemnt char " + c);
}
}

View File

@@ -0,0 +1,41 @@
/*
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 server.life;
public enum ElementalEffectiveness {
NORMAL, IMMUNE, STRONG, WEAK, NEUTRAL;
public static ElementalEffectiveness getByNumber(int num) {
switch (num) {
case 1:
return IMMUNE;
case 2:
return STRONG;
case 3:
return WEAK;
case 4:
return NEUTRAL;
default:
throw new IllegalArgumentException("Unkown effectiveness: " + num);
}
}
}

View File

@@ -0,0 +1,236 @@
/*
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 server.life;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import provider.MapleData;
import provider.MapleDataProvider;
import provider.MapleDataProviderFactory;
import provider.MapleDataTool;
import provider.wz.MapleDataType;
import tools.Pair;
import tools.StringUtil;
public class MapleLifeFactory {
private static MapleDataProvider data = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Mob.wz"));
private final static MapleDataProvider stringDataWZ = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/String.wz"));
private static MapleData mobStringData = stringDataWZ.getData("Mob.img");
private static MapleData npcStringData = stringDataWZ.getData("Npc.img");
private static Map<Integer, MapleMonsterStats> monsterStats = new HashMap<>();
public static AbstractLoadedMapleLife getLife(int id, String type) {
if (type.equalsIgnoreCase("n")) {
return getNPC(id);
} else if (type.equalsIgnoreCase("m")) {
return getMonster(id);
} else {
System.out.println("Unknown Life type: " + type);
return null;
}
}
public static MapleMonster getMonster(int mid) {
MapleMonsterStats stats = monsterStats.get(Integer.valueOf(mid));
if (stats == null) {
MapleData monsterData = data.getData(StringUtil.getLeftPaddedStr(Integer.toString(mid) + ".img", '0', 11));
if (monsterData == null) {
return null;
}
MapleData monsterInfoData = monsterData.getChildByPath("info");
stats = new MapleMonsterStats();
stats.setHp(MapleDataTool.getIntConvert("maxHP", monsterInfoData));
stats.setFriendly(MapleDataTool.getIntConvert("damagedByMob", monsterInfoData, 0) == 1);
stats.setPADamage(MapleDataTool.getIntConvert("PADamage", monsterInfoData));
stats.setPDDamage(MapleDataTool.getIntConvert("PDDamage", monsterInfoData));
stats.setMADamage(MapleDataTool.getIntConvert("MADamage", monsterInfoData));
stats.setMDDamage(MapleDataTool.getIntConvert("MDDamage", monsterInfoData));
stats.setMp(MapleDataTool.getIntConvert("maxMP", monsterInfoData, 0));
stats.setExp(MapleDataTool.getIntConvert("exp", monsterInfoData, 0));
stats.setLevel(MapleDataTool.getIntConvert("level", monsterInfoData));
stats.setRemoveAfter(MapleDataTool.getIntConvert("removeAfter", monsterInfoData, 0));
stats.setBoss(MapleDataTool.getIntConvert("boss", monsterInfoData, 0) > 0);
stats.setExplosiveReward(MapleDataTool.getIntConvert("explosiveReward", monsterInfoData, 0) > 0);
stats.setFfaLoot(MapleDataTool.getIntConvert("publicReward", monsterInfoData, 0) > 0);
stats.setUndead(MapleDataTool.getIntConvert("undead", monsterInfoData, 0) > 0);
stats.setName(MapleDataTool.getString(mid + "/name", mobStringData, "MISSINGNO"));
stats.setBuffToGive(MapleDataTool.getIntConvert("buff", monsterInfoData, -1));
stats.setCP(MapleDataTool.getIntConvert("getCP", monsterInfoData, 0));
stats.setRemoveOnMiss(MapleDataTool.getIntConvert("removeOnMiss", monsterInfoData, 0) > 0);
MapleData special = monsterInfoData.getChildByPath("coolDamage");
if (special != null) {
int coolDmg = MapleDataTool.getIntConvert("coolDamage", monsterInfoData);
int coolProb = MapleDataTool.getIntConvert("coolDamageProb", monsterInfoData, 0);
stats.setCool(new Pair<>(coolDmg, coolProb));
}
special = monsterInfoData.getChildByPath("loseItem");
if (special != null) {
for (MapleData liData : special.getChildren()) {
stats.addLoseItem(new loseItem(MapleDataTool.getInt(liData.getChildByPath("id")), (byte) MapleDataTool.getInt(liData.getChildByPath("prop")), (byte) MapleDataTool.getInt(liData.getChildByPath("x"))));
}
}
special = monsterInfoData.getChildByPath("selfDestruction");
if (special != null) {
stats.setSelfDestruction(new selfDestruction((byte) MapleDataTool.getInt(special.getChildByPath("action")), MapleDataTool.getIntConvert("removeAfter", special, -1), MapleDataTool.getIntConvert("hp", special, -1)));
}
MapleData firstAttackData = monsterInfoData.getChildByPath("firstAttack");
int firstAttack = 0;
if (firstAttackData != null) {
if (firstAttackData.getType() == MapleDataType.FLOAT) {
firstAttack = Math.round(MapleDataTool.getFloat(firstAttackData));
} else {
firstAttack = MapleDataTool.getInt(firstAttackData);
}
}
stats.setFirstAttack(firstAttack > 0);
stats.setDropPeriod(MapleDataTool.getIntConvert("dropItemPeriod", monsterInfoData, 0) * 10000);
stats.setTagColor(MapleDataTool.getIntConvert("hpTagColor", monsterInfoData, 0));
stats.setTagBgColor(MapleDataTool.getIntConvert("hpTagBgcolor", monsterInfoData, 0));
for (MapleData idata : monsterData) {
if (!idata.getName().equals("info")) {
int delay = 0;
for (MapleData pic : idata.getChildren()) {
delay += MapleDataTool.getIntConvert("delay", pic, 0);
}
stats.setAnimationTime(idata.getName(), delay);
}
}
MapleData reviveInfo = monsterInfoData.getChildByPath("revive");
if (reviveInfo != null) {
List<Integer> revives = new LinkedList<>();
for (MapleData data_ : reviveInfo) {
revives.add(MapleDataTool.getInt(data_));
}
stats.setRevives(revives);
}
decodeElementalString(stats, MapleDataTool.getString("elemAttr", monsterInfoData, ""));
MapleData monsterSkillData = monsterInfoData.getChildByPath("skill");
if (monsterSkillData != null) {
int i = 0;
List<Pair<Integer, Integer>> skills = new ArrayList<>();
while (monsterSkillData.getChildByPath(Integer.toString(i)) != null) {
skills.add(new Pair<>(Integer.valueOf(MapleDataTool.getInt(i + "/skill", monsterSkillData, 0)), Integer.valueOf(MapleDataTool.getInt(i + "/level", monsterSkillData, 0))));
i++;
}
stats.setSkills(skills);
}
MapleData banishData = monsterInfoData.getChildByPath("ban");
if (banishData != null) {
stats.setBanishInfo(new BanishInfo(MapleDataTool.getString("banMsg", banishData), MapleDataTool.getInt("banMap/0/field", banishData, -1), MapleDataTool.getString("banMap/0/portal", banishData, "sp")));
}
monsterStats.put(Integer.valueOf(mid), stats);
}
MapleMonster ret = new MapleMonster(mid, stats);
return ret;
}
private static void decodeElementalString(MapleMonsterStats stats, String elemAttr) {
for (int i = 0; i < elemAttr.length(); i += 2) {
stats.setEffectiveness(Element.getFromChar(elemAttr.charAt(i)), ElementalEffectiveness.getByNumber(Integer.valueOf(String.valueOf(elemAttr.charAt(i + 1)))));
}
}
public static MapleNPC getNPC(int nid) {
return new MapleNPC(nid, new MapleNPCStats(MapleDataTool.getString(nid + "/name", npcStringData, "MISSINGNO")));
}
public static class BanishInfo {
private int map;
private String portal, msg;
public BanishInfo(String msg, int map, String portal) {
this.msg = msg;
this.map = map;
this.portal = portal;
}
public int getMap() {
return map;
}
public String getPortal() {
return portal;
}
public String getMsg() {
return msg;
}
}
public static class loseItem {
private int id;
private byte chance, x;
private loseItem(int id, byte chance, byte x) {
this.id = id;
this.chance = chance;
this.x = x;
}
public int getId() {
return id;
}
public byte getChance() {
return chance;
}
public byte getX() {
return x;
}
}
public static class selfDestruction {
private byte action;
private int removeAfter;
private int hp;
private selfDestruction(byte action, int removeAfter, int hp) {
this.action = action;
this.removeAfter = removeAfter;
this.hp = hp;
}
public int getHp() {
return hp;
}
public byte getAction() {
return action;
}
public int removeAfter() {
return removeAfter;
}
}
}

View File

@@ -0,0 +1,954 @@
/*
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 server.life;
import client.MapleBuffStat;
import client.MapleCharacter;
import client.MapleClient;
import client.MapleJob;
import client.Skill;
import client.SkillFactory;
import client.status.MonsterStatus;
import client.status.MonsterStatusEffect;
import constants.ServerConstants;
import constants.skills.FPMage;
import constants.skills.Hermit;
import constants.skills.ILMage;
import constants.skills.NightLord;
import constants.skills.NightWalker;
import constants.skills.Shadower;
import constants.skills.SuperGM;
import java.awt.Point;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
import net.server.world.MapleParty;
import net.server.world.MaplePartyCharacter;
import scripting.event.EventInstanceManager;
import server.TimerManager;
import server.life.MapleLifeFactory.BanishInfo;
import server.maps.MapleMap;
import server.maps.MapleMapObject;
import server.maps.MapleMapObjectType;
import tools.MaplePacketCreator;
import tools.Pair;
import tools.Randomizer;
public class MapleMonster extends AbstractLoadedMapleLife {
private MapleMonsterStats stats;
private int hp, mp;
private WeakReference<MapleCharacter> controller = new WeakReference<>(null);
private boolean controllerHasAggro, controllerKnowsAboutAggro;
private EventInstanceManager eventInstance = null;
private Collection<MonsterListener> listeners = new LinkedList<>();
private EnumMap<MonsterStatus, MonsterStatusEffect> stati = new EnumMap<>(MonsterStatus.class);
private ArrayList<MonsterStatus> alreadyBuffed = new ArrayList<MonsterStatus>();
private MapleMap map;
private int VenomMultiplier = 0;
private boolean fake = false;
private boolean dropsDisabled = false;
private List<Pair<Integer, Integer>> usedSkills = new ArrayList<>();
private Map<Pair<Integer, Integer>, Integer> skillsUsed = new HashMap<>();
private List<Integer> stolenItems = new ArrayList<>();
private int team;
private final HashMap<Integer, AtomicInteger> takenDamage = new HashMap<>();
public ReentrantLock monsterLock = new ReentrantLock();
public MapleMonster(int id, MapleMonsterStats stats) {
super(id);
initWithStats(stats);
}
public MapleMonster(MapleMonster monster) {
super(monster);
initWithStats(monster.stats);
}
private void initWithStats(MapleMonsterStats stats) {
setStance(5);
this.stats = stats;
hp = stats.getHp();
mp = stats.getMp();
}
public void disableDrops() {
this.dropsDisabled = true;
}
public boolean dropsDisabled() {
return dropsDisabled;
}
public void setMap(MapleMap map) {
this.map = map;
}
public int getHp() {
return hp;
}
public void setHp(int hp) {
this.hp = hp;
}
public int getMaxHp() {
return stats.getHp();
}
public int getMp() {
return mp;
}
public void setMp(int mp) {
if (mp < 0) {
mp = 0;
}
this.mp = mp;
}
public int getMaxMp() {
return stats.getMp();
}
public int getExp() {
return stats.getExp();
}
int getLevel() {
return stats.getLevel();
}
public int getCP() {
return stats.getCP();
}
public int getTeam() {
return team;
}
public void setTeam(int team) {
this.team = team;
}
public int getVenomMulti() {
return this.VenomMultiplier;
}
public void setVenomMulti(int multiplier) {
this.VenomMultiplier = multiplier;
}
public MapleMonsterStats getStats() {
return stats;
}
public boolean isBoss() {
return stats.isBoss() || isHT();
}
public int getAnimationTime(String name) {
return stats.getAnimationTime(name);
}
private List<Integer> getRevives() {
return stats.getRevives();
}
private byte getTagColor() {
return stats.getTagColor();
}
private byte getTagBgColor() {
return stats.getTagBgColor();
}
/**
*
* @param from the player that dealt the damage
* @param damage
*/
public synchronized void damage(MapleCharacter from, int damage) { // may be pointless synchronization
if (!isAlive()) {
return;
}
int trueDamage = Math.min(hp, damage); // since magic happens otherwise B^)
if(ServerConstants.USE_DEBUG == true && from != null) from.dropMessage(5, "Hitted MOB " + this.getId());
hp -= damage;
if (takenDamage.containsKey(from.getId())) {
takenDamage.get(from.getId()).addAndGet(trueDamage);
} else {
takenDamage.put(from.getId(), new AtomicInteger(trueDamage));
}
if (hasBossHPBar()) {
from.getMap().broadcastMessage(makeBossHPBarPacket(), getPosition());
} else if (!isBoss()) {
int remainingHP = (int) Math.max(1, hp * 100f / getMaxHp());
byte[] packet = MaplePacketCreator.showMonsterHP(getObjectId(), remainingHP);
if (from.getParty() != null) {
for (MaplePartyCharacter mpc : from.getParty().getMembers()) {
MapleCharacter member = from.getMap().getCharacterById(mpc.getId()); // god bless
if (member != null) {
member.announce(packet.clone()); // clone it just in case of crypto
}
}
} else {
from.announce(packet);
}
}
}
public void heal(int hp, int mp) {
int hp2Heal = getHp() + hp;
int mp2Heal = getMp() + mp;
if (hp2Heal >= getMaxHp()) {
hp2Heal = getMaxHp();
}
if (mp2Heal >= getMaxMp()) {
mp2Heal = getMaxMp();
}
setHp(hp2Heal);
setMp(mp2Heal);
getMap().broadcastMessage(MaplePacketCreator.healMonster(getObjectId(), hp));
}
public boolean isAttackedBy(MapleCharacter chr) {
return takenDamage.containsKey(chr.getId());
}
private void distributeExperienceToParty(int pid, int exp, int killer, Map<Integer, Integer> expDist) {
LinkedList<MapleCharacter> members = new LinkedList<>();
map.getCharacterReadLock().lock();
Collection<MapleCharacter> chrs = map.getCharacters();
try {
for (MapleCharacter mc : chrs) {
if (mc.getPartyId() == pid) {
members.add(mc);
}
}
} finally {
map.getCharacterReadLock().unlock();
}
final int minLevel = getLevel() - 5;
int partyLevel = 0;
int leechMinLevel = 0;
for (MapleCharacter mc : members) {
if (mc.getLevel() >= minLevel) {
leechMinLevel = Math.min(mc.getLevel() - 5, minLevel);
}
}
int leechCount = 0;
for (MapleCharacter mc : members) {
if (mc.getLevel() >= leechMinLevel) {
partyLevel += mc.getLevel();
leechCount++;
}
}
final int mostDamageCid = getHighestDamagerId();
for (MapleCharacter mc : members) {
int id = mc.getId();
int level = mc.getLevel();
if (expDist.containsKey(id)
|| level >= leechMinLevel) {
boolean isKiller = killer == id;
boolean mostDamage = mostDamageCid == id;
int xp = (int) (exp * 0.80f * level / partyLevel);
if (mostDamage) {
xp += (exp * 0.20f);
}
giveExpToCharacter(mc, xp, isKiller, leechCount);
}
}
}
public void distributeExperience(int killerId) {
if (isAlive()) {
return;
}
int exp = getExp();
int totalHealth = getMaxHp();
Map<Integer, Integer> expDist = new HashMap<>();
Map<Integer, Integer> partyExp = new HashMap<>();
// 80% of pool is split amongst all the damagers
for (Entry<Integer, AtomicInteger> damage : takenDamage.entrySet()) {
expDist.put(damage.getKey(), (int) (0.80f * exp * damage.getValue().get() / totalHealth));
}
map.getCharacterReadLock().lock(); // avoid concurrent mod
Collection<MapleCharacter> chrs = map.getCharacters();
try {
for (MapleCharacter mc : chrs) {
if (expDist.containsKey(mc.getId())) {
boolean isKiller = mc.getId() == killerId;
int xp = expDist.get(mc.getId());
if (isKiller) {
xp += exp / 5;
}
MapleParty p = mc.getParty();
if (p != null) {
int pID = p.getId();
int pXP = xp + (partyExp.containsKey(pID) ? partyExp.get(pID) : 0);
partyExp.put(pID, pXP);
} else {
giveExpToCharacter(mc, xp, isKiller, 1);
}
}
}
} finally {
map.getCharacterReadLock().unlock();
}
for (Entry<Integer, Integer> party : partyExp.entrySet()) {
distributeExperienceToParty(party.getKey(), party.getValue(), killerId, expDist);
}
}
public void giveExpToCharacter(MapleCharacter attacker, int exp, boolean isKiller, int numExpSharers) {
if (isKiller) {
if (eventInstance != null) {
eventInstance.monsterKilled(attacker, this);
}
}
final int partyModifier = numExpSharers > 1 ? (110 + (5 * (numExpSharers - 2))) : 0;
int partyExp = 0;
if (attacker.getHp() > 0) {
int personalExp = exp * attacker.getExpRate();
if (exp > 0) {
if (partyModifier > 0) {
partyExp = (int) (personalExp * ServerConstants.PARTY_EXPERIENCE_MOD * partyModifier / 1000f);
}
Integer holySymbol = attacker.getBuffedValue(MapleBuffStat.HOLY_SYMBOL);
boolean GMHolySymbol = attacker.getBuffSource(MapleBuffStat.HOLY_SYMBOL) == SuperGM.HOLY_SYMBOL;
if (holySymbol != null) {
if (numExpSharers == 1 && !GMHolySymbol) {
personalExp *= 1.0 + (holySymbol.doubleValue() / 500.0);
} else {
personalExp *= 1.0 + (holySymbol.doubleValue() / 100.0);
}
}
if (stati.containsKey(MonsterStatus.SHOWDOWN)) {
personalExp *= (stati.get(MonsterStatus.SHOWDOWN).getStati().get(MonsterStatus.SHOWDOWN).doubleValue() / 100.0 + 1.0);
}
}
if (exp < 0) {//O.O ><
personalExp = Integer.MAX_VALUE;
}
attacker.gainExp(personalExp, partyExp, true, false, isKiller);
attacker.mobKilled(getId());
attacker.increaseEquipExp(personalExp);//better place
}
}
public MapleCharacter killBy(MapleCharacter killer) {
distributeExperience(killer != null ? killer.getId() : 0);
if (getController() != null) { // this can/should only happen when a hidden gm attacks the monster
getController().getClient().announce(MaplePacketCreator.stopControllingMonster(this.getObjectId()));
getController().stopControllingMonster(this);
}
final List<Integer> toSpawn = this.getRevives(); // this doesn't work (?)
if (toSpawn != null) {
final MapleMap reviveMap = killer.getMap();
if (toSpawn.contains(9300216) && reviveMap.getId() > 925000000 && reviveMap.getId() < 926000000) {
reviveMap.broadcastMessage(MaplePacketCreator.playSound("Dojang/clear"));
reviveMap.broadcastMessage(MaplePacketCreator.showEffect("dojang/end/clear"));
}
Pair<Integer, String> timeMob = reviveMap.getTimeMob();
if (timeMob != null) {
if (toSpawn.contains(timeMob.getLeft())) {
reviveMap.broadcastMessage(MaplePacketCreator.serverNotice(6, timeMob.getRight()));
}
if (timeMob.getLeft() == 9300338 && (reviveMap.getId() >= 922240100 && reviveMap.getId() <= 922240119)) {
if (!reviveMap.containsNPC(9001108)) {
MapleNPC npc = MapleLifeFactory.getNPC(9001108);
npc.setPosition(new Point(172, 9));
npc.setCy(9);
npc.setRx0(172 + 50);
npc.setRx1(172 - 50);
npc.setFh(27);
reviveMap.addMapObject(npc);
reviveMap.broadcastMessage(MaplePacketCreator.spawnNPC(npc));
} else {
reviveMap.toggleHiddenNPC(9001108);
}
}
}
TimerManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
for (Integer mid : toSpawn) {
final MapleMonster mob = MapleLifeFactory.getMonster(mid);
mob.setPosition(getPosition());
if (dropsDisabled()) {
mob.disableDrops();
}
reviveMap.spawnMonster(mob);
}
}
}, getAnimationTime("die1"));
}
if (eventInstance != null) {
if (!this.getStats().isFriendly()) {
eventInstance.monsterKilled(this);
}
}
// idk V just a troll
for (MonsterListener listener : listeners.toArray(new MonsterListener[listeners.size()])) {
listener.monsterKilled(getAnimationTime("die1"));
}
MapleCharacter looter = map.getCharacterById(getHighestDamagerId());
return looter != null ? looter : killer;
}
// should only really be used to determine drop owner
private int getHighestDamagerId() {
int curId = 0;
int curDmg = 0;
for (Entry<Integer, AtomicInteger> damage : takenDamage.entrySet()) {
curId = damage.getValue().get() >= curDmg ? damage.getKey() : curId;
curDmg = damage.getKey() == curId ? damage.getValue().get() : curDmg;
}
return curId;
}
public boolean isAlive() {
return this.hp > 0;
}
public MapleCharacter getController() {
return controller.get();
}
public void setController(MapleCharacter controller) {
this.controller = new WeakReference<>(controller);
}
public void switchController(MapleCharacter newController, boolean immediateAggro) {
MapleCharacter controllers = getController();
if (controllers == newController) {
return;
}
if (controllers != null) {
controllers.stopControllingMonster(this);
controllers.getClient().announce(MaplePacketCreator.stopControllingMonster(getObjectId()));
}
newController.controlMonster(this, immediateAggro);
setController(newController);
if (immediateAggro) {
setControllerHasAggro(true);
}
setControllerKnowsAboutAggro(false);
}
public void addListener(MonsterListener listener) {
listeners.add(listener);
}
public boolean isControllerHasAggro() {
return fake ? false : controllerHasAggro;
}
public void setControllerHasAggro(boolean controllerHasAggro) {
if (fake) {
return;
}
this.controllerHasAggro = controllerHasAggro;
}
public boolean isControllerKnowsAboutAggro() {
return fake ? false : controllerKnowsAboutAggro;
}
public void setControllerKnowsAboutAggro(boolean controllerKnowsAboutAggro) {
if (fake) {
return;
}
this.controllerKnowsAboutAggro = controllerKnowsAboutAggro;
}
public byte[] makeBossHPBarPacket() {
return MaplePacketCreator.showBossHP(getId(), getHp(), getMaxHp(), getTagColor(), getTagBgColor());
}
public boolean hasBossHPBar() {
return (isBoss() && getTagColor() > 0) || isHT();
}
private boolean isHT() {
return getId() == 8810018;
}
@Override
public void sendSpawnData(MapleClient c) {
if (!isAlive()) {
return;
}
if (isFake()) {
c.announce(MaplePacketCreator.spawnFakeMonster(this, 0));
} else {
c.announce(MaplePacketCreator.spawnMonster(this, false));
}
if (stati.size() > 0) {
for (final MonsterStatusEffect mse : this.stati.values()) {
c.announce(MaplePacketCreator.applyMonsterStatus(getObjectId(), mse, null));
}
}
if (hasBossHPBar()) {
if (this.getMap().countMonster(8810026) > 0 && this.getMap().getId() == 240060200) {
this.getMap().killAllMonsters();
return;
}
c.announce(makeBossHPBarPacket());
}
}
@Override
public void sendDestroyData(MapleClient client) {
client.announce(MaplePacketCreator.killMonster(getObjectId(), false));
}
@Override
public MapleMapObjectType getType() {
return MapleMapObjectType.MONSTER;
}
public void setEventInstance(EventInstanceManager eventInstance) {
this.eventInstance = eventInstance;
}
public EventInstanceManager getEventInstance() {
return eventInstance;
}
public boolean isMobile() {
return stats.isMobile();
}
public ElementalEffectiveness getEffectiveness(Element e) {
if (stati.size() > 0 && stati.get(MonsterStatus.DOOM) != null) {
return ElementalEffectiveness.NORMAL; // like blue snails
}
return stats.getEffectiveness(e);
}
public boolean applyStatus(MapleCharacter from, final MonsterStatusEffect status, boolean poison, long duration) {
return applyStatus(from, status, poison, duration, false);
}
public boolean applyStatus(MapleCharacter from, final MonsterStatusEffect status, boolean poison, long duration, boolean venom) {
switch (stats.getEffectiveness(status.getSkill().getElement())) {
case IMMUNE:
case STRONG:
case NEUTRAL:
return false;
case NORMAL:
case WEAK:
break;
default: {
System.out.println("Unknown elemental effectiveness: " + stats.getEffectiveness(status.getSkill().getElement()));
return false;
}
}
if (status.getSkill().getId() == FPMage.ELEMENT_COMPOSITION) { // fp compo
ElementalEffectiveness effectiveness = stats.getEffectiveness(Element.POISON);
if (effectiveness == ElementalEffectiveness.IMMUNE || effectiveness == ElementalEffectiveness.STRONG) {
return false;
}
} else if (status.getSkill().getId() == ILMage.ELEMENT_COMPOSITION) { // il compo
ElementalEffectiveness effectiveness = stats.getEffectiveness(Element.ICE);
if (effectiveness == ElementalEffectiveness.IMMUNE || effectiveness == ElementalEffectiveness.STRONG) {
return false;
}
} else if (status.getSkill().getId() == NightLord.VENOMOUS_STAR || status.getSkill().getId() == Shadower.VENOMOUS_STAB || status.getSkill().getId() == NightWalker.VENOM) {// venom
if (stats.getEffectiveness(Element.POISON) == ElementalEffectiveness.WEAK) {
return false;
}
}
if (poison && getHp() <= 1) {
return false;
}
final Map<MonsterStatus, Integer> statis = status.getStati();
if (stats.isBoss()) {
if (!(statis.containsKey(MonsterStatus.SPEED)
&& statis.containsKey(MonsterStatus.NINJA_AMBUSH)
&& statis.containsKey(MonsterStatus.WATK))) {
return false;
}
}
for (MonsterStatus stat : statis.keySet()) {
final MonsterStatusEffect oldEffect = stati.get(stat);
if (oldEffect != null) {
oldEffect.removeActiveStatus(stat);
if (oldEffect.getStati().isEmpty()) {
oldEffect.cancelTask();
oldEffect.cancelDamageSchedule();
}
}
}
TimerManager timerManager = TimerManager.getInstance();
final Runnable cancelTask = new Runnable() {
@Override
public void run() {
if (isAlive()) {
byte[] packet = MaplePacketCreator.cancelMonsterStatus(getObjectId(), status.getStati());
map.broadcastMessage(packet, getPosition());
if (getController() != null && !getController().isMapObjectVisible(MapleMonster.this)) {
getController().getClient().announce(packet);
}
}
for (MonsterStatus stat : status.getStati().keySet()) {
stati.remove(stat);
}
setVenomMulti(0);
status.cancelDamageSchedule();
}
};
if (poison) {
int poisonLevel = from.getSkillLevel(status.getSkill());
int poisonDamage = Math.min(Short.MAX_VALUE, (int) (getMaxHp() / (70.0 - poisonLevel) + 0.999));
status.setValue(MonsterStatus.POISON, Integer.valueOf(poisonDamage));
status.setDamageSchedule(timerManager.register(new DamageTask(poisonDamage, from, status, cancelTask, 0), 1000, 1000));
} else if (venom) {
if (from.getJob() == MapleJob.NIGHTLORD || from.getJob() == MapleJob.SHADOWER || from.getJob().isA(MapleJob.NIGHTWALKER3)) {
int poisonLevel, matk, id = from.getJob().getId();
int skill = (id == 412 ? NightLord.VENOMOUS_STAR : (id == 422 ? Shadower.VENOMOUS_STAB : NightWalker.VENOM));
poisonLevel = from.getSkillLevel(SkillFactory.getSkill(skill));
if (poisonLevel <= 0) {
return false;
}
matk = SkillFactory.getSkill(skill).getEffect(poisonLevel).getMatk();
int luk = from.getLuk();
int maxDmg = (int) Math.ceil(Math.min(Short.MAX_VALUE, 0.2 * luk * matk));
int minDmg = (int) Math.ceil(Math.min(Short.MAX_VALUE, 0.1 * luk * matk));
int gap = maxDmg - minDmg;
if (gap == 0) {
gap = 1;
}
int poisonDamage = 0;
for (int i = 0; i < getVenomMulti(); i++) {
poisonDamage += (Randomizer.nextInt(gap) + minDmg);
}
poisonDamage = Math.min(Short.MAX_VALUE, poisonDamage);
status.setValue(MonsterStatus.VENOMOUS_WEAPON, Integer.valueOf(poisonDamage));
status.setDamageSchedule(timerManager.register(new DamageTask(poisonDamage, from, status, cancelTask, 0), 1000, 1000));
} else {
return false;
}
} else if (status.getSkill().getId() == Hermit.SHADOW_WEB || status.getSkill().getId() == NightWalker.SHADOW_WEB) { //Shadow Web
status.setDamageSchedule(timerManager.schedule(new DamageTask((int) (getMaxHp() / 50.0 + 0.999), from, status, cancelTask, 1), 3500));
} else if (status.getSkill().getId() == 4121004 || status.getSkill().getId() == 4221004) { // Ninja Ambush
final Skill skill = SkillFactory.getSkill(status.getSkill().getId());
final byte level = from.getSkillLevel(skill);
final int damage = (int) ((from.getStr() + from.getLuk()) * (1.5 + (level * 0.05)) * skill.getEffect(level).getDamage());
/*if (getHp() - damage <= 1) { make hp 1 betch
damage = getHp() - (getHp() - 1);
}*/
status.setValue(MonsterStatus.NINJA_AMBUSH, Integer.valueOf(damage));
status.setDamageSchedule(timerManager.register(new DamageTask(damage, from, status, cancelTask, 2), 1000, 1000));
}
for (MonsterStatus stat : status.getStati().keySet()) {
stati.put(stat, status);
alreadyBuffed.add(stat);
}
int animationTime = status.getSkill().getAnimationTime();
byte[] packet = MaplePacketCreator.applyMonsterStatus(getObjectId(), status, null);
map.broadcastMessage(packet, getPosition());
if (getController() != null && !getController().isMapObjectVisible(this)) {
getController().getClient().announce(packet);
}
status.setCancelTask(timerManager.schedule(cancelTask, duration + animationTime));
return true;
}
public void applyMonsterBuff(final Map<MonsterStatus, Integer> stats, final int x, int skillId, long duration, MobSkill skill, final List<Integer> reflection) {
TimerManager timerManager = TimerManager.getInstance();
final Runnable cancelTask = new Runnable() {
@Override
public void run() {
if (isAlive()) {
byte[] packet = MaplePacketCreator.cancelMonsterStatus(getObjectId(), stats);
map.broadcastMessage(packet, getPosition());
if (getController() != null && !getController().isMapObjectVisible(MapleMonster.this)) {
getController().getClient().announce(packet);
}
for (final MonsterStatus stat : stats.keySet()) {
stati.remove(stat);
}
}
}
};
final MonsterStatusEffect effect = new MonsterStatusEffect(stats, null, skill, true);
byte[] packet = MaplePacketCreator.applyMonsterStatus(getObjectId(), effect, reflection);
map.broadcastMessage(packet, getPosition());
for (MonsterStatus stat : stats.keySet()) {
stati.put(stat, effect);
alreadyBuffed.add(stat);
}
if (getController() != null && !getController().isMapObjectVisible(this)) {
getController().getClient().announce(packet);
}
effect.setCancelTask(timerManager.schedule(cancelTask, duration));
}
public void debuffMob(int skillid) {
//skillid is not going to be used for now until I get warrior debuff working
MonsterStatus[] stats = {MonsterStatus.WEAPON_ATTACK_UP, MonsterStatus.WEAPON_DEFENSE_UP, MonsterStatus.MAGIC_ATTACK_UP, MonsterStatus.MAGIC_DEFENSE_UP};
for (int i = 0; i < stats.length; i++) {
if (isBuffed(stats[i])) {
final MonsterStatusEffect oldEffect = stati.get(stats[i]);
byte[] packet = MaplePacketCreator.cancelMonsterStatus(getObjectId(), oldEffect.getStati());
map.broadcastMessage(packet, getPosition());
if (getController() != null && !getController().isMapObjectVisible(MapleMonster.this)) {
getController().getClient().announce(packet);
}
stati.remove(stats);
}
}
}
public boolean isBuffed(MonsterStatus status) {
return stati.containsKey(status);
}
public void setFake(boolean fake) {
this.fake = fake;
}
public boolean isFake() {
return fake;
}
public MapleMap getMap() {
return map;
}
public List<Pair<Integer, Integer>> getSkills() {
return stats.getSkills();
}
public boolean hasSkill(int skillId, int level) {
return stats.hasSkill(skillId, level);
}
public boolean canUseSkill(MobSkill toUse) {
if (toUse == null) {
return false;
}
for (Pair<Integer, Integer> skill : usedSkills) {
if (skill.getLeft() == toUse.getSkillId() && skill.getRight() == toUse.getSkillLevel()) {
return false;
}
}
if (toUse.getLimit() > 0) {
if (this.skillsUsed.containsKey(new Pair<>(toUse.getSkillId(), toUse.getSkillLevel()))) {
int times = this.skillsUsed.get(new Pair<>(toUse.getSkillId(), toUse.getSkillLevel()));
if (times >= toUse.getLimit()) {
return false;
}
}
}
if (toUse.getSkillId() == 200) {
Collection<MapleMapObject> mmo = getMap().getMapObjects();
int i = 0;
for (MapleMapObject mo : mmo) {
if (mo.getType() == MapleMapObjectType.MONSTER) {
i++;
}
}
if (i > 100) {
return false;
}
}
return true;
}
public void usedSkill(final int skillId, final int level, long cooltime) {
this.usedSkills.add(new Pair<>(skillId, level));
if (this.skillsUsed.containsKey(new Pair<>(skillId, level))) {
int times = this.skillsUsed.get(new Pair<>(skillId, level)) + 1;
this.skillsUsed.remove(new Pair<>(skillId, level));
this.skillsUsed.put(new Pair<>(skillId, level), times);
} else {
this.skillsUsed.put(new Pair<>(skillId, level), 1);
}
final MapleMonster mons = this;
TimerManager tMan = TimerManager.getInstance();
tMan.schedule(
new Runnable() {
@Override
public void run() {
mons.clearSkill(skillId, level);
}
}, cooltime);
}
public void clearSkill(int skillId, int level) {
int index = -1;
for (Pair<Integer, Integer> skill : usedSkills) {
if (skill.getLeft() == skillId && skill.getRight() == level) {
index = usedSkills.indexOf(skill);
break;
}
}
if (index != -1) {
usedSkills.remove(index);
}
}
public int getNoSkills() {
return this.stats.getNoSkills();
}
public boolean isFirstAttack() {
return this.stats.isFirstAttack();
}
public int getBuffToGive() {
return this.stats.getBuffToGive();
}
private final class DamageTask implements Runnable {
private final int dealDamage;
private final MapleCharacter chr;
private final MonsterStatusEffect status;
private final Runnable cancelTask;
private final int type;
private final MapleMap map;
private DamageTask(int dealDamage, MapleCharacter chr, MonsterStatusEffect status, Runnable cancelTask, int type) {
this.dealDamage = dealDamage;
this.chr = chr;
this.status = status;
this.cancelTask = cancelTask;
this.type = type;
this.map = chr.getMap();
}
@Override
public void run() {
int damage = dealDamage;
if (damage >= hp) {
damage = hp - 1;
if (type == 1 || type == 2) {
map.broadcastMessage(MaplePacketCreator.damageMonster(getObjectId(), damage), getPosition());
cancelTask.run();
status.getCancelTask().cancel(false);
}
}
if (hp > 1 && damage > 0) {
damage(chr, damage);
if (type == 1) {
map.broadcastMessage(MaplePacketCreator.damageMonster(getObjectId(), damage), getPosition());
}
}
}
}
public String getName() {
return stats.getName();
}
public void addStolen(int itemId) {
stolenItems.add(itemId);
}
public List<Integer> getStolen() {
return stolenItems;
}
public void setTempEffectiveness(Element e, ElementalEffectiveness ee, long milli) {
final Element fE = e;
final ElementalEffectiveness fEE = stats.getEffectiveness(e);
if (!stats.getEffectiveness(e).equals(ElementalEffectiveness.WEAK)) {
stats.setEffectiveness(e, ee);
TimerManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
stats.removeEffectiveness(fE);
stats.setEffectiveness(fE, fEE);
}
}, milli);
}
}
public Collection<MonsterStatus> alreadyBuffedStats() {
return Collections.unmodifiableCollection(alreadyBuffed);
}
public BanishInfo getBanish() {
return stats.getBanishInfo();
}
public void setBoss(boolean boss) {
this.stats.setBoss(boss);
}
public int getDropPeriodTime() {
return stats.getDropPeriod();
}
public int getPADamage() {
return stats.getPADamage();
}
public Map<MonsterStatus, MonsterStatusEffect> getStati() {
return stati;
}
}

View File

@@ -0,0 +1,171 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 ~ 2010 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 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 server.life;
import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import provider.MapleData;
import provider.MapleDataProvider;
import provider.MapleDataProviderFactory;
import provider.MapleDataTool;
import tools.DatabaseConnection;
import tools.Pair;
public class MapleMonsterInformationProvider {
// Author : LightPepsi
private static final MapleMonsterInformationProvider instance = new MapleMonsterInformationProvider();
private final Map<Integer, List<MonsterDropEntry>> drops = new HashMap<>();
private final List<MonsterGlobalDropEntry> globaldrops = new ArrayList<>();
protected MapleMonsterInformationProvider() {
retrieveGlobal();
}
public static MapleMonsterInformationProvider getInstance() {
return instance;
}
public final List<MonsterGlobalDropEntry> getGlobalDrop() {
return globaldrops;
}
private void retrieveGlobal() {
PreparedStatement ps = null;
ResultSet rs = null;
try {
final Connection con = DatabaseConnection.getConnection();
ps = con.prepareStatement("SELECT * FROM drop_data_global WHERE chance > 0");
rs = ps.executeQuery();
while (rs.next()) {
globaldrops.add(
new MonsterGlobalDropEntry(
rs.getInt("itemid"),
rs.getInt("chance"),
rs.getInt("continent"),
rs.getByte("dropType"),
rs.getInt("minimum_quantity"),
rs.getInt("maximum_quantity"),
rs.getShort("questid")));
}
rs.close();
ps.close();
} catch (SQLException e) {
System.err.println("Error retrieving drop" + e);
} finally {
try {
if (ps != null) {
ps.close();
}
if (rs != null) {
rs.close();
}
} catch (SQLException ignore) {
}
}
}
public final List<MonsterDropEntry> retrieveDrop(final int monsterId) {
if (drops.containsKey(monsterId)) {
return drops.get(monsterId);
}
final List<MonsterDropEntry> ret = new LinkedList<>();
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = DatabaseConnection.getConnection().prepareStatement("SELECT * FROM drop_data WHERE dropperid = ?");
ps.setInt(1, monsterId);
rs = ps.executeQuery();
while (rs.next()) {
ret.add(
new MonsterDropEntry(
rs.getInt("itemid"),
rs.getInt("chance"),
rs.getInt("minimum_quantity"),
rs.getInt("maximum_quantity"),
rs.getShort("questid")));
}
} catch (SQLException e) {
return ret;
} finally {
try {
if (ps != null) {
ps.close();
}
if (rs != null) {
rs.close();
}
} catch (SQLException ignore) {
return ret;
}
}
drops.put(monsterId, ret);
return ret;
}
public static ArrayList<Pair<Integer, String>> getMobsIDsFromName(String search)
{
MapleDataProvider dataProvider = MapleDataProviderFactory.getDataProvider(new File("wz/String.wz"));
ArrayList<Pair<Integer, String>> retMobs = new ArrayList<Pair<Integer, String>>();
MapleData data = dataProvider.getData("Mob.img");
List<Pair<Integer, String>> mobPairList = new LinkedList<Pair<Integer, String>>();
for (MapleData mobIdData : data.getChildren()) {
int mobIdFromData = Integer.parseInt(mobIdData.getName());
String mobNameFromData = MapleDataTool.getString(mobIdData.getChildByPath("name"), "NO-NAME");
mobPairList.add(new Pair<Integer, String>(mobIdFromData, mobNameFromData));
}
for (Pair<Integer, String> mobPair : mobPairList) {
if (mobPair.getRight().toLowerCase().contains(search.toLowerCase())) {
retMobs.add(mobPair);
}
}
return retMobs;
}
public static String getMobNameFromID(int id)
{
try
{
return MapleLifeFactory.getMonster(id).getName();
} catch (Exception e)
{
return null; //nonexistant mob
}
}
public final void clearDrops() {
drops.clear();
globaldrops.clear();
retrieveGlobal();
}
}

View File

@@ -0,0 +1,327 @@
/*
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 server.life;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import server.life.MapleLifeFactory.BanishInfo;
import server.life.MapleLifeFactory.loseItem;
import server.life.MapleLifeFactory.selfDestruction;
import tools.Pair;
/**
* @author Frz
*/
public class MapleMonsterStats {
private int exp, hp, mp, level, PADamage, PDDamage, MADamage, MDDamage, dropPeriod, cp, buffToGive, removeAfter;
private boolean boss, undead, ffaLoot, isExplosiveReward, firstAttack, removeOnMiss;
private String name;
private Map<String, Integer> animationTimes = new HashMap<String, Integer>();
private Map<Element, ElementalEffectiveness> resistance = new HashMap<Element, ElementalEffectiveness>();
private List<Integer> revives = Collections.emptyList();
private byte tagColor, tagBgColor;
private List<Pair<Integer, Integer>> skills = new ArrayList<Pair<Integer, Integer>>();
private Pair<Integer, Integer> cool = null;
private BanishInfo banish = null;
private List<loseItem> loseItem = null;
private selfDestruction selfDestruction = null;
private boolean friendly;
public int getExp() {
return exp;
}
public void setExp(int exp) {
this.exp = exp;
}
public int getHp() {
return hp;
}
public void setHp(int hp) {
this.hp = hp;
}
public int getMp() {
return mp;
}
public void setMp(int mp) {
this.mp = mp;
}
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
public int removeAfter() {
return removeAfter;
}
public void setRemoveAfter(int removeAfter) {
this.removeAfter = removeAfter;
}
public int getDropPeriod() {
return dropPeriod;
}
public void setDropPeriod(int dropPeriod) {
this.dropPeriod = dropPeriod;
}
public void setBoss(boolean boss) {
this.boss = boss;
}
public boolean isBoss() {
return boss;
}
public void setFfaLoot(boolean ffaLoot) {
this.ffaLoot = ffaLoot;
}
public boolean isFfaLoot() {
return ffaLoot;
}
public void setAnimationTime(String name, int delay) {
animationTimes.put(name, delay);
}
public int getAnimationTime(String name) {
Integer ret = animationTimes.get(name);
if (ret == null) {
return 500;
}
return ret.intValue();
}
public boolean isMobile() {
return animationTimes.containsKey("move") || animationTimes.containsKey("fly");
}
public List<Integer> getRevives() {
return revives;
}
public void setRevives(List<Integer> revives) {
this.revives = revives;
}
public void setUndead(boolean undead) {
this.undead = undead;
}
public boolean getUndead() {
return undead;
}
public void setEffectiveness(Element e, ElementalEffectiveness ee) {
resistance.put(e, ee);
}
public ElementalEffectiveness getEffectiveness(Element e) {
ElementalEffectiveness elementalEffectiveness = resistance.get(e);
if (elementalEffectiveness == null) {
return ElementalEffectiveness.NORMAL;
} else {
return elementalEffectiveness;
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public byte getTagColor() {
return tagColor;
}
public void setTagColor(int tagColor) {
this.tagColor = (byte) tagColor;
}
public byte getTagBgColor() {
return tagBgColor;
}
public void setTagBgColor(int tagBgColor) {
this.tagBgColor = (byte) tagBgColor;
}
public void setSkills(List<Pair<Integer, Integer>> skills) {
for (Pair<Integer, Integer> skill : skills) {
this.skills.add(skill);
}
}
public List<Pair<Integer, Integer>> getSkills() {
return Collections.unmodifiableList(this.skills);
}
public int getNoSkills() {
return this.skills.size();
}
public boolean hasSkill(int skillId, int level) {
for (Pair<Integer, Integer> skill : skills) {
if (skill.getLeft() == skillId && skill.getRight() == level) {
return true;
}
}
return false;
}
public void setFirstAttack(boolean firstAttack) {
this.firstAttack = firstAttack;
}
public boolean isFirstAttack() {
return firstAttack;
}
public void setBuffToGive(int buff) {
this.buffToGive = buff;
}
public int getBuffToGive() {
return buffToGive;
}
void removeEffectiveness(Element e) {
resistance.remove(e);
}
public BanishInfo getBanishInfo() {
return banish;
}
public void setBanishInfo(BanishInfo banish) {
this.banish = banish;
}
public int getPADamage() {
return PADamage;
}
public void setPADamage(int PADamage) {
this.PADamage = PADamage;
}
public int getCP() {
return cp;
}
public void setCP(int cp) {
this.cp = cp;
}
public List<loseItem> loseItem() {
return loseItem;
}
public void addLoseItem(loseItem li) {
if (loseItem == null) {
loseItem = new LinkedList<loseItem>();
}
loseItem.add(li);
}
public selfDestruction selfDestruction() {
return selfDestruction;
}
public void setSelfDestruction(selfDestruction sd) {
this.selfDestruction = sd;
}
public void setExplosiveReward(boolean isExplosiveReward) {
this.isExplosiveReward = isExplosiveReward;
}
public boolean isExplosiveReward() {
return isExplosiveReward;
}
public void setRemoveOnMiss(boolean removeOnMiss) {
this.removeOnMiss = removeOnMiss;
}
public boolean removeOnMiss() {
return removeOnMiss;
}
public void setCool(Pair<Integer, Integer> cool) {
this.cool = cool;
}
public Pair<Integer, Integer> getCool() {
return cool;
}
public int getPDDamage() {
return PDDamage;
}
public int getMADamage() {
return MADamage;
}
public int getMDDamage() {
return MDDamage;
}
public boolean isFriendly() {
return friendly;
}
public void setFriendly(boolean value) {
this.friendly = value;
}
public void setPDDamage(int PDDamage) {
this.PDDamage = PDDamage;
}
public void setMADamage(int MADamage) {
this.MADamage = MADamage;
}
public void setMDDamage(int MDDamage) {
this.MDDamage = MDDamage;
}
}

View File

@@ -0,0 +1,68 @@
/*
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 server.life;
import client.MapleClient;
import server.MapleShopFactory;
import server.maps.MapleMapObjectType;
import tools.MaplePacketCreator;
public class MapleNPC extends AbstractLoadedMapleLife {
private MapleNPCStats stats;
public MapleNPC(int id, MapleNPCStats stats) {
super(id);
this.stats = stats;
}
public boolean hasShop() {
return MapleShopFactory.getInstance().getShopForNPC(getId()) != null;
}
public void sendShop(MapleClient c) {
MapleShopFactory.getInstance().getShopForNPC(getId()).sendShop(c);
}
@Override
public void sendSpawnData(MapleClient client) {
if (this.getId() > 9010010 && this.getId() < 9010014) {
client.announce(MaplePacketCreator.spawnNPCRequestController(this, false));
} else {
client.announce(MaplePacketCreator.spawnNPC(this));
client.announce(MaplePacketCreator.spawnNPCRequestController(this, true));
}
}
@Override
public void sendDestroyData(MapleClient client) {
client.announce(MaplePacketCreator.removeNPC(getObjectId()));
}
@Override
public MapleMapObjectType getType() {
return MapleMapObjectType.NPC;
}
public String getName() {
return stats.getName();
}
}

View File

@@ -0,0 +1,42 @@
/*
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 server.life;
/**
*
* @author Matze
*/
public class MapleNPCStats {
private String name;
public MapleNPCStats(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@@ -0,0 +1,77 @@
/*
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 server.life;
/**
*
* @author Danny (Leifde)
*/
public class MobAttackInfo {
private boolean isDeadlyAttack;
private int mpBurn;
private int diseaseSkill;
private int diseaseLevel;
private int mpCon;
public MobAttackInfo(int mobId, int attackId) {
}
public void setDeadlyAttack(boolean isDeadlyAttack) {
this.isDeadlyAttack = isDeadlyAttack;
}
public boolean isDeadlyAttack() {
return isDeadlyAttack;
}
public void setMpBurn(int mpBurn) {
this.mpBurn = mpBurn;
}
public int getMpBurn() {
return mpBurn;
}
public void setDiseaseSkill(int diseaseSkill) {
this.diseaseSkill = diseaseSkill;
}
public int getDiseaseSkill() {
return diseaseSkill;
}
public void setDiseaseLevel(int diseaseLevel) {
this.diseaseLevel = diseaseLevel;
}
public int getDiseaseLevel() {
return diseaseLevel;
}
public void setMpCon(int mpCon) {
this.mpCon = mpCon;
}
public int getMpCon() {
return mpCon;
}
}

View File

@@ -0,0 +1,79 @@
/*
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 server.life;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import provider.MapleData;
import provider.MapleDataProvider;
import provider.MapleDataProviderFactory;
import provider.MapleDataTool;
import tools.StringUtil;
/**
*
* @author Danny (Leifde)
*/
public class MobAttackInfoFactory {
private static Map<String, MobAttackInfo> mobAttacks = new HashMap<String, MobAttackInfo>();
private static MapleDataProvider dataSource = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Mob.wz"));
public static MobAttackInfo getMobAttackInfo(MapleMonster mob, int attack) {
MobAttackInfo ret = mobAttacks.get(mob.getId() + "" + attack);
if (ret != null) {
return ret;
}
synchronized (mobAttacks) {
ret = mobAttacks.get(mob.getId() + "" + attack);
if (ret == null) {
MapleData mobData = dataSource.getData(StringUtil.getLeftPaddedStr(Integer.toString(mob.getId()) + ".img", '0', 11));
if (mobData != null) {
// MapleData infoData = mobData.getChildByPath("info");
String linkedmob = MapleDataTool.getString("link", mobData, "");
if (!linkedmob.equals("")) {
mobData = dataSource.getData(StringUtil.getLeftPaddedStr(linkedmob + ".img", '0', 11));
}
MapleData attackData = mobData.getChildByPath("attack" + (attack + 1) + "/info");
if (attackData == null) {
return null;
}
MapleData deadlyAttack = attackData.getChildByPath("deadlyAttack");
int mpBurn = MapleDataTool.getInt("mpBurn", attackData, 0);
int disease = MapleDataTool.getInt("disease", attackData, 0);
int level = MapleDataTool.getInt("level", attackData, 0);
int mpCon = MapleDataTool.getInt("conMP", attackData, 0);
ret = new MobAttackInfo(mob.getId(), attack);
ret.setDeadlyAttack(deadlyAttack != null);
ret.setMpBurn(mpBurn);
ret.setDiseaseSkill(disease);
ret.setDiseaseLevel(level);
ret.setMpCon(mpCon);
}
mobAttacks.put(mob.getId() + "" + attack, ret);
}
return ret;
}
}
}

View File

@@ -0,0 +1,386 @@
/*
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 server.life;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import client.MapleCharacter;
import client.MapleDisease;
import client.status.MonsterStatus;
import java.util.LinkedList;
import java.util.Map;
import tools.Randomizer;
import server.maps.MapleMapObject;
import server.maps.MapleMapObjectType;
import server.maps.MapleMist;
import tools.ArrayMap;
/**
*
* @author Danny (Leifde)
*/
public class MobSkill {
private int skillId, skillLevel, mpCon;
private List<Integer> toSummon = new ArrayList<Integer>();
private int spawnEffect, hp, x, y;
private long duration, cooltime;
private float prop;
private Point lt, rb;
private int limit;
public MobSkill(int skillId, int level) {
this.skillId = skillId;
this.skillLevel = level;
}
public void setMpCon(int mpCon) {
this.mpCon = mpCon;
}
public void addSummons(List<Integer> toSummon) {
for (Integer summon : toSummon) {
this.toSummon.add(summon);
}
}
public void setSpawnEffect(int spawnEffect) {
this.spawnEffect = spawnEffect;
}
public void setHp(int hp) {
this.hp = hp;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setDuration(long duration) {
this.duration = duration;
}
public void setCoolTime(long cooltime) {
this.cooltime = cooltime;
}
public void setProp(float prop) {
this.prop = prop;
}
public void setLtRb(Point lt, Point rb) {
this.lt = lt;
this.rb = rb;
}
public void setLimit(int limit) {
this.limit = limit;
}
public void applyEffect(MapleCharacter player, MapleMonster monster, boolean skill) {
MapleDisease disease = null;
Map<MonsterStatus, Integer> stats = new ArrayMap<MonsterStatus, Integer>();
List<Integer> reflection = new LinkedList<Integer>();
switch (skillId) {
case 100:
case 110:
case 150:
stats.put(MonsterStatus.WEAPON_ATTACK_UP, Integer.valueOf(x));
break;
case 101:
case 111:
case 151:
stats.put(MonsterStatus.MAGIC_ATTACK_UP, Integer.valueOf(x));
break;
case 102:
case 112:
case 152:
stats.put(MonsterStatus.WEAPON_DEFENSE_UP, Integer.valueOf(x));
break;
case 103:
case 113:
case 153:
stats.put(MonsterStatus.MAGIC_DEFENSE_UP, Integer.valueOf(x));
break;
case 114:
if (lt != null && rb != null && skill) {
List<MapleMapObject> objects = getObjectsInRange(monster, MapleMapObjectType.MONSTER);
final int hps = (getX() / 1000) * (int) (950 + 1050 * Math.random());
for (MapleMapObject mons : objects) {
((MapleMonster) mons).heal(hps, getY());
}
} else {
monster.heal(getX(), getY());
}
break;
case 120:
disease = MapleDisease.SEAL;
break;
case 121:
disease = MapleDisease.DARKNESS;
break;
case 122:
disease = MapleDisease.WEAKEN;
break;
case 123:
disease = MapleDisease.STUN;
break;
case 124:
disease = MapleDisease.CURSE;
break;
case 125:
disease = MapleDisease.POISON;
break;
case 126: // Slow
disease = MapleDisease.SLOW;
break;
case 127:
if (lt != null && rb != null && skill) {
for (MapleCharacter character : getPlayersInRange(monster, player)) {
character.dispel();
}
} else {
player.dispel();
}
break;
case 128: // Seduce
disease = MapleDisease.SEDUCE;
break;
case 129: // Banish
if (lt != null && rb != null && skill) {
for (MapleCharacter chr : getPlayersInRange(monster, player)) {
chr.changeMapBanish(monster.getBanish().getMap(), monster.getBanish().getPortal(), monster.getBanish().getMsg());
}
} else {
player.changeMapBanish(monster.getBanish().getMap(), monster.getBanish().getPortal(), monster.getBanish().getMsg());
}
break;
case 131: // Mist
monster.getMap().spawnMist(new MapleMist(calculateBoundingBox(monster.getPosition(), true), monster, this), x * 10, false, false, false);
break;
case 132:
disease = MapleDisease.CONFUSE;
break;
case 133: // zombify
break;
case 140:
if (makeChanceResult() && !monster.isBuffed(MonsterStatus.MAGIC_IMMUNITY)) {
stats.put(MonsterStatus.WEAPON_IMMUNITY, Integer.valueOf(x));
}
break;
case 141:
if (makeChanceResult() && !monster.isBuffed(MonsterStatus.WEAPON_IMMUNITY)) {
stats.put(MonsterStatus.MAGIC_IMMUNITY, Integer.valueOf(x));
}
break;
case 143: // Weapon Reflect
stats.put(MonsterStatus.WEAPON_REFLECT, Integer.valueOf(x));
stats.put(MonsterStatus.WEAPON_IMMUNITY, Integer.valueOf(x));
reflection.add(x);
break;
case 144: // Magic Reflect
stats.put(MonsterStatus.MAGIC_REFLECT, Integer.valueOf(x));
stats.put(MonsterStatus.MAGIC_IMMUNITY, Integer.valueOf(x));
reflection.add(x);
break;
case 145: // Weapon / Magic reflect
stats.put(MonsterStatus.WEAPON_REFLECT, Integer.valueOf(x));
stats.put(MonsterStatus.WEAPON_IMMUNITY, Integer.valueOf(x));
stats.put(MonsterStatus.MAGIC_REFLECT, Integer.valueOf(x));
stats.put(MonsterStatus.MAGIC_IMMUNITY, Integer.valueOf(x));
reflection.add(x);
break;
case 154: // accuracy up
case 155: // avoid up
case 156: // speed up
break;
case 200:
if (monster.getMap().getSpawnedMonstersOnMap() < 80) {
for (Integer mobId : getSummons()) {
MapleMonster toSpawn = MapleLifeFactory.getMonster(mobId);
toSpawn.setPosition(monster.getPosition());
int ypos, xpos;
xpos = (int) monster.getPosition().getX();
ypos = (int) monster.getPosition().getY();
switch (mobId) {
case 8500003: // Pap bomb high
toSpawn.setFh((int) Math.ceil(Math.random() * 19.0));
ypos = -590;
break;
case 8500004: // Pap bomb
xpos = (int) (monster.getPosition().getX() + Randomizer.nextInt(1000) - 500);
if (ypos != -590) {
ypos = (int) monster.getPosition().getY();
}
break;
case 8510100: //Pianus bomb
if (Math.ceil(Math.random() * 5) == 1) {
ypos = 78;
xpos = (int) Randomizer.nextInt(5) + (Randomizer.nextInt(2) == 1 ? 180 : 0);
} else {
xpos = (int) (monster.getPosition().getX() + Randomizer.nextInt(1000) - 500);
}
break;
}
switch (monster.getMap().getId()) {
case 220080001: //Pap map
if (xpos < -890) {
xpos = (int) (Math.ceil(Math.random() * 150) - 890);
} else if (xpos > 230) {
xpos = (int) (230 - Math.ceil(Math.random() * 150));
}
break;
case 230040420: // Pianus map
if (xpos < -239) {
xpos = (int) (Math.ceil(Math.random() * 150) - 239);
} else if (xpos > 371) {
xpos = (int) (371 - Math.ceil(Math.random() * 150));
}
break;
}
toSpawn.setPosition(new Point(xpos, ypos));
if (toSpawn.getId() == 8500004) {
monster.getMap().spawnFakeMonster(toSpawn);
} else {
monster.getMap().spawnMonsterWithEffect(toSpawn, getSpawnEffect(), toSpawn.getPosition());
}
}
}
break;
default:
System.out.println("Unhandeled Mob skill: " + skillId);
break;
}
if (stats.size() > 0) {
if (lt != null && rb != null && skill) {
for (MapleMapObject mons : getObjectsInRange(monster, MapleMapObjectType.MONSTER)) {
((MapleMonster) mons).applyMonsterBuff(stats, getX(), getSkillId(), getDuration(), this, reflection);
}
} else {
monster.applyMonsterBuff(stats, getX(), getSkillId(), getDuration(), this, reflection);
}
}
if (disease != null) {
if (lt != null && rb != null && skill) {
int i = 0;
for (MapleCharacter character : getPlayersInRange(monster, player)) {
if (!character.isActiveBuffedValue(2321005)) {
if (disease.equals(MapleDisease.SEDUCE)) {
if (i < 10) {
character.giveDebuff(MapleDisease.SEDUCE, this);
i++;
}
} else {
character.giveDebuff(disease, this);
}
}
}
} else {
player.giveDebuff(disease, this);
}
}
monster.usedSkill(skillId, skillLevel, cooltime);
monster.setMp(monster.getMp() - getMpCon());
}
private List<MapleCharacter> getPlayersInRange(MapleMonster monster, MapleCharacter player) {
List<MapleCharacter> players = new ArrayList<MapleCharacter>();
players.add(player);
return monster.getMap().getPlayersInRange(calculateBoundingBox(monster.getPosition(), monster.isFacingLeft()), players);
}
public int getSkillId() {
return skillId;
}
public int getSkillLevel() {
return skillLevel;
}
public int getMpCon() {
return mpCon;
}
public List<Integer> getSummons() {
return Collections.unmodifiableList(toSummon);
}
public int getSpawnEffect() {
return spawnEffect;
}
public int getHP() {
return hp;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public long getDuration() {
return duration;
}
public long getCoolTime() {
return cooltime;
}
public Point getLt() {
return lt;
}
public Point getRb() {
return rb;
}
public int getLimit() {
return limit;
}
public boolean makeChanceResult() {
return prop == 1.0 || Math.random() < prop;
}
private Rectangle calculateBoundingBox(Point posFrom, boolean facingLeft) {
int multiplier = facingLeft ? 1 : -1;
Point mylt = new Point(lt.x * multiplier + posFrom.x, lt.y + posFrom.y);
Point myrb = new Point(rb.x * multiplier + posFrom.x, rb.y + posFrom.y);
return new Rectangle(mylt.x, mylt.y, myrb.x - mylt.x, myrb.y - mylt.y);
}
private List<MapleMapObject> getObjectsInRange(MapleMonster monster, MapleMapObjectType objectType) {
List<MapleMapObjectType> objectTypes = new ArrayList<MapleMapObjectType>();
objectTypes.add(objectType);
return monster.getMap().getMapObjectsInBox(calculateBoundingBox(monster.getPosition(), monster.isFacingLeft()), objectTypes);
}
}

View File

@@ -0,0 +1,109 @@
/*
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 server.life;
import java.awt.Point;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import provider.MapleData;
import provider.MapleDataProvider;
import provider.MapleDataProviderFactory;
import provider.MapleDataTool;
/**
*
* @author Danny (Leifde)
*/
public class MobSkillFactory {
private static Map<String, MobSkill> mobSkills = new HashMap<String, MobSkill>();
private final static MapleDataProvider dataSource = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Skill.wz"));
private static MapleData skillRoot = dataSource.getData("MobSkill.img");
private static ReentrantReadWriteLock dataLock = new ReentrantReadWriteLock();
public static MobSkill getMobSkill(final int skillId, final int level) {
final String key = skillId + "" + level;
dataLock.readLock().lock();
try {
MobSkill ret = mobSkills.get(key);
if (ret != null) {
return ret;
}
} finally {
dataLock.readLock().unlock();
}
dataLock.writeLock().lock();
try {
MobSkill ret;
ret = mobSkills.get(key);
if (ret == null) {
MapleData skillData = skillRoot.getChildByPath(skillId + "/level/" + level);
if (skillData != null) {
int mpCon = MapleDataTool.getInt(skillData.getChildByPath("mpCon"), 0);
List<Integer> toSummon = new ArrayList<Integer>();
for (int i = 0; i > -1; i++) {
if (skillData.getChildByPath(String.valueOf(i)) == null) {
break;
}
toSummon.add(Integer.valueOf(MapleDataTool.getInt(skillData.getChildByPath(String.valueOf(i)), 0)));
}
int effect = MapleDataTool.getInt("summonEffect", skillData, 0);
int hp = MapleDataTool.getInt("hp", skillData, 100);
int x = MapleDataTool.getInt("x", skillData, 1);
int y = MapleDataTool.getInt("y", skillData, 1);
long duration = MapleDataTool.getInt("time", skillData, 0) * 1000;
long cooltime = MapleDataTool.getInt("interval", skillData, 0) * 1000;
int iprop = MapleDataTool.getInt("prop", skillData, 100);
float prop = iprop / 100;
int limit = MapleDataTool.getInt("limit", skillData, 0);
MapleData ltd = skillData.getChildByPath("lt");
Point lt = null;
Point rb = null;
if (ltd != null) {
lt = (Point) ltd.getData();
rb = (Point) skillData.getChildByPath("rb").getData();
}
ret = new MobSkill(skillId, level);
ret.addSummons(toSummon);
ret.setCoolTime(cooltime);
ret.setDuration(duration);
ret.setHp(hp);
ret.setMpCon(mpCon);
ret.setSpawnEffect(effect);
ret.setX(x);
ret.setY(y);
ret.setProp(prop);
ret.setLimit(limit);
ret.setLtRb(lt, rb);
}
mobSkills.put(skillId + "" + level, ret);
}
return ret;
} finally {
dataLock.writeLock().unlock();
}
}
}

View File

@@ -0,0 +1,38 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 ~ 2010 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 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 server.life;
/**
*
* @author LightPepsi
*/
public class MonsterDropEntry {
public MonsterDropEntry(int itemId, int chance, int Minimum, int Maximum, short questid) {
this.itemId = itemId;
this.chance = chance;
this.questid = questid;
this.Minimum = Minimum;
this.Maximum = Maximum;
}
public short questid;
public int itemId, chance, Minimum, Maximum;
}

View File

@@ -0,0 +1,39 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 ~ 2010 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 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 server.life;
/**
*
* @author LightPepsi
*/
public class MonsterGlobalDropEntry {
public MonsterGlobalDropEntry(int itemId, int chance, int continent, byte dropType, int Minimum, int Maximum, short questid) {
this.itemId = itemId;
this.chance = chance;
this.dropType = dropType;
this.questid = questid;
this.Minimum = Minimum;
this.Maximum = Maximum;
}
public byte dropType;
public int itemId, chance, Minimum, Maximum;
public short questid;
}

View File

@@ -0,0 +1,6 @@
package server.life;
public interface MonsterListener {
public void monsterKilled(int aniTime);
}

View File

@@ -0,0 +1,101 @@
/*
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 server.life;
import client.MapleCharacter;
import java.awt.Point;
import java.util.concurrent.atomic.AtomicInteger;
public class SpawnPoint {
private int monster, mobTime, team, fh, f;
private Point pos;
private long nextPossibleSpawn;
private int mobInterval = 5000;
private AtomicInteger spawnedMonsters = new AtomicInteger(0);
private boolean immobile;
public SpawnPoint(final MapleMonster monster, Point pos, boolean immobile, int mobTime, int mobInterval, int team) {
this.monster = monster.getId();
this.pos = new Point(pos);
this.mobTime = mobTime;
this.team = team;
this.fh = monster.getFh();
this.f = monster.getF();
this.immobile = immobile;
this.mobInterval = mobInterval;
this.nextPossibleSpawn = System.currentTimeMillis();
}
public boolean shouldSpawn() {
if (mobTime < 0 || ((mobTime != 0 || immobile) && spawnedMonsters.get() > 0) || spawnedMonsters.get() > 2) {//lol
return false;
}
return nextPossibleSpawn <= System.currentTimeMillis();
}
public boolean shouldForceSpawn() {
if (mobTime < 0 || ((mobTime != 0 || immobile) && spawnedMonsters.get() > 0) || spawnedMonsters.get() > 2) {//lol
return false;
}
return true;
}
public MapleMonster getMonster() {
MapleMonster mob = new MapleMonster(MapleLifeFactory.getMonster(monster));
mob.setPosition(new Point(pos));
mob.setTeam(team);
mob.setFh(fh);
mob.setF(f);
spawnedMonsters.incrementAndGet();
mob.addListener(new MonsterListener() {
@Override
public void monsterKilled(int aniTime) {
nextPossibleSpawn = System.currentTimeMillis();
if (mobTime > 0) {
nextPossibleSpawn += mobTime * 1000;
} else {
nextPossibleSpawn += aniTime;
}
spawnedMonsters.decrementAndGet();
}
});
if (mobTime == 0) {
nextPossibleSpawn = System.currentTimeMillis() + mobInterval;
}
return mob;
}
public Point getPosition() {
return pos;
}
public final int getF() {
return f;
}
public final int getFh() {
return fh;
}
}

View File

@@ -0,0 +1,38 @@
/*
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 server.maps;
public abstract class AbstractAnimatedMapleMapObject extends AbstractMapleMapObject implements AnimatedMapleMapObject {
private int stance;
public int getStance() {
return stance;
}
public void setStance(int stance) {
this.stance = stance;
}
public boolean isFacingLeft() {
return Math.abs(stance) % 2 == 1;
}
}

View File

@@ -0,0 +1,58 @@
/*
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 server.maps;
import java.awt.Point;
public abstract class AbstractMapleMapObject implements MapleMapObject {
private Point position = new Point();
private int objectId;
@Override
public abstract MapleMapObjectType getType();
@Override
public Point getPosition() {
return new Point(position);
}
@Override
public void setPosition(Point position) {
this.position.x = position.x;
this.position.y = position.y;
}
@Override
public int getObjectId() {
return objectId;
}
@Override
public void setObjectId(int id) {
this.objectId = id;
}
@Override
public void nullifyPosition() {
this.position = null;
}
}

View File

@@ -0,0 +1,28 @@
/*
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 server.maps;
public interface AnimatedMapleMapObject extends MapleMapObject {
int getStance();
void setStance(int stance);
boolean isFacingLeft();
}

View File

@@ -0,0 +1,69 @@
/*
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 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 server.maps;
/**
*
* @author AngelSL
*/
public enum FieldLimit {
JUMP(0x01),
MOVEMENTSKILLS(0x02),
SUMMON(0x04),
DOOR(0x08),
CHANGECHANNEL(0x10),
//NO_NOTES(0x20),
CANNOTVIPROCK(0x40),
CANNOTMINIGAME(0x80),
//SPECIFIC_PORTAL_SCROLL_LIMIT(0x100), // APQ and a couple quest maps have this
CANNOTUSEMOUNTS(0x200),
//STAT_CHANGE_ITEM_CONSUME_LIMIT(0x400), // Monster carnival?
//PARTY_BOSS_CHANGE_LIMIT(0x800), // Monster carnival?
CANNOTUSEPOTION(0x1000),
//WEDDING_INVITATION_LIMIT(0x2000), // No notes
//CASH_WEATHER_CONSUME_LIMIT(0x4000),
//NO_PET(0x8000), // Ariant colosseum-related?
//ANTI_MACRO_LIMIT(0x10000), // No notes
CANNOTJUMPDOWN(0x20000);
//SUMMON_NPC_LIMIT(0x40000); // Seems to .. disable Rush if 0x2 is set
//......... EVEN MORE LIMITS ............
//SUMMON_NPC_LIMIT(0x40000),
//NO_EXP_DECREASE(0x80000),
//NO_DAMAGE_ON_FALLING(0x100000),
//PARCEL_OPEN_LIMIT(0x200000),
//DROP_LIMIT(0x400000),
//ROCKETBOOSTER_LIMIT(0x800000) //lol we don't even have mechanics <3
private long i;
private FieldLimit(long i) {
this.i = i;
}
public long getValue() {
return i;
}
public boolean check(int fieldlimit) {
return (fieldlimit & i) == i;
}
}

View File

@@ -0,0 +1,459 @@
/*
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 server.maps;
import client.MapleCharacter;
import client.MapleClient;
import client.inventory.Item;
import client.inventory.ItemFactory;
import client.inventory.MapleInventoryType;
import com.mysql.jdbc.Statement;
import constants.ItemConstants;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ScheduledFuture;
import net.server.Server;
import server.MapleInventoryManipulator;
import server.MapleItemInformationProvider;
import server.MaplePlayerShopItem;
import server.TimerManager;
import tools.DatabaseConnection;
import tools.MaplePacketCreator;
import tools.Pair;
/**
*
* @author XoticStory
*/
public class HiredMerchant extends AbstractMapleMapObject {
private int ownerId, itemId, mesos = 0;
private int channel, world;
private long start;
private String ownerName = "";
private String description = "";
private MapleCharacter[] visitors = new MapleCharacter[3];
private List<MaplePlayerShopItem> items = new LinkedList<>();
private List<Pair<String, Byte>> messages = new LinkedList<>();
private List<SoldItem> sold = new LinkedList<>();
private boolean open;
public ScheduledFuture<?> schedule = null;
private MapleMap map;
public HiredMerchant(final MapleCharacter owner, int itemId, String desc) {
this.setPosition(owner.getPosition());
this.start = System.currentTimeMillis();
this.ownerId = owner.getId();
this.channel = owner.getClient().getChannel();
this.world = owner.getWorld();
this.itemId = itemId;
this.ownerName = owner.getName();
this.description = desc;
this.map = owner.getMap();
this.schedule = TimerManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
HiredMerchant.this.forceClose();
Server.getInstance().getChannel(world, channel).removeHiredMerchant(ownerId);
}
}, 1000 * 60 * 60 * 24);
}
public void broadcastToVisitors(final byte[] packet) {
for (MapleCharacter visitor : visitors) {
if (visitor != null) {
visitor.getClient().announce(packet);
}
}
}
public void addVisitor(MapleCharacter visitor) {
int i = this.getFreeSlot();
if (i > -1) {
visitors[i] = visitor;
broadcastToVisitors(MaplePacketCreator.hiredMerchantVisitorAdd(visitor, i + 1));
}
}
public void removeVisitor(MapleCharacter visitor) {
int slot = getVisitorSlot(visitor);
if (slot < 0){ //Not found
return;
}
if (visitors[slot] != null && visitors[slot].getId() == visitor.getId()) {
visitors[slot] = null;
if (slot != -1) {
broadcastToVisitors(MaplePacketCreator.hiredMerchantVisitorLeave(slot + 1));
}
}
}
public int getVisitorSlot(MapleCharacter visitor) {
for (int i = 0; i < 3; i++) {
if (visitors[i] != null && visitors[i].getId() == visitor.getId()){
return i;
}
}
return -1; //Actually 0 because of the +1's.
}
public void removeAllVisitors(String message) {
for (int i = 0; i < 3; i++) {
if (visitors[i] != null) {
visitors[i].setHiredMerchant(null);
visitors[i].getClient().announce(MaplePacketCreator.leaveHiredMerchant(i + 1, 0x11));
if (message.length() > 0) {
visitors[i].dropMessage(1, message);
}
visitors[i] = null;
}
}
}
public void buy(MapleClient c, int item, short quantity) {
MaplePlayerShopItem pItem = items.get(item);
synchronized (items) {
Item newItem = pItem.getItem().copy();
newItem.setQuantity((short) ((pItem.getItem().getQuantity() * quantity)));
if ((newItem.getFlag() & ItemConstants.KARMA) == ItemConstants.KARMA) {
newItem.setFlag((byte) (newItem.getFlag() ^ ItemConstants.KARMA));
}
if (newItem.getType() == 2 && (newItem.getFlag() & ItemConstants.SPIKES) == ItemConstants.SPIKES) {
newItem.setFlag((byte) (newItem.getFlag() ^ ItemConstants.SPIKES));
}
if (quantity < 1 || pItem.getBundles() < 1 || !pItem.isExist() || pItem.getBundles() < quantity) {
c.announce(MaplePacketCreator.enableActions());
return;
} else if (newItem.getType() == 1 && newItem.getQuantity() > 1) {
c.announce(MaplePacketCreator.enableActions());
return;
} else if (!pItem.isExist()) {
c.announce(MaplePacketCreator.enableActions());
return;
}
int price = pItem.getPrice() * quantity;
if (c.getPlayer().getMeso() >= price) {
if (MapleInventoryManipulator.addFromDrop(c, newItem, true)) {
c.getPlayer().gainMeso(-price, false);
sold.add(new SoldItem(c.getPlayer().getName(), pItem.getItem().getItemId(), quantity, price));
pItem.setBundles((short) (pItem.getBundles() - quantity));
if (pItem.getBundles() < 1) {
pItem.setDoesExist(false);
}
MapleCharacter owner = Server.getInstance().getWorld(world).getPlayerStorage().getCharacterByName(ownerName);
if (owner != null) {
owner.addMerchantMesos(price);
} else {
try {
try (PreparedStatement ps = DatabaseConnection.getConnection().prepareStatement("UPDATE characters SET MerchantMesos = MerchantMesos + " + price + " WHERE id = ?", Statement.RETURN_GENERATED_KEYS)) {
ps.setInt(1, ownerId);
ps.executeUpdate();
}
} catch (Exception e) {
}
}
} else {
c.getPlayer().dropMessage(1, "Your inventory is full. Please clean a slot before buying this item.");
}
} else {
c.getPlayer().dropMessage(1, "You do not have enough mesos.");
}
try {
this.saveItems(false);
} catch (Exception e) {
}
}
}
public void forceClose() {
if (schedule != null) {
schedule.cancel(false);
}
try {
saveItems(true);
items.clear();
} catch (SQLException ex) {
}
//Server.getInstance().getChannel(world, channel).removeHiredMerchant(ownerId);
map.broadcastMessage(MaplePacketCreator.destroyHiredMerchant(getOwnerId()));
map.removeMapObject(this);
MapleCharacter player = Server.getInstance().getWorld(world).getPlayerStorage().getCharacterById(ownerId);
if(player != null) {
player.setHasMerchant(false);
} else {
try (PreparedStatement ps = DatabaseConnection.getConnection().prepareStatement("UPDATE characters SET HasMerchant = 0 WHERE id = ?", Statement.RETURN_GENERATED_KEYS)) {
ps.setInt(1, ownerId);
ps.executeUpdate();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
map = null;
schedule = null;
}
public void closeShop(MapleClient c, boolean timeout) {
map.removeMapObject(this);
map.broadcastMessage(MaplePacketCreator.destroyHiredMerchant(ownerId));
c.getChannelServer().removeHiredMerchant(ownerId);
try {
MapleCharacter player = c.getWorldServer().getPlayerStorage().getCharacterById(ownerId);
if(player != null) {
player.setHasMerchant(false);
} else {
try (PreparedStatement ps = DatabaseConnection.getConnection().prepareStatement("UPDATE characters SET HasMerchant = 0 WHERE id = ?", Statement.RETURN_GENERATED_KEYS)) {
ps.setInt(1, ownerId);
ps.executeUpdate();
}
}
if (check(c.getPlayer(), getItems()) && !timeout) {
for (MaplePlayerShopItem mpsi : getItems()) {
if (mpsi.isExist() && (mpsi.getItem().getType() == MapleInventoryType.EQUIP.getType())) {
MapleInventoryManipulator.addFromDrop(c, mpsi.getItem(), false);
} else if (mpsi.isExist()) {
MapleInventoryManipulator.addById(c, mpsi.getItem().getItemId(), (short) (mpsi.getBundles() * mpsi.getItem().getQuantity()), null, -1, mpsi.getItem().getFlag(), mpsi.getItem().getExpiration());
}
}
items.clear();
}
try {
this.saveItems(timeout);
} catch (Exception e) {
}
items.clear();
} catch (Exception e) {
}
schedule.cancel(false);
}
public String getOwner() {
return ownerName;
}
public void clearItems() {
items.clear();
}
public int getOwnerId() {
return ownerId;
}
public String getDescription() {
return description;
}
public MapleCharacter[] getVisitors() {
return visitors;
}
public List<MaplePlayerShopItem> getItems() {
return Collections.unmodifiableList(items);
}
public void addItem(MaplePlayerShopItem item) {
items.add(item);
try {
this.saveItems(false);
} catch (SQLException ex) {
}
}
public void removeFromSlot(int slot) {
items.remove(slot);
try {
this.saveItems(false);
} catch (SQLException ex) {
}
}
public int getFreeSlot() {
for (int i = 0; i < 3; i++) {
if (visitors[i] == null) {
return i;
}
}
return -1;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isOpen() {
return open;
}
public void setOpen(boolean set) {
this.open = set;
}
public int getItemId() {
return itemId;
}
public boolean isOwner(MapleCharacter chr) {
return chr.getId() == ownerId;
}
public void saveItems(boolean shutdown) throws SQLException {
List<Pair<Item, MapleInventoryType>> itemsWithType = new ArrayList<>();
for (MaplePlayerShopItem pItems : items) {
Item newItem = pItems.getItem();
if (shutdown) {
newItem.setQuantity((short) (pItems.getItem().getQuantity() * pItems.getBundles()));
} else {
newItem.setQuantity(pItems.getItem().getQuantity());
}
if (pItems.getBundles() > 0) {
itemsWithType.add(new Pair<>(newItem, MapleInventoryType.getByType(newItem.getType())));
}
}
ItemFactory.MERCHANT.saveItems(itemsWithType, this.ownerId, DatabaseConnection.getConnection());
}
private static boolean check(MapleCharacter chr, List<MaplePlayerShopItem> items) {
byte eq = 0, use = 0, setup = 0, etc = 0, cash = 0;
List<MapleInventoryType> li = new LinkedList<>();
for (MaplePlayerShopItem item : items) {
final MapleInventoryType invtype = MapleItemInformationProvider.getInstance().getInventoryType(item.getItem().getItemId());
if (!li.contains(invtype)) {
li.add(invtype);
}
if (invtype == MapleInventoryType.EQUIP) {
eq++;
} else if (invtype == MapleInventoryType.USE) {
use++;
} else if (invtype == MapleInventoryType.SETUP) {
setup++;
} else if (invtype == MapleInventoryType.ETC) {
etc++;
} else if (invtype == MapleInventoryType.CASH) {
cash++;
}
}
for (MapleInventoryType mit : li) {
if (mit == MapleInventoryType.EQUIP) {
if (chr.getInventory(MapleInventoryType.EQUIP).getNumFreeSlot() <= eq) {
return false;
}
} else if (mit == MapleInventoryType.USE) {
if (chr.getInventory(MapleInventoryType.USE).getNumFreeSlot() <= use) {
return false;
}
} else if (mit == MapleInventoryType.SETUP) {
if (chr.getInventory(MapleInventoryType.SETUP).getNumFreeSlot() <= setup) {
return false;
}
} else if (mit == MapleInventoryType.ETC) {
if (chr.getInventory(MapleInventoryType.ETC).getNumFreeSlot() <= etc) {
return false;
}
} else if (mit == MapleInventoryType.CASH) {
if (chr.getInventory(MapleInventoryType.CASH).getNumFreeSlot() <= cash) {
return false;
}
}
}
return true;
}
public int getChannel() {
return channel;
}
public int getTimeLeft() {
return (int) ((System.currentTimeMillis() - start) / 1000);
}
public List<Pair<String, Byte>> getMessages() {
return messages;
}
public int getMapId() {
return map.getId();
}
public List<SoldItem> getSold() {
return sold;
}
public int getMesos() {
return mesos;
}
@Override
public void sendDestroyData(MapleClient client) {
}
@Override
public MapleMapObjectType getType() {
return MapleMapObjectType.HIRED_MERCHANT;
}
@Override
public void sendSpawnData(MapleClient client) {
client.announce(MaplePacketCreator.spawnHiredMerchant(this));
}
public class SoldItem {
int itemid, mesos;
short quantity;
String buyer;
public SoldItem(String buyer, int itemid, short quantity, int mesos) {
this.buyer = buyer;
this.itemid = itemid;
this.quantity = quantity;
this.mesos = mesos;
}
public String getBuyer() {
return buyer;
}
public int getItemId() {
return itemid;
}
public short getQuantity() {
return quantity;
}
public int getMesos() {
return mesos;
}
}
}

View File

@@ -0,0 +1,55 @@
/*
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 server.maps;
import java.util.concurrent.ScheduledFuture;
import server.MaplePortal;
import server.TimerManager;
public class MapMonitor {
private ScheduledFuture<?> monitorSchedule;
private MapleMap map;
private MaplePortal portal;
public MapMonitor(final MapleMap map, String portal) {
this.map = map;
this.portal = map.getPortal(portal);
this.monitorSchedule = TimerManager.getInstance().register(new Runnable() {
@Override
public void run() {
if (map.getCharacters().size() < 1) {
cancelAction();
}
}
}, 5000);
}
private void cancelAction() {
monitorSchedule.cancel(false);
map.killAllMonsters();
map.clearDrops();
if (portal != null) {
portal.setPortalStatus(MaplePortal.OPEN);
}
map.resetReactors();
}
}

View File

@@ -0,0 +1,157 @@
/*
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 server.maps;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import server.MaplePortal;
import tools.MaplePacketCreator;
import client.MapleCharacter;
import client.MapleClient;
/**
*
* @author Matze
*/
public class MapleDoor extends AbstractMapleMapObject {
private MapleCharacter owner;
private MapleMap town;
private MaplePortal townPortal;
private MapleMap target;
private Point targetPosition;
public MapleDoor(MapleCharacter owner, Point targetPosition) {
super();
this.owner = owner;
this.target = owner.getMap();
this.targetPosition = targetPosition;
setPosition(this.targetPosition);
this.town = this.target.getReturnMap();
this.townPortal = getFreePortal();
}
public MapleDoor(MapleDoor origDoor) {
super();
this.owner = origDoor.owner;
this.town = origDoor.town;
this.townPortal = origDoor.townPortal;
this.target = origDoor.target;
this.targetPosition = origDoor.targetPosition;
this.townPortal = origDoor.townPortal;
setPosition(this.townPortal.getPosition());
}
private MaplePortal getFreePortal() {
List<MaplePortal> freePortals = new ArrayList<MaplePortal>();
for (MaplePortal port : town.getPortals()) {
if (port.getType() == 6) {
freePortals.add(port);
}
}
Collections.sort(freePortals, new Comparator<MaplePortal>() {
public int compare(MaplePortal o1, MaplePortal o2) {
if (o1.getId() < o2.getId()) {
return -1;
} else if (o1.getId() == o2.getId()) {
return 0;
} else {
return 1;
}
}
});
for (MapleMapObject obj : town.getMapObjects()) {
if (obj instanceof MapleDoor) {
MapleDoor door = (MapleDoor) obj;
if (door.getOwner().getParty() != null && door.getOwner().getParty().containsMembers(door.getOwner().getMPC())) {
freePortals.remove(door.getTownPortal());
}
}
}
return freePortals.iterator().next();
}
@Override
public void sendSpawnData(MapleClient client) {
if (target.getId() == client.getPlayer().getMapId() || owner == client.getPlayer() && owner.getParty() == null) {
client.announce(MaplePacketCreator.spawnDoor(owner.getId(), town.getId() == client.getPlayer().getMapId() ? townPortal.getPosition() : targetPosition, true));
if (owner.getParty() != null && (owner == client.getPlayer() || owner.getParty().containsMembers(client.getPlayer().getMPC()))) {
client.announce(MaplePacketCreator.partyPortal(town.getId(), target.getId(), targetPosition));
}
}
if (owner.getId() != client.getPlayer().getId()) {
client.announce(MaplePacketCreator.spawnPortal(town.getId(), target.getId(), targetPosition));
}
}
@Override
public void sendDestroyData(MapleClient client) {
if (target.getId() == client.getPlayer().getMapId() || owner == client.getPlayer() || owner.getParty() != null && owner.getParty().containsMembers(client.getPlayer().getMPC())) {
if (owner.getParty() != null && (owner == client.getPlayer() || owner.getParty().containsMembers(client.getPlayer().getMPC()))) {
client.announce(MaplePacketCreator.partyPortal(999999999, 999999999, new Point(-1, -1)));
}
client.announce(MaplePacketCreator.removeDoor(owner.getId(), false));
client.announce(MaplePacketCreator.removeDoor(owner.getId(), true));
}
}
public void warp(MapleCharacter chr, boolean toTown) {
if (chr == owner || owner.getParty() != null && owner.getParty().containsMembers(chr.getMPC())) {
if (!toTown) {
chr.changeMap(target, targetPosition);
} else {
chr.changeMap(town, townPortal);
}
} else {
chr.getClient().announce(MaplePacketCreator.enableActions());
}
}
public MapleCharacter getOwner() {
return owner;
}
public MapleMap getTown() {
return town;
}
public MaplePortal getTownPortal() {
return townPortal;
}
public MapleMap getTarget() {
return target;
}
public Point getTargetPosition() {
return targetPosition;
}
@Override
public MapleMapObjectType getType() {
return MapleMapObjectType.DOOR;
}
}

View File

@@ -0,0 +1,65 @@
/*
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 server.maps;
import tools.MaplePacketCreator;
import client.MapleCharacter;
import client.MapleClient;
public class MapleDragon extends AbstractAnimatedMapleMapObject {
private MapleCharacter owner;
public MapleDragon(MapleCharacter chr) {
super();
this.owner = chr;
this.setPosition(chr.getPosition());
this.setStance(chr.getStance());
sendSpawnData(chr.getClient());
}
@Override
public MapleMapObjectType getType() {
return MapleMapObjectType.DRAGON;
}
@Override
public void sendSpawnData(MapleClient c) {
c.announce(MaplePacketCreator.spawnDragon(this));
}
@Override
public int getObjectId() {
return owner.getId();
}
@Override
public void sendDestroyData(MapleClient c) {
c.announce(MaplePacketCreator.removeDragon(owner.getId()));
}
public MapleCharacter getOwner() {
return owner;
}
}

View File

@@ -0,0 +1,102 @@
/*
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 server.maps;
import java.awt.Point;
/**
*
* @author Matze
*/
public class MapleFoothold implements Comparable<MapleFoothold> {
private Point p1;
private Point p2;
private int id;
private int next, prev;
public MapleFoothold(Point p1, Point p2, int id) {
this.p1 = p1;
this.p2 = p2;
this.id = id;
}
public boolean isWall() {
return p1.x == p2.x;
}
public int getX1() {
return p1.x;
}
public int getX2() {
return p2.x;
}
public int getY1() {
return p1.y;
}
public int getY2() {
return p2.y;
}
// XXX may need more precision
public int calculateFooting(int x) {
if (p1.y == p2.y) {
return p2.y; // y at both ends is the same
}
int slope = (p1.y - p2.y) / (p1.x - p2.x);
int intercept = p1.y - (slope * p1.x);
return (slope * x) + intercept;
}
public int compareTo(MapleFoothold o) {
MapleFoothold other = o;
if (p2.y < other.getY1()) {
return -1;
} else if (p1.y > other.getY2()) {
return 1;
} else {
return 0;
}
}
public int getId() {
return id;
}
public int getNext() {
return next;
}
public void setNext(int next) {
this.next = next;
}
public int getPrev() {
return prev;
}
public void setPrev(int prev) {
this.prev = prev;
}
}

View File

@@ -0,0 +1,220 @@
/*
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 server.maps;
import java.awt.Point;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
*
* @author Matze
*/
public class MapleFootholdTree {
private MapleFootholdTree nw = null;
private MapleFootholdTree ne = null;
private MapleFootholdTree sw = null;
private MapleFootholdTree se = null;
private List<MapleFoothold> footholds = new LinkedList<MapleFoothold>();
private Point p1;
private Point p2;
private Point center;
private int depth = 0;
private static int maxDepth = 8;
private int maxDropX;
private int minDropX;
public MapleFootholdTree(Point p1, Point p2) {
this.p1 = p1;
this.p2 = p2;
center = new Point((p2.x - p1.x) / 2, (p2.y - p1.y) / 2);
}
public MapleFootholdTree(Point p1, Point p2, int depth) {
this.p1 = p1;
this.p2 = p2;
this.depth = depth;
center = new Point((p2.x - p1.x) / 2, (p2.y - p1.y) / 2);
}
public void insert(MapleFoothold f) {
if (depth == 0) {
if (f.getX1() > maxDropX) {
maxDropX = f.getX1();
}
if (f.getX1() < minDropX) {
minDropX = f.getX1();
}
if (f.getX2() > maxDropX) {
maxDropX = f.getX2();
}
if (f.getX2() < minDropX) {
minDropX = f.getX2();
}
}
if (depth == maxDepth ||
(f.getX1() >= p1.x && f.getX2() <= p2.x &&
f.getY1() >= p1.y && f.getY2() <= p2.y)) {
footholds.add(f);
} else {
if (nw == null) {
nw = new MapleFootholdTree(p1, center, depth + 1);
ne = new MapleFootholdTree(new Point(center.x, p1.y), new Point(p2.x, center.y), depth + 1);
sw = new MapleFootholdTree(new Point(p1.x, center.y), new Point(center.x, p2.y), depth + 1);
se = new MapleFootholdTree(center, p2, depth + 1);
}
if (f.getX2() <= center.x && f.getY2() <= center.y) {
nw.insert(f);
} else if (f.getX1() > center.x && f.getY2() <= center.y) {
ne.insert(f);
} else if (f.getX2() <= center.x && f.getY1() > center.y) {
sw.insert(f);
} else {
se.insert(f);
}
}
}
private List<MapleFoothold> getRelevants(Point p) {
return getRelevants(p, new LinkedList<MapleFoothold>());
}
private List<MapleFoothold> getRelevants(Point p, List<MapleFoothold> list) {
list.addAll(footholds);
if (nw != null) {
if (p.x <= center.x && p.y <= center.y) {
nw.getRelevants(p, list);
} else if (p.x > center.x && p.y <= center.y) {
ne.getRelevants(p, list);
} else if (p.x <= center.x && p.y > center.y) {
sw.getRelevants(p, list);
} else {
se.getRelevants(p, list);
}
}
return list;
}
private MapleFoothold findWallR(Point p1, Point p2) {
MapleFoothold ret;
for (MapleFoothold f : footholds) {
if (f.isWall() && f.getX1() >= p1.x && f.getX1() <= p2.x &&
f.getY1() >= p1.y && f.getY2() <= p1.y) {
return f;
}
}
if (nw != null) {
if (p1.x <= center.x && p1.y <= center.y) {
ret = nw.findWallR(p1, p2);
if (ret != null) {
return ret;
}
}
if ((p1.x > center.x || p2.x > center.x) && p1.y <= center.y) {
ret = ne.findWallR(p1, p2);
if (ret != null) {
return ret;
}
}
if (p1.x <= center.x && p1.y > center.y) {
ret = sw.findWallR(p1, p2);
if (ret != null) {
return ret;
}
}
if ((p1.x > center.x || p2.x > center.x) && p1.y > center.y) {
ret = se.findWallR(p1, p2);
if (ret != null) {
return ret;
}
}
}
return null;
}
public MapleFoothold findWall(Point p1, Point p2) {
if (p1.y != p2.y) {
throw new IllegalArgumentException();
}
return findWallR(p1, p2);
}
public MapleFoothold findBelow(Point p) {
List<MapleFoothold> relevants = getRelevants(p);
List<MapleFoothold> xMatches = new LinkedList<MapleFoothold>();
for (MapleFoothold fh : relevants) {
if (fh.getX1() <= p.x && fh.getX2() >= p.x) {
xMatches.add(fh);
}
}
Collections.sort(xMatches);
for (MapleFoothold fh : xMatches) {
if (!fh.isWall() && fh.getY1() != fh.getY2()) {
int calcY;
double s1 = Math.abs(fh.getY2() - fh.getY1());
double s2 = Math.abs(fh.getX2() - fh.getX1());
double s4 = Math.abs(p.x - fh.getX1());
double alpha = Math.atan(s2 / s1);
double beta = Math.atan(s1 / s2);
double s5 = Math.cos(alpha) * (s4 / Math.cos(beta));
if (fh.getY2() < fh.getY1()) {
calcY = fh.getY1() - (int) s5;
} else {
calcY = fh.getY1() + (int) s5;
}
if (calcY >= p.y) {
return fh;
}
} else if (!fh.isWall()) {
if (fh.getY1() >= p.y) {
return fh;
}
}
}
return null;
}
public int getX1() {
return p1.x;
}
public int getX2() {
return p2.x;
}
public int getY1() {
return p1.y;
}
public int getY2() {
return p2.y;
}
public int getMaxDropX() {
return maxDropX;
}
public int getMinDropX() {
return minDropX;
}
}

View File

@@ -0,0 +1,144 @@
/*
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 server.maps;
import client.MapleClient;
import java.awt.Point;
import scripting.portal.PortalScriptManager;
import server.MaplePortal;
import tools.MaplePacketCreator;
public class MapleGenericPortal implements MaplePortal {
private String name;
private String target;
private Point position;
private int targetmap;
private int type;
private boolean status = true;
private int id;
private String scriptName;
private boolean portalState;
public MapleGenericPortal(int type) {
this.type = type;
}
@Override
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String getName() {
return name;
}
@Override
public Point getPosition() {
return position;
}
@Override
public String getTarget() {
return target;
}
@Override
public void setPortalStatus(boolean newStatus) {
this.status = newStatus;
}
@Override
public boolean getPortalStatus() {
return status;
}
@Override
public int getTargetMapId() {
return targetmap;
}
@Override
public int getType() {
return type;
}
@Override
public String getScriptName() {
return scriptName;
}
public void setName(String name) {
this.name = name;
}
public void setPosition(Point position) {
this.position = position;
}
public void setTarget(String target) {
this.target = target;
}
public void setTargetMapId(int targetmapid) {
this.targetmap = targetmapid;
}
@Override
public void setScriptName(String scriptName) {
this.scriptName = scriptName;
}
@Override
public void enterPortal(MapleClient c) {
boolean changed = false;
if (getScriptName() != null) {
changed = PortalScriptManager.getInstance().executePortalScript(this, c);
} else if (getTargetMapId() != 999999999) {
MapleMap to = c.getPlayer().getEventInstance() == null ? c.getChannelServer().getMapFactory().getMap(getTargetMapId()) : c.getPlayer().getEventInstance().getMapInstance(getTargetMapId());
MaplePortal pto = to.getPortal(getTarget());
if (pto == null) {// fallback for missing portals - no real life case anymore - intresting for not implemented areas
pto = to.getPortal(0);
}
c.getPlayer().changeMap(to, pto); //late resolving makes this harder but prevents us from loading the whole world at once
changed = true;
}
if (!changed) {
c.announce(MaplePacketCreator.enableActions());
}
}
@Override
public void setPortalState(boolean state) {
this.portalState = state;
}
@Override
public boolean getPortalState() {
return portalState;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,48 @@
/*
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 server.maps;
import client.MapleClient;
import tools.MaplePacketCreator;
public class MapleMapEffect {
private String msg;
private int itemId;
private boolean active = true;
public MapleMapEffect(String msg, int itemId) {
this.msg = msg;
this.itemId = itemId;
}
public final byte[] makeDestroyData() {
return MaplePacketCreator.removeMapEffect();
}
public final byte[] makeStartData() {
return MaplePacketCreator.startMapEffect(msg, itemId, active);
}
public void sendStartData(MapleClient client) {
client.announce(makeStartData());
}
}

View File

@@ -0,0 +1,301 @@
/*
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 server.maps;
import java.awt.Point;
import java.awt.Rectangle;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import provider.MapleData;
import provider.MapleDataProvider;
import provider.MapleDataTool;
import server.PortalFactory;
import server.life.AbstractLoadedMapleLife;
import server.life.MapleLifeFactory;
import server.life.MapleMonster;
import tools.DatabaseConnection;
import tools.StringUtil;
public class MapleMapFactory {
private MapleDataProvider source;
private MapleData nameData;
private Map<Integer, MapleMap> maps = new HashMap<>();
private int channel, world;
public MapleMapFactory(MapleDataProvider source, MapleDataProvider stringSource, int world, int channel) {
this.source = source;
this.nameData = stringSource.getData("Map.img");
this.world = world;
this.channel = channel;
}
public MapleMap getMap(int mapid) {
Integer omapid = Integer.valueOf(mapid);
MapleMap map = maps.get(omapid);
if (map == null) {
synchronized (this) {
map = maps.get(omapid);
if (map != null) {
return map;
}
String mapName = getMapName(mapid);
MapleData mapData = source.getData(mapName);
String link = MapleDataTool.getString(mapData.getChildByPath("info/link"), "");
if (!link.equals("")) { //nexon made hundreds of dojo maps so to reduce the size they added links.
mapName = getMapName(Integer.parseInt(link));
mapData = source.getData(mapName);
}
float monsterRate = 0;
MapleData mobRate = mapData.getChildByPath("info/mobRate");
if (mobRate != null) {
monsterRate = ((Float) mobRate.getData()).floatValue();
}
map = new MapleMap(mapid, world, channel, MapleDataTool.getInt("info/returnMap", mapData), monsterRate);
String onFirstEnter = MapleDataTool.getString(mapData.getChildByPath("info/onFirstUserEnter"), String.valueOf(mapid));
map.setOnFirstUserEnter(onFirstEnter.equals("") ? String.valueOf(mapid) : onFirstEnter);
String onEnter = MapleDataTool.getString(mapData.getChildByPath("info/onUserEnter"), String.valueOf(mapid));
map.setOnUserEnter(onEnter.equals("") ? String.valueOf(mapid) : onEnter);
map.setFieldLimit(MapleDataTool.getInt(mapData.getChildByPath("info/fieldLimit"), 0));
map.setMobInterval((short) MapleDataTool.getInt(mapData.getChildByPath("info/createMobInterval"), 5000));
PortalFactory portalFactory = new PortalFactory();
for (MapleData portal : mapData.getChildByPath("portal")) {
map.addPortal(portalFactory.makePortal(MapleDataTool.getInt(portal.getChildByPath("pt")), portal));
}
MapleData timeMob = mapData.getChildByPath("info/timeMob");
if (timeMob != null) {
map.timeMob(MapleDataTool.getInt(timeMob.getChildByPath("id")),
MapleDataTool.getString(timeMob.getChildByPath("message")));
}
List<MapleFoothold> allFootholds = new LinkedList<>();
Point lBound = new Point();
Point uBound = new Point();
for (MapleData footRoot : mapData.getChildByPath("foothold")) {
for (MapleData footCat : footRoot) {
for (MapleData footHold : footCat) {
int x1 = MapleDataTool.getInt(footHold.getChildByPath("x1"));
int y1 = MapleDataTool.getInt(footHold.getChildByPath("y1"));
int x2 = MapleDataTool.getInt(footHold.getChildByPath("x2"));
int y2 = MapleDataTool.getInt(footHold.getChildByPath("y2"));
MapleFoothold fh = new MapleFoothold(new Point(x1, y1), new Point(x2, y2), Integer.parseInt(footHold.getName()));
fh.setPrev(MapleDataTool.getInt(footHold.getChildByPath("prev")));
fh.setNext(MapleDataTool.getInt(footHold.getChildByPath("next")));
if (fh.getX1() < lBound.x) {
lBound.x = fh.getX1();
}
if (fh.getX2() > uBound.x) {
uBound.x = fh.getX2();
}
if (fh.getY1() < lBound.y) {
lBound.y = fh.getY1();
}
if (fh.getY2() > uBound.y) {
uBound.y = fh.getY2();
}
allFootholds.add(fh);
}
}
}
MapleFootholdTree fTree = new MapleFootholdTree(lBound, uBound);
for (MapleFoothold fh : allFootholds) {
fTree.insert(fh);
}
map.setFootholds(fTree);
if (mapData.getChildByPath("area") != null) {
for (MapleData area : mapData.getChildByPath("area")) {
int x1 = MapleDataTool.getInt(area.getChildByPath("x1"));
int y1 = MapleDataTool.getInt(area.getChildByPath("y1"));
int x2 = MapleDataTool.getInt(area.getChildByPath("x2"));
int y2 = MapleDataTool.getInt(area.getChildByPath("y2"));
map.addMapleArea(new Rectangle(x1, y1, (x2 - x1), (y2 - y1)));
}
}
try { try (PreparedStatement ps = DatabaseConnection.getConnection().prepareStatement("SELECT * FROM playernpcs WHERE map = ?")) {
ps.setInt(1, omapid);
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
map.addMapObject(new PlayerNPCs(rs));
}
}
}
} catch (Exception e) {
}
for (MapleData life : mapData.getChildByPath("life")) {
String id = MapleDataTool.getString(life.getChildByPath("id"));
String type = MapleDataTool.getString(life.getChildByPath("type"));
if (id.equals("9001105")) {
id = "9001108";//soz
}
AbstractLoadedMapleLife myLife = loadLife(life, id, type);
if (myLife instanceof MapleMonster) {
MapleMonster monster = (MapleMonster) myLife;
int mobTime = MapleDataTool.getInt("mobTime", life, 0);
int team = MapleDataTool.getInt("team", life, -1);
if (mobTime == -1) { //does not respawn, force spawn once
map.spawnMonster(monster);
} else {
map.addMonsterSpawn(monster, mobTime, team);
}
} else {
map.addMapObject(myLife);
}
}
if (mapData.getChildByPath("reactor") != null) {
for (MapleData reactor : mapData.getChildByPath("reactor")) {
String id = MapleDataTool.getString(reactor.getChildByPath("id"));
if (id != null) {
MapleReactor newReactor = loadReactor(reactor, id);
map.spawnReactor(newReactor);
}
}
}
try {
map.setMapName(MapleDataTool.getString("mapName", nameData.getChildByPath(getMapStringName(omapid)), ""));
map.setStreetName(MapleDataTool.getString("streetName", nameData.getChildByPath(getMapStringName(omapid)), ""));
} catch (Exception e) {
map.setMapName("");
map.setStreetName("");
}
map.setClock(mapData.getChildByPath("clock") != null);
map.setEverlast(mapData.getChildByPath("everlast") != null);
map.setTown(mapData.getChildByPath("info/town") != null);
map.setHPDec(MapleDataTool.getIntConvert("info/decHP", mapData, 0));
map.setHPDecProtect(MapleDataTool.getIntConvert("info/protectItem", mapData, 0));
map.setForcedReturnMap(MapleDataTool.getInt(mapData.getChildByPath("info/forcedReturn"), 999999999));
map.setBoat(mapData.getChildByPath("shipObj") != null);
map.setTimeLimit(MapleDataTool.getIntConvert("timeLimit", mapData.getChildByPath("info"), -1));
map.setFieldType(MapleDataTool.getIntConvert("info/fieldType", mapData, 0));
map.setMobCapacity(MapleDataTool.getIntConvert("fixedMobCapacity", mapData.getChildByPath("info"), 500));//Is there a map that contains more than 500 mobs?
HashMap<Integer, Integer> backTypes = new HashMap<>();
try {
for (MapleData layer : mapData.getChildByPath("back")) { // yolo
int layerNum = Integer.parseInt(layer.getName());
int type = MapleDataTool.getInt(layer.getChildByPath("type"), 0);
backTypes.put(layerNum, type);
}
} catch (Exception e) {
e.printStackTrace();
// swallow cause I'm cool
}
map.setBackgroundTypes(backTypes);
maps.put(omapid, map);
}
}
return map;
}
public boolean isMapLoaded(int mapId) {
return maps.containsKey(mapId);
}
private AbstractLoadedMapleLife loadLife(MapleData life, String id, String type) {
AbstractLoadedMapleLife myLife = MapleLifeFactory.getLife(Integer.parseInt(id), type);
myLife.setCy(MapleDataTool.getInt(life.getChildByPath("cy")));
MapleData dF = life.getChildByPath("f");
if (dF != null) {
myLife.setF(MapleDataTool.getInt(dF));
}
myLife.setFh(MapleDataTool.getInt(life.getChildByPath("fh")));
myLife.setRx0(MapleDataTool.getInt(life.getChildByPath("rx0")));
myLife.setRx1(MapleDataTool.getInt(life.getChildByPath("rx1")));
int x = MapleDataTool.getInt(life.getChildByPath("x"));
int y = MapleDataTool.getInt(life.getChildByPath("y"));
myLife.setPosition(new Point(x, y));
int hide = MapleDataTool.getInt("hide", life, 0);
if (hide == 1) {
myLife.setHide(true);
}
return myLife;
}
private MapleReactor loadReactor(MapleData reactor, String id) {
MapleReactor myReactor = new MapleReactor(MapleReactorFactory.getReactor(Integer.parseInt(id)), Integer.parseInt(id));
int x = MapleDataTool.getInt(reactor.getChildByPath("x"));
int y = MapleDataTool.getInt(reactor.getChildByPath("y"));
myReactor.setPosition(new Point(x, y));
myReactor.setDelay(MapleDataTool.getInt(reactor.getChildByPath("reactorTime")) * 1000);
myReactor.setState((byte) 0);
myReactor.setName(MapleDataTool.getString(reactor.getChildByPath("name"), ""));
return myReactor;
}
private String getMapName(int mapid) {
String mapName = StringUtil.getLeftPaddedStr(Integer.toString(mapid), '0', 9);
StringBuilder builder = new StringBuilder("Map/Map");
int area = mapid / 100000000;
builder.append(area);
builder.append("/");
builder.append(mapName);
builder.append(".img");
mapName = builder.toString();
return mapName;
}
private String getMapStringName(int mapid) {
StringBuilder builder = new StringBuilder();
if (mapid < 100000000) {
builder.append("maple");
} else if (mapid >= 100000000 && mapid < 200000000) {
builder.append("victoria");
} else if (mapid >= 200000000 && mapid < 300000000) {
builder.append("ossyria");
} else if (mapid >= 540000000 && mapid < 551030200) {
builder.append("singapore");
} else if (mapid >= 600000000 && mapid < 620000000) {
builder.append("MasteriaGL");
} else if (mapid >= 670000000 && mapid < 682000000) {
builder.append("weddingGL");
} else if (mapid >= 682000000 && mapid < 683000000) {
builder.append("HalloweenGL");
} else if (mapid >= 800000000 && mapid < 900000000) {
builder.append("jp");
} else {
builder.append("etc");
}
builder.append("/").append(mapid);
return builder.toString();
}
public void setChannel(int channel) {
this.channel = channel;
}
public void setWorld(int world) {
this.channel = world;
}
public Map<Integer, MapleMap> getMaps() {
return maps;
}
}

View File

@@ -0,0 +1,138 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 ~ 2010 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 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 server.maps;
import client.MapleCharacter;
import client.MapleClient;
import client.inventory.Item;
import java.awt.Point;
import java.util.concurrent.locks.ReentrantLock;
import tools.MaplePacketCreator;
public class MapleMapItem extends AbstractMapleMapObject {
protected Item item;
protected MapleMapObject dropper;
protected int character_ownerid, meso, questid = -1;
protected byte type;
protected boolean pickedUp = false, playerDrop;
protected long dropTime;
public ReentrantLock itemLock = new ReentrantLock();
public MapleMapItem(Item item, Point position, MapleMapObject dropper, MapleCharacter owner, byte type, boolean playerDrop) {
setPosition(position);
this.item = item;
this.dropper = dropper;
this.character_ownerid = owner.getId();
this.meso = 0;
this.type = type;
this.playerDrop = playerDrop;
}
public MapleMapItem(Item item, Point position, MapleMapObject dropper, MapleCharacter owner, byte type, boolean playerDrop, int questid) {
setPosition(position);
this.item = item;
this.dropper = dropper;
this.character_ownerid = owner.getParty() == null ? owner.getId() : owner.getPartyId();
this.meso = 0;
this.type = type;
this.playerDrop = playerDrop;
this.questid = questid;
}
public MapleMapItem(int meso, Point position, MapleMapObject dropper, MapleCharacter owner, byte type, boolean playerDrop) {
setPosition(position);
this.item = null;
this.dropper = dropper;
this.character_ownerid = owner.getParty() == null ? owner.getId() : owner.getPartyId();
this.meso = meso;
this.type = type;
this.playerDrop = playerDrop;
}
public final Item getItem() {
return item;
}
public final int getQuest() {
return questid;
}
public final int getItemId() {
if (getMeso() > 0) {
return meso;
}
return item.getItemId();
}
public final MapleMapObject getDropper() {
return dropper;
}
public final int getOwner() {
return character_ownerid;
}
public final int getMeso() {
return meso;
}
public final boolean isPlayerDrop() {
return playerDrop;
}
public final boolean isPickedUp() {
return pickedUp;
}
public void setPickedUp(final boolean pickedUp) {
this.pickedUp = pickedUp;
}
public long getDropTime() {
return dropTime;
}
public void setDropTime(long time) {
this.dropTime = time;
}
public byte getDropType() {
return type;
}
@Override
public final MapleMapObjectType getType() {
return MapleMapObjectType.ITEM;
}
@Override
public void sendSpawnData(final MapleClient client) {
if (questid <= 0 || (client.getPlayer().getQuestStatus(questid) == 1 && client.getPlayer().needQuestItem(questid, item.getItemId()))) {
client.announce(MaplePacketCreator.dropItemFromMapObject(this, null, getPosition(), (byte) 2));
}
}
@Override
public void sendDestroyData(final MapleClient client) {
client.announce(MaplePacketCreator.removeItemFromMap(getObjectId(), 1, 0));
}
}

View File

@@ -0,0 +1,36 @@
/*
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 server.maps;
import java.awt.Point;
import client.MapleClient;
public interface MapleMapObject {
public int getObjectId();
public void setObjectId(int id);
public MapleMapObjectType getType();
public Point getPosition();
public void setPosition(Point position);
public void sendSpawnData(MapleClient client);
public void sendDestroyData(MapleClient client);
public void nullifyPosition();
}

View File

@@ -0,0 +1,26 @@
/*
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 server.maps;
public enum MapleMapObjectType {
NPC, MONSTER, ITEM, PLAYER, DOOR, SUMMON, SHOP, MINI_GAME, MIST, REACTOR, HIRED_MERCHANT, PLAYER_NPC, DRAGON;
}

View File

@@ -0,0 +1,30 @@
/*
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 server.maps;
import server.MaplePortal;
public class MapleMapPortal extends MapleGenericPortal {
public MapleMapPortal() {
super(MaplePortal.MAP_PORTAL);
}
}

View File

@@ -0,0 +1,86 @@
package server.maps;
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
*
* @author SharpAceX(Alan)
*/
public enum MapleMiniDungeon {
//http://bbb.hidden-street.net/search_finder/mini%20dungeon
CAVE_OF_MUSHROOMS(105050100, 105050101, 30),
GOLEM_CASTLE_RUINS(105040304, 105040320, 34),
HILL_OF_SANDSTORMS(260020600, 260020630, 30),
HENESYS_PIG_FARM(100020000, 100020100, 30),
DRAKES_BLUE_CAVE(105090311, 105090320, 30),
DRUMMER_BUNNYS_LAIR(221023400, 221023401, 30),
THE_ROUND_TABLE_OF_KENTARUS(240020500, 240020512, 30),
THE_RESTORING_MEMORY(240040511, 240040800, 19),
NEWT_SECURED_ZONE(240040520, 240040900, 19),
PILLAGE_OF_TREASURE_ISLAND(251010402, 251010410, 30),
;
private int baseId;
private int dungeonId;
private int dungeons;
private MapleMiniDungeon(int baseId, int dungeonId, int dungeons) {
this.baseId = baseId;
this.dungeonId = dungeonId;
this.dungeons = dungeons;
}
public int getBase() {
return baseId;
}
public int getDungeonId() {
return dungeonId;
}
public int getDungeons() {
return dungeons;
}
public static boolean isDungeonMap(int map){
for (MapleMiniDungeon dungeon : MapleMiniDungeon.values()){
if (map >= dungeon.getDungeonId() && map <= dungeon.getDungeonId() + dungeon.getDungeons()){
return true;
}
}
return false;
}
public static MapleMiniDungeon getDungeon(int map){
for (MapleMiniDungeon dungeon : MapleMiniDungeon.values()){
if (map >= dungeon.getDungeonId() && map <= dungeon.getDungeonId() + dungeon.getDungeons()){
return dungeon;
}
}
return null;
}
}

View File

@@ -0,0 +1,166 @@
/*
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 server.maps;
import client.MapleCharacter;
import client.MapleClient;
import client.Skill;
import client.SkillFactory;
import java.awt.Point;
import java.awt.Rectangle;
import constants.skills.BlazeWizard;
import constants.skills.Evan;
import constants.skills.FPMage;
import constants.skills.NightWalker;
import constants.skills.Shadower;
import server.MapleStatEffect;
import server.life.MapleMonster;
import server.life.MobSkill;
import tools.MaplePacketCreator;
/**
*
* @author LaiLaiNoob
*/
public class MapleMist extends AbstractMapleMapObject {
private Rectangle mistPosition;
private MapleCharacter owner = null;
private MapleMonster mob = null;
private MapleStatEffect source;
private MobSkill skill;
private boolean isMobMist, isPoisonMist, isRecoveryMist;
private int skillDelay;
public MapleMist(Rectangle mistPosition, MapleMonster mob, MobSkill skill) {
this.mistPosition = mistPosition;
this.mob = mob;
this.skill = skill;
isMobMist = true;
isPoisonMist = true;
isRecoveryMist = false;
skillDelay = 0;
}
public MapleMist(Rectangle mistPosition, MapleCharacter owner, MapleStatEffect source) {
this.mistPosition = mistPosition;
this.owner = owner;
this.source = source;
this.skillDelay = 8;
this.isMobMist = false;
this.isRecoveryMist = false;
this.isPoisonMist = false;
switch (source.getSourceId()) {
case Evan.RECOVERY_AURA:
isRecoveryMist = true;
break;
case Shadower.SMOKE_SCREEN: // Smoke Screen
isPoisonMist = false;
break;
case FPMage.POISON_MIST: // FP mist
case BlazeWizard.FLAME_GEAR: // Flame Gear
case NightWalker.POISON_BOMB: // Poison Bomb
isPoisonMist = true;
break;
}
}
@Override
public MapleMapObjectType getType() {
return MapleMapObjectType.MIST;
}
@Override
public Point getPosition() {
return mistPosition.getLocation();
}
public Skill getSourceSkill() {
return SkillFactory.getSkill(source.getSourceId());
}
public boolean isMobMist() {
return isMobMist;
}
public boolean isPoisonMist() {
return isPoisonMist;
}
public boolean isRecoveryMist() {
return isRecoveryMist;
}
public int getSkillDelay() {
return skillDelay;
}
public MapleMonster getMobOwner() {
return mob;
}
public MapleCharacter getOwner() {
return owner;
}
public Rectangle getBox() {
return mistPosition;
}
@Override
public void setPosition(Point position) {
throw new UnsupportedOperationException();
}
public final byte[] makeDestroyData() {
return MaplePacketCreator.removeMist(getObjectId());
}
public final byte[] makeSpawnData() {
if (owner != null) {
return MaplePacketCreator.spawnMist(getObjectId(), owner.getId(), getSourceSkill().getId(), owner.getSkillLevel(SkillFactory.getSkill(source.getSourceId())), this);
}
return MaplePacketCreator.spawnMist(getObjectId(), mob.getId(), skill.getSkillId(), skill.getSkillLevel(), this);
}
public final byte[] makeFakeSpawnData(int level) {
if (owner != null) {
return MaplePacketCreator.spawnMist(getObjectId(), owner.getId(), getSourceSkill().getId(), level, this);
}
return MaplePacketCreator.spawnMist(getObjectId(), mob.getId(), skill.getSkillId(), skill.getSkillLevel(), this);
}
@Override
public void sendSpawnData(MapleClient client) {
client.announce(makeSpawnData());
}
@Override
public void sendDestroyData(MapleClient client) {
client.announce(makeDestroyData());
}
public boolean makeChanceResult() {
return source.makeChanceResult();
}
}

View File

@@ -0,0 +1,204 @@
/*
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 server.maps;
import client.MapleClient;
import constants.ServerConstants;
import java.awt.Rectangle;
import java.util.List;
import scripting.reactor.ReactorScriptManager;
import server.TimerManager;
import tools.MaplePacketCreator;
import tools.Pair;
/**
*
* @author Lerk
*/
public class MapleReactor extends AbstractMapleMapObject {
private int rid;
private MapleReactorStats stats;
private byte state;
private int delay;
private MapleMap map;
private String name;
private boolean timerActive;
private boolean alive;
public MapleReactor(MapleReactorStats stats, int rid) {
this.stats = stats;
this.rid = rid;
alive = true;
}
public void setTimerActive(boolean active) {
this.timerActive = active;
}
public boolean isTimerActive() {
return timerActive;
}
public void setState(byte state) {
this.state = state;
}
public byte getState() {
return state;
}
public int getId() {
return rid;
}
public void setDelay(int delay) {
this.delay = delay;
}
public int getDelay() {
return delay;
}
@Override
public MapleMapObjectType getType() {
return MapleMapObjectType.REACTOR;
}
public int getReactorType() {
return stats.getType(state);
}
public void setMap(MapleMap map) {
this.map = map;
}
public MapleMap getMap() {
return map;
}
public Pair<Integer, Integer> getReactItem(byte index) {
return stats.getReactItem(state, index);
}
public boolean isAlive() {
return alive;
}
public void setAlive(boolean alive) {
this.alive = alive;
}
@Override
public void sendDestroyData(MapleClient client) {
client.announce(makeDestroyData());
}
public final byte[] makeDestroyData() {
return MaplePacketCreator.destroyReactor(this);
}
@Override
public void sendSpawnData(MapleClient client) {
client.announce(makeSpawnData());
}
public final byte[] makeSpawnData() {
return MaplePacketCreator.spawnReactor(this);
}
public void forceHitReactor(final byte newState) {
setState((byte) newState);
setTimerActive(false);
map.broadcastMessage(MaplePacketCreator.triggerReactor(this, (short) 0));
}
public void delayedHitReactor(final MapleClient c, long delay) {
TimerManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
hitReactor(c);
}
}, delay);
}
public void hitReactor(MapleClient c) {
hitReactor(0, (short) 0, 0, c);
}
public synchronized void hitReactor(int charPos, short stance, int skillid, MapleClient c) {
try {
if(!this.isAlive()) {
return;
}
if(ServerConstants.USE_DEBUG == true) c.getPlayer().dropMessage(5, "Hitted REACTOR " + this.getId());
if (stats.getType(state) < 999 && stats.getType(state) != -1) {//type 2 = only hit from right (kerning swamp plants), 00 is air left 02 is ground left
if (!(stats.getType(state) == 2 && (charPos == 0 || charPos == 2))) { //get next state
for (byte b = 0; b < stats.getStateSize(state); b++) {//YAY?
List<Integer> activeSkills = stats.getActiveSkills(state, b);
if (activeSkills != null) {
if (!activeSkills.contains(skillid)) continue;
}
state = stats.getNextState(state, b);
if (stats.getNextState(state, b) == -1) {//end of reactor
if (stats.getType(state) < 100) {//reactor broken
if (delay > 0) {
map.destroyReactor(getObjectId());
} else {//trigger as normal
map.broadcastMessage(MaplePacketCreator.triggerReactor(this, stance));
}
} else {//item-triggered on final step
map.broadcastMessage(MaplePacketCreator.triggerReactor(this, stance));
}
ReactorScriptManager.getInstance().act(c, this);
} else { //reactor not broken yet
map.broadcastMessage(MaplePacketCreator.triggerReactor(this, stance));
if (state == stats.getNextState(state, b)) {//current state = next state, looping reactor
ReactorScriptManager.getInstance().act(c, this);
}
}
break;
}
}
} else {
state++;
map.broadcastMessage(MaplePacketCreator.triggerReactor(this, stance));
ReactorScriptManager.getInstance().act(c, this);
}
} catch(Exception e) {
e.printStackTrace();
}
}
public Rectangle getArea() {
return new Rectangle(getPosition().x + stats.getTL().x, getPosition().y + stats.getTL().y, stats.getBR().x - stats.getTL().x, stats.getBR().y - stats.getTL().y);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@@ -0,0 +1,112 @@
/*
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 server.maps;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import provider.MapleData;
import provider.MapleDataProvider;
import provider.MapleDataProviderFactory;
import provider.MapleDataTool;
import server.maps.MapleReactorStats.StateData;
import tools.Pair;
import tools.StringUtil;
public class MapleReactorFactory {
private static MapleDataProvider data = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Reactor.wz"));
private static Map<Integer, MapleReactorStats> reactorStats = new HashMap<Integer, MapleReactorStats>();
public static MapleReactorStats getReactor(int rid) {
MapleReactorStats stats = reactorStats.get(Integer.valueOf(rid));
if (stats == null) {
int infoId = rid;
MapleData reactorData = data.getData(StringUtil.getLeftPaddedStr(Integer.toString(infoId) + ".img", '0', 11));
MapleData link = reactorData.getChildByPath("info/link");
if (link != null) {
infoId = MapleDataTool.getIntConvert("info/link", reactorData);
stats = reactorStats.get(Integer.valueOf(infoId));
}
MapleData activateOnTouch = reactorData.getChildByPath("info/activateByTouch");
boolean loadArea = false;
if (activateOnTouch != null) {
loadArea = MapleDataTool.getInt("info/activateByTouch", reactorData, 0) != 0;
}
if (stats == null) {
reactorData = data.getData(StringUtil.getLeftPaddedStr(Integer.toString(infoId) + ".img", '0', 11));
MapleData reactorInfoData = reactorData.getChildByPath("0");
stats = new MapleReactorStats();
List<StateData> statedatas = new ArrayList<StateData>();
if (reactorInfoData != null) {
boolean areaSet = false;
byte i = 0;
while (reactorInfoData != null) {
MapleData eventData = reactorInfoData.getChildByPath("event");
if (eventData != null) {
for (MapleData fknexon : eventData.getChildren()) {
if (fknexon.getName().equals("timeOut")) continue;
Pair<Integer, Integer> reactItem = null;
int type = MapleDataTool.getIntConvert("type", fknexon);
if (type == 100) { //reactor waits for item
reactItem = new Pair<Integer, Integer>(MapleDataTool.getIntConvert("0", fknexon), MapleDataTool.getIntConvert("1", fknexon));
if (!areaSet || loadArea) { //only set area of effect for item-triggered reactors once
stats.setTL(MapleDataTool.getPoint("lt", fknexon));
stats.setBR(MapleDataTool.getPoint("rb", fknexon));
areaSet = true;
}
}
MapleData activeSkillID = fknexon.getChildByPath("activeSkillID");
List<Integer> skillids = null;
if (activeSkillID != null) {
skillids = new ArrayList<Integer>();
for (MapleData skill : activeSkillID.getChildren()) {
skillids.add(MapleDataTool.getInt(skill));
}
}
byte nextState = (byte) MapleDataTool.getIntConvert("state", fknexon);
statedatas.add(new StateData(type, reactItem, skillids, nextState));
}
stats.addState(i, statedatas);
}
i++;
reactorInfoData = reactorData.getChildByPath(Byte.toString(i));
statedatas = new ArrayList<StateData>();
}
} else //sit there and look pretty; likely a reactor such as Zakum/Papulatus doors that shows if player can enter
{
statedatas.add(new StateData(999, null, null, (byte) 0));
stats.addState((byte) 0, statedatas);
}
reactorStats.put(Integer.valueOf(infoId), stats);
if (rid != infoId) {
reactorStats.put(Integer.valueOf(rid), stats);
}
} else // stats exist at infoId but not rid; add to map
{
reactorStats.put(Integer.valueOf(rid), stats);
}
}
return stats;
}
}

View File

@@ -0,0 +1,129 @@
/*
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 server.maps;
import java.awt.Point;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import tools.Pair;
/**
* @author Lerk
*/
public class MapleReactorStats {
private Point tl;
private Point br;
private Map<Byte, List<StateData>> stateInfo = new HashMap<Byte, List<StateData>>();
public void setTL(Point tl) {
this.tl = tl;
}
public void setBR(Point br) {
this.br = br;
}
public Point getTL() {
return tl;
}
public Point getBR() {
return br;
}
public void addState(byte state, List<StateData> data) {
stateInfo.put(state, data);
}
public byte getStateSize(byte state) {
return (byte) stateInfo.get(state).size();
}
public byte getNextState(byte state, byte index) {
if (stateInfo.get(state) == null || stateInfo.get(state).size() < (index + 1)) return -1;
StateData nextState = stateInfo.get(state).get(index);
if (nextState != null) {
return nextState.getNextState();
} else {
return -1;
}
}
public List<Integer> getActiveSkills(byte state, byte index) {
StateData nextState = stateInfo.get(state).get(index);
if (nextState != null) {
return nextState.getActiveSkills();
} else {
return null;
}
}
public int getType(byte state) {
List<StateData> list = stateInfo.get(state);
if (list != null) {
return list.get(0).getType();
} else {
return -1;
}
}
public Pair<Integer, Integer> getReactItem(byte state, byte index) {
StateData nextState = stateInfo.get(state).get(index);
if (nextState != null) {
return nextState.getReactItem();
} else {
return null;
}
}
public static class StateData {
private int type;
private Pair<Integer, Integer> reactItem;
private List<Integer> activeSkills;
private byte nextState;
public StateData(int type, Pair<Integer, Integer> reactItem, List<Integer> activeSkills, byte nextState) {
this.type = type;
this.reactItem = reactItem;
this.activeSkills = activeSkills;
this.nextState = nextState;
}
private int getType() {
return type;
}
private byte getNextState() {
return nextState;
}
private Pair<Integer, Integer> getReactItem() {
return reactItem;
}
private List<Integer> getActiveSkills() {
return activeSkills;
}
}
}

View File

@@ -0,0 +1,101 @@
/*
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 server.maps;
import java.awt.Point;
import client.MapleCharacter;
import client.MapleClient;
import client.SkillFactory;
import tools.MaplePacketCreator;
/**
*
* @author Jan
*/
public class MapleSummon extends AbstractAnimatedMapleMapObject {
private MapleCharacter owner;
private byte skillLevel;
private int skill, hp;
private SummonMovementType movementType;
public MapleSummon(MapleCharacter owner, int skill, Point pos, SummonMovementType movementType) {
this.owner = owner;
this.skill = skill;
this.skillLevel = owner.getSkillLevel(SkillFactory.getSkill(skill));
if (skillLevel == 0) throw new RuntimeException();
this.movementType = movementType;
setPosition(pos);
}
public void sendSpawnData(MapleClient client) {
if (this != null) client.announce(MaplePacketCreator.spawnSummon(this, false));
}
public void sendDestroyData(MapleClient client) {
client.announce(MaplePacketCreator.removeSummon(this, true));
}
public MapleCharacter getOwner() {
return owner;
}
public int getSkill() {
return skill;
}
public int getHP() {
return hp;
}
public void addHP(int delta) {
this.hp += delta;
}
public SummonMovementType getMovementType() {
return movementType;
}
public boolean isStationary() {
return (skill == 3111002 || skill == 3211002 || skill == 5211001 || skill == 13111004);
}
public byte getSkillLevel() {
return skillLevel;
}
@Override
public MapleMapObjectType getType() {
return MapleMapObjectType.SUMMON;
}
public final boolean isPuppet() {
switch (skill) {
case 3111002:
case 3211002:
case 13111004:
return true;
}
return false;
}
}

View File

@@ -0,0 +1,78 @@
/*
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 server.maps;
import client.MapleCharacter;
import java.util.ArrayList;
import java.util.List;
import net.server.Server;
import server.TimerManager;
import tools.MaplePacketCreator;
/*
* MapleTVEffect
* @author MrXotic
*/
public class MapleTVEffect {
private static boolean ACTIVE;
private List<String> message = new ArrayList<>(5);
private MapleCharacter user;
private int type;
private MapleCharacter partner;
public MapleTVEffect(MapleCharacter u, MapleCharacter p, List<String> msg, int t) {
this.message = msg;
this.user = u;
this.type = t;
this.partner = p;
broadcastTV(true);
}
public static boolean isActive(){
return ACTIVE;
}
private void broadcastTV(boolean activity) {
Server server = Server.getInstance();
ACTIVE = activity;
if (ACTIVE) {
server.broadcastMessage(MaplePacketCreator.enableTV());
server.broadcastMessage(MaplePacketCreator.sendTV(user, message, type <= 2 ? type : type - 3, partner));
int delay = 15000;
if (type == 4) {
delay = 30000;
} else if (type == 5) {
delay = 60000;
}
TimerManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
broadcastTV(false);
}
}, delay);
} else {
server.broadcastMessage(MaplePacketCreator.removeTV());
}
}
}

View File

@@ -0,0 +1,124 @@
/*
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 server.maps;
import java.awt.Point;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.HashMap;
import java.util.Map;
import client.MapleClient;
import java.sql.SQLException;
import tools.DatabaseConnection;
import tools.MaplePacketCreator;
/**
*
* @author XoticStory
*/
public class PlayerNPCs extends AbstractMapleMapObject {
private Map<Short, Integer> equips = new HashMap<Short, Integer>();
private int npcId, face, hair;
private byte skin;
private String name = "";
private int FH, RX0, RX1, CY;
public PlayerNPCs(ResultSet rs) {
try {
CY = rs.getInt("cy");
name = rs.getString("name");
hair = rs.getInt("hair");
face = rs.getInt("face");
skin = rs.getByte("skin");
FH = rs.getInt("Foothold");
RX0 = rs.getInt("rx0");
RX1 = rs.getInt("rx1");
npcId = rs.getInt("ScriptId");
setPosition(new Point(rs.getInt("x"), CY));
PreparedStatement ps = DatabaseConnection.getConnection().prepareStatement("SELECT equippos, equipid FROM playernpcs_equip WHERE NpcId = ?");
ps.setInt(1, rs.getInt("id"));
ResultSet rs2 = ps.executeQuery();
while (rs2.next()) {
equips.put(rs2.getShort("equippos"), rs2.getInt("equipid"));
}
rs2.close();
ps.close();
} catch (SQLException e) {
}
}
public Map<Short, Integer> getEquips() {
return equips;
}
public int getId() {
return npcId;
}
public int getFH() {
return FH;
}
public int getRX0() {
return RX0;
}
public int getRX1() {
return RX1;
}
public int getCY() {
return CY;
}
public byte getSkin() {
return skin;
}
public String getName() {
return name;
}
public int getFace() {
return face;
}
public int getHair() {
return hair;
}
@Override
public void sendDestroyData(MapleClient client) {
return;
}
@Override
public MapleMapObjectType getType() {
return MapleMapObjectType.PLAYER_NPC;
}
@Override
public void sendSpawnData(MapleClient client) {
client.announce(MaplePacketCreator.spawnPlayerNPC(this));
client.announce(MaplePacketCreator.getPlayerNPC(this));
}
}

View File

@@ -0,0 +1,32 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 ~ 2010 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 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 server.maps;
public class ReactorDropEntry {
public ReactorDropEntry(int itemId, int chance, int questId) {
this.itemId = itemId;
this.chance = chance;
this.questid = questId;
}
public int itemId, chance, questid;
public int assignedRangeStart, assignedRangeLength;
}

View File

@@ -0,0 +1,39 @@
/*
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 server.maps;
public class SavedLocation {
private int mapid = 102000000, portal;
public SavedLocation(int mapid, int portal) {
this.mapid = mapid;
this.portal = portal;
}
public int getMapId() {
return mapid;
}
public int getPortal() {
return portal;
}
}

View File

@@ -0,0 +1,37 @@
/*
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 server.maps;
public enum SavedLocationType {
FREE_MARKET,
EVENT,
WORLDTOUR,
FLORINA,
INTRO,
SUNDAY_MARKET,
MIRROR,
DOJO;
public static SavedLocationType fromString(String Str) {
return valueOf(Str);
}
}

View File

@@ -0,0 +1,35 @@
/*
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 server.maps;
public enum SummonMovementType {
STATIONARY(0), FOLLOW(1), CIRCLE_FOLLOW(3);
private final int val;
private SummonMovementType(int val) {
this.val = val;
}
public int getValue() {
return val;
}
}

View File

@@ -0,0 +1,62 @@
/*
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 server.movement;
import java.awt.Point;
import tools.data.output.LittleEndianWriter;
public class AbsoluteLifeMovement extends AbstractLifeMovement {
private Point pixelsPerSecond;
private int unk;
public AbsoluteLifeMovement(int type, Point position, int duration, int newstate) {
super(type, position, duration, newstate);
}
public Point getPixelsPerSecond() {
return pixelsPerSecond;
}
public void setPixelsPerSecond(Point wobble) {
this.pixelsPerSecond = wobble;
}
public int getUnk() {
return unk;
}
public void setUnk(int unk) {
this.unk = unk;
}
@Override
public void serialize(LittleEndianWriter lew) {
lew.write(getType());
lew.writeShort(getPosition().x);
lew.writeShort(getPosition().y);
lew.writeShort(pixelsPerSecond.x);
lew.writeShort(pixelsPerSecond.y);
lew.writeShort(unk);
lew.write(getNewstate());
lew.writeShort(getDuration());
}
}

View File

@@ -0,0 +1,58 @@
/*
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 server.movement;
import java.awt.Point;
public abstract class AbstractLifeMovement implements LifeMovement {
private Point position;
private int duration;
private int newstate, type;
public AbstractLifeMovement(int type, Point position, int duration, int newstate) {
super();
this.type = type;
this.position = position;
this.duration = duration;
this.newstate = newstate;
}
@Override
public int getType() {
return this.type;
}
@Override
public int getDuration() {
return duration;
}
@Override
public int getNewstate() {
return newstate;
}
@Override
public Point getPosition() {
return position;
}
}

View File

@@ -0,0 +1,52 @@
/*
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 server.movement;
import java.awt.Point;
import tools.data.output.LittleEndianWriter;
public class ChairMovement extends AbstractLifeMovement {
private int unk;
public ChairMovement(int type, Point position, int duration, int newstate) {
super(type, position, duration, newstate);
}
public int getUnk() {
return unk;
}
public void setUnk(int unk) {
this.unk = unk;
}
@Override
public void serialize(LittleEndianWriter lew) {
lew.write(getType());
lew.writeShort(getPosition().x);
lew.writeShort(getPosition().y);
lew.writeShort(unk);
lew.write(getNewstate());
lew.writeShort(getDuration());
}
}

View File

@@ -0,0 +1,44 @@
/*
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 server.movement;
import java.awt.Point;
import tools.data.output.LittleEndianWriter;
public class ChangeEquip implements LifeMovementFragment {
private int wui;
public ChangeEquip(int wui) {
this.wui = wui;
}
@Override
public void serialize(LittleEndianWriter lew) {
lew.write(10);
lew.write(wui);
}
@Override
public Point getPosition() {
return new Point(0, 0);
}
}

View File

@@ -0,0 +1,72 @@
/*
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 server.movement;
import java.awt.Point;
import tools.data.output.LittleEndianWriter;
public class JumpDownMovement extends AbstractLifeMovement {
private Point pixelsPerSecond;
private int unk;
private int fh;
public JumpDownMovement(int type, Point position, int duration, int newstate) {
super(type, position, duration, newstate);
}
public Point getPixelsPerSecond() {
return pixelsPerSecond;
}
public void setPixelsPerSecond(Point wobble) {
this.pixelsPerSecond = wobble;
}
public int getUnk() {
return unk;
}
public void setUnk(int unk) {
this.unk = unk;
}
public int getFH() {
return fh;
}
public void setFH(int fh) {
this.fh = fh;
}
@Override
public void serialize(LittleEndianWriter lew) {
lew.write(getType());
lew.writeShort(getPosition().x);
lew.writeShort(getPosition().y);
lew.writeShort(pixelsPerSecond.x);
lew.writeShort(pixelsPerSecond.y);
lew.writeShort(unk);
lew.writeShort(fh);
lew.write(getNewstate());
lew.writeShort(getDuration());
}
}

View File

@@ -0,0 +1,31 @@
/*
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 server.movement;
import java.awt.Point;
public interface LifeMovement extends LifeMovementFragment {
Point getPosition();
int getNewstate();
int getDuration();
int getType();
}

View File

@@ -0,0 +1,30 @@
/*
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 server.movement;
import java.awt.Point;
import tools.data.output.LittleEndianWriter;
public interface LifeMovementFragment {
void serialize(LittleEndianWriter lew);
Point getPosition();
}

View File

@@ -0,0 +1,40 @@
/*
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 server.movement;
import java.awt.Point;
import tools.data.output.LittleEndianWriter;
public class RelativeLifeMovement extends AbstractLifeMovement {
public RelativeLifeMovement(int type, Point position, int duration, int newstate) {
super(type, position, duration, newstate);
}
@Override
public void serialize(LittleEndianWriter lew) {
lew.write(getType());
lew.writeShort(getPosition().x);
lew.writeShort(getPosition().y);
lew.write(getNewstate());
lew.writeShort(getDuration());
}
}

View File

@@ -0,0 +1,41 @@
/*
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 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 server.movement;
import java.awt.Point;
import tools.data.output.LittleEndianWriter;
public class TeleportMovement extends AbsoluteLifeMovement {
public TeleportMovement(int type, Point position, int newstate) {
super(type, position, 0, newstate);
}
@Override
public void serialize(LittleEndianWriter lew) {
lew.write(getType());
lew.writeShort(getPosition().x);
lew.writeShort(getPosition().y);
lew.writeShort(getPixelsPerSecond().x);
lew.writeShort(getPixelsPerSecond().y);
lew.write(getNewstate());
}
}

View File

@@ -0,0 +1,172 @@
/*
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 server.partyquest;
import client.MapleCharacter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.concurrent.ScheduledFuture;
import server.TimerManager;
import server.maps.MapleMap;
import tools.DatabaseConnection;
import tools.MaplePacketCreator;
/**
*
* @author kevintjuh93 - LOST MOTIVATION >=(
*/
public class MonsterCarnival {
private MonsterCarnivalParty red, blue;
private MapleMap map;
private int room;
private long time = 0;
private long timeStarted = 0;
private ScheduledFuture<?> schedule = null;
public MonsterCarnival(int room, byte channel, MonsterCarnivalParty red1, MonsterCarnivalParty blue1) {
//this.map = Channel.getInstance(channel).getMapFactory().getMap(980000001 + (room * 100));
this.room = room;
this.red = red1;
this.blue = blue1;
this.timeStarted = System.currentTimeMillis();
this.time = 600000;
map.broadcastMessage(MaplePacketCreator.getClock((int) (time / 1000)));
for (MapleCharacter chr : red.getMembers())
chr.setCarnival(this);
for (MapleCharacter chr : blue.getMembers())
chr.setCarnival(this);
this.schedule = TimerManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
if (red.getTotalCP() > blue.getTotalCP()) {
red.setWinner(true);
blue.setWinner(false);
red.displayMatchResult();
blue.displayMatchResult();
} else if (blue.getTotalCP() > red.getTotalCP()) {
red.setWinner(false);
blue.setWinner(true);
red.displayMatchResult();
blue.displayMatchResult();
} else {
red.setWinner(false);
blue.setWinner(false);
red.displayMatchResult();
blue.displayMatchResult();
}
saveResults();
warpOut();
}
}, time);
/* if (room == 0) {
MapleData data = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Map.wz")).getData("Map/Map9" + (980000001 + (room * 100)) + ".img").getChildByPath("monsterCarnival");
if (data != null) {
for (MapleData p : data.getChildByPath("mobGenPos").getChildren()) {
MapleData team = p.getChildByPath("team");
if (team != null) {
if (team.getData().equals(0))
redmonsterpoints.add(new Point(MapleDataTool.getInt(p.getChildByPath("x")), MapleDataTool.getInt(p.getChildByPath("y"))));
else
bluemonsterpoints.add(new Point(MapleDataTool.getInt(p.getChildByPath("x")), MapleDataTool.getInt(p.getChildByPath("y"))));
} else
monsterpoints.add(new Point(MapleDataTool.getInt(p.getChildByPath("x")), MapleDataTool.getInt(p.getChildByPath("y"))));
}
for (MapleData p : data.getChildByPath("guardianGenPos").getChildren()) {
MapleData team = p.getChildByPath("team");
if (team != null) {
if (team.getData().equals(0))
redreactorpoints.add(new Point(MapleDataTool.getInt(p.getChildByPath("x")), MapleDataTool.getInt(p.getChildByPath("y"))));
else
bluereactorpoints.add(new Point(MapleDataTool.getInt(p.getChildByPath("x")), MapleDataTool.getInt(p.getChildByPath("y"))));
} else
reactorpoints.add(new Point(MapleDataTool.getInt(p.getChildByPath("x")), MapleDataTool.getInt(p.getChildByPath("y"))));
}
}
} */
}
public long getTimeLeft() {
return time - (System.currentTimeMillis() - timeStarted);
}
public MonsterCarnivalParty getPartyRed() {
return red;
}
public MonsterCarnivalParty getPartyBlue() {
return blue;
}
public MonsterCarnivalParty oppositeTeam(MonsterCarnivalParty team) {
if (team == red)
return blue;
else
return red;
}
public void playerLeft(MapleCharacter chr) {
map.broadcastMessage(chr, MaplePacketCreator.leaveCPQ(chr));
}
private void warpOut() {
this.schedule = TimerManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
red.warpOut();
blue.warpOut();
}
}, 12000);
}
public int getRoom() {
return room;
}
public void saveResults() {
Connection con = DatabaseConnection.getConnection();
try {
PreparedStatement ps = con.prepareStatement("INSERT INTO carnivalresults VALUES (?,?,?,?)");
for (MapleCharacter chr : red.getMembers()) {
ps.setInt(1, chr.getId());
ps.setInt(2, chr.getCP());
ps.setInt(3, red.getTotalCP());
ps.setInt(4, red.isWinner() ? 1 : 0);
ps.execute();
}
for (MapleCharacter chr : blue.getMembers()) {
ps.setInt(1, chr.getId());
ps.setInt(2, chr.getCP());
ps.setInt(3, blue.getTotalCP());
ps.setInt(4, blue.isWinner() ? 1 : 0);
ps.execute();
}
ps.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}

Some files were not shown because too many files have changed in this diff Show More