uhhh go brrr?

This commit is contained in:
Ceikry
2021-03-11 20:42:32 -06:00
parent 89d51b788b
commit 76c7b16108
2757 changed files with 0 additions and 0 deletions
@@ -0,0 +1,217 @@
package core
import core.game.system.SystemShutdownHook
import core.game.system.mysql.SQLManager
import core.game.world.map.Location
import core.tools.mysql.Database
import core.tools.secondsToTicks
import org.json.simple.JSONObject
import java.io.File
import java.math.BigInteger
/**
* A class holding various variables for the server.
* @author Ceikry
*/
class ServerConstants {
companion object {
@JvmField
var SHUTDOWN_HOOK: Thread = Thread(SystemShutdownHook())
@JvmField
var DATA_PATH: String? = null
//path to the cache
@JvmField
var CACHE_PATH: String? = null
//path for the server store (obsolete, but kept for the sake of system sanity.)
@JvmField
var STORE_PATH: String? = null
//path for player saves
@JvmField
var PLAYER_SAVE_PATH: String? = null
@JvmField
var PLAYER_ATTRIBUTE_PATH = "ish";
//path to the various config files, such as npc_spawns.json
var CONFIG_PATH: String? = null
@JvmField
var GRAND_EXCHANGE_DATA_PATH: String? = null
@JvmField
var RDT_DATA_PATH: String? = null
@JvmField
var OBJECT_PARSER_PATH: String? = null
@JvmField
var SCRIPTS_PATH: String? = null
@JvmField
var DIALOGUE_SCRIPTS_PATH: String? = null
@JvmField
var LOGS_PATH: String? = null
@JvmField
var BOT_DATA_PATH: String? = null
//the max number of players.
@JvmField
var MAX_PLAYERS = 0
//the max number of NPCs
@JvmField
var MAX_NPCS = 0
//the location where new players are placed on login.
@JvmField
var START_LOCATION: Location? = null
//Location for all home teleports/respawn location
@JvmField
var HOME_LOCATION: Location? = null
//the name for the database
@JvmField
var DATABASE_NAME: String? = null
//username for the database
@JvmField
var DATABASE_USER: String? = null
//password for the database
@JvmField
var DATABASE_PASS: String? = null
//address for the database
@JvmField
var DATABASE_ADDRESS: String? = null
@JvmField
var DATABASE_PORT: String? = null
@JvmField
var WRITE_LOGS: Boolean = false
@JvmField
var BANK_SIZE: Int = 496
@JvmField
var GE_AUTOSAVE_FREQUENCY = secondsToTicks(3600) //1 hour
@JvmField
var GE_AUTOSTOCK_ENABLED = false
//location names for the ::to command.
val TELEPORT_DESTINATIONS = arrayOf(
arrayOf(Location.create(2974, 4383, 2), "corp", "corporal", "corporeal"),
arrayOf(Location.create(2659, 2649, 0), "pc", "pest control", "pest"),
arrayOf(Location.create(3293, 3184, 0), "al kharid", "alkharid", "kharid"),
arrayOf(Location.create(3222, 3217, 0), "lumbridge", "lumby"),
arrayOf(Location.create(3110, 3168, 0), "wizard tower", "wizards tower", "tower", "wizards"),
arrayOf(Location.create(3083, 3249, 0), "draynor", "draynor village"),
arrayOf(Location.create(3019, 3244, 0), "port sarim", "sarim"),
arrayOf(Location.create(2956, 3209, 0), "rimmington"),
arrayOf(Location.create(2965, 3380, 0), "fally", "falador"),
arrayOf(Location.create(2895, 3436, 0), "taverley"),
arrayOf(Location.create(3080, 3423, 0), "barbarian village", "barb"),
arrayOf(Location.create(3213, 3428, 0), "varrock"),
arrayOf(Location.create(3164, 3485, 0), "grand exchange", "ge"),
arrayOf(Location.create(2917, 3175, 0), "karamja"),
arrayOf(Location.create(2450, 5165, 0), "tzhaar"),
arrayOf(Location.create(2795, 3177, 0), "brimhaven"),
arrayOf(Location.create(2849, 2961, 0), "shilo village", "shilo"),
arrayOf(Location.create(2605, 3093, 0), "yanille"),
arrayOf(Location.create(2663, 3305, 0), "ardougne", "ardy"),
arrayOf(Location.create(2450, 3422, 0), "gnome stronghold", "gnome"),
arrayOf(Location.create(2730, 3485, 0), "camelot", "cammy", "seers"),
arrayOf(Location.create(2805, 3435, 0), "catherby"),
arrayOf(Location.create(2659, 3657, 0), "rellekka"),
arrayOf(Location.create(2890, 3676, 0), "trollheim"),
arrayOf(Location.create(2914, 3746, 0), "godwars", "gwd", "god wars"),
arrayOf(Location.create(3180, 3684, 0), "bounty hunter", "bh"),
arrayOf(Location.create(3272, 3687, 0), "clan wars", "clw"),
arrayOf(Location.create(3090, 3957, 0), "mage arena", "mage", "magearena", "arena"),
arrayOf(Location.create(3069, 10257, 0), "king black dragon", "kbd"),
arrayOf(Location.create(3359, 3416, 0), "digsite"),
arrayOf(Location.create(3488, 3489, 0), "canifis"),
arrayOf(Location.create(3428, 3526, 0), "slayer tower", "slayer"),
arrayOf(Location.create(3502, 9483, 2), "kalphite queen", "kq", "kalphite hive", "kalphite"),
arrayOf(Location.create(3233, 2913, 0), "pyramid"),
arrayOf(Location.create(3419, 2917, 0), "nardah"),
arrayOf(Location.create(3482, 3090, 0), "uzer"),
arrayOf(Location.create(3358, 2970, 0), "pollnivneach", "poln"),
arrayOf(Location.create(3305, 2788, 0), "sophanem"),
arrayOf(Location.create(2898, 3544, 0), "burthorpe", "burthorp"),
arrayOf(Location.create(3088, 3491, 0), "edge", "edgeville"),
arrayOf(Location.create(3169, 3034, 0), "bedabin"),
arrayOf(Location.create(3565, 3289, 0), "barrows"),
arrayOf(Location.create(3016, 3513, 0), "bkf", "black knights fortress"),
arrayOf(Location.create(3052, 3481, 0), "monastery")
)
@JvmField
var DATABASE: Database? = null
//if SQL is enabled
@JvmField
var MYSQL = true
//the server name
@JvmField
var SERVER_NAME: String = ""
//The RSA_KEY for the server.
@JvmField
var EXPONENT = BigInteger("52317200263721308660411803146360972546561037484450290559823448967617618536819222494429186211525706853703641369936136465589036631055945454547936148730495933263344792588795811788941129493188907621550836988152620502378278134421731002382361670176785306598134280732756356458964850508114958769985438054979422820241")
//The MODULUS for the server.
@JvmField
var MODULUS = BigInteger("96982303379631821170939875058071478695026608406924780574168393250855797534862289546229721580153879336741968220328805101128831071152160922518190059946555203865621183480223212969502122536662721687753974815205744569357388338433981424032996046420057284324856368815997832596174397728134370577184183004453899764051")
/**
* Parses a JSONObject and retrieves the values for all settings in this file.
* @author Ceikry
* @param data : The JSONObject to parse.
*/
fun parse(data: JSONObject) {
MAX_PLAYERS = data["max_players"].toString().toInt()
MAX_NPCS = data["max_npcs"].toString().toInt()
START_LOCATION = JSONUtils.parseLocation(data["new_player_location"].toString())
HOME_LOCATION = JSONUtils.parseLocation(data["home_location"].toString())
DATA_PATH = JSONUtils.parsePath(data["data_path"].toString())
CACHE_PATH = JSONUtils.parsePath(data["cache_path"].toString())
STORE_PATH = JSONUtils.parsePath(data["store_path"].toString())
PLAYER_SAVE_PATH = JSONUtils.parsePath(data["save_path"].toString())
CONFIG_PATH = JSONUtils.parsePath(data["configs_path"].toString())
PLAYER_ATTRIBUTE_PATH = PLAYER_SAVE_PATH + "attributes" + File.separator
GRAND_EXCHANGE_DATA_PATH = JSONUtils.parsePath(data["grand_exchange_data_path"].toString())
BOT_DATA_PATH = JSONUtils.parsePath(data["bot_data_path"].toString())
RDT_DATA_PATH = JSONUtils.parsePath(data["rare_drop_table_path"].toString())
OBJECT_PARSER_PATH = JSONUtils.parsePath(data["object_parser_path"].toString())
SCRIPTS_PATH = JSONUtils.parsePath(data["scripts_path"].toString())
DIALOGUE_SCRIPTS_PATH = JSONUtils.parsePath(data["dialogue_scripts_path"].toString())
if(data.containsKey("logs_path")){
LOGS_PATH = data["logs_path"].toString()
}
if(data.containsKey("writeLogs")){
WRITE_LOGS = data["writeLogs"] as Boolean
}
DATABASE_NAME = data["database_name"].toString()
DATABASE_USER = data["database_username"].toString()
DATABASE_PASS = data["database_password"].toString()
DATABASE_ADDRESS = data["database_address"].toString()
DATABASE_PORT = data["database_port"].toString()
DATABASE = Database(DATABASE_ADDRESS, DATABASE_NAME, DATABASE_USER, DATABASE_PASS)
}
}
}
+52
View File
@@ -0,0 +1,52 @@
package core;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
public class Util {
/**
* Capitalize the first letter of the string
* @return Capitalized string
*/
public static String capitalize(String name) {
if (name != null && name.length() != 0) {
char[] chars = name.toCharArray();
chars[0] = Character.toUpperCase(chars[0]);
return new String(chars);
} else {
return name;
}
}
public static String strToEnum(String name) {
name = name.toUpperCase();
return name.replaceAll(" ", "_");
}
public static String enumToString(String name) {
name = name.toLowerCase();
name = name.replaceAll("_", " ");
return capitalize(name);
}
public static double clamp(double input, double min, double max) {
return Math.max(Math.min(input, max), min);
}
public static long nextMidnight(long currentTime) {
Date date = new Date();
Calendar cal = Calendar.getInstance();
date.setTime(currentTime);
cal.setTime(date);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
cal.add(Calendar.HOUR_OF_DAY, 24);
return cal.getTime().getTime();
}
}
+238
View File
@@ -0,0 +1,238 @@
package core.cache;
import java.io.File;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import core.ServerConstants;
import core.cache.def.impl.AnimationDefinition;
import core.cache.def.impl.GraphicDefinition;
import core.cache.def.impl.ItemDefinition;
import core.cache.def.impl.NPCDefinition;
import core.cache.def.impl.ObjectDefinition;
import core.game.system.SystemLogger;
/**
* A cache reader.
*
* @author Emperor
* @author Dragonkk
*/
public final class Cache {
/**
* The cache file manager.
*/
private static CacheFileManager[] cacheFileManagers;
/**
* The container cache file informer.
*/
private static CacheFile referenceFile;
/**
* Construct a new instance.
*/
private Cache(String location) {
try {
init(location);
} catch (Throwable e) {
e.printStackTrace();
}
}
/**
* Initialize the cache reader.
*
* @param path The cache path.x
* @throws Throwable When an exception occurs.
*/
public static void init(String path) throws Throwable {
SystemLogger.logInfo("Initializing cache...");
byte[] cacheFileBuffer = new byte[520];
RandomAccessFile containersInformFile = new RandomAccessFile(path + File.separator + "main_file_cache.idx255", "r");
RandomAccessFile dataFile = new RandomAccessFile(path + File.separator + "main_file_cache.dat2", "r");
referenceFile = new CacheFile(255, containersInformFile, dataFile, 500000, cacheFileBuffer);
int length = (int) (containersInformFile.length() / 6);
cacheFileManagers = new CacheFileManager[length];
for (int i = 0; i < length; i++) {
File f = new File(path + File.separator + "main_file_cache.idx" + i);
if (f.exists() && f.length() > 0) {
CacheFile cacheFile = new CacheFile(i, new RandomAccessFile(f, "r"), dataFile, 1000000, cacheFileBuffer);
cacheFileManagers[i] = new CacheFileManager(cacheFile, true);
if (cacheFileManagers[i].getInformation() == null) {
SystemLogger.logErr("Error loading cache index " + i + ": no information.");
cacheFileManagers[i] = null;
}
}
}
ItemDefinition.parse();
ObjectDefinition.parse();
}
/**
* Initializes the cache.
*/
public static void init() {
try {
init(ServerConstants.CACHE_PATH);
} catch (Throwable e) {
e.printStackTrace();
}
}
/**
* Gets the archive buffer for the grab requests.
*
* @param index The index id.
* @param archive The archive id.
* @param priority The priority.
* @param encryptionValue The current encryption value.
* @return The byte buffer.
*/
public static ByteBuffer getArchiveData(int index, int archive, boolean priority, int encryptionValue) {
byte[] data = index == 255 ? referenceFile.getContainerData(archive) : cacheFileManagers[index].getCacheFile().getContainerData(archive);
if (data == null || data.length < 1) {
SystemLogger.logErr("Invalid JS-5 request - " + index + ", " + archive + ", " + priority + ", " + encryptionValue + "!");
return null;
}
int compression = data[0] & 0xff;
int length = ((data[1] & 0xff) << 24) + ((data[2] & 0xff) << 16) + ((data[3] & 0xff) << 8) + (data[4] & 0xff);
int settings = compression;
if (!priority) {
settings |= 0x80;
}
int realLength = compression != 0 ? length + 4 : length;
// TODO There are two archives that lack two bytes at the end (The version, most likely). This causes the client CRC to be miscalculated. To combat this, we simply send two more bytes if the length seems to be off.
realLength += (index != 255 && compression != 0 && data.length - length == 9) ? 2 : 0;
ByteBuffer buffer = ByteBuffer.allocate((realLength + 5) + (realLength / 512) + 10);
buffer.put((byte) index);
buffer.putShort((short) archive);
buffer.put((byte) settings);
buffer.putInt(length);
for (int i = 5; i < realLength + 5; i++) {
if (buffer.position() % 512 == 0) {
buffer.put((byte) 255);
}
if (data.length > i)
buffer.put(data[i]);
else
buffer.put((byte) 0);
}
if (encryptionValue != 0) {
for (int i = 0; i < buffer.position(); i++) {
buffer.put(i, (byte) (buffer.get(i) ^ encryptionValue));
}
}
buffer.flip();
return buffer;
}
/**
* Generate the reference data for the cache files.
*
* @return The reference data byte array.
*/
public static final byte[] generateReferenceData() {
ByteBuffer buffer = ByteBuffer.allocate(cacheFileManagers.length * 8);
for (int index = 0; index < cacheFileManagers.length; index++) {
if (cacheFileManagers[index] == null) {
buffer.putInt(index == 24 ? 609698396 : 0);
buffer.putInt(0);
continue;
}
buffer.putInt(cacheFileManagers[index].getInformation().getInformationContainer().getCrc());
buffer.putInt(cacheFileManagers[index].getInformation().getRevision());
}
return buffer.array();
}
/**
* Get the cache file managers.
*
* @return The cache file managers.
*/
public static final CacheFileManager[] getIndexes() {
return cacheFileManagers;
}
/**
* Get the container cache file informer.
*
* @return The container cache file informer.
*/
public static final CacheFile getReferenceFile() {
return referenceFile;
}
/**
* Method used to return the component size of the interface.
*
* @param interfaceId the interface.
* @return the value.
*/
public static final int getInterfaceDefinitionsComponentsSize(int interfaceId) {
return getIndexes()[3].getFilesSize(interfaceId);
}
/**
* Method used to return the max size of the interface definitions.
*
* @return the size.
*/
public static final int getInterfaceDefinitionsSize() {
return getIndexes()[3].getContainersSize();
}
/**
* Method used to return the {@link NPCDefinition} size.
*
* @return the size.
*/
public static final int getNPCDefinitionsSize() {
int lastContainerId = getIndexes()[18].getContainersSize() - 1;
return lastContainerId * 128 + getIndexes()[18].getFilesSize(lastContainerId);
}
/**
* Method used to return the {@link GraphicDefinition} size.
*
* @return the size.
*/
public static final int getGraphicDefinitionsSize() {
int lastContainerId = getIndexes()[21].getContainersSize() - 1;
return lastContainerId * 256 + getIndexes()[21].getFilesSize(lastContainerId);
}
/**
* Method used to return the {@link AnimationDefinition} size.
*
* @return the size.
*/
public static final int getAnimationDefinitionsSize() {
int lastContainerId = getIndexes()[20].getContainersSize() - 1;
return lastContainerId * 128 + getIndexes()[20].getFilesSize(lastContainerId);
}
/**
* Method used to return the {@link ObjectDefinition} size.
*
* @return the size.
*/
public static final int getObjectDefinitionsSize() {
int lastContainerId = getIndexes()[16].getContainersSize() - 1;
return lastContainerId * 256 + getIndexes()[16].getFilesSize(lastContainerId);
}
/**
* Method used to return the item definition size.
*
* @return the size.
*/
public static final int getItemDefinitionsSize() {
int lastContainerId = getIndexes()[19].getContainersSize() - 1;
return lastContainerId * 256 + getIndexes()[19].getFilesSize(lastContainerId);
}
}
+148
View File
@@ -0,0 +1,148 @@
package core.cache;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import core.cache.crypto.XTEACryption;
import core.cache.misc.ContainersInformation;
/**
* A cache file.
* @author Dragonkk
*/
public final class CacheFile {
/**
* The index file id.
*/
private int indexFileId;
/**
* The cache file buffer.
*/
private byte[] cacheFileBuffer;
/**
* The maximum container size.
*/
private int maxContainerSize;
/**
* The index file.
*/
private RandomAccessFile indexFile;
/**
* The data file.
*/
private RandomAccessFile dataFile;
/**
* Construct a new cache file.
* @param indexFileId The index file id.
* @param indexFile The index file.
* @param dataFile The data file.
* @param maxContainerSize The maximum container size.
* @param cacheFileBuffer The cache file buffer.
*/
public CacheFile(int indexFileId, RandomAccessFile indexFile, RandomAccessFile dataFile, int maxContainerSize, byte[] cacheFileBuffer) {
this.cacheFileBuffer = cacheFileBuffer;
this.indexFileId = indexFileId;
this.maxContainerSize = maxContainerSize;
this.indexFile = indexFile;
this.dataFile = dataFile;
}
/**
* Get the unpacked container data.
* @param containerId The container id.
* @param xteaKeys The container keys.
* @return The unpacked container data.
*/
public final byte[] getContainerUnpackedData(int containerId, int[] xteaKeys) {
byte[] packedData = getContainerData(containerId);
if (packedData == null) {
return null;
}
if (xteaKeys != null && (xteaKeys[0] != 0 || xteaKeys[1] != 0 || xteaKeys[2] != 0 || xteaKeys[3] != 0)) {
packedData = XTEACryption.decrypt(xteaKeys, ByteBuffer.wrap(packedData), 5, packedData.length).array();
}
return ContainersInformation.unpackCacheContainer(packedData);
}
/**
* Get the container data for the specified container id.
* @param containerId The container id.
* @return The container data.
*/
public final byte[] getContainerData(int containerId) {
synchronized (dataFile) {
try {
if (indexFile.length() < (6 * containerId + 6)) {
return null;
}
indexFile.seek(6 * containerId);
indexFile.read(cacheFileBuffer, 0, 6);
int containerSize = (cacheFileBuffer[2] & 0xff) + (((0xff & cacheFileBuffer[0]) << 16) + (cacheFileBuffer[1] << 8 & 0xff00));
int sector = ((cacheFileBuffer[3] & 0xff) << 16) - (-(0xff00 & cacheFileBuffer[4] << 8) - (cacheFileBuffer[5] & 0xff));
if (containerSize < 0 || containerSize > maxContainerSize) {
return null;
}
if (sector <= 0 || dataFile.length() / 520L < sector) {
return null;
}
byte data[] = new byte[containerSize];
int dataReadCount = 0;
int part = 0;
while (containerSize > dataReadCount) {
if (sector == 0) {
return null;
}
dataFile.seek(520 * sector);
int dataToReadCount = containerSize - dataReadCount;
if (dataToReadCount > 512) {
dataToReadCount = 512;
}
dataFile.read(cacheFileBuffer, 0, 8 + dataToReadCount);
int currentContainerId = (0xff & cacheFileBuffer[1]) + (0xff00 & cacheFileBuffer[0] << 8);
int currentPart = ((cacheFileBuffer[2] & 0xff) << 8) + (0xff & cacheFileBuffer[3]);
int nextSector = (cacheFileBuffer[6] & 0xff) + (0xff00 & cacheFileBuffer[5] << 8) + ((0xff & cacheFileBuffer[4]) << 16);
int currentIndexFileId = cacheFileBuffer[7] & 0xff;
if (containerId != currentContainerId || currentPart != part || indexFileId != currentIndexFileId) {
return null;
}
if (nextSector < 0 || (dataFile.length() / 520L) < nextSector) {
return null;
}
for (int index = 0; dataToReadCount > index; index++) {
data[dataReadCount++] = cacheFileBuffer[8 + index];
}
part++;
sector = nextSector;
}
return data;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
/**
* Get the index file id.
* @return
*/
public int getIndexFileId() {
return indexFileId;
}
/**
* Get the unpacked container data.
* @param containerId The container id.
* @return The unpacked container data.
*/
public final byte[] getContainerUnpackedData(int containerId) {
return getContainerUnpackedData(containerId, null);
}
}
+293
View File
@@ -0,0 +1,293 @@
package core.cache;
import java.nio.ByteBuffer;
import core.cache.misc.ContainersInformation;
import core.tools.StringUtils;
/**
* A cache file manager.
* @author Dragonkk
*/
public final class CacheFileManager {
/**
* The cache file.
*/
private CacheFile cacheFile;
/**
* The containers information.
*/
private ContainersInformation information;
/**
* Discard a files data.
*/
private boolean discardFilesData;
/**
* A array holding file data.
*/
private byte[][][] filesData;
/**
* Construct a new cache file manager.
* @param cacheFile The cache file.
* @param discardFilesData To discard a files data.
*/
public CacheFileManager(CacheFile cacheFile, boolean discardFilesData) {
this.cacheFile = cacheFile;
this.discardFilesData = discardFilesData;
byte[] informContainerPackedData = Cache.getReferenceFile().getContainerData(cacheFile.getIndexFileId());
if (informContainerPackedData == null) {
return;
}
information = new ContainersInformation(informContainerPackedData);
resetFilesData();
}
/**
* Get the cache file.
* @return The cache file.
*/
public CacheFile getCacheFile() {
return cacheFile;
}
/**
* Get the containers size.
* @return The containers size.
*/
public int getContainersSize() {
return information.getContainers().length;
}
/**
* Get the files size.
* @param containerId The container id.
* @return The files size.
*/
public int getFilesSize(int containerId) {
if (!validContainer(containerId)) {
return -1;
}
return information.getContainers()[containerId].getFiles().length;
}
/**
* Reset the file data.
*/
public void resetFilesData() {
filesData = new byte[information.getContainers().length][][];
}
/**
* Check if a file is valid.
* @param containerId The container id.
* @param fileId The file id.
* @return If the file is valid {@code true}.
*/
public boolean validFile(int containerId, int fileId) {
if (!validContainer(containerId)) {
return false;
}
if (fileId < 0 || information.getContainers()[containerId] == null || information.getContainers()[containerId].getFiles().length <= fileId) {
return false;
}
return true;
}
/**
* If a container is valid.
* @param containerId The container id.
* @return If the container is valid {@code true}.
*/
public boolean validContainer(int containerId) {
if (containerId < 0 || information.getContainers().length <= containerId) {
return false;
}
return true;
}
/**
* Get the file ids.
* @param containerId The container id.
* @return The file ids.
*/
public int[] getFileIds(int containerId) {
if (!validContainer(containerId)) {
return null;
}
return information.getContainers()[containerId].getFilesIndexes();
}
/**
* Get the archive id.
* @param name The archive name.
* @return The archive id.
*/
public int getArchiveId(String name) {
if (name == null) {
return -1;
}
int hash = StringUtils.getNameHash(name);
for (int containerIndex = 0; containerIndex < information.getContainersIndexes().length; containerIndex++) {
if (information.getContainers()[information.getContainersIndexes()[containerIndex]].getNameHash() == hash) {
return information.getContainersIndexes()[containerIndex];
}
}
return -1;
}
/**
* Get the file data.
* @param containerId The container id.
* @param fileId The file id.
* @return The get file data.
*/
public byte[] getFileData(int containerId, int fileId) {
return getFileData(containerId, fileId, null);
}
/**
* Load the file data.
* @param archiveId The container id.
* @param keys The container keys.
* @return If the file data is loaded {@code true}.
*/
public boolean loadFilesData(int archiveId, int[] keys) {
byte[] data = cacheFile.getContainerUnpackedData(archiveId, keys);
if (data == null) {
return false;
}
if (filesData[archiveId] == null) {
if (information.getContainers()[archiveId] == null) {
return false; // container inform doesnt exist anymore
}
filesData[archiveId] = new byte[information.getContainers()[archiveId].getFiles().length][];
}
if (information.getContainers()[archiveId].getFilesIndexes().length == 1) {
int fileId = information.getContainers()[archiveId].getFilesIndexes()[0];
filesData[archiveId][fileId] = data;
} else {
int readPosition = data.length;
int amtOfLoops = data[--readPosition] & 0xff;
readPosition -= amtOfLoops * (information.getContainers()[archiveId].getFilesIndexes().length * 4);
ByteBuffer buffer = ByteBuffer.wrap(data);
int filesSize[] = new int[information.getContainers()[archiveId].getFilesIndexes().length];
buffer.position(readPosition);
for (int loop = 0; loop < amtOfLoops; loop++) {
int offset = 0;
for (int fileIndex = 0; fileIndex < information.getContainers()[archiveId].getFilesIndexes().length; fileIndex++) {
filesSize[fileIndex] += offset += buffer.getInt();
}
}
byte[][] filesBufferData = new byte[information.getContainers()[archiveId].getFilesIndexes().length][];
for (int fileIndex = 0; fileIndex < information.getContainers()[archiveId].getFilesIndexes().length; fileIndex++) {
filesBufferData[fileIndex] = new byte[filesSize[fileIndex]];
filesSize[fileIndex] = 0;
}
buffer.position(readPosition);
int sourceOffset = 0;
for (int loop = 0; loop < amtOfLoops; loop++) {
int dataRead = 0;
for (int fileIndex = 0; fileIndex < information.getContainers()[archiveId].getFilesIndexes().length; fileIndex++) {
dataRead += buffer.getInt();
System.arraycopy(data, sourceOffset, filesBufferData[fileIndex], filesSize[fileIndex], dataRead);
sourceOffset += dataRead;
filesSize[fileIndex] += dataRead;
}
}
for (int fileIndex = 0; fileIndex < information.getContainers()[archiveId].getFilesIndexes().length; fileIndex++) {
filesData[archiveId][information.getContainers()[archiveId].getFilesIndexes()[fileIndex]] = filesBufferData[fileIndex];
}
}
return true;
}
/**
* Get the file data.
* @param containerId The container id.
* @param fileId The file id.
* @param xteaKeys The container keys.
* @return The file data.
*/
public byte[] getFileData(int containerId, int fileId, int[] xteaKeys) {
if (!validFile(containerId, fileId)) {
return null;
}
if (filesData[containerId] == null || filesData[containerId][fileId] == null) {
if (!loadFilesData(containerId, xteaKeys)) {
return null;
}
}
byte[] data = filesData[containerId][fileId];
if (discardFilesData) {
if (filesData[containerId].length == 1) {
filesData[containerId] = null;
} else {
filesData[containerId][fileId] = null;
}
}
return data;
}
/**
* Get the containers information.
* @return The containers information.
*/
public ContainersInformation getInformation() {
return information;
}
/**
* Gets the discardFilesData.
* @return the discardFilesData.
*/
public boolean isDiscardFilesData() {
return discardFilesData;
}
/**
* Sets the discardFilesData.
* @param discardFilesData the discardFilesData to set
*/
public void setDiscardFilesData(boolean discardFilesData) {
this.discardFilesData = discardFilesData;
}
/**
* Gets the filesData.
* @return the filesData.
*/
public byte[][][] getFilesData() {
return filesData;
}
/**
* Sets the filesData.
* @param filesData the filesData to set
*/
public void setFilesData(byte[][][] filesData) {
this.filesData = filesData;
}
/**
* Sets the cacheFile.
* @param cacheFile the cacheFile to set
*/
public void setCacheFile(CacheFile cacheFile) {
this.cacheFile = cacheFile;
}
/**
* Sets the information.
* @param information the information to set
*/
public void setInformation(ContainersInformation information) {
this.information = information;
}
}
+193
View File
@@ -0,0 +1,193 @@
package core.cache;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.util.HashMap;
import java.util.Map;
import core.cache.misc.buffer.ByteBufferUtils;
/**
* The server data storage.
* @author Emperor
*/
public final class ServerStore {
/**
* The storage.
*/
private static Map<String, StoreFile> storage = new HashMap<>();
/**
* If the store has initialized.
*/
private static boolean initialized;
/**
* Initializes the store.
* @param path The file path.
*/
public static void init(String path) {
storage = new HashMap<>();
File file = new File(path + "/dynamic_cache.keldagrim");
if (file.exists()) {
try (RandomAccessFile raf = new RandomAccessFile(file, "rw")) {
FileChannel channel = raf.getChannel();
ByteBuffer buffer = channel.map(MapMode.READ_WRITE, 0, channel.size());
int size = buffer.getShort() & 0xFFFF;
for (int i = 0; i < size; i++) {
StoreFile store = new StoreFile();
store.setDynamic(true);
String archive = ByteBufferUtils.getString(buffer);
byte[] data = new byte[buffer.getInt()];
buffer.get(data);
store.setData(data);
storage.put(archive, store);
}
if (buffer.hasRemaining()) {
throw new IllegalStateException("Unable to read all dynamic data (size=" + size + ")!");
}
channel.close();
raf.close();
} catch (IOException e) {
e.printStackTrace();
}
}
initialized = true;
}
/**
* Used for writing the static store.
* @param path The path.
*/
public static void createStaticStore(String path) {
write(path + "/static_cache.keldagrim", false);
}
/**
* Writes all the dynamic storage files (on server termination).
* @param path The path.
*/
public static void dump(String path) {
write(path + "/dynamic_cache.keldagrim", true);
}
/**
* Writes the store file to the given file path.
* @param filePath The file path.
* @param dynamic If the dynamic store is being written.
*/
public static void write(String filePath, boolean dynamic) {
if (!initialized) {
throw new IllegalStateException("Server store has not been initialized!");
}
File f = new File(filePath);
if (f.exists()) {
f.delete();
}
ByteBuffer buffer = ByteBuffer.allocate(1 << 28);
buffer.putShort((short) 0);
int size = 0;
for (String archive : storage.keySet()) {
StoreFile file = storage.get(archive);
if (file.isDynamic() != dynamic) {
continue;
}
size++;
ByteBuffer buf = file.data();
ByteBufferUtils.putString(archive, buffer);
buffer.putInt(buf.remaining());
buffer.put(buf);
}
buffer.putShort(0, (short) size);
buffer.flip();
try (RandomAccessFile raf = new RandomAccessFile(f, "rw")) {
FileChannel channel = raf.getChannel();
channel.write(buffer);
channel.close();
raf.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Sets the archive data.
* @param archive The archive id.
* @param buffer The readable buffer.
*/
public static void setArchive(String archive, ByteBuffer buffer) {
setArchive(archive, buffer, true);
}
/**
* Sets the archive data.
* @param archive The archive id.
* @param buffer The readable buffer.
* @param dynamic If the data changes during server runtime.
*/
public static void setArchive(String archive, ByteBuffer buffer, boolean dynamic) {
byte[] data = new byte[buffer.remaining()];
buffer.get(data);
setArchive(archive, data, dynamic, true);
}
/**
* Sets the archive data.
* @param archive The archive index.
* @param data The archive data.
* @param dynamic If the data changes during server runtime.
*/
public static void setArchive(String archive, byte[] data, boolean dynamic) {
setArchive(archive, data, dynamic, true);
}
/**
* Sets the archive data.
* @param archive The archive index.
* @param data The archive data.
* @param dynamic If the data changes during server runtime.
* @param overwrite If the archive should be overwritten.
*/
public static void setArchive(String archive, byte[] data, boolean dynamic, boolean overwrite) {
StoreFile file = storage.get(archive);
if (file == null) {
storage.put(archive, file = new StoreFile());
} else if (!overwrite) {
throw new IllegalStateException("Already contained archive " + archive + "!");
}
file.setDynamic(dynamic);
file.setData(data);
}
/**
* Gets the archive data for the given archive id.
* @param archive The archive index.
* @return The archive data.
*/
public static ByteBuffer getArchive(String archive) {
return get(archive).data();
}
/**
* Sets the archive file.
* @param archive The archive.
* @param file The file.
*/
public static void set(String archive, StoreFile file) {
storage.put(archive, file);
}
/**
* Gets the store file for the given archive.
* @param archive The archive id.
* @return The store file.
*/
public static StoreFile get(String archive) {
return storage.get(archive);
}
}
+72
View File
@@ -0,0 +1,72 @@
package core.cache;
import java.nio.ByteBuffer;
/**
* Represents a file used in the server store.
* @author Emperor
*/
public final class StoreFile {
/**
* If the data can change during server runtime.
*/
private boolean dynamic;
/**
* The file data.
*/
private byte[] data;
/**
* Constructs a new {@code StoreFile} {@code Object}.
*/
public StoreFile() {
/*
* empty.
*/
}
/**
* Puts the data on the buffer.
* @param buffer The buffer.
*/
public void put(ByteBuffer buffer) {
byte[] data = new byte[buffer.remaining()];
buffer.get(data);
this.data = data;
}
/**
* Creates a byte buffer containing the file data.
* @return The buffer.
*/
public ByteBuffer data() {
return ByteBuffer.wrap(data);
}
/**
* Sets the data.
* @param data The data.
*/
public void setData(byte[] data) {
this.data = data;
}
/**
* Gets the dynamic.
* @return The dynamic.
*/
public boolean isDynamic() {
return dynamic;
}
/**
* Sets the dynamic.
* @param dynamic The dynamic to set.
*/
public void setDynamic(boolean dynamic) {
this.dynamic = dynamic;
}
}
@@ -0,0 +1,56 @@
package core.cache.bzip2;
public class BZip2BlockEntry {
boolean aBooleanArray2205[];
boolean aBooleanArray2213[];
byte aByte2201;
byte aByteArray2204[];
byte aByteArray2211[];
byte aByteArray2212[];
byte aByteArray2214[];
byte aByteArray2219[];
byte aByteArray2224[];
byte aByteArrayArray2229[][];
int anInt2202;
int anInt2203;
int anInt2206;
int anInt2207;
int anInt2208;
int anInt2209;
int anInt2215;
int anInt2216;
int anInt2217;
int anInt2221;
int anInt2222;
int anInt2223;
int anInt2225;
int anInt2227;
int anInt2232;
int anIntArray2200[];
int anIntArray2220[];
int anIntArray2226[];
int anIntArray2228[];
int anIntArrayArray2210[][];
int anIntArrayArray2218[][];
int anIntArrayArray2230[][];
public BZip2BlockEntry() {
anIntArray2200 = new int[6];
anInt2203 = 0;
aByteArray2204 = new byte[4096];
aByteArray2211 = new byte[256];
aByteArray2214 = new byte[18002];
aByteArray2219 = new byte[18002];
anIntArray2220 = new int[257];
anIntArrayArray2218 = new int[6][258];
aBooleanArray2205 = new boolean[16];
aBooleanArray2213 = new boolean[256];
anInt2209 = 0;
anIntArray2226 = new int[16];
anIntArrayArray2210 = new int[6][258];
aByteArrayArray2229 = new byte[6][258];
anIntArrayArray2230 = new int[6][258];
anIntArray2228 = new int[256];
}
}
@@ -0,0 +1,536 @@
package core.cache.bzip2;
public class BZip2Decompressor {
private static int anIntArray257[];
private static BZip2BlockEntry entryInstance = new BZip2BlockEntry();
public static final void decompress(byte decompressedData[], byte packedData[], int containerSize, int blockSize) {
synchronized (entryInstance) {
entryInstance.aByteArray2224 = packedData;
entryInstance.anInt2209 = blockSize;
entryInstance.aByteArray2212 = decompressedData;
entryInstance.anInt2203 = 0;
entryInstance.anInt2206 = decompressedData.length;
entryInstance.anInt2232 = 0;
entryInstance.anInt2207 = 0;
entryInstance.anInt2217 = 0;
entryInstance.anInt2216 = 0;
method1793(entryInstance);
entryInstance.aByteArray2224 = null;
entryInstance.aByteArray2212 = null;
}
}
private static final void method1785(BZip2BlockEntry entry) {
entry.anInt2215 = 0;
for (int i = 0; i < 256; i++) {
if (entry.aBooleanArray2213[i]) {
entry.aByteArray2211[entry.anInt2215] = (byte) i;
entry.anInt2215++;
}
}
}
private static final void method1786(int ai[], int ai1[], int ai2[], byte abyte0[], int i, int j, int k) {
int l = 0;
for (int i1 = i; i1 <= j; i1++) {
for (int l2 = 0; l2 < k; l2++) {
if (abyte0[l2] == i1) {
ai2[l] = l2;
l++;
}
}
}
for (int j1 = 0; j1 < 23; j1++) {
ai1[j1] = 0;
}
for (int k1 = 0; k1 < k; k1++) {
ai1[abyte0[k1] + 1]++;
}
for (int l1 = 1; l1 < 23; l1++) {
ai1[l1] += ai1[l1 - 1];
}
for (int i2 = 0; i2 < 23; i2++) {
ai[i2] = 0;
}
int i3 = 0;
for (int j2 = i; j2 <= j; j2++) {
i3 += ai1[j2 + 1] - ai1[j2];
ai[j2] = i3 - 1;
i3 <<= 1;
}
for (int k2 = i + 1; k2 <= j; k2++) {
ai1[k2] = (ai[k2 - 1] + 1 << 1) - ai1[k2];
}
}
private static final void method1787(BZip2BlockEntry entry) {
byte byte4 = entry.aByte2201;
int i = entry.anInt2222;
int j = entry.anInt2227;
int k = entry.anInt2221;
int ai[] = anIntArray257;
int l = entry.anInt2208;
byte abyte0[] = entry.aByteArray2212;
int i1 = entry.anInt2203;
int j1 = entry.anInt2206;
int k1 = j1;
int l1 = entry.anInt2225 + 1;
label0: do {
if (i > 0) {
do {
if (j1 == 0) {
break label0;
}
if (i == 1) {
break;
}
abyte0[i1] = byte4;
i--;
i1++;
j1--;
} while (true);
if (j1 == 0) {
i = 1;
break;
}
abyte0[i1] = byte4;
i1++;
j1--;
}
boolean flag = true;
while (flag) {
flag = false;
if (j == l1) {
i = 0;
break label0;
}
byte4 = (byte) k;
l = ai[l];
byte byte0 = (byte) (l & 0xff);
l >>= 8;
j++;
if (byte0 != k) {
k = byte0;
if (j1 == 0) {
i = 1;
} else {
abyte0[i1] = byte4;
i1++;
j1--;
flag = true;
continue;
}
break label0;
}
if (j != l1) {
continue;
}
if (j1 == 0) {
i = 1;
break label0;
}
abyte0[i1] = byte4;
i1++;
j1--;
flag = true;
}
i = 2;
l = ai[l];
byte byte1 = (byte) (l & 0xff);
l >>= 8;
if (++j != l1) {
if (byte1 != k) {
k = byte1;
} else {
i = 3;
l = ai[l];
byte byte2 = (byte) (l & 0xff);
l >>= 8;
if (++j != l1) {
if (byte2 != k) {
k = byte2;
} else {
l = ai[l];
byte byte3 = (byte) (l & 0xff);
l >>= 8;
j++;
i = (byte3 & 0xff) + 4;
l = ai[l];
k = (byte) (l & 0xff);
l >>= 8;
j++;
}
}
}
}
} while (true);
entry.anInt2216 += k1 - j1;
entry.aByte2201 = byte4;
entry.anInt2222 = i;
entry.anInt2227 = j;
entry.anInt2221 = k;
anIntArray257 = ai;
entry.anInt2208 = l;
entry.aByteArray2212 = abyte0;
entry.anInt2203 = i1;
entry.anInt2206 = j1;
}
private static final byte method1788(BZip2BlockEntry entry) {
return (byte) method1790(1, entry);
}
private static final byte method1789(BZip2BlockEntry entryInstance2) {
return (byte) method1790(8, entryInstance2);
}
private static final int method1790(int i, BZip2BlockEntry entry) {
int j;
do {
if (entry.anInt2232 >= i) {
int k = entry.anInt2207 >> entry.anInt2232 - i & (1 << i) - 1;
entry.anInt2232 -= i;
j = k;
break;
}
entry.anInt2207 = entry.anInt2207 << 8 | entry.aByteArray2224[entry.anInt2209] & 0xff;
entry.anInt2232 += 8;
entry.anInt2209++;
entry.anInt2217++;
} while (true);
return j;
}
public static void clearBlockEntryInstance() {
entryInstance = null;
}
private static final void method1793(BZip2BlockEntry entryInstance2) {
// unused
/*
* boolean flag = false; boolean flag1 = false; boolean flag2 = false;
* boolean flag3 = false; boolean flag4 = false; boolean flag5 = false;
* boolean flag6 = false; boolean flag7 = false; boolean flag8 = false;
* boolean flag9 = false; boolean flag10 = false; boolean flag11 =
* false; boolean flag12 = false; boolean flag13 = false; boolean flag14
* = false; boolean flag15 = false; boolean flag16 = false; boolean
* flag17 = false;
*/
int j8 = 0;
int ai[] = null;
int ai1[] = null;
int ai2[] = null;
entryInstance2.anInt2202 = 1;
if (anIntArray257 == null) {
anIntArray257 = new int[entryInstance2.anInt2202 * 0x186a0];
}
boolean flag18 = true;
while (flag18) {
byte byte0 = method1789(entryInstance2);
if (byte0 == 23) {
return;
}
byte0 = method1789(entryInstance2);
byte0 = method1789(entryInstance2);
byte0 = method1789(entryInstance2);
byte0 = method1789(entryInstance2);
byte0 = method1789(entryInstance2);
byte0 = method1789(entryInstance2);
byte0 = method1789(entryInstance2);
byte0 = method1789(entryInstance2);
byte0 = method1789(entryInstance2);
byte0 = method1788(entryInstance2);
entryInstance2.anInt2223 = 0;
byte0 = method1789(entryInstance2);
entryInstance2.anInt2223 = entryInstance2.anInt2223 << 8 | byte0 & 0xff;
byte0 = method1789(entryInstance2);
entryInstance2.anInt2223 = entryInstance2.anInt2223 << 8 | byte0 & 0xff;
byte0 = method1789(entryInstance2);
entryInstance2.anInt2223 = entryInstance2.anInt2223 << 8 | byte0 & 0xff;
for (int j = 0; j < 16; j++) {
byte byte1 = method1788(entryInstance2);
if (byte1 == 1) {
entryInstance2.aBooleanArray2205[j] = true;
} else {
entryInstance2.aBooleanArray2205[j] = false;
}
}
for (int k = 0; k < 256; k++) {
entryInstance2.aBooleanArray2213[k] = false;
}
for (int l = 0; l < 16; l++) {
if (entryInstance2.aBooleanArray2205[l]) {
for (int i3 = 0; i3 < 16; i3++) {
byte byte2 = method1788(entryInstance2);
if (byte2 == 1) {
entryInstance2.aBooleanArray2213[l * 16 + i3] = true;
}
}
}
}
method1785(entryInstance2);
int i4 = entryInstance2.anInt2215 + 2;
int j4 = method1790(3, entryInstance2);
int k4 = method1790(15, entryInstance2);
for (int i1 = 0; i1 < k4; i1++) {
int j3 = 0;
do {
byte byte3 = method1788(entryInstance2);
if (byte3 == 0) {
break;
}
j3++;
} while (true);
entryInstance2.aByteArray2214[i1] = (byte) j3;
}
byte abyte0[] = new byte[6];
for (byte byte16 = 0; byte16 < j4; byte16++) {
abyte0[byte16] = byte16;
}
for (int j1 = 0; j1 < k4; j1++) {
byte byte17 = entryInstance2.aByteArray2214[j1];
byte byte15 = abyte0[byte17];
for (; byte17 > 0; byte17--) {
abyte0[byte17] = abyte0[byte17 - 1];
}
abyte0[0] = byte15;
entryInstance2.aByteArray2219[j1] = byte15;
}
for (int k3 = 0; k3 < j4; k3++) {
int k6 = method1790(5, entryInstance2);
for (int k1 = 0; k1 < i4; k1++) {
do {
byte byte4 = method1788(entryInstance2);
if (byte4 == 0) {
break;
}
byte4 = method1788(entryInstance2);
if (byte4 == 0) {
k6++;
} else {
k6--;
}
} while (true);
entryInstance2.aByteArrayArray2229[k3][k1] = (byte) k6;
}
}
for (int l3 = 0; l3 < j4; l3++) {
byte byte8 = 32;
int i = 0;
for (int l1 = 0; l1 < i4; l1++) {
if (entryInstance2.aByteArrayArray2229[l3][l1] > i) {
i = entryInstance2.aByteArrayArray2229[l3][l1];
}
if (entryInstance2.aByteArrayArray2229[l3][l1] < byte8) {
byte8 = entryInstance2.aByteArrayArray2229[l3][l1];
}
}
method1786(entryInstance2.anIntArrayArray2230[l3], entryInstance2.anIntArrayArray2218[l3], entryInstance2.anIntArrayArray2210[l3], entryInstance2.aByteArrayArray2229[l3], byte8, i, i4);
entryInstance2.anIntArray2200[l3] = byte8;
}
int l4 = entryInstance2.anInt2215 + 1;
int i5 = -1;
int j5 = 0;
for (int i2 = 0; i2 <= 255; i2++) {
entryInstance2.anIntArray2228[i2] = 0;
}
int i9 = 4095;
for (int k8 = 15; k8 >= 0; k8--) {
for (int l8 = 15; l8 >= 0; l8--) {
entryInstance2.aByteArray2204[i9] = (byte) (k8 * 16 + l8);
i9--;
}
entryInstance2.anIntArray2226[k8] = i9 + 1;
}
int l5 = 0;
if (j5 == 0) {
i5++;
j5 = 50;
byte byte12 = entryInstance2.aByteArray2219[i5];
j8 = entryInstance2.anIntArray2200[byte12];
ai = entryInstance2.anIntArrayArray2230[byte12];
ai2 = entryInstance2.anIntArrayArray2210[byte12];
ai1 = entryInstance2.anIntArrayArray2218[byte12];
}
j5--;
int l6 = j8;
int k7;
byte byte9;
for (k7 = method1790(l6, entryInstance2); k7 > ai[l6]; k7 = k7 << 1 | byte9) {
l6++;
byte9 = method1788(entryInstance2);
}
for (int k5 = ai2[k7 - ai1[l6]]; k5 != l4;) {
if (k5 == 0 || k5 == 1) {
int i6 = -1;
int j6 = 1;
do {
if (k5 == 0) {
i6 += j6;
} else if (k5 == 1) {
i6 += 2 * j6;
}
j6 *= 2;
if (j5 == 0) {
i5++;
j5 = 50;
byte byte13 = entryInstance2.aByteArray2219[i5];
j8 = entryInstance2.anIntArray2200[byte13];
ai = entryInstance2.anIntArrayArray2230[byte13];
ai2 = entryInstance2.anIntArrayArray2210[byte13];
ai1 = entryInstance2.anIntArrayArray2218[byte13];
}
j5--;
int i7 = j8;
int l7;
byte byte10;
for (l7 = method1790(i7, entryInstance2); l7 > ai[i7]; l7 = l7 << 1 | byte10) {
i7++;
byte10 = method1788(entryInstance2);
}
k5 = ai2[l7 - ai1[i7]];
} while (k5 == 0 || k5 == 1);
i6++;
byte byte5 = entryInstance2.aByteArray2211[entryInstance2.aByteArray2204[entryInstance2.anIntArray2226[0]] & 0xff];
entryInstance2.anIntArray2228[byte5 & 0xff] += i6;
for (; i6 > 0; i6--) {
anIntArray257[l5] = byte5 & 0xff;
l5++;
}
} else {
int i11 = k5 - 1;
byte byte6;
if (i11 < 16) {
int i10 = entryInstance2.anIntArray2226[0];
byte6 = entryInstance2.aByteArray2204[i10 + i11];
for (; i11 > 3; i11 -= 4) {
int j11 = i10 + i11;
entryInstance2.aByteArray2204[j11] = entryInstance2.aByteArray2204[j11 - 1];
entryInstance2.aByteArray2204[j11 - 1] = entryInstance2.aByteArray2204[j11 - 2];
entryInstance2.aByteArray2204[j11 - 2] = entryInstance2.aByteArray2204[j11 - 3];
entryInstance2.aByteArray2204[j11 - 3] = entryInstance2.aByteArray2204[j11 - 4];
}
for (; i11 > 0; i11--) {
entryInstance2.aByteArray2204[i10 + i11] = entryInstance2.aByteArray2204[(i10 + i11) - 1];
}
entryInstance2.aByteArray2204[i10] = byte6;
} else {
int k10 = i11 / 16;
int l10 = i11 % 16;
int j10 = entryInstance2.anIntArray2226[k10] + l10;
byte6 = entryInstance2.aByteArray2204[j10];
for (; j10 > entryInstance2.anIntArray2226[k10]; j10--) {
entryInstance2.aByteArray2204[j10] = entryInstance2.aByteArray2204[j10 - 1];
}
entryInstance2.anIntArray2226[k10]++;
for (; k10 > 0; k10--) {
entryInstance2.anIntArray2226[k10]--;
entryInstance2.aByteArray2204[entryInstance2.anIntArray2226[k10]] = entryInstance2.aByteArray2204[(entryInstance2.anIntArray2226[k10 - 1] + 16) - 1];
}
entryInstance2.anIntArray2226[0]--;
entryInstance2.aByteArray2204[entryInstance2.anIntArray2226[0]] = byte6;
if (entryInstance2.anIntArray2226[0] == 0) {
int l9 = 4095;
for (int j9 = 15; j9 >= 0; j9--) {
for (int k9 = 15; k9 >= 0; k9--) {
entryInstance2.aByteArray2204[l9] = entryInstance2.aByteArray2204[entryInstance2.anIntArray2226[j9] + k9];
l9--;
}
entryInstance2.anIntArray2226[j9] = l9 + 1;
}
}
}
entryInstance2.anIntArray2228[entryInstance2.aByteArray2211[byte6 & 0xff] & 0xff]++;
anIntArray257[l5] = entryInstance2.aByteArray2211[byte6 & 0xff] & 0xff;
l5++;
if (j5 == 0) {
i5++;
j5 = 50;
byte byte14 = entryInstance2.aByteArray2219[i5];
j8 = entryInstance2.anIntArray2200[byte14];
ai = entryInstance2.anIntArrayArray2230[byte14];
ai2 = entryInstance2.anIntArrayArray2210[byte14];
ai1 = entryInstance2.anIntArrayArray2218[byte14];
}
j5--;
int j7 = j8;
int i8;
byte byte11;
for (i8 = method1790(j7, entryInstance2); i8 > ai[j7]; i8 = i8 << 1 | byte11) {
j7++;
byte11 = method1788(entryInstance2);
}
k5 = ai2[i8 - ai1[j7]];
}
}
entryInstance2.anInt2222 = 0;
entryInstance2.aByte2201 = 0;
entryInstance2.anIntArray2220[0] = 0;
for (int j2 = 1; j2 <= 256; j2++) {
entryInstance2.anIntArray2220[j2] = entryInstance2.anIntArray2228[j2 - 1];
}
for (int k2 = 1; k2 <= 256; k2++) {
entryInstance2.anIntArray2220[k2] += entryInstance2.anIntArray2220[k2 - 1];
}
for (int l2 = 0; l2 < l5; l2++) {
byte byte7 = (byte) (anIntArray257[l2] & 0xff);
anIntArray257[entryInstance2.anIntArray2220[byte7 & 0xff]] |= l2 << 8;
entryInstance2.anIntArray2220[byte7 & 0xff]++;
}
entryInstance2.anInt2208 = anIntArray257[entryInstance2.anInt2223] >> 8;
entryInstance2.anInt2227 = 0;
entryInstance2.anInt2208 = anIntArray257[entryInstance2.anInt2208];
entryInstance2.anInt2221 = (byte) (entryInstance2.anInt2208 & 0xff);
entryInstance2.anInt2208 >>= 8;
entryInstance2.anInt2227++;
entryInstance2.anInt2225 = l5;
method1787(entryInstance2);
if (entryInstance2.anInt2227 == entryInstance2.anInt2225 + 1 && entryInstance2.anInt2222 == 0) {
flag18 = true;
} else {
flag18 = false;
}
}
}
}
+271
View File
@@ -0,0 +1,271 @@
package core.cache.crypto;
/**
* <p> An implementation of an ISAAC cipher. See <a
* href="http://en.wikipedia.org/wiki/ISAAC_(cipher)">
* http://en.wikipedia.org/wiki/ISAAC_(cipher)</a> for more information. </p>
* <p> This implementation is based on the one written by Bob Jenkins, which is
* available at <a href="http://www.burtleburtle.net/bob/java/rand/Rand.java">
* http://www.burtleburtle.net/bob/java/rand/Rand.java</a>. </p>
* @author Graham Edgecombe
*/
public class ISAACCipher {
/**
* The golden ratio.
*/
public static final int RATIO = 0x9e3779b9;
/**
* The log of the size of the results and memory arrays.
*/
public static final int SIZE_LOG = 8;
/**
* The size of the results and memory arrays.
*/
public static final int SIZE = 1 << SIZE_LOG;
/**
* For pseudorandom lookup.
*/
public static final int MASK = (SIZE - 1) << 2;
/**
* The count through the results.
*/
private int count = 0;
/**
* The results.
*/
private int results[] = new int[SIZE];
/**
* The internal memory state.
*/
private int memory[] = new int[SIZE];
/**
* The accumulator.
*/
private int a;
/**
* The last result.
*/
private int b;
/**
* The counter.
*/
private int c;
/**
* Creates the ISAAC cipher.
* @param seed The seed.
*/
public ISAACCipher(int[] seed) {
for (int i = 0; i < seed.length; i++) {
results[i] = seed[i];
}
init(true);
}
/**
* Gets the next value.
* @return The next value.
*/
public int getNextValue() {
if (count-- == 0) {
isaac();
count = SIZE - 1;
}
return 0;//results[count];
}
/**
* Generates 256 results.
*/
public void isaac() {
int i, j, x, y;
b += ++c;
for (i = 0, j = SIZE / 2; i < SIZE / 2;) {
x = memory[i];
a ^= a << 13;
a += memory[j++];
memory[i] = y = memory[(x & MASK) >> 2] + a + b;
results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x;
x = memory[i];
a ^= a >>> 6;
a += memory[j++];
memory[i] = y = memory[(x & MASK) >> 2] + a + b;
results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x;
x = memory[i];
a ^= a << 2;
a += memory[j++];
memory[i] = y = memory[(x & MASK) >> 2] + a + b;
results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x;
x = memory[i];
a ^= a >>> 16;
a += memory[j++];
memory[i] = y = memory[(x & MASK) >> 2] + a + b;
results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x;
}
for (j = 0; j < SIZE / 2;) {
x = memory[i];
a ^= a << 13;
a += memory[j++];
memory[i] = y = memory[(x & MASK) >> 2] + a + b;
results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x;
x = memory[i];
a ^= a >>> 6;
a += memory[j++];
memory[i] = y = memory[(x & MASK) >> 2] + a + b;
results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x;
x = memory[i];
a ^= a << 2;
a += memory[j++];
memory[i] = y = memory[(x & MASK) >> 2] + a + b;
results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x;
x = memory[i];
a ^= a >>> 16;
a += memory[j++];
memory[i] = y = memory[(x & MASK) >> 2] + a + b;
results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x;
}
}
/**
* Initialises the ISAAC.
* @param flag Flag indicating if we should perform a second pass.
*/
public void init(boolean flag) {
int i;
int a, b, c, d, e, f, g, h;
a = b = c = d = e = f = g = h = RATIO;
for (i = 0; i < 4; ++i) {
a ^= b << 11;
d += a;
b += c;
b ^= c >>> 2;
e += b;
c += d;
c ^= d << 8;
f += c;
d += e;
d ^= e >>> 16;
g += d;
e += f;
e ^= f << 10;
h += e;
f += g;
f ^= g >>> 4;
a += f;
g += h;
g ^= h << 8;
b += g;
h += a;
h ^= a >>> 9;
c += h;
a += b;
}
for (i = 0; i < SIZE; i += 8) {
if (flag) {
a += results[i];
b += results[i + 1];
c += results[i + 2];
d += results[i + 3];
e += results[i + 4];
f += results[i + 5];
g += results[i + 6];
h += results[i + 7];
}
a ^= b << 11;
d += a;
b += c;
b ^= c >>> 2;
e += b;
c += d;
c ^= d << 8;
f += c;
d += e;
d ^= e >>> 16;
g += d;
e += f;
e ^= f << 10;
h += e;
f += g;
f ^= g >>> 4;
a += f;
g += h;
g ^= h << 8;
b += g;
h += a;
h ^= a >>> 9;
c += h;
a += b;
memory[i] = a;
memory[i + 1] = b;
memory[i + 2] = c;
memory[i + 3] = d;
memory[i + 4] = e;
memory[i + 5] = f;
memory[i + 6] = g;
memory[i + 7] = h;
}
if (flag) {
for (i = 0; i < SIZE; i += 8) {
a += memory[i];
b += memory[i + 1];
c += memory[i + 2];
d += memory[i + 3];
e += memory[i + 4];
f += memory[i + 5];
g += memory[i + 6];
h += memory[i + 7];
a ^= b << 11;
d += a;
b += c;
b ^= c >>> 2;
e += b;
c += d;
c ^= d << 8;
f += c;
d += e;
d ^= e >>> 16;
g += d;
e += f;
e ^= f << 10;
h += e;
f += g;
f ^= g >>> 4;
a += f;
g += h;
g ^= h << 8;
b += g;
h += a;
h ^= a >>> 9;
c += h;
a += b;
memory[i] = a;
memory[i + 1] = b;
memory[i + 2] = c;
memory[i + 3] = d;
memory[i + 4] = e;
memory[i + 5] = f;
memory[i + 6] = g;
memory[i + 7] = h;
}
}
isaac();
count = SIZE;
}
}
+45
View File
@@ -0,0 +1,45 @@
package core.cache.crypto;
/**
* Represents a ISAAC key pair, for both input and output.
* @author `Discardedx2
*/
public final class ISAACPair {
/**
* The input cipher.
*/
private ISAACCipher input;
/**
* The output cipher.
*/
private ISAACCipher output;
/**
* Constructs a new {@code ISAACPair} {@code Object}.
* @param input The input cipher.
* @param output The output cipher.
*/
public ISAACPair(ISAACCipher input, ISAACCipher output) {
this.input = input;
this.output = output;
}
/**
* Gets the input cipher.
* @return The input cipher.
*/
public ISAACCipher getInput() {
return input;
}
/**
* Gets the output cipher.
* @return The output cipher.
*/
public ISAACCipher getOutput() {
return output;
}
}
+124
View File
@@ -0,0 +1,124 @@
package core.cache.crypto;
import java.nio.ByteBuffer;
/**
* Holds XTEA cryption methods.
* @author ?
* @author Emperor
*/
public final class XTEACryption {
/**
* The delta value
*/
private static final int DELTA = -1640531527;
/**
* The sum.
*/
private static final int SUM = -957401312;
/**
* The amount of "cryption cycles".
*/
private static final int NUM_ROUNDS = 32;
/**
* Constructs a new {@code XTEACryption}.
*/
private XTEACryption() {
/*
* empty.
*/
}
/**
* Decrypts the contents of the buffer.
* @param keys The cryption keys.
* @param buffer The buffer.
*/
public static ByteBuffer decrypt(int[] keys, ByteBuffer buffer) {
return decrypt(keys, buffer, buffer.position(), buffer.limit());
}
/**
* Decrypts the buffer data.
* @param keys The keys.
* @param buffer The buffer to decrypt.
* @param offset The offset of the data to decrypt.
* @param length The length.
* @return The decrypted data.
*/
public static ByteBuffer decrypt(int[] keys, ByteBuffer buffer, int offset, int length) {
int numBlocks = (length - offset) / 8;
int[] block = new int[2];
for (int i = 0; i < numBlocks; i++) {
int index = i * 8 + offset;
block[0] = buffer.getInt(index);
block[1] = buffer.getInt(index + 4);
decipher(keys, block);
buffer.putInt(index, block[0]);
buffer.putInt(index + 4, block[1]);
}
return buffer;
}
/**
* Deciphers the values.
* @param keys The cryption key.
* @param block The values to decipher.
*/
private static void decipher(int[] keys, int[] block) {
long sum = SUM;
for (int i = 0; i < NUM_ROUNDS; i++) {
block[1] -= (keys[(int) ((sum & 0x1933) >>> 11)] + sum ^ block[0] + (block[0] << 4 ^ block[0] >>> 5));
sum -= DELTA;
block[0] -= ((block[1] << 4 ^ block[1] >>> 5) + block[1] ^ keys[(int) (sum & 0x3)] + sum);
}
}
/**
* Encrypts the contents of the byte buffer.
* @param keys The cryption keys.
* @param buffer The buffer to encrypt.
*/
public static void encrypt(int[] keys, ByteBuffer buffer) {
encrypt(keys, buffer, buffer.position(), buffer.limit());
}
/**
* Encrypts the buffer data.
* @param keys The keys.
* @param buffer The buffer to encrypt.
* @param offset The offset of the data to encrypt.
* @param length The length.
* @return The encrypted data.
*/
public static void encrypt(int[] keys, ByteBuffer buffer, int offset, int length) {
int numBlocks = (length - offset) / 8;
int[] block = new int[2];
for (int i = 0; i < numBlocks; i++) {
int index = i * 8 + offset;
block[0] = buffer.getInt(index);
block[1] = buffer.getInt(index + 4);
encipher(keys, block);
buffer.putInt(index, block[0]);
buffer.putInt(index + 4, block[1]);
}
}
/**
* Enciphers the values of the block.
* @param keys The cryption keys.
* @param block The block to encipher.
*/
private static void encipher(int[] keys, int[] block) {
long sum = 0;
for (int i = 0; i < NUM_ROUNDS; i++) {
block[0] += ((block[1] << 4 ^ block[1] >>> 5) + block[1] ^ keys[(int) (sum & 0x3)] + sum);
sum += DELTA;
block[1] += (keys[(int) ((sum & 0x1933) >>> 11)] + sum ^ block[0] + (block[0] << 4 ^ block[0] >>> 5));
}
}
}
+187
View File
@@ -0,0 +1,187 @@
package core.cache.def;
import java.util.HashMap;
import java.util.Map;
import core.tools.StringUtils;
import core.game.node.Node;
/**
* Represent's a node's definitions.
* @author Emperor
* @param <T> The node type.
*/
public class Definition<T extends Node> {
/**
* The node id.
*/
protected int id;
/**
* The name.
*/
protected String name = "null";
/**
* The examine info.
*/
protected String examine;
/**
* The options.
*/
protected String[] options;
/**
* The configurations.
*/
protected final Map<String, Object> handlers = new HashMap<String, Object>();
/**
* Constructs a new {@code Definition} {@code Object}.
*/
public Definition() {
/*
* empty.
*/
}
/**
* Checks if this node has options.
* @return {@code True} if so.
*/
public boolean hasOptions() {
return hasOptions(true);
}
/**
* Checks if this node has options.
* @param examine If examine should be treated as an option.
* @return {@code True} if so.
*/
public boolean hasOptions(boolean examine) {
if (name.equals("null") || options == null) {
return false;
}
for (String option : options) {
if (option != null && !option.equals("null")) {
if (examine || !option.equals("Examine")) {
return true;
}
}
}
return false;
}
/**
* Gets a configuration of this item's definitions.
* @param key The key.
* @return The configuration value.
*/
@SuppressWarnings("unchecked")
public <V> V getConfiguration(String key) {
return (V) handlers.get(key);
}
/**
* Gets a configuration from this item's definitions.
* @param key The key.
* @param fail The object to return if there was no value found for this
* key.
* @return The value, or the fail object.
*/
@SuppressWarnings("unchecked")
public <V> V getConfiguration(String key, V fail) {
V object = (V) handlers.get(key);
if (object == null) {
return fail;
}
return object;
}
/**
* Gets the id.
* @return The id.
*/
public int getId() {
return id;
}
/**
* Sets the id.
* @param id The id to set.
*/
public void setId(int id) {
this.id = id;
}
/**
* Gets the name.
* @return The name.
*/
public String getName() {
return name;
}
/**
* Sets the name.
* @param name The name to set.
*/
public void setName(String name) {
this.name = name;
}
/**
* Gets the examine.
* @return The examine.
*/
public String getExamine() {
if (examine == null) {
try {
examine = handlers.get("examine").toString();
} catch (Exception e){}
if(examine == null) {
if (name.length() > 0) {
examine = "It's a" + (StringUtils.isPlusN(name) ? "n " : " ") + name + ".";
} else {
examine = "null";
}
}
}
return examine;
}
/**
* Sets the examine.
* @param examine The examine to set.
*/
public void setExamine(String examine) {
this.examine = examine;
}
/**
* Gets the options.
* @return The options.
*/
public String[] getOptions() {
return options;
}
/**
* Sets the options.
* @param options The options to set.
*/
public void setOptions(String[] options) {
this.options = options;
}
/**
* Gets the configurations.
* @return The configurations.
*/
public Map<String, Object> getHandlers() {
return handlers;
}
}
@@ -0,0 +1,201 @@
package core.cache.def.impl;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import core.cache.Cache;
import core.cache.misc.buffer.ByteBufferUtils;
/**
* Represents an animation's definitions.
* @author Emperor
*/
public final class AnimationDefinition {
public int anInt2136;
public int anInt2137;
public int[] anIntArray2139;
public int anInt2140;
public boolean aBoolean2141 = false;
public int anInt2142;
public int emoteItem;
public int anInt2144 = -1;
public int[][] handledSounds;
public boolean[] aBooleanArray2149;
public int[] anIntArray2151;
public boolean aBoolean2152;
public int[] durations;
public int anInt2155;
public boolean aBoolean2158;
public boolean aBoolean2159;
public int anInt2162;
public int anInt2163;
boolean newHeader;
// added
public int[] soundMinDelay;
public int[] soundMaxDelay;
public int[] anIntArray1362;
public boolean effect2Sound;
private static final Map<Integer, AnimationDefinition> animDefs = new HashMap<>();
public static final AnimationDefinition forId(int emoteId) {
try {
AnimationDefinition defs = animDefs.get(emoteId);
if (defs != null) {
return defs;
}
byte[] data = Cache.getIndexes()[20].getFileData(emoteId >>> 7, emoteId & 0x7f);
defs = new AnimationDefinition();
if (data != null) {
defs.readValueLoop(ByteBuffer.wrap(data));
}
defs.method2394();
animDefs.put(emoteId, defs);
return defs;
} catch (Throwable t) {
return null;
}
}
private void readValueLoop(ByteBuffer buffer) {
for (;;) {
int opcode = buffer.get() & 0xFF;
if (opcode == 0) {
break;
}
readValues(buffer, opcode);
}
}
/**
* Gets the duration of this animation in milliseconds.
* @return The duration.
*/
public int getDuration() {
if (durations == null) {
return 0;
}
int duration = 0;
for (int i : durations) {
if (i > 100) {
continue;
}
duration += i * 20;
}
return duration;
}
/**
* Gets the duration of this animation in (600ms) ticks.
* @return The duration in ticks.
*/
public int getDurationTicks() {
int ticks = getDuration() / 600;
return Math.max(ticks, 1);
}
private void readValues(ByteBuffer buffer, int opcode) {
if (opcode == 1) {
int length = buffer.getShort() & 0xFFFF;
durations = new int[length];
for (int i = 0; i < length; i++) {
durations[i] = buffer.getShort() & 0xFFFF;
}
anIntArray2139 = new int[length];
for (int i = 0; i < length; i++) {
anIntArray2139[i] = buffer.getShort() & 0xFFFF;
}
for (int i = 0; i < length; i++) {
anIntArray2139[i] = ((buffer.getShort() & 0xFFFF << 16) + anIntArray2139[i]);
}
} else if (opcode != 2) {
if (opcode != 3) {
if (opcode == 4)
aBoolean2152 = true;
else if (opcode == 5)
anInt2142 = buffer.get() & 0xFF;
else if (opcode != 6) {
if (opcode == 7)
emoteItem = buffer.getShort() & 0xFFFF;
else if ((opcode ^ 0xffffffff) != -9) {
if (opcode != 9) {
if (opcode != 10) {
if (opcode == 11)
anInt2155 = buffer.get() & 0xFF;
else if (opcode == 12) {
int i = buffer.get() & 0xFF;
anIntArray2151 = new int[i];
for (int i_19_ = 0; ((i_19_ ^ 0xffffffff) > (i ^ 0xffffffff)); i_19_++) {
anIntArray2151[i_19_] = buffer.getShort() & 0xFFFF;
}
for (int i_20_ = 0; i > i_20_; i_20_++)
anIntArray2151[i_20_] = ((buffer.getShort() & 0xFFFF << 16) + anIntArray2151[i_20_]);
} else if (opcode == 13) {
// opcode 13
int i = buffer.getShort() & 0xFFFF;
handledSounds = new int[i][];
for (int i_21_ = 0; i_21_ < i; i_21_++) {
int i_22_ = buffer.get() & 0xFF;
if ((i_22_ ^ 0xffffffff) < -1) {
handledSounds[i_21_] = new int[i_22_];
handledSounds[i_21_][0] = ByteBufferUtils.getTriByte(buffer);
for (int i_23_ = 1; ((i_22_ ^ 0xffffffff) < (i_23_ ^ 0xffffffff)); i_23_++) {
handledSounds[i_21_][i_23_] = buffer.getShort() & 0xFFFF;
}
}
}
} else if (opcode == 14) {
aBoolean2141 = true;
} else {
System.out.println("Unhandled animation opcode " + opcode);
}
} else
anInt2162 = buffer.get() & 0xFF;
} else
anInt2140 = buffer.get() & 0xFF;
} else
anInt2136 = buffer.get() & 0xFF;
} else
anInt2144 = buffer.getShort() & 0xFFFF;
} else {
aBooleanArray2149 = new boolean[256];
int length = buffer.get() & 0xFF;
for (int i = 0; i < length; i++) {
aBooleanArray2149[buffer.get() & 0xFF] = true;
}
}
} else
anInt2163 = buffer.getShort() & 0xFFFF;
}
public void method2394() {
if (anInt2140 == -1) {
if (aBooleanArray2149 == null)
anInt2140 = 0;
else
anInt2140 = 2;
}
if (anInt2162 == -1) {
if (aBooleanArray2149 == null)
anInt2162 = 0;
else
anInt2162 = 2;
}
}
public AnimationDefinition() {
anInt2136 = 99;
emoteItem = -1;
anInt2140 = -1;
aBoolean2152 = false;
anInt2142 = 5;
aBoolean2159 = false;
anInt2163 = -1;
anInt2155 = 2;
aBoolean2158 = false;
anInt2162 = -1;
}
}
+255
View File
@@ -0,0 +1,255 @@
package core.cache.def.impl;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import core.cache.Cache;
import core.cache.misc.buffer.ByteBufferUtils;
import core.game.world.GameWorld;
/**
* The CS2 mapping.
* @author Emperor
*/
public final class CS2Mapping {
/**
* The CS2 mappings.
*/
private static final Map<Integer, CS2Mapping> maps = new HashMap<>();
/**
* The script id.
*/
private final int scriptId;
/**
* Unknown value.
*/
private int unknown;
/**
* Second unknown value.
*/
private int unknown1;
/**
* The default string value.
*/
private String defaultString;
/**
* The default integer value.
*/
private int defaultInt;
/**
* The mapping.
*/
private HashMap<Integer, Object> map;
/**
* The array of the objects.
*/
private Object[] array;
/**
* Constructs a new {@code CS2Mapping} {@code Object}.
* @param scriptId The script id.
*/
public CS2Mapping(int scriptId) {
this.scriptId = scriptId;
}
/**
* The main method.
* @param args The arguments cast on runtime.
* @throws Throwable When an exception occurs.
*/
public static void main(String... args) throws Throwable {
GameWorld.prompt(false);
BufferedWriter bw = new BufferedWriter(new FileWriter("./cs2.txt"));
for (int i = 0; i < 10000; i++) {
CS2Mapping mapping = forId(i);
if (mapping == null) {
continue;
}
if (mapping.map == null) {
continue;
}
bw.append("ScriptAPI - " + i + " [");
for (int index : mapping.map.keySet()) {
bw.append(mapping.map.get(index) + ": " + index + " ");
}
bw.append("]");
bw.newLine();
}
bw.flush();
bw.close();
}
/**
* Gets the mapping for the given script id.
* @param scriptId The script id.
* @return The mapping.
*/
public static CS2Mapping forId(int scriptId) {
CS2Mapping mapping = maps.get(scriptId);
if (mapping != null) {
return mapping;
}
mapping = new CS2Mapping(scriptId);
byte[] bs = Cache.getIndexes()[17].getFileData(scriptId >>> 8, scriptId & 0xFF);
if (bs != null) {
mapping.load(ByteBuffer.wrap(bs));
} else {
return null;
}
maps.put(scriptId, mapping);
return mapping;
}
/**
* Loads the mapping data.
* @param buffer The buffer to read the data from.
*/
private void load(ByteBuffer buffer) {
int opcode;
while ((opcode = buffer.get() & 0xFF) != 0) {
switch (opcode) {
case 1:
unknown = buffer.get() & 0xFF;
break;
case 2:
unknown1 = buffer.get() & 0xFF;
break;
case 3:
defaultString = ByteBufferUtils.getString(buffer);
break;
case 4:
defaultInt = buffer.getInt();
break;
case 5:
case 6:
int size = buffer.getShort() & 0xFFFF;
String string = null;
int val = 0;
map = new HashMap<>(size);
array = new Object[size];
for (int i = 0; i < size; i++) {
int key = buffer.getInt();
if (opcode == 5) {
string = ByteBufferUtils.getString(buffer);
array[i] = string;
map.put(key, string);
} else {
val = buffer.getInt();
array[i] = val;
map.put(key, val);
}
}
break;
}
}
}
/**
* Gets the array of objects.
* @return the objects.
*/
public Object[] getArray() {
return array;
}
/**
* Gets the scriptId.
* @return The scriptId.
*/
public int getScriptId() {
return scriptId;
}
/**
* Gets the unknown.
* @return The unknown.
*/
public int getUnknown() {
return unknown;
}
/**
* Sets the unknown.
* @param unknown The unknown to set.
*/
public void setUnknown(int unknown) {
this.unknown = unknown;
}
/**
* Gets the unknown1.
* @return The unknown1.
*/
public int getUnknown1() {
return unknown1;
}
/**
* Sets the unknown1.
* @param unknown1 The unknown1 to set.
*/
public void setUnknown1(int unknown1) {
this.unknown1 = unknown1;
}
/**
* Gets the defaultString.
* @return The defaultString.
*/
public String getDefaultString() {
return defaultString;
}
/**
* Sets the defaultString.
* @param defaultString The defaultString to set.
*/
public void setDefaultString(String defaultString) {
this.defaultString = defaultString;
}
/**
* Gets the defaultInt.
* @return The defaultInt.
*/
public int getDefaultInt() {
return defaultInt;
}
/**
* Sets the defaultInt.
* @param defaultInt The defaultInt to set.
*/
public void setDefaultInt(int defaultInt) {
this.defaultInt = defaultInt;
}
/**
* Gets the map.
* @return The map.
*/
public HashMap<Integer, Object> getMap() {
return map;
}
/**
* Sets the map.
* @param map The map to set.
*/
public void setMap(HashMap<Integer, Object> map) {
this.map = map;
}
}
@@ -0,0 +1,208 @@
package core.cache.def.impl;
import java.nio.ByteBuffer;
import java.util.Arrays;
import core.ServerConstants;
import core.cache.Cache;
/**
* The definitions for player clothing/look.
* @author Emperor
*/
public final class ClothDefinition {
/**
* The equipment slot.
*/
private int equipmentSlot;
/**
* The model ids.
*/
private int[] modelIds;
/**
* Unknown boolean.
*/
private boolean unknownBool;
/**
* Original colors.
*/
private int[] originalColors;
/**
* The colors to change to.
*/
private int[] modifiedColors;
/**
* Original texture colors.
*/
private int[] originalTextureColors;
/**
* Texture colors to change to.
*/
private int[] modifiedTextureColors;
/**
* Other model ids(?)
*/
private int[] models = { -1, -1, -1, -1, -1 };
/**
* Gets the definitions for the given cloth id.
* @param clothId The clothing id.
* @return The definition.
*/
public static ClothDefinition forId(int clothId) {
ClothDefinition def = new ClothDefinition();
byte[] bs = Cache.getIndexes()[2].getFileData(3, clothId);
if (bs != null) {
def.load(ByteBuffer.wrap(bs));
}
return def;
}
/**
* The main method.
* @param args The arguments cast on runtime.
*/
public static void main(String... args) {
try {
Cache.init(ServerConstants.CACHE_PATH);
} catch (Throwable e) {
e.printStackTrace();
}
int length = Cache.getIndexes()[2].getFilesSize(3);
System.out.println("Definition size: " + length + ".");
for (int i = 0; i < length; i++) {
ClothDefinition def = forId(i);
if (def.unknownBool)
System.out.println("Clothing " + i + ": " + def.equipmentSlot + ", " + def.unknownBool + ", " + Arrays.toString(def.modelIds) + ", " + Arrays.toString(def.models));
}
}
/**
* Loads the definitions.
* @param buffer The buffer.
*/
public void load(ByteBuffer buffer) {
int opcode;
while ((opcode = buffer.get() & 0xFF) != 0) {
parse(opcode, buffer);
}
}
/**
* Parses an opcode.
* @param opcode The opcode.
* @param buffer The buffer to read the data from.
*/
private void parse(int opcode, ByteBuffer buffer) {
switch (opcode) {
case 1:
equipmentSlot = buffer.get() & 0xFF;
break;
case 2:
int length = buffer.get() & 0xFF;
modelIds = new int[length];
for (int i = 0; i < length; i++) {
modelIds[i] = buffer.getShort() & 0xFFFF;
}
break;
case 3:
unknownBool = true;
break;
case 40:
length = buffer.get() & 0xFF;
originalColors = new int[length];
modifiedColors = new int[length];
for (int i = 0; i < length; i++) {
originalColors[i] = buffer.getShort();
modifiedColors[i] = buffer.getShort();
}
break;
case 41:
length = buffer.get() & 0xFF;
originalTextureColors = new int[length];
modifiedTextureColors = new int[length];
for (int i = 0; i < length; i++) {
originalTextureColors[i] = buffer.getShort();
modifiedTextureColors[i] = buffer.getShort();
}
break;
default:
if (opcode >= 60 && opcode < 70) {
models[opcode - 60] = buffer.getShort() & 0xFFFF;
}
break;
}
}
/**
* Gets the unknown.
* @return The unknown.
*/
public int getUnknown() {
return equipmentSlot;
}
/**
* Gets the modelIds.
* @return The modelIds.
*/
public int[] getModelIds() {
return modelIds;
}
/**
* Gets the unknownBool.
* @return The unknownBool.
*/
public boolean isUnknownBool() {
return unknownBool;
}
/**
* Gets the originalColors.
* @return The originalColors.
*/
public int[] getOriginalColors() {
return originalColors;
}
/**
* Gets the modifiedColors.
* @return The modifiedColors.
*/
public int[] getModifiedColors() {
return modifiedColors;
}
/**
* Gets the originalTextureColors.
* @return The originalTextureColors.
*/
public int[] getOriginalTextureColors() {
return originalTextureColors;
}
/**
* Gets the modifiedTextureColors.
* @return The modifiedTextureColors.
*/
public int[] getModifiedTextureColors() {
return modifiedTextureColors;
}
/**
* Gets the models.
* @return The models.
*/
public int[] getModels() {
return models;
}
}
@@ -0,0 +1,189 @@
package core.cache.def.impl;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import core.ServerConstants;
import core.cache.Cache;
/**
* Represents a Graphic's definition.
* @author Jagex
*/
public class GraphicDefinition {
public short[] aShortArray1435;
public short[] aShortArray1438;
public int anInt1440;
public boolean aBoolean1442;
public int defaultModel;
public int anInt1446;
public boolean aBoolean1448 = false;
public int anInt1449;
public int animationId;
public int anInt1451;
public int graphicsId;
public int anInt1454;
public short[] aShortArray1455;
public short[] aShortArray1456;
// added
public byte byteValue;
// added
public int intValue;
/**
* The definitions mapping.
*/
private static final Map<Integer, GraphicDefinition> graphicDefinitions = new HashMap<>();
/**
* Gets the graphic definition for the given graphic id.
* @param gfxId The graphic id.
* @return The definition.
*/
public static final GraphicDefinition forId(int gfxId) {
GraphicDefinition def = graphicDefinitions.get(gfxId);
if (def != null) {
return def;
}
byte[] data = Cache.getIndexes()[21].getFileData(gfxId >>> 735411752, gfxId & 0xff);
def = new GraphicDefinition();
def.graphicsId = gfxId;
if (data != null) {
def.readValueLoop(ByteBuffer.wrap(data));
}
graphicDefinitions.put(gfxId, def);
return def;
}
/**
* The main method, used for running a graphic definition search.
* @param s The arguments cast on runtime.
*/
public static final void main(String... s) {
try {
Cache.init(ServerConstants.CACHE_PATH);
} catch (Throwable e) {
e.printStackTrace();
}
// 5046 - 5050 are related anims & 2148
GraphicDefinition d = GraphicDefinition.forId(803);
System.out.println("Graphic " + d.graphicsId + " anim id = " + d.animationId + ", " + d.defaultModel + ".");
for (int i = 0; i < 5000; i++) {
GraphicDefinition def = GraphicDefinition.forId(i);
if (def == null) {
continue;
}
if ((def.animationId > 2000 && def.animationId < 2200) || (def.defaultModel >= 1300 && def.defaultModel < 1500)) {
System.out.println("Possible match [id=" + i + ", anim=" + def.animationId + "].");
}
}
}
/**
* Reads and handles all data from the input stream.
* @param buffer The input stream.
*/
private void readValueLoop(ByteBuffer buffer) {
for (;;) {
int opcode = buffer.get() & 0xFF;
if (opcode == 0) {
break;
}
readValues(buffer, opcode);
}
}
/**
* Reads the opcode values from the input stream.
* @param buffer The input stream.
* @param opcode The opcode to handle.
*/
public void readValues(ByteBuffer buffer, int opcode) {
if (opcode != 1) {
if (opcode == 2)
animationId = buffer.getShort();
else if (opcode == 4)
anInt1446 = buffer.getShort() & 0xFFFF;
else if (opcode != 5) {
if ((opcode ^ 0xffffffff) != -7) {
if (opcode == 7)
anInt1440 = buffer.get() & 0xFF;
else if ((opcode ^ 0xffffffff) == -9)
anInt1451 = buffer.get() & 0xFF;
else if (opcode != 9) {
if (opcode != 10) {
if (opcode == 11) { // added opcode
// aBoolean1442 = true;
byteValue = (byte) 1;
} else if (opcode == 12) { // added opcode
// aBoolean1442 = true;
byteValue = (byte) 4;
} else if (opcode == 13) { // added opcode
// aBoolean1442 = true;
byteValue = (byte) 5;
} else if (opcode == 14) { // added opcode
// aBoolean1442 = true;
// aByte2856 = 2;
byteValue = (byte) 2;
intValue = (buffer.get() & 0xFF) * 256;
} else if (opcode == 15) {
// aByte2856 = 3;
byteValue = (byte) 3;
intValue = buffer.getShort() & 0xFFFF;
} else if (opcode == 16) {
// aByte2856 = 3;
byteValue = (byte) 3;
intValue = buffer.getInt();
} else if (opcode != 40) {
if ((opcode ^ 0xffffffff) == -42) {
int i = buffer.get() & 0xFF;
aShortArray1455 = new short[i];
aShortArray1435 = new short[i];
for (int i_0_ = 0; i > i_0_; i_0_++) {
aShortArray1455[i_0_] = (short) (buffer.getShort() & 0xFFFF);
aShortArray1435[i_0_] = (short) (buffer.getShort() & 0xFFFF);
}
}
} else {
int i = buffer.get() & 0xFF;
aShortArray1438 = new short[i];
aShortArray1456 = new short[i];
for (int i_1_ = 0; ((i ^ 0xffffffff) < (i_1_ ^ 0xffffffff)); i_1_++) {
aShortArray1438[i_1_] = (short) (buffer.getShort() & 0xFFFF);
aShortArray1456[i_1_] = (short) (buffer.getShort() & 0xFFFF);
}
}
} else
aBoolean1448 = true;
} else {
// aBoolean1442 = true;
byteValue = (byte) 3;
intValue = 8224;
}
} else
anInt1454 = buffer.getShort() & 0xFFFF;
} else
anInt1449 = buffer.getShort() & 0xFFFF;
} else
defaultModel = buffer.getShort();
}
/**
* Constructs a new {@code GraphicDefinition} {@code Object}.
*/
public GraphicDefinition() {
byteValue = 0;
intValue = -1;
anInt1446 = 128;
aBoolean1442 = false;
anInt1449 = 128;
anInt1451 = 0;
animationId = -1;
anInt1454 = 0;
anInt1440 = 0;
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,329 @@
package core.cache.def.impl;
import core.cache.Cache;
import core.game.system.SystemLogger;
import core.game.world.GameWorld;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.nio.ByteBuffer;
/**
* Holds definitions for render animations.
* @author Jagex
* @author Emperor
*
*/
public class RenderAnimationDefinition {
public int turn180Animation;
public int anInt951 = -1;
public int anInt952;
public int turnCWAnimation = -1;
public int anInt954;
public int anInt955;
public int anInt956;
public int anInt957;
public int anInt958;
public int[] anIntArray959 = null;
public int anInt960;
public int anInt961 = 0;
public int anInt962;
public int walkAnimationId;
public int anInt964;
public int anInt965;
public int anInt966;
public int[] standAnimationIds;
public int anInt969;
public int[] anIntArray971;
public int standAnimationId;
public int anInt973;
public int anInt974;
public int anInt975;
public int runAnimationId;
public int anInt977;
public boolean aBoolean978;
public int[][] anIntArrayArray979;
public int anInt980;
public int turnCCWAnimation;
public int anInt983;
public int anInt985;
public int anInt986;
public int anInt987;
public int anInt988;
public int anInt989;
public int anInt990;
public int anInt992;
public int anInt993;
public int anInt994;
/**
* Gets the render animation definitions for the given id.
* @param animId The render animation id.
* @return The render animation definitions.
*/
public static RenderAnimationDefinition forId(int animId) {
RenderAnimationDefinition defs = new RenderAnimationDefinition();
if (animId == -1) {
return null;
}
byte[] data = Cache.getIndexes()[2].getFileData(32, animId);
defs = new RenderAnimationDefinition();
if (data != null) {
defs.parse(ByteBuffer.wrap(data));
} else {
SystemLogger.logErr("No definitions found for render animation " + animId + ", size=" + Cache.getIndexes()[2].getFilesSize(32) + "!");
}
return defs;
}
private void parse(ByteBuffer buffer) {
for (;;) {
int opcode = buffer.get() & 0xFF;
if (opcode == 0) {
break;
}
parseOpcode(buffer, opcode);
}
}
private void parseOpcode(ByteBuffer buffer, int opcode) {
if (opcode == 54) {
@SuppressWarnings("unused")
int anInt1260 = (buffer.get() & 0xFF) << 6;
@SuppressWarnings("unused")
int anInt1227 = (buffer.get() & 0xFF) << 6;
} else if (opcode == 55) {
int[] anIntArray1246 = new int[12];
int i_14_ = buffer.get() & 0xFF;
anIntArray1246[i_14_] = buffer.getShort() & 0xFFFF;
} else if (opcode == 56) {
int[][] anIntArrayArray1217 = new int[12][];
int i_12_ = buffer.get() & 0xFF;
anIntArrayArray1217[i_12_] = new int[3];
for (int i_13_ = 0; i_13_ < 3; i_13_++)
anIntArrayArray1217[i_12_][i_13_] = buffer.getShort();
} else if ((opcode ^ 0xffffffff) != -2) {
if ((opcode ^ 0xffffffff) != -3) {
if (opcode != 3) {
if ((opcode ^ 0xffffffff) != -5) {
if (opcode == 5)
anInt977 = buffer.getShort() & 0xFFFF;
else if ((opcode ^ 0xffffffff) != -7) {
if (opcode == 7)
anInt960 = buffer.getShort() & 0xFFFF;
else if ((opcode ^ 0xffffffff) == -9)
anInt985 = buffer.getShort() & 0xFFFF;
else if (opcode == 9)
anInt957 = buffer.getShort() & 0xFFFF;
else if (opcode == 26) {
anInt973 = (short) (4 * buffer
.get() & 0xFF);
anInt975 = (short) (buffer.get() & 0xFF * 4);
} else if ((opcode ^ 0xffffffff) == -28) {
if (anIntArrayArray979 == null)
anIntArrayArray979 = new int[12][];
int i = buffer.get() & 0xFF;
anIntArrayArray979[i] = new int[6];
for (int i_1_ = 0; (i_1_ ^ 0xffffffff) > -7; i_1_++)
anIntArrayArray979[i][i_1_] = buffer
.getShort();
} else if ((opcode ^ 0xffffffff) == -29) {
anIntArray971 = new int[12];
for (int i = 0; i < 12; i++) {
anIntArray971[i] = buffer
.get() & 0xFF;
if (anIntArray971[i] == 255)
anIntArray971[i] = -1;
}
} else if (opcode != 29) {
if (opcode != 30) {
if ((opcode ^ 0xffffffff) != -32) {
if (opcode != 32) {
if ((opcode ^ 0xffffffff) != -34) {
if (opcode != 34) {
if (opcode != 35) {
if ((opcode ^ 0xffffffff) != -37) {
if ((opcode ^ 0xffffffff) != -38) {
if (opcode != 38) {
if ((opcode ^ 0xffffffff) != -40) {
if ((opcode ^ 0xffffffff) != -41) {
if ((opcode ^ 0xffffffff) == -42)
turnCWAnimation = buffer
.getShort() & 0xFFFF;
else if (opcode != 42) {
if ((opcode ^ 0xffffffff) == -44)
buffer.getShort();
else if ((opcode ^ 0xffffffff) != -45) {
if ((opcode ^ 0xffffffff) == -46)
anInt964 = buffer
.getShort() & 0xFFFF;
else if ((opcode ^ 0xffffffff) != -47) {
if (opcode == 47)
anInt966 = buffer
.getShort() & 0xFFFF;
else if (opcode == 48)
anInt989 = buffer
.getShort() & 0xFFFF;
else if (opcode != 49) {
if ((opcode ^ 0xffffffff) != -51) {
if (opcode != 51) {
if (opcode == 52) {
int i = buffer
.get() & 0xFF;
anIntArray959 = new int[i];
standAnimationIds = new int[i];
for (int i_2_ = 0; i_2_ < i; i_2_++) {
standAnimationIds[i_2_] = buffer
.getShort() & 0xFFFF;
int i_3_ = buffer
.get() & 0xFF;
anIntArray959[i_2_] = i_3_;
anInt994 += i_3_;
}
} else if (opcode == 53)
aBoolean978 = false;
} else
anInt962 = buffer
.getShort() & 0xFFFF;
} else
anInt990 = buffer
.getShort() & 0xFFFF;
} else
anInt952 = buffer
.getShort() & 0xFFFF;
} else
anInt983 = buffer
.getShort() & 0xFFFF;
} else
anInt955 = buffer
.getShort() & 0xFFFF;
} else
turnCCWAnimation = buffer
.getShort() & 0xFFFF;
} else
turn180Animation = buffer
.getShort() & 0xFFFF;
} else
anInt954 = buffer
.getShort() & 0xFFFF;
} else
anInt958 = (buffer
.getShort() & 0xFFFF);
} else
anInt951 = (buffer
.get() & 0xFF);
} else
anInt965 = (buffer
.getShort());
} else
anInt969 = (buffer
.getShort() & 0xFFFF);
} else
anInt993 = buffer
.get() & 0xFF;
} else
anInt956 = (buffer.getShort());
} else
anInt961 = buffer
.getShort() & 0xFFFF;
} else
anInt988 = buffer.get() & 0xFF;
} else
anInt980 = buffer.getShort() & 0xFFFF;
} else
anInt992 = buffer.get() & 0xFF;
} else
runAnimationId = buffer.getShort() & 0xFFFF;
} else
anInt986 = buffer.getShort() & 0xFFFF;
} else
anInt987 = buffer.getShort() & 0xFFFF;
} else
anInt974 = buffer.getShort() & 0xFFFF;
} else {
standAnimationId = buffer.getShort() & 0xFFFF;
walkAnimationId = buffer.getShort() & 0xFFFF;
if ((standAnimationId ^ 0xffffffff) == -65536)
standAnimationId = -1;
if ((walkAnimationId ^ 0xffffffff) == -65536)
walkAnimationId = -1;
}
}
public RenderAnimationDefinition() {
anInt957 = -1;
anInt954 = -1;
anInt960 = -1;
anInt958 = -1;
anInt965 = 0;
anInt973 = 0;
turn180Animation = -1;
anInt956 = 0;
standAnimationId = -1;
standAnimationIds = null;
anInt952 = -1;
anInt983 = -1;
anInt985 = -1;
anInt962 = -1;
anInt966 = -1;
anInt977 = -1;
anInt975 = 0;
runAnimationId = -1;
anInt988 = 0;
turnCCWAnimation = -1;
anInt987 = -1;
anInt980 = 0;
anInt964 = -1;
walkAnimationId = -1;
anInt986 = -1;
aBoolean978 = true;
anInt992 = 0;
anInt955 = -1;
anInt989 = -1;
anInt974 = -1;
anInt969 = 0;
anInt994 = 0;
anInt990 = -1;
anInt993 = 0;
}
public static void main(String...args) throws Throwable {
GameWorld.prompt(false);
RenderAnimationDefinition def = RenderAnimationDefinition.forId(1426);
System.out.println("size: " + def.getClass().getDeclaredFields().length);
for (Field f : def.getClass().getDeclaredFields()) {
if (!Modifier.isStatic(f.getModifiers())) {
if (f.getType().isArray()) {
Object object = f.get(def);
if (object != null) {
int length = Array.getLength(object);
System.out.print(f.getName() + ", [");
for (int i = 0; i < length; i++) {
System.out.print(Array.get(object, i) + (i < (length - 1) ? ", " : "]"));
}
continue;
}
}
System.out.println(f.getName() + ", " + f.get(def));
}
}
for (Field f : def.getClass().getSuperclass().getDeclaredFields()) {
if (!Modifier.isStatic(f.getModifiers())) {
if (f.getType().isArray()) {
Object object = f.get(def);
if (object != null) {
int length = Array.getLength(object);
System.out.print(f.getName() + ", [");
for (int i = 0; i < length; i++) {
System.out.print(Array.get(object, i) + (i < (length - 1) ? ", " : "]"));
}
continue;
}
}
System.out.println(f.getName() + ", " + f.get(def));
}
}
}
}
@@ -0,0 +1,176 @@
package core.cache.def.impl;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import core.cache.Cache;
import core.game.Varbit;
import core.game.node.entity.player.Player;
import core.game.system.SystemLogger;
import core.game.world.GameWorld;
/**
* Handles config definition reading.
* @author Emperor
*/
public final class VarbitDefinition {
/**
* The config definitions mapping.
*/
private static final Map<Integer, VarbitDefinition> MAPPING = new HashMap<>();
/**
* The bit size flags.
*/
private static final int[] BITS = new int[32];
/**
* The file id.
*/
private final int id;
/**
* The config id.
*/
private int configId;
/**
* The bit shift amount.
*/
private int bitShift;
/**
* The bit amount.
*/
private int bitSize;
/**
* Constructs a new {@code ConfigFileDefinition} {@code Object}.
* @param id The file id.
*/
public VarbitDefinition(int id) {
this.id = id;
}
/**
* Initializes the bit flags.
*/
static {
int flag = 2;
for (int i = 0; i < 32; i++) {
BITS[i] = flag - 1;
flag += flag;
}
}
/**
* Gets the config file definitions for the given file id.
* @param id The file id.
* @return The definition.
*/
public static VarbitDefinition forObjectID(int id) {
return forId(id,10);
}
public static VarbitDefinition forNPCID(int id){
return forId(id,10);
}
public static VarbitDefinition forItemID(int id){
return forId(id,30);
}
public static VarbitDefinition forId(int id, int shiftAmount){
/*VarbitDefinition def = MAPPING.get(id);
if (def != null) {
return def;
}*/
VarbitDefinition def;
def = new VarbitDefinition(id);
byte[] bs = Cache.getIndexes()[22].getFileData(id >>> 10, id & 0x3ff);
if (bs != null) {
ByteBuffer buffer = ByteBuffer.wrap(bs);
int opcode = 0;
while ((opcode = buffer.get() & 0xFF) != 0) {
if (opcode == 1) {
def.configId = buffer.getShort() & 0xFFFF;
def.bitShift = buffer.get() & 0xFF;
def.bitSize = buffer.get() & 0xFF;
}
}
}
MAPPING.put(id, def);
return def;
}
public static void main(String... args) throws Throwable {
GameWorld.prompt(false);
for (int i = 0; i < 15000; i++) {
VarbitDefinition def = forObjectID(i);
if (def != null && def.configId == 33) {
System.out.println("Config file [id=" + i + ", shift=" + def.bitShift + "]!");
}
}
}
/**
* Gets the current config value for this file.
* @param player The player.
* @return The config value.
*/
public int getValue(Player player) {
int size = BITS[bitSize - bitShift];
int bitValue = player.varpManager.get(getConfigId()).getBitRangeValue(getBitShift(), getBitShift() + (bitSize - bitShift));
if(bitValue != 0){
return bitValue >>> bitShift;
}
return size & (player.getConfigManager().get(configId) >>> bitShift);
}
/**
* Gets the mapping.
* @return The mapping.
*/
public static Map<Integer, VarbitDefinition> getMapping() {
return MAPPING;
}
/**
* Gets the id.
* @return The id.
*/
public int getId() {
return id;
}
/**
* Gets the configId.
* @return The configId.
*/
public int getConfigId() {
return configId;
}
/**
* Gets the bitShift.
* @return The bitShift.
*/
public int getBitShift() {
return bitShift;
}
/**
* Gets the bitSize.
* @return The bitSize.
*/
public int getBitSize() {
return bitSize;
}
@Override
public String toString() {
return "ConfigFileDefinition [id=" + id + ", configId=" + configId + ", bitShift=" + bitShift + ", bitSize=" + bitSize + "]";
}
}
+365
View File
@@ -0,0 +1,365 @@
private void readValues(int i, InputStream stream, int opcode) {
if (opcode != 1 && opcode != 5) {
if (opcode != 2) {
if (opcode != 14) {
if (opcode != 15) {
if (opcode == 17) {
projectileCliped = false;
clipType = 0;
} else if (opcode != 18) {
if (opcode == 19)
secondInt = stream.readUnsignedByte();
else if (opcode == 21)
aByte3912 = (byte) 1;
else if (opcode != 22) {
if (opcode != 23) {
if (opcode != 24) {
if (opcode == 27)
clipType = 1;
else if (opcode == 28)
anInt3892 = (stream
.readUnsignedByte() << 2);
else if (opcode != 29) {
if (opcode != 39) {
if (opcode < 30 || opcode >= 35) {
if (opcode == 40) {
int i_53_ = (stream
.readUnsignedByte());
originalColors = new short[i_53_];
modifiedColors = new short[i_53_];
for (int i_54_ = 0; i_53_ > i_54_; i_54_++) {
originalColors[i_54_] = (short) (stream
.readUnsignedShort());
modifiedColors[i_54_] = (short) (stream
.readUnsignedShort());
}
} else if (opcode != 41) {
if (opcode != 42) {
if (opcode != 62) {
if (opcode != 64) {
if (opcode == 65)
anInt3902 = stream
.readUnsignedShort();
else if (opcode != 66) {
if (opcode != 67) {
if (opcode == 69)
anInt3925 = stream
.readUnsignedByte();
else if (opcode != 70) {
if (opcode == 71)
anInt3889 = stream
.readShort() << 2;
else if (opcode != 72) {
if (opcode == 73)
secondBool = true;
else if (opcode == 74)
notCliped = true;
else if (opcode != 75) {
if (opcode != 77
&& opcode != 92) {
if (opcode == 78) {
anInt3860 = stream
.readUnsignedShort();
anInt3904 = stream
.readUnsignedByte();
} else if (opcode != 79) {
if (opcode == 81) {
aByte3912 = (byte) 2;
anInt3882 = 256 * stream
.readUnsignedByte();
} else if (opcode != 82) {
if (opcode == 88)
aBoolean3853 = false;
else if (opcode != 89) {
if (opcode == 90)
aBoolean3870 = true;
else if (opcode != 91) {
if (opcode != 93) {
if (opcode == 94)
aByte3912 = (byte) 4;
else if (opcode != 95) {
if (opcode != 96) {
if (opcode == 97)
aBoolean3866 = true;
else if (opcode == 98)
aBoolean3923 = true;
else if (opcode == 99) {
anInt3857 = stream
.readUnsignedByte();
anInt3835 = stream
.readUnsignedShort();
} else if (opcode == 100) {
anInt3844 = stream
.readUnsignedByte();
anInt3913 = stream
.readUnsignedShort();
} else if (opcode != 101) {
if (opcode == 102)
anInt3838 = stream
.readUnsignedShort();
else if (opcode == 103)
thirdInt = 0;
else if (opcode != 104) {
if (opcode == 105)
aBoolean3906 = true;
else if (opcode == 106) {
int i_55_ = stream
.readUnsignedByte();
anIntArray3869 = new int[i_55_];
anIntArray3833 = new int[i_55_];
for (int i_56_ = 0; i_56_ < i_55_; i_56_++) {
anIntArray3833[i_56_] = stream
.readUnsignedShort();
int i_57_ = stream
.readUnsignedByte();
anIntArray3869[i_56_] = i_57_;
anInt3881 += i_57_;
}
} else if (opcode == 107)
anInt3851 = stream
.readUnsignedShort();
else if (opcode >= 150
&& opcode < 155) {
options[opcode
+ -150] = stream
.readString();
/*if (!loader.showOptions)
options[opcode + -150] = null;*/
} else if (opcode != 160) {
if (opcode == 162) {
aByte3912 = (byte) 3;
anInt3882 = stream
.readInt();
} else if (opcode == 163) {
aByte3847 = (byte) stream
.readByte();
aByte3849 = (byte) stream
.readByte();
aByte3837 = (byte) stream
.readByte();
aByte3914 = (byte) stream
.readByte();
} else if (opcode != 164) {
if (opcode != 165) {
if (opcode != 166) {
if (opcode == 167)
anInt3921 = stream
.readUnsignedShort();
else if (opcode != 168) {
if (opcode == 169) {
aBoolean3845 = true;
//added opcode
}else if (opcode == 170) {
int anInt3383 = stream.readUnsignedSmart();
//added opcode
}else if (opcode == 171) {
int anInt3362 = stream.readUnsignedSmart();
//added opcode
}else if (opcode == 173) {
int anInt3302 = stream.readUnsignedShort();
int anInt3336 = stream.readUnsignedShort();
//added opcode
}else if (opcode == 177) {
boolean ub = true;
//added opcode
}else if (opcode == 178) {
int db = stream.readUnsignedByte();
} else if (opcode == 249) {
int i_58_ = stream
.readUnsignedByte();
if (aClass194_3922 == null) {
/*int i_59_ = Class307
.method3331(
(byte) -117,
i_58_);
aClass194_3922 = new HashTable(
i_59_);*/
}
for (int i_60_ = 0; i_60_ < i_58_; i_60_++) {
boolean bool = stream
.readUnsignedByte() == 1;
int i_61_ = stream.read24BitInt();
Object class279;
if (!bool)
/*class279 = new IntegerNode(*/
stream
.readInt();//);
else
/*class279 = new Class279_Sub4(*/
stream
.readString();//);
/*aClass194_3922
.method1598(
(long) i_61_,
-125,
class279);*/
}
}
} else
aBoolean3894 = true;
} else
anInt3877 = stream
.readShort();
} else
anInt3875 = stream
.readShort();
} else
anInt3834 = stream
.readShort();
} else {
int i_62_ = stream
.readUnsignedByte();
anIntArray3908 = new int[i_62_];
for (int i_63_ = 0; i_62_ > i_63_; i_63_++)
anIntArray3908[i_63_] = stream
.readUnsignedShort();
}
} else
anInt3865 = stream
.readUnsignedByte();
} else
anInt3850 = stream
.readUnsignedByte();
} else
aBoolean3924 = true;
} else {
aByte3912 = (byte) 5;
anInt3882 = stream
.readShort();
}
} else {
aByte3912 = (byte) 3;
anInt3882 = stream
.readUnsignedShort();
}
} else
aBoolean3873 = true;
} else
aBoolean3895 = false;
} else
aBoolean3891 = true;
} else {
anInt3900 = stream
.readUnsignedShort();
anInt3905 = stream
.readUnsignedShort();
anInt3904 = stream
.readUnsignedByte();
int i_64_ = stream
.readUnsignedByte();
anIntArray3859 = new int[i_64_];
for (int i_65_ = 0; i_65_ < i_64_; i_65_++)
anIntArray3859[i_65_] = stream
.readUnsignedShort();
}
} else {
configFileId = stream
.readUnsignedShort();
if (configFileId == 65535)
configFileId = -1;
configId = stream
.readUnsignedShort();
if (configId == 65535)
configId = -1;
int i_66_ = -1;
if (opcode == 92) {
i_66_ = stream
.readUnsignedShort();
if (i_66_ == 65535)
i_66_ = -1;
}
int i_67_ = stream
.readUnsignedByte();
childrenIds = new int[i_67_
- -2];
for (int i_68_ = 0; i_67_ >= i_68_; i_68_++) {
childrenIds[i_68_] = stream
.readUnsignedShort();
if (childrenIds[i_68_] == 65535)
childrenIds[i_68_] = -1;
}
childrenIds[i_67_ + 1] = i_66_;
}
} else
anInt3855 = stream
.readUnsignedByte();
} else
anInt3915 = stream
.readShort() << 2;
} else
anInt3883 = stream
.readShort() << 2;
} else
anInt3917 = stream
.readUnsignedShort();
} else
anInt3841 = stream
.readUnsignedShort();
} else
aBoolean3872 = false;
} else
aBoolean3839 = true;
} else {
int i_69_ = (stream
.readUnsignedByte());
aByteArray3858 = (new byte[i_69_]);
for (int i_70_ = 0; i_70_ < i_69_; i_70_++)
aByteArray3858[i_70_] = (byte) (stream
.readByte());
}
} else {
int i_71_ = (stream
.readUnsignedByte());
aShortArray3920 = new short[i_71_];
aShortArray3919 = new short[i_71_];
for (int i_72_ = 0; i_71_ > i_72_; i_72_++) {
aShortArray3920[i_72_] = (short) (stream
.readUnsignedShort());
aShortArray3919[i_72_] = (short) (stream
.readUnsignedShort());
}
}
} else
options[-30
+ opcode] = (stream
.readString());
} else
anInt3840 = (stream.readByte() * 5);
} else
anInt3878 = stream.readByte();
} else {
anInt3876 = stream.readUnsignedShort();
if (anInt3876 == 65535)
anInt3876 = -1;
}
} else
thirdInt = 1;
} else
aBoolean3867 = true;
} else
projectileCliped = false;
} else
sizeY = stream.readUnsignedByte();
} else
sizeX = stream.readUnsignedByte();
} else
name = stream.readString();
} else {
boolean aBoolean1162 = false;
if (opcode == 5 && aBoolean1162)
method3297(stream);
int i_73_ = stream.readUnsignedByte();
anIntArrayArray3916 = new int[i_73_][];
aByteArray3899 = new byte[i_73_];
for (int i_74_ = 0; i_74_ < i_73_; i_74_++) {
aByteArray3899[i_74_] = (byte) stream.readByte();
int i_75_ = stream.readUnsignedByte();
anIntArrayArray3916[i_74_] = new int[i_75_];
for (int i_76_ = 0; i_75_ > i_76_; i_76_++)
anIntArrayArray3916[i_74_][i_76_] = stream
.readUnsignedShort();
}
if (opcode == 5 && !aBoolean1162)
method3297(stream);
}
}
@@ -0,0 +1,47 @@
package core.cache.gzip;
import java.nio.ByteBuffer;
import java.util.zip.Inflater;
public class GZipDecompressor {
private static final Inflater inflaterInstance = new Inflater(true);
public static final void decompress(ByteBuffer buffer, byte data[]) {
synchronized (inflaterInstance) {
if (~buffer.get(buffer.position()) != -32 || buffer.get(buffer.position() + 1) != -117) {
data = null;
// throw new RuntimeException("Invalid GZIP header!");
}
try {
inflaterInstance.setInput(buffer.array(), buffer.position() + 10, -buffer.position() - 18 + buffer.limit());
inflaterInstance.inflate(data);
} catch (Exception e) {
// inflaterInstance.reset();
data = null;
// throw new RuntimeException("Invalid GZIP compressed data!");
}
inflaterInstance.reset();
}
}
public static final boolean decompress(byte[] compressed, byte data[], int offset, int length) {
synchronized (inflaterInstance) {
if (data[offset] != 31 || data[offset + 1] != -117)
return false;
// throw new RuntimeException("Invalid GZIP header!");
try {
inflaterInstance.setInput(data, offset + 10, -offset - 18 + length);
inflaterInstance.inflate(compressed);
} catch (Exception e) {
inflaterInstance.reset();
e.printStackTrace();
return false;
// throw new RuntimeException("Invalid GZIP compressed data!");
}
inflaterInstance.reset();
return true;
}
}
}
+109
View File
@@ -0,0 +1,109 @@
package core.cache.misc;
/**
* A container.
* @author Dragonkk
*/
public class Container {
/**
* The version.
*/
private int version;
/**
* The CRC.
*/
private int crc;
/**
* The name hash.
*/
private int nameHash;
/**
* If updated.
*/
private boolean updated;
/**
* Construct a new container.
*/
public Container() {
nameHash = -1;
version = -1;
crc = -1;
}
/**
* Set the version.
* @param version
*/
public void setVersion(int version) {
this.version = version;
}
/**
* Update the version.
*/
public void updateVersion() {
version++;
updated = true;
}
/**
* Get the version.
* @return The version.
*/
public int getVersion() {
return version;
}
/**
* Get the next version.
* @return The next version.
*/
public int getNextVersion() {
return updated ? version : version + 1;
}
/**
* Set the CRC.
* @param crc The cRC.
*/
public void setCrc(int crc) {
this.crc = crc;
}
/**
* Get the CRC.
* @return The CRC.
*/
public int getCrc() {
return crc;
}
/**
* Set the name hash.
* @param nameHash The name hash.
*/
public void setNameHash(int nameHash) {
this.nameHash = nameHash;
}
/**
* Get the name hash.
* @return The name hash.
*/
public int getNameHash() {
return nameHash;
}
/**
* If is updated.
* @return If is updated.
*/
public boolean isUpdated() {
return updated;
}
}
@@ -0,0 +1,228 @@
package core.cache.misc;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.zip.CRC32;
import core.cache.bzip2.BZip2Decompressor;
import core.cache.gzip.GZipDecompressor;
/**
* A class holding the containers information.
* @author Dragonkk
*/
public final class ContainersInformation {
/**
* The information container.
*/
private Container informationContainer;
/**
* The protocol.
*/
private int protocol;
/**
* The revision.
*/
private int revision;
/**
* The container indexes.
*/
private int[] containersIndexes;
/**
* The containers.
*/
private FilesContainer[] containers;
/**
* If files have to be named.
*/
private boolean filesNamed;
/**
* If it has to be whirpool.
*/
private boolean whirpool;
/**
* The data.
*/
private final byte[] data;
/**
* Construct a new containers information.
* @param informationContainerPackedData The information container data
* packed.
*/
public ContainersInformation(byte[] informationContainerPackedData) {
this.data = Arrays.copyOf(informationContainerPackedData, informationContainerPackedData.length);
informationContainer = new Container();
informationContainer.setVersion((informationContainerPackedData[informationContainerPackedData.length - 2] << 8 & 0xff00) + (informationContainerPackedData[-1 + informationContainerPackedData.length] & 0xff));
CRC32 crc32 = new CRC32();
crc32.update(informationContainerPackedData);
informationContainer.setCrc((int) crc32.getValue());
decodeContainersInformation(unpackCacheContainer(informationContainerPackedData));
}
/**
* Unpacks a container.
* @param packedData The packed container data.
* @return The unpacked data.
*/
public static final byte[] unpackCacheContainer(byte[] packedData) {
ByteBuffer buffer = ByteBuffer.wrap(packedData);
int compression = buffer.get() & 0xFF;
int containerSize = buffer.getInt();
if (containerSize < 0 || containerSize > 5000000) {
return null;
// throw new RuntimeException();
}
if (compression == 0) {
byte unpacked[] = new byte[containerSize];
buffer.get(unpacked, 0, containerSize);
return unpacked;
}
int decompressedSize = buffer.getInt();
if (decompressedSize < 0 || decompressedSize > 20000000) {
return null;
// throw new RuntimeException();
}
byte decompressedData[] = new byte[decompressedSize];
if (compression == 1) {
BZip2Decompressor.decompress(decompressedData, packedData, containerSize, 9);
} else {
GZipDecompressor.decompress(buffer, decompressedData);
}
return decompressedData;
}
/**
* Get the container indexes.
* @return The container indexes.
*/
public int[] getContainersIndexes() {
return containersIndexes;
}
/**
* Get the containers.
* @return The containers.
*/
public FilesContainer[] getContainers() {
return containers;
}
/**
* Get the information container.
* @return The information container.
*/
public Container getInformationContainer() {
return informationContainer;
}
/**
* Get the revision.
* @return The revision.
*/
public int getRevision() {
return revision;
}
/**
* Decode the containers information.
* @param data The data.
*/
public void decodeContainersInformation(byte[] data) {
ByteBuffer buffer = ByteBuffer.wrap(data);
protocol = buffer.get() & 0xFF;
if (protocol != 5 && protocol != 6) {
throw new RuntimeException();
}
revision = protocol < 6 ? 0 : buffer.getInt();
int nameHash = buffer.get() & 0xFF;
filesNamed = (0x1 & nameHash) != 0;
whirpool = (0x2 & nameHash) != 0;
containersIndexes = new int[buffer.getShort() & 0xFFFF];
int lastIndex = -1;
for (int index = 0; index < containersIndexes.length; index++) {
containersIndexes[index] = (buffer.getShort() & 0xFFFF) + (index == 0 ? 0 : containersIndexes[index - 1]);
if (containersIndexes[index] > lastIndex) {
lastIndex = containersIndexes[index];
}
}
containers = new FilesContainer[lastIndex + 1];
for (int index = 0; index < containersIndexes.length; index++) {
containers[containersIndexes[index]] = new FilesContainer();
}
if (filesNamed) {
for (int index = 0; index < containersIndexes.length; index++) {
containers[containersIndexes[index]].setNameHash(buffer.getInt());
}
}
byte[][] filesHashes = null;
if (whirpool) {
filesHashes = new byte[containers.length][];
for (int index = 0; index < containersIndexes.length; index++) {
filesHashes[containersIndexes[index]] = new byte[64];
buffer.get(filesHashes[containersIndexes[index]], 0, 64);
}
}
for (int index = 0; index < containersIndexes.length; index++) {
containers[containersIndexes[index]].setCrc(buffer.getInt());
}
for (int index = 0; index < containersIndexes.length; index++) {
containers[containersIndexes[index]].setVersion(buffer.getInt());
}
for (int index = 0; index < containersIndexes.length; index++) {
containers[containersIndexes[index]].setFilesIndexes(new int[buffer.getShort() & 0xFFFF]);
}
for (int index = 0; index < containersIndexes.length; index++) {
int lastFileIndex = -1;
for (int fileIndex = 0; fileIndex < containers[containersIndexes[index]].getFilesIndexes().length; fileIndex++) {
containers[containersIndexes[index]].getFilesIndexes()[fileIndex] = (buffer.getShort() & 0xFFFF) + (fileIndex == 0 ? 0 : containers[containersIndexes[index]].getFilesIndexes()[fileIndex - 1]);
if (containers[containersIndexes[index]].getFilesIndexes()[fileIndex] > lastFileIndex) {
lastFileIndex = containers[containersIndexes[index]].getFilesIndexes()[fileIndex];
}
}
containers[containersIndexes[index]].setFiles(new Container[lastFileIndex + 1]);
for (int fileIndex = 0; fileIndex < containers[containersIndexes[index]].getFilesIndexes().length; fileIndex++) {
containers[containersIndexes[index]].getFiles()[containers[containersIndexes[index]].getFilesIndexes()[fileIndex]] = new Container();
}
}
if (whirpool) {
for (int index = 0; index < containersIndexes.length; index++) {
for (int fileIndex = 0; fileIndex < containers[containersIndexes[index]].getFilesIndexes().length; fileIndex++) {
containers[containersIndexes[index]].getFiles()[containers[containersIndexes[index]].getFilesIndexes()[fileIndex]].setVersion(filesHashes[containersIndexes[index]][containers[containersIndexes[index]].getFilesIndexes()[fileIndex]]);
}
}
}
if (filesNamed) {
for (int index = 0; index < containersIndexes.length; index++) {
for (int fileIndex = 0; fileIndex < containers[containersIndexes[index]].getFilesIndexes().length; fileIndex++) {
containers[containersIndexes[index]].getFiles()[containers[containersIndexes[index]].getFilesIndexes()[fileIndex]].setNameHash(buffer.getInt());
}
}
}
}
/**
* If is whirpool.
* @return If is whirpool {@code true}.
*/
public boolean isWhirpool() {
return whirpool;
}
/**
* Gets the data.
* @return The data.
*/
public byte[] getData() {
return data;
}
}
@@ -0,0 +1,57 @@
package core.cache.misc;
/**
* A class holding the file containers.
* @author Dragonkk
*/
public final class FilesContainer extends Container {
/**
* The file indexes.
*/
private int[] filesIndexes;
/**
* The files.
*/
private Container[] files;
/**
* Construct a new files container.
*/
public FilesContainer() {
}
/**
* Set the files.
* @param containers The files.
*/
public void setFiles(Container[] containers) {
this.files = containers;
}
/**
* Get the files.
* @return The files.
*/
public Container[] getFiles() {
return files;
}
/**
* Set the file indexes.
* @param containersIndexes The file indexes.
*/
public void setFilesIndexes(int[] containersIndexes) {
this.filesIndexes = containersIndexes;
}
/**
* Get the file indexes.
* @return The file indexes.
*/
public int[] getFilesIndexes() {
return filesIndexes;
}
}
@@ -0,0 +1,39 @@
package core.cache.misc.buffer;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
/**
* Handles the reading of data from a byte buffer.
* @author Emperor
*/
public final class BufferInputStream extends InputStream {
/**
* The buffer to write on.
*/
private final ByteBuffer buffer;
/**
* The buffer input stream.
* @param buffer The buffer.
*/
public BufferInputStream(ByteBuffer buffer) throws IOException {
this.buffer = buffer;
}
@Override
public int read() throws IOException {
return buffer.get();
}
/**
* Gets the buffer.
* @return The buffer.
*/
public ByteBuffer getBuffer() {
return buffer;
}
}
@@ -0,0 +1,57 @@
package core.cache.misc.buffer;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
/**
* Handles the writing of data on a byte buffer.
* @author Emperor
*/
public final class BufferOutputStream extends OutputStream {
/**
* The buffer to write on.
*/
private final ByteBuffer buffer;
/**
* Constructs a new {@code BufferOutputStream} {@code Object}.
* @param buffer The buffer to write on.
* @throws IOException When an I/O exception occurs.
* @throws SecurityException If a security manager exists and its
* checkPermission method denies enabling subclassing.
*/
public BufferOutputStream(ByteBuffer buffer) throws IOException, SecurityException {
super();
this.buffer = buffer;
}
@Override
public void write(int b) throws IOException {
buffer.put((byte) b);
}
@Override
public void flush() {
/*
* empty.
*/
}
@Override
public void close() {
/*
* empty.
*/
}
/**
* Gets the buffer.
* @return The buffer.
*/
public ByteBuffer getBuffer() {
return buffer;
}
}
@@ -0,0 +1,181 @@
package core.cache.misc.buffer;
import java.io.ObjectInputStream;
import java.nio.ByteBuffer;
/**
* Holds utility methods for reading/writing a byte buffer.
* @author Emperor
*/
public final class ByteBufferUtils {
/**
* Gets a string from the byte buffer.
* @param buffer The byte buffer.
* @return The string.
*/
public static String getString(ByteBuffer buffer) {
StringBuilder sb = new StringBuilder();
byte b;
while ((b = buffer.get()) != 0) {
sb.append((char) b);
}
return sb.toString();
}
/**
* Puts a string on the byte buffer.
* @param s The string to put.
* @param buffer The byte buffer.
*/
public static void putString(String s, ByteBuffer buffer) {
buffer.put(s.getBytes()).put((byte) 0);
}
/**
* Gets a string from the byte buffer.
* @param s The string.
* @param buffer The byte buffer.
* @return The string.
*/
public static ByteBuffer putGJ2String(String s, ByteBuffer buffer) {
byte[] packed = new byte[256];
int length = packGJString2(0, packed, s);
return buffer.put((byte) 0).put(packed, 0, length).put((byte) 0);
}
/**
* Decodes the XTEA encryption.
* @param keys The keys.
* @param start The start index.
* @param end The end index.
* @param buffer The byte buffer.
*/
public static void decodeXTEA(int[] keys, int start, int end, ByteBuffer buffer) {
int l = buffer.position();
buffer.position(start);
int length = (end - start) / 8;
for (int i = 0; i < length; i++) {
int firstInt = buffer.getInt();
int secondInt = buffer.getInt();
int sum = 0xc6ef3720;
int delta = 0x9e3779b9;
for (int j = 32; j-- > 0;) {
secondInt -= keys[(sum & 0x1c84) >>> 11] + sum ^ (firstInt >>> 5 ^ firstInt << 4) + firstInt;
sum -= delta;
firstInt -= (secondInt >>> 5 ^ secondInt << 4) + secondInt ^ keys[sum & 3] + sum;
}
buffer.position(buffer.position() - 8);
buffer.putInt(firstInt);
buffer.putInt(secondInt);
}
buffer.position(l);
}
/**
* Converts a String to an Integer?
* @param position The position.
* @param buffer The buffer used.
* @param string The String to convert.
* @return The Integer.
*/
public static int packGJString2(int position, byte[] buffer, String string) {
int length = string.length();
int offset = position;
for (int i = 0; length > i; i++) {
int character = string.charAt(i);
if (character > 127) {
if (character > 2047) {
buffer[offset++] = (byte) ((character | 919275) >> 12);
buffer[offset++] = (byte) (128 | ((character >> 6) & 63));
buffer[offset++] = (byte) (128 | (character & 63));
} else {
buffer[offset++] = (byte) ((character | 12309) >> 6);
buffer[offset++] = (byte) (128 | (character & 63));
}
} else
buffer[offset++] = (byte) character;
}
return offset - position;
}
/**
* Gets a tri-byte from the buffer.
* @param buffer The buffer.
* @return The value.
*/
public static int getTriByte(ByteBuffer buffer) {
return ((buffer.get() & 0xFF) << 16) + ((buffer.get() & 0xFF) << 8) + (buffer.get() & 0xFF);
}
/**
* Gets a smart from the buffer.
* @param buffer The buffer.
* @return The value.
*/
public static int getSmart(ByteBuffer buffer) {
int peek = buffer.get() & 0xFF;
if (peek <= Byte.MAX_VALUE) {
return peek;
}
return ((peek << 8) | (buffer.get() & 0xFF)) - 32768;
}
/**
* Gets a smart from the buffer.
* @param buffer The buffer.
* @return The value.
*/
public static int getBigSmart(ByteBuffer buffer) {
int value = 0;
int current = getSmart(buffer);
while (current == 32767) {
current = getSmart(buffer);
value += 32767;
}
value += current;
return value;
}
/* *//**
* Writes an object on the buffer.
* @param buffer The buffer to write on.
* @param o The object.
*/
/*
* public static void putObject(ByteBuffer buffer, Object o) { ByteBuffer b;
* try (ObjectOutputStream out = new ObjectOutputStream(new
* BufferOutputStream(b = ByteBuffer.allocate(99999)))) {
* out.writeObject(o); b.flip(); } catch (Throwable e) {
* e.printStackTrace(); b = (ByteBuffer) ByteBuffer.allocate(0).flip(); }
* buffer.putInt(b.remaining()); if (b.remaining() > 0) { buffer.put(b); } }
*/
/**
* Gets an object from the byte buffer.
* @param buffer The buffer.
* @return The object.
*/
public static Object getObject(ByteBuffer buffer) {
int length = buffer.getInt();
if (length > 0) {
byte[] bytes = new byte[length];
buffer.get(bytes);
try (ObjectInputStream str = new ObjectInputStream(new BufferInputStream(ByteBuffer.wrap(bytes)))) {
return (Object) str.readObject();
} catch (Throwable e) {
e.printStackTrace();
}
}
return null;
}
/**
* Constructs a new {@code ByteBufferUtils} {@code Object}.
*/
private ByteBufferUtils() {
/*
* empty.
*/
}
}
@@ -0,0 +1,104 @@
package core.game.component;
/**
* Used to generate component option settings.
* @author Mangis
*/
public final class AccessMaskBuilder {
/**
* Contains the value which should be sent in access mask packet.
*/
private int value;
/**
* Sets default option setting.
* @param allowed If the packet for the default option should be sent to the
* server.
*/
public void allowDefaultOption(boolean allowed) {
value &= ~(0x1);
if (allowed) {
value |= 0x1;
}
}
/**
* Sets right click option settings. If specified option is not allowed, it
* will not appear in right click menu and the packet will not be send to
* server when clicked.
* @param optionId The option index.
* @param show If the option is allowed.
*/
public void showMenuOption(int optionId, boolean show) {
if (optionId < 0 || optionId > 9) {
throw new IllegalArgumentException("Option index must be 0-9.");
}
value &= ~(0x1 << (optionId + 1));
if (show) {
value |= (0x1 << (optionId + 1));
}
}
/**
* Sets use on option settings. If nothing is allowed then 'use' option will
* not appear in right click menu.
*/
public void setUseOnSettings(boolean groundItems, boolean npcs, boolean objects, boolean otherPlayer, boolean selfPlayer, boolean component) {
int useFlag = 0;
if (groundItems) {
useFlag |= 0x1;
}
if (npcs) {
useFlag |= 0x2;
}
if (objects) {
useFlag |= 0x4;
}
if (otherPlayer) {
useFlag |= 0x8;
}
if (selfPlayer) {
useFlag |= 0x10;
}
if (component) {
useFlag |= 0x20;
}
value &= ~(127 << 7); // disable
value |= useFlag << 7;
}
/**
* Sets interface events depth. For example, we have inventory interface
* which is opened on gameframe interface (548) If depth is 1, then the
* clicks in inventory will also invoke click event handler scripts on
* gameframe interface.
* @param depth The depth value.
*/
public void setInterfaceEventsDepth(int depth) {
if (depth < 0 || depth > 7) {
throw new IllegalArgumentException("depth must be 0-7.");
}
value &= ~(0x7 << 18);
value |= (depth << 18);
}
/**
* Flags other component options being allowed to be used on this component.
* @param allow If an option can be used on this component.
*/
public void allowUsage(boolean allow) {
value &= ~(1 << 22);
if (allow) {
value |= (1 << 22);
}
}
/**
* Gets the current value.
* @return The value.
*/
public int getValue() {
return value;
}
}
@@ -0,0 +1,20 @@
package core.game.component;
import core.game.node.entity.player.Player;
/**
* An event called when the interface gets closed.
* @author Emperor
*/
public interface CloseEvent {
/**
* Called when the interface gets closed.
* @param player The player.
* @param c The component.
* @return {@code True} if successful, {@code false} if the component should
* remain open.
*/
boolean close(Player player, Component c);
}
@@ -0,0 +1,178 @@
package core.game.component;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.InterfaceManager;
import core.net.packet.PacketRepository;
import core.net.packet.context.InterfaceContext;
import core.net.packet.out.Interface;
/**
* Represents a component.
* @author Emperor
*
*/
public class Component {
/**
* The component id.
*/
protected int id;
/**
* The component definitions.
*/
protected final ComponentDefinition definition;
/**
* The close event.
*/
protected CloseEvent closeEvent;
/**
* The component plugin.
*/
protected ComponentPlugin plugin;
/**
* If the component is hidden.
*/
private boolean hidden;
/**
* Constructs a new {@code Component} {@code Object}.
* @param id The component id.
*/
public Component(int id) {
this.id = id;
this.definition = ComponentDefinition.forId(id);
this.plugin = definition.getPlugin();
}
/**
* Opens the component.
*/
public void open(Player player) {
InterfaceManager manager = player.getInterfaceManager();
if (definition == null) {
PacketRepository.send(Interface.class, new InterfaceContext(player, manager.getWindowPaneId(), manager.getDefaultChildId(), getId(), false));
if (plugin != null) {
plugin.open(player, this);
}
return;
}
if (definition.getType() == InterfaceType.WINDOW_PANE) {
return;
}
if (definition.getType() == InterfaceType.TAB) {
PacketRepository.send(Interface.class, new InterfaceContext(player, definition.getWindowPaneId(manager.isResizable()), definition.getChildId(manager.isResizable()) + definition.getTabIndex(), getId(), definition.isWalkable()));
if (plugin != null) {
plugin.open(player, this);
}
return;
}
PacketRepository.send(Interface.class, new InterfaceContext(player, definition.getWindowPaneId(manager.isResizable()), definition.getChildId(manager.isResizable()), getId(), definition.isWalkable()));
if (plugin != null) {
plugin.open(player, this);
}
}
/**
* Closes the component.
* @param player The player.
* @return {@code True} if the component can be closed.
*/
public boolean close(Player player) {
if (closeEvent != null && !closeEvent.close(player, this)) {
return false;
}
return true;
}
/**
* Gets the id.
* @return The id.
*/
public int getId() {
return id;
}
/**
* Gets the definition.
* @return The definition.
*/
public ComponentDefinition getDefinition() {
return definition;
}
/**
* Gets the closeEvent.
* @return The closeEvent.
*/
public CloseEvent getCloseEvent() {
return closeEvent;
}
/**
* Sets the closeEvent.
* @param closeEvent The closeEvent to set.
*/
public Component setCloseEvent(CloseEvent closeEvent) {
this.closeEvent = closeEvent;
return this;
}
/**
* Sets the component unclosable.
* @param c The component.
*/
public static void setUnclosable(Player p, Component c) {
p.setAttribute("close_c_", false);
c.setCloseEvent(new CloseEvent() {
@Override
public boolean close(Player player, Component c) {
if (!player.getAttribute("close_c_", false)) {
return false;
}
return true;
}
});
}
/**
* Sets the plugin.
* @param plugin the plugin.
*/
public void setPlugin(ComponentPlugin plugin) {
this.plugin = plugin;
}
/**
* Gets the component plugin.
* @return the plugin.
*/
public ComponentPlugin getPlugin() {
if (plugin == null) {
ComponentPlugin p = ComponentDefinition.forId(getId()).getPlugin();
if ((plugin = p) != null) {
return p;
}
}
return plugin;
}
/**
* Gets the hidden value.
* @return The hidden.
*/
public boolean isHidden() {
return hidden;
}
/**
* Sets the hidden value.
* @param hidden The hidden to set.
*/
public void setHidden(boolean hidden) {
this.hidden = hidden;
}
}
@@ -0,0 +1,178 @@
package core.game.component;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
/**
* Represents the component definitions.
* @author Emperor
*
*/
public final class ComponentDefinition {
/**
* The component definitions mapping.
*/
private static final Map<Integer, ComponentDefinition> DEFINITIONS = new HashMap<Integer, ComponentDefinition>();
/**
* The interface type.
*/
private InterfaceType type = InterfaceType.DEFAULT;
/**
* The interface context.
*/
private boolean walkable;
/**
* The tab index.
*/
private int tabIndex = -1;
/**
* Represents the plugin handler.
*/
private ComponentPlugin plugin;
/**
* Constructs a new {@code ComponentDefinition} {@code Object}.
*/
public ComponentDefinition() {
/*
* empty.
*/
}
/**
* Parses the definition values from a result set.
* @throws SQLException The exception if thrown.
*/
public ComponentDefinition parse(String type, String walkable, String tabIndex){
setType(InterfaceType.values()[Integer.parseInt(type)]);
setWalkable(Boolean.parseBoolean(walkable));
setTabIndex(Integer.parseInt(tabIndex));
return this;
}
/**
* Gets the component definitions for the component id.
* @param componentId The component id.
* @return The component definitions.
*/
public static ComponentDefinition forId(int componentId) {
ComponentDefinition def = DEFINITIONS.get(componentId);
if (def == null) {
DEFINITIONS.put(componentId, def = new ComponentDefinition());
}
return def;
}
/**
* Add a plugin to a definition.
* @param id the id.
* @param plugin the plugin.
*/
public static void put(int id, ComponentPlugin plugin) {
ComponentDefinition.forId(id).setPlugin(plugin);
}
/**
* Gets the definitions mapping.
* @return The definitions mapping.
*/
public static Map<Integer, ComponentDefinition> getDefinitions() {
return DEFINITIONS;
}
/**
* Gets the plugin.
* @return The plugin.
*/
public ComponentPlugin getPlugin() {
return plugin;
}
/**
* Sets the plugin.
* @param plugin The plugin to set.
*/
public void setPlugin(ComponentPlugin plugin) {
this.plugin = plugin;
}
/**
* Gets the window pane id.
* @param resizable If the player is using resizable mode.
* @return The window pane id.
*/
public int getWindowPaneId(boolean resizable) {
return resizable ? type.getResizablePaneId() : type.getFixedPaneId();
}
/**
* Gets the child id.
* @param resizable If the player is using resizable mode.
* @return The child id.
*/
public int getChildId(boolean resizable) {
return resizable ? type.getResizableChildId() : type.getFixedChildId();
}
/**
* Gets the type.
* @return the type
*/
public InterfaceType getType() {
return type;
}
/**
* Sets the batype.
* @param type the type to set.
*/
public void setType(InterfaceType type) {
this.type = type;
}
/**
* Gets the walkable.
* @return the walkable
*/
public boolean isWalkable() {
return walkable;
}
/**
* Sets the bawalkable.
* @param walkable the walkable to set.
*/
public void setWalkable(boolean walkable) {
this.walkable = walkable;
}
/**
* Gets the tabIndex.
* @return the tabIndex
*/
public int getTabIndex() {
return tabIndex;
}
/**
* Sets the batabIndex.
* @param tabIndex the tabIndex to set.
*/
public void setTabIndex(int tabIndex) {
this.tabIndex = tabIndex;
}
@Override
public String toString() {
return "ComponentDefinition [type=" + type + ", walkable=" + walkable + ", tabIndex=" + tabIndex + ", plugin=" + plugin + "]";
}
}
@@ -0,0 +1,35 @@
package core.game.component;
import core.game.node.entity.player.Player;
import core.plugin.Plugin;
/**
* Represents the plugin used to handle a component reward.
* @author Vexia
*/
public abstract class ComponentPlugin implements Plugin<Object> {
/**
* Handles the interface interaction.
* @param player The player.
* @param component The component.
* @param opcode The opcode.
* @param slot The slot.
* @param itemId The item id.
* @return {@code True} if succesfully handled.
*/
public abstract boolean handle(final Player player, Component component, final int opcode, final int button, int slot, int itemId);
/**
* Called when this component opens.
* @param player The player
* @param component The component opening.
*/
public void open(Player player, Component component) {}
@Override
public Object fireEvent(String identifier, Object... args) {
return null;
}
}
@@ -0,0 +1,122 @@
package core.game.component;
import static core.tools.Interfaces.*;
/**
* Represents an interface type.
* @author Emperor
*
*/
public enum InterfaceType {
/**
* Default interface.
*/
DEFAULT(TOPLEVEL_548, TOPLEVEL_FULLSCREEN_746, 11, 6),
/**
* Walkable interface.
*/
OVERLAY(TOPLEVEL_548, TOPLEVEL_FULLSCREEN_746, 4, 5),
/**
* A tab interface.
*/
TAB(TOPLEVEL_548, TOPLEVEL_FULLSCREEN_746, 83, 93),
/**
* The only tab to be shown (when this type is opened).
*/
SINGLE_TAB(TOPLEVEL_548, TOPLEVEL_FULLSCREEN_746, 80, 76),
/**
* Chatbox dialogue interface.
*/
DIALOGUE(CHATTOP_752, CHATTOP_752, 12, 12),
/**
* A window pane.
*/
WINDOW_PANE(TOPLEVEL_548, TOPLEVEL_FULLSCREEN_746, 0, 0),
/**
* Client script chatbox interface.
*/
CS_CHATBOX(CHATTOP_752, CHATTOP_752, 6, 6),
/**
* Chatbox interface.
*/
CHATBOX(CHATTOP_752, CHATTOP_752, 8, 8),
/**
* Wilderness overlay
*/
WILDERNESS_OVERLAY(TOPLEVEL_548, TOPLEVEL_FULLSCREEN_746, 11, 3);
/**
* The fixed window pane id.
*/
private final int fixedPaneId;
/**
* The resizable window pane id.
*/
private final int resizablePaneId;
/**
* The fixed child id.
*/
private final int fixedChildId;
/**
* The resizable child id.
*/
private final int resizableChildId;
/**
* Constructs a new {@Code InterfaceType} {@Code Object}
* @param fixedPaneId The fixed window pane id.
* @param resizablePaneId The resizable window pane id.
* @param fixedChildId The fixed child id.
* @param resizableChildId The resizable child id.
*/
private InterfaceType(int fixedPaneId, int resizablePaneId, int fixedChildId, int resizableChildId) {
this.fixedPaneId = fixedPaneId;
this.resizablePaneId = resizablePaneId;
this.fixedChildId = fixedChildId;
this.resizableChildId = resizableChildId;
}
/**
* Gets the fixedPaneId.
* @return the fixedPaneId
*/
public int getFixedPaneId() {
return fixedPaneId;
}
/**
* Gets the resizablePaneId.
* @return the resizablePaneId
*/
public int getResizablePaneId() {
return resizablePaneId;
}
/**
* Gets the fixedChildId.
* @return the fixedChildId
*/
public int getFixedChildId() {
return fixedChildId;
}
/**
* Gets the resizableChildId.
* @return the resizableChildId
*/
public int getResizableChildId() {
return resizableChildId;
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,117 @@
package core.game.container;
import core.game.node.item.Item;
/**
* Represents a container event.
* @author Emperor
*/
public final class ContainerEvent {
/**
* Represents a null item.
*/
public static final Item NULL_ITEM = new Item(0, 0);
/**
* The array of changed items.
*/
private final Item[] items;
/**
* Clears the container.
*/
private boolean clear;
/**
* Constructs a new {@code ContainerEvent} {@code Object}.
* @param size The container size.
*/
public ContainerEvent(int size) {
this.items = new Item[size];
}
/**
* Flags a null item on the given slot.
* @param slot The slot.
*/
public void flagNull(int slot) {
items[slot] = NULL_ITEM;
}
/**
* Flags an item on the given slot.
* @param slot The slot.
* @param item The item.
*/
public void flag(int slot, Item item) {
items[slot] = item;
}
/**
* Gets the amount of item slots changed.
* @return The amount of item slots that have changed.
*/
public int getChangeCount() {
int count = 0;
for (Item item : items) {
if (item != null) {
count++;
}
}
return count;
}
/**
* Gets the updated slots.
* @return The slots array.
*/
public int[] getSlots() {
int size = 0;
int[] slots = new int[items.length];
for (int i = 0; i < items.length; i++) {
if (items[i] != null) {
slots[size++] = i;
}
}
int[] slot = new int[size];
for (int i = 0; i < size; i++) {
slot[i] = slots[i];
}
return slot;
}
/**
* Gets the items.
* @return The items.
*/
public Item[] getItems() {
return items;
}
/**
* Flags an empty container.
*/
public void flagEmpty() {
this.clear = true;
for (int i = 0; i < items.length; i++) {
items[i] = null;
}
}
/**
* Gets the clear.
* @return The clear.
*/
public boolean isClear() {
return clear;
}
/**
* Sets the clear flag.
* @param clear The container is cleared.
*/
public void setClear(boolean clear) {
this.clear = clear;
}
}
@@ -0,0 +1,21 @@
package core.game.container;
/**
* Represents a container listener.
* @author Emperor
*/
public interface ContainerListener {
/**
* Updates the changed item slots in the container.
* @param c The container we're listening to.
* @param event The container event.
*/
void update(Container c, ContainerEvent event);
/**
* Updates the entire container.
* @param c The container.
*/
void refresh(Container c);
}
@@ -0,0 +1,29 @@
package core.game.container;
/**
* Represents the container types.
* @author Emperor
*/
public enum ContainerType {
/**
* The default container type.
*/
DEFAULT,
/**
* If the container is used for a shop.
*/
SHOP,
/**
* The container should always stack items.
*/
ALWAYS_STACK,
/**
* The container should never stack items.
*/
NEVER_STACK;
}
@@ -0,0 +1,19 @@
package core.game.container;
/**
* The sort type of the container.
* @author Emperor
*/
public enum SortType {
/**
* Sort by item id (default).
*/
ID,
/**
* Sort by item identification hash (bank).
*/
HASH
}
@@ -0,0 +1,122 @@
package core.game.container.access;
import core.game.node.entity.player.Player;
/**
* Contains the mask value methods. The 'access mask' is actually just a bit
* register that contains permissions for a specific interface (@Peterbjornx)
* @date 5/02/2013
* @author Stacx
* @author Emperor
*/
public final class BitregisterAssembler {
/**
* The register size.
*/
public static final int SIZE = 32 - 1;
/**
* Examine option.
*/
public static final int EXAMINE_OPT = 9;
/**
* Allow dragging.
*/
public static final int DRAGABLE = 17;
/**
* Allow switching item slots.
*/
public static final int SLOT_SWITCH = 20;
/**
* The flags.
*/
private boolean[] permissions = new boolean[SIZE];
/**
* Constructs a new {@code BitregisterAssembler} {@code Object}.
* @param permissions The permissions.
*/
public BitregisterAssembler(int... permissions) {
for (int i : permissions) {
this.permissions[i] = true;
}
}
/**
* Constructs a new {@code BitregisterAssembler} {@code Object}.
*/
public BitregisterAssembler(String[] options) {
enableOptions(options);
}
/**
* Enables the given options ({@code null} options will remain disabled).
* @param options The options.
*/
public void enableOptions(String...options) {
if (options.length > 9) {
throw new IllegalStateException("Too many options specified - maximum 9 allowed!");
}
for (int i = 0; i < options.length; i++) {
if (options[i] != null && !options[i].equals("null")) {
permissions[i] = true;
}
}
}
/**
* Enables the examine option.
*/
public void enableExamineOption() {
permissions[EXAMINE_OPT] = true;
}
/**
* Enables items being dragged.
*/
public void enableDragging() {
permissions[DRAGABLE] = true;
}
/**
* Enables item switching slots (& dragging).
*/
public void enableSlotSwitch() {
enableDragging();
permissions[SLOT_SWITCH] = true;
}
/**
* <b>Send</b> and assemble a bit register for our
* @param player , the player instance
* @param interfaceIndex , the interface index
* @param childIndex , the child index for our interface
* @param offset , the offset for the loop in client
* @param length , the length of our loop
*/
public static void send(Player player, int interfaceIndex, int childIndex, int offset, int length, BitregisterAssembler assembler) {
if (offset >= length) {
throw new RuntimeException("Offset cannot excess length. length = " + length);
}
player.getPacketDispatch().sendAccessMask(assembler.calculateRegister(), childIndex, interfaceIndex, offset, length);
}
/**
* Calculates the register.
* @return The value.
*/
public int calculateRegister() {
int value = 0;
for (int i = 0; i < SIZE; i++) {
if (permissions[i]) {
value |= 2 << i;
}
}
return value;
}
}
@@ -0,0 +1,165 @@
package core.game.container.access;
import core.game.node.entity.player.Player;
import core.game.node.item.Item;
import core.net.packet.PacketRepository;
import core.net.packet.context.ContainerContext;
import core.net.packet.out.ContainerPacket;
/**
* Generates a set of items and options on an interface.
* @date 5/02/2013
* @author Stacx
*/
public class InterfaceContainer {
/**
* The client script index for set_options.
*/
private static final int CLIENT_SCRIPT_INDEX = 150;
/**
* This index will increase each time a set is generated.
*/
private static int index = 600; // 93
/**
* Generates a container/array of items in an interface positioned on the
* child index.
* @param player , the player we generate this set for
* @param itemArray , the container/array of items we want to display
* @param options , the right-click options we want for the items
* @param interfaceIndex , the interface index
* @param childIndex , the child index of the interface where we display the
* items at.
* @return The container key.
*/
private static int generate(Player player, Item[] itemArray, String[] options, int interfaceIndex, int childIndex, int x, int y, int key) {
Object[] clientScript = new Object[options.length + 7];
player.getPacketDispatch().sendRunScript(CLIENT_SCRIPT_INDEX, generateScriptArguments(options.length), populateScript(clientScript, options, interfaceIndex << 16 | childIndex, x, y, key));
BitregisterAssembler.send(player, interfaceIndex, childIndex, 0, itemArray.length, new BitregisterAssembler(options));
PacketRepository.send(ContainerPacket.class, new ContainerContext(player, -1, -2, key, itemArray, itemArray.length, false));
return increment();
}
public static int generateOptions(Player player, String[] options, int interfaceIndex, int childIndex, int x, int y, int key){
player.getPacketDispatch().sendRunScript(CLIENT_SCRIPT_INDEX, generateScriptArguments(options.length), populateScript(new Object[options.length + 7],options,interfaceIndex << 16 | childIndex, x, y, key));
BitregisterAssembler.send(player,interfaceIndex,childIndex,0,28,new BitregisterAssembler(options));
return increment();
}
/**
* Generates options for the interface item container.
* @param player The player.
* @param interfaceId The interface id.
* @param childId The child index.
* @param itemLength The amount of items.
* @param options The options.
* @return The container key.
*/
public static int generate(Player player, int interfaceId, int childId, int itemLength, String... options) {
return generate(player, interfaceId, childId, itemLength, 7, 3, options);
}
/**
* Generates options for the interface item container.
* @param player The player.
* @param interfaceId The interface id.
* @param childId The child index.
* @param itemLength The amount of items.
* @param x The amount of items in a row.
* @param y The amount of item rows.
* @param options The options.
* @return The container key.
*/
public static int generate(Player player, int interfaceId, int childId, int itemLength, int x, int y, String... options) {
int key = increment();
Object[] clientScript = new Object[options.length + 7];
player.getPacketDispatch().sendRunScript(CLIENT_SCRIPT_INDEX, generateScriptArguments(options.length), populateScript(clientScript, options, interfaceId << 16 | childId, x, y, key));
BitregisterAssembler.send(player, interfaceId, childId, 0, itemLength, new BitregisterAssembler(options));
return key;
}
/**
* Increments the current index.
* @return The previous index.
*/
private static int increment() {
if (index == 6999) {
index = 600;
}
return index++;
}
/**
* Populates an object array used as a script for the client
* @param script , the array we want to populate
* @param options , the right-click options for our items
* @param hash , interfaceIndex << 16 | childIndex
* @return script, the populated script
*/
private static Object[] populateScript(Object[] script, String[] options, int hash, int x, int y, int key) {
int offset = 0;
for (String option : options) {
script[offset++] = option;
}
System.arraycopy(new Object[] { -1, 0, x, y, key, hash }, 0, script, offset, 6);
return script;
}
/**
* Generates a script argument type string for the client (note: everything
* but a "s" is integer for the run script packet)
* @param length , the amount of options
* @return the generated string.
*/
private static String generateScriptArguments(int length) {
StringBuilder builder = new StringBuilder("IviiiI");
while (length > 0) {
builder.append("s");
length--;
}
return builder.toString();
}
/**
* Default method to generate and send an item array for the client.
* @return The container key.
* @see {@link InterfaceContainer.generate}
*/
public static int generateItems(Player player, Item[] itemArray, String[] options, int interfaceIndex, int childIndex) {
return generateItems(player, itemArray, options, interfaceIndex, childIndex, 7, 3, increment());
}
/**
* Default method to generate and send an item array for the client.
* @return The container key.
* @see {@link InterfaceContainer.generate}
*/
public static int generateItems(Player player, Item[] itemArray, String[] options, int interfaceIndex, int childIndex, int key) {
return generateItems(player, itemArray, options, interfaceIndex, childIndex, 7, 3, key);
}
/**
* Method to generate the send items for the client with a specified
* location for the items.
* @param x , the x coordinate
* @param y , the y coordinate
* @return The container key.
*/
public static int generateItems(Player player, Item[] itemArray, String[] options, int interfaceIndex, int childIndex, int x, int y) {
return generateItems(player, itemArray, options, interfaceIndex, childIndex, x, y, increment());
}
/**
* Method to generate the send items for the client with a specified
* location for the items.
* @param x , the x coordinate
* @param y , the y coordinate
* @return The container key.
*/
public static int generateItems(Player player, Item[] itemArray, String[] options, int interfaceIndex, int childIndex, int x, int y, int key) {
return generate(player, itemArray, options, interfaceIndex, childIndex, x, y, key);
}
}
@@ -0,0 +1,556 @@
package core.game.container.impl;
import core.ServerConstants;
import core.game.component.Component;
import core.game.container.*;
import core.game.container.access.BitregisterAssembler;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.IronmanMode;
import core.game.node.item.Item;
import core.game.system.config.ItemConfigParser;
import core.game.world.GameWorld;
import core.net.packet.PacketRepository;
import core.net.packet.context.ContainerContext;
import core.net.packet.out.ContainerPacket;
import java.nio.ByteBuffer;
/**
* Represents the bank container.
* @author Emperor
*/
public final class BankContainer extends Container {
/**
* The bank container size.
*/
public static final int SIZE = ServerConstants.BANK_SIZE;
/**
* The maximum amount of bank tabs
*/
public static final int TAB_SIZE = 11;
/**
* The player reference.
*/
private Player player;
/**
* The bank listener.
*/
private final BankListener listener;
/**
* Set {@code true} to note items.
*/
private boolean noteItems;
/**
* If the bank is open.
*/
private boolean open;
/**
* The last x-amount entered.
*/
private int lastAmountX = 50;
/**
* The current tab index.
*/
private int tabIndex = 10;
/**
* The tab start indexes.
*/
private final int[] tabStartSlot = new int[TAB_SIZE];
/**
* If inserting items is enabled.
*/
private boolean insertItems;
/**
* Construct a new {@code BankContainer} {@code Object}.
* @param player The player reference.
*/
public BankContainer(Player player) {
super(SIZE, ContainerType.ALWAYS_STACK, SortType.HASH);
super.register(listener = new BankListener(player));
this.player = player;
}
/**
* Open the bank.
*/
public void open() {
if (open) {
return;
}
if (player.getIronmanManager().checkRestriction(IronmanMode.ULTIMATE)) {
return;
}
if (!player.getBankPinManager().isUnlocked() && !GameWorld.getSettings().isDevMode()) {
player.getBankPinManager().openType(1);
return;
}
player.getInterfaceManager().openComponent(762).setCloseEvent((player, c) -> {
BankContainer.this.close();
return true;
});
player.getInterfaceManager().openSingleTab(new Component(763));
super.refresh();
player.getInventory().getListeners().add(listener);
player.getInventory().refresh();
player.varpManager.get(1249).setVarbit(0,lastAmountX).send(player);
player.getPacketDispatch().sendAccessMask(1278, 73, 762, 0, ServerConstants.BANK_SIZE);
BitregisterAssembler assembly = new BitregisterAssembler(0, 1, 2, 3, 4, 5);
assembly.enableExamineOption();
assembly.enableSlotSwitch();
player.getPacketDispatch().sendAccessMask(assembly.calculateRegister(), 0, 763, 0, 27);
player.getPacketDispatch().sendRunScript(1451, "");
open = true;
setTabConfigurations();
sendBankSpace();
}
public void open(Player player) {
if (open) {
return;
}
if (player.getIronmanManager().checkRestriction(IronmanMode.ULTIMATE)) {
return;
}
if (!player.getBankPinManager().isUnlocked() && !GameWorld.getSettings().isDevMode()) {
player.getBankPinManager().openType(1);
return;
}
player.getInterfaceManager().openComponent(762).setCloseEvent((player1, c) -> {
BankContainer.this.close();
return true;
});
this.player.getBank().refresh(player.getBank().listener);
player.getInterfaceManager().openSingleTab(new Component(763));
player.getInventory().getListeners().add(player.getBank().listener);
player.getInventory().refresh();
player.varpManager.get(1249).setVarbit(0,lastAmountX).send(player);
player.getPacketDispatch().sendAccessMask(1278, 73, 762, 0, SIZE);
BitregisterAssembler assembly = new BitregisterAssembler(0, 1, 2, 3, 4, 5);
assembly.enableExamineOption();
assembly.enableSlotSwitch();
player.getPacketDispatch().sendAccessMask(assembly.calculateRegister(), 0, 763, 0, 27);
player.getPacketDispatch().sendRunScript(1451, "");
open = true;
this.player.getBank().setTabConfigurations(player);
}
@Override
public long save(ByteBuffer buffer) {
buffer.putInt(lastAmountX);
buffer.put((byte) tabStartSlot.length);
for (int j : tabStartSlot) {
buffer.putShort((short) j);
}
return super.save(buffer);
}
@Override
public int parse(ByteBuffer buffer) {
lastAmountX = buffer.getInt();
int length = buffer.get() & 0xFF;
for (int i = 0; i < length; i++) {
tabStartSlot[i] = buffer.getShort();
}
return super.parse(buffer);
}
/**
* Closes the bank.
*/
public void close() {
open = false;
player.getInventory().getListeners().remove(listener);
player.getInterfaceManager().closeSingleTab();
player.removeAttribute("search");
player.getPacketDispatch().sendRunScript(571, "");
}
/**
* Adds an item to the bank container.
* @param slot The item slot.
* @param amount The amount.
*/
public void addItem(int slot, int amount) {
if (slot < 0 || slot > player.getInventory().capacity() || amount < 1) {
return;
}
Item item = player.getInventory().get(slot);
if (item == null) {
return;
}
int maximum = player.getInventory().getAmount(item);
if (amount > maximum) {
amount = maximum;
}
int maxCount = super.getMaximumAdd(item);
if (amount > maxCount) {
amount = maxCount;
if (amount < 1) {
player.getPacketDispatch().sendMessage("There is not enough space left in your bank.");
return;
}
}
if (!item.getDefinition().getConfiguration(ItemConfigParser.BANKABLE, true)) {
player.sendMessage("A magical force prevents you from banking this item");
return;
}
item = new Item(item.getId(), amount, item.getCharge());
boolean unnote = !item.getDefinition().isUnnoted();
if (player.getInventory().remove(item, slot, true)) {
Item add = unnote ? new Item(item.getDefinition().getNoteId(), amount, item.getCharge()) : item;
if (unnote && !add.getDefinition().isUnnoted()) {
add = item;
}
int preferredSlot = -1;
if (tabIndex != 0 && tabIndex != 10 && !super.contains(add.getId(), 1)) {
preferredSlot = tabStartSlot[tabIndex] + getItemsInTab(tabIndex);
insert(freeSlot(), preferredSlot, false);
increaseTabStartSlots(tabIndex);
}
super.add(add, true, preferredSlot);
setTabConfigurations();
}
}
/**
* Re-opens the bank interface.
*/
public void reopen() {
if (!open) {
return;
}
player.getInterfaceManager().close();
open();
refresh();
}
/**
* Takes a item from the bank container and adds one to the inventory
* container.
* @param slot The slot.
* @param amount The amount.
*/
public void takeItem(int slot, int amount) {
if (slot < 0 || slot > super.capacity() || amount <= 0) {
return;
}
Item item = get(slot);
if (item == null) {
return;
}
if (amount > item.getAmount()) {
amount = item.getAmount(); // It always stacks in the bank.
}
item = new Item(item.getId(), amount, item.getCharge());
int noteId = item.getDefinition().getNoteId();
Item add = noteItems && noteId > 0 ? new Item(noteId, amount, item.getCharge()) : item;
int maxCount = player.getInventory().getMaximumAdd(add);
if (amount > maxCount) {
item.setAmount(maxCount);
add.setAmount(maxCount);
if (maxCount < 1) {
player.getPacketDispatch().sendMessage("Not enough space in your inventory.");
return;
}
}
if (noteItems && noteId < 0) {
player.getPacketDispatch().sendMessage("This item can't be withdrawn as a note.");
add = item;
}
if (super.remove(item, slot, false)) {
player.getInventory().add(add);
}
int tabId = getTabByItemSlot(slot);
if (get(slot) == null) {
decreaseTabStartSlots(tabId);
}
setTabConfigurations();
shift();
if (player.getAttribute("search", false)) {
reopen();
}
}
/**
* Updates the last x-amount entered.
* @param amount The amount to set.
*/
public void updateLastAmountX(int amount) {
this.lastAmountX = amount;
player.varpManager.get(1249).setVarbit(0,amount).send(player);
}
/**
* Gets the tab the item slot is in.
* @param itemSlot The item slot.
* @return The tab index.
*/
public int getTabByItemSlot(int itemSlot) {
int tabId = 0;
for (int i = 0; i < tabStartSlot.length; i++) {
if (itemSlot >= tabStartSlot[i]) {
tabId = i;
}
}
return tabId;
}
/**
* Increases a tab's start slot.
* @param startId The start id.
*/
public void increaseTabStartSlots(int startId) {
for (int i = startId + 1; i < tabStartSlot.length; i++) {
tabStartSlot[i]++;
}
}
/**
* Decreases a tab's start slot.
* @param startId The start id.
*/
public void decreaseTabStartSlots(int startId) {
if (startId == 10) {
return;
}
for (int i = startId + 1; i < tabStartSlot.length; i++) {
tabStartSlot[i]--;
}
if (getItemsInTab(startId) == 0) {
collapseTab(startId);
}
}
/**
* Gets the array index for a tab.
* @param tabId The tab id.
* @return The array index.
*/
public static int getArrayIndex(int tabId) {
if (tabId == 41 || tabId == 74) {
return 10;
}
int base = 39;
for (int i = 1; i < 10; i++) {
if (tabId == base) {
return i;
}
base -= 2;
}
return -1;
}
/**
* Sends the bank space values on the interface.
*/
public void sendBankSpace() {
player.getPacketDispatch().sendString(Integer.toString(capacity() - freeSlots()), 762, 97);
player.getPacketDispatch().sendString(Integer.toString(capacity()), 762, 98);
}
/**
* Collapses a tab.
* @param tabId The tab index.
*/
public void collapseTab(int tabId) {
int size = getItemsInTab(tabId);
Item[] tempTabItems = new Item[size];
for (int i = 0; i < size; i++) {
tempTabItems[i] = get(tabStartSlot[tabId] + i);
replace(null, tabStartSlot[tabId] + i, false);
}
shift();
for (int i = tabId; i < tabStartSlot.length - 1; i++) {
tabStartSlot[i] = tabStartSlot[i + 1] - size;
}
tabStartSlot[10] = tabStartSlot[10] - size;
for (int i = 0; i < size; i++) {
int slot = freeSlot();
replace(tempTabItems[i], slot, false);
}
refresh(); //We only refresh once.
setTabConfigurations();
}
/**
* Sets the tab configs.
*/
public void setTabConfigurations() {
int value = getItemsInTab(1);
value += getItemsInTab(2) << 10;
value += getItemsInTab(3) << 20;
player.getConfigManager().set(1246, value);
value = getItemsInTab(4);
value += getItemsInTab(5) << 10;
value += getItemsInTab(6) << 20;
player.getConfigManager().set(1247, value);
value = -2013265920;
value += (134217728 * (tabIndex == 10 ? 0 : tabIndex));
value += getItemsInTab(7);
value += getItemsInTab(8) << 10;
player.getConfigManager().set(1248, value);
}
/**
* Sets the tab configs.
*/
public void setTabConfigurations(Player player) {
int value = getItemsInTab(1);
value += getItemsInTab(2) << 10;
value += getItemsInTab(3) << 20;
player.getConfigManager().set(1246, value);
value = getItemsInTab(4);
value += getItemsInTab(5) << 10;
value += getItemsInTab(6) << 20;
player.getConfigManager().set(1247, value);
value = -2013265920;
value += (134217728 * (tabIndex == 10 ? 0 : tabIndex));
value += getItemsInTab(7);
value += getItemsInTab(8) << 10;
player.getConfigManager().set(1248, value);
}
/**
* Gets the amount of items in one tab.
* @param tabId The tab index.
* @return The amount of items in this tab.
*/
public int getItemsInTab(int tabId) {
return tabStartSlot[tabId + 1] - tabStartSlot[tabId];
}
/**
* Checks if the item can be added.
* @param item the item.
* @return {@code True} if so.
*/
public boolean canAdd(Item item) {
return item.getDefinition().getConfiguration(ItemConfigParser.BANKABLE, true);
}
/**
* Gets the last x-amount.
* @return The last x-amount.
*/
public int getLastAmountX() {
return lastAmountX;
}
/**
* If items have to be noted.
* @return If items have to be noted {@code true}.
*/
public boolean isNoteItems() {
return noteItems;
}
/**
* Set if items have to be noted.
* @param noteItems If items have to be noted {@code true}.
*/
public void setNoteItems(boolean noteItems) {
this.noteItems = noteItems;
}
/**
* Gets the tabStartSlot value.
* @return The tabStartSlot.
*/
public int[] getTabStartSlot() {
return tabStartSlot;
}
/**
* Gets the tabIndex value.
* @return The tabIndex.
*/
public int getTabIndex() {
return tabIndex;
}
/**
* Sets the tabIndex value.
* @param tabIndex The tabIndex to set.
*/
public void setTabIndex(int tabIndex) {
this.tabIndex = tabIndex;
}
/**
* Sets the insert items value.
* @param insertItems The insert items value.
*/
public void setInsertItems(boolean insertItems) {
this.insertItems = insertItems;
}
/**
* Gets the insert items value.
* @return {@code True} if inserting items mode is enabled.
*/
public boolean isInsertItems() {
return insertItems;
}
/**
* Checks if the bank is opened.
* @return {@code True} if so.
*/
public boolean isOpen() {
return open;
}
/**
* Listens to the bank container.
* @author Emperor
*/
private static class BankListener implements ContainerListener {
/**
* The player reference.
*/
private Player player;
/**
* Construct a new {@code BankListener} {@code Object}.
* @param player The player reference.
*/
public BankListener(Player player) {
this.player = player;
}
@Override
public void update(Container c, ContainerEvent event) {
if (c instanceof BankContainer) {
PacketRepository.send(ContainerPacket.class, new ContainerContext(player, 762, 64000, 95, event.getItems(), false, event.getSlots()));
} else {
PacketRepository.send(ContainerPacket.class, new ContainerContext(player, 763, 64000, 93, event.getItems(), false, event.getSlots()));
}
player.getBank().setTabConfigurations();
player.getBank().sendBankSpace();
}
@Override
public void refresh(Container c) {
if (c instanceof BankContainer) {
PacketRepository.send(ContainerPacket.class, new ContainerContext(player, 762, 64000, 95, c.toArray(), c.capacity(), false));
} else {
PacketRepository.send(ContainerPacket.class, new ContainerContext(player, 763, 64000, 93, c.toArray(), 28, false));
}
player.getBank().setTabConfigurations();
player.getBank().sendBankSpace();
}
}
}
@@ -0,0 +1,285 @@
package core.game.container.impl;
import core.game.container.Container;
import core.game.container.ContainerEvent;
import core.game.container.ContainerListener;
import core.game.node.entity.combat.equipment.WeaponInterface;
import core.game.node.entity.player.Player;
import core.game.node.item.Item;
import core.game.system.config.ItemConfigParser;
import core.game.world.update.flag.player.AppearanceFlag;
import core.net.packet.PacketRepository;
import core.net.packet.context.ContainerContext;
import core.net.packet.out.ContainerPacket;
import core.net.packet.out.WeightUpdate;
import core.plugin.Plugin;
import core.game.node.entity.skill.Skills;
import core.game.node.entity.skill.skillcapeperks.SkillcapePerks;
/**
* Represents the equipment container.
* @author Emperor
*/
public final class EquipmentContainer extends Container {
/**
* The equipment slots.
*/
public static final int SLOT_HAT = 0, SLOT_CAPE = 1, SLOT_AMULET = 2, SLOT_WEAPON = 3, SLOT_CHEST = 4, SLOT_SHIELD = 5, SLOT_LEGS = 7, SLOT_HANDS = 9, SLOT_FEET = 10, SLOT_RING = 12, SLOT_ARROWS = 13;
/**
* The bonus names.
*/
private static final String[] BONUS_NAMES = { "Stab: ", "Slash: ", "Crush: ", "Magic: ", "Ranged: ", "Stab: ", "Slash: ", "Crush: ", "Magic: ", "Ranged: ", "Summoning: ", "Strength: ", "Prayer: " };
/**
* The player.
*/
private final Player player;
/**
* Constructs a new {@code EquipmentContainer} {@code Object}.
* @param player The player.
*/
public EquipmentContainer(Player player) {
super(14);
this.player = player;
register(new EquipmentListener(player));
}
@Override
public boolean add(Item item, boolean fire) {
return add(item, fire, true);
}
/**
* Adds an item to the equipment container.
* @param item The item to add.
* @param fire If we should refresh.
* @param fromInventory If the item is being equipped from the inventory.
* @return {@code True} if succesful, {@code false} if not.
*/
public boolean add(Item item, boolean fire, boolean fromInventory) {
return add(item, player.getInventory().getSlot(item), fire, fromInventory);
}
/**
* Adds an item to the equipment container.
* @param item The item to add.
* @param inventorySlot The inventory slot of the item.
* @param fire If we should refresh.
* @param fromInventory If the item is being equipped from the inventory.
* @return {@code True} if succesful, {@code false} if not.
*/
public boolean add(Item item, int inventorySlot, boolean fire, boolean fromInventory) {
int slot = item.getDefinition().getConfiguration(ItemConfigParser.EQUIP_SLOT, -1);
if (slot == -1 && item.getDefinition().getConfiguration(ItemConfigParser.WEAPON_INTERFACE, -1) != -1) {
slot = SLOT_WEAPON;
}
// slot = 3;
if (slot < 0) {
return false; // Item can't be equipped.
}
if (!item.getDefinition().hasRequirement(player, true, true)) {
return false;
}
Item current = super.get(slot);
if (current != null && current.getId() == item.getId() && current.getDefinition().isStackable()) {
int amount = getMaximumAdd(item);
if (item.getAmount() > amount) {
amount += current.getAmount();
} else {
amount = current.getAmount() + item.getAmount();
}
if (fromInventory) {
player.getInventory().remove(new Item(item.getId(), amount - current.getAmount()));
}
replace(new Item(item.getId(), amount), slot);
return true;
}
if (fromInventory && current != null) {
Plugin<Object> plugin = current.getDefinition().getConfiguration("equipment", null);
if (plugin != null) {
Object object = plugin.fireEvent("unequip", player, current, item);
if (object != null && !((Boolean) object)) {
return true;
}
}
}
if (fromInventory && !player.getInventory().remove(item, inventorySlot, true)) {
return false;
}
Item secondary = null;
if (item.getDefinition().getConfiguration(ItemConfigParser.TWO_HANDED, false)) {
secondary = get(SLOT_SHIELD);
} else if (slot == SLOT_SHIELD) {
secondary = get(SLOT_WEAPON);
if (secondary != null && !secondary.getDefinition().getConfiguration(ItemConfigParser.TWO_HANDED, false)) {
secondary = null;
}
}
int currentSlot = -1;
if (current != null) {
currentSlot = inventorySlot;
if (current.getDefinition().isStackable() && player.getInventory().contains(current.getId(), 1)) {
currentSlot = -1;
}
}
if (current != null && !player.getInventory().add(current, true, inventorySlot)) {
player.getInventory().add(item);
player.getPacketDispatch().sendMessage("Not enough space in your inventory!");
return false;
}
if (secondary != null && !player.getInventory().add(secondary)) {
if (current != null && currentSlot != -1) {
player.getInventory().remove(current, currentSlot, false);
}
player.getInventory().add(item);
player.getPacketDispatch().sendMessage("Not enough space in your inventory!");
return false;
}
super.replace(item, slot, fire);
if (item.getSlot() == SLOT_WEAPON) {
player.getPacketDispatch().sendString(item.getName(), 92, 0);
}
if (secondary != null) {
super.remove(secondary);
}
return true;
}
/**
* Listens to the equipment container.
* @author Emperor
*/
private static class EquipmentListener implements ContainerListener {
/**
* The player.
*/
private final Player player;
/**
* Constructs a new {@code EquipmentContainer} {@code Object}.
* @param player The player.
*/
public EquipmentListener(Player player) {
this.player = player;
}
@Override
public void update(Container c, ContainerEvent event) {
int[] slots = event.getSlots();
PacketRepository.send(ContainerPacket.class, new ContainerContext(player, 387, 28, 94, event.getItems(), false, slots));
update(c);
boolean updateDefenceAnimation = false;
for (int slot : slots) {
if (slot == EquipmentContainer.SLOT_WEAPON) {
player.getProperties().setAttackSpeed(c.getNew(slot).getDefinition().getConfiguration(ItemConfigParser.ATTACK_SPEED, 4));
WeaponInterface inter = player.getExtension(WeaponInterface.class);
if (inter == null) {
break;
}
inter.updateInterface();
updateDefenceAnimation = true;
} else if (slot == EquipmentContainer.SLOT_SHIELD) {
updateDefenceAnimation = true;
}
}
if (updateDefenceAnimation) {
player.getProperties().updateDefenceAnimation();
}
}
@Override
public void refresh(Container c) {
player.getProperties().setAttackSpeed(c.getNew(3).getDefinition().getConfiguration(ItemConfigParser.ATTACK_SPEED, 4));
WeaponInterface inter = player.getExtension(WeaponInterface.class);
if (inter != null) {
inter.updateInterface();
}
PacketRepository.send(ContainerPacket.class, new ContainerContext(player, 387, 28, 94, c.toArray(), 14, false));
update(c);
player.getProperties().updateDefenceAnimation();
}
/**
* Updates the bonuses, weight, animations, ...
* @param c The container.
*/
public void update(Container c) {
if (c.getNew(SLOT_SHIELD).getId() != 11283 && player.getAttribute("dfs_spec", false)) {
player.removeAttribute("dfs_spec");
player.getProperties().getCombatPulse().setHandler(null);
if (!player.getSettings().isSpecialToggled()) {
player.getConfigManager().set(301, 0);
}
}
player.getAppearance().setAnimations();
player.getUpdateMasks().register(new AppearanceFlag(player));
player.getSettings().updateWeight();
updateBonuses(player);
}
}
/**
* Updates the bonuses.
* @param player The player.
*/
public static void updateBonuses(Player player) {
int[] bonuses = new int[15];
for (Item item : player.getEquipment().toArray()) {
if (item != null) {
int[] bonus = item.getDefinition().getConfiguration(ItemConfigParser.BONUS, new int[15]);
for (int i = 0; i < bonus.length; i++) {
if (i == 14 && bonuses[i] != 0) {
continue;
}
bonuses[i] += bonus[i];
}
}
}
Item weapon = player.getEquipment().get(SLOT_WEAPON);
if(weapon != null && weapon.getDefinition().getRequirement(Skills.STRENGTH) > 0 && SkillcapePerks.isActive(SkillcapePerks.FINE_ATTUNEMENT,player)){
int[] bonus = weapon.getDefinition().getConfiguration(ItemConfigParser.BONUS, new int[15]);
bonuses[11] += Math.ceil(bonus[11] * 0.20);
}
Item shield = player.getEquipment().get(SLOT_SHIELD);
if(shield != null && SkillcapePerks.isActive(SkillcapePerks.GRAND_BULLWARK,player)){
bonuses[5] += Math.ceil(bonuses[5] * 0.20);
bonuses[6] += Math.ceil(bonuses[6] * 0.20);
bonuses[7] += Math.ceil(bonuses[7] * 0.20);
bonuses[9] += Math.ceil(bonuses[9] * 0.20);
}
if (shield != null && shield.getId() == 11283) {
int increase = shield.getCharge() / 20;
bonuses[5] += increase;
bonuses[6] += increase;
bonuses[7] += increase;
bonuses[9] += increase;
}
player.getProperties().setBonuses(bonuses);
update(player);
}
/**
* Updates the equipment stats interface.
* @param player The player to update for.
*/
public static void update(Player player) {
if (!player.getInterfaceManager().hasMainComponent(667)) {
return;
}
PacketRepository.send(WeightUpdate.class, player.getPacketDispatch().getContext());
int index = 0;
int[] bonuses = player.getProperties().getBonuses();
for (int i = 36; i < 50; i++) {
if (i == 47) {
continue;
}
int bonus = bonuses[index];
String bonusValue = bonus > -1 ? ("+" + bonus) : Integer.toString(bonus);
player.getPacketDispatch().sendString(BONUS_NAMES[index++] + bonusValue, 667, i);
}
player.getPacketDispatch().sendString("Attack bonus", 667, 34);
}
}
@@ -0,0 +1,65 @@
package core.game.container.impl;
import core.game.container.Container;
import core.game.container.ContainerEvent;
import core.game.container.ContainerListener;
import core.game.node.entity.skill.summoning.SummoningPouch;
import core.game.node.entity.player.Player;
import core.game.node.item.Item;
import core.net.packet.PacketRepository;
import core.net.packet.context.ContainerContext;
import core.net.packet.out.ContainerPacket;
/**
* Handles the inventory container listening.
* @author Emperor
*/
public final class InventoryListener implements ContainerListener {
/**
* The player.
*/
private final Player player;
/**
* Constructs a new {@code InventoryListener} {@code Object}.
* @param player The player.
*/
public InventoryListener(Player player) {
this.player = player;
}
/**
* Updates the required settings etc for the player when the container
* updates.
* @param c The container.
*/
public void update(Container c) {
player.getSettings().updateWeight();
boolean hadPouch = player.getFamiliarManager().isHasPouch();
boolean pouch = false;
for (Item item : c.toArray()) {
if (item != null && SummoningPouch.get(item.getId()) != null) {
pouch = true;
break;
}
}
player.getFamiliarManager().setHasPouch(pouch);
if (hadPouch != pouch && player.getSkullManager().isWilderness()) {
player.getAppearance().sync();
}
}
@Override
public void refresh(Container c) {
PacketRepository.send(ContainerPacket.class, new ContainerContext(player, 149, 0, 93, c, false));
update(c);
}
@Override
public void update(Container c, ContainerEvent event) {
PacketRepository.send(ContainerPacket.class, new ContainerContext(player, 149, 0, 93, event.getItems(), false, event.getSlots()));
update(c);
}
}
@@ -0,0 +1,79 @@
package core.game.content.activity;
import core.game.node.entity.player.Player;
import core.game.system.SystemLogger;
import core.game.world.GameWorld;
import java.util.HashMap;
import java.util.Map;
/**
* Manages the activities.
* @author Emperor
*/
public final class ActivityManager {
/**
* The mapping of instanced activities.
*/
private static final Map<String, ActivityPlugin> ACTIVITIES = new HashMap<>();
/**
* Constructs a new {@code ActivityManager} {@code Object}.
*/
private ActivityManager() {
/*
* empty.
*/
}
/**
* Registers an activity plugin.
* @param plugin The plugin to register.
*/
public static void register(ActivityPlugin plugin) {
plugin.register();
ACTIVITIES.put(plugin.getName(), plugin);
if (!plugin.isInstanced()) {
plugin.configure();
}
}
/**
* Starts an instanced activity.
* @param player The player.
* @param name The name.
* @param login If we are logging in.
* @param args The arguments.
*/
public static boolean start(Player player, String name, boolean login, Object... args) {
ActivityPlugin plugin = ACTIVITIES.get(name);
if (plugin == null) {
if (GameWorld.getSettings().isDevMode()) {
SystemLogger.logErr("Unhandled activity - " + name + "!");
}
return false;
}
try {
if (plugin.isInstanced()) {
(plugin = plugin.newInstance(player)).configure();
}
return plugin.start(player, login, args);
} catch (Throwable e) {
e.printStackTrace();
if (GameWorld.getSettings().isDevMode()) {
player.getPacketDispatch().sendMessage("Error starting activity " + (plugin == null ? null : plugin.getName()) + "!");
}
}
return false;
}
/**
* Gets the activity by the name.
* @param name the name.
* @return the activity.
*/
public static ActivityPlugin getActivity(String name) {
return ACTIVITIES.get(name);
}
}
@@ -0,0 +1,246 @@
package core.game.content.activity;
import core.ServerConstants;
import core.game.node.entity.Entity;
import core.game.node.entity.player.Player;
import core.game.world.map.Location;
import core.game.world.map.Region;
import core.game.world.map.build.DynamicRegion;
import core.game.world.map.zone.*;
import core.game.world.map.zone.impl.MultiwayCombatZone;
import core.plugin.Plugin;
import core.plugin.PluginManifest;
import core.plugin.PluginType;
/**
* A plugin implementation used for activity plugins.
* @author Emperor
*/
@PluginManifest(type = PluginType.ACTIVITY)
public abstract class ActivityPlugin extends MapZone implements Plugin<Player> {
/**
* If the activity is instanced.
*/
private boolean instanced;
/**
* If the activity is multicombat.
*/
private boolean multicombat;
/**
* If the activity is safe.
*/
private boolean safe;
/**
* The region of the activity.
*/
protected DynamicRegion region;
/**
* The base location.
*/
protected Location base;
/**
* The player.
*/
protected Player player;
/**
* Constructs a new {@code ActivityPlugin} {@code Object}.
* @param name The name.
* @param instanced If the activity is instanced.
* @param multicombat If the activity is multicombat.
* @param safe If the activity is safe (the player does not lose his/her
* items).
*/
public ActivityPlugin(String name, boolean instanced, boolean multicombat, boolean safe, ZoneRestriction... restrictions) {
super(name, true, ZoneRestriction.RANDOM_EVENTS);
for (ZoneRestriction restriction : restrictions) {
addRestriction(restriction.getFlag());
}
this.instanced = instanced;
this.multicombat = multicombat;
this.safe = safe;
if (safe) {
setZoneType(ZoneType.SAFE.getId());
}
}
@Override
public void register(ZoneBorders borders) {
if (multicombat) {
MultiwayCombatZone.getInstance().register(borders);
}
super.register(borders);
}
/**
* Sets the region base location.
*/
protected void setRegionBase() {
if (region != null) {
if (multicombat) {
region.toggleMulticombat();
}
setBase(Location.create(region.getBorders().getSouthWestX(), region.getBorders().getSouthWestY(), 0));
}
}
/**
* Sets the region base for multiple regions.
* @param regions The regions.
*/
protected void setRegionBase(DynamicRegion[] regions) {
region = regions[0];
Location l = region.getBaseLocation();
for (DynamicRegion r : regions) {
if (r.getX() > l.getX() || r.getY() > l.getY()) {
l = r.getBaseLocation();
}
}
ZoneBorders borders = new ZoneBorders(region.getX() << 6, region.getY() << 6, l.getX() + Region.SIZE, l.getY() + Region.SIZE);
RegionZone multiZone = multicombat ? new RegionZone(MultiwayCombatZone.getInstance(), borders) : null;
RegionZone zone = new RegionZone(this, borders);
for (DynamicRegion r : regions) {
if (multicombat) {
r.setMulticombat(true);
r.getRegionZones().add(multiZone);
}
r.getRegionZones().add(zone);
}
setBase(Location.create(borders.getSouthWestX(), borders.getSouthWestY(), 0));
}
/**
* Starts the activity for the player.
* @param player The player.
* @param login If the player is logging in.
* @param args The arguments.
* @return {@code True} if successfully started the activity.
*/
public boolean start(Player player, boolean login, Object... args) {
this.player = player;
return true;
}
@Override
public boolean enter(Entity e) {
Location l;
if (e instanceof Player && (l = getSpawnLocation()) != null) {
e.getProperties().setSpawnLocation(l);
}
e.getProperties().setSafeZone(safe);
e.setAttribute("activity", this);
return super.enter(e);
}
@Override
public boolean leave(Entity e, boolean logout) {
if (e instanceof Player) {
e.getProperties().setSpawnLocation(ServerConstants.HOME_LOCATION);
}
Location l;
if (instanced && logout && (l = getSpawnLocation()) != null) {
e.setLocation(l);
}
e.getProperties().setSafeZone(false);
e.removeAttribute("activity");
return super.leave(e, logout);
}
/**
* Method used to do anything on registration.
*/
public void register() {
}
@Override
public Object fireEvent(String identifier, Object... args) {
return null;
}
@Override
public abstract ActivityPlugin newInstance(Player p) throws Throwable;
/**
* Gets the spawn location for this activity.
*/
public abstract Location getSpawnLocation();
/**
* Gets the instanced.
* @return The instanced.
*/
public boolean isInstanced() {
return instanced;
}
/**
* Sets the instanced.
* @param instanced The instanced to set.
*/
public void setInstanced(boolean instanced) {
this.instanced = instanced;
}
/**
* Gets the multicombat.
* @return The multicombat.
*/
public boolean isMulticombat() {
return multicombat;
}
/**
* Sets the multicombat.
* @param multicombat The multicombat to set.
*/
public void setMulticombat(boolean multicombat) {
this.multicombat = multicombat;
}
/**
* Gets the safe.
* @return The safe.
*/
public boolean isSafe() {
return safe;
}
/**
* Sets the safe.
* @param safe The safe to set.
*/
public void setSafe(boolean safe) {
this.safe = safe;
}
/**
* Gets the player.
* @return The player.
*/
public Player getPlayer() {
return player;
}
/**
* Gets the base.
* @return The base.
*/
public Location getBase() {
return base;
}
/**
* Sets the base.
* @param base The base to set.
*/
public void setBase(Location base) {
this.base = base;
}
}
@@ -0,0 +1,336 @@
package core.game.content.activity;
import core.game.component.Component;
import core.game.node.entity.Entity;
import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player;
import core.game.system.task.Pulse;
import core.game.world.GameWorld;
import core.game.world.map.Location;
import core.game.world.map.build.DynamicRegion;
import core.net.packet.PacketRepository;
import core.net.packet.context.MinimapStateContext;
import core.net.packet.out.MinimapState;
import core.plugin.PluginManifest;
import core.plugin.PluginType;
import java.util.ArrayList;
import java.util.List;
/**
* Represents the plugin used to handle a cutscene.
* @author Vexia
* @date 28/12/2013
*/
@PluginManifest(type = PluginType.ACTIVITY)
public abstract class CutscenePlugin extends ActivityPlugin {
/**
* The list of tabs to remove.
*/
private static final int[] TABS = new int[] { 0, 1, 2, 3, 4, 5, 6, 11, 12 };
/**
* The npcs in our cutscene.
*/
protected final List<NPC> npcs = new ArrayList<>();
/**
* The start pulse used for effect.
*/
private final StartPulse startPulse = new StartPulse();
/**
* The ending pulse used for effect.
*/
private final EndPulse endPulse = new EndPulse();
/**
* If we should use a fade in or not.
*/
private final boolean fade;
/**
* Constructs a new {@code CutscenePlugin} {@code Object}.
* @param name the name of the cutscene/mapzone.
* @param fade fading in or not.
*/
public CutscenePlugin(String name, final boolean fade) {
super(name, true, false, true);
this.fade = fade;
}
/**
* Constructs a new {@code CutscenePlugin} {@code Object}.
* @param name the name.
*/
public CutscenePlugin(final String name) {
this(name, true);
}
@Override
public boolean start(final Player player, boolean login, Object... args) {
player.setAttribute("cutscene:original-loc", player.getLocation());
player.removeAttribute("real-end");
player.setAttribute("real-end", player.getLocation());
if (isFade()) {
GameWorld.getPulser().submit(getStartPulse());
} else {
PacketRepository.send(MinimapState.class, new MinimapStateContext(player, getMapState()));
player.getInterfaceManager().hideTabs(getRemovedTabs());
player.getProperties().setTeleportLocation(getStartLocation());
player.unlock();
player.getWalkingQueue().reset();
player.getLocks().lockMovement(1000000);
player.getInterfaceManager().close();
open();
}
player.lock();
return super.start(player, login, args);
}
@SuppressWarnings("deprecation")
@Override
public boolean leave(final Entity e, boolean logout) {
if (player != null) {
if (logout) {
player.setLocation(player.getAttribute("cutscene:original-loc", player.getLocation()));
end();
} else {
unpause();
}
player.unlock();
player.getWalkingQueue().reset();
player.getLocks().unlockMovement();
}
return super.leave(e, logout);
}
@Override
public Object fireEvent(String identifier, Object... args) {
return null;
}
/**
* Method used to stop the cutscene.
* @param fade if we should use a fade cutout.
*/
public void stop(boolean fade) {
if (fade) {
GameWorld.getPulser().submit(endPulse);
} else {
end();
}
}
/**
* Method used to end the cutscene.
*/
public void end() {
if (region != null) {
for (int i = 0; i < region.getPlanes().length; i++) {
for (NPC n : region.getPlanes()[i].getNpcs()) {
if (n == null) {
continue;
}
n.clear();
}
}
}
PacketRepository.send(MinimapState.class, new MinimapStateContext(player, 0));
player.getInterfaceManager().restoreTabs();
player.unlock();// incase he was locked.
player.getWalkingQueue().reset();
}
/**
* Represents the pulse used when starting a cutscene. This is used to give
* dramatic effect for entering a cutscene. In the future allow for this to
* be toggled.
* @author 'Vexia
* @date 30/12/2013
*/
public class StartPulse extends Pulse {
/**
* Represents the counter.
*/
private int counter = 0;
/**
* Constructs a new {@code StartPulse} {@code Object}.
*/
public StartPulse() {
super(1, player);
}
@Override
public boolean pulse() {
switch (counter++) {
case 1:
player.lock();
player.getInterfaceManager().openOverlay(new Component(115));
break;
case 3:
PacketRepository.send(MinimapState.class, new MinimapStateContext(player, getMapState()));
player.getInterfaceManager().hideTabs(getRemovedTabs());
break;
case 4:
player.getProperties().setTeleportLocation(getStartLocation());
break;
case 5:
player.getInterfaceManager().closeOverlay();
player.getInterfaceManager().close();
player.unlock();
player.getWalkingQueue().reset();
player.getLocks().lockMovement(1000000);
open();
return true;
}
return false;
}
}
/**
* Represents the pulse used when ending a cutscene. This is used to give
* dramatic effect for entering a cutscene.
* @author 'Vexia
* @date 30/12/2013
*/
public class EndPulse extends Pulse {
/**
* Represents the counter.
*/
private int counter = 0;
/**
* Constructs a new {@code EndPulse} {@code Object}.
*/
public EndPulse() {
super(1, player);
}
@Override
public boolean pulse() {
switch (counter++) {
case 1:
player.lock();
player.getInterfaceManager().openOverlay(new Component(115));
break;
case 3:
PacketRepository.send(MinimapState.class, new MinimapStateContext(player, getMapState()));
player.getInterfaceManager().hideTabs(getRemovedTabs());
break;
case 4:
Location loc = (Location) (player.getAttribute("real-end", player.getAttribute("cutscene:original-loc", player.getLocation())));
player.getProperties().setTeleportLocation(loc);
break;
case 5:
end();
stop();
fade();// specfic for fadeout.
if (player.getSession().isActive()) {
PacketRepository.send(MinimapState.class, new MinimapStateContext(player, 0));
}
player.getInterfaceManager().closeOverlay();
if (player.getSession().isActive()) {
player.getInterfaceManager().close();
}
player.getProperties().setSafeZone(false);
return true;
}
return false;
}
}
/**
* Method called when the dim interface is closed. And you can see the
* cutscene.
*/
public void open() {
}
/**
* Method called on the end of the cutscene.
*/
public void fade() {
}
/**
* Gets the mapstate to use. (override if needed).
* @return the state.
*/
public int getMapState() {
return 2;
}
/**
* Gets the removed tabs. (override if needed).
* @return the tabs.
*/
public int[] getRemovedTabs() {
return TABS;
}
/**
* Gets the starting location (region based, override if needed).
* @return the location.
*/
public Location getStartLocation() {
return getBase();
}
/**
* Method used to unpause this cutscene.
*/
public final void unpause() {
stop(true);
}
/**
* Gets the player.
* @return The player.
*/
public Player getPlayer() {
return player;
}
/**
* Gets the region.
* @return The region.
*/
public DynamicRegion getRegion() {
return region;
}
/**
* Gets the nPCS.
* @return The nPCS.
*/
public List<NPC> getNPCS() {
return npcs;
}
/**
* Gets the fade.
* @return The fade.
*/
public boolean isFade() {
return fade;
}
/**
* Gets the start pulse.
* @return the pulse.
*/
public Pulse getStartPulse() {
return startPulse;
}
public Pulse getEndPulse(){return new EndPulse();}
}
@@ -0,0 +1,126 @@
package core.game.content.activity.barrows;
import core.game.node.entity.Entity;
import core.game.node.entity.combat.BattleState;
import core.game.node.entity.combat.DeathTask;
import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.HintIconManager;
import core.game.world.map.Location;
import core.tools.RandomFunction;
/**
* Handles a barrow brother NPC.
* @author Emperor
*/
public final class BarrowBrother extends NPC {
/**
* The player to target.
*/
private final Player player;
/**
* Constructs a new {@code BarrowBrother} {@code Object}.
* @param player The target.
* @param id The NPC id.
* @param location The location.
*/
public BarrowBrother(Player player, int id, Location location) {
super(id, location);
this.player = player;
}
@Override
public void init() {
super.init();
super.setRespawn(false);
if (location.getZ() == 3) {
sendChat("You dare disturb my rest!");
} else {
sendChat("You dare steal from us!");
}
getProperties().getCombatPulse().attack(player);
HintIconManager.registerHintIcon(player, this);
}
@Override
public void handleTickActions() {
if (DeathTask.isDead(player)) {
return;
}
if (!player.isActive() || !player.getLocation().withinDistance(location)) {
clear();
return;
}
if (!getProperties().getCombatPulse().isAttacking()) {
getProperties().getCombatPulse().attack(player);
}
}
@Override
public void sendImpact(BattleState state) {
int maxHit = 0;
switch (getId()) {
case 2025:// ahrim
maxHit = 25;
break;
case 2026:// dharok
maxHit = 60;
break;
case 2027:// guthan
maxHit = 24;
break;
case 2028:// karil
maxHit = 20;
break;
case 2029:// torag
maxHit = 23;
break;
case 2030:// verac
maxHit = 25;
break;
}
if (state.getEstimatedHit() > maxHit) {
state.setEstimatedHit(RandomFunction.random(maxHit - 10, maxHit));
}
if (state.getSecondaryHit() > maxHit) {
state.setSecondaryHit(RandomFunction.random(maxHit - 10, maxHit));
}
}
@Override
public void finalizeDeath(Entity killer) {
super.finalizeDeath(killer);
if (killer == player) {
player.getSavedData().getActivityData().getBarrowBrothers()[getBrotherIndex()] = true;
BarrowsActivityPlugin.sendConfiguration(player);
}
}
@Override
public void clear() {
super.clear();
if (player.isActive()) {
player.getHintIconManager().clear();
}
player.removeAttribute("barrow:npc");
player.removeAttribute("brother:" + getBrotherIndex());
}
/**
* Gets the barrow brother index.
* @return The index.
*/
private int getBrotherIndex() {
return getId() - 2025;
}
/**
* Gets the player.
* @return The player.
*/
public Player getPlayer() {
return player;
}
}
@@ -0,0 +1,375 @@
package core.game.content.activity.barrows;
import core.game.component.Component;
import core.game.content.activity.ActivityPlugin;
import core.game.content.global.action.ClimbActionHandler;
import core.game.content.global.action.DoorActionHandler;
import core.plugin.Initializable;
import core.game.node.entity.skill.summoning.familiar.Familiar;
import core.game.interaction.Option;
import core.game.node.Node;
import core.game.node.entity.Entity;
import core.game.node.entity.combat.CombatStyle;
import core.game.node.entity.combat.DeathTask;
import core.game.node.entity.combat.ImpactHandler.HitsplatType;
import core.game.node.entity.npc.NPC;
import core.game.node.entity.npc.agg.AggressiveBehavior;
import core.game.node.entity.npc.agg.AggressiveHandler;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.ActivityData;
import core.game.node.object.GameObject;
import core.game.system.task.Pulse;
import core.game.world.GameWorld;
import core.game.world.map.Location;
import core.game.world.map.RegionManager;
import core.game.world.map.zone.ZoneBorders;
import core.game.world.update.flag.context.Graphics;
import core.net.packet.PacketRepository;
import core.net.packet.context.CameraContext;
import core.net.packet.context.MinimapStateContext;
import core.net.packet.context.CameraContext.CameraType;
import core.net.packet.out.CameraViewPacket;
import core.net.packet.out.MinimapState;
import core.plugin.PluginManager;
import core.tools.RandomFunction;
/**
* Handles the barrows activity plugin.
* @author Emperor
*/
@Initializable
public final class BarrowsActivityPlugin extends ActivityPlugin {
/**
* The tunnel configuration values.
*/
private static final int[] TUNNEL_CONFIGS = { 55328769, 2867201, 44582944, 817160, 537688072, 40763408, 44320784, 23478274 };
/**
* Represents the tunnels between 2 rooms in the barrows tunnels.
*/
public static final ZoneBorders[] MINI_TUNNELS = {
new ZoneBorders(3532, 9665, 3570, 9671),
new ZoneBorders(3575, 9676, 3570, 9671),
new ZoneBorders(3575, 9676, 3581, 9714),
new ZoneBorders(3534, 9718, 3570, 9723),
new ZoneBorders(3523, 9675, 3528, 9712),
new ZoneBorders(3541, 9711, 3545, 9712),
new ZoneBorders(3558, 9711, 3562, 9712),
new ZoneBorders(3568, 9701, 3569, 9705),
new ZoneBorders(3551, 9701, 3552, 9705),
new ZoneBorders(3534, 9701, 3535, 9705),
new ZoneBorders(3541, 9694, 3545, 9695),
new ZoneBorders(3558, 9694, 3562, 9695),
new ZoneBorders(3568, 9684, 3569, 9688),
new ZoneBorders(3551, 9684, 3552, 9688),
new ZoneBorders(3534, 9684, 3535, 9688),
new ZoneBorders(3541, 9677, 3545, 9678),
new ZoneBorders(3558, 9677, 3562, 9678),
};
/**
* The overlay.
*/
private static final Component OVERLAY = new Component(24);
/**
* The activity handling pulse.
*/
private static final Pulse PULSE = new Pulse(3) {
@Override
public boolean pulse() {
boolean end = true;
for (Player p : RegionManager.getRegionPlayers(14231)) {
end = false;
int index = p.getAttribute("barrow:drain-index", -1);
if (index > -1) {
p.removeAttribute("barrow:drain-index");
p.getPacketDispatch().sendItemOnInterface(-1, 1, 24, index);
continue;
}
if (p.getLocation().getZ() == 0 && p.getAttribute("barrow:looted", false)) {
if (RandomFunction.random(15) == 0) {
p.getImpactHandler().manualHit(p, RandomFunction.random(5), HitsplatType.NORMAL);
Graphics.send(Graphics.create(405), p.getLocation());
}
}
if (p.getLocks().isLocked("barrow:drain") || RandomFunction.random(100) % 2 == 0) {
continue;
}
int drain = 8;
for (boolean killed : p.getSavedData().getActivityData().getBarrowBrothers()) {
if (killed) {
drain += 1;
}
}
p.getSkills().decrementPrayerPoints(drain);
p.getLocks().lock("barrow:drain", (3 + RandomFunction.random(15)) * 3);
index = 1 + RandomFunction.random(6);
p.setAttribute("barrow:drain-index", index);
p.getPacketDispatch().sendItemZoomOnInterface(4761 + RandomFunction.random(12), 100, 24, index);
p.getPacketDispatch().sendAnimationInterface(9810, 24, index);
}
return end;
}
};
/**
* Constructs a new {@code BarrowsActivityPlugin} {@code Object}.
*/
public BarrowsActivityPlugin() {
super("Barrows", false, false, false);
}
@Override
public void locationUpdate(Entity e, Location last) {
if (e instanceof Player && e.getViewport().getRegion().getId() == 14231) {
boolean tunnel = false;
for (ZoneBorders border : MINI_TUNNELS) {
if (border.insideBorder(e)) {
tunnel = true;
break;
}
}
Player player = (Player) e;
if ((player.getConfigManager().get(1270) == 1) != tunnel) {
player.getConfigManager().set(1270, tunnel ? 3 : 0, true);//@emp: proper value seems to be 3, val of 1 makes corridors black
}
}
}
@Override
public boolean enter(Entity e) {
if (e instanceof Player) {
Player player = (Player) e;
PacketRepository.send(MinimapState.class, new MinimapStateContext(player, 2));
player.getInterfaceManager().openOverlay(OVERLAY);
player.getConfigManager().set(0, 1);
if (player.getConfigManager().get(452) == 0) {
shuffleCatacombs(player);
}
sendConfiguration(player);
if (!PULSE.isRunning()) {
PULSE.restart();
PULSE.start();
GameWorld.getPulser().submit(PULSE);
}
} else {
((NPC) e).setAggressive(true);
((NPC) e).setAggressiveHandler(new AggressiveHandler(e, new AggressiveBehavior() {
@Override
public boolean canSelectTarget(Entity entity, Entity target) {
if (!target.isActive() || DeathTask.isDead(target)) {
return false;
}
if (!target.getProperties().isMultiZone() && target.inCombat()) {
return false;
}
return true;
}
}));
}
return super.enter(e);
}
@Override
public boolean leave(Entity e, boolean logout) {
if (e instanceof Player) {
Player player = (Player) e;
PacketRepository.send(MinimapState.class, new MinimapStateContext(player, 0));
player.getInterfaceManager().closeOverlay();
NPC npc = player.getAttribute("barrow:npc");
if (npc != null && !DeathTask.isDead(npc)) {
npc.clear();
}
player.removeAttribute("barrow:solvedpuzzle");
player.removeAttribute("barrow:opened_chest");
player.removeAttribute("crusade-delay");
if (!logout && player.getAttribute("barrow:looted", false)) {
for (int i = 0; i < 6; i++) {
player.removeAttribute("brother:" + i);
player.getSavedData().getActivityData().getBarrowBrothers()[i] = false;
}
player.removeAttribute("barrow:looted");
shuffleCatacombs(player);
player.getSavedData().getActivityData().setBarrowTunnelIndex(RandomFunction.random(6));
player.getSavedData().getActivityData().setBarrowKills(0);
PacketRepository.send(CameraViewPacket.class, new CameraContext(player, CameraType.RESET, 0, 0, 0, 0, 0));
}
}
return super.leave(e, logout);
}
/**
* "Shuffles" the catacomb gates.
* @param player The player.
*/
public static void shuffleCatacombs(Player player) {
int value = TUNNEL_CONFIGS[RandomFunction.random(TUNNEL_CONFIGS.length)];
value |= 1 << (6 + RandomFunction.random(4));
player.getConfigManager().set(452, value);
}
@Override
public boolean death(Entity e, Entity killer) {
Player player = null;
if (killer instanceof Player) {
player = (Player) killer;
} else if (killer instanceof Familiar) {
player = ((Familiar) killer).getOwner();
}
if (player != null && e instanceof NPC) {
player.getSavedData().getActivityData().setBarrowKills(player.getSavedData().getActivityData().getBarrowKills() + 1);
sendConfiguration(player);
}
return false;
}
@Override
public boolean interact(Entity e, Node target, Option option) {
if (target instanceof GameObject) {
GameObject object = (GameObject) target;
Player player = (Player) e;
if (object.getId() >= 6702 && object.getId() <= 6707) {
ClimbActionHandler.climb((Player) e, ClimbActionHandler.CLIMB_UP, BarrowsCrypt.getCrypt(object.getId() - 6702).getExitLocation());
return true;
}
if (object.getId() >= 6708 && object.getId() <= 6712) {
ClimbActionHandler.climb((Player) e, ClimbActionHandler.CLIMB_UP, BarrowsCrypt.getCrypt(player.getSavedData().getActivityData().getBarrowTunnelIndex()).getEnterLocation());
return true;
}
switch (object.getWrapper().getId()) {
case 6727:
case 6724:
case 6746:
case 6743:
if (player.getAttribute("barrow:solvedpuzzle", false)) {
break;
}
player.setAttribute("barrow:puzzledoor", object);
BarrowsPuzzle.open(player);
return true;
}
switch (object.getId()) {
case 6714:
case 6733:
int index = -1;
for (int i = 0; i < player.getSavedData().getActivityData().getBarrowBrothers().length; i++) {
if (!player.getSavedData().getActivityData().getBarrowBrothers()[i] && RandomFunction.random(15) == 0 && !player.getAttribute("brother:" + i, false)) {
index = i;
break;
}
}
if (index > -1) {
BarrowsCrypt.getCrypt(index).spawnBrother(player, RegionManager.getTeleportLocation(target.getLocation(), 1));
}
DoorActionHandler.handleAutowalkDoor(e, (GameObject) target);
return true;
case 6821:
BarrowsCrypt.getCrypt(BarrowsCrypt.AHRIM).openSarcophagus((Player) e, object);
return true;
case 6771:
BarrowsCrypt.getCrypt(BarrowsCrypt.DHAROK).openSarcophagus((Player) e, object);
return true;
case 6773:
BarrowsCrypt.getCrypt(BarrowsCrypt.GUTHAN).openSarcophagus((Player) e, object);
return true;
case 6822:
BarrowsCrypt.getCrypt(BarrowsCrypt.KARIL).openSarcophagus((Player) e, object);
return true;
case 6772:
BarrowsCrypt.getCrypt(BarrowsCrypt.TORAG).openSarcophagus((Player) e, object);
return true;
case 6823:
BarrowsCrypt.getCrypt(BarrowsCrypt.VERAC).openSarcophagus((Player) e, object);
return true;
case 6774:
player.lock(1);
for (int i = 0; i < player.getSavedData().getActivityData().getBarrowBrothers().length; i++) {
if (!player.getSavedData().getActivityData().getBarrowBrothers()[i] && !player.getAttribute("brother:" + i, false)) {
BarrowsCrypt.getCrypt(i).spawnBrother(player, RegionManager.getTeleportLocation(target.getCenterLocation(), 4));
}
}
player.setAttribute("barrow:opened_chest", true);
sendConfiguration(player);
return true;
case 6775:
if (option.getName().equals("Close")) {
player.removeAttribute("barrow:opened_chest");
sendConfiguration(player);
return true;
}
if (player.getAttribute("barrow:looted", false)) {
player.getPacketDispatch().sendMessage("The chest is empty.");
return true;
}
player.setAttribute("/save:barrow:looted",true);
RewardChest.reward(player);
//PacketRepository.send(CameraViewPacket.class, new CameraContext(player, CameraType.SHAKE, 3, 2, 2, 2, 2));
return true;
}
}
return false;
}
/**
* Sends the kill count configuration.
* @param player The player.
*/
public static void sendConfiguration(Player player) {
ActivityData data = player.getSavedData().getActivityData();
int config = data.getBarrowKills() << 17;
for (int i = 0; i < data.getBarrowBrothers().length; i++) {
if (data.getBarrowBrothers()[i]) { // This actually wasn't in 498
// but we'll keep it anyways.
config |= 1 << i;
}
}
if (player.getAttribute("barrow:opened_chest", false)) {
config |= 1 << 16;
}
player.getConfigManager().set(453, config);
}
@Override
public boolean actionButton(Player player, int interfaceId, int buttonId, int slot, int itemId, int opcode) {
return false;
}
@Override
public boolean continueAttack(Entity e, Node target, CombatStyle style, boolean message) {
if (target instanceof BarrowBrother) {
Player p = null;
if (e instanceof Player) {
p = (Player) e;
} else if (e instanceof Familiar) {
p = ((Familiar) e).getOwner();
}
if (p != null && p != ((BarrowBrother) target).getPlayer()) {
p.getPacketDispatch().sendMessage("He's not after you.");
return false;
}
}
return super.continueAttack(e, target, style, message);
}
@Override
public ActivityPlugin newInstance(Player p) throws Throwable {
return this;
}
@Override
public Location getSpawnLocation() {
return null;
}
@Override
public void configure() {
PluginManager.definePlugin(new TunnelEntranceDialogue());
PluginManager.definePlugin(BarrowsPuzzle.SHAPES);
registerRegion(14231);
BarrowsCrypt.init();
PULSE.stop();
}
}
@@ -0,0 +1,191 @@
package core.game.content.activity.barrows;
import core.game.content.global.action.DigAction;
import core.game.content.global.action.DigSpadeHandler;
import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player;
import core.game.node.object.GameObject;
import core.game.world.map.Direction;
import core.game.world.map.Location;
import core.game.world.map.RegionManager;
/**
* Handles a barrows crypt.
* @author Emperor
*/
public final class BarrowsCrypt {
/**
* The ahrim barrows crypt index.
*/
public static final int AHRIM = 0;
/**
* The dharok barrows crypt index.
*/
public static final int DHAROK = 1;
/**
* The guthan barrows crypt index.
*/
public static final int GUTHAN = 2;
/**
* The karil barrows crypt index.
*/
public static final int KARIL = 3;
/**
* The torag barrows crypt index.
*/
public static final int TORAG = 4;
/**
* The verac barrows crypt index.
*/
public static final int VERAC = 5;
/**
* The barrows crypts.
*/
private static final BarrowsCrypt[] CRYPTS = { new BarrowsCrypt(AHRIM, 2025, Location.create(3557, 9703, 3), Location.create(3565, 3289, 0)), new BarrowsCrypt(DHAROK, 2026, Location.create(3556, 9718, 3), Location.create(3575, 3298, 0)), new BarrowsCrypt(GUTHAN, 2027, Location.create(3534, 9704, 3), Location.create(3577, 3283, 0)), new BarrowsCrypt(KARIL, 2028, Location.create(3546, 9684, 3), Location.create(3565, 3276, 0)), new BarrowsCrypt(TORAG, 2029, Location.create(3568, 9683, 3), Location.create(3553, 3283, 0)), new BarrowsCrypt(VERAC, 2030, Location.create(3578, 9706, 3), Location.create(3557, 3298, 0)) };
/**
* The NPC id.
*/
private final int npcId;
/**
* The location to teleport to when entering the crypt.
*/
private final Location location;
/**
* The exit location.
*/
private final Location exitLocation;
/**
* The crypt index.
*/
private final int index;
/**
* Constructs a new {@code BarrowsCrypt} {@code Object}.
* @param location The location to teleport to when entering the crypt.
* @param exitLocation The location to teleport to when leaving the crypt.
*/
public BarrowsCrypt(int index, int npcId, Location location, Location exitLocation) {
this.index = index;
this.npcId = npcId;
this.location = location;
this.exitLocation = exitLocation;
}
/**
* Initializes the barrow crypts.
*/
public static void init() {
for (final BarrowsCrypt crypt : CRYPTS) {
DigAction action = new DigAction() {
@Override
public void run(Player player) {
crypt.enter(player);
}
};
Location base = crypt.getExitLocation();
for (int x = -2; x <= 2; x++) {
for (int y = -2; y <= 2; y++) {
DigSpadeHandler.register(base.transform(x, y, 0), action);
}
}
}
}
/**
* Opens the sarcophagus.
* @param player The player.
*/
public void openSarcophagus(Player player, GameObject object) {
if (index == player.getSavedData().getActivityData().getBarrowTunnelIndex()) {
player.getDialogueInterpreter().open("barrow_tunnel", index);
return;
}
if (player.getSavedData().getActivityData().getBarrowBrothers()[index] || player.getAttribute("barrow:npc") != null) {
player.getPacketDispatch().sendMessage("You don't find anything.");
return;
}
player.getPacketDispatch().sendMessage("You don't find anything.");
Location location = RegionManager.getTeleportLocation(object.getLocation().transform(Direction.SOUTH_WEST), object.getSizeX() + 1, object.getSizeY() + 1);
spawnBrother(player, location);
}
/**
* Spawns the barrow brother.
* @param player The player.
* @param location The location.
* @return {@code True} if successful.
*/
public boolean spawnBrother(Player player, Location location) {
if (player.getAttribute("brother:" + index, false)) {
return false;
}
NPC npc = new BarrowBrother(player, npcId, location);
npc.init();
player.setAttribute("barrow:npc", npc);
player.setAttribute("brother:" + index, true);
return true;
}
/**
* Enters the crypt.
* @param player The player.
*/
protected void enter(Player player) {
player.addExtension(BarrowsCrypt.class, this);
player.getPacketDispatch().sendMessage("You've broken into a crypt!");
player.getProperties().setTeleportLocation(getEnterLocation());
}
/**
* Gets the crypt for the given index.
* @param index The crypt index.
* @return The barrows crypt.
*/
public static BarrowsCrypt getCrypt(int index) {
return CRYPTS[index];
}
/**
* Gets the location to teleport to upon entering.
* @return The location.
*/
public Location getEnterLocation() {
return location;
}
/**
* Gets the exit location.
* @return The location.
*/
public Location getExitLocation() {
return exitLocation;
}
/**
* Gets the npcId.
* @return The npcId.
*/
public int getNpcId() {
return npcId;
}
/**
* Gets the index.
* @return The index.
*/
public int getIndex() {
return index;
}
}
@@ -0,0 +1,169 @@
package core.game.content.activity.barrows;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import core.game.component.Component;
import core.game.component.ComponentDefinition;
import core.game.component.ComponentPlugin;
import core.game.node.entity.player.Player;
import core.net.packet.PacketRepository;
import core.net.packet.context.DisplayModelContext;
import core.net.packet.context.DisplayModelContext.ModelType;
import core.net.packet.out.DisplayModel;
import core.plugin.Plugin;
import core.tools.RandomFunction;
/**
* Handles the barrows puzzle.
* @author Emperor
*/
public final class BarrowsPuzzle extends ComponentPlugin {
/**
* The shapes puzzle.
*/
public static final BarrowsPuzzle SHAPES = new BarrowsPuzzle(new int[] { 6734, 6735, 6736 }, getAnswerModel(6731, true), getAnswerModel(6732, false), getAnswerModel(6733, false));
/**
* The lines puzzle.
*/
public static final BarrowsPuzzle LINES = new BarrowsPuzzle(new int[] { 6728, 6729, 6730 }, getAnswerModel(6725, true), getAnswerModel(6726, false), getAnswerModel(6727, false));
/**
* The squares puzzle.
*/
public static final BarrowsPuzzle SQUARES = new BarrowsPuzzle(new int[] { 6722, 6723, 6724 }, getAnswerModel(6719, true), getAnswerModel(6720, false), getAnswerModel(6721, false));
/**
* The triangle-on-circles puzzle.
*/
public static final BarrowsPuzzle TRIANGLE_CIRCLES = new BarrowsPuzzle(new int[] { 6716, 6717, 6718 }, getAnswerModel(6713, true), getAnswerModel(6714, false), getAnswerModel(6715, false));
/**
* The puzzle component.
*/
private static final Component COMPONENT = new Component(25);
/**
* The question models.
*/
private final int[] questionModels;
/**
* The answer models.
*/
private final int[] answerModels;
/**
* Constructs a new {@code BarrowsPuzzle} {@code Object}.
* @param questionModels The question models.
* @param answerModels The answer models.
*/
private BarrowsPuzzle(int[] questionModels, int... answerModels) {
this.questionModels = questionModels;
this.answerModels = answerModels;
}
/**
* Creates a new barrows puzzle instance of this puzzle.
* @return The new barrows puzzle instance.
*/
public BarrowsPuzzle create() {
int[] answers = Arrays.copyOf(answerModels, answerModels.length);
List<Integer> list = new ArrayList<>();
for (int answer : answers) {
list.add(answer);
}
Collections.shuffle(list, new Random());
for (int i = 0; i < list.size(); i++) {
answers[i] = list.get(i);
}
return new BarrowsPuzzle(questionModels, answers);
}
/**
* Opens a random barrows puzzle.
* @param player The player.
*/
public static void open(Player player) {
int index = RandomFunction.random(4);
if (index == player.getAttribute("puzzle:index", -1)) {
index = (index + 1) % 4;
}
open(player, index);
}
/**
* Opens the barrows puzzle for the given index.
* @param player The player.
* @param index The index (0 = shapes, 1 = lines, 2 = squares, 3 =
* triangle-on-circle).
*/
public static void open(Player player, int index) {
BarrowsPuzzle puzzle = SHAPES;
switch (index) {
case 1:
puzzle = LINES;
break;
case 2:
puzzle = SQUARES;
break;
case 3:
puzzle = TRIANGLE_CIRCLES;
break;
}
puzzle = puzzle.create();
player.setAttribute("puzzle:index", index);
player.setAttribute("puzzle:answers", puzzle.answerModels);
player.getInterfaceManager().open(COMPONENT);
for (int i = 0; i < puzzle.questionModels.length; i++) {
PacketRepository.send(DisplayModel.class, new DisplayModelContext(player, ModelType.MODEL, puzzle.questionModels[i], 0, 25, 6 + i));
}
for (int i = 0; i < puzzle.answerModels.length; i++) {
PacketRepository.send(DisplayModel.class, new DisplayModelContext(player, ModelType.MODEL, puzzle.answerModels[i] & 0xFFFF, 0, 25, 2 + i));
}
PacketRepository.send(DisplayModel.class, new DisplayModelContext(player, ModelType.MODEL, puzzle.answerModels[2] & 0xFFFF, 0, 25, 5));
}
/**
* Gets the answer model id.
* @param modelId The model id.
* @param correct If the answer is correct.
* @return The model id hash.
*/
private static int getAnswerModel(int modelId, boolean correct) {
return modelId | (correct ? 1 : 0) << 16;
}
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
ComponentDefinition.put(25, this);
return this;
}
@Override
public boolean handle(Player player, Component component, int opcode, int button, int slot, int itemId) {
switch (button) {
case 2:
case 3:
case 5:
player.getInterfaceManager().close();
boolean correct = ((player.getAttribute("puzzle:answers", new int[3])[button == 5 ? 2 : button - 2] >> 16) & 0xFF) == 1;
if (!correct) {
player.getPacketDispatch().sendMessage("You got the puzzle wrong! You can hear the catacombs moving around you.");
BarrowsActivityPlugin.shuffleCatacombs(player);
break;
}
player.setAttribute("/save:barrow:solvedpuzzle", true);
player.getPacketDispatch().sendMessage("You hear the doors' locking mechanism grind open.");
break;
default:
return false;
}
return true;
}
}
@@ -0,0 +1,83 @@
package core.game.content.activity.barrows;
import core.game.content.dialogue.DialogueInterpreter;
import core.game.content.dialogue.DialoguePlugin;
import core.game.node.entity.player.Player;
import core.game.world.map.Location;
import core.plugin.PluginManifest;
import core.plugin.PluginType;
/**
* The tunnel entrance dialogue handling plugin.
* @author Emperor
*/
@PluginManifest(type = PluginType.DIALOGUE)
public final class TunnelEntranceDialogue extends DialoguePlugin {
/**
* The crypt index.
*/
@SuppressWarnings("unused")
private int index;
/**
* Constructs a new {@code TunnelEntranceDialogue} {@code Object}.
*/
public TunnelEntranceDialogue() {
super();
}
/**
* Constructs a new {@code TunnelEntranceDialogue} {@code Object}.
* @param player The player.
*/
public TunnelEntranceDialogue(Player player) {
super(player);
}
@Override
public DialoguePlugin newInstance(Player player) {
return new TunnelEntranceDialogue(player);
}
@Override
public boolean open(Object... args) {
this.index = (Integer) args[0];
player.getDialogueInterpreter().sendPlainMessage(false, "You find a hidden tunnel, do you want to enter?");
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
if (stage++ == 0) {
player.getDialogueInterpreter().sendOptions(null, "Yeah, I'm fearless!", "No way, that looks scary!");
return true;
}
switch (buttonId) {
case 1:
int offsetX = 0;
int offsetY = 0;
int configValue = player.getConfigManager().get(452);
if ((configValue & (1 << 7)) != 0) {
offsetX = 34;
offsetY = 34;
} else if ((configValue & (1 << 6)) != 0) {
offsetY = 34;
} else if ((configValue & (1 << 9)) != 0) {
offsetX = 34;
}
int x = 3534 + offsetX;
int y = 9677 + offsetY;
player.getProperties().setTeleportLocation(Location.create(x, y, 0));
case 2:
end();
return true;
}
return false;
}
@Override
public int[] getIds() {
return new int[] { DialogueInterpreter.getDialogueKey("barrow_tunnel") };
}
}
@@ -0,0 +1,80 @@
package core.game.content.activity.bountyhunter;
import core.cache.def.impl.ObjectDefinition;
import core.game.content.activity.ActivityManager;
import core.game.interaction.OptionHandler;
import core.game.node.Node;
import core.game.node.entity.player.Player;
import core.game.node.object.GameObject;
import core.game.system.task.Pulse;
import core.game.world.GameWorld;
import core.game.world.update.flag.context.Animation;
import core.plugin.Plugin;
/**
* Handles the bounty hunter options.
* @author Emperor
*/
public final class BHOptionHandler extends OptionHandler {
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
ObjectDefinition.forId(28110).getHandlers().put("option:exit", this);
ObjectDefinition.forId(28119).getHandlers().put("option:enter", this);
ObjectDefinition.forId(28120).getHandlers().put("option:enter", this);
ObjectDefinition.forId(28121).getHandlers().put("option:enter", this);
ObjectDefinition.forId(28122).getHandlers().put("option:exit", this);
ObjectDefinition.forId(28115).getHandlers().put("option:view", this);
ObjectDefinition.forId(28116).getHandlers().put("option:view", this);
return this;
}
@Override
public boolean handle(final Player player, Node node, String option) {
GameObject object = (GameObject) node;
final BountyHunterActivity activity = player.getExtension(BountyHunterActivity.class);
switch (object.getId()) {
case 28119:
ActivityManager.start(player, "BH low_level", false);
return true;
case 28120:
ActivityManager.start(player, "BH mid_level", false);
return true;
case 28121:
ActivityManager.start(player, "BH high_level", false);
return true;
case 28115:
BHScoreBoard.getRogues().open(player);
return true;
case 28116:
BHScoreBoard.getHunters().open(player);
return true;
case 28122:
if (activity == null) {
return false;
}
if (player.getAttribute("exit_penalty", 0) > GameWorld.getTicks()) {
player.getPacketDispatch().sendMessage("You can't leave the crater until the exit penalty is over.");
return true;
}
player.lock(2);
GameWorld.getPulser().submit(new Pulse(1) {
@Override
public boolean pulse() {
player.getProperties().setTeleportLocation(activity.getType().getExitLocation());
return true;
}
});
player.animate(Animation.create(7376));
return true;
case 28110:
if (activity == null) {
return false;
}
activity.leaveWaitingRoom(player, false);
return true;
}
return false;
}
}
@@ -0,0 +1,161 @@
package core.game.content.activity.bountyhunter;
import java.nio.ByteBuffer;
import core.cache.ServerStore;
import core.cache.StoreFile;
import core.cache.misc.buffer.ByteBufferUtils;
import core.game.component.Component;
import core.game.node.entity.player.Player;
import core.tools.StringUtils;
/**
* The score board.
* @author Emperor
*/
public final class BHScoreBoard {
/**
* The score board size.
*/
private static final int SIZE = 10;
/**
* The names.
*/
private String[] names = new String[SIZE];
/**
* The scores.
*/
private int[] scores = new int[SIZE];
/**
* The bounty hunters scoreboard.
*/
private static final BHScoreBoard HUNTERS = new BHScoreBoard();
/**
* The bounty hunter rogues scoreboard.
*/
private static final BHScoreBoard ROGUES = new BHScoreBoard();
/**
* Constructs a new {@code BHScoreBoard} {@code Object}.
*/
public BHScoreBoard() {
for (int i = 0; i < SIZE; i++) {
names[i] = "Nobody yet";
}
}
/**
* Initializes the score boards data.
*/
public static void init() {
StoreFile file = ServerStore.get("bh_scores");
if (file == null) { // Indicates no cache exists yet.
return;
}
ByteBuffer buffer = file.data();
for (int i = 0; i < SIZE; i++) {
HUNTERS.scores[i] = buffer.getInt();
HUNTERS.names[i] = ByteBufferUtils.getString(buffer);
}
for (int i = 0; i < SIZE; i++) {
ROGUES.scores[i] = buffer.getInt();
ROGUES.names[i] = ByteBufferUtils.getString(buffer);
}
}
/**
* Updates the store file for the scores.
*/
public static void update() {
ByteBuffer buffer = ByteBuffer.allocate(500);
for (int i = 0; i < SIZE; i++) {
buffer.putInt(HUNTERS.scores[i]);
ByteBufferUtils.putString(HUNTERS.names[i], buffer);
}
for (int i = 0; i < SIZE; i++) {
buffer.putInt(ROGUES.scores[i]);
ByteBufferUtils.putString(ROGUES.names[i], buffer);
}
buffer.flip();
ServerStore.setArchive("bh_scores", buffer);
}
/**
* Opens the score board.
* @param player The player.
*/
public void open(Player player) {
int component = 654;
if (this == ROGUES) {
component = 655;
}
player.getInterfaceManager().open(new Component(component));
for (int i = 0; i < SIZE; i++) {
player.getPacketDispatch().sendString(StringUtils.formatDisplayName(names[i]), component, 15 + i);
player.getPacketDispatch().sendString(Integer.toString(scores[i]), component, 25 + i);
}
}
/**
* Checks if the ratings of the player is good enough for the score board.
* @param player The player.
*/
public void check(Player player) {
int score = player.getSavedData().getActivityData().getBountyHunterRate();
if (this == ROGUES) {
score = player.getSavedData().getActivityData().getBountyRogueRate();
}
for (int i = 0; i < SIZE; i++) {
if (score > scores[i]) {
insert(player, score, i);
update();
break;
}
}
}
/**
* Inserts the player in the score board.
* @param player The player.
* @param score The score.
* @param index The board index.
*/
private void insert(Player player, int score, int index) {
if (names[index].equals(player.getName())) {
scores[index] = score;
return;
}
for (int i = SIZE - 2; i >= index; i--) {
String name = names[i];
if (name.equals(player.getName())) {
name = names[--i];
}
scores[i + 1] = scores[i];
names[i + 1] = name;
}
names[index] = player.getName();
scores[index] = score;
}
/**
* Gets the rogues.
* @return The rogues.
*/
public static BHScoreBoard getRogues() {
return ROGUES;
}
/**
* Gets the hunters.
* @return The hunters.
*/
public static BHScoreBoard getHunters() {
return HUNTERS;
}
}
@@ -0,0 +1,105 @@
package core.game.content.activity.bountyhunter;
import core.game.node.entity.player.Player;
import core.game.world.GameWorld;
/**
* Holds a player's bounty hunter data.
* @author Emperor
*/
public final class BountyEntry {
/**
* The target.
*/
private Player target;
/**
* The player hunting this player.
*/
private Player hunter;
/**
* Constructs a new {@code BountyEntry} {@code Object}.
*/
public BountyEntry() {
/*
* empty.
*/
}
/**
* Updates the overlay.
* @param player The player.
*/
public void update(Player player) {
String name = "No one";
if (target != null) {
name = target.getUsername();
}
player.getPacketDispatch().sendString(name, 653, 7);
updatePenalty(player, false);
}
/**
* Updates the current penalty.
* @param player The player.
* @param unlock If the components should be unlocked.
*/
public void updatePenalty(Player player, boolean unlock) {
int penalty = player.getAttribute("pickup_penalty", 0);
int child = -1;
if (GameWorld.getTicks() > penalty) {
player.removeAttribute("pickup_penalty");
player.getPacketDispatch().sendInterfaceConfig(653, 8, true);
} else if (penalty != 0) {
child = 8;
int seconds = (int) Math.round((penalty - GameWorld.getTicks()) * 0.6);
player.getPacketDispatch().sendString(seconds + " Sec", 653, 10);
}
penalty = player.getAttribute("exit_penalty", 0);
if (GameWorld.getTicks() > penalty) {
player.removeAttribute("exit_penalty");
player.getPacketDispatch().sendInterfaceConfig(653, 11, true);
} else if (penalty != 0) {
child = 11;
int seconds = (int) Math.round((penalty - GameWorld.getTicks()) * 0.6);
player.getPacketDispatch().sendString(seconds + " Sec", 653, 13);
}
if (unlock && child > -1) {
player.getPacketDispatch().sendInterfaceConfig(653, child, false);
}
}
/**
* Gets the target.
* @return The target.
*/
public Player getTarget() {
return target;
}
/**
* Sets the target.
* @param target The target to set.
*/
public void setTarget(Player target) {
this.target = target;
}
/**
* Gets the hunter.
* @return The hunter.
*/
public Player getHunter() {
return hunter;
}
/**
* Sets the hunter.
* @param hunter The hunter to set.
*/
public void setHunter(Player hunter) {
this.hunter = hunter;
}
}
@@ -0,0 +1,639 @@
package core.game.content.activity.bountyhunter;
import core.game.component.Component;
import core.game.component.ComponentDefinition;
import core.game.component.ComponentPlugin;
import core.game.container.Container;
import core.game.container.ContainerEvent;
import core.game.container.ContainerListener;
import core.game.content.activity.ActivityManager;
import core.game.content.activity.ActivityPlugin;
import core.game.interaction.Option;
import core.game.node.Node;
import core.game.node.entity.Entity;
import core.game.node.entity.combat.CombatStyle;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.HintIconManager;
import core.game.node.entity.player.link.prayer.PrayerType;
import core.game.node.item.GroundItem;
import core.game.node.item.Item;
import core.game.system.task.Pulse;
import core.game.world.GameWorld;
import core.game.world.map.Location;
import core.game.world.map.Point;
import core.game.world.map.zone.ZoneBorders;
import core.game.world.map.zone.ZoneRestriction;
import core.game.world.map.zone.impl.MultiwayCombatZone;
import core.game.world.map.zone.impl.WildernessZone;
import core.game.world.update.flag.context.Animation;
import core.plugin.Initializable;
import core.plugin.Plugin;
import core.plugin.PluginManager;
import core.tools.RandomFunction;
import java.util.*;
/**
* Handles the Bounty hunter activity.
* @author Emperor
*/
@Initializable
public final class BountyHunterActivity extends ActivityPlugin {
/**
* The skull values.
*/
private static final int[] SKULL_VALUES = { 100_000, // Bronze skull
500_000, // Iron skull
1_100_000, // Adamant skull
2_500_000, // Runite skull
-1 // Dragon skull
};
/**
* The exit offsets.
*/
private static final Point[] EXIT_OFFSETS = { new Point(19, 58), new Point(24, 44), new Point(29, 34), new Point(36, 22), new Point(52, 17), new Point(14, 72), new Point(15, 85), new Point(17, 127), new Point(14, 133), new Point(19, 151), new Point(38, 163), new Point(49, 170), new Point(64, 20), new Point(84, 16), new Point(106, 18), new Point(69, 176), new Point(85, 176), new Point(127, 174), new Point(130, 21), new Point(138, 33), new Point(155, 48), new Point(163, 53), new Point(172, 60), new Point(174, 64), new Point(176, 106), new Point(178, 84), new Point(155, 169), new Point(162, 162), new Point(163, 153), new Point(173, 136) };
/**
* The minimum amount of players to enter the crater.
*/
private static final int MINIMUM_PLAYERS = 2;
/**
* The waiting room overlay.
*/
private static final Component WAITING_OVERLAY = new Component(656);
/**
* The game overlay.
*/
private static final Component GAME_OVERLAY = new Component(653);
/**
* The player in the current crater.
*/
final Map<Player, BountyEntry> players = new HashMap<>();
/**
* The waiting room.
*/
private final List<Player> waitingRoom = new ArrayList<>();
/**
* The crater type.
*/
private final CraterType type;
/**
* The amount of time to wait in the waiting room.
*/
private int waitingTime = 166;
/**
* The waiting room pulse.
*/
private final Pulse waitRoomPulse = new Pulse(1) {
@Override
public boolean pulse() {
String time = Integer.toString((int) Math.round(waitingTime-- * 0.6)) + " Sec";
for (Player player : waitingRoom) {
player.getPacketDispatch().sendString(time, 656, 10);
}
if (waitingTime == -1) {
for (Iterator<Player> it = waitingRoom.iterator(); it.hasNext();) {
enterCrater(it.next());
it.remove();
}
return true;
}
return false;
}
@Override
public void stop() {
super.stop();
waitingTime = 166;
}
};
/**
* The game pulse (doesn't update every tick on 2009scape as well).
*/
private final Pulse gamePulse = new Pulse(10) {
@Override
public boolean pulse() {
for (Player player : players.keySet()) {
BountyEntry entry = players.get(player);
if (entry.getTarget() == null) {
findTarget(player);
}
entry.updatePenalty(player, false);
}
return false;
}
};
/**
* Constructs a new {@code BountyHunterActivity} {@code Object}.
*/
public BountyHunterActivity() {
this(CraterType.LOW_LEVEL);
}
/**
* Constructs a new {@code BountyHunterActivity} {@code Object}.
*/
public BountyHunterActivity(CraterType type) {
super("BH " + type.name().toLowerCase(), false, false, false, ZoneRestriction.FOLLOWERS);
this.type = type;
}
@Override
public void register() {
waitRoomPulse.stop();
gamePulse.stop();
if (getType() == CraterType.LOW_LEVEL) {
// Disable bounty hunter area as wilderness
Location check = Location.create(3166, 3679, 0);
for (ZoneBorders border : WildernessZone.getInstance().getBorders()) {
if (border.insideBorder(check)) {
/* if (GameWorld.getSettings().isPvp()) {
border.addException(new ZoneBorders(2924, 3306, 3078, 3404));
}*/
border.addException(new ZoneBorders(3140, 3653, 3149, 3670));
border.addException(new ZoneBorders(3150, 3656, 3154, 3676));
border.addException(new ZoneBorders(3155, 3661, 3164, 3686));
border.addException(new ZoneBorders(3165, 3667, 3173, 3693));
border.addException(new ZoneBorders(3174, 3673, 3192, 3705));
border.addException(new ZoneBorders(3193, 3681, 3196, 3709));
break;
}
}
PluginManager.definePlugin(new ComponentPlugin() {
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
ComponentDefinition.put(657, this);
return this;
}
@Override
public boolean handle(Player player, Component component, int opcode, int button, int slot, int itemId) {
if (button == 18) {
player.getInterfaceManager().close();
player.lock(1);
BountyHunterActivity activity = player.getExtension(BountyHunterActivity.class);
if (activity.players.isEmpty()) {
activity.joinWaitingRoom(player);
return true;
}
activity.enterCrater(player);
}
return true;
}
});
BHScoreBoard.init();
PluginManager.definePlugin(new BountyLocateSpell());
PluginManager.definePlugin(new BHOptionHandler());
ActivityManager.register(new BountyHunterActivity(CraterType.MID_LEVEL));
ActivityManager.register(new BountyHunterActivity(CraterType.HIGH_LEVEL));
}
}
@Override
public boolean start(Player player, boolean login, Object... args) {
if (player.getFamiliarManager().hasFamiliar()) {
player.getPacketDispatch().sendMessage("You can't bring a follower into the crater.");
return false;
}
if (!getType().canEnter(player)) {
return false;
}
player.addExtension(BountyHunterActivity.class, this);
if (!login) {
player.getInterfaceManager().open(new Component(657));
} else {
enterCrater(player);
}
return true;
}
@Override
public boolean enter(Entity e) {
if (e instanceof Player && getType().getZone().insideBorder(e.getLocation()) || e instanceof Player) {
if (e.getAttribute("viewing_orb") != null) {
return super.enter(e);
}
Player player = (Player) e;
for (int i = 0; i < type.ordinal(); i++) {
if (!player.getMusicPlayer().hasUnlockedIndex(517 + i)) {
player.getMusicPlayer().unlock(444 - i, false);
}
}
player.addExtension(BountyHunterActivity.class, this);
BountyEntry entry = new BountyEntry();
players.put(player, entry);
player.getInterfaceManager().openOverlay(GAME_OVERLAY);
int penalty;
if ((penalty = player.getAttribute("pickup_penalty", 0)) != 0) {
player.setAttribute("/save:pickup_penalty", GameWorld.getTicks() + penalty);
}
if ((penalty = player.getAttribute("exit_penalty", 0)) != 0) {
player.setAttribute("/save:exit_penalty", GameWorld.getTicks() + penalty);
if (player.getPrayer().get(PrayerType.PROTECT_ITEMS)) {
player.getPrayer().toggle(PrayerType.PROTECT_ITEMS);
}
}
findTarget(player);
entry.updatePenalty(player, true);
player.getInteraction().set(Option._P_ATTACK);
player.getInteraction().remove(Option._P_ASSIST);
player.getSkullManager().setSkullCheckDisabled(true);
player.getSkullManager().setWilderness(true);
player.setAttribute("bh_joined", GameWorld.getTicks() + 10);
updateSkull(player);
if (!gamePulse.isRunning()) {
gamePulse.start();
GameWorld.getPulser().submit(gamePulse);
}
}
return super.enter(e);
}
@Override
public boolean leave(Entity e, boolean logout) {
if (e instanceof Player) {
Player player = (Player) e;
player.removeExtension(BountyHunterActivity.class);
if (waitingRoom.contains(player)) {
leaveWaitingRoom(player, logout);
}
BountyEntry entry = players.get(player);
if (entry != null) {
leaveCrater(player, logout, entry);
}
}
return super.leave(e, logout);
}
@Override
public boolean interact(Entity e, Node target, Option option) {
if (target instanceof GroundItem && option.getName().equals("take")) {
return actionButton((Player) e, 192, 19, -1, -1, 55);
}
if (target instanceof Item && option.getName().equals("drop")) {
if (((Item) target).getValue() > 1000) {
((Player) e).getPacketDispatch().sendMessage("This item is too valuable to drop in the crater.");
return true;
}
}
return false;
}
@Override
public boolean ignoreMultiBoundaries(Entity attacker, Entity victim) {
if (attacker instanceof Player) {
BountyEntry entry = players.get(attacker);
return entry != null && entry.getTarget() == victim;
}
return false;
}
@SuppressWarnings("deprecation")
@Override
public boolean actionButton(Player player, int interfaceId, int buttonId, int slot, int itemId, int opcode) {
if (interfaceId == 192 && buttonId == 19) {
BountyEntry entry = players.get(player);
if (entry != null && player.getAttribute("pickup_penalty", 0) > GameWorld.getTicks()) {
player.getPacketDispatch().sendMessage("You should not be picking up items. Now you must wait before you can leave.");
player.removeAttribute("pickup_penalty");
player.setAttribute("/save:exit_penalty", GameWorld.getTicks() + 300);
entry.updatePenalty(player, true);
if (player.getPrayer().get(PrayerType.PROTECT_ITEMS)) {
player.getPrayer().toggle(PrayerType.PROTECT_ITEMS);
}
}
} else if (interfaceId == 271 && buttonId == 25) {
if (player.getAttribute("exit_penalty", 0) > GameWorld.getTicks()) {
player.getPacketDispatch().sendMessage("You can't use the protect item prayer until your penalty has passed.");
player.getConfigManager().send(PrayerType.PROTECT_ITEMS.getConfig(), 0);
return true;
}
}
return false;
}
@Override
public boolean continueAttack(Entity e, Node target, CombatStyle style, boolean message) {
if (e instanceof Player && target instanceof Player) {
if (((Player) target).getAttribute("bh_joined", -1) > GameWorld.getTicks()) {
((Player) e).getPacketDispatch().sendMessage("This player has only just entered and is temporarily invulnerable to attacks.");
return false;
}
e.removeAttribute("bh_joined");
}
return true;
}
/**
* Updates the skull.
* @param player The player.
*/
private void updateSkull(final Player player) {
if (player.getAttribute("value_listener") == null) {
ContainerListener listener = new ContainerListener() {
@Override
public void update(Container c, ContainerEvent event) {
refresh(c);
}
@Override
public void refresh(Container c) {
updateSkull(player);
}
};
player.setAttribute("value_listener", listener);
player.getInventory().getListeners().add(listener);
player.getEquipment().getListeners().add(listener);
}
long value = 0;
for (Item item : player.getInventory().toArray()) {
if (item != null) {
value += item.getValue();
}
}
for (Item item : player.getEquipment().toArray()) {
if (item != null) {
value += item.getValue();
}
}
int skull = 2;
if (value >= 0) {
for (int i = 0; i < SKULL_VALUES.length - 1; i++) {
if (value < SKULL_VALUES[i]) {
skull = 6 - i;
break;
}
}
}
player.getSkullManager().setSkulled(true);
player.getAppearance().setSkullIcon(skull);
player.getAppearance().sync();
}
/**
* Enters the bounty hunter crater.
* @param player The player.
*/
public void enterCrater(Player player) {
Point offset = RandomFunction.getRandomElement(EXIT_OFFSETS);
Location destination = Location.create(getType().getZone().getSouthWestX() + offset.getX(), getType().getZone().getSouthWestY() + offset.getY(), 0);
player.getProperties().setTeleportLocation(destination);
player.animate(Animation.create(7377));
}
/**
* Leaves the bounty hunter crater.
* @param player The player.
* @param logout If the player has logged out.
* @param entry The player's bounty entry.
*/
public void leaveCrater(Player player, boolean logout, BountyEntry entry) {
if (entry.getHunter() != null) {
BountyEntry other = players.get(entry.getHunter());
if (other != null) {
entry.getHunter().getPacketDispatch().sendMessage("Your target has " + (logout ? "logged out" : "left") + ". You shall be found a new target.");
other.setTarget(null);
findTarget(entry.getHunter());
}
}
if (entry.getTarget() != null) {
BountyEntry other = players.get(entry.getTarget());
if (other != null) {
other.setHunter(null);
}
}
player.getHintIconManager().clear();
players.remove(player);
ContainerListener listener = player.getAttribute("value_listener");
if (listener != null) {
player.getInventory().getListeners().remove(listener);
player.getEquipment().getListeners().remove(listener);
}
player.getAppearance().setSkullIcon(-1);
player.getAppearance().sync();
player.getInteraction().remove(Option._P_ATTACK);
player.getInteraction().set(Option._P_ASSIST);
player.getSkullManager().setSkullCheckDisabled(false);
player.getSkullManager().setWilderness(false);
player.getInterfaceManager().closeOverlay();
if (players.isEmpty()) {
gamePulse.stop();
}
int penalty;
if ((penalty = player.getAttribute("pickup_penalty", 0)) > GameWorld.getTicks()) {
player.setAttribute("/save:pickup_penalty", penalty - GameWorld.getTicks());
} else {
player.removeAttribute("pickup_penalty");
}
if ((penalty = player.getAttribute("exit_penalty", 0)) > GameWorld.getTicks()) {
player.setAttribute("/save:exit_penalty", penalty - GameWorld.getTicks());
} else {
player.removeAttribute("exit_penalty");
}
player.getSkullManager().setSkulled(false);
}
/**
* Joins the waiting room.
* @param player The player.
*/
private void joinWaitingRoom(Player player) {
waitingRoom.add(player);
player.getProperties().setTeleportLocation(getType().getRoomLocation());
player.getInterfaceManager().openOverlay(WAITING_OVERLAY);
player.getPacketDispatch().sendString("Players waiting (need " + MINIMUM_PLAYERS + "):", 656, 6);
updateWaitingRoomSize();
if (waitingRoom.size() == MINIMUM_PLAYERS) {
String time = (int) Math.round(waitingTime * 0.6) + " Sec";
for (Player p : waitingRoom) {
player.getPacketDispatch().sendString(time, 656, 10);
p.getPacketDispatch().sendInterfaceConfig(656, 9, false);
p.getPacketDispatch().sendInterfaceConfig(656, 8, false);
}
if (!waitRoomPulse.isRunning()) {
waitRoomPulse.start();
GameWorld.getPulser().submit(waitRoomPulse);
}
} else if (waitingRoom.size() > MINIMUM_PLAYERS) {
player.getPacketDispatch().sendString((int) Math.round(waitingTime * 0.6) + " Sec", 656, 10);
player.getPacketDispatch().sendInterfaceConfig(656, 9, false);
player.getPacketDispatch().sendInterfaceConfig(656, 8, false);
}
}
/**
* Leaves the waiting room.
* @param player The player.
*/
@SuppressWarnings("deprecation")
public void leaveWaitingRoom(Player player, boolean logout) {
waitingRoom.remove(player);
if (waitingRoom.size() < MINIMUM_PLAYERS && waitRoomPulse.isRunning()) {
waitRoomPulse.stop();
for (Player p : waitingRoom) {
p.getPacketDispatch().sendInterfaceConfig(656, 9, true);
p.getPacketDispatch().sendInterfaceConfig(656, 8, true);
}
}
updateWaitingRoomSize();
player.getProperties().setTeleportLocation(getType().getExitLocation());
player.getInterfaceManager().closeOverlay();
if (logout) {
player.setLocation(getType().getExitLocation());
}
}
/**
* Finds a target for the specified player.
* @param player The player.
*/
private void findTarget(Player player) {
Player target = null;
BountyEntry other = null;
int difference = 999;
for (Player p : players.keySet()) {
if (p == player) {
continue;
}
BountyEntry entry = players.get(p);
if (entry.getHunter() == null) {
int diff = Math.abs(player.getProperties().getCurrentCombatLevel() - p.getProperties().getCurrentCombatLevel());
if (diff < difference) {
difference = diff;
target = p;
other = entry;
}
}
}
if (other != null) {
other.setHunter(player);
HintIconManager.registerHintIcon(player, target);
} else {
player.getHintIconManager().clear();
}
BountyEntry entry = players.get(player);
entry.setTarget(target);
entry.update(player);
}
/**
* Updates the amount of players in the waiting room.
*/
private void updateWaitingRoomSize() {
String size = Integer.toString(waitingRoom.size());
for (Player player : waitingRoom) {
player.getPacketDispatch().sendString(size, 656, 7);
}
}
@Override
public boolean canLogout(Player player) {
if (player.getAttribute("exit_penalty", 0) > GameWorld.getTicks()) {
player.getPacketDispatch().sendMessage("You can't logout until the exit penalty is over.");
return false;
}
return true;
}
@Override
public boolean death(Entity e, Entity killer) {
if (e instanceof Player) {
Player player = (Player) e;
BountyEntry entry = players.get(player);
if (entry != null) {
if (entry.getHunter() != killer && killer instanceof Player) {
handleRogueKill((Player) killer, player, entry);
} else if (entry.getHunter() == killer) { // "They" is not a
// typo, this was
// the actual
// message on RS.
entry.getHunter().getPacketDispatch().sendMessage("You killed " + player.getUsername() + ". They were your target, so your Hunter PvP rating increases!");
entry.getHunter().getSavedData().getActivityData().updateBountyHunterRate(1);
BHScoreBoard.getHunters().check(entry.getHunter());
} else if (entry.getHunter() != null) {
entry.getHunter().getPacketDispatch().sendMessage("Your target has died. You shall be found a new target.");
}
if (entry.getHunter() != null) {
BountyEntry other = players.get(entry.getHunter());
if (other != null) {
other.setTarget(null);
}
entry.setHunter(null);
}
player.getHintIconManager().clear();
if (player.getAttribute("pickup_penalty", 0) != 0) {
player.setAttribute("pickup_penalty", GameWorld.getTicks() - 5);
}
if (player.getAttribute("exit_penalty", 0) != 0) {
player.setAttribute("exit_penalty", GameWorld.getTicks() - 5);
}
entry.updatePenalty((Player) e, true);
}
}
return false;
}
/**
* Handles a rogue kill.
* @param player The player who killed the victim.
* @param victim The victim.
*/
private void handleRogueKill(Player player, Player victim, BountyEntry entry) {
player.getPacketDispatch().sendMessage("You killed " + victim.getUsername() + ". They were not your target, so your Rogue PvP rating");
player.getPacketDispatch().sendMessage("increases!");
player.getPacketDispatch().sendMessage("This means you get the pick-up penalty: pick anything up and you can't leave!");
player.getSavedData().getActivityData().updateBountyRogueRate(1);
BHScoreBoard.getRogues().check(player);
player.setAttribute("/save:pickup_penalty", GameWorld.getTicks() + 300);
entry.updatePenalty(player, true);
}
@Override
public boolean teleport(Entity e, int type, Node node) {
if (e instanceof Player && type != -1) {
((Player) e).getPacketDispatch().sendMessage("A magical force stops you from teleporting.");
return false;
}
return true;
}
@Override
public ActivityPlugin newInstance(Player p) throws Throwable {
return this;
}
@Override
public Location getSpawnLocation() {
return Location.create(3166, 3679, 0);
}
@Override
public void configure() {
registerRegion(6234);
register(getType().getZone());
int x = getType().getZone().getSouthWestX();
int y = getType().getZone().getSouthWestY();
MultiwayCombatZone.getInstance().register(new ZoneBorders(x + 56, y + 40, x + 140, y + 140));
}
/**
* Gets the type.
* @return The type.
*/
public CraterType getType() {
return type;
}
}
@@ -0,0 +1,98 @@
package core.game.content.activity.bountyhunter;
import core.game.node.entity.skill.magic.MagicSpell;
import core.game.node.entity.skill.magic.Runes;
import core.game.interaction.MovementPulse;
import core.game.node.Node;
import core.game.node.entity.Entity;
import core.game.node.entity.combat.equipment.SpellType;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.SpellBookManager.SpellBook;
import core.game.node.entity.player.link.TeleportManager.TeleportType;
import core.game.node.entity.state.EntityState;
import core.game.node.item.Item;
import core.game.world.GameWorld;
import core.game.world.map.Location;
import core.game.world.map.RegionManager;
import core.plugin.Plugin;
/**
* Handles the bounty target locate spell.
* @author Emperor
*/
public final class BountyLocateSpell extends MagicSpell {
/**
* Constructs a new {@code BountyLocateSpell} {@code Object}.
*/
public BountyLocateSpell() {
super(SpellBook.MODERN, 32, 45, null, null, null, new Item[] { Runes.AIR_RUNE.getItem(1), Runes.FIRE_RUNE.getItem(1), Runes.LAW_RUNE.getItem(1) });
}
@Override
public boolean cast(Entity entity, Node target) {
BountyHunterActivity activity = entity.getExtension(BountyHunterActivity.class);
Player player = (Player) entity;
if (activity == null) {
player.getPacketDispatch().sendMessage("You can only use this spell in the Bounty Hunter craters.");
return false;
}
BountyEntry entry = activity.players.get(player);
if (entry == null || entry.getTarget() == null) {
player.getPacketDispatch().sendMessage("You don't have a target to teleport to.");
return true;
}
if (player.getStateManager().hasState(EntityState.FROZEN) || player.getStateManager().hasState(EntityState.STUNNED)) {
player.getPacketDispatch().sendMessage("You can't use this when " + (player.getStateManager().hasState(EntityState.STUNNED) ? "stunned." : "frozen."));
return true;
}
boolean combat = player.inCombat();
if (!super.meetsRequirements(entity, true, combat)) {
return false;
}
if (combat) {
player.getPacketDispatch().sendMessage("You were fighting recently so you'll run instead of teleport.");
target = entry.getTarget();
Location location = entry.getTarget().getLocation();
if (!location.withinDistance(player.getLocation(), 30)) {
int offsetX = location.getX() - player.getLocation().getX();
int offsetY = location.getY() - player.getLocation().getY();
if (offsetX > 30) {
offsetX = 30;
} else if (offsetX < -30) {
offsetX = -30;
}
if (offsetY > 30) {
offsetY = 30;
} else if (offsetY < -30) {
offsetY = -30;
}
target = player.getLocation().transform(offsetX, offsetY, 0);
}
player.getPulseManager().run(new MovementPulse(player, target) {
@Override
public boolean pulse() {
return true;
}
}, "movement");
return true;
}
Location destination = RegionManager.getTeleportLocation(entry.getTarget().getLocation(), 5);
if (entity.getTeleporter().send(destination, TeleportType.NORMAL, -1)) {
if (!super.meetsRequirements(entity, true, true)) {
entity.getTeleporter().getCurrentTeleport().stop();
return false;
}
entity.setAttribute("magic-delay", GameWorld.getTicks() + 5);
return true;
}
return false;
}
@Override
public Plugin<SpellType> newInstance(SpellType arg) throws Throwable {
SpellBook.MODERN.register(60, this);
return this;
}
}
@@ -0,0 +1,131 @@
package core.game.content.activity.bountyhunter;
import core.game.node.entity.player.Player;
import core.game.world.map.Location;
import core.game.world.map.zone.ZoneBorders;
/**
* Represents the crater types.
* @author Emperor
*/
public enum CraterType {
/**
* The low level crater.
*/
LOW_LEVEL(3, Location.create(1548, 5804, 0), Location.create(1548, 5804, 0), Location.create(3152, 3672, 0), new ZoneBorders(2688, 5632, 2879, 5823)),
/**
* The mid level crater.
*/
MID_LEVEL(50, Location.create(1558, 5785, 0), Location.create(1548, 5804, 0), Location.create(3158, 3680, 0), new ZoneBorders(2944, 5632, 3135, 5823)),
/**
* The high level crater.
*/
HIGH_LEVEL(95, Location.create(1570, 5804, 0), Location.create(1548, 5804, 0), Location.create(3164, 3685, 0), new ZoneBorders(3200, 5632, 3391, 5823));
/**
* The level required to enter the crater.
*/
private final int level;
/**
* The waiting room location.
*/
private final Location roomLocation;
/**
* The crater location.
*/
private final Location craterLocation;
/**
* The exit location.
*/
private final Location exitLocation;
/**
* The zone borders.
*/
private final ZoneBorders zone;
/**
* Constructs a new {@code CraterType} {@code Object}. The level required to
* enter the crater.
* @param roomLocation The location of the waiting room.
* @param craterLocation The location of the crater.
* @param exitLocation The location to go the when exiting.
* @param zone The crater zone.
*/
private CraterType(int level, Location roomLocation, Location craterLocation, Location exitLocation, ZoneBorders zone) {
this.level = level;
this.roomLocation = roomLocation;
this.craterLocation = craterLocation;
this.exitLocation = exitLocation;
this.zone = zone;
}
/**
* Checks if the player can enter the crater.
* @param player The player.
* @return {@code True} if so.
*/
public boolean canEnter(Player player) {
int combatLevel = player.getProperties().getCurrentCombatLevel();
if (player.getIronmanManager().checkRestriction()) {
return false;
}
if (ordinal() < CraterType.values().length - 1) {
if (combatLevel > CraterType.values()[ordinal() + 1].level + 5) {
player.getPacketDispatch().sendMessage("Your combat level has to be below " + (CraterType.values()[ordinal() + 1].level + 5) + " to enter this crater.");
return false;
}
}
if (combatLevel < level) {
player.getPacketDispatch().sendMessage("You need a combat level of " + level + " to enter this crater.");
return false;
}
return true;
}
/**
* Gets the level requirement.
* @return The level requirement.
*/
public int getLevel() {
return level;
}
/**
* Gets the roomLocation.
* @return The roomLocation.
*/
public Location getRoomLocation() {
return roomLocation;
}
/**
* Gets the craterLocation.
* @return The craterLocation.
*/
public Location getCraterLocation() {
return craterLocation;
}
/**
* Gets the exitLocation.
* @return The exitLocation.
*/
public Location getExitLocation() {
return exitLocation;
}
/**
* Gets the zone.
* @return The zone.
*/
public ZoneBorders getZone() {
return zone;
}
}
@@ -0,0 +1,87 @@
package core.game.content.activity.clanwars;
import core.game.content.activity.ActivityManager;
import core.game.interaction.Option;
import core.game.interaction.OptionHandler;
import core.game.node.Node;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.request.RequestModule;
import core.game.node.entity.player.link.request.RequestType;
import core.game.system.communication.ClanRank;
import core.plugin.Plugin;
/**
* Handles the Clan wars challenge option.
* @author Emperor
* @versuib 1,9
*/
public final class CWChallengeOption extends OptionHandler {
/**
* The challenge option.
*/
public static final Option OPTION = new Option("Challenge", 0);
/**
* The request type.
*/
private static final RequestType REQUEST_TYPE = new RequestType("Sending challenge request...", ":clanreq:", getModule()) {
@Override
public boolean canRequest(Player player, Player target) {
if (player.getCommunication().getClan() == null) {
player.getPacketDispatch().sendMessage("You have to be in a clan to challenge players.");
return false;
}
if (player.getCommunication().getClan().getRank(player).ordinal() < ClanRank.CAPTAIN.ordinal()) {
player.getPacketDispatch().sendMessage("Your clan rank is not high enough to challenge other clans.");
return false;
}
if (player.getCommunication().getClan().getClanWar() != null) {
player.getPacketDispatch().sendMessage("Your clan is already in a war.");
return false;
}
if (target.getCommunication().getClan() == null) {
player.getPacketDispatch().sendMessage("This player is not in a clan.");
return false;
}
if (target.getCommunication().getClan().getRank(target).ordinal() < ClanRank.CAPTAIN.ordinal()) {
player.getPacketDispatch().sendMessage("This player's clan rank is not high enough to accept challenges.");
return false;
}
if (target.getCommunication().getClan().getClanWar() != null) {
player.getPacketDispatch().sendMessage("This player's clan is already in a war.");
return false;
}
if (target.getCommunication().getClan() == player.getCommunication().getClan()) {
player.getPacketDispatch().sendMessage("You can't challenge someone from your own clan.");
return false;
}
return true;
}
};
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
OPTION.setHandler(this);
return this;
}
@Override
public boolean handle(Player player, Node node, String option) {
player.getRequestManager().request((Player) node, REQUEST_TYPE);
return true;
}
/**
* Gets the request module.
* @return The module.
*/
private static RequestModule getModule() {
return new RequestModule() {
@Override
public void open(Player player, Player target) {
ActivityManager.start(player, "Clan wars", false, target);
}
};
}
}
@@ -0,0 +1,497 @@
package core.game.content.activity.clanwars;
import java.util.ArrayList;
import java.util.List;
import core.game.component.Component;
import core.game.content.activity.ActivityPlugin;
import core.plugin.Initializable;
import core.game.node.entity.skill.summoning.familiar.Familiar;
import core.game.node.entity.skill.summoning.pet.Pet;
import core.game.interaction.Option;
import core.game.interaction.OptionHandler;
import core.game.node.Node;
import core.game.node.entity.Entity;
import core.game.node.entity.combat.CombatStyle;
import core.game.node.entity.impl.PulseManager;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.ConfigurationManager.Configuration;
import core.game.node.object.GameObject;
import core.game.node.object.ObjectBuilder;
import core.game.system.communication.ClanEntry;
import core.game.system.communication.ClanRepository;
import core.game.system.task.Pulse;
import core.game.world.GameWorld;
import core.game.world.map.Location;
import core.game.world.map.RegionManager;
import core.game.world.map.build.DynamicRegion;
import core.game.world.map.zone.RegionZone;
import core.game.world.map.zone.ZoneBorders;
import core.game.world.map.zone.ZoneType;
import core.game.world.map.zone.impl.MultiwayCombatZone;
import core.game.world.update.flag.chunk.AnimateObjectUpdateFlag;
import core.game.world.update.flag.context.Animation;
import core.plugin.Plugin;
import core.tools.RandomFunction;
/**
* Handles the clan wars activity.
* @author Emperor
*/
@Initializable
public final class ClanWarsActivityPlugin extends ActivityPlugin {
/**
* The first clan.
*/
private ClanRepository firstClan;
/**
* The second clan.
*/
private ClanRepository secondClan;
/**
* The first clan's players.
*/
private List<Player> firstClanPlayers = new ArrayList<>();
/**
* The second clan's players.
*/
private List<Player> secondClanPlayers = new ArrayList<>();
/**
* The list of viewing players.
*/
private List<Player> viewingPlayers = new ArrayList<>();
/**
* The amount of ticks.
*/
private int ticks;
/**
* The updating pulse.
*/
private Pulse pulse;
/**
* The attack option.
*/
private static final Option ATTACK_OPTION = new Option("Attack", 0).setHandler(new OptionHandler() {
@Override
public boolean handle(Player player, Node node, String option) {
player.getPulseManager().clear("interaction:attack:" + node.hashCode());
player.getProperties().getCombatPulse().attack(node);
return true;
}
@Override
public boolean isWalk() {
return false;
}
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
return this;
}
@Override
public boolean isDelayed(Player player) {
return false;
}
});
/**
* Constructs a new {@code ClanWarsActivityPlugin} {@code Object}.
*/
public ClanWarsActivityPlugin() {
super("Clan wars", true, false, true);
}
@Override
public boolean start(Player player, boolean login, Object... args) {
Player other = (Player) args[0];
firstClan = player.getCommunication().getClan();
secondClan = other.getCommunication().getClan();
firstClan.setClanWar(this);
secondClan.setClanWar(this);
sendWarDeclaration(firstClan.getPlayers());
sendWarDeclaration(secondClan.getPlayers());
handleWall();
join(player);
join(other);
return true;
}
/**
* Handles the wall in the middle of the battlefield.
*/
private void handleWall() {
int offset = 0;
for (int x = 5; x < 54; x++) {
offset = (offset + 1) % 3;
ObjectBuilder.add(new GameObject(28174 + offset, base.transform(x, 64, 0)));
}
GameWorld.getPulser().submit(pulse = new Pulse(200) {
@Override
public boolean pulse() {
for (int x = 5; x < 54; x++) {
Location l = base.transform(x, 64, 0);
GameObject object = RegionManager.getObject(l);
if (object != null) {
Animation anim = Animation.create(7386 + ((object.getId() - 28174) % 3));
anim.setObject(object);
RegionManager.getRegionChunk(l).flag(new AnimateObjectUpdateFlag(anim));
}
}
GameWorld.getPulser().submit(new Pulse(5) {
@Override
public boolean pulse() {
for (int x = 5; x < 54; x++) {
Location l = base.transform(x, 64, 0);
GameObject object = RegionManager.getObject(l);
if (object != null) {
ObjectBuilder.remove(object);
}
}
return true;
}
});
super.setTicksPassed(250);
sendGameData();
if (firstClanPlayers.isEmpty() || secondClanPlayers.isEmpty()) {
finishWar();
}
return true;
}
});
}
/**
* Ends the war.
*/
public void finishWar() {
firstClan.setClanWar(null);
secondClan.setClanWar(null);
int firstInterfaceId = firstClanPlayers.isEmpty() ? 650 : 651;
int secondInterfaceId = firstClanPlayers.isEmpty() ? 651 : 650;
String[] message = new String[] { "Your clan has been defeated!", "Your clan is victorious!" };
for (Player p : firstClanPlayers) {
p.getProperties().setTeleportLocation(getLeaveLocation());
p.getInterfaceManager().openComponent(firstInterfaceId);
p.getPacketDispatch().sendMessage(message[firstInterfaceId - 650]);
p.fullRestore();
PulseManager.cancelDeathTask(p);
}
for (Player p : secondClanPlayers) {
p.getProperties().setTeleportLocation(getLeaveLocation());
p.getInterfaceManager().openComponent(secondInterfaceId);
p.getPacketDispatch().sendMessage(message[secondInterfaceId - 650]);
p.fullRestore();
PulseManager.cancelDeathTask(p);
}
for (Player p : viewingPlayers) {
p.getProperties().setTeleportLocation(getLeaveLocation());
if (p.getCommunication().getClan() == firstClan) {
p.getInterfaceManager().openComponent(firstInterfaceId);
p.getPacketDispatch().sendMessage(message[firstInterfaceId - 650]);
} else {
p.getInterfaceManager().openComponent(secondInterfaceId);
p.getPacketDispatch().sendMessage(message[secondInterfaceId - 650]);
}
}
}
/**
* Sends the game data for all players in the game.
*/
public void sendGameData() {
for (Player p : firstClanPlayers) {
sendGameData(p);
}
for (Player p : secondClanPlayers) {
sendGameData(p);
}
for (Player p : viewingPlayers) {
sendGameData(p);
}
}
/**
* Sends the game data for the player.
* @param p The player.
*/
public void sendGameData(Player p) {
int value = 0;
boolean first = p.getCommunication().getClan() == firstClan;
String name = firstClan.getName();
if (first) {
value |= firstClanPlayers.size() << 5;
value |= secondClanPlayers.size() << 14;
} else {
name = secondClan.getName();
value |= secondClanPlayers.size() << 5;
value |= firstClanPlayers.size() << 14;
}
if (pulse.getTicksPassed() < 200) {
value |= (200 - pulse.getTicksPassed()) << 23;
}
p.getConfigManager().set(Configuration.CLAN_WAR_DATA, value);
p.getPacketDispatch().sendString(name, 265, 2);
}
@Override
public boolean teleport(Entity e, int type, Node node) {
if (type != -1 && type != 2 && e instanceof Player) {
((Player) e).getPacketDispatch().sendMessage("You can't teleport away from a war.");
return false;
}
return true;
}
@Override
public boolean enter(Entity e) {
if (e instanceof Player) {
Player player = (Player) e;
player.getInteraction().set(ATTACK_OPTION);
player.getInteraction().remove(Option._P_ASSIST);
player.getSkullManager().setSkullCheckDisabled(true);
player.getSkullManager().setWilderness(true);
player.getInterfaceManager().openOverlay(new Component(265));
} else if (e instanceof Familiar && !(e instanceof Pet)) {
Familiar familiar = (Familiar) e;
if (familiar.isCombatFamiliar()) {
familiar.transform(familiar.getOriginalId() + 1);
}
}
return true;
}
@Override
public boolean death(Entity e, Entity killer) {
if (e instanceof Player) {
return enterViewingRoom((Player) e);
}
return false;
}
/**
* Enters the viewing room.
* @param player The player.
* @return {@code True} if successfully entered the viewing room.
*/
public boolean enterViewingRoom(Player player) {
Location destination = null;
if (player.getCommunication().getClan() == firstClan) {
remove(player, firstClanPlayers);
destination = base.transform(55 + RandomFunction.randomize(3), 51 + RandomFunction.randomize(11), 0);
} else if (player.getCommunication().getClan() == secondClan) {
remove(player, secondClanPlayers);
destination = base.transform(55 + RandomFunction.randomize(3), 66 + RandomFunction.randomize(11), 0);
} else {
return false;
}
player.getProperties().setTeleportLocation(destination);
viewingPlayers.add(player);
sendGameData();
return true;
}
@Override
public boolean continueAttack(Entity e, Node target, CombatStyle style, boolean message) {
if (e instanceof Familiar) {
e = ((Familiar) e).getOwner();
}
if (target instanceof Familiar) {
target = ((Familiar) target).getOwner();
}
if (e instanceof Player && target instanceof Player) {
Player player = (Player) e;
Player other = (Player) target;
ClanRepository clan = player.getCommunication().getClan();
if (pulse.isRunning()) {
player.getPacketDispatch().sendMessage("The war hasn't started yet.");
return false;
}
if (!firstClanPlayers.contains(player) && !secondClanPlayers.contains(player)) {
return false;
}
if (other.getCommunication().getClan() == clan) {
player.getPacketDispatch().sendMessage("You can only attack players in a different clan.");
return false;
}
if (!firstClanPlayers.contains(other) && !secondClanPlayers.contains(other)) {
player.getPacketDispatch().sendMessage("You can't attack this player.");
return false;
}
}
return true;
}
/**
* Removes the player from the game.
* @param player The player.
* @param players The players list.
*/
public void remove(Player player, List<Player> players) {
players.remove(player);
if (!pulse.isRunning() && players.isEmpty()) {
finishWar();
}
}
@Override
public boolean interact(Entity e, Node target, Option option) {
if (target instanceof GameObject) {
GameObject object = (GameObject) target;
if (object.getId() == 28214 || object.getId() == 28140) {
e.getProperties().setTeleportLocation(getLeaveLocation());
return true;
}
}
return false;
}
@Override
public boolean leave(Entity e, boolean logout) {
if (e instanceof Player) {
Player player = (Player) e;
player.getInterfaceManager().closeOverlay();
player.getInteraction().remove(ATTACK_OPTION);
if (firstClanPlayers.contains(player)) {
remove(player, firstClanPlayers);
} else if (secondClanPlayers.contains(player)) {
remove(player, secondClanPlayers);
} else {
viewingPlayers.remove(player);
}
sendGameData();
player.getSkullManager().setSkullCheckDisabled(false);
player.getSkullManager().setWilderness(false);
if (logout) {
e.setLocation(getLeaveLocation());
}
} else if (e instanceof Familiar && !(e instanceof Pet)) {
Familiar familiar = (Familiar) e;
if (familiar.isCombatFamiliar()) {
familiar.reTransform();
}
}
return true;
}
@Override
public Object fireEvent(String identifier, Object... args) {
if (identifier.equals("join")) {
join((Player) args[0]);
return true;
}
if (identifier.equals("leavefc")) {
Player p = (Player) args[0];
p.getProperties().setTeleportLocation(getLeaveLocation());
return true;
}
return null;
}
/**
* Gets the leaving location.
* @return The leaving location.
*/
private static Location getLeaveLocation() {
Location l = Location.create(3265 + RandomFunction.randomize(13), 3675 + RandomFunction.randomize(18), 0);
while (!RegionManager.isTeleportPermitted(l)) {
l = l.transform(1, 1, 0);
}
return l;
}
/**
* Makes the player join the game.
* @param player The player.
*/
public void join(Player player) {
if (!pulse.isRunning()) {
enterViewingRoom(player);
return;
}
boolean first = player.getCommunication().getClan() == firstClan;
if (first) {
if (firstClanPlayers.contains(player)) {
return;
}
firstClanPlayers.add(player);
player.getProperties().setTeleportLocation(base.transform(34 + RandomFunction.randomize(4), 10, 0));
} else {
if (secondClanPlayers.contains(player)) {
return;
}
secondClanPlayers.add(player);
player.getProperties().setTeleportLocation(base.transform(26 + RandomFunction.randomize(4), 118, 0));
}
sendGameData();
}
/**
* Sends messages to the list of players.
* @param players The players list.
*/
private static void sendWarDeclaration(List<ClanEntry> players) {
Location check = Location.create(3272, 3682, 0);
for (ClanEntry e : players) {
Player p = e.getPlayer();
if (p.getLocation().withinDistance(check, 128)) {
p.getPacketDispatch().sendMessage("<col=ff0000>Your clan has been challenged to a clan war!");
p.getPacketDispatch().sendMessage("<col=ff0000>Step through the purple portal in the Challenge Hall.");
p.getPacketDispatch().sendMessage("<col=ff0000>Battle will commence in 2 minutes.");
}
}
}
@Override
public void configure() {
setZoneType(ZoneType.SAFE.getId());
DynamicRegion[] regions = DynamicRegion.create(new ZoneBorders(3264, 3712, 3328, 3840));
setRegionBase(regions);
int x = base.getX();
int y = base.getY() + 20;
RegionZone multi = new RegionZone(MultiwayCombatZone.getInstance(), new ZoneBorders(x, y, x + 63, y + 88));
for (DynamicRegion r : regions) {
r.setMulticombat(true);
r.getRegionZones().add(multi);
r.setRegionTimeOut(250);
r.setMusicId(442);
}
}
@Override
public Location getSpawnLocation() {
return null;
}
@Override
public ActivityPlugin newInstance(Player p) throws Throwable {
return new ClanWarsActivityPlugin();
}
/**
* Gets the ticks.
* @return The ticks.
*/
public int getTicks() {
return ticks;
}
/**
* Sets the ticks.
* @param ticks The ticks to set.
*/
public void setTicks(int ticks) {
this.ticks = ticks;
}
}
@@ -0,0 +1,98 @@
package core.game.content.activity.clanwars;
import core.game.interaction.Option;
import core.game.node.Node;
import core.game.node.entity.Entity;
import core.game.node.entity.player.Player;
import core.game.node.object.GameObject;
import core.game.world.map.zone.MapZone;
import core.game.world.map.zone.ZoneBorders;
import core.game.world.map.zone.ZoneBuilder;
import core.game.world.map.zone.ZoneRestriction;
import core.game.world.map.zone.impl.WildernessZone;
import core.plugin.Initializable;
import core.plugin.Plugin;
import core.plugin.PluginManager;
/**
* Handles the clan wars challenge room.
* @author Emperor
*/
@Initializable
public final class ClanWarsChallengeRoom extends MapZone implements Plugin<Object> {
/**
* Constructs a new {@code ClanWarsChallengeRoom} {@code Object}.
*/
public ClanWarsChallengeRoom() {
super("clan wars cr", true, ZoneRestriction.RANDOM_EVENTS);
}
@Override
public void configure() {
register(new ZoneBorders(3264, 3672, 3279, 3695));
}
@Override
public boolean enter(Entity e) {
if (e instanceof Player) {
Player p = (Player) e;
p.getSkullManager().setWildernessDisabled(true);
p.getSkullManager().setWilderness(false);
p.getInterfaceManager().closeOverlay();
p.getInteraction().remove(Option._P_ASSIST);
p.getInteraction().set(CWChallengeOption.OPTION);
}
return super.enter(e);
}
@Override
public boolean leave(final Entity e, final boolean logout) {
if (e instanceof Player) {
Player p = (Player) e;
p.getSkullManager().setWildernessDisabled(false);
p.getInteraction().remove(CWChallengeOption.OPTION);
p.getInteraction().set(Option._P_ASSIST);
if (WildernessZone.isInZone(e)) {
WildernessZone.show(p);
p.getSkullManager().setWilderness(true);
}
}
return super.leave(e, logout);
}
@Override
public boolean interact(Entity e, Node target, Option option) {
if (target instanceof GameObject) {
GameObject object = (GameObject) target;
Player player = (Player) e;
if (object.getId() == 28213) {
if (player.getCommunication().getClan() == null) {
player.getPacketDispatch().sendMessage("You have to be in a clan to enter this portal.");
} else if (player.getCommunication().getClan().isDefault()) {
player.sendMessage("You can't use the main clan chat for this.");
return true;
} else if (player.getCommunication().getClan().getClanWar() == null) {
player.getPacketDispatch().sendMessage("Your clan has to be in a war.");
} else {
player.getCommunication().getClan().getClanWar().fireEvent("join", player);
}
return true;
}
}
return false;
}
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
ZoneBuilder.configure(this);
PluginManager.definePlugin(new CWChallengeOption());
return this;
}
@Override
public Object fireEvent(String identifier, Object... args) {
return null;
}
}
@@ -0,0 +1,39 @@
package core.game.content.activity.duel;
import core.game.interaction.OptionHandler;
import core.game.node.Node;
import core.game.node.entity.player.Player;
import core.plugin.Plugin;
/**
* Handles the challenge option for dueling.
* @author Vexia
*
*/
public class ChallengeOptionPlugin extends OptionHandler {
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
DuelArenaActivity.CHALLENGE_OPTION.setHandler(this);
return this;
}
@Override
public boolean handle(Player player, Node node, String option) {
Player other = (Player) node;
if (other.getInterfaceManager().isOpened() || other.getExtension(DuelSession.class) != null) {
player.getPacketDispatch().sendMessage("Other player is busy at the moment.");
return true;
}
if (other.getRequestManager().getTarget() == player && other.getAttribute("duel:partner") == player) {
player.getRequestManager().request(other, other.getAttribute("duel:staked", false) ? DuelArenaActivity.STAKE_REQUEST : DuelArenaActivity.FRIEND_REQUEST);
return true;
}
player.getInterfaceManager().open(DuelArenaActivity.DUEL_TYPE_SELECT);
player.setAttribute("duel:staked", false);
player.setAttribute("duel:partner", other);
player.getConfigManager().set(283, 1 << 26);
return true;
}
}
@@ -0,0 +1,595 @@
package core.game.content.activity.duel;
import java.util.ArrayList;
import java.util.List;
import core.ServerConstants;
import core.cache.def.impl.ObjectDefinition;
import core.game.container.Container;
import core.game.container.impl.EquipmentContainer;
import core.game.content.dialogue.DialogueAction;
import core.game.node.entity.skill.summoning.familiar.Familiar;
import core.game.interaction.Option;
import core.game.interaction.OptionHandler;
import core.game.node.Node;
import core.game.node.entity.Entity;
import core.game.node.entity.combat.CombatStyle;
import core.game.node.entity.combat.equipment.WeaponInterface;
import core.game.node.entity.impl.PulseManager;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.HintIconManager;
import core.game.node.entity.player.link.prayer.PrayerType;
import core.game.node.item.GroundItem;
import core.game.node.item.GroundItemManager;
import core.game.node.item.Item;
import core.game.system.task.Pulse;
import core.game.world.GameWorld;
import core.game.world.map.Location;
import core.game.world.map.RegionManager;
import core.game.world.map.zone.MapZone;
import core.game.world.map.zone.ZoneBorders;
import core.game.world.map.zone.ZoneRestriction;
import core.plugin.Plugin;
import core.tools.RandomFunction;
import core.tools.StringUtils;
/**
* Represents a dueling area.
* @author Vexia
*
*/
public class DuelArea extends MapZone {
/**
* The respawn locations.
*/
public static final Location[] RESPAWN_LOCATIONS = new Location[] { Location.create(3371, 3275, 0), Location.create(3365, 3276, 0), Location.create(3366, 3274, 0), Location.create(3369, 3274, 0), Location.create(3372, 3275, 0), Location.create(3372, 3266, 0), Location.create(3371, 3269, 0), Location.create(3376, 3270, 0), Location.create(3376, 3273, 0), Location.create(3377, 3275, 0) };
/**
* The zone borders set for the area.
*/
private final ZoneBorders border;
/**
* If this area has obstacles.
*/
private final boolean obstacles;
/**
* The center location to determine starting points.
*/
private final Location center;
/**
* The fight option.
*/
private static final Option FIGHT_OPTION = new Option("Fight", 0).setHandler(new OptionHandler() {
@Override
public boolean handle(Player player, Node node, String option) {
player.getPulseManager().clear("interaction:attack:" + node.hashCode());
player.getProperties().getCombatPulse().attack(node);
return true;
}
@Override
public boolean isWalk() {
return false;
}
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
return this;
}
@Override
public boolean isDelayed(Player player) {
return false;
}
});
/**
* Constructs a new {@Code DuelArea} {@Code Object}
*/
public DuelArea() {
this(-1, null, false, null);
}
/**
* Constructs a new {@Code DuelArea} {@Code Object}
* @param index the index.
* @param border the border.
* @param obstacles if there is obstacles.
*/
public DuelArea(int index, ZoneBorders border, boolean obstacles, Location center) {
super("Duel Area - " + index, true, ZoneRestriction.FIRES, ZoneRestriction.CANNON, ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.FOLLOWERS);
this.obstacles = obstacles;
this.border = border;
this.center = center;
}
/**
* Starts a duel between two players.
* @param session the session.
*/
public void duel(final DuelSession session) {
Location[] locations = getStartLocations(session);
session.getPlayer().teleport(locations[0]);
session.getOther().teleport(locations[1]);
session.getPlayer().getInterfaceManager().close();
session.getPlayer().getInterfaceManager().restoreTabs();
session.getOther().getInterfaceManager().close();
session.getOther().getInterfaceManager().restoreTabs();
session.getPlayer().setAttribute("duel:icon", HintIconManager.registerHintIcon(session.getPlayer(), session.getOther()));
session.getOther().setAttribute("duel:icon", HintIconManager.registerHintIcon(session.getOther(), session.getPlayer()));
session.getPlayer().setAttribute("duel:ammo", new ArrayList<GroundItem>());
session.getOther().setAttribute("duel:ammo", new ArrayList<GroundItem>());
session.getPlayer().setAttribute("vengeance", false);
session.getOther().setAttribute("vengeance", false);
GameWorld.getPulser().submit(new Pulse(4, session.getPlayer(), session.getOther()) {
int count;
@Override
public boolean pulse() {
String chat = count < 3 ? String.valueOf(3 - count) : "FIGHT!";
session.getPlayer().sendChat(chat);
session.getOther().sendChat(chat);
return count++ >= 3;
}
@Override
public void stop() {
super.stop();
if (session.getPlayer().isActive() && session.getOther().isActive() && session.getFightState() != 2) {
session.setFightState(1);
session.getPlayer().getSkullManager().setSkullCheckDisabled(true);
session.getPlayer().getSkullManager().setWilderness(true);
session.getOther().getSkullManager().setSkullCheckDisabled(true);
session.getOther().getSkullManager().setWilderness(true);
session.getPlayer().getProperties().setMultiZone(true);
session.getOther().getProperties().setMultiZone(true);
}
}
});
}
@Override
public boolean interact(Entity e, Node target, Option option) {
if (!e.isPlayer()) {
return true;
}
Player p = e.asPlayer();
final DuelSession session = getSession(p);
if (session == null) {
return true;
}
if (option.getName().equalsIgnoreCase("eat") && session.hasRule(DuelRule.NO_FOOD)) {
p.sendMessage("You can't eat in this fight.");
return true;
}
if (option.getName().equalsIgnoreCase("drink") && session.hasRule(DuelRule.NO_DRINKS)) {
p.sendMessage("You can't drink in this fight.");
return true;
}
if (option.getName().equalsIgnoreCase("wield") || option.getName().equalsIgnoreCase("wear") && target instanceof Item) {
if (session.isRestrictedEquipment(target.asItem())) {
p.sendMessage("You can't equip that during this duel.");
return true;
}
}
if (option.getName().equalsIgnoreCase("Summon") && !session.hasRule(DuelRule.ENABLE_SUMMONING)) {
p.sendMessage("You cannot summon familiars whilst in a duel.");
return true;
}
if (option.getName().equalsIgnoreCase("drop") && target instanceof Item) {
p.sendMessage("You cannot drop items whilst in a duel.");
return true;
}
switch (target.getId()) {
case 3203:
handleForfeit(p);
return true;
}
return super.interact(e, target, option);
}
@Override
public boolean move(Entity entity, Location from, Location to) {
if (entity.isPlayer()) {
Player p = entity.asPlayer();
DuelSession session = getSession(p);
if (session == null) {
return false;
}
return !session.hasRule(DuelRule.NO_MOVEMENT);
}
return super.move(entity, from, to);
}
@Override
public boolean actionButton(Player player, int interfaceId, int buttonId, int slot, int itemId, int opcode) {
DuelSession session = getSession(player);
if (session == null) {
return true;
}
WeaponInterface inter = player.getExtension(WeaponInterface.class);
if (inter != null && interfaceId == inter.getId()) {
switch (buttonId) {
case 8:
case 10:
if (session.hasRule(DuelRule.NO_SPECIAL_ATTACKS)) {
player.sendMessage("You can't use special attacks during a duel.");
return true;
}
break;
}
}
switch (interfaceId) {
case 182:
player.sendMessage("You can't logout during a duel.");
return true;
case 271:
if (session.hasRule(DuelRule.NO_PRAYER)) {
player.getPrayer().toggle(PrayerType.get(buttonId));
player.getPrayer().toggle(PrayerType.get(buttonId));
player.sendMessage("Use of prayer has been turned off for this duel.");
return true;
}
break;
case 430:
if (session.hasRule(DuelRule.NO_MAGIC)) {
player.sendMessage("Use of prayer has been turned off for this duel.");
return true;
}
break;
}
return super.actionButton(player, interfaceId, buttonId, slot, itemId, opcode);
}
@Override
public boolean continueAttack(Entity e, Node target, CombatStyle style, boolean message) {
if (e.isPlayer() && target instanceof Player && !checkAttack(e.asPlayer(), ((Player) target))) {
return false;
}
if (e instanceof Familiar && target instanceof Player) {
Familiar f = (Familiar) e;
Player o = f.getOwner();
if (o != null && target.asPlayer() != getSession(o).getOpposite(o)) {
return false;
}
}
if (e instanceof Familiar && target instanceof Familiar) {
Familiar f = (Familiar) e;
Familiar t = (Familiar) target;
if (getSession(f.getOwner()).getOpposite(f.getOwner()) != t.getOwner()) {
return false;
}
}
if (e.isPlayer()) {
Player p = e.asPlayer();
DuelSession session = getSession(p);
if (session == null) {
return false;
}
boolean canAttack = true;
switch (style) {
case MAGIC:
canAttack = !session.hasRule(DuelRule.NO_MAGIC);
break;
case MELEE:
canAttack = !session.hasRule(DuelRule.NO_MELEE);
break;
case RANGE:
canAttack = !session.hasRule(DuelRule.NO_RANGE);
break;
}
if (!canAttack) {
p.sendMessage(StringUtils.formatDisplayName(style.name().toLowerCase()) + " has been turned off for this duel.");
return false;
}
if (session.hasRule(DuelRule.FUN_WEAPONS) && (p.getEquipment().get(EquipmentContainer.SLOT_WEAPON) == null || !p.getEquipment().get(EquipmentContainer.SLOT_WEAPON).getDefinition().getConfiguration("fun_weapon", false))) {
p.sendMessages("This is a 'fun weapon' duel. You can only use flowers, basket of eggs, or a", "rubber chicken.");
return false;
}
if (target instanceof Familiar) {
Familiar f = (Familiar) target;
if (f.getOwner() != null && getSession(p).getOpposite(p) != f.getOwner()) {
p.sendMessage("You can't attack that familiar.");
return false;
}
}
}
return true;
}
@Override
public boolean teleport(Entity e, int type, Node node) {
if (e.isPlayer()) {
e.asPlayer().getDialogueInterpreter().sendDialogue("Coward! You can't teleport from a duel.");
}
return false;
}
@Override
public boolean enter(Entity e) {
if (e.isPlayer()) {
getSession(e.asPlayer());
e.getProperties().setSafeZone(true);
e.getProperties().setSpawnLocation(RandomFunction.getRandomElement(RESPAWN_LOCATIONS));
e.asPlayer().getInteraction().remove(DuelArenaActivity.CHALLENGE_OPTION);
e.asPlayer().getInteraction().set(FIGHT_OPTION);
} else if (e instanceof Familiar) {
Familiar f = (Familiar) e;
Player o = f.getOwner();
if (o != null && !o.getFamiliarManager().hasPet()) {
DuelSession s = getSession(f.getOwner());
if (s != null && s.hasRule(DuelRule.ENABLE_SUMMONING)) {
f.transform();
}
}
f.getProperties().setMultiZone(true);
}
return super.enter(e);
}
@SuppressWarnings("deprecation")
@Override
public boolean leave(Entity entity, boolean logout) {
entity.getProperties().setSafeZone(false);
if (entity instanceof Player) {
Player p = entity.asPlayer();
if (logout) {
p.setLocation(RandomFunction.getRandomElement(RESPAWN_LOCATIONS));
}
p.lock(1);
leave(p);
DuelSession session = getSession(p);
if (session == null) {
return true;
}
session.leave(p, logout ? 1 : p.getAttribute("duel:forfeit", false) ? 0 : 2);
remove(session.getOpposite(p));
leave(session.getOpposite(p));
} else if (entity instanceof Familiar) {
Familiar familiar = (Familiar) entity;
if (familiar.isCombatFamiliar()) {
familiar.reTransform();
}
familiar.getProperties().setMultiZone(false);
}
return super.leave(entity, logout);
}
@Override
public void configure() {
register(border);
}
/**
* Handles the leaving of a player.
* @param p the player.
*/
private void leave(Player p) {
if (p.getAttribute("duel:ammo", null) != null) {
List<GroundItem> ammo = p.getAttribute("duel:ammo");
Container c = new Container(40);
for (GroundItem item : ammo) {
if (item == null) {
continue;
}
if (item.isActive() && GroundItemManager.getItems().contains(item) && item.droppedBy(p)) {
GroundItemManager.destroy(item);
c.add(item);
}
}
p.getInventory().addAll(c);
}
p.getInteraction().remove(FIGHT_OPTION);
p.getSkullManager().setSkullCheckDisabled(false);
p.getSkullManager().setWilderness(false);
p.getProperties().setSpawnLocation(ServerConstants.HOME_LOCATION);
p.getProperties().setMultiZone(false);
p.getInteraction().set(DuelArenaActivity.CHALLENGE_OPTION);
}
/**
* Forcefully removes a player.
* @param player the player.
*/
private static void remove(Player player) {
HintIconManager.removeHintIcon(player, player.getAttribute("duel:icon", -1));
if (player.getExtension(DuelSession.class) != null) {
player.teleport(RandomFunction.getRandomElement(RESPAWN_LOCATIONS));
}
}
/**
* Handles the forfeit trapdoor.
* @param p the player.
*/
public static void handleForfeit(Player p) {
DuelSession session = getSession(p);
if (session == null) {
return;
}
if (session.getFightState() != 1) {
p.sendMessage("The duel has not started yet!");
return;
}
if (session.hasRule(DuelRule.NO_FORFEIT)) {
p.getDialogueInterpreter().sendDialogue("Forfeit has been turned off for this duel.");
return;
}
p.getDialogueInterpreter().sendOptions("Do you wish to forfeit?", "Yes", "No");
p.getDialogueInterpreter().addAction(new DialogueAction() {
@Override
public void handle(Player player, int buttonId) {
if (buttonId == 2) {
remove(player);
player.setAttribute("duel:forfeit", true);
}
}
});
}
/**
* Gets the starting locations for the session.
* @param session the session.
* @return the locations.
*/
public Location[] getStartLocations(DuelSession session) {
Location start = null;
Location[] locations = new Location[2];
while (start == null) {
start = center.transform(RandomFunction.random(10), RandomFunction.random(session.hasRule(DuelRule.NO_MOVEMENT) ? 6 : 10), 0);
if (isValidLocation(start)) {
locations[locations[0] == null ? 0 : 1] = start;
if (session.hasRule(DuelRule.NO_MOVEMENT)) {
Location l = null;
if (!isValidLocation(l = start.transform(1, 0, 0))) {
if (!isValidLocation(l = start.transform(-1, 0, 0))) {
if (!isValidLocation(l = start.transform(1, 0, 0))) {
if (!isValidLocation(l = start.transform(-1, 0, 0))) {
locations[1] = start;
break;
}
}
}
}
start = l;
locations[1] = l;
break;
}
start = locations[1] == null ? null : start;
} else {
start = null;
}
}
return locations;
}
@Override
public boolean startDeath(Entity entity, Entity killer) {
if (entity instanceof Player) {
Player k = killer instanceof Player ? killer.asPlayer() : killer instanceof Familiar ? ((Familiar) killer).getOwner() : null;
if (k != null) {
k.getImpactHandler().setDisabledTicks(10);
k.getSkills().heal(100);
k.lock(5);
}
}
return true;
}
@Override
public boolean death(Entity e, Entity killer) {
if (e.isPlayer() && (killer.isPlayer() || killer instanceof Familiar)) {
Player k = killer instanceof Familiar ? ((Familiar) killer).getOwner() : killer.asPlayer();
if (k != null) {
k.getSkills().heal(100);
PulseManager.cancelDeathTask(e);
}
}
return super.death(e, killer);
}
/**
* Checks if the location is valid to start on.
* @param location the location.
* @return {@code True} if so.
*/
public boolean isValidLocation(Location location) {
return RegionManager.isTeleportPermitted(location) && RegionManager.getObject(location) == null;
}
/**
* Checks the attack of a player.
* @param player the player.
* @param target the target.
* @return {@code True} if so.
*/
public boolean checkAttack(Player player, Player target) {
DuelSession session = getSession(player);
if (session == null) {
return false;
}
if (session.getOpposite(player) != target) {
player.sendMessage("You can only attack your opponent!");
return false;
}
if (session.getFightState() != 1) {
player.sendMessage("You can't attack yet!");
return false;
}
return true;
}
/**
* Gets the duel session for the player.
* @param player the player.
* @return the duel session.
*/
public static DuelSession getSession(Player player) {
DuelSession session = player.getExtension(DuelSession.class);
if (session == null) {
remove(player);
}
return session;
}
/**
* Gets the obstacles.
* @return the obstacles.
*/
public boolean isObstacles() {
return obstacles;
}
/**
* Gets the border.
* @return the border.
*/
public ZoneBorders getBorder() {
return border;
}
/**
* Gets the center.
* @return the center.
*/
public Location getCenter() {
return center;
}
/**
* Handles the forfeit trapdoor plugin.
* @author Vexia
*
*/
public static class ForfeitTrapdoorPlugin extends OptionHandler {
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
ObjectDefinition.forId(3203).getHandlers().put("option:forfeit", this);
return this;
}
@Override
public boolean handle(Player player, Node node, String option) {
handleForfeit(player);
return true;
}
@Override
public Location getDestination(Node node, Node n) {
Location loc = null;
if (node instanceof Player) {
DuelSession session = getSession(node.asPlayer());
if (session != null && session.hasRule(DuelRule.NO_MOVEMENT)) {
loc = node.getLocation();
}
}
return loc;
}
}
}
@@ -0,0 +1,229 @@
package core.game.content.activity.duel;
import java.util.ArrayList;
import java.util.List;
import core.game.component.Component;
import core.game.content.activity.ActivityPlugin;
import core.game.interaction.Option;
import core.game.node.Node;
import core.game.node.entity.Entity;
import core.game.node.entity.combat.CombatStyle;
import core.game.node.entity.impl.PulseManager;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.request.RequestType;
import core.game.world.map.Location;
import core.game.world.map.zone.ZoneBorders;
import core.game.world.map.zone.ZoneBuilder;
import core.plugin.Initializable;
import core.plugin.PluginManager;
import core.tools.RandomFunction;
/**
* Handles the Duel Arena activity.
* @author Emperor
* @author Vexia
*
*/
@Initializable
public final class DuelArenaActivity extends ActivityPlugin {
/**
* The friendly duel request.
*/
public static final RequestType FRIEND_REQUEST = new RequestType("Sending duel offer...", ":duelfriend:", new DuelReqModule(false));
/**
* The staked duel request.
*/
public static final RequestType STAKE_REQUEST = new RequestType("Sending duel offer...", ":duelstake:", new DuelReqModule(true));
/**
* The dueling areas.
*/
public static final DuelArea[] DUEL_AREAS = new DuelArea[] { new DuelArea(0, new ZoneBorders(3332, 3244, 3357, 3258), false, Location.create(3345, 3251, 0)), new DuelArea(1, new ZoneBorders(3364, 3244, 3388, 3259), true, Location.create(3378, 3251, 0)), new DuelArea(2, new ZoneBorders(3333, 3224, 3357, 3239), true, Location.create(3345, 3231, 0)), new DuelArea(3, new ZoneBorders(3364, 3225, 3388, 3240), false, Location.create(3376, 3231, 0)), new DuelArea(4, new ZoneBorders(3333, 3205, 3357, 3220), false, Location.create(3346, 3212, 0)), new DuelArea(5, new ZoneBorders(3364, 3206, 3388, 3221), true, Location.create(3377, 3213, 0)) };
/**
* The challenge option.
*/
public static final Option CHALLENGE_OPTION = new Option("Challenge", 0);
/**
* The select duel type component.
*/
public static final Component DUEL_TYPE_SELECT = new Component(640);
/**
* The overlay.
*/
private static final Component OVERLAY = new Component(638);
/**
* The scoreboard.
*/
private static final String[] SCOREBOARD = new String[50];
/**
* Constructs a new {@code DuelArenaActivity} {@code Object}.
*/
public DuelArenaActivity() {
super("Duel arena", false, false, true);
}
@Override
public boolean enter(Entity e) {
if (e instanceof Player) {
Player player = (Player) e;
player.getInterfaceManager().openOverlay(OVERLAY);
player.getInteraction().set(CHALLENGE_OPTION);
player.getConfigManager().set(286, 0);
}
return super.enter(e);
}
@Override
public boolean leave(Entity e, boolean logout) {
if (e instanceof Player) {
Player player = (Player) e;
player.getInterfaceManager().closeOverlay();
player.getInteraction().remove(CHALLENGE_OPTION);
}
return super.leave(e, logout);
}
@Override
public ActivityPlugin newInstance(Player p) throws Throwable {
return this;
}
@Override
public Location getSpawnLocation() {
return null;
}
@Override
public boolean continueAttack(Entity e, Node target, CombatStyle style, boolean message) {
if (e.isPlayer() && e.asPlayer().getZoneMonitor().getZones().size() > 1) {
return super.continueAttack(e, target, style, message);
}
return false;
}
@Override
public boolean interact(Entity e, Node target, Option o) {
if (e.isPlayer()) {
switch (target.getId()) {
case 3192:
openScoreboard(e.asPlayer());
return true;
}
}
return super.interact(e, target, o);
}
@Override
public boolean death(Entity e, Entity killer) {
if (e.isPlayer() && e.asPlayer().getZoneMonitor().getZones().size() > 1) {
return true;
}
if (e instanceof Player && killer instanceof Player) {
e.getSkills().heal(100);
PulseManager.cancelDeathTask(e);
return true;
}
return true;
}
@Override
public void configure() {
for (DuelArea area : DUEL_AREAS) {
ZoneBuilder.configure(area);
}
parseScoreboard();
register(new ZoneBorders(3325, 3201, 3396, 3280));
PluginManager.definePlugin(new DuelArea.ForfeitTrapdoorPlugin());
PluginManager.definePlugins(new DuelSession(null, null, false), new DuelComponentPlugin(), new ChallengeOptionPlugin());
}
/**
* Opens the scoreboard.
* @param player the player.
*/
public static void openScoreboard(Player player) {
player.lock(2);
parseScoreboard();
player.getInterfaceManager().open(new Component(632));
int index = 0;
for (int i = 16; i < 65; i++) {
player.getPacketDispatch().sendString(SCOREBOARD[index] == null ? "" : SCOREBOARD[index], 632, i - 1);
index++;
}
}
/**
* Parses the scoreboard data from the database.
*/
public static void parseScoreboard() {
/*Connection connection = SQLManager.getConnection();
if (connection == null) {
return;
}
java.sql.PreparedStatement statement;
try {
statement = connection.prepareStatement("SELECT * FROM duel_scoreboard WHERE id <= 50");
ResultSet set = statement.executeQuery();
while (set.next()) {
SCOREBOARD[set.getInt(1) - 1] = set.getString(2);
}
statement = connection.prepareStatement("DELETE FROM duel_scoreboard WHERE id > 50");
statement.executeUpdate();
} catch (SQLException e) {
SQLManager.close(connection);
e.printStackTrace();
}
SQLManager.close(connection);*/
}
/**
* Inserts an entry into the scoreboard.
* @param winner the winner.
* @param looser the looser.
*/
public static void insertEntry(Player winner, Player looser) {
/*String entry = winner.getUsername() + " (" + winner.getProperties().getCurrentCombatLevel() + ") beat " + looser.getUsername() + " (" + looser.getProperties().getCurrentCombatLevel() + ")";
Connection connection = SQLManager.getConnection();
if (connection == null) {
return;
}
java.sql.PreparedStatement statement;
try {
statement = connection.prepareStatement("UPDATE duel_scoreboard SET id = ID + 1");
statement.executeUpdate();
statement = connection.prepareStatement("INSERT INTO duel_scoreboard (id,entry) VALUES(?,?)");
statement.setInt(1, 1);
statement.setString(2, entry);
statement.executeUpdate();
} catch (SQLException e) {
SQLManager.close(connection);
e.printStackTrace();
}
SQLManager.close(connection);*/
}
/**
* Gets the dueling area.
* @param obstacles if we're using obstacles.
* @return {@code DuelArea} the area.
*/
public static DuelArea getDuelArea(boolean obstacles) {
List<DuelArea> options = new ArrayList<>();
for (DuelArea area : DUEL_AREAS) {
if (!obstacles && area.isObstacles() || obstacles && !area.isObstacles()) {
continue;
}
options.add(area);
}
return options.get(RandomFunction.random(options.size()));
}
}
@@ -0,0 +1,69 @@
package core.game.content.activity.duel;
import core.game.component.Component;
import core.game.component.ComponentDefinition;
import core.game.component.ComponentPlugin;
import core.game.node.entity.player.Player;
import core.game.world.GameWorld;
import core.plugin.Plugin;
/**
* Handles the duel arena components.
* @author Vexia
*
*/
public class DuelComponentPlugin extends ComponentPlugin {
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
ComponentDefinition.forId(640).setPlugin(this);
return this;
}
@Override
public boolean handle(Player player, Component component, int opcode, int button, int slot, int itemId) {
switch (component.getId()) {
case 640:
boolean staked = false;
switch (button) {
case 20:
Player other = player.getAttribute("duel:partner");
if (other == null || other.getExtension(DuelSession.class) != null) {
player.getPacketDispatch().sendMessage("Other player is busy at the moment.");
return true;
}
if (player.getAttribute("duel:staked", false) && other.getIronmanManager().isIronman() && !GameWorld.getSettings().isDevMode()) {
other.sendMessage("You can't accept a staked duel as an Ironman.");
player.sendMessage("You can't duel Ironman players.");
return true;
}
player.getInterfaceManager().close();
if (!player.getAttribute("duel:staked", false)) {
player.getRequestManager().request(other, DuelArenaActivity.FRIEND_REQUEST);
} else {
player.getRequestManager().request(other, DuelArenaActivity.STAKE_REQUEST);
}
return true;
case 18:
case 22:
staked = false;
break;
case 19:
case 21:
staked = true;
if (player.getIronmanManager().isIronman()) {
player.sendMessage("You can't stake as an Iron man.");
staked = false;
}
break;
default:
return false;
}
player.setAttribute("duel:staked", staked);
player.getConfigManager().set(283, (staked ? 2 : 1) << 26);
break;
}
return true;
}
}
@@ -0,0 +1,33 @@
package core.game.content.activity.duel;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.request.RequestModule;
/**
* Handles a duel request getting accepted.
* @author Emperor
*/
public final class DuelReqModule implements RequestModule {
/**
* If the duel request is staked.
*/
private boolean staked;
/**
* Constructs a new {@code DuelReqModule} {@code Object}.
* @param staked If the duel is staked.
*/
public DuelReqModule(boolean staked) {
this.staked = staked;
}
@Override
public void open(Player player, Player target) {
DuelSession session = new DuelSession(player, target, staked);
player.addExtension(DuelSession.class, session);
target.addExtension(DuelSession.class, session);
session.openRules();
}
}
@@ -0,0 +1,80 @@
package core.game.content.activity.duel;
import core.game.container.impl.EquipmentContainer;
/**
* Represents a dueling rule.
* @author Emperor
*/
public enum DuelRule {
NO_RANGE(4, "You cannot use Ranged attacks."), NO_MELEE(5, "You cannot use Melee attacks."), NO_MAGIC(6, "You cannot use Magic attacks."), FUN_WEAPONS(12, "You can only attack with 'fun' weapons."), NO_FORFEIT(0, "You cannot forfeit the duel."), NO_DRINKS(7, "You cannot use potions."), NO_FOOD(8, "You cannot use food."), NO_PRAYER(9, "You cannot use Prayer."), NO_MOVEMENT(1, "You cannot move."), OBSTACLES(10, "There will be obstacles in the arena."), ENABLE_SUMMONING(28, "Familiars will be allowed in the arena."), NO_SPECIAL_ATTACKS(13, "You cannot use special attacks."), NO_HATS(14, "", EquipmentContainer.SLOT_HAT), NO_CAPES(15, "", EquipmentContainer.SLOT_CAPE), NO_AMULET(16, "", EquipmentContainer.SLOT_AMULET), NO_WEAPON(17, "You can't use 2H weapons such as bows.", EquipmentContainer.SLOT_WEAPON), NO_SHIELD(19, "You can't use 2H weapons such as bows.", EquipmentContainer.SLOT_SHIELD), NO_BODY(18, "", EquipmentContainer.SLOT_CHEST), NO_LEGS(21, "", EquipmentContainer.SLOT_LEGS), NO_GLOVES(23, "", EquipmentContainer.SLOT_HANDS), NO_RINGS(26, "", EquipmentContainer.SLOT_RING), NO_BOOTS(24, "", EquipmentContainer.SLOT_FEET), NO_ARROWS(27, "", EquipmentContainer.SLOT_ARROWS);
/**
* The config index.
*/
private final int configIndex;
/**
* The information to display on the second screen.
*/
private final String info;
/**
* The equpment slot.
*/
private int equipmentSlot = -1;
/**
* Constructs a new {@code DuelRule} {@code Object}.
* @param configIndex The config index.
* @param info the info for the second screen.
*/
private DuelRule(int configIndex, String info) {
this.configIndex = configIndex;
this.info = info;
}
/**
* Constructs a new {@code DuelRule} {@code Object}.
* @param configIndex The config index.
* @param info the info for the second screen.
* @param equipmentSlot the equipment slot.
*/
private DuelRule(int configIndex, String info, int equipmentSlot) {
this.configIndex = configIndex;
this.info = info;
this.equipmentSlot = equipmentSlot;
}
/**
* Gets the configIndex.
* @return The configIndex.
*/
public int getConfigIndex() {
return configIndex;
}
/**
* Gets the info.
* @return The info.
*/
public String getInfo() {
return info;
}
/**
* Gets the equipmentSlot.
* @return the equipmentSlot.
*/
public int getEquipmentSlot() {
return equipmentSlot;
}
/**
* Sets the equipmentSlot.
* @param equipmentSlot the equipmentSlot to set
*/
public void setEquipmentSlot(int equipmentSlot) {
this.equipmentSlot = equipmentSlot;
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,212 @@
package core.game.content.activity.duel;
import core.game.component.Component;
import core.game.container.Container;
import core.game.container.ContainerEvent;
import core.game.container.ContainerListener;
import core.game.container.ContainerType;
import core.game.container.SortType;
import core.game.container.access.InterfaceContainer;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.info.login.PlayerParser;
import core.game.node.item.Item;
import core.net.packet.PacketRepository;
import core.net.packet.context.ContainerContext;
import core.net.packet.out.ContainerPacket;
/**
* Represents the staking container.
* @author Vexia
*
*/
public class StakeContainer extends Container {
/**
* The inventory params.
*/
private static final Object[] INVY_PARAMS = new Object[] { "", "", "", "Stake-X", "Stake-All", "Stake-10", "Stake-5", "Stake", -1, 0, 7, 4, 93, (336 << 16) };
/**
* The withdraw options.
*/
private static final String[] WITHDRAW_OPTIONS = new String[] { "Remove-X", "Remove-All", "Remove-10", "Remove-5", "Remove" };
/**
* The overlay interface.
*/
public static final Component OVERLAY = new Component(336);
/**
* The serial version UID.
*/
private static final long serialVersionUID = 3454088488966242754L;
/**
* The player of the container.
*/
private final Player player;
/**
* The dueling session.
*/
private final DuelSession session;
/**
* The stake listener.
*/
private final StakeListener listener;
/**
* If the container has been released.
*/
private boolean released;
/**
* Constructs a new {@Code StakeContainer} {@Code Object}
* @param player the player.
* @param session the session.
*/
public StakeContainer(Player player, DuelSession session) {
super(28, ContainerType.DEFAULT, SortType.ID);
this.player = player;
this.session = session;
this.getListeners().add(listener = new StakeListener());
}
/**
* Opens the staking container.
*/
public void open() {
player.getInterfaceManager().openSingleTab(OVERLAY);
player.getPacketDispatch().sendRunScript(150, "IviiiIssssssss", INVY_PARAMS);
player.getPacketDispatch().sendAccessMask(1278, 0, 336, 0, 27);
PacketRepository.send(ContainerPacket.class, new ContainerContext(player, -1, 2, 93, player.getInventory(), false));
}
/**
* Offers an item to the stake.
* @param slot the slot.
* @param amount the amount.
*/
public void offer(final int slot, int amount) {
final Item item = player.getInventory().get(slot);
if (item == null) {
return;
}
if ((slot < 0 || slot > player.getInventory().capacity() || amount < 1)) {
return;
}
if (!item.getDefinition().isTradeable()) {
player.sendMessage("You can't offer that item.");
return;
}
Item remove = new Item(item.getId(), amount);
if (item.getAmount() > getMaximumAdd(item)) {
item.setAmount(getMaximumAdd(item));
if (item.getAmount() < 1) {
return;
}
}
remove.setAmount(amount > player.getInventory().getAmount(item) ? player.getInventory().getAmount(item) : amount);
if (player.getInventory().remove(remove, slot, true)) {
session.resetAccept();
add(remove);
StakeContainer c = session.getOppositeContainer(player);
c.getListener().update(c, c.getEvent());
}
}
/**
* Withdraws an item from the container.
* @param slot the slot.
* @param amount the amount.
*/
public void withdraw(final int slot, int amount) {
final Item item = get(slot);
if (item == null) {
return;
}
if ((slot < 0 || slot > player.getInventory().capacity() || amount < 1)) {
return;
}
if (!item.getDefinition().isTradeable()) {
player.sendMessage("You can't offer that item.");
return;
}
Item remove = new Item(item.getId(), amount);
if (item.getAmount() > getMaximumAdd(item)) {
item.setAmount(getMaximumAdd(item));
if (item.getAmount() < 1) {
return;
}
}
remove.setAmount(amount > getAmount(item) ? getAmount(item) : amount);
if (remove(remove, slot, true) && player.getInventory().add(remove)) {
session.resetAccept();
shift();
StakeContainer c = session.getOppositeContainer(player);
c.getListener().update(c, c.getEvent());
}
}
/**
* Releases the container back to the player.
*/
public void release() {
if (released) {
return;
}
released = true;
if (!player.getInventory().hasSpaceFor(this)) {
player.getBank().addAll(this);
player.sendMessage("Your stake was sent to your bake due to invalid inventory space.");
return;
}
player.getInventory().addAll(this);
PlayerParser.save(player);
}
/**
* Gets the serialversionuid.
* @return the serialversionuid.
*/
public static long getSerialversionuid() {
return serialVersionUID;
}
/**
* Gets the session.
* @return the session.
*/
public DuelSession getSession() {
return session;
}
/**
* Gets the listener.
* @return the listener.
*/
public StakeListener getListener() {
return listener;
}
/**
* Represents the container listener for a players stake session.
* @author Vexia
*
*/
public final class StakeListener implements ContainerListener {
@Override
public void update(Container c, ContainerEvent event) {
InterfaceContainer.generateItems(player, c.toArray(), WITHDRAW_OPTIONS, 631, 103, 12, 3);
InterfaceContainer.generateItems(player, session.getOppositeContainer(player).toArray(), WITHDRAW_OPTIONS, 631, 104, 12, 3);
}
@Override
public void refresh(Container c) {
PacketRepository.send(ContainerPacket.class, new ContainerContext(player, -1, 2, 93, player.getInventory(), false));
}
}
}
@@ -0,0 +1,91 @@
package core.game.content.activity.fog;
import core.cache.def.impl.ObjectDefinition;
import core.game.content.activity.ActivityPlugin;
import core.game.interaction.OptionHandler;
import core.game.node.Node;
import core.game.node.entity.player.Player;
import core.game.world.map.Location;
import core.game.world.map.zone.ZoneBorders;
import core.plugin.Plugin;
import core.plugin.PluginManager;
/**
* Represents the fist of guthix activity.
* @author Vexia
*/
public class FOGActivityPlugin extends ActivityPlugin {
/**
* The maximum amount of players in a game.
*/
public static final int MAX_PLAYERS = 250;
/**
* The waiting interface id.
*/
public static final int WAITING_INTERFACE = 731;
/**
* The current fist of guthix round.
*/
private int round;
/**
* Constructs a new {@code FOGActivityPlugin} {@code Object}
*/
public FOGActivityPlugin() {
super("Fist of Guthix", false, true, true);
}
@Override
public ActivityPlugin newInstance(Player p) throws Throwable {
return new FOGActivityPlugin();
}
@Override
public Location getSpawnLocation() {
return null;
}
@Override
public void configure() {
PluginManager.definePlugin(new FOGLobbyZone());
PluginManager.definePlugin(new FOGWaitingZone());
PluginManager.definePlugin(new OptionHandler() {
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
ObjectDefinition.forId(30204).getHandlers().put("option:enter", this);
return this;
}
@Override
public boolean handle(Player player, Node node, String option) {
switch (node.getId()) {
case 30204:
player.teleport(Location.create(1675, 5599, 0));
return true;
}
return true;
}
});
register(new ZoneBorders(1625, 5638, 1715, 5747));
}
/**
* Gets the round.
* @return the round
*/
public int getRound() {
return round;
}
/**
* Sets the round.
* @param round the round to set.
*/
public void setRound(int round) {
this.round = round;
}
}
@@ -0,0 +1,75 @@
package core.game.content.activity.fog;
import core.game.component.Component;
import core.game.interaction.Option;
import core.game.node.Node;
import core.game.node.entity.Entity;
import core.game.node.entity.player.Player;
import core.game.world.map.Location;
import core.game.world.map.zone.MapZone;
import core.game.world.map.zone.ZoneBuilder;
import core.plugin.Plugin;
/**
* Represents a zone where players can prepare for a game.
* @author Vexia
*/
public class FOGLobbyZone extends MapZone implements Plugin<Object> {
/**
* Constructs a new {@code FOGHallZone} {@code Object}
*/
public FOGLobbyZone() {
super("Fog Lobby", true);
}
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
ZoneBuilder.configure(this);
return this;
}
@Override
public boolean enter(Entity e) {
if (e.isPlayer()) {
sendInterface(e.asPlayer());
}
return super.enter(e);
}
@Override
public boolean interact(Entity e, Node target, Option option) {
if (!e.isPlayer()) {
return super.interact(e, target, option);
}
Player player = e.asPlayer();
switch (target.getId()) {
case 30203:
player.teleport(Location.create(3242, 3574, 0));
return true;
}
return super.interact(e, target, option);
}
/**
* Sends the fist of guthix lobby interface.
* @param player the player.
*/
private void sendInterface(Player player) {
player.getInterfaceManager().openOverlay(new Component(FOGActivityPlugin.WAITING_INTERFACE));
player.getPacketDispatch().sendInterfaceConfig(FOGActivityPlugin.WAITING_INTERFACE, 17, true);
player.getPacketDispatch().sendInterfaceConfig(FOGActivityPlugin.WAITING_INTERFACE, 26, true);
player.getPacketDispatch().sendString("Rating: " + player.getSavedData().getActivityData().getFogRating(), FOGActivityPlugin.WAITING_INTERFACE, 7);
}
@Override
public Object fireEvent(String identifier, Object... args) {
return null;
}
@Override
public void configure() {
super.registerRegion(6743);
}
}
@@ -0,0 +1,104 @@
package core.game.content.activity.fog;
import core.game.node.entity.player.Player;
/**
* Represents a fist of guthix player.
* @author Vexia
*/
public class FOGPlayer {
/**
* The player instance.
*/
private final Player player;
/**
* The target FOG player.
*/
private final FOGPlayer target;
/**
* If the player is hunted or a hunter.
*/
private boolean hunted;
/**
* The amount of fist of guthix charges.
*/
private int charges;
/**
* Constructs a new {@code FOGPlayer} {@code Object}
* @param player the player.
* @param oponent the other player.
*/
public FOGPlayer(Player player, FOGPlayer oponent) {
this.player = player;
this.target = oponent;
}
/**
* Switches the roles of the player.
*/
public void switchRoles() {
hunted = !hunted;
}
/**
* Increments the energy charges.
* @param increment the number to increment.
*/
public void incrementCharges(int increment) {
charges += increment;
}
/**
* Gets the hunted.
* @return the hunted
*/
public boolean isHunted() {
return hunted;
}
/**
* Sets the hunted.
* @param hunted the hunted to set.
*/
public void setHunted(boolean hunted) {
this.hunted = hunted;
}
/**
* Gets the charges.
* @return the charges
*/
public int getCharges() {
return charges;
}
/**
* Sets the charges.
* @param charges the charges to set.
*/
public void setCharges(int charges) {
this.charges = charges;
}
/**
* Gets the player.
* @return the player
*/
public Player getPlayer() {
return player;
}
/**
* Gets the target.
* @return the target
*/
public FOGPlayer getTarget() {
return target;
}
}
@@ -0,0 +1,49 @@
package core.game.content.activity.fog;
import core.game.interaction.Option;
import core.game.node.Node;
import core.game.node.entity.Entity;
import core.game.world.map.zone.MapZone;
import core.game.world.map.zone.ZoneBuilder;
import core.plugin.Plugin;
/**
* Represents the zone where players wait for a match.
* @author Vexia
*/
public class FOGWaitingZone extends MapZone implements Plugin<Object> {
/**
* Constructs a new {@code FOGLobbyZone} {@code Object}
*/
public FOGWaitingZone() {
super("Fog Waiting Room", true);
}
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
ZoneBuilder.configure(this);
return this;
}
@Override
public boolean enter(Entity e) {
return super.enter(e);
}
@Override
public boolean interact(Entity e, Node target, Option option) {
return super.interact(e, target, option);
}
@Override
public Object fireEvent(String identifier, Object... args) {
return null;
}
@Override
public void configure() {
super.registerRegion(6487);
}
}
@@ -0,0 +1,50 @@
package core.game.content.activity.gnomecopter;
import core.game.component.Component;
import core.game.node.entity.player.Player;
/**
* The information signs for the Gnomecopter tours.
* @author Emperor
*/
public enum GCInformationSign {
/**
* The gnomecopters entrance sign.
*/
ENTRANCE("~ Gnomecopter Tours ~", "Welcome to Gnomecopter", "Tours: the unique flying", "experience!", "", "If you're a new flier, talk to", "<col=FF0000>Hieronymous</col> and prepare to be", "amazed by this triumph of", "gnomic engineering.", "", "", "Warning: all riders must be at", "least 2ft, 6ins tall.");
/**
* The button text.
*/
private final String button;
/**
* The info.
*/
private final String[] info;
/**
* Constructs a new {@code GCInformationSign} {@code Object}.
* @param button The button text.
* @param info The information.
*/
private GCInformationSign(String button, String... info) {
this.button = button;
this.info = info;
}
/**
* Reads the information sign.
* @param player The player.
*/
public void read(Player player) {
player.getInterfaceManager().openSingleTab(new Component(723));
player.getPacketDispatch().sendString(button, 723, 9);
String information = info[0];
for (int i = 1; i < info.length; i++) {
information += "<br>" + info[i];
}
player.getPacketDispatch().sendString(information, 723, 10);
}
}
@@ -0,0 +1,205 @@
package core.game.content.activity.gnomecopter;
import core.game.container.impl.EquipmentContainer;
import core.game.node.entity.player.link.diary.DiaryType;
import core.game.content.activity.ActivityPlugin;
import core.game.interaction.Option;
import core.game.node.Node;
import core.game.node.entity.Entity;
import core.game.node.entity.impl.ForceMovement;
import core.game.node.entity.player.Player;
import core.game.node.item.Item;
import core.game.node.object.GameObject;
import core.game.node.object.ObjectBuilder;
import core.game.system.task.Pulse;
import core.game.world.GameWorld;
import core.game.world.map.Direction;
import core.game.world.map.Location;
import core.game.world.map.zone.ZoneBorders;
import core.game.world.update.flag.context.Animation;
import core.plugin.Initializable;
import core.game.world.update.flag.context.Graphics;
/**
* Handles the gnome copter activity.
* @author Emperor
*/
@Initializable
public final class GnomeCopterActivity extends ActivityPlugin {
/**
* The gnome copter item.
*/
private static final Item COPTER_ITEM = new Item(12842);
/**
* The landing pads currently in use.
*/
private final boolean[] usedLandingPads = new boolean[4];
/**
* Constructs a new {@code GnomeCopterActivity} {@code Object}.
*/
public GnomeCopterActivity() {
super("Gnome copters", false, false, true);
}
@Override
public ActivityPlugin newInstance(Player p) throws Throwable {
return this;
}
@Override
public boolean interact(Entity e, Node target, Option option) {
if (target instanceof GameObject) {
GameObject object = (GameObject) target;
if (object.getId() == 30032) {
flyGnomeCopter((Player) e, object);
return true;
}
if (object.getId() == 30036) {
GCInformationSign.ENTRANCE.read((Player) e);
return true;
}
} else if (target instanceof Item && e.getAttribute("gc:flying", false)) {
((Player) e).getPacketDispatch().sendMessage("You can't do this right now.");
return true;
}
return false;
}
@Override
public boolean leave(Entity e, boolean logout) {
if (logout && e.getAttribute("gc:flying", false)) {
e.setLocation(getSpawnLocation());
((Player) e).getEquipment().remove(COPTER_ITEM);
}
return super.leave(e, logout);
}
/**
* Starts flying the gnome copter.
* @param player The player.
* @param object The object.
*/
private void flyGnomeCopter(final Player player, final GameObject object) {
if (!player.getLocation().equals(object.getLocation().transform(0, 1, 0))) {
return;
}
if (object.getCharge() == 88) {
player.getPacketDispatch().sendMessage("Someone else is already using this gnomecopter.");
return;
}
if (player.getEquipment().get(EquipmentContainer.SLOT_HAT) != null) {
player.getPacketDispatch().sendMessage("You can't wear a hat on a Gnomecopter.");
return;
}
if (player.getEquipment().get(EquipmentContainer.SLOT_CAPE) != null) {
player.getPacketDispatch().sendMessage("You can't wear a cape on a Gnomecopter.");
return;
}
if (player.getEquipment().get(3) != null || player.getEquipment().get(5) != null) {
player.getPacketDispatch().sendMessage("You need to have your hands free to use this.");
return;
}
player.setAttribute("gc:flying", true);
player.lock();
player.faceLocation(player.getLocation().transform(0, 3, 0));
object.setCharge(88);
GameWorld.getPulser().submit(new Pulse(1, player) {
int stage = 0;
@Override
public boolean pulse() {
if (++stage == 1) {
player.getInterfaceManager().hideTabs(0, 1, 2, 3, 4, 5, 6, 7, 11);
ForceMovement.run(player, player.getLocation(), object.getLocation(), ForceMovement.WALK_ANIMATION, new Animation(8955), Direction.NORTH, 8);
player.lock();
} else if (stage == 3) {
player.getEquipment().replace(COPTER_ITEM, 3);
player.visualize(Animation.create(8956), Graphics.create(1578));
player.getAppearance().setStandAnimation(8964);
player.getAppearance().setWalkAnimation(8961);
player.getAppearance().setRunAnimation(8963);
player.getAppearance().setTurn180(8963);
player.getAppearance().setTurn90ccw(8963);
player.getAppearance().setTurn90cw(8963);
player.getAppearance().setStandTurnAnimation(8963);
} else if (stage == 4) {
object.setCharge(88);
player.getPacketDispatch().sendObjectAnimation(object, new Animation(5));
} else if (stage == 16) {
player.getWalkingQueue().reset();
player.getWalkingQueue().addPath(object.getLocation().getX(), object.getLocation().getY() + 16, true);
Graphics.send(Graphics.create(1579), object.getLocation());
} else if (stage == 20) {
object.setCharge(1000);
player.getPacketDispatch().sendObjectAnimation(object, new Animation(8941));
} else if (stage == 33) {
player.unlock();
landGnomeCopter(player);
return true;
}
return false;
}
});
}
/**
* Lands the gnomecopter.
* @param player The player.
*/
private void landGnomeCopter(final Player player) {
int index = 0;
for (index = 0; index < usedLandingPads.length; index++) {
if (!usedLandingPads[index]) {
break;
}
}
usedLandingPads[index] = true;
player.lock();
final int pad = index;
player.setDirection(Direction.SOUTH);
player.getProperties().setTeleportLocation(Location.create(3162, 3352, 0));
GameWorld.getPulser().submit(new Pulse(1, player) {
int stage = 0;
int tick = 0;
@Override
public boolean pulse() {
if (++stage == 1) {
player.getWalkingQueue().reset();
player.getWalkingQueue().addPath(3162, 3348, true);
player.getWalkingQueue().addPath(3161 - (pad << 1), 3336, true);
tick = stage + player.getWalkingQueue().getQueue().size();
} else if (stage == tick) {
player.animate(Animation.create(8957));
} else if (stage == tick + 14) {
ObjectBuilder.add(new GameObject(30034, player.getLocation()), 6);
player.getEquipment().replace(null, 3);
ForceMovement.run(player, player.getLocation(), player.getLocation().transform(0, -1, 0), new Animation(8959), 8);
player.lock(2);
} else if (stage == tick + 15) {
player.unlock();
player.getInterfaceManager().restoreTabs();
usedLandingPads[pad] = false;
player.removeAttribute("gc:flying");
player.getAchievementDiaryManager().finishTask(player, DiaryType.LUMBRIDGE, 2, 1);
return true;
}
return false;
}
});
}
@Override
public Location getSpawnLocation() {
return Location.create(3161, 3337, 0);
}
@Override
public void configure() {
register(new ZoneBorders(3154, 3330, 3171, 3353));
}
}
@@ -0,0 +1,293 @@
package core.game.content.activity.guild;
import core.cache.def.impl.NPCDefinition;
import core.cache.def.impl.ObjectDefinition;
import core.game.content.dialogue.DialoguePlugin;
import core.game.content.global.Skillcape;
import core.game.content.global.action.DoorActionHandler;
import core.game.node.entity.skill.Skills;
import core.game.node.entity.skill.crafting.TanningProduct;
import core.game.interaction.OptionHandler;
import core.game.node.Node;
import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player;
import core.game.node.item.Item;
import core.game.node.object.GameObject;
import core.game.world.map.Location;
import core.plugin.Initializable;
import core.plugin.Plugin;
/**
* Represents the plugin used for the crafting guild.
* @author 'Vexia
* @version 1.0
*/
@Initializable
public final class CraftingGuildPlugin extends OptionHandler {
/**
* Represents the brown apron item.
*/
private static final Item BROWN_APRON = new Item(1757);
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
ObjectDefinition.forId(2647).getHandlers().put("option:open", this);
NPCDefinition.forId(804).getHandlers().put("option:trade", this);
new MasterCrafterDialogue().init();
new TannerDialogue().init();
return this;
}
@Override
public boolean handle(Player player, Node node, String option) {
final int id = node instanceof GameObject ? ((GameObject) node).getId() : ((NPC) node).getId();
switch (option) {
case "open":
switch (id) {
case 2647:
if (player.getLocation().getY() >= 3289) {
if (player.getSkills().getStaticLevel(Skills.CRAFTING) < 40) {
player.getDialogueInterpreter().sendDialogues(805, null, "Sorry, only experienced crafters are allowed in here.", "You must be level 40 or above to enter.");
return true;
}
if (!player.getEquipment().containsItem(BROWN_APRON)) {
player.getDialogueInterpreter().open(805, true, true);
return true;
}
player.getDialogueInterpreter().sendDialogues(805, null, "Welcome to the Guild of Master Craftsmen.");
DoorActionHandler.handleAutowalkDoor(player, (GameObject) node);
} else {
DoorActionHandler.handleAutowalkDoor(player, (GameObject) node);
return true;
}
break;
}
return true;
case "trade":
switch (id) {
case 804:
TanningProduct.open(player, 804);
break;
}
return true;
}
return true;
}
@Override
public Location getDestination(Node node, Node n) {
if (n instanceof GameObject) {
return DoorActionHandler.getDestination((Player) node, (GameObject) n);
}
return null;
}
/**
* Represents the dialogue plugin used for the crafting master.
* @author 'Vexia
* @version 1.0
*/
public final class MasterCrafterDialogue extends DialoguePlugin {
/**
* Constructs a new {@code MasterCrafterDialogue} {@code Object}.
*/
public MasterCrafterDialogue() {
/**
* empty.
*/
}
/**
* Constructs a new {@code MasterCrafterDialogue} {@code Object}.
* @param player the player.
*/
public MasterCrafterDialogue(final Player player) {
super(player);
}
@Override
public DialoguePlugin newInstance(Player player) {
return new MasterCrafterDialogue(player);
}
@Override
public boolean open(Object... args) {
if (args.length == 2) {
npc("Where's your brown apron? You can't come in here", "unless you're wearing one.");
stage = 100;
return true;
}
npc = (NPC) args[0];
npc("Hello, and welcome to the Crafting Guild. Accomplished", "crafters from all over the land come here to use our", "top notch workshops.");
stage = 0;
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
switch (stage) {
case 0:
if (npc.getId() == 805) {
if (Skillcape.isMaster(player, Skills.CRAFTING)) {
player("Hey, could I buy a Skillcape of Crafting?");
stage = 3;
} else {
player("Hey, what is that cape you're wearing?", "I don't recognise it.");
stage = 1;
}
} else {
end();
}
break;
case 1:
npc("This? This is a Skillcape of Crafting. It is a symbol of", "my ability and standing here in the Crafting Guild. If", "you should ever achieve level 99 Crafting come and talk", "to me and we'll see if we can sort you out with one.");
stage = 2;
break;
case 2:
end();
break;
case 3:
npc("Certainly! Right after you pay me 99000 coins.");
stage = 4;
break;
case 4:
options("Okay, here you go.", "No, thanks.");
stage = 5;
break;
case 5:
switch (buttonId) {
case 1:
player("Okay, here you go.");
stage = 6;
break;
case 2:
end();
break;
}
break;
case 6:
if (Skillcape.purchase(player, Skills.CRAFTING)) {
npc("There you go! Enjoy.");
}
stage = 7;
break;
case 7:
end();
break;
case 100:
npc("Where's your borwn apron? You can't come in here", "unless you're wearing one.");
stage = 101;
break;
case 101:
player("Err... I haven't got one.");
stage = 102;
break;
case 102:
end();
break;
}
return true;
}
@Override
public int[] getIds() {
return new int[] { 805, 2732, 2733 };
}
}
/**
* Represents the dialogue used for the tanner npc.
* @author 'Vexia
* @version 1.0
*/
public final class TannerDialogue extends DialoguePlugin {
/**
* Constructs a new {@code TannerDialogue} {@code Object}.
*/
public TannerDialogue() {
/**
* empty.
*/
}
/**
* Constructs a new {@code TannerDialogue} {@code Object}.
* @param player the player.
*/
public TannerDialogue(final Player player) {
super(player);
}
@Override
public DialoguePlugin newInstance(Player player) {
return new TannerDialogue(player);
}
@Override
public boolean open(Object... args) {
npc("Greetings friend. I am a manufacturer of leather.");
stage = 0;
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
switch (stage) {
case 0:
options("Can I buy some leather then?", "Leather is rather weak stuff.");
stage = 1;
break;
case 1:
switch (buttonId) {
case 1:
player("Can I buy some leather then?");
stage = 10;
break;
case 2:
player("Leather is rather weak stuff.");
stage = 20;
break;
}
break;
case 10:
npc("Certainly!");
stage = 11;
break;
case 11:
end();
TanningProduct.open(player, 804);
break;
case 20:
npc("Normal leather may be quite weak, but it's very cheap -", "I make it from cowhides for only 1 gp per hide - and", "it's so easy to craft that anyone can work with it.");
stage = 21;
break;
case 21:
npc("Alternatively you could try hard leather. It's not so", "easy to craft, but I only charge 3gp per cowhide to", "prepare it, and it makes much studier armour.");
stage = 22;
break;
case 22:
npc("I can also tan snake hides and dragonhides, suitable for", "crafting into the highest quality armour for rangers.");
stage = 23;
break;
case 23:
player("Thanks, I'll bear it in mind.");
stage = 24;
break;
case 24:
end();
break;
}
return true;
}
@Override
public int[] getIds() {
return new int[] { 804 };
}
}
}
@@ -0,0 +1,152 @@
package core.game.content.activity.guild;
import core.cache.def.impl.ObjectDefinition;
import core.plugin.Initializable;
import core.game.content.dialogue.DialoguePlugin;
import core.game.content.global.Skillcape;
import core.game.content.global.action.DoorActionHandler;
import core.game.node.entity.skill.Skills;
import core.game.interaction.OptionHandler;
import core.game.node.Node;
import core.game.node.entity.player.Player;
import core.game.node.object.GameObject;
import core.game.world.map.Location;
import core.plugin.Plugin;
/**
* Represents the plugin used for the fishing guild.
* @author 'Vexia
* @version 1.0
*/
@Initializable
public final class FishingGuild extends OptionHandler {
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
ObjectDefinition.forId(2025).getHandlers().put("option:open", this);
new MasterFisherDialogue().init();
return this;
}
@Override
public boolean handle(Player player, Node node, String option) {
final int id = ((GameObject) node).getId();
switch (option) {
case "open":
switch (id) {
case 2025:
if (player.getSkills().getStaticLevel(Skills.FISHING) < 68 && player.getLocation().withinDistance(new Location(2611, 3394, 0))) {
player.getDialogueInterpreter().sendDialogues(308, null, "Hello, I'm afraid only the top fishers are allowed to use", "our premier fishing facilities.");
return true;
}
DoorActionHandler.handleAutowalkDoor(player, (GameObject) node);
break;
}
break;
}
return true;
}
/**
* Represents the master fisher dialogue.
* @author 'Vexia
* @version 1.0
*/
public final class MasterFisherDialogue extends DialoguePlugin {
/**
* Constructs a new {@code MasterFisherDialogue} {@code Object}.
*/
public MasterFisherDialogue() {
/**
* empty.
*/
}
/**
* Constructs a new {@code MasterFisherDialogue} {@code Object}.
* @param player the player.
*/
public MasterFisherDialogue(final Player player) {
super(player);
}
@Override
public DialoguePlugin newInstance(Player player) {
return new MasterFisherDialogue(player);
}
@Override
public boolean open(Object... args) {
if (!Skillcape.isMaster(player, Skills.FISHING)) {
npc("Hello, I'm afraid only the top fishers are allowed to use", "our premier fishing facilities.");
} else {
npc("Hello, only the top fishers are allowed to use", "our premier fishing facilities and you seem", "to meet the criteria. Enjoy!");
}
stage = 0;
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
switch (stage) {
case 0:
if (Skillcape.isMaster(player, Skills.FISHING)) {
player("Can I buy a Skillcape of Fishing?");
stage = 4;
} else {
player("Can you tell me about that skillcape you're wearing?");
stage = 1;
}
break;
case 1:
npc("I'm happy to, my friend. This beautiful cape was", "presented to me in recognition of my skills and", "experience as a fisherman and I was asked to be the", "head of this guild at the same time. As the best");
stage = 2;
break;
case 2:
npc("fisherman in the guild it is my duty to control who has", "access to the guild and to say who can buy similar", "skillcapes.");
stage = 3;
break;
case 3:
end();
break;
case 4:
npc("Certainly! Right when you pay me 99000 coins.");
stage = 5;
break;
case 5:
options("Okay, here you go.", "No, thanks.");
stage = 6;
break;
case 6:
switch (buttonId) {
case 1:
player("Okay, here you go.");
stage = 7;
break;
case 2:
end();
break;
}
break;
case 7:
if (Skillcape.purchase(player, Skills.FISHING)) {
npc("There you go! Enjoy.");
}
stage = 8;
break;
case 8:
end();
break;
}
return true;
}
@Override
public int[] getIds() {
return new int[] { 308 };
}
}
}
@@ -0,0 +1,117 @@
package core.game.content.activity.guild;
import core.cache.def.impl.ObjectDefinition;
import core.game.content.global.EnchantedJewellery;
import core.game.content.global.action.DoorActionHandler;
import core.game.node.entity.skill.summoning.familiar.Familiar;
import core.game.interaction.NodeUsageEvent;
import core.game.interaction.OptionHandler;
import core.game.interaction.UseWithHandler;
import core.game.node.Node;
import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player;
import core.game.node.item.Item;
import core.game.node.object.GameObject;
import core.game.world.update.flag.context.Animation;
import core.plugin.Plugin;
import core.plugin.Initializable;
import core.plugin.PluginManager;
/**
* Represents the hero guild.
* @author Vexia
*/
@Initializable
public final class HeroGuildPlugin extends OptionHandler {
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
ObjectDefinition.forId(2624).getHandlers().put("option:open", this);
ObjectDefinition.forId(2625).getHandlers().put("option:open", this);
PluginManager.definePlugin(new JewelleryRechargePlugin());
return this;
}
@Override
public boolean handle(Player player, Node node, String option) {
final int id = ((GameObject) node).getId();
switch (option) {
case "open":
switch (id) {
case 2624:
case 2625:
// player.getPacketDispatch().sendMessage("You need to complete the Heroes' Quest.");
DoorActionHandler.handleAutowalkDoor(player, (GameObject) node);
break;
}
return true;
}
return true;
}
/**
* Handles the recharging of dragonstone jewellery.
* @author Vexia
*/
public static final class JewelleryRechargePlugin extends UseWithHandler {
/**
* The ids of rechargeable items.
*/
private static final int[] IDS = new int[] { 1710, 1708, 1706, 1704, 11107, 11109, 11111, 11113, 11120, 11122, 11124, 11126, 10354, 10356, 10358, 10360, 10362, 14644,14642,14640,14638, 2572 };
/**
* Constructs a new {@Code JewelleryRechargePlugin} {@Code
* Object}
*/
public JewelleryRechargePlugin() {
super(IDS);
}
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
addHandler(36695, OBJECT_TYPE, this);
addHandler(7339, NPC_TYPE, this);
addHandler(7340, NPC_TYPE, this);
return this;
}
@Override
public boolean handle(NodeUsageEvent event) {
final Player player = event.getPlayer();
final EnchantedJewellery jewellery = EnchantedJewellery.forItem(event.getUsedItem());
if (jewellery == null && event.getUsedItem().getId() != 2572) {
return true;
}
boolean fam = event.getUsedWith() instanceof NPC;
if (fam && jewellery != EnchantedJewellery.AMULET_OF_GLORY & jewellery != EnchantedJewellery.AMULET_OF_GLORY_T) {
return false;
}
if (fam) {
Familiar familiar = (Familiar) event.getUsedWith();
if (!player.getFamiliarManager().isOwner(familiar)) {
return false;
}
familiar.animate(Animation.create(7882));
}
player.lock(1);
player.animate(Animation.create(832));
if(event.getUsedItem().getId() == 2572){
player.getInventory().replace(new Item(14646), event.getUsedItem().getSlot());
} else {
player.getInventory().replace(new Item(jewellery.getIds()[0]), event.getUsedItem().getSlot());
}
String name = event.getUsedItem().getName().toLowerCase();
for (int i = 0; i < 4; i++) {
name = name.replace("(" + (i + 1) + ")", "").trim();
}
if (!fam) {
player.sendMessage("You dip the " + name + " in the fountain...");
} else {
player.sendMessage("Your titan recharges the glory.");
}
return true;
}
}
}
@@ -0,0 +1,64 @@
package core.game.content.activity.guild;
import core.cache.def.impl.ObjectDefinition;
import core.game.content.global.action.ClimbActionHandler;
import core.game.content.global.action.DoorActionHandler;
import core.game.node.entity.skill.Skills;
import core.game.interaction.OptionHandler;
import core.game.node.Node;
import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player;
import core.game.node.object.GameObject;
import core.game.world.map.Location;
import core.game.world.update.flag.context.Animation;
import core.plugin.Initializable;
import core.plugin.Plugin;
/**
* Represents the plugin used for the mining guild.
* @author 'Vexia
* @version 1.0
*/
@Initializable
public final class MiningGuildPlugin extends OptionHandler {
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
ObjectDefinition.forId(2113).getHandlers().put("option:climb-down", this);
ObjectDefinition.forId(30941).getHandlers().put("option:climb-up", this);
ObjectDefinition.forId(2112).getHandlers().put("option:open", this);
return this;
}
@Override
public boolean handle(Player player, Node node, String option) {
if (option.equals("climb-down")) {
if (player.getLocation().withinDistance(Location.create(3019, 3339, 0), 4)) {
if (player.getSkills().getStaticLevel(Skills.MINING) < 60) {
player.getDialogueInterpreter().open(382, NPC.create(382, Location.create(0, 0, 0)), 1);
return true;
}
ClimbActionHandler.climb(player, new Animation(828), Location.create(3021, 9739, 0));
return true;
}
ClimbActionHandler.climbLadder(player, (GameObject) node, option);
return true;
}
if (option.equals("open")) {
if (player.getSkills().getStaticLevel(Skills.MINING) < 60) {
player.getDialogueInterpreter().open(382, NPC.create(382, Location.create(0, 0, 0)), 1);
return true;
}
DoorActionHandler.handleAutowalkDoor(player, (GameObject) node);
}
if (option.equals("climb-up")) {
if (player.getLocation().withinDistance(new Location(3019, 9739, 0))) {
ClimbActionHandler.climb(player, new Animation(828), new Location(3017, 3339, 0));
} else {
ClimbActionHandler.climbLadder(player, (GameObject) node, "climb-up");
}
}
return true;
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,468 @@
package core.game.content.activity.guild;
import core.cache.def.impl.NPCDefinition;
import core.cache.def.impl.ObjectDefinition;
import core.plugin.Initializable;
import core.game.content.dialogue.DialoguePlugin;
import core.game.content.global.Skillcape;
import core.game.content.global.action.ClimbActionHandler;
import core.game.content.global.action.DoorActionHandler;
import core.game.content.global.travel.EssenceTeleport;
import core.game.node.entity.skill.Skills;
import core.game.interaction.OptionHandler;
import core.game.node.Node;
import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player;
import core.game.node.object.GameObject;
import core.game.world.map.Location;
import core.plugin.Plugin;
/**
* Represents the wizard guild plugin.
* @author 'Vexia
* @version 1.0
*/
@Initializable
public final class WizardGuildPlugin extends OptionHandler {
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
ObjectDefinition.forId(1600).getHandlers().put("option:open", this);
ObjectDefinition.forId(1601).getHandlers().put("option:open", this);
NPCDefinition.forId(462).getHandlers().put("option:teleport", this);
ObjectDefinition.forId(2154).getHandlers().put("option:open", this);
ObjectDefinition.forId(2155).getHandlers().put("option:open", this);
ObjectDefinition.forId(1722).getHandlers().put("option:climb-up", this);
new WizardDistentorDialogue().init();
new ZavisticRarveDialogue().init();
new ProfessorImblewynDialogue().init();
new WizardFrumsconeDialogue().init();
new RobeStoreDialogue().init();
return this;
}
@Override
public boolean handle(Player player, Node node, String option) {
final int id = node instanceof GameObject ? ((GameObject) node).getId() : ((NPC) node).getId();
switch (option) {
case "climb-up":
switch (id) {
case 1722:
if (node.getLocation().equals(new Location(2590, 3089, 0))) {
ClimbActionHandler.climb(player, null, Location.create(2591, 3092, 1));
} else {
ClimbActionHandler.climbLadder(player, (GameObject) node, option);
}
break;
}
break;
case "open":
switch (id) {
case 1600:
case 1601:
if (player.getSkills().getStaticLevel(Skills.MAGIC) < 66) {
player.getDialogueInterpreter().sendDialogue("You need a Magic level of at least 66 to enter.");
return true;
}
DoorActionHandler.handleAutowalkDoor(player, (GameObject) node);
break;
case 2155:
case 2154:
player.getDialogueInterpreter().sendDialogues(460, null, "You can't attack the Zombies in the room, my Zombies", "are for magic target practice only and should be", "attacked from the other side of the fence.");
break;
}
break;
case "teleport":
if (!player.getQuestRepository().isComplete("Rune Mysteries")) {
player.getPacketDispatch().sendMessage("You need to have completed the Rune Mysteries Quest to use this feature.");
return true;
}
EssenceTeleport.teleport(((NPC) node), player);
return true;
}
return true;
}
/**
* Represents the wizard distentor dialogue.
* @author 'Vexia
* @version 1.0
*/
public final class WizardDistentorDialogue extends DialoguePlugin {
/**
* Constructs a new {@code WizardDistentorDialogue} {@code Object}.
*/
public WizardDistentorDialogue() {
/**
* empty.
*/
}
/**
* Constructs a new {@code WizardDistentorDialogue} {@code Object}.
* @param player the player.
*/
public WizardDistentorDialogue(final Player player) {
super(player);
}
@Override
public DialoguePlugin newInstance(Player player) {
return new WizardDistentorDialogue(player);
}
@Override
public boolean open(Object... args) {
npc = (NPC) args[0];
npc("Welcome to the Magicians' Guild!");
stage = 0;
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
switch (stage) {
case 0:
player("Hello there.");
stage = 1;
break;
case 1:
npc("What can I do for you?");
stage = 2;
break;
case 2:
if (!player.getQuestRepository().isComplete("Rune Mysteries")) {
player("Nothing thanks, I'm just looking around.");
stage = 4;
return true;
}
options("Nothing thanks, I'm just looking around.", "Can you teleport me to Rune Essence?");
stage = 3;
break;
case 3:
switch (buttonId) {
case 1:
player("Nothing thanks, I'm just looking around.");
stage = 4;
break;
case 2:
player("Can you teleport me to the Rune Essence?");
stage = 6;
break;
}
break;
case 4:
npc("That's fine with me.");
stage = 5;
break;
case 5:
end();
break;
case 6:
end();
EssenceTeleport.teleport(npc, player);
break;
}
return true;
}
@Override
public int[] getIds() {
return new int[] { 462 };
}
}
/**
* Represents the dialogue used for zavistic rarve.
* @author 'Vexia
* @version 1.0
*/
public final class ZavisticRarveDialogue extends DialoguePlugin {
/**
* Constructs a new {@code ZavisticRarveDialogue} {@code Object}.
*/
public ZavisticRarveDialogue() {
/**
* empty.
*/
}
/**
* Constructs a new {@code ZavisticRarveDialogue} {@code Object}.
* @param player the player.
*/
public ZavisticRarveDialogue(final Player player) {
super(player);
}
@Override
public DialoguePlugin newInstance(Player player) {
return new ZavisticRarveDialogue(player);
}
@Override
public boolean open(Object... args) {
npc = (NPC) args[0];
npc("What are you doing...Oh, it's you...sorry...didn't", "realise... what can I do for you?");
stage = 0;
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
switch (stage) {
case 0:
player("Thanks for your help with all of this.");
stage = 1;
break;
case 1:
npc("Ooohh, no thanks required. It's I who should be", "thanking you my friend...your investigative mind has", "shown how vigilant we really should be for this type of", "evil use of the magical arts.");
stage = 2;
break;
case 2:
end();
break;
}
return true;
}
@Override
public int[] getIds() {
return new int[] { 2059 };
}
}
/**
* Represents the wizard distentor dialogue.
* @author 'Vexia
* @version 1.0
*/
public final class ProfessorImblewynDialogue extends DialoguePlugin {
/**
* Constructs a new {@code ProfessorImblewynDialogue} {@code Object}.
*/
public ProfessorImblewynDialogue() {
/**
* empty.
*/
}
/**
* Constructs a new {@code ProfessorImblewynDialogue} {@code Object}.
* @param player the player.
*/
public ProfessorImblewynDialogue(final Player player) {
super(player);
}
@Override
public DialoguePlugin newInstance(Player player) {
return new ProfessorImblewynDialogue(player);
}
@Override
public boolean open(Object... args) {
npc = (NPC) args[0];
player("I didn't realise gnomes were interested in magic.");
stage = 0;
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
switch (stage) {
case 0:
npc("Gnomes are interested in everything, lad.");
stage = 1;
break;
case 1:
player("Of course.");
stage = 2;
break;
case 2:
end();
break;
}
return true;
}
@Override
public int[] getIds() {
return new int[] { 4586 };
}
}
/**
* Represents the dialogue plugin used for the wizard frumscone.
* @author 'Vexia
* @version 1.0
*/
public final class WizardFrumsconeDialogue extends DialoguePlugin {
/**
* Constructs a new {@code WizardFrumsconeDialogue} {@code Object}.
* @param player the player.
*/
public WizardFrumsconeDialogue(final Player player) {
super(player);
}
/**
* Constructs a new {@code WizardFrumsconeDialogue} {@code Object}.
*/
public WizardFrumsconeDialogue() {
/**
* empty.
*/
}
@Override
public DialoguePlugin newInstance(Player player) {
return new WizardFrumsconeDialogue(player);
}
@Override
public boolean open(Object... args) {
npc("Do you like my magic Zombies? Feel free to kill them,", "there's plenty more where these came from!");
stage = 0;
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
end();
return true;
}
@Override
public int[] getIds() {
return new int[] { 460 };
}
}
/**
* Represents the dialogue plugin used for the robe storew owner.
* @author 'Vexia
* @version 1.0
*/
public final class RobeStoreDialogue extends DialoguePlugin {
/**
* Constructs a new {@code RobeStoreDialogue} {@code Object}.
* @param player the player.
*/
public RobeStoreDialogue(final Player player) {
super(player);
}
/**
* Constructs a new {@code RobeStoreDialogue} {@code Object}.
*/
public RobeStoreDialogue() {
/**
* empty.
*/
}
@Override
public DialoguePlugin newInstance(Player player) {
return new RobeStoreDialogue(player);
}
@Override
public boolean open(Object... args) {
npc = (NPC) args[0];
if (Skillcape.isMaster(player, Skills.MAGIC)) {
options("Ask about Skillcape.", "Something else");
stage = 6;
} else {
npc("Welcome to the Magic Guild Store. Would you like to", "buy some magic supplies?");
stage = 0;
}
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
switch (stage) {
case 0:
options("Yes please.", "No thank you.");
stage = 1;
break;
case 1:
switch (buttonId) {
case 1:
player("Yes please.");
stage = 4;
break;
case 2:
player("No thank you.");
stage = 3;
break;
}
break;
case 3:
end();
break;
case 4:
end();
npc.openShop(player);
break;
case 6:
switch (buttonId) {
case 1:
player("Can I buy a Skillcape of Magic?");
stage = 7;
break;
case 2:
npc("Welcome to the Magic Guild Store. Would you like to", "buy some magic supplies?");
stage = 0;
break;
}
break;
case 7:
npc("Certinaly! Right when you give me 99000 coins.");
stage = 8;
break;
case 8:
options("Okay, here you go.", "No, thanks.");
stage = 9;
break;
case 9:
switch (buttonId) {
case 1:
player("Okay, here you go.");
stage = 10;
break;
case 2:
end();
break;
}
break;
case 10:
if (Skillcape.purchase(player, Skills.MAGIC)) {
npc("There you go! Enjoy.");
}
stage = 11;
break;
case 11:
end();
break;
}
return true;
}
@Override
public int[] getIds() {
return new int[] { 1658 };
}
}
}
@@ -0,0 +1,70 @@
/**
* https://oldschool.2009scape.wiki/w/Ecumenical_key
*/
//package core.game.content.activity.gwd;
//
//import core.game.content.global.action.DoorActionHandler;
//import core.game.interaction.NodeUsageEvent;
//import core.game.interaction.UseWithHandler;
//import core.game.node.entity.player.Player;
//import core.game.node.object.GameObject;
//import core.game.world.map.Direction;
//import core.plugin.InitializablePlugin;
//import core.plugin.Plugin;
//
///**
// * Handles the boss room instant-access key.
// * @author Splinter
// */
//@InitializablePlugin
//public class EcumenicalKeyHandler extends UseWithHandler {
//
// /**
// * Constructs a new {@code EcumenicalKeyHandler} {@code Object}
// */
// public EcumenicalKeyHandler() {
// super(14674);
// }
//
// @Override
// public Plugin<Object> newInstance(Object arg) throws Throwable {
// addHandler(26425, OBJECT_TYPE, this);
// addHandler(26426, OBJECT_TYPE, this);
// addHandler(26427, OBJECT_TYPE, this);
// addHandler(26428, OBJECT_TYPE, this);
// return this;
// }
//
// @Override
// public boolean handle(NodeUsageEvent event) {
// final Player player = event.getPlayer();
// final GameObject object = event.getUsedWith().asObject();
// Direction dir = Direction.get((object.getRotation() + 3) % 4);
// if (dir.getStepX() != 0) {
// if (player.getLocation().getX() == object.getLocation().transform(dir.getStepX(), 0, 0).getX()) {
// player.sendMessage("It would be unwise to use the key on this side of the door!");
// return true;
// }
// } else if (player.getLocation().getY() == object.getLocation().transform(0, dir.getStepY(), 0).getY()) {
// player.sendMessage("It would be unwise to use the key on this side of the door!");
// return true;
// }
// player.lock(2);
// player.getInventory().remove(event.getUsedItem());
// player.sendMessage("The key shatters as you insert it into the lock.");
// DoorActionHandler.handleAutowalkDoor(player, event.getUsedWith().asObject());
// return true;
// }
//
//}
/**
* Function to add key into player inventory
* Goes in GodwarsMapZone.java 'death' method
*/
// int count = killer.asPlayer().getBank().getAmount(14674) + killer.asPlayer().getInventory().getAmount(14674);
// int rand = RandomFunction.random(1, 60 + (count * 10));
// if(rand == 15 && count < 3){
// Item item = new Item(14674);
// GroundItemManager.create(item, e.getLocation(), ((Player) killer));
// killer.asPlayer().sendMessage("<col=990000>A crystalline key falls to the ground as you slay your opponent.</col>");
// }
@@ -0,0 +1,171 @@
package core.game.content.activity.gwd;
import java.util.ArrayList;
import java.util.List;
import core.game.node.entity.Entity;
import core.game.node.entity.combat.BattleState;
import core.game.node.entity.combat.CombatStyle;
import core.game.node.entity.combat.CombatSwingHandler;
import core.game.node.entity.combat.InteractionType;
import core.game.node.entity.combat.equipment.ArmourSet;
import core.game.node.entity.impl.Projectile;
import core.game.node.entity.impl.Animator.Priority;
import core.game.node.entity.npc.NPC;
import core.game.world.map.RegionManager;
import core.game.world.map.zone.ZoneBorders;
import core.game.world.update.flag.context.Animation;
import core.tools.RandomFunction;
/**
* Handles General Graardor's combat.
* @author Emperor
*/
public final class GWDGraardorSwingHandler extends CombatSwingHandler {
/**
* The boss chamber.
*/
private static final ZoneBorders CHAMBER = new ZoneBorders(2864, 5351, 2876, 5369);
/**
* The melee attack animation.
*/
private static final Animation MELEE_ATTACK = new Animation(7060, Priority.HIGH);
/**
* The range attack animation.
*/
private static final Animation RANGE_ATTACK = new Animation(7063, Priority.HIGH);
/**
* Constructs a new {@code GWDGraardorSwingHandler} {@Code Object}.
*/
public GWDGraardorSwingHandler() {
super(CombatStyle.MELEE);
}
@Override
public InteractionType canSwing(Entity entity, Entity victim) {
return CombatStyle.MELEE.getSwingHandler().canSwing(entity, victim);
}
@Override
public int swing(Entity entity, Entity victim, BattleState state) {
int ticks = 1;
if (RandomFunction.randomize(10) < 7) {
int hit = 0;
if (CombatStyle.MELEE.getSwingHandler().isAccurateImpact(entity, victim, CombatStyle.MELEE)) {
int max = CombatStyle.MELEE.getSwingHandler().calculateHit(entity, victim, 1.0);
hit = RandomFunction.random(max);
state.setMaximumHit(max);
}
state.setEstimatedHit(hit);
state.setStyle(CombatStyle.MELEE);
} else {
ticks += (int) Math.ceil(entity.getLocation().getDistance(victim.getLocation()) * 0.3);
NPC npc = (NPC) entity;
List<BattleState> list = new ArrayList<>();
for (Entity t : RegionManager.getLocalPlayers(npc, 28)) {
if (!CHAMBER.insideBorder(t.getLocation())) {
continue;
}
if (t.isAttackable(npc, CombatStyle.RANGE)) {
list.add(new BattleState(entity, t));
}
}
BattleState[] targets;
state.setStyle(CombatStyle.RANGE);
state.setTargets(targets = list.toArray(new BattleState[list.size()]));
for (BattleState s : targets) {
s.setStyle(CombatStyle.RANGE);
int hit = 0;
if (CombatStyle.RANGE.getSwingHandler().isAccurateImpact(entity, s.getVictim(), CombatStyle.RANGE)) {
int max = CombatStyle.RANGE.getSwingHandler().calculateHit(entity, s.getVictim(), 1.0);
s.setMaximumHit(max);
hit = RandomFunction.random(max);
}
s.setEstimatedHit(hit);
}
}
return ticks;
}
@Override
public void visualize(Entity entity, Entity victim, BattleState state) {
switch (state.getStyle()) {
case MELEE:
entity.animate(MELEE_ATTACK);
break;
default:
entity.animate(RANGE_ATTACK);
for (BattleState s : state.getTargets()) {
Projectile.ranged(entity, s.getVictim(), 1200, 0, 0, 46, 1).send();
}
break;
}
}
@Override
public ArmourSet getArmourSet(Entity e) {
return getType().getSwingHandler().getArmourSet(e);
}
@Override
public double getSetMultiplier(Entity e, int skillId) {
return getType().getSwingHandler().getSetMultiplier(e, skillId);
}
@Override
public void impact(Entity entity, Entity victim, BattleState state) {
if (state.getStyle() == CombatStyle.MELEE) {
state.getStyle().getSwingHandler().impact(entity, victim, state);
return;
}
for (BattleState s : state.getTargets()) {
if (s == null || s.getEstimatedHit() < 0) {
continue;
}
int hit = s.getEstimatedHit();
s.getVictim().getImpactHandler().handleImpact(entity, hit, CombatStyle.RANGE, s);
}
}
@Override
public void visualizeImpact(Entity entity, Entity victim, BattleState state) {
if (state.getStyle() == CombatStyle.MELEE) {
victim.animate(victim.getProperties().getDefenceAnimation());
return;
}
for (BattleState s : state.getTargets()) {
s.getVictim().animate(s.getVictim().getProperties().getDefenceAnimation());
}
}
@Override
public void adjustBattleState(Entity entity, Entity victim, BattleState state) {
if (state.getStyle() == CombatStyle.MELEE) {
state.getStyle().getSwingHandler().adjustBattleState(entity, victim, state);
return;
}
for (BattleState s : state.getTargets()) {
CombatStyle.RANGE.getSwingHandler().adjustBattleState(entity, s.getVictim(), s);
}
}
@Override
public int calculateAccuracy(Entity entity) {
return getType().getSwingHandler().calculateAccuracy(entity);
}
@Override
public int calculateDefence(Entity entity, Entity attacker) {
return getType().getSwingHandler().calculateDefence(entity, attacker);
}
@Override
public int calculateHit(Entity entity, Entity victim, double modifier) {
return getType().getSwingHandler().calculateHit(entity, victim, modifier);
}
}
@@ -0,0 +1,204 @@
package core.game.content.activity.gwd;
import java.util.ArrayList;
import java.util.List;
import core.game.node.entity.Entity;
import core.game.node.entity.combat.BattleState;
import core.game.node.entity.combat.CombatStyle;
import core.game.node.entity.combat.CombatSwingHandler;
import core.game.node.entity.combat.InteractionType;
import core.game.node.entity.combat.equipment.ArmourSet;
import core.game.node.entity.impl.Projectile;
import core.game.node.entity.impl.Animator.Priority;
import core.game.node.entity.npc.NPC;
import core.game.world.map.Direction;
import core.game.world.map.Location;
import core.game.world.map.RegionManager;
import core.game.world.map.zone.ZoneBorders;
import core.game.world.update.flag.context.Animation;
import core.game.world.update.flag.context.Graphics;
import core.tools.RandomFunction;
/**
* Handles Kree'arra's combat.
* @author Emperor
*/
public final class GWDKreeArraSwingHandler extends CombatSwingHandler {
/**
* The boss chamber.
*/
private static final ZoneBorders CHAMBER = new ZoneBorders(2824, 5296, 2842, 5308);
/**
* The melee attack animation.
*/
private static final Animation MELEE_ATTACK = new Animation(6977, Priority.HIGH);
/**
* The range attack animation.
*/
private static final Animation RANGE_ATTACK = new Animation(6976, Priority.HIGH);
/**
* The end graphic.
*/
private static final Graphics END_GRAPHIC = new Graphics(80, 96);
/**
* Constructs a new {@code GWDKreeArraSwingHandler} {@Code Object}.
*/
public GWDKreeArraSwingHandler() {
super(CombatStyle.RANGE);
}
@Override
public InteractionType canSwing(Entity entity, Entity victim) {
return CombatStyle.RANGE.getSwingHandler().canSwing(entity, victim);
}
@Override
public int swing(Entity entity, Entity victim, BattleState state) {
int ticks = 1;
int distance = entity.size() >> 1;
if (!entity.inCombat()) {
distance++;
}
if (victim.getLocation().withinDistance(entity.getCenterLocation(), distance) && RandomFunction.RANDOM.nextBoolean()) {
int hit = 0;
int max = CombatStyle.MELEE.getSwingHandler().calculateHit(entity, victim, 1.0);
if (CombatStyle.MELEE.getSwingHandler().isAccurateImpact(entity, victim, CombatStyle.MELEE)) {
hit = RandomFunction.random(max);
}
state.setEstimatedHit(hit);
hit = 0;
if (CombatStyle.MELEE.getSwingHandler().isAccurateImpact(entity, victim, CombatStyle.MELEE)) {
hit = RandomFunction.random(max);
}
state.setSecondaryHit(hit);
state.setMaximumHit(max);
state.setStyle(CombatStyle.MELEE);
} else {
ticks += (int) Math.ceil(entity.getLocation().getDistance(victim.getLocation()) * 0.3);
NPC npc = (NPC) entity;
List<BattleState> list = new ArrayList<>();
for (Entity t : RegionManager.getLocalPlayers(npc, 28)) {
if (!CHAMBER.insideBorder(t.getLocation())) {
continue;
}
if (t.isAttackable(npc, CombatStyle.RANGE)) {
list.add(new BattleState(entity, t));
}
}
BattleState[] targets;
state.setStyle(CombatStyle.RANGE);
state.setTargets(targets = list.toArray(new BattleState[list.size()]));
for (BattleState s : targets) {
CombatStyle style = RandomFunction.randomize(10) < 3 ? CombatStyle.MAGIC : CombatStyle.RANGE;
s.setStyle(style);
int hit = 0;
if (style.getSwingHandler().isAccurateImpact(entity, s.getVictim(), style)) {
int max = style.getSwingHandler().calculateHit(entity, s.getVictim(), 1.0);
s.setMaximumHit(max);
if(style.equals(CombatStyle.RANGE)){
max = 71;
}
hit = RandomFunction.random(max);
}
s.setEstimatedHit(hit);
}
}
return ticks;
}
@Override
public void visualize(Entity entity, Entity victim, BattleState state) {
switch (state.getStyle()) {
case MELEE:
entity.animate(MELEE_ATTACK);
break;
default:
entity.animate(RANGE_ATTACK);
for (BattleState s : state.getTargets()) {
int gfxId = 1197;
if (s.getStyle() == CombatStyle.MAGIC) {
gfxId = 1198;
}
Projectile.ranged(entity, s.getVictim(), gfxId, 92, 36, 46, 5).send();
}
break;
}
}
@Override
public ArmourSet getArmourSet(Entity e) {
return getType().getSwingHandler().getArmourSet(e);
}
@Override
public double getSetMultiplier(Entity e, int skillId) {
return getType().getSwingHandler().getSetMultiplier(e, skillId);
}
@Override
public void impact(Entity entity, Entity victim, BattleState state) {
if (state.getStyle() == CombatStyle.MELEE) {
state.getStyle().getSwingHandler().impact(entity, victim, state);
return;
}
for (BattleState s : state.getTargets()) {
if (s == null || s.getEstimatedHit() < 0) {
continue;
}
int hit = s.getEstimatedHit();
s.getVictim().getImpactHandler().handleImpact(entity, hit, s.getStyle(), s);
}
}
@Override
public void visualizeImpact(Entity entity, Entity victim, BattleState state) {
if (state.getStyle() == CombatStyle.MELEE) {
victim.animate(victim.getProperties().getDefenceAnimation());
return;
}
for (BattleState s : state.getTargets()) {
s.getVictim().animate(s.getVictim().getProperties().getDefenceAnimation());
if (RandomFunction.randomize(10) < 8) {
Direction dir = Direction.getLogicalDirection(entity.getLocation(), s.getVictim().getLocation());
Location destination = s.getVictim().getLocation().transform(dir.getStepX(), dir.getStepY(), 0);
if (CHAMBER.insideBorder(destination)) {
s.getVictim().getProperties().setTeleportLocation(destination);
s.getVictim().graphics(END_GRAPHIC);
}
}
}
}
@Override
public void adjustBattleState(Entity entity, Entity victim, BattleState state) {
if (state.getStyle() == CombatStyle.MELEE) {
state.getStyle().getSwingHandler().adjustBattleState(entity, victim, state);
return;
}
for (BattleState s : state.getTargets()) {
s.getStyle().getSwingHandler().adjustBattleState(entity, s.getVictim(), s);
}
}
@Override
public int calculateAccuracy(Entity entity) {
return getType().getSwingHandler().calculateAccuracy(entity);
}
@Override
public int calculateDefence(Entity entity, Entity attacker) {
return getType().getSwingHandler().calculateDefence(entity, attacker);
}
@Override
public int calculateHit(Entity entity, Entity victim, double modifier) {
return getType().getSwingHandler().calculateHit(entity, victim, modifier);
}
}
@@ -0,0 +1,155 @@
package core.game.content.activity.gwd;
import core.game.node.entity.Entity;
import core.game.node.entity.combat.BattleState;
import core.game.node.entity.combat.CombatStyle;
import core.game.node.entity.combat.CombatSwingHandler;
import core.game.node.entity.combat.InteractionType;
import core.game.node.entity.combat.equipment.ArmourSet;
import core.game.node.entity.impl.Projectile;
import core.game.node.entity.impl.Animator.Priority;
import core.game.node.entity.player.Player;
import core.game.node.entity.state.EntityState;
import core.game.world.update.flag.context.Animation;
import core.game.world.update.flag.context.Graphics;
import core.tools.RandomFunction;
/**
* Handles K'ril Tsutsaroth's combat.
* @author Emperor
*/
public final class GWDTsutsarothSwingHandler extends CombatSwingHandler {
/**
* The melee attack animation.
*/
private static final Animation MELEE_ATTACK = new Animation(6945, Priority.HIGH);
/**
* The range attack animation.
*/
private static final Animation MAGIC_ATTACK = new Animation(6947, Priority.HIGH);
/**
* The magic start graphic.
*/
private static final Graphics MAGIC_START = new Graphics(1210);
/**
* If K'ril is performing its special attack.
*/
private boolean special;
/**
* Constructs a new {@code GWDTsutsarothSwingHandler} {@Code Object}.
*/
public GWDTsutsarothSwingHandler() {
super(CombatStyle.MELEE);
}
@Override
public InteractionType canSwing(Entity entity, Entity victim) {
return CombatStyle.MELEE.getSwingHandler().canSwing(entity, victim);
}
@Override
public int swing(Entity entity, Entity victim, BattleState state) {
int ticks = 1;
special = false;
int hit = 0;
CombatStyle style = CombatStyle.MELEE;
if (RandomFunction.randomize(10) < 4) {
ticks += (int) Math.ceil(entity.getLocation().getDistance(victim.getLocation()) * 0.3);
style = CombatStyle.MAGIC;
} else if (RandomFunction.randomize(10) == 0) {
if (special = (victim instanceof Player)) {
((Player) victim).getPacketDispatch().sendMessage("K'ril Tsutsaroth slams through your protection prayer, leaving you feeling drained.");
}
entity.sendChat("YARRRRRRR!");
}
if (style.getSwingHandler().isAccurateImpact(entity, victim)) {
int max = style.getSwingHandler().calculateHit(entity, victim, special ? 1.08 : 1.0);
hit = RandomFunction.random(max);
state.setMaximumHit(max);
if (style == CombatStyle.MELEE) {
victim.getStateManager().register(EntityState.POISONED, false, 168, entity);
}
if (special) {
((Player) victim).getSkills().decrementPrayerPoints(hit / 2);
}
}
state.setEstimatedHit(hit);
state.setStyle(style);
return ticks;
}
@Override
public void visualize(Entity entity, Entity victim, BattleState state) {
switch (state.getStyle()) {
case MELEE:
entity.animate(MELEE_ATTACK);
break;
default:
entity.visualize(MAGIC_ATTACK, MAGIC_START);
Projectile.magic(entity, victim, 1211, 0, 0, 46, 1).send();
break;
}
}
@Override
public ArmourSet getArmourSet(Entity e) {
return getType().getSwingHandler().getArmourSet(e);
}
@Override
public double getSetMultiplier(Entity e, int skillId) {
return getType().getSwingHandler().getSetMultiplier(e, skillId);
}
@Override
public void impact(Entity entity, Entity victim, BattleState state) {
if (state.getStyle() == CombatStyle.MAGIC) {
if (state.getEstimatedHit() > -1) {
victim.getImpactHandler().handleImpact(entity, state.getEstimatedHit(), CombatStyle.MAGIC, state);
}
return;
}
state.getStyle().getSwingHandler().impact(entity, victim, state);
}
@Override
public void visualizeImpact(Entity entity, Entity victim, BattleState state) {
victim.animate(victim.getProperties().getDefenceAnimation());
}
@Override
public void adjustBattleState(Entity entity, Entity victim, BattleState state) {
super.adjustBattleState(entity, victim, state);
}
@Override
protected int getFormattedHit(Entity entity, Entity victim, BattleState state, int hit) {
if (!special) {
if (state.getArmourEffect() != ArmourSet.VERAC && victim.hasProtectionPrayer(state.getStyle())) {
hit *= entity instanceof Player ? 0.6 : 0;
}
}
return formatHit(victim, hit);
}
@Override
public int calculateAccuracy(Entity entity) {
return getType().getSwingHandler().calculateAccuracy(entity);
}
@Override
public int calculateDefence(Entity entity, Entity attacker) {
return getType().getSwingHandler().calculateDefence(entity, attacker);
}
@Override
public int calculateHit(Entity entity, Entity victim, double modifier) {
return getType().getSwingHandler().calculateHit(entity, victim, modifier);
}
}
@@ -0,0 +1,146 @@
package core.game.content.activity.gwd;
import java.util.ArrayList;
import java.util.List;
import core.game.node.entity.Entity;
import core.game.node.entity.combat.BattleState;
import core.game.node.entity.combat.CombatStyle;
import core.game.node.entity.combat.CombatSwingHandler;
import core.game.node.entity.combat.InteractionType;
import core.game.node.entity.combat.equipment.ArmourSet;
import core.game.node.entity.impl.Animator.Priority;
import core.game.node.entity.npc.NPC;
import core.game.world.map.RegionManager;
import core.game.world.update.flag.context.Animation;
import core.game.world.update.flag.context.Graphics;
import core.tools.RandomFunction;
/**
* Handles the Commander Zilyana combat.
* @author Emperor
*/
public class GWDZilyanaSwingHandler extends CombatSwingHandler {
/**
* The melee attack animation.
*/
private static final Animation MELEE_ATTACK = new Animation(6964, Priority.HIGH);
/**
* The magic attack animation.
*/
private static final Animation MAGIC_ATTACK = new Animation(6967, Priority.HIGH);
/**
* The magic end graphic.
*/
private static final Graphics MAGIC_END_GRAPHIC = new Graphics(1207);
/**
* Constructs a new {@code ZilyanaSwingHandler} {@Code Object}.
*/
public GWDZilyanaSwingHandler() {
super(CombatStyle.MAGIC);
}
@Override
public InteractionType canSwing(Entity entity, Entity victim) {
return CombatStyle.MELEE.getSwingHandler().canSwing(entity, victim);
}
@Override
public int swing(Entity entity, Entity victim, BattleState state) {
BattleState[] targets;
if (RandomFunction.randomize(10) < 7) {
targets = new BattleState[] { state };
setType(CombatStyle.MELEE);
state.setStyle(CombatStyle.MELEE);
} else {
NPC npc = (NPC) entity;
List<BattleState> list = new ArrayList<>();
for (Entity t : RegionManager.getLocalPlayers(npc.getCenterLocation(), (npc.size() >> 1) + 2)) {
if (t.getLocation().getX() < 2908 && t.isAttackable(npc, CombatStyle.MAGIC)) {
list.add(new BattleState(entity, t));
}
}
state.setTargets(targets = list.toArray(new BattleState[list.size()]));
state.setStyle(CombatStyle.MAGIC);
setType(CombatStyle.MAGIC);
}
for (BattleState s : targets) {
s.setStyle(state.getStyle());
int hit = getType() == CombatStyle.MAGIC ? -1 : 0;
if (isAccurateImpact(entity, s.getVictim())) {
int max = calculateHit(entity, s.getVictim(), 1.0);
s.setMaximumHit(max);
hit = RandomFunction.random(max);
}
s.setEstimatedHit(hit);
}
return 1;
}
@Override
public void visualize(Entity entity, Entity victim, BattleState state) {
switch (getType()) {
case MELEE:
entity.animate(MELEE_ATTACK);
break;
case MAGIC:
entity.animate(MAGIC_ATTACK);
break;
default:
break;
}
}
@Override
public ArmourSet getArmourSet(Entity e) {
return getType().getSwingHandler().getArmourSet(e);
}
@Override
public double getSetMultiplier(Entity e, int skillId) {
return getType().getSwingHandler().getSetMultiplier(e, skillId);
}
@Override
public void impact(Entity entity, Entity victim, BattleState state) {
state.getStyle().getSwingHandler().impact(entity, victim, state);
}
@Override
public void adjustBattleState(Entity entity, Entity victim, BattleState state) {
state.getStyle().getSwingHandler().adjustBattleState(entity, victim, state);
}
@Override
public int calculateAccuracy(Entity entity) {
return getType().getSwingHandler().calculateAccuracy(entity);
}
@Override
public int calculateDefence(Entity entity, Entity attacker) {
return getType().getSwingHandler().calculateDefence(entity, attacker);
}
@Override
public int calculateHit(Entity entity, Entity victim, double modifier) {
return getType().getSwingHandler().calculateHit(entity, victim, modifier);
}
@Override
public void visualizeImpact(Entity entity, Entity victim, BattleState state) {
if (state.getStyle() == CombatStyle.MAGIC) {
for (BattleState s : state.getTargets()) {
if (s.getEstimatedHit() > 0) {
s.getVictim().graphics(MAGIC_END_GRAPHIC);
}
}
return;
}
state.getStyle().getSwingHandler().visualizeImpact(entity, victim, state);
}
}
@@ -0,0 +1,99 @@
package core.game.content.activity.gwd;
import core.game.node.entity.player.Player;
import core.game.node.item.Item;
/**
* The god wars factions.
* @author Emperor
*/
public enum GodWarsFaction {
ARMADYL(6222, 6246, 87, 11694, 11718, 11720, 11722, 12670, 12671, 14671),
BANDOS(6260, 6283, 11061, 11696, 11724, 11726, 11728),
SARADOMIN(6247, 6259, 1718, 2412, 2415, 2661, 2663, 2665, 2667, 3479, 3675, 3489, 3840, 4682, 6762, 8055, 10384, 10386, 10388, 10390, 10440, 10446, 10452, 10458, 10464, 10470, 11181, 11698, 11730,542,544),
ZAMORAK(6203, 6221, 11716, 11700, 1724, 2414, 2417, 2653, 2655, 2657, 2659, 3478, 3674, 3841, 3842, 3852, 4683, 6764, 8056, 10368, 10370, 10372, 10374, 10444, 10450, 10456, 10460, 10468, 10474, 10776, 10786, 10790, 14662);
/**
* The start NPC id.
*/
private final int startId;
/**
* The end NPC id.
*/
private final int endId;
/**
* The protection items.
*/
private final int[] protectionItems;
/**
* Constructs a new {@code GodWarsFaction} {@code Object}.
* @param startId The start NPC id.
* @param endId The end NPC id.
* @param protectionItems The protection items for this faction.
*/
private GodWarsFaction(int startId, int endId, int... protectionItems) {
this.startId = startId;
this.endId = endId;
this.protectionItems = protectionItems;
}
/**
* Gets the god wars faction for the given NPC id.
* @param npcId The NPC id.
* @return The faction for this NPC.
*/
public static GodWarsFaction forId(int npcId) {
for (GodWarsFaction faction : values()) {
if (npcId >= faction.getStartId() && npcId <= faction.getEndId()) {
return faction;
}
}
return null;
}
/**
* Checks if the player is protected from this faction.
* @param player The player.
* @return {@code True} if no NPCs of this faction should attack the
* player.
*/
public boolean isProtected(Player player) {
for (Item item : player.getEquipment().toArray()) {
if (item != null) {
for (int id : protectionItems) {
if (item.getId() == id) {
return true;
}
}
}
}
return false;
}
/**
* Gets the startId.
* @return The startId.
*/
public int getStartId() {
return startId;
}
/**
* Gets the endId.
* @return The endId.
*/
public int getEndId() {
return endId;
}
/**
* Gets the protectionItems.
* @return The protectionItems.
*/
public int[] getProtectionItems() {
return protectionItems;
}
}
@@ -0,0 +1,100 @@
package core.game.content.activity.gwd;
import core.game.node.entity.Entity;
import core.game.node.entity.combat.CombatStyle;
import core.game.node.entity.combat.DeathTask;
import core.game.node.entity.npc.AbstractNPC;
import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player;
import core.game.world.GameWorld;
import core.plugin.Initializable;
import core.game.world.map.Location;
/**
* Handles a god wars minion NPC.
* @author Emperor
*/
@Initializable
public final class GodWarsMinionNPC extends AbstractNPC {
/**
* The boss NPC.
*/
private NPC boss;
/**
* Constructs a new {@code GodWarsMinionNPC} {@code Object}.
*/
public GodWarsMinionNPC() {
super(6223, null);
}
/**
* Constructs a new {@code GodWarsMinionNPC} {@code Object}.
* @param id The NPC id.
* @param location The location.
*/
public GodWarsMinionNPC(int id, Location location) {
super(id, location);
}
@Override
public void init() {
super.init();
}
@Override
public void tick() {
super.tick();
if (boss != null && boss.inCombat()) {
Entity target = boss.getAttribute("combat-attacker");
if (target != null && (target != getProperties().getCombatPulse().getVictim() || !getProperties().getCombatPulse().isAttacking())) {
if (!getProperties().getCombatPulse().isAttacking() && !DeathTask.isDead(this)) {
// getProperties().getCombatPulse().attack(target);
} else {
getProperties().getCombatPulse().setVictim(target);
face(target);
}
}
}
}
@Override
public void finalizeDeath(Entity killer) {
super.finalizeDeath(killer);
getProperties().getCombatPulse().stop();
if (boss != null && boss.getRespawnTick() > GameWorld.getTicks()) {
setRespawnTick(boss.getRespawnTick());
}
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new GodWarsMinionNPC(id, location);
}
@Override
public Object fireEvent(String identifier, Object... args) {
switch (identifier) {
case "set_boss":
boss = (NPC) args[0];
return true;
}
return null;
}
@Override
public boolean isAttackable(Entity entity, CombatStyle style) {
if (boss != null && boss.getId() == 6222 && style == CombatStyle.MELEE && entity instanceof Player) {
((Player) entity).getPacketDispatch().sendMessage("The aviansie is flying too high for you to attack using melee.");
return false;
}
return super.isAttackable(entity, style);
}
@Override
public int[] getIds() {
return new int[] { 6204, 6206, 6208, 6223, 6225, 6227, 6248, 6250, 6252, 6261, 6263, 6265 };
}
}
@@ -0,0 +1,123 @@
package core.game.content.activity.gwd;
import java.util.ArrayList;
import java.util.List;
import core.game.node.entity.Entity;
import core.game.node.entity.combat.CombatStyle;
import core.game.node.entity.combat.DeathTask;
import core.game.node.entity.npc.AbstractNPC;
import core.game.node.entity.npc.NPC;
import core.game.node.entity.npc.agg.AggressiveBehavior;
import core.game.node.entity.npc.agg.AggressiveHandler;
import core.game.node.entity.player.Player;
import core.game.world.map.Location;
import core.plugin.Initializable;
import core.game.world.map.RegionManager;
/**
* Handles a god wars NPC.
* @author Emperor
*/
@Initializable
public final class GodWarsNPC extends AbstractNPC {
/**
* The aggressive behavior.
*/
private static final AggressiveBehavior AGGRO_BEHAVIOR = new AggressiveBehavior() {
@Override
public boolean canSelectTarget(Entity entity, Entity target) {
if (!target.isActive() || DeathTask.isDead(target) || DeathTask.isDead(entity)) {
return false;
}
if (!target.getProperties().isMultiZone() && target.inCombat()) {
return false;
}
if (target instanceof GodWarsNPC) {
if (((GodWarsNPC) target).faction != ((GodWarsNPC) entity).faction) {
return true;
}
} else if (target instanceof Player) {
if (!((GodWarsNPC) entity).faction.isProtected((Player) target)) {
return true;
}
}
return false;
}
@Override
public List<Entity> getPossibleTargets(Entity entity, int radius) {
List<Entity> targets = new ArrayList<>();
for (Player player : RegionManager.getLocalPlayers(entity, radius)) {
if (canSelectTarget(entity, player)) {
targets.add(player);
}
}
if (!targets.isEmpty()) {
return targets;
}
for (NPC npc : RegionManager.getLocalNpcs(entity, radius)) {
if (canSelectTarget(entity, npc)) {
targets.add(npc);
}
}
return targets;
}
};
/**
* The god wars faction (0=armadyl, 1=bandos, 2=saradomin, 3=zamorak).
*/
private GodWarsFaction faction;
/**
* Constructs a new {@code GodWarsNPC} {@code Object}.
*/
public GodWarsNPC() {
super(-1, null);
}
/**
* Constructs a new {@code GodWarsNPC} {@code Object}.
* @param id The NPC id.
* @param location The location.
*/
public GodWarsNPC(int id, Location location) {
super(id, location);
}
@Override
public void init() {
super.init();
setWalks(true);
faction = GodWarsFaction.forId(getId());
}
@Override
public void setDefaultBehavior() {
setAggressive(true);
aggressiveHandler = new AggressiveHandler(this, AGGRO_BEHAVIOR);
}
@Override
public boolean isAttackable(Entity entity, CombatStyle style) {
if (style == CombatStyle.MELEE && faction == GodWarsFaction.ARMADYL && entity instanceof Player) {
((Player) entity).getPacketDispatch().sendMessage("The aviansie is flying too high for you to attack using melee.");
return false;
}
return super.isAttackable(entity, style);
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new GodWarsNPC(id, location);
}
@Override
public int[] getIds() {
return new int[] { 6210, 6211, 6212, 6213, 6214, 6215, 6216, 6217, 6218, 6219, 6220, 6221, 6229, 6230, 6231, 6232, 6233, 6234, 6235, 6236, 6237, 6238, 6239, 6240, 6241, 6242, 6243, 6244, 6245, 6246, 6254, 6255, 6256, 6257, 6258, 6259, 6267, 6268, 6269, 6270, 6271, 6272, 6273, 6274, 6275, 6276, 6277, 6278, 6279, 6280, 6281, 6282, 6283 };
}
}
@@ -0,0 +1,308 @@
package core.game.content.activity.gwd;
import core.game.content.global.BossKillCounter;
import core.game.node.entity.Entity;
import core.game.node.entity.combat.BattleState;
import core.game.node.entity.combat.CombatPulse;
import core.game.node.entity.combat.CombatStyle;
import core.game.node.entity.combat.CombatSwingHandler;
import core.game.node.entity.combat.DeathTask;
import core.game.node.entity.npc.AbstractNPC;
import core.game.node.entity.npc.NPC;
import core.game.node.entity.npc.agg.AggressiveBehavior;
import core.game.node.entity.npc.agg.AggressiveHandler;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.prayer.PrayerType;
import core.game.world.GameWorld;
import core.game.world.map.Location;
import core.game.world.map.zone.ZoneBorders;
import core.plugin.Initializable;
import core.tools.RandomFunction;
/**
* Handles a god wars boss NPC.
* @author Emperor
*/
@Initializable
public final class GodwarsBossNPC extends AbstractNPC {
/**
* Handles the combat swing of Commander Zilyana.
*/
private static final CombatSwingHandler ZILYANA_COMBAT = new GWDZilyanaSwingHandler();
/**
* Handles the combat swing of Kree'arra.
*/
private static final CombatSwingHandler KREE_ARRA_COMBAT = new GWDKreeArraSwingHandler();
/**
* Handles the combat swing of General Graardor.
*/
private static final CombatSwingHandler GRAARDOR_COMBAT = new GWDGraardorSwingHandler();
/**
* Handles the combat swing of General Graardor.
*/
private static final CombatSwingHandler TSUTSAROTH_COMBAT = new GWDTsutsarothSwingHandler();
/**
* The battle cries.
*/
private static final String[][] BATTLE_CRIES = { { // Zamorak
"Attack them, you dogs!", "Forward!", "Death to Saradomin's dogs!", "Kill them, you cowards!", "The Dark One will have their souls!", "Zamorak curse them!", "Rend them limb from limb!", "No retreat!", "Flay them all!" }, { // Armadyl
"Kraaaw!" }, { // Saradomin
"Death to the enemies of the light!", "Slay the evil ones!", "Saradomin lend me strength!", "By the power of Saradomin!", "May Saradomin be my sword.", "Good will always triumph!", "Forward! Our allies are with us!", "Saradomin is with us!", "In the name of Saradomin!", "Attack! Find the Godsword!" }, { // Bandos
"Death to our enemies!", "Brargh!", "Break their bones!", "For the glory of Bandos!", "Split their skulls!", "We feast on the bones of our enemies tonight!", "CHAAARGE!", "Crush them underfoot!", "All glory to Bandos!", "GRAAAAAAAAAAAR!", "FOR THE GLORY OF THE BIG HIGH WAR GOD!" } };
/**
* The minions.
*/
private NPC[] minions;
/**
* The boss chamber.
*/
private ZoneBorders chamber;
/**
* The next battle cry tick.
*/
private int nextBattleCry;
/**
* The combat swing handler.
*/
private CombatSwingHandler handler;
/**
* If the NPC focuses on one target.
*/
private boolean targetFocus;
/**
* Constructs a new {@code CommanderZilyanaNPC} {@code Object}.
*/
public GodwarsBossNPC() {
super(6203, null);
}
/**
* Constructs a new {@code CommanderZilyanaNPC} {@code Object}.
* @param id The NPC id.
* @param location The location.
*/
public GodwarsBossNPC(int id, Location location) {
super(id, location);
}
@Override
public void init() {
setAggressive(false);
super.init();
switch (getId()) {
case 6203:
chamber = new ZoneBorders(2918, 5318, 2936, 5331);
handler = TSUTSAROTH_COMBAT;
targetFocus = true;
break;
case 6222:
chamber = new ZoneBorders(2824, 5296, 2842, 5308);
handler = KREE_ARRA_COMBAT;
break;
case 6247:
chamber = new ZoneBorders(2889, 5258, 2907, 5276);
handler = ZILYANA_COMBAT;
break;
case 6260:
chamber = new ZoneBorders(2864, 5351, 2876, 5369);
handler = GRAARDOR_COMBAT;
targetFocus = true;
break;
}
AggressiveBehavior behavior = null;
if (chamber != null) {
final ZoneBorders borders = chamber;
behavior = new AggressiveBehavior() {
@Override
public boolean canSelectTarget(Entity entity, Entity target) {
if (!target.isActive() || DeathTask.isDead(target)) {
return false;
}
if (!target.getProperties().isMultiZone() && target.inCombat()) {
return false;
}
return borders.insideBorder(target.getLocation());
}
};
super.setAggressiveHandler(new AggressiveHandler(this, behavior));
if (chamber.insideBorder(getLocation())) {
minions = new NPC[3];
for (int i = 0; i < 3; i++) {
int npcId = getId() + 1 + (i << 1);
AbstractNPC npc = (AbstractNPC) (minions[i] = NPC.create(npcId, getSpawnLocation(npcId)));
npc.init();
npc.fireEvent("set_boss", this);
if (behavior != null) {
npc.setAggressiveHandler(new AggressiveHandler(npc, behavior));
npc.getAggressiveHandler().setChanceRatio(6);
npc.getAggressiveHandler().setAllowTolerance(false);
npc.getAggressiveHandler().setRadius(28);
}
}
}
}
getProperties().setNPCWalkable(true);
getProperties().setCombatTimeOut(2);
getAggressiveHandler().setChanceRatio(6);
getAggressiveHandler().setRadius(28);
getAggressiveHandler().setAllowTolerance(false);
walkRadius = 28;
}
@Override
public void tick() {
CombatPulse pulse = getProperties().getCombatPulse();
if (chamber != null && pulse.isAttacking()) {
Entity e = pulse.getVictim();
if (!targetFocus) {
Entity target = getImpactHandler().getMostDamageEntity(null);
if (target != null && target != e && target instanceof Player) {
pulse.setVictim(target);
}
}
if (!chamber.insideBorder(e.getLocation().getX(), e.getLocation().getY())) {
getPulseManager().clear();
}
if (nextBattleCry < GameWorld.getTicks()) {
String[] cries = BATTLE_CRIES[(getId() - 6203) >> 4];
sendChat(cries[RandomFunction.randomize(cries.length)]);
nextBattleCry = GameWorld.getTicks() + 7 + RandomFunction.randomize(20);
}
}
super.tick();
if (getRespawnTick() == GameWorld.getTicks() && minions != null) {
for (NPC npc : minions) {
npc.setRespawnTick(-1);
}
}
}
@Override
public void onImpact(final Entity entity, BattleState state) {
if (targetFocus) {
if (getProperties().getCombatPulse().getNextAttack() < GameWorld.getTicks() - 3) {
getProperties().getCombatPulse().attack(entity);
return;
}
}
super.onImpact(entity, state);
}
@Override
public void sendImpact(BattleState state) {
if (state.getVictim() == null || getId() != 6222) {
return;
}
int max = 0;
if (state.getVictim().isPlayer() && state.getEstimatedHit() > 0) {
switch (state.getStyle()) {
case MAGIC:
max = 21;
break;
case MELEE:
max = 26;
break;
case RANGE:
max = 71;
break;
}
}
if (state.getEstimatedHit() > max) {
state.setEstimatedHit(RandomFunction.random(max - 10));
}
if (state.getStyle() == CombatStyle.RANGE && state.getVictim().asPlayer().getPrayer().get(PrayerType.PROTECT_FROM_MISSILES)) {
state.neutralizeHits();
}
}
@Override
public void finalizeDeath(Entity killer) {
super.finalizeDeath(killer);
if (getId() == 6222 || getId() == 6260 || getId() == 6247 || getId() == 6203) {
BossKillCounter.addtoKillcount((Player) killer, this.getId());
}
if (minions == null) {
return;
}
for (NPC minion : minions) {
if (minion.getRespawnTick() >= GameWorld.getTicks()) {
minion.setRespawnTick(getRespawnTick());
}
}
}
@Override
public boolean isAttackable(Entity entity, CombatStyle style) {
if (getId() == 6222 && style == CombatStyle.MELEE && entity instanceof Player) {
((Player) entity).getPacketDispatch().sendMessage("The aviansie is flying too high for you to attack using melee.");
return false;
}
return super.isAttackable(entity, style);
}
/**
* Gets the spawn location for the given NPC id.
* @param id The NPC id.
* @return The spawn location.
*/
private Location getSpawnLocation(int id) {
switch (id) {
case 6208:
return Location.create(2920, 5320, 2);
case 6206:
return Location.create(2919, 5327, 2);
case 6204:
return Location.create(2927, 5325, 2);
case 6223:
return Location.create(2828, 5298, 2);
case 6225:
return Location.create(2837, 5299, 2);
case 6227:
return Location.create(2834, 5302, 2);
case 6248:
return Location.create(2898, 5267, 0);
case 6250:
return Location.create(2901, 5268, 0);
case 6252:
return Location.create(2895, 5260, 0);
case 6265:
return Location.create(2866, 5363, 2);
case 6261:
return Location.create(2867, 5354, 2);
case 6263:
return Location.create(2873, 5354, 2);
}
return null;
}
@Override
public CombatSwingHandler getSwingHandler(boolean swing) {
if (handler != null) {
return handler;
}
return super.getSwingHandler(swing);
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new GodwarsBossNPC(id, location);
}
@Override
public int[] getIds() {
return new int[] { 6203, 6222, 6247, 6260 };
}
}
@@ -0,0 +1,102 @@
package core.game.content.activity.gwd;
import core.cache.def.impl.ObjectDefinition;
import core.plugin.Initializable;
import core.game.content.dialogue.FacialExpression;
import core.game.node.entity.skill.Skills;
import core.game.interaction.OptionHandler;
import core.game.node.Node;
import core.game.node.entity.impl.ForceMovement;
import core.game.node.entity.player.Player;
import core.game.node.item.Item;
import core.game.node.object.GameObject;
import core.game.system.task.Pulse;
import core.game.world.GameWorld;
import core.game.world.map.Location;
import core.game.world.map.RegionManager;
import core.game.world.update.flag.context.Animation;
import core.plugin.Plugin;
/**
* Handles the entrance hole to the godwars dungeon.
* @author Emperor
*/
@Initializable
public final class GodwarsEntranceHandler extends OptionHandler {
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
ObjectDefinition.forId(26340).getHandlers().put("option:tie-rope", this);
ObjectDefinition.forId(26341).getHandlers().put("option:climb-down", this);
ObjectDefinition.forId(26338).getHandlers().put("option:move", this);
ObjectDefinition.forId(26305).getHandlers().put("option:crawl-through", this);
return this;
}
@Override
public boolean handle(final Player player, Node node, String option) {
GameObject object = (GameObject) node;
switch (object.getId()) {
case 26340:
if (!player.getInventory().remove(new Item(954))) {
player.getPacketDispatch().sendMessage("You don't have a rope to tie around the pillar.");
return true;
}
player.varpManager.get(1048).setVarbit(0,1).send(player);
player.varpManager.flagSave(1048);
return true;
case 26341:
if (player.getSkills().getStaticLevel(Skills.AGILITY) < 15) {
player.getPacketDispatch().sendMessage("You need an Agility level of 15 to enter this.");
return true;
}
if (player.varpManager.get(1048).getVarbit(4) == null) {
player.getDialogueInterpreter().sendDialogues(6201, FacialExpression.HALF_GUILTY, "Cough... Hey, over here.");
return true;
}
player.lock(2);
player.getPacketDispatch().sendMessage("You climb down the rope.");
player.animate(Animation.create(828));
GameWorld.getPulser().submit(new Pulse(1, player) {
@Override
public boolean pulse() {
player.getProperties().setTeleportLocation(Location.create(2882, 5311, 2));
return true;
}
});
return true;
case 26338:
if (player.getSkills().getStaticLevel(Skills.STRENGTH) < 60) {
player.getPacketDispatch().sendMessage("You need a Strength level of 60 to move this boulder.");
return true;
}
player.getPacketDispatch().sendObjectAnimation(object, Animation.create(6980));
if (player.getLocation().getY() < 3716) {
ForceMovement.run(player, Location.create(2898, 3715, 0), Location.create(2898, 3719, 0), new Animation(6978), 3);
} else {
ForceMovement.run(player, Location.create(2898, 3719, 0), Location.create(2898, 3715, 0), new Animation(6979), 3);
}
GameWorld.getPulser().submit(new Pulse(12, player) {
@Override
public boolean pulse() {
player.getPacketDispatch().sendObjectAnimation(RegionManager.getObject(0, 2898, 3716), Animation.create(6981));
return true;
}
});
return true;
case 26305:
if (player.getSkills().getStaticLevel(Skills.AGILITY) < 60) {
player.getPacketDispatch().sendMessage("You need an Agility level of 60 to squeeze through the crack.");
return true;
}
if (object.getLocation().equals(Location.create(2900, 3713, 0))) {
player.getProperties().setTeleportLocation(Location.create(2904, 3720, 0));
} else {
player.getProperties().setTeleportLocation(Location.create(2899, 3713, 0));
}
return true;
}
return false;
}
}
@@ -0,0 +1,555 @@
package core.game.content.activity.gwd;
import core.cache.def.impl.ObjectDefinition;
import core.game.component.Component;
import core.game.container.impl.EquipmentContainer;
import core.game.content.global.action.DoorActionHandler;
import core.game.interaction.MovementPulse;
import core.game.interaction.Option;
import core.game.node.Node;
import core.game.node.entity.Entity;
import core.game.node.entity.combat.equipment.RangeWeapon;
import core.game.node.entity.impl.ForceMovement;
import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.info.Rights;
import core.game.node.item.Item;
import core.game.node.object.GameObject;
import core.game.system.task.Pulse;
import core.game.world.GameWorld;
import core.game.world.map.Direction;
import core.game.world.map.Location;
import core.game.world.map.zone.MapZone;
import core.game.world.map.zone.ZoneBorders;
import core.game.world.map.zone.ZoneBuilder;
import core.game.world.map.zone.ZoneRestriction;
import core.game.world.update.flag.context.Animation;
import core.game.world.update.flag.context.Graphics;
import core.net.packet.PacketRepository;
import core.net.packet.context.MinimapStateContext;
import core.net.packet.out.MinimapState;
import core.plugin.Initializable;
import core.plugin.Plugin;
import core.tools.StringUtils;
import core.game.node.entity.skill.Skills;
/**
* Handles the god wars map zone.
* @author Emperor
*/
@Initializable
public final class GodwarsMapzone extends MapZone implements Plugin<Object> {
/**
* The Zamorak's fortress area.
*/
private static final ZoneBorders ZAMORAK_FORTRESS = new ZoneBorders(2880, 5317, 2944, 5362);
static {
ZAMORAK_FORTRESS.addException(new ZoneBorders(2880, 5317, 2904, 5338));
}
/**
* Constructs a new {@code GodwarsMapzone} {@code Object}.
*/
public GodwarsMapzone() {
super("Godwars", true, ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON);
}
@Override
public void configure() {
register(new ZoneBorders(2816, 5248, 2943, 5375));
}
@Override
public boolean enter(Entity e) {
if (e instanceof Player) {
Player player = (Player) e;
int componentId = player.getInterfaceManager().isResizable() ? 597 : 601;
if (ZAMORAK_FORTRESS.insideBorder(player.getLocation().getX(), player.getLocation().getY())) {
componentId = player.getInterfaceManager().isResizable() ? 598 : 599;
}
openOverlay(player, componentId);
if (player.getDetails().getRights() == Rights.ADMINISTRATOR) {
for (GodWarsFaction faction : GodWarsFaction.values()) {
increaseKillcount(player, faction, 40);
}
}
}
return true;
}
/**
* Sets the rope setting.
* @param player The player.
* @param setting The setting.
*/
public void setRopeSetting(Player player, int setting) {
int value = player.getConfigManager().get(1048) | setting;
player.getConfigManager().set(1048, value, true);
}
/**
* Opens the overlay.
* @param player The player.
* @param componentId The component id.
*/
private void openOverlay(Player player, int componentId) {
player.setAttribute("gwd:overlay", componentId);
player.getInterfaceManager().openOverlay(new Component(componentId));
int child = (componentId == 601 || componentId == 599) ? 6 : 7;
for (GodWarsFaction faction : GodWarsFaction.values()) {
int amount = player.getAttribute("gwd:" + faction.name().toLowerCase() + "kc", 0);
player.getPacketDispatch().sendString(Integer.toString(amount), componentId, child + faction.ordinal());
}
}
@Override
public boolean leave(Entity e, boolean logout) {
if (!logout && e instanceof Player) {
for (GodWarsFaction faction : GodWarsFaction.values()) {
e.removeAttribute("gwd:" + faction.name().toLowerCase() + "kc");
}
e.removeAttribute("gwd:overlay");
e.removeAttribute("gwd:altar-recharge");
((Player) e).getInterfaceManager().closeOverlay();
} else if (logout) {
e.setLocation(e.getAttribute("cross_bridge_loc", e.getLocation()));
}
return true;
}
@Override
public boolean death(Entity e, Entity killer) {
if (killer instanceof Player && e instanceof NPC) {
int npcId = ((NPC) e).getId();
increaseKillcount((Player) killer, GodWarsFaction.forId(npcId), 1);
}
return false;
}
@Override
public void locationUpdate(Entity e, Location last) {
if (e instanceof Player) {
Player player = (Player) e;
Component c = player.getInterfaceManager().getOverlay();
boolean inZamorakFortress = ZAMORAK_FORTRESS.insideBorder(player.getLocation().getX(), player.getLocation().getY());
if ((c == null || c.getId() != 598) && inZamorakFortress) {
openOverlay(player, 598);
} else if ((c == null || c.getId() != 597 && c.getId() != 601) && !inZamorakFortress) {
openOverlay(player, player.getInterfaceManager().isResizable() ? 597 : 601);
}
}
}
@Override
public boolean interact(Entity e, Node target, Option option) {
if (target instanceof GameObject) {
GameObject object = (GameObject) target;
if (object.getId() == 26439) {
handleIceBridge((Player) e, object);
return true;
}
if (object.getId() == 26384) {
handleBigDoor((Player) e, object, true);
return true;
}
if (object.getId() == 26303) {
handlePillarGrapple((Player) e, object);
return true;
}
if (object.getId() == 26293) {
handleRopeClimb((Player) e, Location.create(2915, 3746, 0));
return true;
}
if (object.getId() == 26295) {
handleRopeClimb((Player) e, Location.create(2915, 5300, 1));
return true;
}
if (object.getId() == 26296) {
handleRopeTie((Player) e, 0x2);
return true;
}
if (object.getId() == 26297) {
if (object.getLocation().getY() == 5300) {
handleRopeClimb((Player) e, Location.create(2912, 5300, 2));
} else {
handleRopeClimb((Player) e, Location.create(2920, 5276, 1));
}
return true;
}
if (object.getId() == 26299) {
handleRopeClimb((Player) e, Location.create(2919, 5274, 0));
return true;
}
if (object.getId() == 26300) {
handleRopeTie((Player) e, 0x4);
return true;
}
if (object.getId() == 26286) {
handleAltar((Player) e, option.getName(), GodWarsFaction.ZAMORAK, Location.create(2925, 5332, 2));
return true;
}
if (object.getId() == 26287) {
handleAltar((Player) e, option.getName(), GodWarsFaction.SARADOMIN, Location.create(2908, 5265, 0));
return true;
}
if (object.getId() == 26288) {
handleAltar((Player) e, option.getName(), GodWarsFaction.ARMADYL, Location.create(2839, 5295, 2));
return true;
}
if (object.getId() == 26289) {
handleAltar((Player) e, option.getName(), GodWarsFaction.BANDOS, Location.create(2863, 5354, 2));
return true;
}
if (object.getId() >= 26425 && object.getId() <= 26428) {
return handleChamberEntrance((Player) e, object);
}
}
return false;
}
/**
* Handles praying on an altar.
* @param player The player.
* @param faction The god wars faction.
*/
private void handleAltar(Player player, String option, GodWarsFaction faction, Location destination) {
if (!option.equals("Pray-at")) {
player.getProperties().setTeleportLocation(destination);
return;
}
if (player.getAttribute("gwd:altar-recharge", 0L) > System.currentTimeMillis()) {
player.getPacketDispatch().sendMessage("The gods blessed you recently - this time they ignore your prayers.");
return;
}
if (player.inCombat()) {
player.getPacketDispatch().sendMessage("You can't use the altar while in combat.");
return;
}
if (player.getSkills().getPrayerPoints() >= player.getSkills().getStaticLevel(5)) {
player.getPacketDispatch().sendMessage("You already have full prayer points.");
return;
}
player.lock(2);
int total = player.getSkills().getStaticLevel(5) + faction.getProtectionItemAmount(player);
player.animate(new Animation(645));
player.getSkills().decrementPrayerPoints(player.getSkills().getPrayerPoints() - total);
player.getPacketDispatch().sendMessage("You recharge your Prayer points.");
int time = 600_000;
player.setAttribute("/save:gwd:altar-recharge", System.currentTimeMillis() + time);
}
/**
* Handles the rope tying.
* @param player The player.
* @param type The rock tying type.
*/
private void handleRopeTie(Player player, int type) {
if (player.getSkills().getStaticLevel(Skills.AGILITY) < 70) {
player.getPacketDispatch().sendMessage("You need an Agility level of 70 to enter here.");
return;
}
if (!player.getInventory().remove(new Item(954))) {
player.getPacketDispatch().sendMessage("You don't have a rope to tie on this rock.");
return;
}
setRopeSetting(player, type);
}
/**
* Handles the climbing of a rope.
* @param player The player.
*/
private void handleRopeClimb(final Player player, final Location destination) {
player.lock(2);
player.animate(Animation.create(828));
GameWorld.getPulser().submit(new Pulse(1, player) {
@Override
public boolean pulse() {
player.getProperties().setTeleportLocation(destination);
return true;
}
});
}
/**
* Handles the pillar grappling.
* @param player The player.
* @param object The pillar object.
*/
private void handlePillarGrapple(final Player player, final GameObject object) {
if (player.getSkills().getStaticLevel(Skills.RANGE) < 70) {
player.getPacketDispatch().sendMessage("You need a Range level of 70 to enter here.");
return;
}
if (player.getEquipment().getNew(EquipmentContainer.SLOT_ARROWS).getId() != 9419) {
player.getPacketDispatch().sendMessage("You need a mithril grapple to cross this.");
return;
}
RangeWeapon weapon = RangeWeapon.get(player.getEquipment().getNew(3).getId());
if (weapon == null || weapon.getType() != 1) {
player.getPacketDispatch().sendMessage("You need to wield a crossbow to fire a mithril grapple.");
return;
}
player.lock(4);
if (player.getLocation().getY() < object.getLocation().getY()) {
ForceMovement.run(player, Location.create(2872, 5269, 2), Location.create(2872, 5279, 2), Animation.create(7081), 60).setCommenceSpeed(3);
} else {
ForceMovement.run(player, Location.create(2872, 5279, 2), Location.create(2872, 5269, 2), Animation.create(7081), 60).setCommenceSpeed(3);
}
player.graphics(new Graphics(1036, 96, 30));
}
/**
* Handles the big door.
* @param player The player.
* @param object The door object.
*/
private void handleBigDoor(final Player player, final GameObject object, boolean checkLocation) {
player.lock(4);
if (checkLocation && player.getLocation().getX() > object.getLocation().getX()) {
GameWorld.getPulser().submit(new MovementPulse(player, object.getLocation()) {
@Override
public boolean pulse() {
handleBigDoor(player, object, false);
return true;
}
});
return;
}
if (player.getSkills().getStaticLevel(Skills.STRENGTH) < 70) {
player.getPacketDispatch().sendMessage("You need a Strength level of 70 to enter here.");
return;
}
if (!player.getInventory().contains(2347, 1)) {
player.getPacketDispatch().sendMessage("You need a hammer to bang on the door.");
return;
}
player.getPacketDispatch().sendMessage("You bang on the big door.");
player.animate(Animation.create(7002));
GameWorld.getPulser().submit(new Pulse(1, player) {
@Override
public boolean pulse() {
object.getDefinition().getOptions()[1] = "open";
ObjectDefinition.getOptionHandler(object.getId(), "open").handle(player, object, "open");
return true;
}
});
}
/**
* Handles a chamber door opening reward.
* @param player The player.
* @param object The object.
* @return {@code True} if the player can't pass.
*/
private boolean handleChamberEntrance(Player player, GameObject object) {
Direction dir = Direction.get((object.getRotation() + 3) % 4);
if (dir.getStepX() != 0) {
if (player.getLocation().getX() == object.getLocation().transform(dir.getStepX(), 0, 0).getX()) {
player.getPacketDispatch().sendMessage("You can't leave through this door. The altar can teleport you out.");
return true;
}
} else if (player.getLocation().getY() == object.getLocation().transform(0, dir.getStepY(), 0).getY()) {
player.getPacketDispatch().sendMessage("You can't leave through this door. The altar can teleport you out.");
return true;
}
int index = object.getId() - 26425;
if (index < 2) {
index = 1 - index;
}
GodWarsFaction faction = GodWarsFaction.values()[index];
String name = faction.name().toLowerCase();
int required = 40;
if (player.getAttribute("gwd:" + name + "kc", 0) < required) {
player.getPacketDispatch().sendMessage("You need " + required + " " + StringUtils.formatDisplayName(name) + " kills to enter this.");
return true;
}
increaseKillcount(player, faction, -required);
DoorActionHandler.handleAutowalkDoor(player, object);
return true;
}
/**
* Handles the ice bridge crossing.
* @param player The player.
* @param object The object.
*/
private void handleIceBridge(final Player player, final GameObject object) {
if (player.getSkills().getStaticLevel(Skills.HITPOINTS) < 70) {
player.getPacketDispatch().sendMessage("You need 70 Hitpoints to cross this bridge.");
return;
}
player.lock(7);
GameWorld.getPulser().submit(new Pulse(1, player) {
@Override
public boolean pulse() {
player.visualize(Animation.create(6988), Graphics.create(68));
int diffY = 2;
if (object.getLocation().getY() == 5344) {
diffY = -2;
}
player.getProperties().setTeleportLocation(player.getLocation().transform(0, diffY, 0));
player.getInterfaceManager().openOverlay(new Component(115));
player.setAttribute("cross_bridge_loc", player.getLocation());
GameWorld.getPulser().submit(new Pulse(1, player) {
int counter = 0;
@Override
public boolean pulse() {
switch (counter++) {
case 4:
if (object.getLocation().getY() == 5333) {
player.getProperties().setTeleportLocation(Location.create(2885, 5345, 2));
} else {
player.getProperties().setTeleportLocation(Location.create(2885, 5332, 2));
}
player.setDirection(Direction.get((player.getDirection().toInteger() + 2) % 4));
break;
case 5:
PacketRepository.send(MinimapState.class, new MinimapStateContext(player, 0));
player.getInterfaceManager().close();
player.removeAttribute("cross_bridge_loc");
player.getPacketDispatch().sendMessage("Dripping, you climb out of the water.");
if (player.getLocation().getY() > 5340) {
player.getSkills().decrementPrayerPoints(100.0);
player.getPacketDispatch().sendMessage("The extreme evil of this area leaves your Prayer drained.");
}
return true;
}
return false;
}
});
return true;
}
});
}
/**
* Sets the kill count.
* @param p The player.
* @param faction The god wars faction.
* @param increase The amount to increase with.
*/
public void increaseKillcount(Player p, GodWarsFaction faction, int increase) {
if (faction == null) {
return;
}
String key = "gwd:" + faction.name().toLowerCase() + "kc";
int amount = p.getAttribute(key, 0) + increase;
int componentId = p.getAttribute("gwd:overlay", 601);
int child = (componentId == 601 || componentId == 599) ? 6 : 7;
if (amount >= 4000) {
p.setAttribute("/save:" + key, 4000);
p.getPacketDispatch().sendString("Max", componentId, child + faction.ordinal());
return;
}
p.setAttribute("/save:" + key, amount);
p.getPacketDispatch().sendString(Integer.toString(amount), componentId, child + faction.ordinal());
}
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
ZoneBuilder.configure(this);
return this;
}
@Override
public Object fireEvent(String identifier, Object... args) {
return null;
}
/**
* The god wars factions.
* @author Emperor
*/
static enum GodWarsFaction {
ARMADYL(6222, 6246, 87, 11694, 11718, 11720, 11722, 12670, 12671, 14671), BANDOS(6260, 6283, 11061, 11696, 11724, 11726, 11728), SARADOMIN(6247, 6259, 1718, 2412, 2415, 2661, 2663, 2665, 2667, 3479, 3675, 3489, 3840, 4682, 6762, 8055, 10384, 10386, 10388, 10390, 10440, 10446, 10452, 10458, 10464, 10470, 11181, 11698, 11730), ZAMORAK(6203, 6221, 11716, 11700, 2414, 2417, 2653, 2655, 2657, 2659, 3478, 3674, 3841, 3842, 3852, 4683, 6764, 8056, 10368, 10370, 10372, 10374, 10444, 10450, 10456, 10460, 10468, 10474, 10776, 10786, 10790);
/**
* The start NPC id.
*/
private final int startId;
/**
* The end NPC id.
*/
private final int endId;
/**
* The protection items.
*/
private final int[] protectionItems;
/**
* Constructs a new {@code GodWarsFaction} {@code Object}.
* @param startId The start NPC id.
* @param endId The end NPC id.
* @param protectionItems The protection items for this faction.
*/
private GodWarsFaction(int startId, int endId, int... protectionItems) {
this.startId = startId;
this.endId = endId;
this.protectionItems = protectionItems;
}
/**
* Gets the god wars faction for the given NPC id.
* @param npcId The NPC id.
* @return The faction for this NPC.
*/
public static GodWarsFaction forId(int npcId) {
for (GodWarsFaction faction : values()) {
if (npcId >= faction.getStartId() && npcId <= faction.getEndId()) {
return faction;
}
}
return null;
}
/**
* Gets the amount of items the player is wearing to protect.
* @param player The player.
* @return The amount of protection items.
*/
public int getProtectionItemAmount(Player player) {
int count = 0;
for (Item item : player.getEquipment().toArray()) {
if (item != null) {
for (int id : protectionItems) {
if (item.getId() == id) {
count++;
}
}
}
}
return count;
}
/**
* Gets the startId.
* @return The startId.
*/
public int getStartId() {
return startId;
}
/**
* Gets the endId.
* @return The endId.
*/
public int getEndId() {
return endId;
}
/**
* Gets the protectionItems.
* @return The protectionItems.
*/
public int[] getProtectionItems() {
return protectionItems;
}
}
}
@@ -0,0 +1,138 @@
package core.game.content.activity.magearena;
import core.game.content.dialogue.DialoguePlugin;
import core.game.content.global.GodType;
import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player;
/**
* Handles the chamber guardian dialogue.
* @author Vexia
*/
public final class ChamberGuardianDialogue extends DialoguePlugin {
/**
* The god type.
*/
private GodType godType;
/**
* Constructs a new {@code ChamberGuardianDialogue} {@code Object}.
*/
public ChamberGuardianDialogue() {
/**
* empty.
*/
}
/**
* Constructs a new {@code ChamberGuardianDialogue} {@code Object}.
* @param player the player.
*/
public ChamberGuardianDialogue(Player player) {
super(player);
}
@Override
public DialoguePlugin newInstance(Player player) {
return new ChamberGuardianDialogue(player);
}
@Override
public boolean open(Object... args) {
npc = (NPC) args[0];
if (player.getSavedData().getActivityData().hasRecievedKolodionReward()) {
player("Hello again.");
return true;
} else if (player.getSavedData().getActivityData().hasKilledKolodion()) {
npc("Hello adventurer, have you made your choice?");
return true;
}
npc("YOU SHOULD NOT BE IN HERE!");
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
if (player.getSavedData().getActivityData().hasRecievedKolodionReward()) {
switch (stage) {
case 0:
npc("Hello adventurer, are you looking for another staff?");
stage++;
break;
case 1:
options("What do you have to offer?", "No thanks.");
stage++;
break;
case 2:
switch (buttonId) {
case 1:
end();
npc.openShop(player);
break;
case 2:
player("No thanks.");
stage++;
break;
}
break;
case 3:
npc("Well let me know if you need one.");
stage++;
break;
case 4:
end();
break;
}
return true;
} else if (player.getSavedData().getActivityData().hasKilledKolodion()) {
switch (stage) {
case 0:
godType = GodType.getCape(player);
if (godType == null) {
player("Sorry, I'm still looking.");
stage++;
} else {
player("I have.");
stage += 2;
}
break;
case 1:
end();
break;
case 2:
npc("Good, good, I hope you have chosen well. I will now", "present you with a magic staff. This, along with the", "cape awarded to you by your chosen god, are all the", "weapons and armour you will need here.");
stage++;
break;
case 3:
if (!player.getInventory().hasSpaceFor(godType.getStaff())) {
player("Sorry, I don't have enough inventory space.");
stage = 1;
return true;
}
if (player.getInventory().containsItem(godType.getCape()) || player.getEquipment().containsItem(godType.getCape())) {
stage++;
player.getInventory().add(godType.getStaff());
player.getSavedData().getActivityData().setKolodionStage(3);
interpreter.sendItemMessage(godType.getStaff(), "The guardian hands you an ornate magic staff.");
} else {
end();
}
break;
case 4:
end();
break;
}
return true;
} else {
end();
}
return true;
}
@Override
public int[] getIds() {
return new int[] { 904 };
}
}
@@ -0,0 +1,253 @@
package core.game.content.activity.magearena;
import core.game.content.dialogue.DialoguePlugin;
import core.game.node.entity.skill.Skills;
import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player;
import core.game.world.GameWorld;
import core.game.world.map.Location;
import core.game.world.update.flag.context.Animation;
import core.game.world.update.flag.context.Graphics;
/**
* Handles the kolodion dialogue.
* @author Vexia
*/
public final class KolodionDialogue extends DialoguePlugin {
/**
* Constructs a new {@code KolodionDialogue} {@code Object}.
*/
public KolodionDialogue() {
/**
* empty.
*/
}
/**
* Constructs a new {@code KolodionDialogue} {@code Object}.
* @param player the player.
*/
public KolodionDialogue(Player player) {
super(player);
}
@Override
public DialoguePlugin newInstance(Player player) {
return new KolodionDialogue(player);
}
@Override
public boolean open(Object... args) {
npc = (NPC) args[0];
if (player.getSavedData().getActivityData().hasStartedKolodion()) {
player("Hi.");
return true;
}
if (player.getSavedData().getActivityData().hasKilledKolodion()) {
player("Hello, Kolodion.");
return true;
}
player("Hello there. What is this place?");
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
if (player.getSavedData().getActivityData().hasStartedKolodion()) {
switch (stage) {
case 0:
npc("You return, young conjurer. You obviously have a", "taste for the dark side of magic.");
stage++;
break;
case 1:
startFight(player);
end();
break;
}
return true;
}
if (player.getSavedData().getActivityData().hasRecievedKolodionReward()) {
switch (stage) {
case 0:
npc("Hey there, how are you? Are you enjoying the", "bloodshed?");
stage++;
break;
case 1:
player("I think I've had enough for now.");
stage++;
break;
case 2:
npc("A shame. You're a good battle mage. I hope", "to see you soon.");
stage++;
break;
case 3:
end();
break;
}
return true;
} else if (player.getSavedData().getActivityData().hasKilledKolodion()) {
switch (stage) {
case 0:
npc("Hello, you mage. You're a tough one.");
stage++;
break;
case 1:
player("What now?");
stage++;
break;
case 2:
npc("Step into the magic pool. It will take you to a chamber.", "There, you must decide which god you will represent in", "the arena.");
stage++;
break;
case 3:
player("Thanks, Kolodion.");
stage++;
break;
case 4:
npc("That's what I'm here for.");
stage++;
break;
case 5:
end();
break;
}
return true;
}
switch (stage) {
case 0:
if (player.getSkills().getStaticLevel(Skills.MAGIC) < 60) {
npc("Do not waste my time with trivial questions. I am the", "Great Kolodion, master of battle magic. I have an arena", "to run.");
stage++;
} else {
npc("I am the great Kolodion, master of battle magic, and", "this is my battle arena. Top wizards travel from all over", GameWorld.getSettings().getName() + " to fight here.");
stage = 4;
}
break;
case 1:
player("Can I enter?");
stage++;
break;
case 2:
player("Hah! A wizard of your level? Don't be absurd.");
stage++;
break;
case 3:
end();
break;
case 4:
options("Can I fight here?", "What's the point of that?", "That's barbaric!");
stage++;
break;
case 5:
switch (buttonId) {
case 1:
player("Can I fight here?");
stage = 10;
break;
case 2:
player("What's the point of that?");
stage = 20;
break;
case 3:
player("That's barbaric!");
stage = 30;
break;
}
break;
case 10:
npc("My arena is open to any high level wizard, but this is", "no game. Many wizards fall in this arena, never to rise", "again. The strongest mages have been destroyed.");
stage++;
break;
case 11:
npc("If you're sure you want in?");
stage++;
break;
case 12:
options("Yes indeedy.", "No I don't.");
stage++;
break;
case 13:
switch (buttonId) {
case 1:
player("Yes indeedy.");
stage++;
break;
case 2:
end();
break;
}
break;
case 14:
npc("Good, good. You have a healthy sense of competition.");
stage++;
break;
case 15:
npc("Remember, traveller - in my arena, hand-to-hand", "combat is useless. Your strength will diminish as you", "enter the arena, but the spells you can learn are", "amongst the most powerful in all of " + GameWorld.getSettings().getName() + ".");
stage++;
break;
case 16:
npc("Before I can accept you in, we must duel.");
stage++;
break;
case 17:
options("Okay, let's fight.", "No thanks.");
stage++;
break;
case 18:
switch (buttonId) {
case 1:
player("Okay, let's fight.");
stage++;
break;
case 2:
end();
break;
}
break;
case 19:
npc("I must first check that you are up to scratch.");
stage = 40;
break;
case 40:
player("You don't need to worry about that.");
stage++;
break;
case 41:
npc("Not just any magician can enter - only the most", "powerful and most feared. Before you can use the", "power of this arena, you must prove yourself against", "me.");
stage++;
break;
case 42:
startFight(player);
end();
break;
case 20:
npc("They want to crown themselves the best", "mage in all of " + GameWorld.getSettings().getName() + "!");
stage = 30;
break;
case 30:
end();
break;
}
return true;
}
/**
* Starts the fight.
* @param player the player.
*/
private void startFight(final Player player) {
player.getSavedData().getActivityData().setKolodionStage(1);
player.lock();
npc.animate(Animation.create(811));
player.teleport(Location.create(3105, 3934, 0), 3);
player.visualize(Animation.create(1816), Graphics.create(301, 100));
KolodionSession.create(player).start();
}
@Override
public int[] getIds() {
return new int[] { 905 };
}
}
@@ -0,0 +1,374 @@
package core.game.content.activity.magearena;
import core.game.node.entity.Entity;
import core.game.node.entity.combat.BattleState;
import core.game.node.entity.combat.CombatSpell;
import core.game.node.entity.combat.CombatStyle;
import core.game.node.entity.combat.CombatSwingHandler;
import core.game.node.entity.combat.handlers.MagicSwingHandler;
import core.game.node.entity.npc.AbstractNPC;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.SpellBookManager.SpellBook;
import core.game.system.task.Pulse;
import core.game.world.GameWorld;
import core.game.world.map.Location;
import core.game.world.update.flag.context.Animation;
import core.tools.RandomFunction;
/**
* Handles the kolodion npc.
* @author Vexia
*/
public final class KolodionNPC extends AbstractNPC {
/**
* The combat swing handler.
*/
private static final CombatSwingHandler SWING_HANDLER = new MagicSwingHandler() {
@Override
public void impact(Entity entity, Entity victim, BattleState state) {
super.impact(entity, victim, state);
if (RandomFunction.random(10) < 4) {
((KolodionNPC) entity).setRandomSpell();
}
}
};
/**
* The spell ids.
*/
private static final int[] SPELL_IDS = new int[] { 41, 42, 43 };
/**
* The session.
*/
private final KolodionSession session;
/**
* The kolodion type.
*/
private KolodionType type;
/**
* If the fight has commenced.
*/
private boolean commenced;
/**
* Constructs a new {@code KolodionNPC} {@code Object}.
*/
public KolodionNPC() {
this(0, null, null);
}
/**
* Constructs a new {@code KolodionNPC} {@code Object}.
* @param id the id.
* @param location the location.
*/
public KolodionNPC(int id, Location location, final KolodionSession session) {
super(id, location);
this.setWalks(true);
this.session = session;
this.setRespawn(false);
this.type = KolodionType.forId(id);
}
@Override
public void init() {
super.init();
setRandomSpell();
}
@Override
public void handleTickActions() {
super.handleTickActions();
if (session == null) {
return;
}
if (!session.getPlayer().isActive()) {
clear();
return;
}
if (commenced && !getProperties().getCombatPulse().isAttacking()) {
getProperties().getCombatPulse().attack(session.getPlayer());
}
}
@Override
public void startDeath(Entity killer) {
if (killer == session.getPlayer()) {
type.transform(this, session.getPlayer());
return;
}
super.startDeath(killer);
}
/**
* Sets a random spell.
*/
public void setRandomSpell() {
CombatSpell spell = (CombatSpell) SpellBook.MODERN.getSpell(SPELL_IDS[RandomFunction.random(SPELL_IDS.length)]);
getProperties().setSpell(spell);
getProperties().setAutocastSpell(spell);
}
@Override
public CombatSwingHandler getSwingHandler(boolean swing) {
return SWING_HANDLER;
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new KolodionNPC(id, location, null);
}
@Override
public boolean isAttackable(Entity entity, CombatStyle style) {
if (style != CombatStyle.MAGIC) {
return false;
}
if (session == null) {
return false;
}
if (session.getPlayer() != entity) {
return false;
}
return true;
}
@Override
public boolean canSelectTarget(Entity target) {
if (target instanceof Player) {
Player p = (Player) target;
if (p != session.getPlayer()) {
return false;
}
}
return true;
}
@Override
public int[] getIds() {
return new int[] { 907, 908, 909, 910, 911 };
}
/**
* Gets the session.
* @return The session.
*/
public KolodionSession getSession() {
return session;
}
/**
* Gets the commenced.
* @return The commenced.
*/
public boolean isCommenced() {
return commenced;
}
/**
* Sets the commenced.
* @param commenced The commenced to set.
*/
public void setCommenced(boolean commenced) {
this.commenced = commenced;
}
/**
* Gets the type.
* @return The type.
*/
public KolodionType getType() {
return type;
}
/**
* Sets the type.
* @param type The type to set.
*/
public void setType(KolodionType type) {
this.type = type;
}
/**
* Represents a kolodion type.
* @author Vexia
*/
public enum KolodionType {
HUMAN(907, null, -1, "You must prove yourself... now!"), OGRE(908, null, 188, "This is only the beginning; you can't beat me!"), SPIDER(909, new Animation(5324), 190, "Foolish mortal; I am unstoppable."), GHOST(910, new Animation(715), 188, "Now you feel it.. The dark energy."), DEMON(911, new Animation(4623), 190, "Aaaaaaaarrgghhhh! The power!"), END(906, null, 188, null);
/**
* The npc id.
*/
private final int npcId;
/**
* The appear animation.
*/
private final Animation appearAnimation;
/**
* The graphic id.
*/
private final int graphcId;
/**
* The appeared message.
*/
private final String appearMessage;
/**
* The spell ids.
*/
private final int[] spellIds;
/**
* Constructs a new {@code KolodionType} {@code Object}.
* @param npcId the npc id.
* @param appearMessage the message.
*/
private KolodionType(int npcId, final Animation appearAnimation, final int graphicId, String appearMessage, int... spellIds) {
this.npcId = npcId;
this.appearMessage = appearMessage;
this.appearAnimation = appearAnimation;
this.graphcId = graphicId;
this.spellIds = spellIds;
}
/**
* Transforms the new npc.
*/
public void transform(final KolodionNPC kolodion, final Player player) {
final KolodionType newType = next();
kolodion.lock();
kolodion.getPulseManager().clear();
kolodion.getWalkingQueue().reset();
kolodion.getImpactHandler().setDisabledTicks(50);
player.getSavedData().getActivityData().setKolodionBoss(newType.ordinal());
if (newType == END) {
player.lock();
}
player.lock(2);
GameWorld.getPulser().submit(new Pulse(1, kolodion, player) {
int counter;
@Override
public boolean pulse() {
switch (++counter) {
case 1:
if (newType != GHOST) {
kolodion.getAnimator().forceAnimation(kolodion.getProperties().getDeathAnimation());
}
break;
case 3:
if (newType == GHOST) {
kolodion.getAnimator().forceAnimation(kolodion.getProperties().getDeathAnimation());
}
break;
case 4:
player.getPacketDispatch().sendPositionedGraphic(newType.getGraphcId(), 0, 0, kolodion.getLocation());
if (newType.getAppearAnimation() != null) {
kolodion.animate(newType.getAppearAnimation());
}
break;
case 5:
kolodion.unlock();
kolodion.getAnimator().reset();
kolodion.fullRestore();
kolodion.setType(newType);
kolodion.transform(newType.getNpcId());
kolodion.getImpactHandler().setDisabledTicks(1);
if (newType != END) {
kolodion.getProperties().getCombatPulse().attack(player);
}
break;
case 6:
if (newType.getAppearMessage() != null) {
kolodion.sendChat(newType.getAppearMessage());
}
if (newType == END) {
return false;
}
return true;
case 7:
player.unlock();
player.getSavedData().getActivityData().setKolodionStage(2);
player.getProperties().setTeleportLocation(Location.create(2540, 4717, 0));
return true;
}
return false;
}
});
}
/**
* Gets the kolodion type for the id.
* @param id the id.
* @return the kolodion type.
*/
public static KolodionType forId(int id) {
for (KolodionType type : values()) {
if (type.getNpcId() == id) {
return type;
}
}
return null;
}
/**
* Gets the next type.
* @return the type.
*/
public KolodionType next() {
return values()[ordinal() + 1];
}
/**
* Gets the npcId.
* @return The npcId.
*/
public int getNpcId() {
return npcId;
}
/**
* Gets the appearMessage.
* @return The appearMessage.
*/
public String getAppearMessage() {
return appearMessage;
}
/**
* Gets the spellIds.
* @return The spellIds.
*/
public int[] getSpellIds() {
return spellIds;
}
/**
* Gets the appearAnimation.
* @return The appearAnimation.
*/
public Animation getAppearAnimation() {
return appearAnimation;
}
/**
* Gets the graphcId.
* @return The graphcId.
*/
public int getGraphcId() {
return graphcId;
}
}
}
@@ -0,0 +1,120 @@
package core.game.content.activity.magearena;
import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player;
import core.game.system.task.Pulse;
import core.game.world.GameWorld;
import core.game.world.map.Location;
/**
* Represents a session with kolodion.
* @author Vexia
*/
public final class KolodionSession {
/**
* The player.
*/
private final Player player;
/**
* The kolodion npc.
*/
private final KolodionNPC kolodion;
/**
* Constructs a new {@code ExperimentSession} {@code Object}.
* @param player the player.
*/
public KolodionSession(final Player player) {
this.player = player;
this.kolodion = new KolodionNPC(KolodionNPC.KolodionType.values()[player.getSavedData().getActivityData().getKolodionBoss()].getNpcId(), Location.create(3106, 3934, 0), this);
if (player.getExtension(KolodionSession.class) != null) {
player.removeExtension(KolodionSession.class);
}
player.addExtension(KolodionSession.class, this);
}
/**
* Creates the kolodion session.
* @param player the player.
* @return the session.
*/
public static KolodionSession create(Player player) {
return new KolodionSession(player);
}
/**
* Starts the session.
*/
public void start() {
if (kolodion.getType().ordinal() > 0) {
kolodion.init();
kolodion.sendChat("Let us continue with our battle.");
kolodion.getProperties().getCombatPulse().attack(player);
player.unlock();
player.getAnimator().reset();
return;
}
GameWorld.getPulser().submit(new Pulse(1, player) {
int count;
@Override
public boolean pulse() {
switch (++count) {
case 3:
player.getAnimator().reset();
break;
case 5:
player.getPacketDispatch().sendPositionedGraphic(86, 1, 0, Location.create(3106, 3934, 0));
break;
case 6:
kolodion.init();
kolodion.faceTemporary(player, 1);
break;
case 7:
kolodion.sendChat("You must prove yourself... now!");
break;
case 9:
player.unlock();
kolodion.setCommenced(true);
return true;
}
return false;
}
});
}
/**
* Closes the session.
*/
public void close() {
kolodion.clear();
player.removeExtension(KolodionSession.class);
}
/**
* Gets the kolodion session.
* @param player the player.
* @return the session.
*/
public static KolodionSession getSession(Player player) {
return player.getExtension(KolodionSession.class);
}
/**
* Gets the player.
* @return The player.
*/
public Player getPlayer() {
return player;
}
/**
* Gets the kolodion.
* @return The kolodion.
*/
public NPC getKolodion() {
return kolodion;
}
}
@@ -0,0 +1,103 @@
package core.game.content.activity.magearena;
import core.game.content.dialogue.DialoguePlugin;
import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player;
import core.game.world.GameWorld;
/**
* Handles the lundail dialogue.
* @author Vexia
*/
public final class LundailDialogue extends DialoguePlugin {
/**
* Constructs a new {@code LundailDialogue} {@code Object}.
*/
public LundailDialogue() {
/**
* empty.
*/
}
/**
* Constructs a new {@code LundailDialogue} {@code Object}.
* @param player the player.
*/
public LundailDialogue(Player player) {
super(player);
}
@Override
public DialoguePlugin newInstance(Player player) {
return new LundailDialogue(player);
}
@Override
public boolean open(Object... args) {
npc = (NPC) args[0];
npc("Hello sir.");
stage = 1;
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
switch (stage) {
case 1:
npc("How can I help you, brave adventurer?");
stage++;
break;
case 2:
options("What are you selling?", "What's that big old building above us?");
stage++;
break;
case 3:
switch (buttonId) {
case 1:
player("What are you selling?");
stage = 10;
break;
case 2:
player("What's that big old building above us?");
stage = 20;
break;
}
break;
case 10:
npc("I sell rune stones. I've got some good stuff, some really", "powerful little rocks. Take a look.");
stage++;
break;
case 11:
npc.openShop(player);
end();
break;
case 20:
npc("That, my friend is the mage battle arena. Top mages", "come from all over " + GameWorld.getSettings().getName() + " to compete in the arena.");
stage++;
break;
case 21:
player("Wow.");
stage++;
break;
case 22:
npc("Few return, most get fried, hence the smell.");
stage++;
break;
case 23:
player("Hmmm... I did notice.");
stage++;
break;
case 24:
end();
break;
}
return true;
}
@Override
public int[] getIds() {
return new int[] { 903 };
}
}
@@ -0,0 +1,104 @@
package core.game.content.activity.magearena;
import core.game.content.global.GodType;
import core.game.node.entity.Entity;
import core.game.node.entity.combat.CombatSpell;
import core.game.node.entity.combat.CombatStyle;
import core.game.node.entity.npc.AbstractNPC;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.SpellBookManager.SpellBook;
import core.game.world.map.Location;
import core.tools.RandomFunction;
/**
* A mage arena npc.
* @author Vexia
*/
public final class MageArenaNPC extends AbstractNPC {
/**
* The god type.
*/
private final GodType type;
/**
* Constructs a new {@code MageArenaNPC} {@code Object}.
*/
public MageArenaNPC() {
super(0, null);
this.type = null;
}
/**
* Constructs a new {@code MageArenaNPC} {@code Object}.
* @param id the id.
* @param location the location.
*/
public MageArenaNPC(int id, Location location) {
super(id, location);
this.setWalks(true);
this.type = GodType.forId(id);
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new MageArenaNPC(id, location);
}
@Override
public void init() {
super.init();
CombatSpell spell = (CombatSpell) SpellBook.MODERN.getSpell(41 + type.ordinal());
getProperties().setSpell(spell);
getProperties().setAutocastSpell(spell);
getProperties().getCombatPulse().setStyle(CombatStyle.MAGIC);
}
@Override
public void handleTickActions() {
super.handleTickActions();
if (getProperties().getCombatPulse().isAttacking() && RandomFunction.random(20) < 6) {
sendChat(getWrathMessage());
} else if (getProperties().getCombatPulse().isInCombat() && RandomFunction.random(60) < 10) {
sendChat(getHailMessage());
}
}
@Override
public boolean canSelectTarget(Entity target) {
if (target instanceof Player) {
Player p = (Player) target;
if (type.isFriendly(p)) {
return false;
}
if (p.getZoneMonitor().isInZone("mage arena")) {
if (MageArenaPlugin.MAGE_ARENA.hasSession(p)) {
return false;
}
}
}
return true;
}
/**
* Gets the hail message.
* @return the message.
*/
public String getHailMessage() {
return "Hail " + type.getName() + "!";
}
/**
* Gets the wrath message.
* @return the message.
*/
public String getWrathMessage() {
return "Feel the wrath of " + type.getName() + ".";
}
@Override
public int[] getIds() {
// sara, zammy, guthix
return new int[] { 913, 912, 914 };
}
}

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