Merge branch 'refs/heads/master' into feat/postgresql-database
# Conflicts: # config.yaml # docker-compose.yml # pom.xml # src/main/java/client/Character.java # src/main/java/client/Client.java # src/main/java/client/MonsterBook.java # src/main/java/client/command/commands/gm0/BuyBackCommand.java # src/main/java/client/processor/stat/AssignAPProcessor.java # src/main/java/config/ServerConfig.java # src/main/java/net/server/channel/Channel.java # src/main/java/net/server/channel/handlers/AbstractDealDamageHandler.java # src/main/java/net/server/channel/handlers/BuddylistModifyHandler.java # src/main/java/net/server/channel/handlers/CloseRangeDamageHandler.java # src/main/java/net/server/channel/handlers/EnterMTSHandler.java # src/main/java/net/server/channel/handlers/NPCTalkHandler.java # src/main/java/net/server/channel/handlers/RangedAttackHandler.java # src/main/java/net/server/channel/handlers/SummonDamageHandler.java # src/main/java/net/server/channel/handlers/UseCashItemHandler.java # src/main/java/net/server/handlers/login/CreateCharHandler.java # src/main/java/net/server/world/World.java # src/main/java/scripting/npc/NPCConversationManager.java # src/main/java/server/ItemInformationProvider.java # src/main/java/server/life/Monster.java # src/main/java/server/life/MonsterInformationProvider.java # src/main/java/server/maps/MapleMap.java # src/main/java/tools/PacketCreator.java # src/test/java/service/NoteServiceTest.java # src/test/java/testutil/Any.java
This commit is contained in:
@@ -31,7 +31,12 @@ import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
|
||||
public class BuddyList {
|
||||
public enum BuddyOperation {
|
||||
|
||||
+137
-205
@@ -24,8 +24,17 @@ package client;
|
||||
|
||||
import client.autoban.AutobanManager;
|
||||
import client.creator.CharacterFactoryRecipe;
|
||||
import client.inventory.*;
|
||||
import client.inventory.Equip;
|
||||
import client.inventory.Equip.StatUpgrade;
|
||||
import client.inventory.Inventory;
|
||||
import client.inventory.InventoryProof;
|
||||
import client.inventory.InventoryType;
|
||||
import client.inventory.Item;
|
||||
import client.inventory.ItemFactory;
|
||||
import client.inventory.ModifyInventory;
|
||||
import client.inventory.Pet;
|
||||
import client.inventory.PetDataFactory;
|
||||
import client.inventory.WeaponType;
|
||||
import client.inventory.manipulator.CashIdGenerator;
|
||||
import client.inventory.manipulator.InventoryManipulator;
|
||||
import client.keybind.KeyBinding;
|
||||
@@ -40,7 +49,35 @@ import constants.id.ItemId;
|
||||
import constants.id.MapId;
|
||||
import constants.id.MobId;
|
||||
import constants.inventory.ItemConstants;
|
||||
import constants.skills.*;
|
||||
import constants.skills.Aran;
|
||||
import constants.skills.Beginner;
|
||||
import constants.skills.Bishop;
|
||||
import constants.skills.BlazeWizard;
|
||||
import constants.skills.Bowmaster;
|
||||
import constants.skills.Brawler;
|
||||
import constants.skills.Buccaneer;
|
||||
import constants.skills.Corsair;
|
||||
import constants.skills.Crusader;
|
||||
import constants.skills.DarkKnight;
|
||||
import constants.skills.DawnWarrior;
|
||||
import constants.skills.Evan;
|
||||
import constants.skills.FPArchMage;
|
||||
import constants.skills.Hermit;
|
||||
import constants.skills.Hero;
|
||||
import constants.skills.ILArchMage;
|
||||
import constants.skills.Legend;
|
||||
import constants.skills.Magician;
|
||||
import constants.skills.Marauder;
|
||||
import constants.skills.Marksman;
|
||||
import constants.skills.NightLord;
|
||||
import constants.skills.Noblesse;
|
||||
import constants.skills.Paladin;
|
||||
import constants.skills.Priest;
|
||||
import constants.skills.Ranger;
|
||||
import constants.skills.Shadower;
|
||||
import constants.skills.Sniper;
|
||||
import constants.skills.ThunderBreaker;
|
||||
import constants.skills.Warrior;
|
||||
import model.CharacterIdentity;
|
||||
import net.netty.GameViolationException;
|
||||
import net.packet.Packet;
|
||||
@@ -52,22 +89,59 @@ import net.server.guild.Alliance;
|
||||
import net.server.guild.Guild;
|
||||
import net.server.guild.GuildCharacter;
|
||||
import net.server.guild.GuildPackets;
|
||||
import net.server.world.*;
|
||||
import net.server.world.Messenger;
|
||||
import net.server.world.MessengerCharacter;
|
||||
import net.server.world.Party;
|
||||
import net.server.world.PartyCharacter;
|
||||
import net.server.world.PartyOperation;
|
||||
import net.server.world.World;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import scripting.AbstractPlayerInteraction;
|
||||
import scripting.event.EventInstanceManager;
|
||||
import scripting.item.ItemScriptManager;
|
||||
import server.*;
|
||||
import server.CashShop;
|
||||
import server.ExpLogger;
|
||||
import server.ExpLogger.ExpLogRecord;
|
||||
import server.ItemInformationProvider;
|
||||
import server.ItemInformationProvider.ScriptedItem;
|
||||
import server.Marriage;
|
||||
import server.StatEffect;
|
||||
import server.Storage;
|
||||
import server.ThreadManager;
|
||||
import server.TimerManager;
|
||||
import server.Trade;
|
||||
import server.events.Events;
|
||||
import server.events.RescueGaga;
|
||||
import server.events.gm.Fitness;
|
||||
import server.events.gm.Ola;
|
||||
import server.life.*;
|
||||
import server.maps.*;
|
||||
import server.life.BanishInfo;
|
||||
import server.life.MobSkill;
|
||||
import server.life.MobSkillFactory;
|
||||
import server.life.MobSkillId;
|
||||
import server.life.MobSkillType;
|
||||
import server.life.Monster;
|
||||
import server.life.PlayerNPC;
|
||||
import server.maps.AbstractAnimatedMapObject;
|
||||
import server.maps.Door;
|
||||
import server.maps.DoorObject;
|
||||
import server.maps.Dragon;
|
||||
import server.maps.FieldLimit;
|
||||
import server.maps.HiredMerchant;
|
||||
import server.maps.MapEffect;
|
||||
import server.maps.MapItem;
|
||||
import server.maps.MapManager;
|
||||
import server.maps.MapObject;
|
||||
import server.maps.MapObjectType;
|
||||
import server.maps.MapleMap;
|
||||
import server.maps.MiniGame;
|
||||
import server.maps.MiniGame.MiniGameResult;
|
||||
import server.maps.PlayerShop;
|
||||
import server.maps.PlayerShopItem;
|
||||
import server.maps.Portal;
|
||||
import server.maps.SavedLocation;
|
||||
import server.maps.SavedLocationType;
|
||||
import server.maps.Summon;
|
||||
import server.minigame.RockPaperScissor;
|
||||
import server.partyquest.AriantColiseum;
|
||||
import server.partyquest.MonsterCarnival;
|
||||
@@ -75,17 +149,38 @@ import server.partyquest.MonsterCarnivalParty;
|
||||
import server.partyquest.PartyQuest;
|
||||
import server.quest.Quest;
|
||||
import server.shop.Shop;
|
||||
import tools.*;
|
||||
import tools.exceptions.NotEnabledException;
|
||||
import tools.DatabaseConnection;
|
||||
import tools.LongTool;
|
||||
import tools.PacketCreator;
|
||||
import tools.Pair;
|
||||
import tools.Randomizer;
|
||||
import tools.packets.WeddingPackets;
|
||||
|
||||
import java.awt.*;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.sql.*;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.EnumMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
@@ -95,7 +190,9 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.*;
|
||||
import static java.util.concurrent.TimeUnit.DAYS;
|
||||
import static java.util.concurrent.TimeUnit.MINUTES;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
public class Character extends AbstractCharacterObject {
|
||||
private static final Logger log = LoggerFactory.getLogger(Character.class);
|
||||
@@ -129,7 +226,7 @@ public class Character extends AbstractCharacterObject {
|
||||
private int expRate = 1, mesoRate = 1, dropRate = 1, expCoupon = 1, mesoCoupon = 1, dropCoupon = 1;
|
||||
private int omokwins, omokties, omoklosses, matchcardwins, matchcardties, matchcardlosses;
|
||||
private int owlSearch;
|
||||
private long lastfametime, lastUsedCashItem, lastExpression = 0, lastHealed, lastBuyback = 0, lastDeathtime, jailExpiration = -1;
|
||||
private long lastfametime, lastUsedCashItem, lastExpression = 0, lastHealed, lastDeathtime, jailExpiration = -1;
|
||||
private transient int localstr, localdex, localluk, localint_, localmagic, localwatk;
|
||||
private transient int equipmaxhp, equipmaxmp, equipstr, equipdex, equipluk, equipint_, equipmagic, equipwatk, localchairhp, localchairmp;
|
||||
private int localchairrate;
|
||||
@@ -255,9 +352,6 @@ public class Character extends AbstractCharacterObject {
|
||||
private int targetHpBarHash = 0;
|
||||
private long targetHpBarTime = 0;
|
||||
private long nextWarningTime = 0;
|
||||
private int banishMap = -1;
|
||||
private int banishSp = -1;
|
||||
private long banishTime = 0;
|
||||
private long lastExpGainTime;
|
||||
private boolean pendingNameChange; //only used to change name on logout, not to be relied upon elsewhere
|
||||
private long loginTime;
|
||||
@@ -1259,48 +1353,14 @@ public class Character extends AbstractCharacterObject {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canRecoverLastBanish() {
|
||||
return System.currentTimeMillis() - this.banishTime < MINUTES.toMillis(5);
|
||||
}
|
||||
|
||||
public Pair<Integer, Integer> getLastBanishData() {
|
||||
return new Pair<>(this.banishMap, this.banishSp);
|
||||
}
|
||||
|
||||
public void clearBanishPlayerData() {
|
||||
this.banishMap = -1;
|
||||
this.banishSp = -1;
|
||||
this.banishTime = 0;
|
||||
}
|
||||
|
||||
public void setBanishPlayerData(int banishMap, int banishSp, long banishTime) {
|
||||
this.banishMap = banishMap;
|
||||
this.banishSp = banishSp;
|
||||
this.banishTime = banishTime;
|
||||
}
|
||||
|
||||
public void changeMapBanish(int mapid, String portal, String msg) {
|
||||
if (YamlConfig.config.server.USE_SPIKES_AVOID_BANISH) {
|
||||
for (Item it : this.getInventory(InventoryType.EQUIPPED).list()) {
|
||||
if ((it.getFlag() & ItemConstants.SPIKES) == ItemConstants.SPIKES) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int banMap = this.getMapId();
|
||||
int banSp = this.getMap().findClosestPlayerSpawnpoint(this.getPosition()).getId();
|
||||
long banTime = System.currentTimeMillis();
|
||||
|
||||
if (msg != null) {
|
||||
dropMessage(5, msg);
|
||||
public void changeMapBanish(BanishInfo banishInfo) {
|
||||
if (banishInfo.msg() != null) {
|
||||
dropMessage(5, banishInfo.msg());
|
||||
}
|
||||
|
||||
MapleMap map_ = getWarpMap(mapid);
|
||||
Portal portal_ = map_.getPortal(portal);
|
||||
Portal portal_ = map_.getPortal(banishInfo.portal());
|
||||
changeMap(map_, portal_ != null ? portal_ : map_.getRandomPlayerSpawnpoint());
|
||||
|
||||
setBanishPlayerData(banMap, banSp, banTime);
|
||||
}
|
||||
|
||||
public void changeMap(int map) {
|
||||
@@ -1684,7 +1744,6 @@ public class Character extends AbstractCharacterObject {
|
||||
this.mapTransitioning.set(true);
|
||||
|
||||
this.unregisterChairBuff();
|
||||
this.clearBanishPlayerData();
|
||||
Trade.cancelTrade(this, Trade.TradeResult.UNSUCCESSFUL_ANOTHER_MAP);
|
||||
this.closePlayerInteractions();
|
||||
|
||||
@@ -1972,7 +2031,7 @@ public class Character extends AbstractCharacterObject {
|
||||
this.getCashShop().gainCash(1, nxGain);
|
||||
|
||||
if (YamlConfig.config.server.USE_ANNOUNCE_NX_COUPON_LOOT) {
|
||||
showHint("You have earned #e#b" + nxGain + " NX#k#n. (" + this.getCashShop().getCash(1) + " NX)", 300);
|
||||
showHint("You have earned #e#b" + nxGain + " NX#k#n. (" + this.getCashShop().getCash(CashShop.NX_CREDIT) + " NX)", 300);
|
||||
}
|
||||
|
||||
this.getMap().pickItemDrop(pickupPacket, mapitem);
|
||||
@@ -2024,7 +2083,7 @@ public class Character extends AbstractCharacterObject {
|
||||
this.getCashShop().gainCash(1, nxGain);
|
||||
|
||||
if (YamlConfig.config.server.USE_ANNOUNCE_NX_COUPON_LOOT) {
|
||||
showHint("You have earned #e#b" + nxGain + " NX#k#n. (" + this.getCashShop().getCash(1) + " NX)", 300);
|
||||
showHint("You have earned #e#b" + nxGain + " NX#k#n. (" + this.getCashShop().getCash(CashShop.NX_CREDIT) + " NX)", 300);
|
||||
}
|
||||
} else if (applyConsumeOnPickup(mItem.getItemId())) {
|
||||
} else if (InventoryManipulator.addFromDrop(client, mItem, true)) {
|
||||
@@ -5967,7 +6026,8 @@ public class Character extends AbstractCharacterObject {
|
||||
sendPacket(PacketCreator.giveBuff(energybar, 0, stat));
|
||||
sendPacket(PacketCreator.showOwnBuffEffect(energycharge.getId(), 2));
|
||||
getMap().broadcastPacket(this, PacketCreator.showBuffEffect(id, energycharge.getId(), 2));
|
||||
getMap().broadcastPacket(this, PacketCreator.giveForeignBuff(energybar, stat));
|
||||
getMap().broadcastPacket(this, PacketCreator.giveForeignPirateBuff(id, energycharge.getId(),
|
||||
ceffect.getDuration(), stat));
|
||||
}
|
||||
if (energybar >= 10000 && energybar < 11000) {
|
||||
energybar = 15000;
|
||||
@@ -6056,65 +6116,6 @@ public class Character extends AbstractCharacterObject {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canBuyback(int fee, boolean usingMesos) {
|
||||
return (usingMesos ? this.getMeso() : cashshop.getCash(1)) >= fee;
|
||||
}
|
||||
|
||||
private void applyBuybackFee(int fee, boolean usingMesos) {
|
||||
if (usingMesos) {
|
||||
this.gainMeso(-fee);
|
||||
} else {
|
||||
cashshop.gainCash(1, -fee);
|
||||
}
|
||||
}
|
||||
|
||||
private long getNextBuybackTime() {
|
||||
return lastBuyback + MINUTES.toMillis(YamlConfig.config.server.BUYBACK_COOLDOWN_MINUTES);
|
||||
}
|
||||
|
||||
private boolean isBuybackInvincible() {
|
||||
return Server.getInstance().getCurrentTime() - lastBuyback < 4200;
|
||||
}
|
||||
|
||||
private int getBuybackFee() {
|
||||
float fee = YamlConfig.config.server.BUYBACK_FEE;
|
||||
int grade = Math.min(Math.max(level, 30), 120) - 30;
|
||||
|
||||
fee += (grade * YamlConfig.config.server.BUYBACK_LEVEL_STACK_FEE);
|
||||
if (YamlConfig.config.server.USE_BUYBACK_WITH_MESOS) {
|
||||
fee *= YamlConfig.config.server.BUYBACK_MESO_MULTIPLIER;
|
||||
}
|
||||
|
||||
return (int) Math.floor(fee);
|
||||
}
|
||||
|
||||
public void showBuybackInfo() {
|
||||
String s = "#eBUYBACK STATUS#n\r\n\r\nCurrent buyback fee: #b" + getBuybackFee() + " " + (YamlConfig.config.server.USE_BUYBACK_WITH_MESOS ? "mesos" : "NX") + "#k\r\n\r\n";
|
||||
|
||||
long timeNow = Server.getInstance().getCurrentTime();
|
||||
boolean avail = true;
|
||||
if (!isAlive()) {
|
||||
long timeLapsed = timeNow - lastDeathtime;
|
||||
long timeRemaining = MINUTES.toMillis(YamlConfig.config.server.BUYBACK_RETURN_MINUTES) - (timeLapsed + Math.max(0, getNextBuybackTime() - timeNow));
|
||||
if (timeRemaining < 1) {
|
||||
s += "Buyback #e#rUNAVAILABLE#k#n";
|
||||
avail = false;
|
||||
} else {
|
||||
s += "Buyback countdown: #e#b" + getTimeRemaining(MINUTES.toMillis(YamlConfig.config.server.BUYBACK_RETURN_MINUTES) - timeLapsed) + "#k#n";
|
||||
}
|
||||
s += "\r\n";
|
||||
}
|
||||
|
||||
if (timeNow < getNextBuybackTime() && avail) {
|
||||
s += "Buyback available in #r" + getTimeRemaining(getNextBuybackTime() - timeNow) + "#k";
|
||||
s += "\r\n";
|
||||
} else {
|
||||
s += "Buyback #bavailable#k";
|
||||
}
|
||||
|
||||
this.showHint(s);
|
||||
}
|
||||
|
||||
private static String getTimeRemaining(long timeLeft) {
|
||||
int seconds = (int) Math.floor(timeLeft / SECONDS.toMillis(1)) % 60;
|
||||
int minutes = (int) Math.floor(timeLeft / MINUTES.toMillis(1)) % 60;
|
||||
@@ -6122,34 +6123,6 @@ public class Character extends AbstractCharacterObject {
|
||||
return (minutes > 0 ? (String.format("%02d", minutes) + " minutes, ") : "") + String.format("%02d", seconds) + " seconds";
|
||||
}
|
||||
|
||||
public boolean couldBuyback() { // Ronan's buyback system
|
||||
long timeNow = Server.getInstance().getCurrentTime();
|
||||
|
||||
if (timeNow - lastDeathtime > MINUTES.toMillis(YamlConfig.config.server.BUYBACK_RETURN_MINUTES)) {
|
||||
this.dropMessage(5, "The period of time to decide has expired, therefore you are unable to buyback.");
|
||||
return false;
|
||||
}
|
||||
|
||||
long nextBuybacktime = getNextBuybackTime();
|
||||
if (timeNow < nextBuybacktime) {
|
||||
long timeLeft = nextBuybacktime - timeNow;
|
||||
this.dropMessage(5, "Next buyback available in " + getTimeRemaining(timeLeft) + ".");
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean usingMesos = YamlConfig.config.server.USE_BUYBACK_WITH_MESOS;
|
||||
int fee = getBuybackFee();
|
||||
|
||||
if (!canBuyback(fee, usingMesos)) {
|
||||
this.dropMessage(5, "You don't have " + fee + " " + (usingMesos ? "mesos" : "NX") + " to buyback.");
|
||||
return false;
|
||||
}
|
||||
|
||||
lastBuyback = timeNow;
|
||||
applyBuybackFee(fee, usingMesos);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isBuffFrom(BuffStat stat, Skill skill) {
|
||||
effLock.lock();
|
||||
chrLock.lock();
|
||||
@@ -8878,11 +8851,7 @@ public class Character extends AbstractCharacterObject {
|
||||
boolean playerDied = false;
|
||||
if (hp <= 0) {
|
||||
if (oldHp > hp) {
|
||||
if (!isBuybackInvincible()) {
|
||||
playerDied = true;
|
||||
} else {
|
||||
hp = 1;
|
||||
}
|
||||
playerDied = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10913,70 +10882,33 @@ public class Character extends AbstractCharacterObject {
|
||||
this.commandtext = text;
|
||||
}
|
||||
|
||||
public void setReborns(int value) {
|
||||
if (!YamlConfig.config.server.USE_REBIRTH_SYSTEM) {
|
||||
yellowMessage("Rebirth system is not enabled!");
|
||||
throw new NotEnabledException();
|
||||
}
|
||||
|
||||
public int getRewardPoints() {
|
||||
try (Connection con = DatabaseConnection.getConnection();
|
||||
PreparedStatement ps = con.prepareStatement("UPDATE characters SET reborns=? WHERE id=?;")) {
|
||||
PreparedStatement ps = con.prepareStatement("SELECT rewardpoints FROM accounts WHERE id=?;")) {
|
||||
ps.setInt(1, accountid);
|
||||
ResultSet resultSet = ps.executeQuery();
|
||||
int point = -1;
|
||||
if (resultSet.next()) {
|
||||
point = resultSet.getInt(1);
|
||||
}
|
||||
return point;
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void setRewardPoints(int value) {
|
||||
try (Connection con = DatabaseConnection.getConnection();
|
||||
PreparedStatement ps = con.prepareStatement("UPDATE accounts SET rewardpoints=? WHERE id=?;")) {
|
||||
ps.setInt(1, value);
|
||||
ps.setInt(2, id);
|
||||
ps.setInt(2, accountid);
|
||||
ps.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void addReborns() {
|
||||
setReborns(getReborns() + 1);
|
||||
}
|
||||
|
||||
public int getReborns() {
|
||||
if (!YamlConfig.config.server.USE_REBIRTH_SYSTEM) {
|
||||
yellowMessage("Rebirth system is not enabled!");
|
||||
throw new NotEnabledException();
|
||||
}
|
||||
|
||||
try (Connection con = DatabaseConnection.getConnection();
|
||||
PreparedStatement ps = con.prepareStatement("SELECT reborns FROM characters WHERE id=?;")) {
|
||||
ps.setInt(1, id);
|
||||
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
rs.next();
|
||||
return rs.getInt(1);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
public void executeReborn() {
|
||||
// default to beginner: job id = 0
|
||||
// this prevents a breaking change
|
||||
executeRebornAs(Job.BEGINNER);
|
||||
}
|
||||
|
||||
public void executeRebornAsId(int jobId) {
|
||||
executeRebornAs(Job.getById(jobId));
|
||||
}
|
||||
|
||||
public void executeRebornAs(Job job) {
|
||||
if (!YamlConfig.config.server.USE_REBIRTH_SYSTEM) {
|
||||
yellowMessage("Rebirth system is not enabled!");
|
||||
throw new NotEnabledException();
|
||||
}
|
||||
if (getLevel() != getMaxClassLevel()) {
|
||||
return;
|
||||
}
|
||||
addReborns();
|
||||
changeJob(job);
|
||||
setLevel(0);
|
||||
levelUp(true);
|
||||
}
|
||||
|
||||
//EVENTS
|
||||
private byte team = 0;
|
||||
private Fitness fitness;
|
||||
|
||||
@@ -44,7 +44,11 @@ import net.server.coordinator.session.SessionCoordinator.AntiMulticlientResult;
|
||||
import net.server.guild.Guild;
|
||||
import net.server.guild.GuildCharacter;
|
||||
import net.server.guild.GuildPackets;
|
||||
import net.server.world.*;
|
||||
import net.server.world.MessengerCharacter;
|
||||
import net.server.world.Party;
|
||||
import net.server.world.PartyCharacter;
|
||||
import net.server.world.PartyOperation;
|
||||
import net.server.world.World;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import scripting.AbstractPlayerInteraction;
|
||||
@@ -69,8 +73,23 @@ import java.net.InetSocketAddress;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.sql.*;
|
||||
import java.util.*;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@@ -7,9 +7,9 @@ import tools.PacketCreator;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Map;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -24,7 +24,11 @@ package client;
|
||||
import server.quest.Quest;
|
||||
import tools.StringUtil;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Matze
|
||||
|
||||
@@ -21,8 +21,63 @@
|
||||
*/
|
||||
package client;
|
||||
|
||||
import constants.skills.*;
|
||||
import provider.*;
|
||||
import constants.skills.Aran;
|
||||
import constants.skills.Archer;
|
||||
import constants.skills.Assassin;
|
||||
import constants.skills.Bandit;
|
||||
import constants.skills.Beginner;
|
||||
import constants.skills.Bishop;
|
||||
import constants.skills.BlazeWizard;
|
||||
import constants.skills.Bowmaster;
|
||||
import constants.skills.Buccaneer;
|
||||
import constants.skills.ChiefBandit;
|
||||
import constants.skills.Cleric;
|
||||
import constants.skills.Corsair;
|
||||
import constants.skills.Crossbowman;
|
||||
import constants.skills.Crusader;
|
||||
import constants.skills.DarkKnight;
|
||||
import constants.skills.DawnWarrior;
|
||||
import constants.skills.DragonKnight;
|
||||
import constants.skills.Evan;
|
||||
import constants.skills.FPArchMage;
|
||||
import constants.skills.FPMage;
|
||||
import constants.skills.FPWizard;
|
||||
import constants.skills.Fighter;
|
||||
import constants.skills.GM;
|
||||
import constants.skills.Gunslinger;
|
||||
import constants.skills.Hermit;
|
||||
import constants.skills.Hero;
|
||||
import constants.skills.Hunter;
|
||||
import constants.skills.ILArchMage;
|
||||
import constants.skills.ILMage;
|
||||
import constants.skills.ILWizard;
|
||||
import constants.skills.Legend;
|
||||
import constants.skills.Magician;
|
||||
import constants.skills.Marauder;
|
||||
import constants.skills.Marksman;
|
||||
import constants.skills.NightLord;
|
||||
import constants.skills.NightWalker;
|
||||
import constants.skills.Noblesse;
|
||||
import constants.skills.Page;
|
||||
import constants.skills.Paladin;
|
||||
import constants.skills.Pirate;
|
||||
import constants.skills.Priest;
|
||||
import constants.skills.Ranger;
|
||||
import constants.skills.Rogue;
|
||||
import constants.skills.Shadower;
|
||||
import constants.skills.Sniper;
|
||||
import constants.skills.Spearman;
|
||||
import constants.skills.SuperGM;
|
||||
import constants.skills.ThunderBreaker;
|
||||
import constants.skills.Warrior;
|
||||
import constants.skills.WhiteKnight;
|
||||
import constants.skills.WindArcher;
|
||||
import provider.Data;
|
||||
import provider.DataDirectoryEntry;
|
||||
import provider.DataFileEntry;
|
||||
import provider.DataProvider;
|
||||
import provider.DataProviderFactory;
|
||||
import provider.DataTool;
|
||||
import provider.wz.WZFiles;
|
||||
import server.StatEffect;
|
||||
import server.life.Element;
|
||||
|
||||
@@ -24,13 +24,177 @@
|
||||
package client.command;
|
||||
|
||||
import client.Client;
|
||||
import client.command.commands.gm0.*;
|
||||
import client.command.commands.gm1.*;
|
||||
import client.command.commands.gm2.*;
|
||||
import client.command.commands.gm3.*;
|
||||
import client.command.commands.gm4.*;
|
||||
import client.command.commands.gm5.*;
|
||||
import client.command.commands.gm6.*;
|
||||
import client.command.commands.gm0.ChangeLanguageCommand;
|
||||
import client.command.commands.gm0.DisposeCommand;
|
||||
import client.command.commands.gm0.DropLimitCommand;
|
||||
import client.command.commands.gm0.EnableAuthCommand;
|
||||
import client.command.commands.gm0.EquipLvCommand;
|
||||
import client.command.commands.gm0.GachaCommand;
|
||||
import client.command.commands.gm0.GmCommand;
|
||||
import client.command.commands.gm0.HelpCommand;
|
||||
import client.command.commands.gm0.JoinEventCommand;
|
||||
import client.command.commands.gm0.LeaveEventCommand;
|
||||
import client.command.commands.gm0.MapOwnerClaimCommand;
|
||||
import client.command.commands.gm0.OnlineCommand;
|
||||
import client.command.commands.gm0.RanksCommand;
|
||||
import client.command.commands.gm0.RatesCommand;
|
||||
import client.command.commands.gm0.ReportBugCommand;
|
||||
import client.command.commands.gm0.ShowRatesCommand;
|
||||
import client.command.commands.gm0.StaffCommand;
|
||||
import client.command.commands.gm0.StatDexCommand;
|
||||
import client.command.commands.gm0.StatIntCommand;
|
||||
import client.command.commands.gm0.StatLukCommand;
|
||||
import client.command.commands.gm0.StatStrCommand;
|
||||
import client.command.commands.gm0.TimeCommand;
|
||||
import client.command.commands.gm0.ToggleExpCommand;
|
||||
import client.command.commands.gm0.UptimeCommand;
|
||||
import client.command.commands.gm1.BossHpCommand;
|
||||
import client.command.commands.gm1.BuffMeCommand;
|
||||
import client.command.commands.gm1.GotoCommand;
|
||||
import client.command.commands.gm1.MobHpCommand;
|
||||
import client.command.commands.gm1.WhatDropsFromCommand;
|
||||
import client.command.commands.gm1.WhoDropsCommand;
|
||||
import client.command.commands.gm2.ApCommand;
|
||||
import client.command.commands.gm2.BombCommand;
|
||||
import client.command.commands.gm2.BuffCommand;
|
||||
import client.command.commands.gm2.BuffMapCommand;
|
||||
import client.command.commands.gm2.ClearDropsCommand;
|
||||
import client.command.commands.gm2.ClearSavedLocationsCommand;
|
||||
import client.command.commands.gm2.ClearSlotCommand;
|
||||
import client.command.commands.gm2.DcCommand;
|
||||
import client.command.commands.gm2.EmpowerMeCommand;
|
||||
import client.command.commands.gm2.GachaListCommand;
|
||||
import client.command.commands.gm2.GmShopCommand;
|
||||
import client.command.commands.gm2.HealCommand;
|
||||
import client.command.commands.gm2.HideCommand;
|
||||
import client.command.commands.gm2.IdCommand;
|
||||
import client.command.commands.gm2.ItemCommand;
|
||||
import client.command.commands.gm2.ItemDropCommand;
|
||||
import client.command.commands.gm2.JailCommand;
|
||||
import client.command.commands.gm2.JobCommand;
|
||||
import client.command.commands.gm2.LevelCommand;
|
||||
import client.command.commands.gm2.LevelProCommand;
|
||||
import client.command.commands.gm2.LootCommand;
|
||||
import client.command.commands.gm2.MaxSkillCommand;
|
||||
import client.command.commands.gm2.MaxStatCommand;
|
||||
import client.command.commands.gm2.MobSkillCommand;
|
||||
import client.command.commands.gm2.ReachCommand;
|
||||
import client.command.commands.gm2.RechargeCommand;
|
||||
import client.command.commands.gm2.ResetSkillCommand;
|
||||
import client.command.commands.gm2.SearchCommand;
|
||||
import client.command.commands.gm2.SetSlotCommand;
|
||||
import client.command.commands.gm2.SetStatCommand;
|
||||
import client.command.commands.gm2.SpCommand;
|
||||
import client.command.commands.gm2.SummonCommand;
|
||||
import client.command.commands.gm2.UnBugCommand;
|
||||
import client.command.commands.gm2.UnHideCommand;
|
||||
import client.command.commands.gm2.UnJailCommand;
|
||||
import client.command.commands.gm2.WarpAreaCommand;
|
||||
import client.command.commands.gm2.WarpCommand;
|
||||
import client.command.commands.gm2.WarpMapCommand;
|
||||
import client.command.commands.gm2.WhereaMiCommand;
|
||||
import client.command.commands.gm3.BanCommand;
|
||||
import client.command.commands.gm3.ChatCommand;
|
||||
import client.command.commands.gm3.CheckDmgCommand;
|
||||
import client.command.commands.gm3.ClosePortalCommand;
|
||||
import client.command.commands.gm3.DebuffCommand;
|
||||
import client.command.commands.gm3.EndEventCommand;
|
||||
import client.command.commands.gm3.ExpedsCommand;
|
||||
import client.command.commands.gm3.FaceCommand;
|
||||
import client.command.commands.gm3.FameCommand;
|
||||
import client.command.commands.gm3.FlyCommand;
|
||||
import client.command.commands.gm3.GiveMesosCommand;
|
||||
import client.command.commands.gm3.GiveNxCommand;
|
||||
import client.command.commands.gm3.HairCommand;
|
||||
import client.command.commands.gm3.HealMapCommand;
|
||||
import client.command.commands.gm3.HealPersonCommand;
|
||||
import client.command.commands.gm3.HpMpCommand;
|
||||
import client.command.commands.gm3.HurtCommand;
|
||||
import client.command.commands.gm3.IgnoreCommand;
|
||||
import client.command.commands.gm3.IgnoredCommand;
|
||||
import client.command.commands.gm3.InMapCommand;
|
||||
import client.command.commands.gm3.KillAllCommand;
|
||||
import client.command.commands.gm3.KillCommand;
|
||||
import client.command.commands.gm3.KillMapCommand;
|
||||
import client.command.commands.gm3.MaxEnergyCommand;
|
||||
import client.command.commands.gm3.MaxHpMpCommand;
|
||||
import client.command.commands.gm3.MonitorCommand;
|
||||
import client.command.commands.gm3.MonitorsCommand;
|
||||
import client.command.commands.gm3.MusicCommand;
|
||||
import client.command.commands.gm3.MuteMapCommand;
|
||||
import client.command.commands.gm3.NightCommand;
|
||||
import client.command.commands.gm3.NoticeCommand;
|
||||
import client.command.commands.gm3.NpcCommand;
|
||||
import client.command.commands.gm3.OnlineTwoCommand;
|
||||
import client.command.commands.gm3.OpenPortalCommand;
|
||||
import client.command.commands.gm3.PeCommand;
|
||||
import client.command.commands.gm3.PosCommand;
|
||||
import client.command.commands.gm3.QuestCompleteCommand;
|
||||
import client.command.commands.gm3.QuestResetCommand;
|
||||
import client.command.commands.gm3.QuestStartCommand;
|
||||
import client.command.commands.gm3.ReloadDropsCommand;
|
||||
import client.command.commands.gm3.ReloadEventsCommand;
|
||||
import client.command.commands.gm3.ReloadMapCommand;
|
||||
import client.command.commands.gm3.ReloadPortalsCommand;
|
||||
import client.command.commands.gm3.ReloadShopsCommand;
|
||||
import client.command.commands.gm3.RipCommand;
|
||||
import client.command.commands.gm3.SeedCommand;
|
||||
import client.command.commands.gm3.SpawnCommand;
|
||||
import client.command.commands.gm3.StartEventCommand;
|
||||
import client.command.commands.gm3.StartMapEventCommand;
|
||||
import client.command.commands.gm3.StopMapEventCommand;
|
||||
import client.command.commands.gm3.TimerAllCommand;
|
||||
import client.command.commands.gm3.TimerCommand;
|
||||
import client.command.commands.gm3.TimerMapCommand;
|
||||
import client.command.commands.gm3.ToggleCouponCommand;
|
||||
import client.command.commands.gm3.UnBanCommand;
|
||||
import client.command.commands.gm4.BossDropRateCommand;
|
||||
import client.command.commands.gm4.CakeCommand;
|
||||
import client.command.commands.gm4.DropRateCommand;
|
||||
import client.command.commands.gm4.ExpRateCommand;
|
||||
import client.command.commands.gm4.FishingRateCommand;
|
||||
import client.command.commands.gm4.ForceVacCommand;
|
||||
import client.command.commands.gm4.HorntailCommand;
|
||||
import client.command.commands.gm4.ItemVacCommand;
|
||||
import client.command.commands.gm4.MesoRateCommand;
|
||||
import client.command.commands.gm4.PapCommand;
|
||||
import client.command.commands.gm4.PianusCommand;
|
||||
import client.command.commands.gm4.PinkbeanCommand;
|
||||
import client.command.commands.gm4.PlayerNpcCommand;
|
||||
import client.command.commands.gm4.PlayerNpcRemoveCommand;
|
||||
import client.command.commands.gm4.PmobCommand;
|
||||
import client.command.commands.gm4.PmobRemoveCommand;
|
||||
import client.command.commands.gm4.PnpcCommand;
|
||||
import client.command.commands.gm4.PnpcRemoveCommand;
|
||||
import client.command.commands.gm4.ProItemCommand;
|
||||
import client.command.commands.gm4.QuestRateCommand;
|
||||
import client.command.commands.gm4.ServerMessageCommand;
|
||||
import client.command.commands.gm4.SetEqStatCommand;
|
||||
import client.command.commands.gm4.TravelRateCommand;
|
||||
import client.command.commands.gm4.ZakumCommand;
|
||||
import client.command.commands.gm5.DebugCommand;
|
||||
import client.command.commands.gm5.IpListCommand;
|
||||
import client.command.commands.gm5.SetCommand;
|
||||
import client.command.commands.gm5.ShowMoveLifeCommand;
|
||||
import client.command.commands.gm5.ShowPacketsCommand;
|
||||
import client.command.commands.gm5.ShowSessionsCommand;
|
||||
import client.command.commands.gm6.ClearQuestCacheCommand;
|
||||
import client.command.commands.gm6.ClearQuestCommand;
|
||||
import client.command.commands.gm6.DCAllCommand;
|
||||
import client.command.commands.gm6.DevtestCommand;
|
||||
import client.command.commands.gm6.EraseAllPNpcsCommand;
|
||||
import client.command.commands.gm6.GetAccCommand;
|
||||
import client.command.commands.gm6.MapPlayersCommand;
|
||||
import client.command.commands.gm6.SaveAllCommand;
|
||||
import client.command.commands.gm6.ServerAddChannelCommand;
|
||||
import client.command.commands.gm6.ServerAddWorldCommand;
|
||||
import client.command.commands.gm6.ServerRemoveChannelCommand;
|
||||
import client.command.commands.gm6.ServerRemoveWorldCommand;
|
||||
import client.command.commands.gm6.SetGmLevelCommand;
|
||||
import client.command.commands.gm6.ShutdownCommand;
|
||||
import client.command.commands.gm6.SpawnAllPNpcsCommand;
|
||||
import client.command.commands.gm6.SupplyRateCouponCommand;
|
||||
import client.command.commands.gm6.WarpWorldCommand;
|
||||
import constants.id.MapId;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -178,7 +342,6 @@ public class CommandsExecutor {
|
||||
addCommand("droplimit", DropLimitCommand.class);
|
||||
addCommand("time", TimeCommand.class);
|
||||
addCommand("credits", StaffCommand.class);
|
||||
addCommand("buyback", BuyBackCommand.class);
|
||||
addCommand("uptime", UptimeCommand.class);
|
||||
addCommand("gacha", GachaCommand.class);
|
||||
addCommand("dispose", DisposeCommand.class);
|
||||
@@ -389,6 +552,7 @@ public class CommandsExecutor {
|
||||
addCommand("addworld", 6, ServerAddWorldCommand.class);
|
||||
addCommand("removechannel", 6, ServerRemoveChannelCommand.class);
|
||||
addCommand("removeworld", 6, ServerRemoveWorldCommand.class);
|
||||
addCommand("devtest", 6, DevtestCommand.class);
|
||||
|
||||
commandsNameDesc.add(levelCommandsCursor);
|
||||
}
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
|
||||
Copyleft (L) 2016 - 2019 RonanLana
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
@Author: Arthur L - Refactored command content into modules
|
||||
*/
|
||||
package client.command.commands.gm0;
|
||||
|
||||
import client.Client;
|
||||
import client.command.Command;
|
||||
import client.command.CommandContext;
|
||||
import client.processor.action.BuybackProcessor;
|
||||
|
||||
public class BuyBackCommand extends Command {
|
||||
{
|
||||
setDescription("Revive yourself after a death.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Client c, String[] params, CommandContext ctx) {
|
||||
if (params.length < 1) {
|
||||
c.getPlayer().yellowMessage("Syntax: @buyback <info|now>");
|
||||
return;
|
||||
}
|
||||
|
||||
if (params[0].contentEquals("now")) {
|
||||
BuybackProcessor.processBuyback(c);
|
||||
} else {
|
||||
c.getPlayer().showBuybackInfo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,10 @@ import client.command.Command;
|
||||
import client.command.CommandContext;
|
||||
import net.server.Server;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.*;
|
||||
import static java.util.concurrent.TimeUnit.DAYS;
|
||||
import static java.util.concurrent.TimeUnit.HOURS;
|
||||
import static java.util.concurrent.TimeUnit.MINUTES;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
public class UptimeCommand extends Command {
|
||||
{
|
||||
|
||||
@@ -29,7 +29,11 @@ import client.command.Command;
|
||||
import client.command.CommandContext;
|
||||
import constants.game.GameConstants;
|
||||
import constants.id.NpcId;
|
||||
import server.maps.*;
|
||||
import server.maps.FieldLimit;
|
||||
import server.maps.MapFactory;
|
||||
import server.maps.MapleMap;
|
||||
import server.maps.MiniDungeonInfo;
|
||||
import server.maps.Portal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
@@ -12,7 +12,11 @@ import tools.exceptions.IdTypeNotSupportedException;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
package client.command.commands.gm2;
|
||||
|
||||
import client.Character;
|
||||
import client.*;
|
||||
import client.Client;
|
||||
import client.Job;
|
||||
import client.Skill;
|
||||
import client.SkillFactory;
|
||||
import client.command.Command;
|
||||
import client.command.CommandContext;
|
||||
import provider.Data;
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
package client.command.commands.gm2;
|
||||
|
||||
import client.Character;
|
||||
import client.*;
|
||||
import client.Client;
|
||||
import client.Job;
|
||||
import client.Skill;
|
||||
import client.SkillFactory;
|
||||
import client.command.Command;
|
||||
import client.command.CommandContext;
|
||||
import provider.Data;
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package client.command.commands.gm6;
|
||||
|
||||
import client.Client;
|
||||
import client.command.Command;
|
||||
import client.command.CommandContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import scripting.AbstractScriptManager;
|
||||
|
||||
import javax.script.Invocable;
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptException;
|
||||
|
||||
public class DevtestCommand extends Command {
|
||||
{
|
||||
setDescription("Runs devtest.js. Developer utility - test stuff without restarting the server.");
|
||||
}
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(DevtestCommand.class);
|
||||
|
||||
private static class DevtestScriptManager extends AbstractScriptManager {
|
||||
|
||||
@Override
|
||||
public ScriptEngine getInvocableScriptEngine(String path) {
|
||||
return super.getInvocableScriptEngine(path);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Client client, String[] params, CommandContext context) {
|
||||
DevtestScriptManager scriptManager = new DevtestScriptManager();
|
||||
ScriptEngine scriptEngine = scriptManager.getInvocableScriptEngine("devtest.js");
|
||||
try {
|
||||
Invocable invocable = (Invocable) scriptEngine;
|
||||
invocable.invokeFunction("run", client.getPlayer());
|
||||
} catch (ScriptException | NoSuchMethodException e) {
|
||||
log.info("devtest.js run() threw an exception", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,10 @@ import net.server.Server;
|
||||
import net.server.world.World;
|
||||
import server.TimerManager;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.*;
|
||||
import static java.util.concurrent.TimeUnit.DAYS;
|
||||
import static java.util.concurrent.TimeUnit.HOURS;
|
||||
import static java.util.concurrent.TimeUnit.MINUTES;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
public class ShutdownCommand extends Command {
|
||||
{
|
||||
|
||||
@@ -47,19 +47,19 @@ public abstract class CharacterFactory {
|
||||
return -1;
|
||||
}
|
||||
|
||||
Character newchar = Character.getDefault(c);
|
||||
newchar.setWorld(c.getWorld());
|
||||
newchar.setSkinColor(SkinColor.getById(skin));
|
||||
newchar.setGender(gender);
|
||||
newchar.setName(name);
|
||||
newchar.setHair(hair);
|
||||
newchar.setFace(face);
|
||||
Character newCharacter = Character.getDefault(c);
|
||||
newCharacter.setWorld(c.getWorld());
|
||||
newCharacter.setSkinColor(SkinColor.getById(skin));
|
||||
newCharacter.setGender(gender);
|
||||
newCharacter.setName(name);
|
||||
newCharacter.setHair(hair);
|
||||
newCharacter.setFace(face);
|
||||
|
||||
newchar.setLevel(recipe.getLevel());
|
||||
newchar.setJob(recipe.getJob());
|
||||
newchar.setMapId(recipe.getMap());
|
||||
newCharacter.setLevel(recipe.getLevel());
|
||||
newCharacter.setJob(recipe.getJob());
|
||||
newCharacter.setMapId(recipe.getMap());
|
||||
|
||||
Inventory equipped = newchar.getInventory(InventoryType.EQUIPPED);
|
||||
Inventory equipped = newCharacter.getInventory(InventoryType.EQUIPPED);
|
||||
ItemInformationProvider ii = ItemInformationProvider.getInstance();
|
||||
|
||||
int top = recipe.getTop(), bottom = recipe.getBottom(), shoes = recipe.getShoes(), weapon = recipe.getWeapon();
|
||||
@@ -88,12 +88,17 @@ public abstract class CharacterFactory {
|
||||
equipped.addItemFromDB(eq_weapon.copy());
|
||||
}
|
||||
|
||||
if (!newchar.insertNewChar(recipe)) {
|
||||
if (!MakeCharInfoValidator.isNewCharacterValid(newCharacter)) {
|
||||
log.warn("Owner from account {} tried to packet edit in character creation", c.getAccountName());
|
||||
return -2;
|
||||
}
|
||||
c.sendPacket(PacketCreator.addNewCharEntry(newchar));
|
||||
|
||||
Server.getInstance().createCharacterEntry(newchar);
|
||||
if (!newCharacter.insertNewChar(recipe)) {
|
||||
return -2;
|
||||
}
|
||||
c.sendPacket(PacketCreator.addNewCharEntry(newCharacter));
|
||||
|
||||
Server.getInstance().createCharacterEntry(newCharacter);
|
||||
Server.getInstance().broadcastGMMessage(c.getWorld(), PacketCreator.sendYellowTip("[New Char]: " + c.getAccountName() + " has created a new character with IGN " + name));
|
||||
log.info("Account {} created chr with name {}", c.getAccountName(), name);
|
||||
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
package client.creator;
|
||||
|
||||
import client.Character;
|
||||
import client.Job;
|
||||
import client.inventory.InventoryType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import provider.Data;
|
||||
import provider.DataTool;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class MakeCharInfo {
|
||||
private static final Logger log = LoggerFactory.getLogger(MakeCharInfo.class);
|
||||
private static final String FACE_ID = "0";
|
||||
private static final String HAIR_ID = "1";
|
||||
private static final String HAIR_COLOR_ID = "2";
|
||||
private static final String SKIN_ID = "3";
|
||||
private static final String TOP_ID = "4";
|
||||
private static final String BOTTOM_ID = "5";
|
||||
private static final String SHOE_ID = "6";
|
||||
private static final String WEAPON_ID = "7";
|
||||
|
||||
private final Set<Integer> charFaces = new HashSet<>();
|
||||
private final Set<Integer> charHairs = new HashSet<>();
|
||||
private final Set<Integer> charHairColors = new HashSet<>();
|
||||
private final Set<Integer> charSkins = new HashSet<>();
|
||||
private final Set<Integer> charTops = new HashSet<>();
|
||||
private final Set<Integer> charBottoms = new HashSet<>();
|
||||
private final Set<Integer> charShoes = new HashSet<>();
|
||||
private final Set<Integer> charWeapons = new HashSet<>();
|
||||
|
||||
public MakeCharInfo(Data charInfoData) {
|
||||
for (Data data : charInfoData.getChildren()) {
|
||||
switch (data.getName()) {
|
||||
case FACE_ID -> {
|
||||
for (Data faceData : data) {
|
||||
charFaces.add(DataTool.getInt(faceData));
|
||||
}
|
||||
}
|
||||
case HAIR_ID -> {
|
||||
for (Data hairData : data) {
|
||||
charHairs.add(DataTool.getInt(hairData));
|
||||
}
|
||||
}
|
||||
case HAIR_COLOR_ID -> {
|
||||
for (Data hairColorData : data) {
|
||||
charHairColors.add(DataTool.getInt(hairColorData));
|
||||
}
|
||||
}
|
||||
case SKIN_ID -> {
|
||||
for (Data skinData : data) {
|
||||
charSkins.add(DataTool.getInt(skinData));
|
||||
}
|
||||
}
|
||||
case TOP_ID -> {
|
||||
for (Data topData : data) {
|
||||
charTops.add(DataTool.getInt(topData));
|
||||
}
|
||||
}
|
||||
case BOTTOM_ID -> {
|
||||
for (Data bottomData : data) {
|
||||
charBottoms.add(DataTool.getInt(bottomData));
|
||||
}
|
||||
}
|
||||
case SHOE_ID -> {
|
||||
for (Data shoeData : data) {
|
||||
charShoes.add(DataTool.getInt(shoeData));
|
||||
}
|
||||
}
|
||||
case WEAPON_ID -> {
|
||||
for (Data weaponData : data) {
|
||||
charWeapons.add(DataTool.getInt(weaponData));
|
||||
}
|
||||
}
|
||||
default -> log.error("Unhandled node inside MakeCharInfo.img.xml: '" + data.getName() + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean verifyFaceId(int id) {
|
||||
return this.charFaces.contains(id);
|
||||
}
|
||||
|
||||
public boolean verifyHairId(int id) {
|
||||
if (id % 10 != 0) {
|
||||
return this.charHairs.contains(id - (id % 10));
|
||||
}
|
||||
return this.charHairs.contains(id);
|
||||
}
|
||||
|
||||
public boolean verifyHairColorId(int id) {
|
||||
return this.charHairColors.contains(id % 10);
|
||||
}
|
||||
|
||||
public boolean verifySkinId(int id) {
|
||||
return this.charSkins.contains(id);
|
||||
}
|
||||
|
||||
public boolean verifyTopId(int id) {
|
||||
return this.charTops.contains(id);
|
||||
}
|
||||
|
||||
public boolean verifyBottomId(int id) {
|
||||
return this.charBottoms.contains(id);
|
||||
}
|
||||
|
||||
public boolean verifyShoeId(int id) {
|
||||
return this.charShoes.contains(id);
|
||||
}
|
||||
|
||||
public boolean verifyWeaponId(int id) {
|
||||
return this.charWeapons.contains(id);
|
||||
}
|
||||
|
||||
public boolean verifyCharacter(Character character) {
|
||||
if (!verifyFaceId(character.getFace())) return false;
|
||||
if (!verifyHairId(character.getHair())) return false;
|
||||
if (!verifyHairColorId(character.getHair())) return false;
|
||||
if (!verifySkinId(character.getSkinColor().getId())) return false;
|
||||
|
||||
// Here we only verify the equipment if the character that's being created is of type 'Beginner'
|
||||
// This is because when the Maple Life A or Maple Life B items are used, the client does not send any data
|
||||
// regarding what equipment the character should be wearing (as it's all handled server-side)
|
||||
Job characterJob = character.getJob();
|
||||
if (characterJob == Job.BEGINNER || characterJob == Job.NOBLESSE || characterJob == Job.LEGEND) {
|
||||
if (!verifyTopId(character.getInventory(InventoryType.EQUIPPED).getItem((short) -5).getItemId()))
|
||||
return false;
|
||||
if (!verifyBottomId(character.getInventory(InventoryType.EQUIPPED).getItem((short) -6).getItemId()))
|
||||
return false;
|
||||
if (!verifyShoeId(character.getInventory(InventoryType.EQUIPPED).getItem((short) -7).getItemId()))
|
||||
return false;
|
||||
if (!verifyWeaponId(character.getInventory(InventoryType.EQUIPPED).getItem((short) -11).getItemId()))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package client.creator;
|
||||
|
||||
import client.Character;
|
||||
import provider.Data;
|
||||
import provider.DataProviderFactory;
|
||||
import provider.wz.WZFiles;
|
||||
|
||||
public class MakeCharInfoValidator {
|
||||
private static final MakeCharInfo charFemale;
|
||||
private static final MakeCharInfo charMale;
|
||||
private static final MakeCharInfo orientCharFemale;
|
||||
private static final MakeCharInfo orientCharMale;
|
||||
private static final MakeCharInfo premiumCharFemale;
|
||||
private static final MakeCharInfo premiumCharMale;
|
||||
|
||||
static {
|
||||
Data data = DataProviderFactory.getDataProvider(WZFiles.ETC).getData("MakeCharInfo.img");
|
||||
charFemale = new MakeCharInfo(data.getChildByPath("Info/CharFemale"));
|
||||
charMale = new MakeCharInfo(data.getChildByPath("Info/CharMale"));
|
||||
orientCharFemale = new MakeCharInfo(data.getChildByPath("OrientCharFemale"));
|
||||
orientCharMale = new MakeCharInfo(data.getChildByPath("OrientCharMale"));
|
||||
premiumCharFemale = new MakeCharInfo(data.getChildByPath("PremiumCharFemale"));
|
||||
premiumCharMale = new MakeCharInfo(data.getChildByPath("PremiumCharMale"));
|
||||
}
|
||||
|
||||
private static MakeCharInfo getMakeCharInfo(Character character) {
|
||||
return switch (character.getJob()) {
|
||||
case BEGINNER, WARRIOR, MAGICIAN, BOWMAN, THIEF, PIRATE -> character.isMale() ? charMale : charFemale;
|
||||
case NOBLESSE -> character.isMale() ? premiumCharMale : premiumCharFemale;
|
||||
case LEGEND -> character.isMale() ? orientCharMale : orientCharFemale;
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
public static boolean isNewCharacterValid(Character character) {
|
||||
MakeCharInfo makeCharInfo = getMakeCharInfo(character);
|
||||
if (makeCharInfo == null) return false;
|
||||
|
||||
return makeCharInfo.verifyCharacter(character);
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,6 @@ public class BeginnerCreator extends CharacterFactory {
|
||||
}
|
||||
|
||||
public static int createCharacter(Client c, String name, int face, int hair, int skin, int top, int bottom, int shoes, int weapon, int gender) {
|
||||
int status = createNewCharacter(c, name, face, hair, skin, gender, createRecipe(Job.BEGINNER, 1, MapId.MUSHROOM_TOWN, top, bottom, shoes, weapon));
|
||||
return status;
|
||||
return createNewCharacter(c, name, face, hair, skin, gender, createRecipe(Job.BEGINNER, 1, MapId.MUSHROOM_TOWN, top, bottom, shoes, weapon));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,6 @@ public class LegendCreator extends CharacterFactory {
|
||||
}
|
||||
|
||||
public static int createCharacter(Client c, String name, int face, int hair, int skin, int top, int bottom, int shoes, int weapon, int gender) {
|
||||
int status = createNewCharacter(c, name, face, hair, skin, gender, createRecipe(Job.LEGEND, 1, MapId.ARAN_TUTORIAL_START, top, bottom, shoes, weapon));
|
||||
return status;
|
||||
return createNewCharacter(c, name, face, hair, skin, gender, createRecipe(Job.LEGEND, 1, MapId.ARAN_TUTORIAL_START, top, bottom, shoes, weapon));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,6 @@ public class NoblesseCreator extends CharacterFactory {
|
||||
}
|
||||
|
||||
public static int createCharacter(Client c, String name, int face, int hair, int skin, int top, int bottom, int shoes, int weapon, int gender) {
|
||||
int status = createNewCharacter(c, name, face, hair, skin, gender, createRecipe(Job.NOBLESSE, 1, MapId.STARTING_MAP_NOBLESSE, top, bottom, shoes, weapon));
|
||||
return status;
|
||||
return createNewCharacter(c, name, face, hair, skin, gender, createRecipe(Job.NOBLESSE, 1, MapId.STARTING_MAP_NOBLESSE, top, bottom, shoes, weapon));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,14 @@ import server.ItemInformationProvider;
|
||||
import server.ThreadManager;
|
||||
import tools.Pair;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
@@ -652,4 +659,4 @@ public class Inventory implements Iterable<Item> {
|
||||
public void dispose() {
|
||||
owner = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,11 @@ package client.inventory;
|
||||
import tools.DatabaseConnection;
|
||||
import tools.Pair;
|
||||
|
||||
import java.sql.*;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
@@ -418,4 +422,4 @@ public enum ItemFactory {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,12 @@ package client.inventory.manipulator;
|
||||
import client.BuffStat;
|
||||
import client.Character;
|
||||
import client.Client;
|
||||
import client.inventory.*;
|
||||
import client.inventory.Equip;
|
||||
import client.inventory.Inventory;
|
||||
import client.inventory.InventoryType;
|
||||
import client.inventory.Item;
|
||||
import client.inventory.ModifyInventory;
|
||||
import client.inventory.Pet;
|
||||
import client.newyear.NewYearCardRecord;
|
||||
import config.YamlConfig;
|
||||
import constants.id.ItemId;
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
This file is part of the HeavenMS MapleStory Server
|
||||
Copyleft (L) 2016 - 2019 RonanLana
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package client.processor.action; // thanks Alex for pointing out some package structures containing broad modules
|
||||
|
||||
import client.Character;
|
||||
import client.Client;
|
||||
import server.maps.MapleMap;
|
||||
import tools.PacketCreator;
|
||||
|
||||
/**
|
||||
* @author RonanLana
|
||||
*/
|
||||
public class BuybackProcessor {
|
||||
|
||||
public static void processBuyback(Client c) {
|
||||
Character chr = c.getPlayer();
|
||||
boolean buyback;
|
||||
|
||||
c.lockClient();
|
||||
try {
|
||||
buyback = !chr.isAlive() && chr.couldBuyback();
|
||||
} finally {
|
||||
c.unlockClient();
|
||||
}
|
||||
|
||||
if (buyback) {
|
||||
String jobString;
|
||||
switch (chr.getJobStyle()) {
|
||||
case WARRIOR:
|
||||
jobString = "warrior";
|
||||
break;
|
||||
|
||||
case MAGICIAN:
|
||||
jobString = "magician";
|
||||
break;
|
||||
|
||||
case BOWMAN:
|
||||
jobString = "bowman";
|
||||
break;
|
||||
|
||||
case THIEF:
|
||||
jobString = "thief";
|
||||
break;
|
||||
|
||||
case BRAWLER:
|
||||
case GUNSLINGER:
|
||||
jobString = "pirate";
|
||||
break;
|
||||
|
||||
default:
|
||||
jobString = "beginner";
|
||||
}
|
||||
|
||||
chr.healHpMp();
|
||||
chr.purgeDebuffs();
|
||||
chr.broadcastStance(chr.isFacingLeft() ? 5 : 4);
|
||||
|
||||
MapleMap map = chr.getMap();
|
||||
map.broadcastMessage(PacketCreator.playSound("Buyback/" + jobString));
|
||||
map.broadcastMessage(PacketCreator.earnTitleMessage(chr.getName() + " just bought back into the game!"));
|
||||
|
||||
chr.sendPacket(PacketCreator.showBuybackEffect());
|
||||
map.broadcastMessage(chr, PacketCreator.showForeignBuybackEffect(chr.getId()), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,12 @@ import tools.DatabaseConnection;
|
||||
import tools.PacketCreator;
|
||||
import tools.Pair;
|
||||
|
||||
import java.sql.*;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
|
||||
@@ -41,7 +41,11 @@ import tools.DatabaseConnection;
|
||||
import tools.PacketCreator;
|
||||
import tools.Pair;
|
||||
|
||||
import java.sql.*;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@@ -24,7 +24,11 @@
|
||||
package client.processor.stat;
|
||||
|
||||
import client.Character;
|
||||
import client.*;
|
||||
import client.Client;
|
||||
import client.Job;
|
||||
import client.Skill;
|
||||
import client.SkillFactory;
|
||||
import client.Stat;
|
||||
import client.autoban.AutobanFactory;
|
||||
import client.inventory.Equip;
|
||||
import client.inventory.InventoryType;
|
||||
@@ -32,6 +36,12 @@ import client.inventory.Item;
|
||||
import config.YamlConfig;
|
||||
import constants.skills.*;
|
||||
import net.netty.GameViolationException;
|
||||
import constants.skills.BlazeWizard;
|
||||
import constants.skills.Brawler;
|
||||
import constants.skills.DawnWarrior;
|
||||
import constants.skills.Magician;
|
||||
import constants.skills.ThunderBreaker;
|
||||
import constants.skills.Warrior;
|
||||
import net.packet.InPacket;
|
||||
import tools.PacketCreator;
|
||||
import tools.Randomizer;
|
||||
@@ -542,16 +552,14 @@ public class AssignAPProcessor {
|
||||
return false;
|
||||
}
|
||||
|
||||
int hp = player.getMaxHp();
|
||||
int level_ = player.getLevel();
|
||||
if (hp < level_ * 14 + 148) {
|
||||
int hplose = -takeHp(player.getJob());
|
||||
if (player.getMaxHp() + hplose < getMinHp(player.getJob(), player.getLevel())) {
|
||||
player.message("You don't have the minimum HP pool required to swap.");
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return false;
|
||||
}
|
||||
|
||||
int curHp = player.getHp();
|
||||
int hplose = -takeHp(player.getJob());
|
||||
player.assignHP(hplose, -1);
|
||||
if (!YamlConfig.config.server.USE_FIXED_RATIO_HPMP_UPDATE) {
|
||||
player.updateHp(Math.max(1, curHp + hplose));
|
||||
@@ -573,29 +581,14 @@ public class AssignAPProcessor {
|
||||
return false;
|
||||
}
|
||||
|
||||
int mp = player.getMaxMp();
|
||||
int level = player.getLevel();
|
||||
Job job = player.getJob();
|
||||
|
||||
boolean canWash = true;
|
||||
if (job.isA(Job.SPEARMAN) && mp < 4 * level + 156) {
|
||||
canWash = false;
|
||||
} else if ((job.isA(Job.FIGHTER) || job.isA(Job.ARAN1)) && mp < 4 * level + 56) {
|
||||
canWash = false;
|
||||
} else if (job.isA(Job.THIEF) && job.getId() % 100 > 0 && mp < level * 14 - 4) {
|
||||
canWash = false;
|
||||
} else if (mp < level * 14 + 148) {
|
||||
canWash = false;
|
||||
}
|
||||
|
||||
if (!canWash) {
|
||||
int mplose = -takeMp(player.getJob());
|
||||
if (player.getMaxMp() + mplose < getMinMp(player.getJob(), player.getLevel())) {
|
||||
player.message("You don't have the minimum MP pool required to swap.");
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return false;
|
||||
}
|
||||
|
||||
int curMp = player.getMp();
|
||||
int mplose = -takeMp(job);
|
||||
player.assignMP(mplose, -1);
|
||||
if (!YamlConfig.config.server.USE_FIXED_RATIO_HPMP_UPDATE) {
|
||||
player.updateMp(Math.max(0, curMp + mplose));
|
||||
@@ -886,4 +879,109 @@ public class AssignAPProcessor {
|
||||
return MaxMP;
|
||||
}
|
||||
|
||||
public static int getMinHp(Job job, int level) {
|
||||
int multiplier = 0;
|
||||
int offset = 0;
|
||||
|
||||
if (job == Job.WARRIOR ||
|
||||
job.isA(Job.PAGE) ||
|
||||
job.isA(Job.SPEARMAN) ||
|
||||
job == Job.DAWNWARRIOR1 ||
|
||||
job == Job.ARAN1) {
|
||||
multiplier = 24; offset = 118;
|
||||
|
||||
} else if (job.isA(Job.FIGHTER) ||
|
||||
job.isA(Job.DAWNWARRIOR2) ||
|
||||
job.isA(Job.ARAN2)) {
|
||||
multiplier = 24; offset = 418;
|
||||
|
||||
} else if (job.isA(Job.MAGICIAN) ||
|
||||
job.isA(Job.BLAZEWIZARD1)) {
|
||||
multiplier = 10; offset = 54;
|
||||
|
||||
} else if (job == Job.BOWMAN ||
|
||||
job == Job.THIEF ||
|
||||
job == Job.WINDARCHER1 ||
|
||||
job == Job.NIGHTWALKER1) {
|
||||
multiplier = 20; offset = 58;
|
||||
|
||||
} else if (job.isA(Job.HUNTER) ||
|
||||
job.isA(Job.CROSSBOWMAN) ||
|
||||
job.isA(Job.ASSASSIN) ||
|
||||
job.isA(Job.BANDIT) ||
|
||||
job.isA(Job.WINDARCHER2) ||
|
||||
job.isA(Job.NIGHTWALKER2)) {
|
||||
multiplier = 20; offset = 358;
|
||||
|
||||
} else if (job == Job.PIRATE ||
|
||||
job == Job.THUNDERBREAKER1) {
|
||||
multiplier = 22; offset = 38;
|
||||
|
||||
} else if (job.isA(Job.BRAWLER) ||
|
||||
job.isA(Job.GUNSLINGER) ||
|
||||
job.isA(Job.THUNDERBREAKER2)) {
|
||||
multiplier = 22; offset = 338;
|
||||
|
||||
} else if (job == Job.BEGINNER ||
|
||||
job == Job.NOBLESSE) {
|
||||
multiplier = 12; offset = 38;
|
||||
}
|
||||
|
||||
return (multiplier * level) + offset;
|
||||
}
|
||||
|
||||
public static int getMinMp(Job job, int level) {
|
||||
int multiplier = 0;
|
||||
int offset = 0;
|
||||
|
||||
if (job == Job.WARRIOR ||
|
||||
job.isA(Job.FIGHTER) ||
|
||||
job.isA(Job.DAWNWARRIOR1) ||
|
||||
job.isA(Job.ARAN1)) {
|
||||
multiplier = 4; offset = 55;
|
||||
|
||||
} else if (job.isA(Job.PAGE) ||
|
||||
job.isA(Job.SPEARMAN)) {
|
||||
multiplier = 4; offset = 155;
|
||||
|
||||
} else if (job == Job.MAGICIAN ||
|
||||
job == Job.BLAZEWIZARD1) {
|
||||
multiplier = 22; offset = -1;
|
||||
|
||||
} else if (job.isA(Job.FP_WIZARD) ||
|
||||
job.isA(Job.IL_WIZARD) ||
|
||||
job.isA(Job.CLERIC) ||
|
||||
job.isA(Job.BLAZEWIZARD2)) {
|
||||
multiplier = 22; offset = 449;
|
||||
|
||||
} else if (job == Job.BOWMAN ||
|
||||
job == Job.THIEF ||
|
||||
job == Job.WINDARCHER1 ||
|
||||
job == Job.NIGHTWALKER1) {
|
||||
multiplier = 14; offset = -15;
|
||||
|
||||
} else if (job.isA(Job.HUNTER) ||
|
||||
job.isA(Job.CROSSBOWMAN) ||
|
||||
job.isA(Job.ASSASSIN) ||
|
||||
job.isA(Job.BANDIT) ||
|
||||
job.isA(Job.WINDARCHER2) ||
|
||||
job.isA(Job.NIGHTWALKER2)) {
|
||||
multiplier = 14; offset = 135;
|
||||
|
||||
} else if (job == Job.PIRATE ||
|
||||
job == Job.THUNDERBREAKER1) {
|
||||
multiplier = 18; offset = -55;
|
||||
|
||||
} else if (job.isA(Job.BRAWLER) ||
|
||||
job.isA(Job.GUNSLINGER) ||
|
||||
job.isA(Job.THUNDERBREAKER2)) {
|
||||
multiplier = 18; offset = 95;
|
||||
|
||||
} else if (job == Job.BEGINNER ||
|
||||
job == Job.NOBLESSE) {
|
||||
multiplier = 10; offset = -5;
|
||||
}
|
||||
|
||||
return (multiplier * level) + offset;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,6 @@ public class ServerConfig {
|
||||
public boolean USE_MTS;
|
||||
public boolean USE_CPQ;
|
||||
public boolean USE_AUTOHIDE_GM;
|
||||
public boolean USE_BUYBACK_SYSTEM;
|
||||
public boolean USE_FIXED_RATIO_HPMP_UPDATE;
|
||||
public boolean USE_FAMILY_SYSTEM;
|
||||
public boolean USE_DUEY;
|
||||
@@ -105,17 +104,15 @@ public class ServerConfig {
|
||||
public boolean USE_ENFORCE_UNMERCHABLE_PET;
|
||||
public boolean USE_ENFORCE_MDOOR_POSITION;
|
||||
public boolean USE_SPAWN_CLEAN_MDOOR;
|
||||
public boolean USE_SPAWN_LOOT_ON_ANIMATION;
|
||||
public boolean USE_SPAWN_RELEVANT_LOOT;
|
||||
public boolean USE_ERASE_PERMIT_ON_OPENSHOP;
|
||||
public boolean USE_ERASE_UNTRADEABLE_DROP;
|
||||
public boolean USE_ERASE_PET_ON_EXPIRATION;
|
||||
public boolean USE_BUFF_MOST_SIGNIFICANT;
|
||||
public boolean USE_BUFF_EVERLASTING;
|
||||
public boolean USE_BANISHABLE_TOWN_SCROLL;
|
||||
public boolean USE_MULTIPLE_SAME_EQUIP_DROP;
|
||||
public boolean USE_ENABLE_FULL_RESPAWN;
|
||||
public boolean USE_ENABLE_CHAT_LOG;
|
||||
public boolean USE_REBIRTH_SYSTEM;
|
||||
public boolean USE_MAP_OWNERSHIP_SYSTEM;
|
||||
public boolean USE_FISHING_SYSTEM;
|
||||
public boolean USE_NPCS_SCRIPTABLE;
|
||||
@@ -173,7 +170,6 @@ public class ServerConfig {
|
||||
public long NAME_CHANGE_COOLDOWN;
|
||||
public long WORLD_TRANSFER_COOLDOWN = NAME_CHANGE_COOLDOWN;//Cooldown for world tranfers, default is same as name change (30 days).
|
||||
public boolean INSTANT_NAME_CHANGE;
|
||||
public int REBIRTH_NPC_ID;
|
||||
|
||||
//Dangling Items/Locks Configuration
|
||||
public int ITEM_EXPIRE_TIME;
|
||||
@@ -201,7 +197,6 @@ public class ServerConfig {
|
||||
public boolean USE_PERFECT_SCROLLING;
|
||||
public boolean USE_ENHANCED_CHSCROLL;
|
||||
public boolean USE_ENHANCED_CRAFTING;
|
||||
public boolean USE_ENHANCED_CLNSLATE;
|
||||
public int SCROLL_CHANCE_ROLLS;
|
||||
public int CHSCROLL_STAT_RATE;
|
||||
public int CHSCROLL_STAT_RANGE;
|
||||
@@ -250,7 +245,6 @@ public class ServerConfig {
|
||||
public boolean USE_EQUIPMNT_LVLUP_SLOTS;
|
||||
public boolean USE_EQUIPMNT_LVLUP_POWER;
|
||||
public boolean USE_EQUIPMNT_LVLUP_CASH;
|
||||
public boolean USE_SPIKES_AVOID_BANISH;
|
||||
public int MAX_EQUIPMNT_LVLUP_STAT_UP;
|
||||
public int MAX_EQUIPMNT_STAT;
|
||||
public int USE_EQUIPMNT_LVLUP;
|
||||
@@ -301,14 +295,6 @@ public class ServerConfig {
|
||||
public int WEDDING_GIFT_LIMIT;
|
||||
public boolean WEDDING_BLESSER_SHOWFX;
|
||||
|
||||
//Buyback Configuration
|
||||
public boolean USE_BUYBACK_WITH_MESOS;
|
||||
public float BUYBACK_FEE;
|
||||
public float BUYBACK_LEVEL_STACK_FEE;
|
||||
public int BUYBACK_MESO_MULTIPLIER;
|
||||
public int BUYBACK_RETURN_MINUTES;
|
||||
public int BUYBACK_COOLDOWN_MINUTES;
|
||||
|
||||
// Login timeout by shavit
|
||||
public long TIMEOUT_DURATION;
|
||||
|
||||
|
||||
@@ -101,46 +101,6 @@ public class ItemId {
|
||||
public static final int BEGINNERS_GUIDE = 4161001;
|
||||
public static final int LEGENDS_GUIDE = 4161048;
|
||||
public static final int NOBLESSE_GUIDE = 4161047;
|
||||
public static final int SWORD = 1302000; // Weapon
|
||||
public static final int HAND_AXE = 1312004;
|
||||
public static final int WOODEN_CLUB = 1322005;
|
||||
public static final int BASIC_POLEARM = 1442079;
|
||||
public static final int WHITE_UNDERSHIRT = 1040002; // Top
|
||||
public static final int UNDERSHIRT = 1040006;
|
||||
public static final int GREY_TSHIRT = 1040010;
|
||||
public static final int WHITE_TUBETOP = 1041002;
|
||||
public static final int YELLOW_TSHIRT = 1041006;
|
||||
public static final int GREEN_TSHIRT = 1041010;
|
||||
public static final int RED_STRIPED_TOP = 1041011;
|
||||
public static final int SIMPLE_WARRIOR_TOP = 1042167;
|
||||
public static final int BLUE_JEAN_SHORTS = 1060002; // Bottom
|
||||
public static final int BROWN_COTTON_SHORTS = 1060006;
|
||||
public static final int RED_MINISKIRT = 1061002;
|
||||
public static final int INDIGO_MINISKIRT = 1061008;
|
||||
public static final int SIMPLE_WARRIOR_PANTS = 1062115;
|
||||
public static final int RED_RUBBER_BOOTS = 1072001;
|
||||
public static final int LEATHER_SANDALS = 1072005;
|
||||
public static final int YELLOW_RUBBER_BOOTS = 1072037;
|
||||
public static final int BLUE_RUBBER_BOOTS = 1072038;
|
||||
public static final int AVERAGE_MUSASHI_SHOES = 1072383;
|
||||
public static final int BLACK_TOBEN = 30000; // Hair
|
||||
public static final int ZETA = 30010;
|
||||
public static final int BLACK_REBEL = 30020;
|
||||
public static final int BLACK_BUZZ = 30030;
|
||||
public static final int BLACK_SAMMY = 31000;
|
||||
public static final int BLACK_EDGY = 31040;
|
||||
public static final int BLACK_CONNIE = 31050;
|
||||
public static final int MOTIVATED_LOOK_M = 20000; // Face
|
||||
public static final int PERPLEXED_STARE = 20001;
|
||||
public static final int LEISURE_LOOK_M = 20002;
|
||||
public static final int MOTIVATED_LOOK_F = 21000;
|
||||
public static final int FEARFUL_STARE_M = 21001;
|
||||
public static final int LEISURE_LOOK_F = 21002;
|
||||
public static final int FEARFUL_STARE_F = 21201;
|
||||
public static final int PERPLEXED_STARE_HAZEL = 20401;
|
||||
public static final int LEISURE_LOOK_HAZEL = 20402;
|
||||
public static final int MOTIVATED_LOOK_AMETHYST = 21700;
|
||||
public static final int MOTIVATED_LOOK_BLUE = 20100;
|
||||
|
||||
// Warrior
|
||||
public static final int RED_HWARANG_SHIRT = 1040021;
|
||||
@@ -211,7 +171,6 @@ public class ItemId {
|
||||
public static final int EYEDROP = 2050001;
|
||||
public static final int TONIC = 2050002;
|
||||
public static final int HOLY_WATER = 2050003;
|
||||
public static final int ANTI_BANISH_SCROLL = 2030100;
|
||||
private static final int DOJO_PARTY_ALL_CURE = 2022433;
|
||||
private static final int CARNIVAL_PARTY_ALL_CURE = 2022163;
|
||||
public static final int WHITE_ELIXIR = 2022544;
|
||||
@@ -362,6 +321,10 @@ public class ItemId {
|
||||
return itemId == NX_CARD_100 || itemId == NX_CARD_250;
|
||||
}
|
||||
|
||||
public static boolean isCashPackage(int itemId) {
|
||||
return itemId / 10000 == 910;
|
||||
}
|
||||
|
||||
// Face expression
|
||||
private static final int FACE_EXPRESSION_MIN = 5160000;
|
||||
private static final int FACE_EXPRESSION_MAX = 5160014;
|
||||
|
||||
@@ -134,11 +134,7 @@ public final class ItemConstants {
|
||||
}
|
||||
|
||||
public static boolean isTownScroll(int itemId) {
|
||||
return itemId >= 2030000 && itemId < ItemId.ANTI_BANISH_SCROLL;
|
||||
}
|
||||
|
||||
public static boolean isAntibanishScroll(int itemId) {
|
||||
return itemId == ItemId.ANTI_BANISH_SCROLL;
|
||||
return itemId >= 2030000;
|
||||
}
|
||||
|
||||
public static boolean isCleanSlate(int scrollId) {
|
||||
|
||||
@@ -23,11 +23,174 @@ package net;
|
||||
|
||||
import net.netty.LoginServer;
|
||||
import net.opcodes.RecvOpcode;
|
||||
import net.server.channel.handlers.*;
|
||||
import net.server.channel.handlers.AcceptFamilyHandler;
|
||||
import net.server.channel.handlers.AdminChatHandler;
|
||||
import net.server.channel.handlers.AdminCommandHandler;
|
||||
import net.server.channel.handlers.AdminLogHandler;
|
||||
import net.server.channel.handlers.AllianceOperationHandler;
|
||||
import net.server.channel.handlers.AranComboHandler;
|
||||
import net.server.channel.handlers.AutoAggroHandler;
|
||||
import net.server.channel.handlers.AutoAssignHandler;
|
||||
import net.server.channel.handlers.BBSOperationHandler;
|
||||
import net.server.channel.handlers.BeholderHandler;
|
||||
import net.server.channel.handlers.BuddylistModifyHandler;
|
||||
import net.server.channel.handlers.CancelBuffHandler;
|
||||
import net.server.channel.handlers.CancelChairHandler;
|
||||
import net.server.channel.handlers.CancelDebuffHandler;
|
||||
import net.server.channel.handlers.CancelItemEffectHandler;
|
||||
import net.server.channel.handlers.CashOperationHandler;
|
||||
import net.server.channel.handlers.CashShopSurpriseHandler;
|
||||
import net.server.channel.handlers.ChangeChannelHandler;
|
||||
import net.server.channel.handlers.ChangeMapHandler;
|
||||
import net.server.channel.handlers.ChangeMapSpecialHandler;
|
||||
import net.server.channel.handlers.CharInfoRequestHandler;
|
||||
import net.server.channel.handlers.ClickGuideHandler;
|
||||
import net.server.channel.handlers.CloseChalkboardHandler;
|
||||
import net.server.channel.handlers.CloseRangeDamageHandler;
|
||||
import net.server.channel.handlers.CoconutHandler;
|
||||
import net.server.channel.handlers.CouponCodeHandler;
|
||||
import net.server.channel.handlers.DamageSummonHandler;
|
||||
import net.server.channel.handlers.DenyAllianceRequestHandler;
|
||||
import net.server.channel.handlers.DenyGuildRequestHandler;
|
||||
import net.server.channel.handlers.DenyPartyRequestHandler;
|
||||
import net.server.channel.handlers.DistributeAPHandler;
|
||||
import net.server.channel.handlers.DistributeSPHandler;
|
||||
import net.server.channel.handlers.DoorHandler;
|
||||
import net.server.channel.handlers.DueyHandler;
|
||||
import net.server.channel.handlers.EnterCashShopHandler;
|
||||
import net.server.channel.handlers.EnterMTSHandler;
|
||||
import net.server.channel.handlers.FaceExpressionHandler;
|
||||
import net.server.channel.handlers.FamilyAddHandler;
|
||||
import net.server.channel.handlers.FamilyPreceptsHandler;
|
||||
import net.server.channel.handlers.FamilySeparateHandler;
|
||||
import net.server.channel.handlers.FamilySummonResponseHandler;
|
||||
import net.server.channel.handlers.FamilyUseHandler;
|
||||
import net.server.channel.handlers.FieldDamageMobHandler;
|
||||
import net.server.channel.handlers.FredrickHandler;
|
||||
import net.server.channel.handlers.GeneralChatHandler;
|
||||
import net.server.channel.handlers.GiveFameHandler;
|
||||
import net.server.channel.handlers.GrenadeEffectHandler;
|
||||
import net.server.channel.handlers.GuildOperationHandler;
|
||||
import net.server.channel.handlers.HealOvertimeHandler;
|
||||
import net.server.channel.handlers.HiredMerchantRequest;
|
||||
import net.server.channel.handlers.InnerPortalHandler;
|
||||
import net.server.channel.handlers.InventoryMergeHandler;
|
||||
import net.server.channel.handlers.InventorySortHandler;
|
||||
import net.server.channel.handlers.ItemMoveHandler;
|
||||
import net.server.channel.handlers.ItemPickupHandler;
|
||||
import net.server.channel.handlers.ItemRewardHandler;
|
||||
import net.server.channel.handlers.KeymapChangeHandler;
|
||||
import net.server.channel.handlers.LeftKnockbackHandler;
|
||||
import net.server.channel.handlers.MTSHandler;
|
||||
import net.server.channel.handlers.MagicDamageHandler;
|
||||
import net.server.channel.handlers.MakerSkillHandler;
|
||||
import net.server.channel.handlers.MesoDropHandler;
|
||||
import net.server.channel.handlers.MessengerHandler;
|
||||
import net.server.channel.handlers.MobBanishPlayerHandler;
|
||||
import net.server.channel.handlers.MobDamageMobFriendlyHandler;
|
||||
import net.server.channel.handlers.MobDamageMobHandler;
|
||||
import net.server.channel.handlers.MonsterBombHandler;
|
||||
import net.server.channel.handlers.MonsterBookCoverHandler;
|
||||
import net.server.channel.handlers.MonsterCarnivalHandler;
|
||||
import net.server.channel.handlers.MoveDragonHandler;
|
||||
import net.server.channel.handlers.MoveLifeHandler;
|
||||
import net.server.channel.handlers.MovePetHandler;
|
||||
import net.server.channel.handlers.MovePlayerHandler;
|
||||
import net.server.channel.handlers.MoveSummonHandler;
|
||||
import net.server.channel.handlers.MultiChatHandler;
|
||||
import net.server.channel.handlers.NPCAnimationHandler;
|
||||
import net.server.channel.handlers.NPCMoreTalkHandler;
|
||||
import net.server.channel.handlers.NPCShopHandler;
|
||||
import net.server.channel.handlers.NPCTalkHandler;
|
||||
import net.server.channel.handlers.NewYearCardHandler;
|
||||
import net.server.channel.handlers.NoteActionHandler;
|
||||
import net.server.channel.handlers.OpenFamilyHandler;
|
||||
import net.server.channel.handlers.OpenFamilyPedigreeHandler;
|
||||
import net.server.channel.handlers.OwlWarpHandler;
|
||||
import net.server.channel.handlers.PartyOperationHandler;
|
||||
import net.server.channel.handlers.PartySearchRegisterHandler;
|
||||
import net.server.channel.handlers.PartySearchStartHandler;
|
||||
import net.server.channel.handlers.PartySearchUpdateHandler;
|
||||
import net.server.channel.handlers.PetAutoPotHandler;
|
||||
import net.server.channel.handlers.PetChatHandler;
|
||||
import net.server.channel.handlers.PetCommandHandler;
|
||||
import net.server.channel.handlers.PetExcludeItemsHandler;
|
||||
import net.server.channel.handlers.PetFoodHandler;
|
||||
import net.server.channel.handlers.PetLootHandler;
|
||||
import net.server.channel.handlers.PlayerInteractionHandler;
|
||||
import net.server.channel.handlers.PlayerLoggedinHandler;
|
||||
import net.server.channel.handlers.PlayerMapTransitionHandler;
|
||||
import net.server.channel.handlers.QuestActionHandler;
|
||||
import net.server.channel.handlers.QuickslotKeyMappedModifiedHandler;
|
||||
import net.server.channel.handlers.RPSActionHandler;
|
||||
import net.server.channel.handlers.RaiseIncExpHandler;
|
||||
import net.server.channel.handlers.RaiseUIStateHandler;
|
||||
import net.server.channel.handlers.RangedAttackHandler;
|
||||
import net.server.channel.handlers.ReactorHitHandler;
|
||||
import net.server.channel.handlers.RemoteGachaponHandler;
|
||||
import net.server.channel.handlers.RemoteStoreHandler;
|
||||
import net.server.channel.handlers.ReportHandler;
|
||||
import net.server.channel.handlers.RingActionHandler;
|
||||
import net.server.channel.handlers.ScriptedItemHandler;
|
||||
import net.server.channel.handlers.ScrollHandler;
|
||||
import net.server.channel.handlers.SkillBookHandler;
|
||||
import net.server.channel.handlers.SkillEffectHandler;
|
||||
import net.server.channel.handlers.SkillMacroHandler;
|
||||
import net.server.channel.handlers.SnowballHandler;
|
||||
import net.server.channel.handlers.SpawnPetHandler;
|
||||
import net.server.channel.handlers.SpecialMoveHandler;
|
||||
import net.server.channel.handlers.SpouseChatHandler;
|
||||
import net.server.channel.handlers.StorageHandler;
|
||||
import net.server.channel.handlers.SummonDamageHandler;
|
||||
import net.server.channel.handlers.TakeDamageHandler;
|
||||
import net.server.channel.handlers.TouchMonsterDamageHandler;
|
||||
import net.server.channel.handlers.TouchReactorHandler;
|
||||
import net.server.channel.handlers.TouchingCashShopHandler;
|
||||
import net.server.channel.handlers.TransferNameHandler;
|
||||
import net.server.channel.handlers.TransferNameResultHandler;
|
||||
import net.server.channel.handlers.TransferWorldHandler;
|
||||
import net.server.channel.handlers.TrockAddMapHandler;
|
||||
import net.server.channel.handlers.UseCashItemHandler;
|
||||
import net.server.channel.handlers.UseCatchItemHandler;
|
||||
import net.server.channel.handlers.UseChairHandler;
|
||||
import net.server.channel.handlers.UseDeathItemHandler;
|
||||
import net.server.channel.handlers.UseGachaExpHandler;
|
||||
import net.server.channel.handlers.UseHammerHandler;
|
||||
import net.server.channel.handlers.UseItemEffectHandler;
|
||||
import net.server.channel.handlers.UseItemHandler;
|
||||
import net.server.channel.handlers.UseMapleLifeHandler;
|
||||
import net.server.channel.handlers.UseMountFoodHandler;
|
||||
import net.server.channel.handlers.UseOwlOfMinervaHandler;
|
||||
import net.server.channel.handlers.UseSolomonHandler;
|
||||
import net.server.channel.handlers.UseSummonBagHandler;
|
||||
import net.server.channel.handlers.UseWaterOfLifeHandler;
|
||||
import net.server.channel.handlers.WeddingHandler;
|
||||
import net.server.channel.handlers.WeddingTalkHandler;
|
||||
import net.server.channel.handlers.WeddingTalkMoreHandler;
|
||||
import net.server.channel.handlers.WhisperHandler;
|
||||
import net.server.handlers.CustomPacketHandler;
|
||||
import net.server.handlers.KeepAliveHandler;
|
||||
import net.server.handlers.LoginRequiringNoOpHandler;
|
||||
import net.server.handlers.login.*;
|
||||
import net.server.handlers.login.AcceptToSHandler;
|
||||
import net.server.handlers.login.AfterLoginHandler;
|
||||
import net.server.handlers.login.CharSelectedHandler;
|
||||
import net.server.handlers.login.CharSelectedWithPicHandler;
|
||||
import net.server.handlers.login.CharlistRequestHandler;
|
||||
import net.server.handlers.login.CheckCharNameHandler;
|
||||
import net.server.handlers.login.CreateCharHandler;
|
||||
import net.server.handlers.login.DeleteCharHandler;
|
||||
import net.server.handlers.login.GuestLoginHandler;
|
||||
import net.server.handlers.login.LoginPasswordHandler;
|
||||
import net.server.handlers.login.RegisterPicHandler;
|
||||
import net.server.handlers.login.RegisterPinHandler;
|
||||
import net.server.handlers.login.RelogRequestHandler;
|
||||
import net.server.handlers.login.ServerStatusRequestHandler;
|
||||
import net.server.handlers.login.ServerlistRequestHandler;
|
||||
import net.server.handlers.login.SetGenderHandler;
|
||||
import net.server.handlers.login.ViewAllCharHandler;
|
||||
import net.server.handlers.login.ViewAllCharRegisterPicHandler;
|
||||
import net.server.handlers.login.ViewAllCharSelectedHandler;
|
||||
import net.server.handlers.login.ViewAllCharSelectedWithPicHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
@@ -82,6 +82,11 @@ public class ByteBufInPacket implements InPacket {
|
||||
return byteBuf.readerIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof ByteBufInPacket other && byteBuf.equals(other.byteBuf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final int readerIndex = byteBuf.readerIndex();
|
||||
|
||||
@@ -91,4 +91,9 @@ public class ByteBufOutPacket implements OutPacket {
|
||||
public void skip(int numberOfBytes) {
|
||||
writeBytes(new byte[numberOfBytes]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof ByteBufOutPacket other && byteBuf.equals(other.byteBuf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,11 @@ import client.Character;
|
||||
import client.Client;
|
||||
import service.TransitionService;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
@@ -63,7 +63,17 @@ import net.server.coordinator.session.SessionCoordinator;
|
||||
import net.server.guild.Alliance;
|
||||
import net.server.guild.Guild;
|
||||
import net.server.guild.GuildCharacter;
|
||||
import net.server.task.*;
|
||||
import net.server.task.BossLogTask;
|
||||
import net.server.task.CharacterDiseaseTask;
|
||||
import net.server.task.CouponTask;
|
||||
import net.server.task.DueyFredrickTask;
|
||||
import net.server.task.EventRecallCoordinatorTask;
|
||||
import net.server.task.InvitationTask;
|
||||
import net.server.task.LoginCoordinatorTask;
|
||||
import net.server.task.LoginStorageTask;
|
||||
import net.server.task.RankingCommandTask;
|
||||
import net.server.task.RankingLoginTask;
|
||||
import net.server.task.RespawnTask;
|
||||
import net.server.world.World;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.slf4j.Logger;
|
||||
@@ -88,8 +98,20 @@ import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TimeZone;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
@@ -99,7 +121,10 @@ import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.*;
|
||||
import static java.util.concurrent.TimeUnit.DAYS;
|
||||
import static java.util.concurrent.TimeUnit.HOURS;
|
||||
import static java.util.concurrent.TimeUnit.MINUTES;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
public class Server {
|
||||
private static final Logger log = LoggerFactory.getLogger(Server.class);
|
||||
|
||||
@@ -43,7 +43,11 @@ import server.TimerManager;
|
||||
import server.events.gm.Event;
|
||||
import server.expeditions.Expedition;
|
||||
import server.expeditions.ExpeditionType;
|
||||
import server.maps.*;
|
||||
import server.maps.HiredMerchant;
|
||||
import server.maps.MapManager;
|
||||
import server.maps.MapleMap;
|
||||
import server.maps.MiniDungeon;
|
||||
import server.maps.MiniDungeonInfo;
|
||||
import service.TransitionService;
|
||||
import tools.PacketCreator;
|
||||
import tools.Pair;
|
||||
@@ -52,14 +56,25 @@ import java.io.IOException;
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.*;
|
||||
import static java.util.concurrent.TimeUnit.HOURS;
|
||||
import static java.util.concurrent.TimeUnit.MINUTES;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
public final class Channel {
|
||||
private static final Logger log = LoggerFactory.getLogger(Channel.class);
|
||||
|
||||
@@ -42,7 +42,6 @@ import server.TimerManager;
|
||||
import server.life.*;
|
||||
import server.maps.MapItem;
|
||||
import server.maps.MapObject;
|
||||
import server.maps.MapObjectType;
|
||||
import server.maps.MapleMap;
|
||||
import service.BanService;
|
||||
import tools.PacketCreator;
|
||||
@@ -58,6 +57,8 @@ import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
private final DropProvider dropProvider;
|
||||
private final BanService banService;
|
||||
private static final int EXPLODED_MESO_SPREAD_DELAY = 100;
|
||||
private static final int EXPLODED_MESO_MAX_DELAY = 1000;
|
||||
|
||||
public AbstractDealDamageHandler(DropProvider dropProvider, BanService banService) {
|
||||
this.dropProvider = dropProvider;
|
||||
@@ -67,10 +68,12 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
public class AttackInfo {
|
||||
|
||||
public int numAttacked, numDamage, numAttackedAndDamage, skill, skilllevel, stance, direction, rangedirection, charge, display;
|
||||
public Map<Integer, List<Integer>> allDamage;
|
||||
public Map<Integer, AttackTarget> targets;
|
||||
public boolean ranged, magic;
|
||||
public int speed = 4;
|
||||
public Point position = new Point();
|
||||
public List<Integer> explodedMesos;
|
||||
public Short attackDelay;
|
||||
|
||||
public StatEffect getAttackEffect(Character chr, Skill theSkill) {
|
||||
Skill mySkill = theSkill;
|
||||
@@ -96,6 +99,9 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: add position
|
||||
public record AttackTarget(short delay, List<Integer> damageLines) {}
|
||||
|
||||
protected void applyAttack(AttackInfo attack, final Character player, int attackCount) {
|
||||
final MapleMap map = player.getMap();
|
||||
if (map.isOwnershipRestricted(player)) {
|
||||
@@ -157,50 +163,14 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
//WTF IS THIS F3,1
|
||||
/*if (attackCount != attack.numDamage && attack.skill != ChiefBandit.MESO_EXPLOSION && attack.skill != NightWalker.VAMPIRE && attack.skill != WindArcher.WIND_SHOT && attack.skill != Aran.COMBO_SMASH && attack.skill != Aran.COMBO_FENRIR && attack.skill != Aran.COMBO_TEMPEST && attack.skill != NightLord.NINJA_AMBUSH && attack.skill != Shadower.NINJA_AMBUSH) {
|
||||
return;
|
||||
}*/
|
||||
|
||||
int totDamage = 0;
|
||||
|
||||
if (attack.skill == ChiefBandit.MESO_EXPLOSION) {
|
||||
int delay = 0;
|
||||
for (Integer oned : attack.allDamage.keySet()) {
|
||||
MapObject mapobject = map.getMapObject(oned);
|
||||
if (mapobject != null && mapobject.getType() == MapObjectType.ITEM) {
|
||||
final MapItem mapitem = (MapItem) mapobject;
|
||||
if (mapitem.getMeso() == 0) { //Maybe it is possible some how?
|
||||
return;
|
||||
}
|
||||
|
||||
mapitem.lockItem();
|
||||
try {
|
||||
if (mapitem.isPickedUp()) {
|
||||
return;
|
||||
}
|
||||
TimerManager.getInstance().schedule(() -> {
|
||||
mapitem.lockItem();
|
||||
try {
|
||||
if (mapitem.isPickedUp()) {
|
||||
return;
|
||||
}
|
||||
map.pickItemDrop(PacketCreator.removeItemFromMap(mapitem.getObjectId(), 4, 0), mapitem);
|
||||
} finally {
|
||||
mapitem.unlockItem();
|
||||
}
|
||||
}, delay);
|
||||
delay += 100;
|
||||
} finally {
|
||||
mapitem.unlockItem();
|
||||
}
|
||||
} else if (mapobject != null && mapobject.getType() != MapObjectType.MONSTER) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
removeExplodedMesos(map, attack);
|
||||
}
|
||||
for (Integer oned : attack.allDamage.keySet()) {
|
||||
final Monster monster = map.getMonsterByOid(oned);
|
||||
|
||||
for (Map.Entry<Integer, AttackTarget> target : attack.targets.entrySet()) {
|
||||
final Monster monster = map.getMonsterByOid(target.getKey());
|
||||
if (monster != null) {
|
||||
double distance = player.getPosition().distanceSq(monster.getPosition());
|
||||
double distanceToDetect = 200000.0;
|
||||
@@ -235,7 +205,7 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
}
|
||||
|
||||
int totDamageToOneMonster = 0;
|
||||
List<Integer> onedList = attack.allDamage.get(oned);
|
||||
List<Integer> onedList = target.getValue().damageLines();
|
||||
|
||||
if (attack.magic) { // thanks BHB, Alex (CanIGetaPR) for noticing no immunity status check here
|
||||
if (monster.isBuffed(MonsterStatus.MAGIC_IMMUNITY)) {
|
||||
@@ -271,7 +241,7 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
Skill pickpocket = SkillFactory.getSkill(ChiefBandit.PICKPOCKET);
|
||||
int picklv = (player.isGM()) ? pickpocket.getMaxLevel() : player.getSkillLevel(pickpocket);
|
||||
if (picklv > 0) {
|
||||
int delay = 0;
|
||||
short delay = 0;
|
||||
final int maxmeso = player.getBuffedValue(BuffStat.PICKPOCKET);
|
||||
for (Integer eachd : onedList) {
|
||||
eachd += Integer.MAX_VALUE;
|
||||
@@ -284,7 +254,9 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
eachdf = eachd;
|
||||
}
|
||||
|
||||
TimerManager.getInstance().schedule(() -> map.spawnMesoDrop(Math.min((int) Math.max(((double) eachdf / (double) 20000) * (double) maxmeso, 1), maxmeso), new Point((int) (monster.getPosition().getX() + Randomizer.nextInt(100) - 50), (int) (monster.getPosition().getY())), monster, player, true, (byte) 2), delay);
|
||||
int meso = Math.min((int) Math.max(((double) eachdf / (double) 20000) * (double) maxmeso, 1), maxmeso);
|
||||
Point position = new Point((int) (monster.getPosition().getX() + Randomizer.nextInt(100) - 50), (int) (monster.getPosition().getY()));
|
||||
map.spawnMesoDrop(meso, position, monster, player, true, (byte) 2, delay);
|
||||
delay += 100;
|
||||
}
|
||||
}
|
||||
@@ -296,7 +268,7 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
if (steal.getEffect(player.getSkillLevel(steal)).makeChanceResult() && monster.trySteal()) {
|
||||
|
||||
Optional<MonsterDropEntry> stolenItem = dropProvider.getRandomStealDrop(monster.getId());
|
||||
stolenItem.ifPresent(item -> map.dropItemsFromMonster(Collections.singletonList(item), player, monster));
|
||||
stolenItem.ifPresent(item -> map.dropItemsFromMonster(Collections.singletonList(item), player, monster, attack.attackDelay));
|
||||
}
|
||||
} else if (attack.skill == FPArchMage.FIRE_DEMON) {
|
||||
long duration = SECONDS.toMillis(SkillFactory.getSkill(FPArchMage.FIRE_DEMON).getEffect(player.getSkillLevel(SkillFactory.getSkill(FPArchMage.FIRE_DEMON))).getDuration());
|
||||
@@ -413,7 +385,7 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
StatEffect mortal = mortalBlow.getEffect(skillLevel);
|
||||
if (monster.getHp() <= (monster.getStats().getHp() * mortal.getX()) / 100) {
|
||||
if (Randomizer.rand(1, 100) <= mortal.getY()) {
|
||||
map.damageMonster(player, monster, Integer.MAX_VALUE); // thanks Conrad for noticing reduced EXP gain from skill kill
|
||||
map.damageMonster(player, monster, Integer.MAX_VALUE, target.getValue().delay()); // thanks Conrad for noticing reduced EXP gain from skill kill
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -479,7 +451,7 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
map.broadcastMessage(PacketCreator.damageMonster(monster.getObjectId(), totDamageToOneMonster));
|
||||
}
|
||||
|
||||
map.damageMonster(player, monster, totDamageToOneMonster);
|
||||
map.damageMonster(player, monster, totDamageToOneMonster, target.getValue().delay());
|
||||
}
|
||||
if (monster.isBuffed(MonsterStatus.WEAPON_REFLECT) && !attack.magic) {
|
||||
for (MobSkillId msId : monster.getSkills()) {
|
||||
@@ -506,7 +478,8 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private static void damageMonsterWithSkill(final Character attacker, final MapleMap map, final Monster monster, final int damage, int skillid, int fixedTime) {
|
||||
private static void damageMonsterWithSkill(final Character attacker, final MapleMap map, final Monster monster,
|
||||
final int damage, int skillid, int fixedTime) {
|
||||
int animationTime;
|
||||
|
||||
if (fixedTime == 0) {
|
||||
@@ -533,7 +506,7 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
ret.numAttackedAndDamage = p.readByte();
|
||||
ret.numAttacked = (ret.numAttackedAndDamage >>> 4) & 0xF;
|
||||
ret.numDamage = ret.numAttackedAndDamage & 0xF;
|
||||
ret.allDamage = new HashMap<>();
|
||||
ret.targets = new HashMap<>();
|
||||
ret.skill = p.readInt();
|
||||
ret.ranged = ranged;
|
||||
ret.magic = magic;
|
||||
@@ -556,41 +529,9 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
ret.direction = p.readByte();
|
||||
ret.stance = p.readByte();
|
||||
if (ret.skill == ChiefBandit.MESO_EXPLOSION) {
|
||||
if (ret.numAttackedAndDamage == 0) {
|
||||
p.skip(10);
|
||||
int bullets = p.readByte();
|
||||
for (int j = 0; j < bullets; j++) {
|
||||
int mesoid = p.readInt();
|
||||
p.skip(1);
|
||||
ret.allDamage.put(mesoid, null);
|
||||
}
|
||||
return ret;
|
||||
} else {
|
||||
p.skip(6);
|
||||
}
|
||||
for (int i = 0; i < ret.numAttacked + 1; i++) {
|
||||
int oid = p.readInt();
|
||||
if (i < ret.numAttacked) {
|
||||
p.skip(12);
|
||||
int bullets = p.readByte();
|
||||
List<Integer> allDamageNumbers = new ArrayList<>();
|
||||
for (int j = 0; j < bullets; j++) {
|
||||
int damage = p.readInt();
|
||||
allDamageNumbers.add(damage);
|
||||
}
|
||||
ret.allDamage.put(oid, allDamageNumbers);
|
||||
p.skip(4);
|
||||
} else {
|
||||
int bullets = p.readByte();
|
||||
for (int j = 0; j < bullets; j++) {
|
||||
int mesoid = p.readInt();
|
||||
p.skip(1);
|
||||
ret.allDamage.put(mesoid, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return parseMesoExplosion(p, ret);
|
||||
}
|
||||
|
||||
if (ranged) {
|
||||
p.readByte();
|
||||
ret.speed = p.readByte();
|
||||
@@ -622,9 +563,10 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
calcDmgMax = chr.calculateMaxBaseDamage(chr.getTotalWatk());
|
||||
}
|
||||
|
||||
StatEffect effect = null;
|
||||
if (ret.skill != 0) {
|
||||
Skill skill = SkillFactory.getSkill(ret.skill);
|
||||
StatEffect effect = skill.getEffect(ret.skilllevel);
|
||||
effect = skill.getEffect(ret.skilllevel);
|
||||
|
||||
if (magic) {
|
||||
// Since the skill is magic based, use the magic formula
|
||||
@@ -746,10 +688,12 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
}
|
||||
for (int i = 0; i < ret.numAttacked; i++) {
|
||||
int oid = p.readInt();
|
||||
p.skip(14);
|
||||
List<Integer> allDamageNumbers = new ArrayList<>();
|
||||
Monster monster = chr.getMap().getMonsterByOid(oid);
|
||||
|
||||
p.skip(4);
|
||||
Point curPos = p.readPos();
|
||||
Point nextPos = p.readPos();
|
||||
short delay = p.readShort();
|
||||
List<Integer> damageLines = new ArrayList<>();
|
||||
final Monster monster = chr.getMap().getMonsterByOid(oid);
|
||||
if (chr.getBuffEffect(BuffStat.WK_CHARGE) != null) {
|
||||
// Charge, so now we need to check elemental effectiveness
|
||||
int sourceID = chr.getBuffSource(BuffStat.WK_CHARGE);
|
||||
@@ -863,12 +807,22 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
damage = -Integer.MAX_VALUE + damage - 1;
|
||||
}
|
||||
|
||||
allDamageNumbers.add(damage);
|
||||
if(effect != null) {
|
||||
int maxattack = Math.max(effect.getBulletCount(), effect.getAttackCount());
|
||||
if (shadowPartner) {
|
||||
maxattack = maxattack * 2;
|
||||
}
|
||||
if (ret.numDamage > maxattack) {
|
||||
banService.addPoint(chr, AutobanFactory.DAMAGE_HACK, "Too many lines: " + ret.numDamage + " Max lines: " + maxattack + " SID: " + ret.skill + " MobID: " + (monster != null ? monster.getId() : "null") + " Map: " + chr.getMap().getMapName() + " (" + chr.getMapId() + ")");
|
||||
}
|
||||
}
|
||||
|
||||
damageLines.add(damage);
|
||||
}
|
||||
if (ret.skill != Corsair.RAPID_FIRE || ret.skill != Aran.HIDDEN_FULL_DOUBLE || ret.skill != Aran.HIDDEN_FULL_TRIPLE || ret.skill != Aran.HIDDEN_OVER_DOUBLE || ret.skill != Aran.HIDDEN_OVER_TRIPLE) {
|
||||
p.skip(4);
|
||||
}
|
||||
ret.allDamage.put(oid, allDamageNumbers);
|
||||
ret.targets.put(oid, new AttackTarget(delay, damageLines));
|
||||
}
|
||||
if (ret.skill == NightWalker.POISON_BOMB) { // Poison Bomb
|
||||
p.skip(4);
|
||||
@@ -877,7 +831,67 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static int rand(int l, int u) {
|
||||
return (int) ((Math.random() * (u - l + 1)) + l);
|
||||
private AttackInfo parseMesoExplosion(InPacket p, AttackInfo attackInfo) {
|
||||
p.skip(6);
|
||||
|
||||
Map<Integer, List<Integer>> targetDamage = new HashMap<>();
|
||||
for (int i = 0; i < attackInfo.numAttacked; i++) {
|
||||
int mobOid = p.readInt();
|
||||
p.skip(4);
|
||||
Point curPos = p.readPos();
|
||||
Point nextPos = p.readPos();
|
||||
int damageLines = p.readByte();
|
||||
List<Integer> allDamageNumbers = new ArrayList<>();
|
||||
for (int j = 0; j < damageLines; j++) {
|
||||
int damage = p.readInt();
|
||||
allDamageNumbers.add(damage);
|
||||
}
|
||||
p.skip(4);
|
||||
targetDamage.put(mobOid, allDamageNumbers);
|
||||
}
|
||||
|
||||
p.skip(4);
|
||||
|
||||
List<Integer> explodedMesos = new ArrayList<>();
|
||||
int explodedMesoCount = p.readByte();
|
||||
for (int j = 0; j < explodedMesoCount; j++) {
|
||||
int mesoOid = p.readInt();
|
||||
p.skip(1);
|
||||
explodedMesos.add(mesoOid);
|
||||
}
|
||||
attackInfo.explodedMesos = explodedMesos;
|
||||
|
||||
final short attackDelay = p.readShort();
|
||||
attackInfo.attackDelay = attackDelay;
|
||||
|
||||
Map<Integer, AttackTarget> targets = new HashMap<>();
|
||||
targetDamage.forEach((id, damage) -> targets.put(id, new AttackTarget(attackDelay, damage)));
|
||||
attackInfo.targets = targets;
|
||||
return attackInfo;
|
||||
}
|
||||
|
||||
private void removeExplodedMesos(MapleMap map, AttackInfo attack) {
|
||||
int index = 0;
|
||||
for (Integer mesoId : attack.explodedMesos) {
|
||||
MapObject mapobject = map.getMapObject(mesoId);
|
||||
if (!(mapobject instanceof MapItem mapItem)) {
|
||||
return;
|
||||
}
|
||||
if (mapItem.getMeso() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
mapItem.lockItem();
|
||||
try {
|
||||
if (mapItem.isPickedUp()) {
|
||||
return;
|
||||
}
|
||||
int delay = attack.attackDelay + (index++ % 5) * EXPLODED_MESO_SPREAD_DELAY;
|
||||
delay = Math.min(delay, EXPLODED_MESO_MAX_DELAY);
|
||||
map.pickItemDrop(PacketCreator.removeExplodedMesoFromMap(mapItem.getObjectId(), (short) delay), mapItem);
|
||||
} finally {
|
||||
mapItem.unlockItem();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,12 @@ import net.packet.InPacket;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import server.maps.AnimatedMapObject;
|
||||
import server.movement.*;
|
||||
import server.movement.AbsoluteLifeMovement;
|
||||
import server.movement.ChangeEquip;
|
||||
import server.movement.JumpDownMovement;
|
||||
import server.movement.LifeMovementFragment;
|
||||
import server.movement.RelativeLifeMovement;
|
||||
import server.movement.TeleportMovement;
|
||||
import tools.exceptions.EmptyMovementException;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
@@ -141,7 +141,7 @@ public final class AdminCommandHandler extends AbstractPacketHandler {
|
||||
for (int x = 0; x < amount; x++) {
|
||||
Monster monster = (Monster) monsterx.get(x);
|
||||
if (monster.getId() == mobToKill) {
|
||||
c.getPlayer().getMap().killMonster(monster, c.getPlayer(), true);
|
||||
c.getPlayer().getMap().killMonster(monster, c.getPlayer(), true, (short) 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -23,7 +23,14 @@ package net.server.channel.handlers;
|
||||
|
||||
import client.Client;
|
||||
import client.SkillFactory;
|
||||
import constants.skills.*;
|
||||
import constants.skills.Bishop;
|
||||
import constants.skills.Bowmaster;
|
||||
import constants.skills.Corsair;
|
||||
import constants.skills.Evan;
|
||||
import constants.skills.FPArchMage;
|
||||
import constants.skills.ILArchMage;
|
||||
import constants.skills.Marksman;
|
||||
import constants.skills.WindArcher;
|
||||
import net.AbstractPacketHandler;
|
||||
import net.PacketHandler;
|
||||
import net.packet.InPacket;
|
||||
@@ -53,4 +60,4 @@ public final class CancelBuffHandler extends AbstractPacketHandler implements Pa
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ public final class CashOperationHandler extends AbstractPacketHandler {
|
||||
CashItem cItem = CashItemFactory.getItem(p.readInt());
|
||||
Map<String, String> recipient = Character.getCharacterFromDatabase(p.readString());
|
||||
String message = p.readString();
|
||||
if (!canBuy(chr, cItem, cs.getCash(4)) || message.length() < 1 || message.length() > 73) {
|
||||
if (!canBuy(chr, cItem, cs.getCash(CashShop.NX_PREPAID)) || message.isEmpty() || message.length() > 73) {
|
||||
c.enableCSActions();
|
||||
return;
|
||||
}
|
||||
@@ -405,7 +405,7 @@ public final class CashOperationHandler extends AbstractPacketHandler {
|
||||
c.sendPacket(PacketCreator.showCash(c.getPlayer()));
|
||||
} else if (action == 0x2E) { //name change
|
||||
CashItem cItem = CashItemFactory.getItem(p.readInt());
|
||||
if (cItem == null || !canBuy(chr, cItem, cs.getCash(4))) {
|
||||
if (cItem == null || !canBuy(chr, cItem, cs.getCash(CashShop.NX_PREPAID))) {
|
||||
c.sendPacket(PacketCreator.showCashShopMessage((byte) 0));
|
||||
c.enableCSActions();
|
||||
return;
|
||||
@@ -434,7 +434,7 @@ public final class CashOperationHandler extends AbstractPacketHandler {
|
||||
c.enableCSActions();
|
||||
} else if (action == 0x31) { //world transfer
|
||||
CashItem cItem = CashItemFactory.getItem(p.readInt());
|
||||
if (cItem == null || !canBuy(chr, cItem, cs.getCash(4))) {
|
||||
if (cItem == null || !canBuy(chr, cItem, cs.getCash(CashShop.NX_PREPAID))) {
|
||||
c.sendPacket(PacketCreator.showCashShopMessage((byte) 0));
|
||||
c.enableCSActions();
|
||||
return;
|
||||
|
||||
@@ -24,26 +24,34 @@ import client.inventory.Item;
|
||||
import net.AbstractPacketHandler;
|
||||
import net.packet.InPacket;
|
||||
import server.CashShop;
|
||||
import server.CashShop.CashShopSurpriseResult;
|
||||
import tools.PacketCreator;
|
||||
import tools.Pair;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author RonanLana
|
||||
* @author Ponk
|
||||
*/
|
||||
public class CashShopSurpriseHandler extends AbstractPacketHandler {
|
||||
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
CashShop cs = c.getPlayer().getCashShop();
|
||||
|
||||
if (cs.isOpened()) {
|
||||
Pair<Item, Item> cssResult = cs.openCashShopSurprise();
|
||||
|
||||
if (cssResult != null) {
|
||||
Item cssItem = cssResult.getLeft(), cssBox = cssResult.getRight();
|
||||
c.sendPacket(PacketCreator.onCashGachaponOpenSuccess(c.getAccID(), cssBox.getSN(), cssBox.getQuantity(), cssItem, cssItem.getItemId(), cssItem.getQuantity(), true));
|
||||
} else {
|
||||
c.sendPacket(PacketCreator.onCashItemGachaponOpenFailed());
|
||||
}
|
||||
if (!cs.isOpened()) {
|
||||
return;
|
||||
}
|
||||
|
||||
long cashId = p.readLong();
|
||||
Optional<CashShopSurpriseResult> result = cs.openCashShopSurprise(cashId);
|
||||
if (result.isEmpty()) {
|
||||
c.sendPacket(PacketCreator.onCashItemGachaponOpenFailed());
|
||||
return;
|
||||
}
|
||||
|
||||
Item usedCashShopSurprise = result.get().usedCashShopSurprise();
|
||||
Item reward = result.get().reward();
|
||||
c.sendPacket(PacketCreator.onCashGachaponOpenSuccess(c.getAccID(), usedCashShopSurprise.getCashId(),
|
||||
usedCashShopSurprise.getQuantity(), reward, reward.getItemId(), reward.getQuantity(), true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,14 +21,24 @@
|
||||
*/
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import client.BuffStat;
|
||||
import client.Character;
|
||||
import client.*;
|
||||
import client.Client;
|
||||
import client.Job;
|
||||
import client.Skill;
|
||||
import client.SkillFactory;
|
||||
import config.YamlConfig;
|
||||
import constants.game.GameConstants;
|
||||
import constants.id.MapId;
|
||||
import constants.skills.*;
|
||||
import database.drop.DropProvider;
|
||||
import net.netty.GameViolationException;
|
||||
import constants.skills.Crusader;
|
||||
import constants.skills.DawnWarrior;
|
||||
import constants.skills.DragonKnight;
|
||||
import constants.skills.Hero;
|
||||
import constants.skills.NightWalker;
|
||||
import constants.skills.Rogue;
|
||||
import constants.skills.WindArcher;
|
||||
import net.packet.InPacket;
|
||||
import server.StatEffect;
|
||||
import service.BanService;
|
||||
@@ -71,7 +81,9 @@ public final class CloseRangeDamageHandler extends AbstractDealDamageHandler {
|
||||
c.sendPacket(PacketCreator.getEnergy("energy", chr.getDojoEnergy()));
|
||||
}
|
||||
|
||||
chr.getMap().broadcastMessage(chr, PacketCreator.closeRangeAttack(chr, attack.skill, attack.skilllevel, attack.stance, attack.numAttackedAndDamage, attack.allDamage, attack.speed, attack.direction, attack.display), false, true);
|
||||
chr.getMap().broadcastMessage(chr, PacketCreator.closeRangeAttack(chr, attack.skill, attack.skilllevel,
|
||||
attack.stance, attack.numAttackedAndDamage, attack.targets, attack.speed, attack.direction,
|
||||
attack.display), false, true);
|
||||
int numFinisherOrbs = 0;
|
||||
Integer comboBuff = chr.getBuffedValue(BuffStat.COMBO);
|
||||
if (GameConstants.isFinisherSkill(attack.skill)) {
|
||||
@@ -132,9 +144,9 @@ public final class CloseRangeDamageHandler extends AbstractDealDamageHandler {
|
||||
}
|
||||
if (attack.numAttacked > 0 && attack.skill == DragonKnight.SACRIFICE) {
|
||||
int totDamageToOneMonster = 0; // sacrifice attacks only 1 mob with 1 attack
|
||||
final Iterator<List<Integer>> dmgIt = attack.allDamage.values().iterator();
|
||||
final Iterator<AttackTarget> dmgIt = attack.targets.values().iterator();
|
||||
if (dmgIt.hasNext()) {
|
||||
totDamageToOneMonster = dmgIt.next().get(0);
|
||||
totDamageToOneMonster = dmgIt.next().damageLines().getFirst();
|
||||
}
|
||||
|
||||
chr.safeAddHP(-1 * totDamageToOneMonster * attack.getAttackEffect(chr, null).getX() / 100);
|
||||
|
||||
@@ -42,7 +42,11 @@ import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,7 +25,6 @@ import client.Character;
|
||||
import client.Client;
|
||||
import client.inventory.Equip;
|
||||
import client.inventory.Item;
|
||||
import client.processor.action.BuybackProcessor;
|
||||
import config.YamlConfig;
|
||||
import database.character.CharacterSaver;
|
||||
import net.AbstractPacketHandler;
|
||||
@@ -52,136 +51,132 @@ public final class EnterMTSHandler extends AbstractPacketHandler {
|
||||
this.chrSaver = chrSaver;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
public void handlePacket(InPacket p, Client c) {
|
||||
Character chr = c.getPlayer();
|
||||
|
||||
if (!chr.isAlive() && YamlConfig.config.server.USE_BUYBACK_SYSTEM) {
|
||||
BuybackProcessor.processBuyback(c);
|
||||
if (!YamlConfig.config.server.USE_MTS) {
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
} else {
|
||||
if (!YamlConfig.config.server.USE_MTS) {
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (chr.getEventInstance() != null) {
|
||||
c.sendPacket(PacketCreator.serverNotice(5, "Entering Cash Shop or MTS are disabled when registered on an event."));
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
if (chr.getEventInstance() != null) {
|
||||
c.sendPacket(PacketCreator.serverNotice(5, "Entering Cash Shop or MTS are disabled when registered on an event."));
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
if (MiniDungeonInfo.isDungeonMap(chr.getMapId())) {
|
||||
c.sendPacket(PacketCreator.serverNotice(5, "Changing channels or entering Cash Shop or MTS are disabled when inside a Mini-Dungeon."));
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
if (MiniDungeonInfo.isDungeonMap(chr.getMapId())) {
|
||||
c.sendPacket(PacketCreator.serverNotice(5, "Changing channels or entering Cash Shop or MTS are disabled when inside a Mini-Dungeon."));
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
if (FieldLimit.CANNOTMIGRATE.check(chr.getMap().getFieldLimit())) {
|
||||
chr.dropMessage(1, "You can't do it here in this map.");
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
if (FieldLimit.CANNOTMIGRATE.check(chr.getMap().getFieldLimit())) {
|
||||
chr.dropMessage(1, "You can't do it here in this map.");
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!chr.isAlive()) {
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
if (chr.getLevel() < 10) {
|
||||
c.sendPacket(PacketCreator.blockedMessage2(5));
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
if (!chr.isAlive()) {
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
if (chr.getLevel() < 10) {
|
||||
c.sendPacket(PacketCreator.blockedMessage2(5));
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
chr.closePlayerInteractions();
|
||||
chr.closePartySearchInteractions();
|
||||
chr.closePlayerInteractions();
|
||||
chr.closePartySearchInteractions();
|
||||
|
||||
chr.unregisterChairBuff();
|
||||
Server.getInstance().getPlayerBuffStorage().addBuffsToStorage(chr.getId(), chr.getAllBuffs());
|
||||
Server.getInstance().getPlayerBuffStorage().addDiseasesToStorage(chr.getId(), chr.getAllDiseases());
|
||||
chr.setAwayFromChannelWorld();
|
||||
chr.notifyMapTransferToPartner(-1);
|
||||
chr.removeIncomingInvites();
|
||||
chr.cancelAllBuffs(true);
|
||||
chr.cancelAllDebuffs();
|
||||
chr.cancelBuffExpireTask();
|
||||
chr.cancelDiseaseExpireTask();
|
||||
chr.cancelSkillCooldownTask();
|
||||
chr.cancelExpirationTask();
|
||||
chr.unregisterChairBuff();
|
||||
Server.getInstance().getPlayerBuffStorage().addBuffsToStorage(chr.getId(), chr.getAllBuffs());
|
||||
Server.getInstance().getPlayerBuffStorage().addDiseasesToStorage(chr.getId(), chr.getAllDiseases());
|
||||
chr.setAwayFromChannelWorld();
|
||||
chr.notifyMapTransferToPartner(-1);
|
||||
chr.removeIncomingInvites();
|
||||
chr.cancelAllBuffs(true);
|
||||
chr.cancelAllDebuffs();
|
||||
chr.cancelBuffExpireTask();
|
||||
chr.cancelDiseaseExpireTask();
|
||||
chr.cancelSkillCooldownTask();
|
||||
chr.cancelExpirationTask();
|
||||
|
||||
chr.forfeitExpirableQuests();
|
||||
chr.cancelQuestExpirationTask();
|
||||
chr.forfeitExpirableQuests();
|
||||
chr.cancelQuestExpirationTask();
|
||||
|
||||
chrSaver.save(chr);
|
||||
|
||||
c.getChannelServer().removePlayer(chr);
|
||||
chr.getMap().removePlayer(c.getPlayer());
|
||||
try {
|
||||
c.sendPacket(PacketCreator.openCashShop(c, true));
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
chr.getCashShop().open(true);// xD
|
||||
c.enableCSActions();
|
||||
c.sendPacket(PacketCreator.MTSWantedListingOver(0, 0));
|
||||
c.sendPacket(PacketCreator.showMTSCash(c.getPlayer()));
|
||||
List<MTSItemInfo> items = new ArrayList<>();
|
||||
int pages = 0;
|
||||
try (Connection con = DatabaseConnection.getConnection()) {
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM mts_items WHERE tab = 1 AND transfer = 0 ORDER BY id DESC LIMIT 16, 16");
|
||||
ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
if (rs.getInt("type") != 1) {
|
||||
Item i = new Item(rs.getInt("itemid"), (short) 0, (short) rs.getInt("quantity"));
|
||||
i.setOwner(rs.getString("owner"));
|
||||
items.add(new MTSItemInfo(i, rs.getInt("price") + 100 + (int) (rs.getInt("price") * 0.1), rs.getInt("id"), rs.getInt("seller"), rs.getString("sellername"), rs.getString("sell_ends")));
|
||||
} else {
|
||||
Equip equip = new Equip(rs.getInt("itemid"), (byte) rs.getInt("position"), -1);
|
||||
equip.setOwner(rs.getString("owner"));
|
||||
equip.setQuantity((short) 1);
|
||||
equip.setAcc((short) rs.getInt("acc"));
|
||||
equip.setAvoid((short) rs.getInt("avoid"));
|
||||
equip.setDex((short) rs.getInt("dex"));
|
||||
equip.setHands((short) rs.getInt("hands"));
|
||||
equip.setHp((short) rs.getInt("hp"));
|
||||
equip.setInt((short) rs.getInt("int"));
|
||||
equip.setJump((short) rs.getInt("jump"));
|
||||
equip.setVicious((short) rs.getInt("vicious"));
|
||||
equip.setFlag((short) rs.getInt("flag"));
|
||||
equip.setLuk((short) rs.getInt("luk"));
|
||||
equip.setMatk((short) rs.getInt("matk"));
|
||||
equip.setMdef((short) rs.getInt("mdef"));
|
||||
equip.setMp((short) rs.getInt("mp"));
|
||||
equip.setSpeed((short) rs.getInt("speed"));
|
||||
equip.setStr((short) rs.getInt("str"));
|
||||
equip.setWatk((short) rs.getInt("watk"));
|
||||
equip.setWdef((short) rs.getInt("wdef"));
|
||||
equip.setUpgradeSlots((byte) rs.getInt("upgradeslots"));
|
||||
equip.setLevel((byte) rs.getInt("level"));
|
||||
equip.setItemLevel(rs.getByte("itemlevel"));
|
||||
equip.setItemExp(rs.getInt("itemexp"));
|
||||
equip.setRingId(rs.getInt("ringid"));
|
||||
equip.setExpiration(rs.getLong("expiration"));
|
||||
equip.setGiftFrom(rs.getString("giftFrom"));
|
||||
|
||||
items.add(new MTSItemInfo(equip, rs.getInt("price") + 100 + (int) (rs.getInt("price") * 0.1), rs.getInt("id"), rs.getInt("seller"), rs.getString("sellername"), rs.getString("sell_ends")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT COUNT(*) FROM mts_items");
|
||||
ResultSet rs = ps.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
pages = (int) Math.ceil(rs.getInt(1) / 16);
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
c.sendPacket(PacketCreator.sendMTS(items, 1, 0, 0, pages));
|
||||
c.sendPacket(PacketCreator.transferInventory(getTransfer(chr.getId())));
|
||||
c.sendPacket(PacketCreator.notYetSoldInv(getNotYetSold(chr.getId())));
|
||||
c.getChannelServer().removePlayer(chr);
|
||||
chr.getMap().removePlayer(c.getPlayer());
|
||||
try {
|
||||
c.sendPacket(PacketCreator.openCashShop(c, true));
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
chr.getCashShop().open(true);// xD
|
||||
c.enableCSActions();
|
||||
c.sendPacket(PacketCreator.MTSWantedListingOver(0, 0));
|
||||
c.sendPacket(PacketCreator.showMTSCash(c.getPlayer()));
|
||||
List<MTSItemInfo> items = new ArrayList<>();
|
||||
int pages = 0;
|
||||
try (Connection con = DatabaseConnection.getConnection()) {
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM mts_items WHERE tab = 1 AND transfer = 0 ORDER BY id DESC LIMIT 16, 16");
|
||||
ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
if (rs.getInt("type") != 1) {
|
||||
Item i = new Item(rs.getInt("itemid"), (short) 0, (short) rs.getInt("quantity"));
|
||||
i.setOwner(rs.getString("owner"));
|
||||
items.add(new MTSItemInfo(i, rs.getInt("price") + 100 + (int) (rs.getInt("price") * 0.1), rs.getInt("id"), rs.getInt("seller"), rs.getString("sellername"), rs.getString("sell_ends")));
|
||||
} else {
|
||||
Equip equip = new Equip(rs.getInt("itemid"), (byte) rs.getInt("position"), -1);
|
||||
equip.setOwner(rs.getString("owner"));
|
||||
equip.setQuantity((short) 1);
|
||||
equip.setAcc((short) rs.getInt("acc"));
|
||||
equip.setAvoid((short) rs.getInt("avoid"));
|
||||
equip.setDex((short) rs.getInt("dex"));
|
||||
equip.setHands((short) rs.getInt("hands"));
|
||||
equip.setHp((short) rs.getInt("hp"));
|
||||
equip.setInt((short) rs.getInt("int"));
|
||||
equip.setJump((short) rs.getInt("jump"));
|
||||
equip.setVicious((short) rs.getInt("vicious"));
|
||||
equip.setFlag((short) rs.getInt("flag"));
|
||||
equip.setLuk((short) rs.getInt("luk"));
|
||||
equip.setMatk((short) rs.getInt("matk"));
|
||||
equip.setMdef((short) rs.getInt("mdef"));
|
||||
equip.setMp((short) rs.getInt("mp"));
|
||||
equip.setSpeed((short) rs.getInt("speed"));
|
||||
equip.setStr((short) rs.getInt("str"));
|
||||
equip.setWatk((short) rs.getInt("watk"));
|
||||
equip.setWdef((short) rs.getInt("wdef"));
|
||||
equip.setUpgradeSlots((byte) rs.getInt("upgradeslots"));
|
||||
equip.setLevel((byte) rs.getInt("level"));
|
||||
equip.setItemLevel(rs.getByte("itemlevel"));
|
||||
equip.setItemExp(rs.getInt("itemexp"));
|
||||
equip.setRingId(rs.getInt("ringid"));
|
||||
equip.setExpiration(rs.getLong("expiration"));
|
||||
equip.setGiftFrom(rs.getString("giftFrom"));
|
||||
|
||||
items.add(new MTSItemInfo(equip, rs.getInt("price") + 100 + (int) (rs.getInt("price") * 0.1), rs.getInt("id"), rs.getInt("seller"), rs.getString("sellername"), rs.getString("sell_ends")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT COUNT(*) FROM mts_items");
|
||||
ResultSet rs = ps.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
pages = (int) Math.ceil(rs.getInt(1) / 16);
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
c.sendPacket(PacketCreator.sendMTS(items, 1, 0, 0, pages));
|
||||
c.sendPacket(PacketCreator.transferInventory(getTransfer(chr.getId())));
|
||||
c.sendPacket(PacketCreator.notYetSoldInv(getNotYetSold(chr.getId())));
|
||||
}
|
||||
|
||||
private List<MTSItemInfo> getNotYetSold(int cid) {
|
||||
|
||||
@@ -23,7 +23,11 @@ package net.server.channel.handlers;
|
||||
|
||||
import client.Character;
|
||||
import client.Client;
|
||||
import client.inventory.*;
|
||||
import client.inventory.Equip;
|
||||
import client.inventory.Inventory;
|
||||
import client.inventory.InventoryType;
|
||||
import client.inventory.Item;
|
||||
import client.inventory.ModifyInventory;
|
||||
import config.YamlConfig;
|
||||
import net.AbstractPacketHandler;
|
||||
import net.netty.GameViolationException;
|
||||
|
||||
@@ -35,6 +35,7 @@ import net.server.Server;
|
||||
import net.server.channel.Channel;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import server.CashShop;
|
||||
import server.ItemInformationProvider;
|
||||
import server.MTSItemInfo;
|
||||
import tools.DatabaseConnection;
|
||||
@@ -48,7 +49,6 @@ import java.sql.SQLException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
|
||||
public final class MTSHandler extends AbstractPacketHandler {
|
||||
@@ -403,7 +403,7 @@ public final class MTSHandler extends AbstractPacketHandler {
|
||||
ResultSet rs = ps.executeQuery();
|
||||
if (rs.next()) {
|
||||
int price = rs.getInt("price") + 100 + (int) (rs.getInt("price") * 0.1); // taxes
|
||||
if (c.getPlayer().getCashShop().getCash(4) >= price) { // FIX
|
||||
if (c.getPlayer().getCashShop().getCash(CashShop.NX_PREPAID) >= price) { // FIX
|
||||
boolean alwaysnull = true;
|
||||
for (Channel cserv : Server.getInstance().getAllChannels()) {
|
||||
Character victim = cserv.getPlayerStorage().getCharacterById(rs.getInt("seller"));
|
||||
@@ -460,11 +460,11 @@ public final class MTSHandler extends AbstractPacketHandler {
|
||||
ResultSet rs = ps.executeQuery();
|
||||
if (rs.next()) {
|
||||
int price = rs.getInt("price") + 100 + (int) (rs.getInt("price") * 0.1);
|
||||
if (c.getPlayer().getCashShop().getCash(4) >= price) {
|
||||
if (c.getPlayer().getCashShop().getCash(CashShop.NX_PREPAID) >= price) {
|
||||
for (Channel cserv : Server.getInstance().getAllChannels()) {
|
||||
Character victim = cserv.getPlayerStorage().getCharacterById(rs.getInt("seller"));
|
||||
if (victim != null) {
|
||||
victim.getCashShop().gainCash(4, rs.getInt("price"));
|
||||
victim.getCashShop().gainCash(CashShop.NX_PREPAID, rs.getInt("price"));
|
||||
} else {
|
||||
try (PreparedStatement pse = con.prepareStatement("SELECT accountid FROM characters WHERE id = ?")) {
|
||||
pse.setInt(1, rs.getInt("seller"));
|
||||
|
||||
@@ -21,8 +21,11 @@
|
||||
*/
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import client.BuffStat;
|
||||
import client.Character;
|
||||
import client.*;
|
||||
import client.Client;
|
||||
import client.Skill;
|
||||
import client.SkillFactory;
|
||||
import config.YamlConfig;
|
||||
import constants.id.MapId;
|
||||
import constants.skills.Bishop;
|
||||
@@ -68,7 +71,8 @@ public final class MagicDamageHandler extends AbstractDealDamageHandler {
|
||||
}
|
||||
|
||||
int charge = (attack.skill == Evan.FIRE_BREATH || attack.skill == Evan.ICE_BREATH || attack.skill == FPArchMage.BIG_BANG || attack.skill == ILArchMage.BIG_BANG || attack.skill == Bishop.BIG_BANG) ? attack.charge : -1;
|
||||
Packet packet = PacketCreator.magicAttack(chr, attack.skill, attack.skilllevel, attack.stance, attack.numAttackedAndDamage, attack.allDamage, charge, attack.speed, attack.direction, attack.display);
|
||||
Packet packet = PacketCreator.magicAttack(chr, attack.skill, attack.skilllevel, attack.stance,
|
||||
attack.numAttackedAndDamage, attack.targets, charge, attack.speed, attack.direction, attack.display);
|
||||
|
||||
chr.getMap().broadcastMessage(chr, packet, false, true);
|
||||
StatEffect effect = attack.getAttackEffect(chr, null);
|
||||
@@ -86,8 +90,8 @@ public final class MagicDamageHandler extends AbstractDealDamageHandler {
|
||||
Skill eaterSkill = SkillFactory.getSkill((chr.getJob().getId() - (chr.getJob().getId() % 10)) * 10000);// MP Eater, works with right job
|
||||
int eaterLevel = chr.getSkillLevel(eaterSkill);
|
||||
if (eaterLevel > 0) {
|
||||
for (Integer singleDamage : attack.allDamage.keySet()) {
|
||||
eaterSkill.getEffect(eaterLevel).applyPassive(chr, chr.getMap().getMapObject(singleDamage), 0);
|
||||
for (Integer oid : attack.targets.keySet()) {
|
||||
eaterSkill.getEffect(eaterLevel).applyPassive(chr, chr.getMap().getMapObject(oid), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,8 @@ public final class MesoDropHandler extends AbstractPacketHandler {
|
||||
if (player.attemptCatchFish(meso)) {
|
||||
player.getMap().disappearingMesoDrop(meso, player, player, player.getPosition());
|
||||
} else {
|
||||
player.getMap().spawnMesoDrop(meso, player.getPosition(), player, player, true, (byte) 2);
|
||||
player.getMap().spawnMesoDrop(meso, player.getPosition(), player, player, true, (byte) 2,
|
||||
(short) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,23 +23,25 @@ import client.Character;
|
||||
import client.Client;
|
||||
import net.AbstractPacketHandler;
|
||||
import net.packet.InPacket;
|
||||
import server.life.LifeFactory.BanishInfo;
|
||||
import server.life.BanishInfo;
|
||||
import server.life.Monster;
|
||||
|
||||
public final class MobBanishPlayerHandler extends AbstractPacketHandler {
|
||||
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
int mobid = p.readInt(); // mob banish handling detected thanks to MedicOP
|
||||
public void handlePacket(InPacket p, Client c) {
|
||||
int mobId = p.readInt(); // mob banish handling detected thanks to MedicOP
|
||||
|
||||
Character chr = c.getPlayer();
|
||||
Monster mob = chr.getMap().getMonsterById(mobid);
|
||||
|
||||
if (mob != null) {
|
||||
BanishInfo banishInfo = mob.getBanish();
|
||||
if (banishInfo != null) {
|
||||
chr.changeMapBanish(banishInfo.getMap(), banishInfo.getPortal(), banishInfo.getMsg());
|
||||
}
|
||||
Monster mob = chr.getMap().getMonsterById(mobId);
|
||||
if (mob == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
BanishInfo banishInfo = mob.getBanish();
|
||||
if (banishInfo == null) {
|
||||
return;
|
||||
}
|
||||
chr.changeMapBanish(banishInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,21 +57,24 @@ public final class MobDamageMobHandler extends AbstractPacketHandler {
|
||||
Monster attacker = map.getMonsterByOid(from);
|
||||
Monster damaged = map.getMonsterByOid(to);
|
||||
|
||||
if (attacker != null && damaged != null) {
|
||||
int maxDmg = calcMaxDamage(attacker, damaged, magic); // thanks Darter (YungMoozi) for reporting unchecked dmg
|
||||
|
||||
if (dmg > maxDmg) {
|
||||
AutobanFactory.DAMAGE_HACK.alert(c.getPlayer(), "Possible packet editing hypnotize damage exploit."); // thanks Rien dev team
|
||||
String attackerName = MonsterInformationProvider.getInstance().getMobNameFromId(attacker.getId());
|
||||
String damagedName = MonsterInformationProvider.getInstance().getMobNameFromId(damaged.getId());
|
||||
log.warn("Chr {} had hypnotized {} to attack {} with damage {} (max: {})", c.getPlayer().getName(),
|
||||
attackerName, damagedName, dmg, maxDmg);
|
||||
dmg = maxDmg;
|
||||
}
|
||||
|
||||
map.damageMonster(chr, damaged, dmg);
|
||||
map.broadcastMessage(chr, PacketCreator.damageMonster(to, dmg), false);
|
||||
if (attacker == null || damaged == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int maxDmg = calcMaxDamage(attacker, damaged, magic); // thanks Darter (YungMoozi) for reporting unchecked dmg
|
||||
|
||||
if (dmg > maxDmg) {
|
||||
AutobanFactory.DAMAGE_HACK.alert(c.getPlayer(), "Possible packet editing hypnotize damage exploit."); // thanks Rien dev team
|
||||
String attackerName = MonsterInformationProvider.getInstance().getMobNameFromId(attacker.getId());
|
||||
String damagedName = MonsterInformationProvider.getInstance().getMobNameFromId(damaged.getId());
|
||||
log.warn("Chr {} had hypnotized {} to attack {} with damage {} (max: {})", c.getPlayer().getName(),
|
||||
attackerName, damagedName, dmg, maxDmg);
|
||||
dmg = maxDmg;
|
||||
}
|
||||
|
||||
map.damageMonster(chr, damaged, dmg);
|
||||
map.broadcastMessage(chr, PacketCreator.damageMonster(to, dmg), false);
|
||||
|
||||
}
|
||||
|
||||
private static int calcMaxDamage(Monster attacker, Monster damaged, boolean magic) {
|
||||
|
||||
@@ -27,7 +27,12 @@ import config.YamlConfig;
|
||||
import net.packet.InPacket;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import server.life.*;
|
||||
import server.life.MobSkill;
|
||||
import server.life.MobSkillFactory;
|
||||
import server.life.MobSkillId;
|
||||
import server.life.MobSkillType;
|
||||
import server.life.Monster;
|
||||
import server.life.MonsterInformationProvider;
|
||||
import server.maps.MapObject;
|
||||
import server.maps.MapObjectType;
|
||||
import server.maps.MapleMap;
|
||||
@@ -168,7 +173,7 @@ public final class MoveLifeHandler extends AbstractMovementPacketHandler {
|
||||
|
||||
if (banishPlayers != null) {
|
||||
for (Character chr : banishPlayers) {
|
||||
chr.changeMapBanish(monster.getBanish().getMap(), monster.getBanish().getPortal(), monster.getBanish().getMsg());
|
||||
chr.changeMapBanish(monster.getBanish());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -176,4 +181,4 @@ public final class MoveLifeHandler extends AbstractMovementPacketHandler {
|
||||
private static boolean inRangeInclusive(Byte pVal, Integer pMin, Integer pMax) {
|
||||
return !(pVal < pMin) || (pVal > pMax);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,8 +76,6 @@ public final class NPCTalkHandler extends AbstractPacketHandler {
|
||||
NPCScriptManager.getInstance().start(c, npc.getId(), "gachapon");
|
||||
} else if (npc.getName().endsWith("Maple TV")) {
|
||||
NPCScriptManager.getInstance().start(c, npc.getId(), "mapleTV");
|
||||
} else if (YamlConfig.config.server.USE_REBIRTH_SYSTEM && npc.getId() == YamlConfig.config.server.REBIRTH_NPC_ID) {
|
||||
NPCScriptManager.getInstance().start(c, npc.getId(), "rebirth");
|
||||
} else {
|
||||
boolean hasNpcScript = NPCScriptManager.getInstance().start(c, npc.getId(), oid, null);
|
||||
if (!hasNpcScript) {
|
||||
|
||||
@@ -41,8 +41,15 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import server.ItemInformationProvider;
|
||||
import server.Trade;
|
||||
import server.maps.*;
|
||||
import server.maps.FieldLimit;
|
||||
import server.maps.HiredMerchant;
|
||||
import server.maps.MapObject;
|
||||
import server.maps.MapObjectType;
|
||||
import server.maps.MiniGame;
|
||||
import server.maps.MiniGame.MiniGameType;
|
||||
import server.maps.PlayerShop;
|
||||
import server.maps.PlayerShopItem;
|
||||
import server.maps.Portal;
|
||||
import tools.PacketCreator;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
@@ -21,9 +21,20 @@
|
||||
*/
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import client.BuddyList;
|
||||
import client.BuddylistEntry;
|
||||
import client.Character;
|
||||
import client.*;
|
||||
import client.inventory.*;
|
||||
import client.Client;
|
||||
import client.Disease;
|
||||
import client.Family;
|
||||
import client.FamilyEntry;
|
||||
import client.Mount;
|
||||
import client.SkillFactory;
|
||||
import client.inventory.Equip;
|
||||
import client.inventory.Inventory;
|
||||
import client.inventory.InventoryType;
|
||||
import client.inventory.Item;
|
||||
import client.inventory.Pet;
|
||||
import client.keybind.KeyBinding;
|
||||
import config.YamlConfig;
|
||||
import constants.game.GameConstants;
|
||||
@@ -59,8 +70,14 @@ import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public final class PlayerLoggedinHandler extends AbstractPacketHandler {
|
||||
@@ -423,11 +440,6 @@ public final class PlayerLoggedinHandler extends AbstractPacketHandler {
|
||||
Entry::getValue
|
||||
));
|
||||
|
||||
// Any npc be specified as the rebirth npc. Allow the npc to use custom scripts explicitly.
|
||||
if (YamlConfig.config.server.USE_REBIRTH_SYSTEM) {
|
||||
npcsIds.put(YamlConfig.config.server.REBIRTH_NPC_ID, "Rebirth");
|
||||
}
|
||||
|
||||
c.sendPacket(PacketCreator.setNPCScriptable(npcsIds));
|
||||
}
|
||||
|
||||
|
||||
@@ -21,8 +21,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import client.BuffStat;
|
||||
import client.Character;
|
||||
import client.*;
|
||||
import client.Client;
|
||||
import client.Skill;
|
||||
import client.SkillFactory;
|
||||
import client.inventory.Inventory;
|
||||
import client.inventory.InventoryType;
|
||||
import client.inventory.Item;
|
||||
@@ -32,7 +35,13 @@ import config.YamlConfig;
|
||||
import constants.id.ItemId;
|
||||
import constants.id.MapId;
|
||||
import constants.inventory.ItemConstants;
|
||||
import constants.skills.*;
|
||||
import constants.skills.Aran;
|
||||
import constants.skills.Buccaneer;
|
||||
import constants.skills.NightLord;
|
||||
import constants.skills.NightWalker;
|
||||
import constants.skills.Shadower;
|
||||
import constants.skills.ThunderBreaker;
|
||||
import constants.skills.WindArcher;
|
||||
import database.drop.DropProvider;
|
||||
import net.netty.GameViolationException;
|
||||
import net.packet.InPacket;
|
||||
@@ -79,17 +88,23 @@ public final class RangedAttackHandler extends AbstractDealDamageHandler {
|
||||
}
|
||||
|
||||
if (attack.skill == Buccaneer.ENERGY_ORB || attack.skill == ThunderBreaker.SPARK || attack.skill == Shadower.TAUNT || attack.skill == NightLord.TAUNT) {
|
||||
chr.getMap().broadcastMessage(chr, PacketCreator.rangedAttack(chr, attack.skill, attack.skilllevel, attack.stance, attack.numAttackedAndDamage, 0, attack.allDamage, attack.speed, attack.direction, attack.display), false);
|
||||
chr.getMap().broadcastMessage(chr, PacketCreator.rangedAttack(chr, attack.skill, attack.skilllevel,
|
||||
attack.stance, attack.numAttackedAndDamage, 0, attack.targets, attack.speed,
|
||||
attack.direction, attack.display), false);
|
||||
applyAttack(attack, chr, 1);
|
||||
} else if (attack.skill == ThunderBreaker.SHARK_WAVE && chr.getSkillLevel(ThunderBreaker.SHARK_WAVE) > 0) {
|
||||
chr.getMap().broadcastMessage(chr, PacketCreator.rangedAttack(chr, attack.skill, attack.skilllevel, attack.stance, attack.numAttackedAndDamage, 0, attack.allDamage, attack.speed, attack.direction, attack.display), false);
|
||||
chr.getMap().broadcastMessage(chr, PacketCreator.rangedAttack(chr, attack.skill, attack.skilllevel,
|
||||
attack.stance, attack.numAttackedAndDamage, 0, attack.targets, attack.speed,
|
||||
attack.direction, attack.display), false);
|
||||
applyAttack(attack, chr, 1);
|
||||
|
||||
for (int i = 0; i < attack.numAttacked; i++) {
|
||||
chr.handleEnergyChargeGain();
|
||||
}
|
||||
} else if (attack.skill == Aran.COMBO_SMASH || attack.skill == Aran.COMBO_FENRIR || attack.skill == Aran.COMBO_TEMPEST) {
|
||||
chr.getMap().broadcastMessage(chr, PacketCreator.rangedAttack(chr, attack.skill, attack.skilllevel, attack.stance, attack.numAttackedAndDamage, 0, attack.allDamage, attack.speed, attack.direction, attack.display), false);
|
||||
chr.getMap().broadcastMessage(chr, PacketCreator.rangedAttack(chr, attack.skill, attack.skilllevel,
|
||||
attack.stance, attack.numAttackedAndDamage, 0, attack.targets, attack.speed,
|
||||
attack.direction, attack.display), false);
|
||||
if (attack.skill == Aran.COMBO_SMASH && chr.getCombo() >= 30) {
|
||||
chr.setCombo((short) 0);
|
||||
applyAttack(attack, chr, 1);
|
||||
@@ -209,10 +224,14 @@ public final class RangedAttackHandler extends AbstractDealDamageHandler {
|
||||
case 3221001: // Pierce
|
||||
case 5221004: // Rapid Fire
|
||||
case 13111002: // KoC Hurricane
|
||||
packet = PacketCreator.rangedAttack(chr, attack.skill, attack.skilllevel, attack.rangedirection, attack.numAttackedAndDamage, visProjectile, attack.allDamage, attack.speed, attack.direction, attack.display);
|
||||
packet = PacketCreator.rangedAttack(chr, attack.skill, attack.skilllevel, attack.rangedirection,
|
||||
attack.numAttackedAndDamage, visProjectile, attack.targets, attack.speed,
|
||||
attack.direction, attack.display);
|
||||
break;
|
||||
default:
|
||||
packet = PacketCreator.rangedAttack(chr, attack.skill, attack.skilllevel, attack.stance, attack.numAttackedAndDamage, visProjectile, attack.allDamage, attack.speed, attack.direction, attack.display);
|
||||
packet = PacketCreator.rangedAttack(chr, attack.skill, attack.skilllevel, attack.stance,
|
||||
attack.numAttackedAndDamage, visProjectile, attack.targets, attack.speed,
|
||||
attack.direction, attack.display);
|
||||
break;
|
||||
}
|
||||
chr.getMap().broadcastMessage(chr, packet, false, true);
|
||||
|
||||
@@ -25,8 +25,12 @@ import client.Character;
|
||||
import client.Client;
|
||||
import client.Skill;
|
||||
import client.SkillFactory;
|
||||
import client.inventory.*;
|
||||
import client.inventory.Equip;
|
||||
import client.inventory.Equip.ScrollResult;
|
||||
import client.inventory.Inventory;
|
||||
import client.inventory.InventoryType;
|
||||
import client.inventory.Item;
|
||||
import client.inventory.ModifyInventory;
|
||||
import client.inventory.manipulator.InventoryManipulator;
|
||||
import constants.id.ItemId;
|
||||
import constants.inventory.ItemConstants;
|
||||
@@ -37,7 +41,6 @@ import tools.PacketCreator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Matze
|
||||
@@ -50,8 +53,8 @@ public final class ScrollHandler extends AbstractPacketHandler {
|
||||
if (c.tryacquireClient()) {
|
||||
try {
|
||||
p.readInt(); // whatever...
|
||||
short slot = p.readShort();
|
||||
short dst = p.readShort();
|
||||
short scrollSlot = p.readShort();
|
||||
short equipSlot = p.readShort();
|
||||
byte ws = (byte) p.readShort();
|
||||
boolean whiteScroll = false; // white scroll being used?
|
||||
boolean legendarySpirit = false; // legendary spirit skill
|
||||
@@ -61,24 +64,21 @@ public final class ScrollHandler extends AbstractPacketHandler {
|
||||
|
||||
ItemInformationProvider ii = ItemInformationProvider.getInstance();
|
||||
Character chr = c.getPlayer();
|
||||
Equip toScroll = (Equip) chr.getInventory(InventoryType.EQUIPPED).getItem(dst);
|
||||
Equip toScroll = (Equip) chr.getInventory(InventoryType.EQUIPPED).getItem(equipSlot);
|
||||
Skill LegendarySpirit = SkillFactory.getSkill(1003);
|
||||
if (chr.getSkillLevel(LegendarySpirit) > 0 && dst >= 0) {
|
||||
if (chr.getSkillLevel(LegendarySpirit) > 0 && equipSlot >= 0) {
|
||||
legendarySpirit = true;
|
||||
toScroll = (Equip) chr.getInventory(InventoryType.EQUIP).getItem(dst);
|
||||
toScroll = (Equip) chr.getInventory(InventoryType.EQUIP).getItem(equipSlot);
|
||||
}
|
||||
byte oldLevel = toScroll.getLevel();
|
||||
byte oldSlots = toScroll.getUpgradeSlots();
|
||||
Inventory useInventory = chr.getInventory(InventoryType.USE);
|
||||
Item scroll = useInventory.getItem(slot);
|
||||
Item scroll = useInventory.getItem(scrollSlot);
|
||||
Item wscroll = null;
|
||||
|
||||
if (ItemConstants.isCleanSlate(scroll.getItemId())) {
|
||||
Map<String, Integer> eqStats = ii.getEquipStats(toScroll.getItemId()); // clean slate issue found thanks to Masterrulax
|
||||
if (eqStats == null || eqStats.get("tuc") == 0) {
|
||||
announceCannotScroll(c, legendarySpirit);
|
||||
return;
|
||||
}
|
||||
if (ItemConstants.isCleanSlate(scroll.getItemId()) && !ii.canUseCleanSlate(toScroll)) {
|
||||
announceCannotScroll(c, legendarySpirit);
|
||||
return;
|
||||
} else if (!ItemConstants.isModifierScroll(scroll.getItemId()) && toScroll.getUpgradeSlots() < 1) {
|
||||
announceCannotScroll(c, legendarySpirit); // thanks onechord for noticing zero upgrade slots freezing Legendary Scroll UI
|
||||
return;
|
||||
@@ -103,11 +103,6 @@ public final class ScrollHandler extends AbstractPacketHandler {
|
||||
}
|
||||
}
|
||||
|
||||
if (ItemConstants.isCleanSlate(scroll.getItemId()) && !ii.canUseCleanSlate(toScroll)) {
|
||||
announceCannotScroll(c, legendarySpirit);
|
||||
return;
|
||||
}
|
||||
|
||||
Equip scrolled = (Equip) ii.scrollEquipWithId(toScroll, scroll.getItemId(), whiteScroll, 0, chr.isGM());
|
||||
ScrollResult scrollSuccess = Equip.ScrollResult.FAIL; // fail
|
||||
if (scrolled == null) {
|
||||
@@ -141,7 +136,7 @@ public final class ScrollHandler extends AbstractPacketHandler {
|
||||
if (scrollSuccess == Equip.ScrollResult.CURSE) {
|
||||
if (!ItemId.isWeddingRing(toScroll.getItemId())) {
|
||||
mods.add(new ModifyInventory(3, toScroll));
|
||||
if (dst < 0) {
|
||||
if (equipSlot < 0) {
|
||||
Inventory inv = chr.getInventory(InventoryType.EQUIPPED);
|
||||
|
||||
inv.lockInventory();
|
||||
@@ -174,7 +169,7 @@ public final class ScrollHandler extends AbstractPacketHandler {
|
||||
}
|
||||
c.sendPacket(PacketCreator.modifyInventory(true, mods));
|
||||
chr.getMap().broadcastMessage(PacketCreator.getScrollEffect(chr.getId(), scrollSuccess, legendarySpirit, whiteScroll));
|
||||
if (dst < 0 && (scrollSuccess == Equip.ScrollResult.SUCCESS || scrollSuccess == Equip.ScrollResult.CURSE)) {
|
||||
if (equipSlot < 0 && (scrollSuccess == Equip.ScrollResult.SUCCESS || scrollSuccess == Equip.ScrollResult.CURSE)) {
|
||||
chr.equipChanged();
|
||||
}
|
||||
} finally {
|
||||
|
||||
@@ -22,7 +22,23 @@
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import client.Client;
|
||||
import constants.skills.*;
|
||||
import constants.skills.Bishop;
|
||||
import constants.skills.Bowmaster;
|
||||
import constants.skills.Brawler;
|
||||
import constants.skills.ChiefBandit;
|
||||
import constants.skills.Corsair;
|
||||
import constants.skills.DarkKnight;
|
||||
import constants.skills.Evan;
|
||||
import constants.skills.FPArchMage;
|
||||
import constants.skills.FPMage;
|
||||
import constants.skills.Gunslinger;
|
||||
import constants.skills.Hero;
|
||||
import constants.skills.ILArchMage;
|
||||
import constants.skills.Marksman;
|
||||
import constants.skills.NightWalker;
|
||||
import constants.skills.Paladin;
|
||||
import constants.skills.ThunderBreaker;
|
||||
import constants.skills.WindArcher;
|
||||
import net.AbstractPacketHandler;
|
||||
import net.packet.InPacket;
|
||||
import org.slf4j.Logger;
|
||||
@@ -65,4 +81,4 @@ public final class SkillEffectHandler extends AbstractPacketHandler {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,13 @@ import client.Client;
|
||||
import client.Skill;
|
||||
import client.SkillFactory;
|
||||
import config.YamlConfig;
|
||||
import constants.skills.*;
|
||||
import constants.skills.Brawler;
|
||||
import constants.skills.Corsair;
|
||||
import constants.skills.DarkKnight;
|
||||
import constants.skills.Hero;
|
||||
import constants.skills.Paladin;
|
||||
import constants.skills.Priest;
|
||||
import constants.skills.SuperGM;
|
||||
import net.AbstractPacketHandler;
|
||||
import net.packet.InPacket;
|
||||
import net.server.Server;
|
||||
@@ -153,4 +159,4 @@ public final class SpecialMoveHandler extends AbstractPacketHandler {
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ import server.maps.Summon;
|
||||
import service.BanService;
|
||||
import tools.PacketCreator;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -53,25 +54,7 @@ public final class SummonDamageHandler extends AbstractDealDamageHandler {
|
||||
super(dropProvider, banService);
|
||||
}
|
||||
|
||||
public final class SummonAttackEntry {
|
||||
|
||||
private final int monsterOid;
|
||||
private final int damage;
|
||||
|
||||
public SummonAttackEntry(int monsterOid, int damage) {
|
||||
this.monsterOid = monsterOid;
|
||||
this.damage = damage;
|
||||
}
|
||||
|
||||
public int getMonsterOid() {
|
||||
return monsterOid;
|
||||
}
|
||||
|
||||
public int getDamage() {
|
||||
return damage;
|
||||
}
|
||||
|
||||
}
|
||||
public record SummonAttackTarget(int monsterOid, int damage, short delay) {}
|
||||
|
||||
@Override
|
||||
public void handlePacket(InPacket p, Client c) {
|
||||
@@ -92,17 +75,21 @@ public final class SummonDamageHandler extends AbstractDealDamageHandler {
|
||||
Skill summonSkill = SkillFactory.getSkill(summon.getSkill());
|
||||
StatEffect summonEffect = summonSkill.getEffect(summon.getSkillLevel());
|
||||
p.skip(4);
|
||||
List<SummonAttackEntry> allDamage = new ArrayList<>();
|
||||
List<SummonAttackTarget> targets = new ArrayList<>();
|
||||
byte direction = p.readByte();
|
||||
int numAttacked = p.readByte();
|
||||
p.skip(8); // I failed lol (mob x,y and summon x,y), Thanks Gerald
|
||||
for (int x = 0; x < numAttacked; x++) {
|
||||
int monsterOid = p.readInt(); // attacked oid
|
||||
p.skip(18);
|
||||
p.skip(8);
|
||||
Point curPos = p.readPos();
|
||||
Point nextPos = p.readPos();
|
||||
short delay = p.readShort();
|
||||
int damage = p.readInt();
|
||||
allDamage.add(new SummonAttackEntry(monsterOid, damage));
|
||||
targets.add(new SummonAttackTarget(monsterOid, damage, delay));
|
||||
}
|
||||
player.getMap().broadcastMessage(player, PacketCreator.summonAttack(player.getId(), summon.getObjectId(), direction, allDamage), summon.getPosition());
|
||||
player.getMap().broadcastMessage(player, PacketCreator.summonAttack(player.getId(), summon.getObjectId(),
|
||||
direction, targets), summon.getPosition());
|
||||
|
||||
if (player.getMap().isOwnershipRestricted(player)) {
|
||||
return;
|
||||
@@ -110,25 +97,28 @@ public final class SummonDamageHandler extends AbstractDealDamageHandler {
|
||||
|
||||
boolean magic = summonEffect.getWatk() == 0;
|
||||
int maxDmg = calcMaxDamage(summonEffect, player, magic); // thanks Darter (YungMoozi) for reporting unchecked max dmg
|
||||
for (SummonAttackEntry attackEntry : allDamage) {
|
||||
int damage = attackEntry.getDamage();
|
||||
Monster target = player.getMap().getMonsterByOid(attackEntry.getMonsterOid());
|
||||
if (target != null) {
|
||||
if (damage > maxDmg) {
|
||||
AutobanFactory.DAMAGE_HACK.alert(c.getPlayer(), "Possible packet editing summon damage exploit.");
|
||||
final String mobName = MonsterInformationProvider.getInstance().getMobNameFromId(target.getId());
|
||||
log.info("Possible exploit - chr {} used a summon of skillId {} to attack {} with damage {} (max: {})",
|
||||
c.getPlayer().getName(), summon.getSkill(), mobName, damage, maxDmg);
|
||||
damage = maxDmg;
|
||||
}
|
||||
|
||||
if (damage > 0 && summonEffect.getMonsterStati().size() > 0) {
|
||||
if (summonEffect.makeChanceResult()) {
|
||||
target.applyStatus(player, new MonsterStatusEffect(summonEffect.getMonsterStati(), summonSkill, null, false), summonEffect.isPoison(), 4000);
|
||||
}
|
||||
}
|
||||
player.getMap().damageMonster(player, target, damage);
|
||||
for (SummonAttackTarget target : targets) {
|
||||
int damage = target.damage();
|
||||
Monster mob = player.getMap().getMonsterByOid(target.monsterOid());
|
||||
if (mob == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (damage > maxDmg) {
|
||||
AutobanFactory.DAMAGE_HACK.alert(c.getPlayer(), "Possible packet editing summon damage exploit.");
|
||||
final String mobName = MonsterInformationProvider.getInstance().getMobNameFromId(mob.getId());
|
||||
log.info("Possible exploit - chr {} used a summon of skillId {} to attack {} with damage {} (max: {})",
|
||||
c.getPlayer().getName(), summon.getSkill(), mobName, damage, maxDmg);
|
||||
damage = maxDmg;
|
||||
}
|
||||
|
||||
if (damage > 0 && summonEffect.getMonsterStati().size() > 0) {
|
||||
if (summonEffect.makeChanceResult()) {
|
||||
mob.applyStatus(player, new MonsterStatusEffect(summonEffect.getMonsterStati(), summonSkill, null, false), summonEffect.isPoison(), 4000);
|
||||
}
|
||||
}
|
||||
player.getMap().damageMonster(player, mob, damage, target.delay());
|
||||
|
||||
}
|
||||
|
||||
if (summon.getSkill() == Outlaw.GAVIOTA) { // thanks Periwinks for noticing Gaviota not cancelling after grenade toss
|
||||
|
||||
@@ -21,8 +21,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import client.BuffStat;
|
||||
import client.Character;
|
||||
import client.*;
|
||||
import client.Client;
|
||||
import client.Skill;
|
||||
import client.SkillFactory;
|
||||
import client.inventory.Inventory;
|
||||
import client.inventory.InventoryType;
|
||||
import client.inventory.Item;
|
||||
@@ -39,7 +42,12 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import server.StatEffect;
|
||||
import server.life.LifeFactory.loseItem;
|
||||
import server.life.*;
|
||||
import server.life.MobAttackInfo;
|
||||
import server.life.MobAttackInfoFactory;
|
||||
import server.life.MobSkill;
|
||||
import server.life.MobSkillFactory;
|
||||
import server.life.MobSkillType;
|
||||
import server.life.Monster;
|
||||
import server.maps.MapObject;
|
||||
import server.maps.MapleMap;
|
||||
import tools.PacketCreator;
|
||||
@@ -281,7 +289,7 @@ public final class TakeDamageHandler extends AbstractPacketHandler {
|
||||
}
|
||||
|
||||
for (Character player : banishPlayers) { // chill, if this list ever gets non-empty an attacker does exist, trust me :)
|
||||
player.changeMapBanish(attacker.getBanish().getMap(), attacker.getBanish().getPortal(), attacker.getBanish().getMsg());
|
||||
player.changeMapBanish(attacker.getBanish());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,11 @@ import net.packet.InPacket;
|
||||
import tools.DatabaseConnection;
|
||||
import tools.PacketCreator;
|
||||
|
||||
import java.sql.*;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Calendar;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.DAYS;
|
||||
@@ -81,4 +85,4 @@ public final class TransferNameHandler extends AbstractPacketHandler {
|
||||
}
|
||||
c.sendPacket(PacketCreator.sendNameTransferRules(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,11 @@ import net.server.Server;
|
||||
import tools.DatabaseConnection;
|
||||
import tools.PacketCreator;
|
||||
|
||||
import java.sql.*;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
|
||||
/**
|
||||
* @author Ronan
|
||||
@@ -76,4 +80,4 @@ public final class TransferWorldHandler extends AbstractPacketHandler {
|
||||
}
|
||||
c.sendPacket(PacketCreator.sendWorldTransferRules(0, c));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,10 +22,22 @@
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import client.Character;
|
||||
import client.*;
|
||||
import client.creator.veteran.*;
|
||||
import client.inventory.*;
|
||||
import client.Client;
|
||||
import client.Skill;
|
||||
import client.SkillFactory;
|
||||
import client.SkillMacro;
|
||||
import client.creator.veteran.BowmanCreator;
|
||||
import client.creator.veteran.MagicianCreator;
|
||||
import client.creator.veteran.PirateCreator;
|
||||
import client.creator.veteran.ThiefCreator;
|
||||
import client.creator.veteran.WarriorCreator;
|
||||
import client.inventory.Equip;
|
||||
import client.inventory.Equip.ScrollResult;
|
||||
import client.inventory.Inventory;
|
||||
import client.inventory.InventoryType;
|
||||
import client.inventory.Item;
|
||||
import client.inventory.ModifyInventory;
|
||||
import client.inventory.Pet;
|
||||
import client.inventory.manipulator.InventoryManipulator;
|
||||
import client.inventory.manipulator.KarmaManipulator;
|
||||
import client.processor.npc.DueyProcessor;
|
||||
@@ -44,7 +56,12 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import server.ItemInformationProvider;
|
||||
import server.TimerManager;
|
||||
import server.maps.*;
|
||||
import server.maps.AbstractMapObject;
|
||||
import server.maps.FieldLimit;
|
||||
import server.maps.Kite;
|
||||
import server.maps.MapleMap;
|
||||
import server.maps.MapleTVEffect;
|
||||
import server.maps.PlayerShopItem;
|
||||
import server.shop.Shop;
|
||||
import server.shop.ShopFactory;
|
||||
import service.NoteService;
|
||||
|
||||
@@ -61,7 +61,7 @@ public final class UseCatchItemHandler extends AbstractPacketHandler {
|
||||
case ItemId.PHEROMONE_PERFUME:
|
||||
if (mob.getId() == MobId.TAMABLE_HOG) {
|
||||
chr.getMap().broadcastMessage(PacketCreator.catchMonster(monsterid, itemId, (byte) 1));
|
||||
mob.getMap().killMonster(mob, null, false);
|
||||
killMonster(mob);
|
||||
InventoryManipulator.removeById(c, InventoryType.USE, itemId, 1, true, true);
|
||||
InventoryManipulator.addById(c, ItemId.HOG, (short) 1, "", -1);
|
||||
}
|
||||
@@ -72,7 +72,7 @@ public final class UseCatchItemHandler extends AbstractPacketHandler {
|
||||
if ((abm.getLastSpam(10) + 1000) < currentServerTime()) {
|
||||
if (mob.getHp() < ((mob.getMaxHp() / 10) * 4)) {
|
||||
chr.getMap().broadcastMessage(PacketCreator.catchMonster(monsterid, itemId, (byte) 1));
|
||||
mob.getMap().killMonster(mob, null, false);
|
||||
killMonster(mob);
|
||||
InventoryManipulator.removeById(c, InventoryType.USE, itemId, 1, true, true);
|
||||
InventoryManipulator.addById(c, ItemId.GHOST_SACK, (short) 1, "", -1);
|
||||
} else {
|
||||
@@ -90,9 +90,10 @@ public final class UseCatchItemHandler extends AbstractPacketHandler {
|
||||
if (chr.canHold(ItemId.ARPQ_SPIRIT_JEWEL, 1)) {
|
||||
if (Math.random() < 0.5) { // 50% chance
|
||||
chr.getMap().broadcastMessage(PacketCreator.catchMonster(monsterid, itemId, (byte) 1));
|
||||
mob.getMap().killMonster(mob, null, false);
|
||||
killMonster(mob);
|
||||
InventoryManipulator.removeById(c, InventoryType.USE, itemId, 1, true, true);
|
||||
InventoryManipulator.addById(c, ItemId.ARPQ_SPIRIT_JEWEL, (short) 1, "", -1);
|
||||
chr.updateAriantScore();
|
||||
} else {
|
||||
chr.getMap().broadcastMessage(PacketCreator.catchMonster(monsterid, itemId, (byte) 0));
|
||||
}
|
||||
@@ -112,7 +113,7 @@ public final class UseCatchItemHandler extends AbstractPacketHandler {
|
||||
if (mob.getId() == MobId.LOST_RUDOLPH) {
|
||||
if (mob.getHp() < ((mob.getMaxHp() / 10) * 4)) {
|
||||
chr.getMap().broadcastMessage(PacketCreator.catchMonster(monsterid, itemId, (byte) 1));
|
||||
mob.getMap().killMonster(mob, null, false);
|
||||
killMonster(mob);
|
||||
InventoryManipulator.removeById(c, InventoryType.USE, itemId, 1, true, true);
|
||||
InventoryManipulator.addById(c, ItemId.TAMED_RUDOLPH, (short) 1, "", -1);
|
||||
} else {
|
||||
@@ -125,7 +126,7 @@ public final class UseCatchItemHandler extends AbstractPacketHandler {
|
||||
if (mob.getId() == MobId.KING_SLIME_DOJO) {
|
||||
if (mob.getHp() < ((mob.getMaxHp() / 10) * 3)) {
|
||||
chr.getMap().broadcastMessage(PacketCreator.catchMonster(monsterid, itemId, (byte) 1));
|
||||
mob.getMap().killMonster(mob, null, false);
|
||||
killMonster(mob);
|
||||
InventoryManipulator.removeById(c, InventoryType.USE, itemId, 1, true, true);
|
||||
InventoryManipulator.addById(c, ItemId.MONSTER_MARBLE_1, (short) 1, "", -1);
|
||||
} else {
|
||||
@@ -138,7 +139,7 @@ public final class UseCatchItemHandler extends AbstractPacketHandler {
|
||||
if (mob.getId() == MobId.FAUST_DOJO) {
|
||||
if (mob.getHp() < ((mob.getMaxHp() / 10) * 3)) {
|
||||
chr.getMap().broadcastMessage(PacketCreator.catchMonster(monsterid, itemId, (byte) 1));
|
||||
mob.getMap().killMonster(mob, null, false);
|
||||
killMonster(mob);
|
||||
InventoryManipulator.removeById(c, InventoryType.USE, itemId, 1, true, true);
|
||||
InventoryManipulator.addById(c, ItemId.MONSTER_MARBLE_2, (short) 1, "", -1);
|
||||
} else {
|
||||
@@ -151,7 +152,7 @@ public final class UseCatchItemHandler extends AbstractPacketHandler {
|
||||
if (mob.getId() == MobId.MUSHMOM_DOJO) {
|
||||
if (mob.getHp() < ((mob.getMaxHp() / 10) * 3)) {
|
||||
chr.getMap().broadcastMessage(PacketCreator.catchMonster(monsterid, itemId, (byte) 1));
|
||||
mob.getMap().killMonster(mob, null, false);
|
||||
killMonster(mob);
|
||||
InventoryManipulator.removeById(c, InventoryType.USE, itemId, 1, true, true);
|
||||
InventoryManipulator.addById(c, ItemId.MONSTER_MARBLE_3, (short) 1, "", -1);
|
||||
} else {
|
||||
@@ -164,7 +165,7 @@ public final class UseCatchItemHandler extends AbstractPacketHandler {
|
||||
if (mob.getId() == MobId.POISON_FLOWER) {
|
||||
if (mob.getHp() < ((mob.getMaxHp() / 10) * 4)) {
|
||||
chr.getMap().broadcastMessage(PacketCreator.catchMonster(monsterid, itemId, (byte) 1));
|
||||
mob.getMap().killMonster(mob, null, false);
|
||||
killMonster(mob);
|
||||
InventoryManipulator.removeById(c, InventoryType.USE, itemId, 1, true, true);
|
||||
InventoryManipulator.addById(c, ItemId.EPQ_MONSTER_MARBLE, (short) 1, "", -1);
|
||||
} else {
|
||||
@@ -178,7 +179,7 @@ public final class UseCatchItemHandler extends AbstractPacketHandler {
|
||||
if ((abm.getLastSpam(10) + 3000) < currentServerTime()) {
|
||||
abm.spam(10);
|
||||
chr.getMap().broadcastMessage(PacketCreator.catchMonster(monsterid, itemId, (byte) 1));
|
||||
mob.getMap().killMonster(mob, null, false);
|
||||
killMonster(mob);
|
||||
InventoryManipulator.removeById(c, InventoryType.USE, itemId, 1, true, true);
|
||||
InventoryManipulator.addById(c, ItemId.FISH_NET_WITH_A_CATCH, (short) 1, "", -1);
|
||||
} else {
|
||||
@@ -201,7 +202,7 @@ public final class UseCatchItemHandler extends AbstractPacketHandler {
|
||||
if (timeCatch != 0 && (abm.getLastSpam(10) + timeCatch) < currentServerTime()) {
|
||||
if (mobHp != 0 && mob.getHp() < ((mob.getMaxHp() / 100) * mobHp)) {
|
||||
chr.getMap().broadcastMessage(PacketCreator.catchMonster(monsterid, itemId, (byte) 1));
|
||||
mob.getMap().killMonster(mob, null, false);
|
||||
killMonster(mob);
|
||||
InventoryManipulator.removeById(c, InventoryType.USE, itemId, 1, true, true);
|
||||
InventoryManipulator.addById(c, itemGanho, (short) 1, "", -1);
|
||||
} else if (mob.getId() != MobId.P_JUNIOR) {
|
||||
@@ -219,4 +220,8 @@ public final class UseCatchItemHandler extends AbstractPacketHandler {
|
||||
// System.out.println("UseCatchItemHandler: \r\n" + slea.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private static void killMonster(Monster mob) {
|
||||
mob.getMap().killMonster(mob, null, false, (short) 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ import client.Disease;
|
||||
import client.inventory.InventoryType;
|
||||
import client.inventory.Item;
|
||||
import client.inventory.manipulator.InventoryManipulator;
|
||||
import config.YamlConfig;
|
||||
import constants.id.ItemId;
|
||||
import constants.inventory.ItemConstants;
|
||||
import net.AbstractPacketHandler;
|
||||
@@ -73,23 +72,8 @@ public final class UseItemHandler extends AbstractPacketHandler {
|
||||
remove(c, slot);
|
||||
return;
|
||||
} else if (ItemConstants.isTownScroll(itemId)) {
|
||||
int banMap = chr.getMapId();
|
||||
int banSp = chr.getMap().findClosestPlayerSpawnpoint(chr.getPosition()).getId();
|
||||
long banTime = currentServerTime();
|
||||
|
||||
if (ii.getItemEffect(toUse.getItemId()).applyTo(chr)) {
|
||||
if (YamlConfig.config.server.USE_BANISHABLE_TOWN_SCROLL) {
|
||||
chr.setBanishPlayerData(banMap, banSp, banTime);
|
||||
}
|
||||
|
||||
remove(c, slot);
|
||||
}
|
||||
return;
|
||||
} else if (ItemConstants.isAntibanishScroll(itemId)) {
|
||||
if (ii.getItemEffect(toUse.getItemId()).applyTo(chr)) {
|
||||
remove(c, slot);
|
||||
} else {
|
||||
chr.dropMessage(5, "You cannot recover from a banish state at the moment.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -25,8 +25,12 @@ import net.server.Server;
|
||||
import net.server.coordinator.matchchecker.MatchCheckerListenerFactory.MatchCheckerType;
|
||||
import net.server.world.World;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
/**
|
||||
|
||||
@@ -33,8 +33,14 @@ import provider.wz.WZFiles;
|
||||
import tools.PacketCreator;
|
||||
import tools.Pair;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
@@ -22,7 +22,11 @@ package net.server.coordinator.partysearch;
|
||||
import client.Character;
|
||||
import tools.IntervalBuilder;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
@@ -32,8 +32,14 @@ import tools.DatabaseConnection;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.time.Instant;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
@@ -4,7 +4,11 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import tools.DatabaseConnection;
|
||||
|
||||
import java.sql.*;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -27,8 +27,14 @@ import server.life.Monster;
|
||||
import server.maps.MapleMap;
|
||||
import tools.Pair;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@@ -42,7 +42,13 @@ import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
|
||||
@@ -25,44 +25,14 @@ import client.Client;
|
||||
import client.creator.novice.BeginnerCreator;
|
||||
import client.creator.novice.LegendCreator;
|
||||
import client.creator.novice.NoblesseCreator;
|
||||
import constants.id.ItemId;
|
||||
import net.AbstractPacketHandler;
|
||||
import net.netty.GameViolationException;
|
||||
import net.packet.InPacket;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import tools.PacketCreator;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public final class CreateCharHandler extends AbstractPacketHandler {
|
||||
private static final Logger log = LoggerFactory.getLogger(CreateCharHandler.class);
|
||||
|
||||
private final static Set<Integer> IDs = new HashSet<>(Arrays.asList(
|
||||
ItemId.SWORD, ItemId.HAND_AXE, ItemId.WOODEN_CLUB, ItemId.BASIC_POLEARM,// weapons
|
||||
ItemId.WHITE_UNDERSHIRT, ItemId.UNDERSHIRT, ItemId.GREY_TSHIRT, ItemId.WHITE_TUBETOP, ItemId.YELLOW_TSHIRT,
|
||||
ItemId.GREEN_TSHIRT, ItemId.RED_STRIPED_TOP, ItemId.SIMPLE_WARRIOR_TOP,// bottom
|
||||
ItemId.BLUE_JEAN_SHORTS, ItemId.BROWN_COTTON_SHORTS, ItemId.RED_MINISKIRT, ItemId.INDIGO_MINISKIRT,
|
||||
ItemId.SIMPLE_WARRIOR_PANTS, // top
|
||||
ItemId.RED_RUBBER_BOOTS, ItemId.LEATHER_SANDALS, ItemId.YELLOW_RUBBER_BOOTS, ItemId.BLUE_RUBBER_BOOTS,
|
||||
ItemId.AVERAGE_MUSASHI_SHOES,// shoes
|
||||
ItemId.BLACK_TOBEN, ItemId.ZETA, ItemId.BLACK_REBEL, ItemId.BLACK_BUZZ, ItemId.BLACK_SAMMY,
|
||||
ItemId.BLACK_EDGY, ItemId.BLACK_CONNIE,// hair
|
||||
ItemId.MOTIVATED_LOOK_M, ItemId.PERPLEXED_STARE, ItemId.LEISURE_LOOK_M, ItemId.MOTIVATED_LOOK_F,
|
||||
ItemId.FEARFUL_STARE_M, ItemId.LEISURE_LOOK_F, ItemId.FEARFUL_STARE_F, ItemId.PERPLEXED_STARE_HAZEL,
|
||||
ItemId.LEISURE_LOOK_HAZEL, ItemId.MOTIVATED_LOOK_AMETHYST, ItemId.MOTIVATED_LOOK_BLUE //face
|
||||
//#NeverTrustStevenCode
|
||||
));
|
||||
|
||||
private static boolean isLegal(Integer toCompare) {
|
||||
return IDs.contains(toCompare);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
public void handlePacket(InPacket p, Client c) {
|
||||
String name = p.readString();
|
||||
int job = p.readInt();
|
||||
int face = p.readInt();
|
||||
@@ -77,14 +47,6 @@ public final class CreateCharHandler extends AbstractPacketHandler {
|
||||
int weapon = p.readInt();
|
||||
int gender = p.readByte();
|
||||
|
||||
int[] items = new int[]{weapon, top, bottom, shoes, hair, face};
|
||||
for (int item : items) {
|
||||
if (!isLegal(item)) {
|
||||
log.warn("Owner from account {} tried to packet edit in chr creation", c.getAccountName());
|
||||
throw new GameViolationException("Create character with invalid equip");
|
||||
}
|
||||
}
|
||||
|
||||
int status;
|
||||
switch (job) {
|
||||
case 0: // Knights of Cygnus
|
||||
|
||||
@@ -43,7 +43,13 @@ import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.sql.*;
|
||||
import java.sql.Connection;
|
||||
import java.sql.Date;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Calendar;
|
||||
|
||||
public final class LoginPasswordHandler implements PacketHandler {
|
||||
|
||||
@@ -29,7 +29,11 @@ import net.packet.InPacket;
|
||||
import net.server.Server;
|
||||
import tools.PacketCreator;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public final class ViewAllCharHandler extends AbstractPacketHandler {
|
||||
private static final int CHARACTER_LIMIT = 60; // Client will crash if sending 61 or more characters
|
||||
|
||||
@@ -24,7 +24,11 @@ import net.server.Server;
|
||||
import server.TimerManager;
|
||||
import tools.Pair;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Collections;
|
||||
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.ScheduledFuture;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
@@ -22,7 +22,12 @@ package net.server.services.type;
|
||||
import net.server.services.BaseService;
|
||||
import net.server.services.Service;
|
||||
import net.server.services.ServiceType;
|
||||
import net.server.services.task.channel.*;
|
||||
import net.server.services.task.channel.EventService;
|
||||
import net.server.services.task.channel.MobAnimationService;
|
||||
import net.server.services.task.channel.MobClearSkillService;
|
||||
import net.server.services.task.channel.MobMistService;
|
||||
import net.server.services.task.channel.MobStatusService;
|
||||
import net.server.services.task.channel.OverallService;
|
||||
|
||||
/**
|
||||
* @author Ronan
|
||||
|
||||
@@ -32,7 +32,12 @@ import server.maps.MapleMap;
|
||||
import server.partyquest.MonsterCarnival;
|
||||
import tools.PacketCreator;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
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.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@@ -46,22 +46,57 @@ import net.server.guild.GuildSummary;
|
||||
import net.server.services.BaseService;
|
||||
import net.server.services.ServicesManager;
|
||||
import net.server.services.type.WorldServices;
|
||||
import net.server.task.*;
|
||||
import net.server.task.CharacterHpDecreaseTask;
|
||||
import net.server.task.FamilyDailyResetTask;
|
||||
import net.server.task.FishingTask;
|
||||
import net.server.task.HiredMerchantTask;
|
||||
import net.server.task.MapOwnershipTask;
|
||||
import net.server.task.MountTirednessTask;
|
||||
import net.server.task.PartySearchTask;
|
||||
import net.server.task.PetFullnessTask;
|
||||
import net.server.task.ServerMessageTask;
|
||||
import net.server.task.TimedMapObjectTask;
|
||||
import net.server.task.TimeoutTask;
|
||||
import net.server.task.WeddingReservationTask;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import scripting.event.EventInstanceManager;
|
||||
import server.Storage;
|
||||
import server.TimerManager;
|
||||
import server.maps.*;
|
||||
import server.maps.AbstractMapObject;
|
||||
import server.maps.HiredMerchant;
|
||||
import server.maps.MapleMap;
|
||||
import server.maps.MiniDungeon;
|
||||
import server.maps.MiniDungeonInfo;
|
||||
import server.maps.PlayerShop;
|
||||
import server.maps.PlayerShopItem;
|
||||
import service.TransitionService;
|
||||
import tools.DatabaseConnection;
|
||||
import tools.PacketCreator;
|
||||
import tools.Pair;
|
||||
import tools.packets.Fishing;
|
||||
|
||||
import java.sql.*;
|
||||
import java.util.*;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.PriorityQueue;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
@@ -70,7 +105,9 @@ import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.*;
|
||||
import static java.util.concurrent.TimeUnit.DAYS;
|
||||
import static java.util.concurrent.TimeUnit.MINUTES;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
/**
|
||||
* @author kevintjuh93
|
||||
|
||||
@@ -289,6 +289,10 @@ public class NPCConversationManager extends AbstractPlayerInteraction {
|
||||
gainMeso(-loss);
|
||||
}
|
||||
|
||||
public void gainMeso(Double gain) {
|
||||
getPlayer().gainMeso(gain.intValue());
|
||||
}
|
||||
|
||||
public void gainExp(int gain) {
|
||||
getPlayer().gainExp(gain, true, true);
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import server.TimerManager;
|
||||
import server.life.LifeFactory;
|
||||
import server.life.Monster;
|
||||
import server.maps.MapMonitor;
|
||||
import server.maps.MapleMap;
|
||||
import server.maps.Reactor;
|
||||
import server.maps.ReactorDropEntry;
|
||||
import server.partyquest.CarnivalFactory;
|
||||
@@ -43,7 +44,6 @@ import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
|
||||
/**
|
||||
* @author Lerk
|
||||
@@ -52,7 +52,6 @@ import java.util.concurrent.ScheduledFuture;
|
||||
public class ReactorActionManager extends AbstractPlayerInteraction {
|
||||
private final Reactor reactor;
|
||||
private final Invocable iv;
|
||||
private ScheduledFuture<?> sprayTask = null;
|
||||
|
||||
public ReactorActionManager(Client c, Reactor reactor, Invocable iv) {
|
||||
super(c);
|
||||
@@ -172,7 +171,8 @@ public class ReactorActionManager extends AbstractPlayerInteraction {
|
||||
int range = maxMeso - minMeso;
|
||||
int displayDrop = (int) (Math.random() * range) + minMeso;
|
||||
int mesoDrop = (displayDrop * c.getWorldServer().getMesoRate());
|
||||
reactor.getMap().spawnMesoDrop(mesoDrop, reactor.getMap().calcDropPos(dropPos, reactor.getPosition()), reactor, c.getPlayer(), false, (byte) 2);
|
||||
reactor.getMap().spawnMesoDrop(mesoDrop, reactor.getMap().calcDropPos(dropPos,
|
||||
reactor.getPosition()), reactor, c.getPlayer(), false, (byte) 2, (short) 0);
|
||||
} else {
|
||||
Item drop;
|
||||
|
||||
@@ -182,31 +182,24 @@ public class ReactorActionManager extends AbstractPlayerInteraction {
|
||||
drop = ii.randomizeStats((Equip) ii.getEquipById(d.itemId));
|
||||
}
|
||||
|
||||
reactor.getMap().dropFromReactor(getPlayer(), reactor, drop, dropPos, (short) d.questid);
|
||||
reactor.getMap().dropFromReactor(getPlayer(), reactor, drop, dropPos, (short) d.questid, (short) 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
final Reactor r = reactor;
|
||||
final List<ReactorDropEntry> dropItems = items;
|
||||
final int worldMesoRate = c.getWorldServer().getMesoRate();
|
||||
|
||||
dropPos.x -= (12 * items.size());
|
||||
|
||||
sprayTask = TimerManager.getInstance().register(() -> {
|
||||
if (dropItems.isEmpty()) {
|
||||
sprayTask.cancel(false);
|
||||
return;
|
||||
}
|
||||
|
||||
ReactorDropEntry d = dropItems.remove(0);
|
||||
short delay = 0;
|
||||
for (ReactorDropEntry d : items) {
|
||||
if (d.itemId == 0) {
|
||||
int range = maxMeso - minMeso;
|
||||
int displayDrop = (int) (Math.random() * range) + minMeso;
|
||||
int mesoDrop = (displayDrop * worldMesoRate);
|
||||
r.getMap().spawnMesoDrop(mesoDrop, r.getMap().calcDropPos(dropPos, r.getPosition()), r, chr, false, (byte) 2);
|
||||
int mesoDrop = displayDrop * worldMesoRate;
|
||||
MapleMap map = reactor.getMap();
|
||||
map.spawnMesoDrop(mesoDrop, map.calcDropPos(dropPos, reactor.getPosition()), reactor, chr,
|
||||
false, (byte) 2, delay);
|
||||
} else {
|
||||
Item drop;
|
||||
|
||||
final Item drop;
|
||||
if (ItemConstants.getInventoryType(d.itemId) != InventoryType.EQUIP) {
|
||||
drop = new Item(d.itemId, (short) 0, (short) 1);
|
||||
} else {
|
||||
@@ -214,11 +207,12 @@ public class ReactorActionManager extends AbstractPlayerInteraction {
|
||||
drop = ii.randomizeStats((Equip) ii.getEquipById(d.itemId));
|
||||
}
|
||||
|
||||
r.getMap().dropFromReactor(getPlayer(), r, drop, dropPos, (short) d.questid);
|
||||
reactor.getMap().dropFromReactor(getPlayer(), reactor, drop, dropPos, (short) d.questid, delay);
|
||||
}
|
||||
|
||||
dropPos.x += 25;
|
||||
}, 200);
|
||||
delay += 200;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -333,4 +327,4 @@ public class ReactorActionManager extends AbstractPlayerInteraction {
|
||||
getPlayer().getMap().getBlueTeamBuffs().remove(skil);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+153
-146
@@ -21,10 +21,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package server;
|
||||
|
||||
import client.inventory.*;
|
||||
import client.inventory.Equip;
|
||||
import client.inventory.InventoryType;
|
||||
import client.inventory.Item;
|
||||
import client.inventory.ItemFactory;
|
||||
import client.inventory.Pet;
|
||||
import config.YamlConfig;
|
||||
import constants.id.ItemId;
|
||||
import constants.inventory.ItemConstants;
|
||||
import net.jcip.annotations.GuardedBy;
|
||||
import net.server.Server;
|
||||
import provider.Data;
|
||||
import provider.DataProvider;
|
||||
@@ -38,7 +43,13 @@ import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@@ -47,8 +58,74 @@ import static java.util.concurrent.TimeUnit.HOURS;
|
||||
|
||||
/*
|
||||
* @author Flav
|
||||
* @author Ponk
|
||||
*/
|
||||
public class CashShop {
|
||||
public static final int NX_CREDIT = 1;
|
||||
public static final int MAPLE_POINT = 2;
|
||||
public static final int NX_PREPAID = 4;
|
||||
|
||||
private final int accountId;
|
||||
private final int characterId;
|
||||
private int nxCredit;
|
||||
private int maplePoint;
|
||||
private int nxPrepaid;
|
||||
private boolean opened;
|
||||
private ItemFactory factory;
|
||||
private final List<Item> inventory = new ArrayList<>();
|
||||
private final List<Integer> wishList = new ArrayList<>();
|
||||
private int notes = 0;
|
||||
private final Lock lock = new ReentrantLock();
|
||||
|
||||
public CashShop(int accountId, int characterId, int jobType) throws SQLException {
|
||||
this.accountId = accountId;
|
||||
this.characterId = characterId;
|
||||
|
||||
if (!YamlConfig.config.server.USE_JOINT_CASHSHOP_INVENTORY) {
|
||||
switch (jobType) {
|
||||
case 0:
|
||||
factory = ItemFactory.CASH_EXPLORER;
|
||||
break;
|
||||
case 1:
|
||||
factory = ItemFactory.CASH_CYGNUS;
|
||||
break;
|
||||
case 2:
|
||||
factory = ItemFactory.CASH_ARAN;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
factory = ItemFactory.CASH_OVERALL;
|
||||
}
|
||||
|
||||
try (Connection con = DatabaseConnection.getConnection()) {
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT `nxCredit`, `maplePoint`, `nxPrepaid` FROM `accounts` WHERE `id` = ?")) {
|
||||
ps.setInt(1, accountId);
|
||||
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
this.nxCredit = rs.getInt("nxCredit");
|
||||
this.maplePoint = rs.getInt("maplePoint");
|
||||
this.nxPrepaid = rs.getInt("nxPrepaid");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Pair<Item, InventoryType> item : factory.loadItems(accountId, false)) {
|
||||
inventory.add(item.getLeft());
|
||||
}
|
||||
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT `sn` FROM `wishlists` WHERE `charid` = ?")) {
|
||||
ps.setInt(1, characterId);
|
||||
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
wishList.add(rs.getInt("sn"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class CashItem {
|
||||
|
||||
private final int sn;
|
||||
@@ -104,19 +181,20 @@ public class CashShop {
|
||||
if (ItemConstants.EXPIRING_ITEMS) {
|
||||
if (period == 1) {
|
||||
switch (itemId) {
|
||||
case ItemId.DROP_COUPON_2X_4H, ItemId.EXP_COUPON_2X_4H: // 4 Hour 2X coupons, the period is 1, but we don't want them to last a day.
|
||||
item.setExpiration(Server.getInstance().getCurrentTime() + HOURS.toMillis(4));
|
||||
case ItemId.DROP_COUPON_2X_4H,
|
||||
ItemId.EXP_COUPON_2X_4H: // 4 Hour 2X coupons, the period is 1, but we don't want them to last a day.
|
||||
item.setExpiration(Server.getInstance().getCurrentTime() + HOURS.toMillis(4));
|
||||
/*
|
||||
} else if(itemId == 5211047 || itemId == 5360014) { // 3 Hour 2X coupons, unused as of now
|
||||
item.setExpiration(Server.getInstance().getCurrentTime() + HOURS.toMillis(3));
|
||||
*/
|
||||
break;
|
||||
case ItemId.EXP_COUPON_3X_2H:
|
||||
item.setExpiration(Server.getInstance().getCurrentTime() + HOURS.toMillis(2));
|
||||
break;
|
||||
default:
|
||||
item.setExpiration(Server.getInstance().getCurrentTime() + DAYS.toMillis(1));
|
||||
break;
|
||||
break;
|
||||
case ItemId.EXP_COUPON_3X_2H:
|
||||
item.setExpiration(Server.getInstance().getCurrentTime() + HOURS.toMillis(2));
|
||||
break;
|
||||
default:
|
||||
item.setExpiration(Server.getInstance().getCurrentTime() + DAYS.toMillis(1));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
item.setExpiration(Server.getInstance().getCurrentTime() + DAYS.toMillis(period));
|
||||
@@ -154,7 +232,6 @@ public class CashShop {
|
||||
|
||||
public static class CashItemFactory {
|
||||
private static volatile Map<Integer, CashItem> items = new HashMap<>();
|
||||
private static volatile List<Integer> randomitemsns = new ArrayList<>();
|
||||
private static volatile Map<Integer, List<Integer>> packages = new HashMap<>();
|
||||
private static volatile List<SpecialCashItem> specialcashitems = new ArrayList<>();
|
||||
|
||||
@@ -162,7 +239,6 @@ public class CashShop {
|
||||
DataProvider etc = DataProviderFactory.getDataProvider(WZFiles.ETC);
|
||||
|
||||
Map<Integer, CashItem> loadedItems = new HashMap<>();
|
||||
List<Integer> onSaleItems = new ArrayList<>();
|
||||
for (Data item : etc.getData("Commodity.img").getChildren()) {
|
||||
int sn = DataTool.getIntConvert("SN", item);
|
||||
int itemId = DataTool.getIntConvert("ItemId", item);
|
||||
@@ -171,13 +247,8 @@ public class CashShop {
|
||||
short count = (short) DataTool.getIntConvert("Count", item, 1);
|
||||
boolean onSale = DataTool.getIntConvert("OnSale", item, 0) == 1;
|
||||
loadedItems.put(sn, new CashItem(sn, itemId, price, period, count, onSale));
|
||||
|
||||
if (onSale) {
|
||||
onSaleItems.add(sn);
|
||||
}
|
||||
}
|
||||
CashItemFactory.items = loadedItems;
|
||||
CashItemFactory.randomitemsns = onSaleItems;
|
||||
|
||||
Map<Integer, List<Integer>> loadedPackages = new HashMap<>();
|
||||
for (Data cashPackage : etc.getData("CashPackage.img").getChildren()) {
|
||||
@@ -204,13 +275,20 @@ public class CashShop {
|
||||
CashItemFactory.specialcashitems = loadedSpecialItems;
|
||||
}
|
||||
|
||||
public static CashItem getRandomCashItem() {
|
||||
if (randomitemsns.isEmpty()) {
|
||||
return null;
|
||||
public static Optional<CashItem> getRandomCashItem() {
|
||||
if (items.isEmpty()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
int rnd = (int) (Math.random() * randomitemsns.size());
|
||||
return items.get(randomitemsns.get(rnd));
|
||||
List<CashItem> itemPool = items.values().stream()
|
||||
.filter(CashItem::isOnSale)
|
||||
.filter(cashItem -> !ItemId.isCashPackage(cashItem.itemId))
|
||||
.toList();
|
||||
return Optional.of(getRandomItem(itemPool));
|
||||
}
|
||||
|
||||
private static CashItem getRandomItem(List<CashItem> items) {
|
||||
return items.get(new Random().nextInt(items.size()));
|
||||
}
|
||||
|
||||
public static CashItem getItem(int sn) {
|
||||
@@ -234,107 +312,26 @@ public class CashShop {
|
||||
public static List<SpecialCashItem> getSpecialCashItems() {
|
||||
return specialcashitems;
|
||||
}
|
||||
|
||||
public static void reloadSpecialCashItems() {//Yay?
|
||||
List<SpecialCashItem> loadedSpecialItems = new ArrayList<>();
|
||||
try (Connection con = DatabaseConnection.getConnection();
|
||||
PreparedStatement ps = con.prepareStatement("SELECT * FROM specialcashitems");
|
||||
ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
loadedSpecialItems.add(new SpecialCashItem(rs.getInt("sn"), rs.getInt("modifier"), rs.getByte("info")));
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
CashItemFactory.specialcashitems = loadedSpecialItems;
|
||||
}
|
||||
}
|
||||
|
||||
private final int accountId;
|
||||
private final int characterId;
|
||||
private int nxCredit;
|
||||
private int maplePoint;
|
||||
private int nxPrepaid;
|
||||
private boolean opened;
|
||||
private ItemFactory factory;
|
||||
private final List<Item> inventory = new ArrayList<>();
|
||||
private final List<Integer> wishList = new ArrayList<>();
|
||||
private int notes = 0;
|
||||
private final Lock lock = new ReentrantLock();
|
||||
|
||||
public CashShop(int accountId, int characterId, int jobType) throws SQLException {
|
||||
this.accountId = accountId;
|
||||
this.characterId = characterId;
|
||||
|
||||
if (!YamlConfig.config.server.USE_JOINT_CASHSHOP_INVENTORY) {
|
||||
switch (jobType) {
|
||||
case 0:
|
||||
factory = ItemFactory.CASH_EXPLORER;
|
||||
break;
|
||||
case 1:
|
||||
factory = ItemFactory.CASH_CYGNUS;
|
||||
break;
|
||||
case 2:
|
||||
factory = ItemFactory.CASH_ARAN;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
factory = ItemFactory.CASH_OVERALL;
|
||||
}
|
||||
|
||||
try (Connection con = DatabaseConnection.getConnection()) {
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT `nxCredit`, `maplePoint`, `nxPrepaid` FROM `accounts` WHERE `id` = ?")) {
|
||||
ps.setInt(1, accountId);
|
||||
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
this.nxCredit = rs.getInt("nxCredit");
|
||||
this.maplePoint = rs.getInt("maplePoint");
|
||||
this.nxPrepaid = rs.getInt("nxPrepaid");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Pair<Item, InventoryType> item : factory.loadItems(accountId, false)) {
|
||||
inventory.add(item.getLeft());
|
||||
}
|
||||
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT `sn` FROM `wishlists` WHERE `charid` = ?")) {
|
||||
ps.setInt(1, characterId);
|
||||
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
wishList.add(rs.getInt("sn"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public record CashShopSurpriseResult(Item usedCashShopSurprise, Item reward) {
|
||||
}
|
||||
|
||||
public int getCash(int type) {
|
||||
switch (type) {
|
||||
case 1:
|
||||
return nxCredit;
|
||||
case 2:
|
||||
return maplePoint;
|
||||
case 4:
|
||||
return nxPrepaid;
|
||||
}
|
||||
return switch (type) {
|
||||
case NX_CREDIT -> nxCredit;
|
||||
case MAPLE_POINT -> maplePoint;
|
||||
case NX_PREPAID -> nxPrepaid;
|
||||
default -> 0;
|
||||
};
|
||||
|
||||
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;
|
||||
case NX_CREDIT -> nxCredit += cash;
|
||||
case MAPLE_POINT -> maplePoint += cash;
|
||||
case NX_PREPAID -> nxPrepaid += cash;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -517,47 +514,57 @@ public class CashShop {
|
||||
}
|
||||
}
|
||||
|
||||
private Item getCashShopItemByItemid(int itemid) {
|
||||
public Optional<CashShopSurpriseResult> openCashShopSurprise(long cashId) {
|
||||
lock.lock();
|
||||
try {
|
||||
for (Item it : inventory) {
|
||||
if (it.getItemId() == itemid) {
|
||||
return it;
|
||||
}
|
||||
Optional<Item> maybeCashShopSurprise = getItemByCashId(cashId);
|
||||
if (maybeCashShopSurprise.isEmpty() ||
|
||||
maybeCashShopSurprise.get().getItemId() != ItemId.CASH_SHOP_SURPRISE) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
Item cashShopSurprise = maybeCashShopSurprise.get();
|
||||
if (cashShopSurprise.getQuantity() <= 0) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
if (getItemsSize() >= 100) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
Optional<CashItem> cashItemReward = CashItemFactory.getRandomCashItem();
|
||||
if (cashItemReward.isEmpty()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
short newQuantity = (short) (cashShopSurprise.getQuantity() - 1);
|
||||
cashShopSurprise.setQuantity(newQuantity);
|
||||
if (newQuantity <= 0) {
|
||||
removeFromInventory(cashShopSurprise);
|
||||
}
|
||||
|
||||
Item itemReward = cashItemReward.get().toItem();
|
||||
addToInventory(itemReward);
|
||||
|
||||
return Optional.of(new CashShopSurpriseResult(cashShopSurprise, itemReward));
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public synchronized Pair<Item, Item> openCashShopSurprise() {
|
||||
Item css = getCashShopItemByItemid(ItemId.CASH_SHOP_SURPRISE);
|
||||
@GuardedBy("lock")
|
||||
private Optional<Item> getItemByCashId(long cashId) {
|
||||
return inventory.stream()
|
||||
.filter(item -> item.getCashId() == cashId)
|
||||
.findAny();
|
||||
}
|
||||
|
||||
if (css != null) {
|
||||
CashItem cItem = CashItemFactory.getRandomCashItem();
|
||||
|
||||
if (cItem != null) {
|
||||
if (css.getQuantity() > 1) {
|
||||
/* if(NOT ENOUGH SPACE) { looks like we're not dealing with cash inventory limit whatsoever, k then
|
||||
return null;
|
||||
} */
|
||||
|
||||
css.setQuantity((short) (css.getQuantity() - 1));
|
||||
} else {
|
||||
removeFromInventory(css);
|
||||
}
|
||||
|
||||
Item item = cItem.toItem();
|
||||
addToInventory(item);
|
||||
|
||||
return new Pair<>(item, css);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
public int getItemsSize() {
|
||||
lock.lock();
|
||||
try {
|
||||
return inventory.size();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
package server;
|
||||
|
||||
import config.YamlConfig;
|
||||
import tools.DatabaseConnection;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.sql.Timestamp;
|
||||
import static java.util.concurrent.TimeUnit.*;
|
||||
|
||||
import config.YamlConfig;
|
||||
import tools.DatabaseConnection;
|
||||
import static java.util.concurrent.TimeUnit.MINUTES;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
public class ExpLogger {
|
||||
private static final LinkedBlockingQueue<ExpLogRecord> expLoggerQueue = new LinkedBlockingQueue<>();
|
||||
|
||||
@@ -22,9 +22,16 @@
|
||||
package server;
|
||||
|
||||
import client.Character;
|
||||
import client.*;
|
||||
import client.Client;
|
||||
import client.Job;
|
||||
import client.Skill;
|
||||
import client.SkillFactory;
|
||||
import client.autoban.AutobanFactory;
|
||||
import client.inventory.*;
|
||||
import client.inventory.Equip;
|
||||
import client.inventory.Inventory;
|
||||
import client.inventory.InventoryType;
|
||||
import client.inventory.Item;
|
||||
import client.inventory.WeaponType;
|
||||
import config.YamlConfig;
|
||||
import constants.id.ItemId;
|
||||
import constants.inventory.EquipSlot;
|
||||
@@ -35,7 +42,12 @@ import constants.skills.NightWalker;
|
||||
import net.server.Server;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import provider.*;
|
||||
import provider.Data;
|
||||
import provider.DataDirectoryEntry;
|
||||
import provider.DataFileEntry;
|
||||
import provider.DataProvider;
|
||||
import provider.DataProviderFactory;
|
||||
import provider.DataTool;
|
||||
import provider.wz.WZFiles;
|
||||
import server.life.LifeFactory;
|
||||
import server.life.MonsterInformationProvider;
|
||||
@@ -43,13 +55,22 @@ import tools.DatabaseConnection;
|
||||
import tools.PacketCreator;
|
||||
import tools.Pair;
|
||||
import tools.Randomizer;
|
||||
import tools.StringUtil;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Matze
|
||||
@@ -1024,9 +1045,16 @@ public class ItemInformationProvider {
|
||||
Issue with clean slate found thanks to Masterrulax
|
||||
Vicious added in the clean slate check thanks to Crypter (CrypterDEV)
|
||||
*/
|
||||
public boolean canUseCleanSlate(Equip nEquip) {
|
||||
Map<String, Integer> eqstats = this.getEquipStats(nEquip.getItemId());
|
||||
return YamlConfig.config.server.USE_ENHANCED_CLNSLATE || nEquip.getUpgradeSlots() < (byte) (eqstats.get("tuc") + nEquip.getVicious());
|
||||
public boolean canUseCleanSlate(Equip equip) {
|
||||
Map<String, Integer> eqStats = getEquipStats(equip.getItemId());
|
||||
if (eqStats == null || eqStats.get("tuc") == 0 ) {
|
||||
return false;
|
||||
}
|
||||
int totalUpgradeCount = eqStats.get("tuc");
|
||||
int freeUpgradeCount = equip.getUpgradeSlots();
|
||||
int viciousCount = equip.getVicious();
|
||||
int appliedScrollCount = equip.getLevel();
|
||||
return freeUpgradeCount + appliedScrollCount < totalUpgradeCount + viciousCount;
|
||||
}
|
||||
|
||||
public Item scrollEquipWithId(Item equip, int scrollId, boolean usingWhiteScroll, int vegaItemId, boolean isGM) {
|
||||
|
||||
@@ -21,8 +21,13 @@
|
||||
*/
|
||||
package server;
|
||||
|
||||
import client.BuffStat;
|
||||
import client.Character;
|
||||
import client.*;
|
||||
import client.Disease;
|
||||
import client.Job;
|
||||
import client.Mount;
|
||||
import client.Skill;
|
||||
import client.SkillFactory;
|
||||
import client.inventory.Inventory;
|
||||
import client.inventory.InventoryType;
|
||||
import client.inventory.Item;
|
||||
@@ -33,7 +38,57 @@ import config.YamlConfig;
|
||||
import constants.id.ItemId;
|
||||
import constants.id.MapId;
|
||||
import constants.inventory.ItemConstants;
|
||||
import constants.skills.*;
|
||||
import constants.skills.Aran;
|
||||
import constants.skills.Assassin;
|
||||
import constants.skills.Bandit;
|
||||
import constants.skills.Beginner;
|
||||
import constants.skills.Bishop;
|
||||
import constants.skills.BlazeWizard;
|
||||
import constants.skills.Bowmaster;
|
||||
import constants.skills.Brawler;
|
||||
import constants.skills.Buccaneer;
|
||||
import constants.skills.ChiefBandit;
|
||||
import constants.skills.Cleric;
|
||||
import constants.skills.Corsair;
|
||||
import constants.skills.Crossbowman;
|
||||
import constants.skills.Crusader;
|
||||
import constants.skills.DarkKnight;
|
||||
import constants.skills.DawnWarrior;
|
||||
import constants.skills.DragonKnight;
|
||||
import constants.skills.Evan;
|
||||
import constants.skills.FPArchMage;
|
||||
import constants.skills.FPMage;
|
||||
import constants.skills.FPWizard;
|
||||
import constants.skills.Fighter;
|
||||
import constants.skills.GM;
|
||||
import constants.skills.Gunslinger;
|
||||
import constants.skills.Hermit;
|
||||
import constants.skills.Hero;
|
||||
import constants.skills.Hunter;
|
||||
import constants.skills.ILArchMage;
|
||||
import constants.skills.ILMage;
|
||||
import constants.skills.ILWizard;
|
||||
import constants.skills.Legend;
|
||||
import constants.skills.Magician;
|
||||
import constants.skills.Marauder;
|
||||
import constants.skills.Marksman;
|
||||
import constants.skills.NightLord;
|
||||
import constants.skills.NightWalker;
|
||||
import constants.skills.Noblesse;
|
||||
import constants.skills.Outlaw;
|
||||
import constants.skills.Page;
|
||||
import constants.skills.Paladin;
|
||||
import constants.skills.Pirate;
|
||||
import constants.skills.Priest;
|
||||
import constants.skills.Ranger;
|
||||
import constants.skills.Rogue;
|
||||
import constants.skills.Shadower;
|
||||
import constants.skills.Sniper;
|
||||
import constants.skills.Spearman;
|
||||
import constants.skills.SuperGM;
|
||||
import constants.skills.ThunderBreaker;
|
||||
import constants.skills.WhiteKnight;
|
||||
import constants.skills.WindArcher;
|
||||
import net.packet.Packet;
|
||||
import net.server.Server;
|
||||
import net.server.world.Party;
|
||||
@@ -44,15 +99,27 @@ import server.life.MobSkill;
|
||||
import server.life.MobSkillFactory;
|
||||
import server.life.MobSkillType;
|
||||
import server.life.Monster;
|
||||
import server.maps.*;
|
||||
import server.maps.Door;
|
||||
import server.maps.FieldLimit;
|
||||
import server.maps.MapObject;
|
||||
import server.maps.MapObjectType;
|
||||
import server.maps.MapleMap;
|
||||
import server.maps.Mist;
|
||||
import server.maps.Portal;
|
||||
import server.maps.Summon;
|
||||
import server.maps.SummonMovementType;
|
||||
import server.partyquest.CarnivalFactory;
|
||||
import server.partyquest.CarnivalFactory.MCSkill;
|
||||
import tools.PacketCreator;
|
||||
import tools.Pair;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Matze
|
||||
@@ -910,18 +977,8 @@ public class StatEffect {
|
||||
Portal pt;
|
||||
|
||||
if (moveTo == MapId.NONE) {
|
||||
if (sourceid != ItemId.ANTI_BANISH_SCROLL) {
|
||||
target = applyto.getMap().getReturnMap();
|
||||
pt = target.getRandomPlayerSpawnpoint();
|
||||
} else {
|
||||
if (!applyto.canRecoverLastBanish()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Pair<Integer, Integer> lastBanishInfo = applyto.getLastBanishData();
|
||||
target = applyto.getWarpMap(lastBanishInfo.getLeft());
|
||||
pt = target.getPortal(lastBanishInfo.getRight());
|
||||
}
|
||||
target = applyto.getMap().getReturnMap();
|
||||
pt = target.getRandomPlayerSpawnpoint();
|
||||
} else {
|
||||
target = applyto.getClient().getWorldServer().getChannel(applyto.getClient().getChannel()).getMapFactory().getMap(moveTo);
|
||||
int targetid = target.getId() / 10000000;
|
||||
|
||||
@@ -38,7 +38,12 @@ import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
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 java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@@ -358,4 +363,4 @@ public class Storage {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,11 @@
|
||||
*/
|
||||
package server;
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.RejectedExecutionHandler;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.MINUTES;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
@@ -37,8 +37,14 @@ import server.maps.MapleMap;
|
||||
import tools.PacketCreator;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
|
||||
@@ -23,7 +23,11 @@ import config.YamlConfig;
|
||||
import tools.DatabaseConnection;
|
||||
import tools.Pair;
|
||||
|
||||
import java.sql.*;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Calendar;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package server.life;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public record BanishInfo(int map, String portal, String msg) {
|
||||
public BanishInfo {
|
||||
Objects.requireNonNull(portal, "BanishInfo portal");
|
||||
}
|
||||
}
|
||||
@@ -33,8 +33,12 @@ import tools.Pair;
|
||||
import tools.StringUtil;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class LifeFactory {
|
||||
private static final Logger log = LoggerFactory.getLogger(LifeFactory.class);
|
||||
@@ -227,7 +231,10 @@ public class LifeFactory {
|
||||
|
||||
Data banishData = monsterInfoData.getChildByPath("ban");
|
||||
if (banishData != null) {
|
||||
stats.setBanishInfo(new BanishInfo(DataTool.getString("banMsg", banishData), DataTool.getInt("banMap/0/field", banishData, -1), DataTool.getString("banMap/0/portal", banishData, "sp")));
|
||||
int map = DataTool.getInt("banMap/0/field", banishData, -1);
|
||||
String portal = DataTool.getString("banMap/0/portal", banishData, "sp");
|
||||
String msg = DataTool.getString("banMsg", banishData);
|
||||
stats.setBanishInfo(new BanishInfo(map, portal, msg));
|
||||
}
|
||||
|
||||
int noFlip = DataTool.getInt("noFlip", monsterInfoData, 0);
|
||||
@@ -292,31 +299,6 @@ public class LifeFactory {
|
||||
return DataTool.getString(nid + "/d0", npcStringData, "(...)");
|
||||
}
|
||||
|
||||
public static class BanishInfo {
|
||||
|
||||
private final int map;
|
||||
private final String portal;
|
||||
private final String 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 final int id;
|
||||
|
||||
@@ -38,8 +38,11 @@ import server.maps.Mist;
|
||||
import tools.Randomizer;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Danny (Leifde)
|
||||
@@ -190,6 +193,11 @@ public class MobSkill {
|
||||
|
||||
// TODO: avoid output argument banishPlayersOutput
|
||||
public void applyEffect(Character player, Monster monster, boolean skill, List<Character> banishPlayersOutput) {
|
||||
// See if the MobSkill is successful before doing anything
|
||||
if (!makeChanceResult()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Disease disease = null;
|
||||
Map<MonsterStatus, Integer> stats = new EnumMap<>(MonsterStatus.class);
|
||||
List<Integer> reflection = new ArrayList<>();
|
||||
@@ -213,12 +221,12 @@ public class MobSkill {
|
||||
case REVERSE_INPUT -> disease = Disease.CONFUSE;
|
||||
case UNDEAD -> disease = Disease.ZOMBIFY;
|
||||
case PHYSICAL_IMMUNE -> {
|
||||
if (makeChanceResult() && !monster.isBuffed(MonsterStatus.MAGIC_IMMUNITY)) {
|
||||
if (!monster.isBuffed(MonsterStatus.MAGIC_IMMUNITY)) {
|
||||
stats.put(MonsterStatus.WEAPON_IMMUNITY, x);
|
||||
}
|
||||
}
|
||||
case MAGIC_IMMUNE -> {
|
||||
if (makeChanceResult() && !monster.isBuffed(MonsterStatus.WEAPON_IMMUNITY)) {
|
||||
if (!monster.isBuffed(MonsterStatus.WEAPON_IMMUNITY)) {
|
||||
stats.put(MonsterStatus.MAGIC_IMMUNITY, x);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,8 +28,11 @@ import provider.DataTool;
|
||||
import provider.wz.WZFiles;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
@@ -21,13 +21,26 @@
|
||||
*/
|
||||
package server.life;
|
||||
|
||||
import client.BuffStat;
|
||||
import client.Character;
|
||||
import client.*;
|
||||
import client.Client;
|
||||
import client.FamilyEntry;
|
||||
import client.Job;
|
||||
import client.Skill;
|
||||
import client.SkillFactory;
|
||||
import client.status.MonsterStatus;
|
||||
import client.status.MonsterStatusEffect;
|
||||
import config.YamlConfig;
|
||||
import constants.id.MobId;
|
||||
import constants.skills.*;
|
||||
import constants.skills.Crusader;
|
||||
import constants.skills.FPMage;
|
||||
import constants.skills.Hermit;
|
||||
import constants.skills.ILMage;
|
||||
import constants.skills.NightLord;
|
||||
import constants.skills.NightWalker;
|
||||
import constants.skills.Priest;
|
||||
import constants.skills.Shadower;
|
||||
import constants.skills.WhiteKnight;
|
||||
import database.drop.DropProvider;
|
||||
import net.packet.Packet;
|
||||
import net.server.channel.Channel;
|
||||
@@ -44,7 +57,6 @@ import org.slf4j.LoggerFactory;
|
||||
import scripting.event.EventInstanceManager;
|
||||
import server.StatEffect;
|
||||
import server.TimerManager;
|
||||
import server.life.LifeFactory.BanishInfo;
|
||||
import server.loot.LootManager;
|
||||
import server.maps.AbstractAnimatedMapObject;
|
||||
import server.maps.MapObjectType;
|
||||
@@ -57,9 +69,17 @@ import tools.Randomizer;
|
||||
|
||||
import java.awt.*;
|
||||
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.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
@@ -807,12 +827,12 @@ public class Monster extends AbstractLoadedLife {
|
||||
}
|
||||
|
||||
if (htKilled) {
|
||||
reviveMap.killMonster(ht, killer, true);
|
||||
reviveMap.killMonster(ht, killer, true, (short) 0);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = MobId.DEAD_HORNTAIL_MAX; i >= MobId.DEAD_HORNTAIL_MIN; i--) {
|
||||
reviveMap.killMonster(reviveMap.getMonsterById(i), killer, true);
|
||||
reviveMap.killMonster(reviveMap.getMonsterById(i), killer, true, (short) 0);
|
||||
}
|
||||
} else if (controller != null) {
|
||||
mob.aggroSwitchController(controller, aggro);
|
||||
|
||||
@@ -29,7 +29,17 @@ import provider.DataTool;
|
||||
import provider.wz.WZFiles;
|
||||
import tools.Pair;
|
||||
|
||||
import java.util.*;
|
||||
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.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class MonsterInformationProvider {
|
||||
private static final Logger log = LoggerFactory.getLogger(MonsterInformationProvider.class);
|
||||
|
||||
@@ -21,13 +21,18 @@
|
||||
*/
|
||||
package server.life;
|
||||
|
||||
import server.life.LifeFactory.BanishInfo;
|
||||
import server.life.LifeFactory.loseItem;
|
||||
import server.life.LifeFactory.selfDestruction;
|
||||
import tools.Pair;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Frz
|
||||
|
||||
@@ -44,9 +44,19 @@ import tools.PacketCreator;
|
||||
import tools.Pair;
|
||||
|
||||
import java.awt.*;
|
||||
import java.sql.*;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,7 +22,11 @@
|
||||
package server.maps;
|
||||
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.packet.*;
|
||||
import net.packet.ByteBufInPacket;
|
||||
import net.packet.ByteBufOutPacket;
|
||||
import net.packet.InPacket;
|
||||
import net.packet.OutPacket;
|
||||
import net.packet.Packet;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user