This commit is contained in:
Arthur Ice 2014-12-05 20:16:13 -08:00
commit 2aa287fe3c
124 changed files with 63220 additions and 2537 deletions

View File

@ -24,8 +24,8 @@
#EQEMU_DISABLE_LOGSYS
#EQEMU_COMMANDS_LOGGING
#EQEMU_BUILD_SERVER
#EQEMU_BUILD_LOGIN
#EQEMU_BUILD_TESTS
#EQEMU_BUILD_LOGIN
#EQEMU_BUILD_TESTS
#EQEMU_BUILD_PERL
#EQEMU_BUILD_LUA
#EQEMU_SANITIZE_LUA_LIBS
@ -103,7 +103,7 @@ IF(MSVC)
SET(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} /SAFESEH:NO")
SET(CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO} /SAFESEH:NO")
ENDIF(EQEMU_DISABLE_SAFESEH)
OPTION(EQEMU_BUILD_MSVC_MP "Enable build with multiple processes." ON)
IF(EQEMU_BUILD_MSVC_MP)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
@ -115,7 +115,7 @@ IF(MSVC)
STRING(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
ENDIF(${flag_var} MATCHES "/MD")
ENDFOREACH(flag_var)
ADD_DEFINITIONS(-DNOMINMAX)
ELSE(MSVC)
#Normally set by perl but we don't use the perl flags anymore so we set it.
@ -306,26 +306,26 @@ FIND_PACKAGE(ZLIB REQUIRED)
FIND_PACKAGE(MySQL REQUIRED)
IF(EQEMU_BUILD_PERL)
FIND_PACKAGE(PerlLibs REQUIRED)
INCLUDE_DIRECTORIES("${PERL_INCLUDE_PATH}")
INCLUDE_DIRECTORIES(SYSTEM "${PERL_INCLUDE_PATH}")
ENDIF(EQEMU_BUILD_PERL)
IF(EQEMU_BUILD_LUA)
FIND_PACKAGE(EQLua51 REQUIRED)
SET(Boost_USE_STATIC_LIBS OFF)
SET(Boost_USE_MULTITHREADED ON)
SET(Boost_USE_MULTITHREADED ON)
SET(Boost_USE_STATIC_RUNTIME OFF)
SET(BOOST_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/boost")
FIND_PACKAGE(Boost REQUIRED)
INCLUDE_DIRECTORIES("${LUA_INCLUDE_DIR}" "${Boost_INCLUDE_DIRS}" "luabind")
INCLUDE_DIRECTORIES(SYSTEM "${LUA_INCLUDE_DIR}" "${Boost_INCLUDE_DIRS}" "luabind")
OPTION(EQEMU_SANITIZE_LUA_LIBS "Sanitize Lua Libraries (Remove OS and IO standard libraries from being able to run)." ON)
IF(EQEMU_SANITIZE_LUA_LIBS)
ADD_DEFINITIONS(-DSANITIZE_LUA_LIBS)
ENDIF(EQEMU_SANITIZE_LUA_LIBS)
ENDIF(EQEMU_BUILD_LUA)
INCLUDE_DIRECTORIES("${ZLIB_INCLUDE_DIRS}" "${MySQL_INCLUDE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/common/glm/glm")
INCLUDE_DIRECTORIES(SYSTEM "${ZLIB_INCLUDE_DIRS}" "${MySQL_INCLUDE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/common/glm/glm")
IF(EQEMU_BUILD_LUA)
ADD_SUBDIRECTORY(luabind)

View File

@ -1,5 +1,31 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50)
-------------------------------------------------------
== 12/04/2014 ==
Kayen: Ranged attacks will now more accurately check MAX firing range, fixing the issue where you would
hit ranged attack and nothing would happpen due to incorrect server side range checks.
Trevius: Initial addition of the RoF2 client from May 10th 2013 (currently available on Steam as the F2P client).
Trevius: RoF2 is disabled by default, but you can enable by editing /common/patches/patches.cpp (see comments)
== 12/01/2014 ==
Trevius: Mercenaries now spawn as the same Gender and Size of the Merchant they are purchased from.
Trevius: Mercenaries now spawn with randomized facial features when purchased.
Trevius: Setting a lastname for NPCs will now override any hard coded lastname (such as GM Trainers).
Required SQL: utils/sql/git/required/2014_12_01_mercs_table_update.sql
== 11/28/2014 ==
Trevius: Fixed a zone crash related to numhits for spells.
Trevius: Fixed a query related to group leaders logging in.
Trevius (Natedog): Fixed a world crash related to attempting to join an adventure with Mercenaries.
== 11/27/2014 ==
Kayen: Projectiles (ie Arrows) fired from archery will now do damage upon impact instead of instantly (consistent w/ live).
Optional SQL: utils/sql/git/optional/2014_11_27_ProjectileDmgOnImpact.sql
== 11/25/2014 ==
Trevius: Spells that modify model size are now limited to 2 size adjustments from the base size.
Trevius: Fix to prevent Mercenaries from being set as Group Leader.
== 11/24/2014 ==
Trevius: Added Rule NPC:EnableMeritBasedFaction (disabled by default) - Allows faction gain to work similar to experience.

View File

@ -72,6 +72,7 @@ SET(common_sources
patches/sod.cpp
patches/sof.cpp
patches/rof.cpp
patches/rof2.cpp
patches/titanium.cpp
patches/underfoot.cpp
SocketLib/Base64.cpp
@ -168,6 +169,7 @@ SET(common_headers
ptimer.h
queue.h
races.h
random.h
rdtsc.h
rulesys.h
ruletypes.h
@ -216,6 +218,11 @@ SET(common_headers
patches/rof_itemfields.h
patches/rof_ops.h
patches/rof_structs.h
patches/rof2.h
patches/rof2_constants.h
patches/rof2_itemfields.h
patches/rof2_ops.h
patches/rof2_structs.h
patches/titanium.h
patches/titanium_constants.h
patches/titanium_itemfields.h
@ -269,6 +276,11 @@ SOURCE_GROUP(Patches FILES
patches/rof_ops.h
patches/rof_constants.h
patches/rof_structs.h
patches/rof2.h
patches/rof2_itemfields.h
patches/rof2_ops.h
patches/rof2_constants.h
patches/rof2_structs.h
patches/titanium.h
patches/titanium_itemfields.h
patches/titanium_ops.h
@ -284,6 +296,7 @@ SOURCE_GROUP(Patches FILES
patches/sod.cpp
patches/sof.cpp
patches/rof.cpp
patches/rof2.cpp
patches/titanium.cpp
patches/underfoot.cpp
)
@ -334,7 +347,9 @@ ADD_LIBRARY(common ${common_sources} ${common_headers})
IF(UNIX)
ADD_DEFINITIONS(-fPIC)
SET_SOURCE_FILES_PROPERTIES("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/underfoot.cpp" PROPERTIES COMPILE_FLAGS -O0)
SET_SOURCE_FILES_PROPERTIES("SocketLib/Mime.cpp" PROPERTY COMPILE_FLAGS -Wno-unused-result)
SET_SOURCE_FILES_PROPERTIES("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/rof2.cpp" "patches/underfoot.cpp" PROPERTIES COMPILE_FLAGS -O0)
ENDIF(UNIX)
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)

View File

@ -17,19 +17,16 @@
*/
#include "../common/debug.h"
#include "../common/rulesys.h"
#include <iostream>
#include <fstream>
#include <cmath>
#include <ctype.h>
#include <iomanip>
#include <iostream>
#include <limits.h>
#include <map>
#include <mysqld_error.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errmsg.h>
#include <mysqld_error.h>
#include <limits.h>
#include <ctype.h>
#include <assert.h>
#include <cmath>
#include <map>
// Disgrace: for windows compile
#ifdef _WINDOWS
@ -45,7 +42,6 @@
#include "database.h"
#include "eq_packet_structs.h"
#include "guilds.h"
#include "string_util.h"
#include "extprofile.h"
@ -768,7 +764,10 @@ uint32 Database::GetCharacterID(const char *name) {
std::string query = StringFormat("SELECT `id` FROM `character_data` WHERE `name` = '%s'", name);
auto results = QueryDatabase(query);
auto row = results.begin();
if (row[0]){ return atoi(row[0]); }
if (results.RowCount() == 1)
{
return atoi(row[0]);
}
return 0;
}
@ -901,14 +900,27 @@ bool Database::CheckDatabaseConversions() {
CheckDatabaseConvertCorpseDeblob();
/* Fetch Automatic Database Upgrade Script */
if (!std::ifstream("db_update.pl")){
// if (!std::ifstream("db_update.pl")){
std::cout << "Pulling down automatic database upgrade script...\n" << std::endl;
#ifdef _WIN32
system("perl -MLWP::UserAgent -e \"require LWP::UserAgent; my $ua = LWP::UserAgent->new; $ua->timeout(10); $ua->env_proxy; my $response = $ua->get('https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/db_update.pl'); if ($response->is_success){ open(FILE, '> db_update.pl'); print FILE $response->decoded_content; close(FILE); }\"");
#else
system("wget -O db_update.pl https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/db_update.pl");
#endif
}
// }
/*
Automatic Database Upgrade Script
Script: db_update.pl V 1 - the number that world passes to the script will
force the script to check for a newer version to update itself with
db_update.pl ran_from_world - won't bring up a menu if your database versions match
db_update.pl - ran standalone will bring up a menu prompt
*/
/* Check for a new version of this script, the arg passed
would have to be higher than the copy they have downloaded
locally and they will re fetch */
system("perl db_update.pl V 1");
/* Run Automatic Database Upgrade Script */
system("perl db_update.pl ran_from_world");
@ -3254,7 +3266,7 @@ char* Database::GetGroupLeaderForLogin(const char* name, char* leaderbuf) {
strcpy(leaderbuf, "");
uint32 group_id = 0;
std::string query = StringFormat("SELECT `groupid` FROM `group_id` WHERE `name = '%s'", name);
std::string query = StringFormat("SELECT `groupid` FROM `group_id` WHERE `name` = '%s'", name);
auto results = QueryDatabase(query);
for (auto row = results.begin(); row != results.end(); ++row)
@ -3264,7 +3276,7 @@ char* Database::GetGroupLeaderForLogin(const char* name, char* leaderbuf) {
if (group_id == 0)
return leaderbuf;
query = StringFormat("SELECT `leadername` FROM `group_leader` WHERE `gid` = '%u' AND `groupid` = %u LIMIT 1", group_id);
query = StringFormat("SELECT `leadername` FROM `group_leaders` WHERE `gid` = '%u' LIMIT 1", group_id);
results = QueryDatabase(query);
for (auto row = results.begin(); row != results.end(); ++row)

View File

@ -41,6 +41,7 @@ class SpawnGroupList;
class Petition;
class Client;
class Merc;
class MySQLRequestResult;
struct Combine_Struct;
//struct Faction;
//struct FactionMods;
@ -68,21 +69,15 @@ uint8 eventid;
EventLogDetails_Struct eld[255];
};
// Added By Hogie
// INSERT into variables (varname,value) values('decaytime [minlevel] [maxlevel]','[number of seconds]');
// IE: decaytime 1 54 = Levels 1 through 54
// decaytime 55 100 = Levels 55 through 100
// It will always put the LAST time for the level (I think) from the Database
struct npcDecayTimes_Struct {
uint16 minlvl;
uint16 maxlvl;
uint32 seconds;
};
// Added By Hogie -- End
struct VarCache_Struct {
char varname[26]; // varname is char(25) in database
char varname[26];
char value[0];
};

View File

@ -539,7 +539,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ EmuConstants::MAP_POSSESSIONS_SIZE,
/*Underfoot*/ EmuConstants::MAP_POSSESSIONS_SIZE,
/*RoF*/ EmuConstants::MAP_POSSESSIONS_SIZE,
/*RoF2*/ 0,
/*RoF2*/ EmuConstants::MAP_POSSESSIONS_SIZE,
/*NPC*/ EmuConstants::MAP_POSSESSIONS_SIZE,
/*Merc*/ EmuConstants::MAP_POSSESSIONS_SIZE,
@ -554,7 +554,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ EmuConstants::MAP_BANK_SIZE,
/*Underfoot*/ EmuConstants::MAP_BANK_SIZE,
/*RoF*/ EmuConstants::MAP_BANK_SIZE,
/*RoF2*/ 0,
/*RoF2*/ EmuConstants::MAP_BANK_SIZE,
/*NPC*/ NOT_USED,
/*Merc*/ NOT_USED,
@ -569,7 +569,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ EmuConstants::MAP_SHARED_BANK_SIZE,
/*Underfoot*/ EmuConstants::MAP_SHARED_BANK_SIZE,
/*RoF*/ EmuConstants::MAP_SHARED_BANK_SIZE,
/*RoF2*/ 0,
/*RoF2*/ EmuConstants::MAP_SHARED_BANK_SIZE,
/*NPC*/ NOT_USED,
/*Merc*/ NOT_USED,
@ -584,7 +584,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ EmuConstants::MAP_TRADE_SIZE,
/*Underfoot*/ EmuConstants::MAP_TRADE_SIZE,
/*RoF*/ EmuConstants::MAP_TRADE_SIZE,
/*RoF2*/ 0,
/*RoF2*/ EmuConstants::MAP_TRADE_SIZE,
/*NPC*/ 4,
/*Merc*/ 4,
@ -599,7 +599,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ EmuConstants::MAP_WORLD_SIZE,
/*Underfoot*/ EmuConstants::MAP_WORLD_SIZE,
/*RoF*/ EmuConstants::MAP_WORLD_SIZE,
/*RoF2*/ 0,
/*RoF2*/ EmuConstants::MAP_WORLD_SIZE,
/*NPC*/ NOT_USED,
/*Merc*/ NOT_USED,
@ -614,7 +614,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ EmuConstants::MAP_LIMBO_SIZE,
/*Underfoot*/ EmuConstants::MAP_LIMBO_SIZE,
/*RoF*/ EmuConstants::MAP_LIMBO_SIZE,
/*RoF2*/ 0,
/*RoF2*/ EmuConstants::MAP_LIMBO_SIZE,
/*NPC*/ NOT_USED,
/*Merc*/ NOT_USED,
@ -629,7 +629,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ EmuConstants::MAP_TRIBUTE_SIZE,
/*Underfoot*/ EmuConstants::MAP_TRIBUTE_SIZE,
/*RoF*/ EmuConstants::MAP_TRIBUTE_SIZE,
/*RoF2*/ 0,
/*RoF2*/ EmuConstants::MAP_TRIBUTE_SIZE,
/*NPC*/ 0,
/*Merc*/ 0,
@ -644,7 +644,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ 0,
/*Underfoot*/ 0,
/*RoF*/ EmuConstants::MAP_TROPHY_TRIBUTE_SIZE,
/*RoF2*/ 0,
/*RoF2*/ EmuConstants::MAP_TROPHY_TRIBUTE_SIZE,
/*NPC*/ 0,
/*Merc*/ 0,
@ -659,7 +659,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ 0,
/*Underfoot*/ 0,
/*RoF*/ EmuConstants::MAP_GUILD_TRIBUTE_SIZE,
/*RoF2*/ 0,
/*RoF2*/ EmuConstants::MAP_GUILD_TRIBUTE_SIZE,
/*NPC*/ 0,
/*Merc*/ 0,
@ -674,7 +674,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ 0,
/*Underfoot*/ 0,
/*RoF*/ EmuConstants::MAP_MERCHANT_SIZE,
/*RoF2*/ 0,
/*RoF2*/ EmuConstants::MAP_MERCHANT_SIZE,
/*NPC*/ 0,
/*Merc*/ 0,
@ -689,7 +689,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ 0,
/*Underfoot*/ 0,
/*RoF*/ EmuConstants::MAP_DELETED_SIZE,
/*RoF2*/ 0,
/*RoF2*/ EmuConstants::MAP_DELETED_SIZE,
/*NPC*/ 0,
/*Merc*/ 0,
@ -704,7 +704,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ SoD::consts::MAP_CORPSE_SIZE,
/*Underfoot*/ Underfoot::consts::MAP_CORPSE_SIZE,
/*RoF*/ RoF::consts::MAP_CORPSE_SIZE,
/*RoF2*/ 0,
/*RoF2*/ RoF2::consts::MAP_CORPSE_SIZE,
/*NPC*/ 0,
/*Merc*/ 0,
@ -719,7 +719,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ EmuConstants::MAP_BAZAAR_SIZE,
/*Underfoot*/ EmuConstants::MAP_BAZAAR_SIZE,
/*RoF*/ EmuConstants::MAP_BAZAAR_SIZE,
/*RoF2*/ 0,
/*RoF2*/ EmuConstants::MAP_BAZAAR_SIZE,
/*NPC*/ 0, // this may need to be 'EmuConstants::MAP_BAZAAR_SIZE' if offline client traders respawn as an npc
/*Merc*/ 0,
@ -734,7 +734,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ SoD::consts::MAP_INSPECT_SIZE,
/*Underfoot*/ Underfoot::consts::MAP_INSPECT_SIZE,
/*RoF*/ RoF::consts::MAP_INSPECT_SIZE,
/*RoF2*/ 0,
/*RoF2*/ RoF2::consts::MAP_INSPECT_SIZE,
/*NPC*/ NOT_USED,
/*Merc*/ NOT_USED,
@ -749,7 +749,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ 0,
/*Underfoot*/ 0,
/*RoF*/ EmuConstants::MAP_REAL_ESTATE_SIZE,
/*RoF2*/ 0,
/*RoF2*/ EmuConstants::MAP_REAL_ESTATE_SIZE,
/*NPC*/ 0,
/*Merc*/ 0,
@ -764,7 +764,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ 0,
/*Underfoot*/ 0,
/*RoF*/ EmuConstants::MAP_VIEW_MOD_PC_SIZE,
/*RoF2*/ 0,
/*RoF2*/ EmuConstants::MAP_VIEW_MOD_PC_SIZE,
/*NPC*/ 0,
/*Merc*/ 0,
@ -779,7 +779,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ 0,
/*Underfoot*/ 0,
/*RoF*/ EmuConstants::MAP_VIEW_MOD_BANK_SIZE,
/*RoF2*/ 0,
/*RoF2*/ EmuConstants::MAP_VIEW_MOD_BANK_SIZE,
/*NPC*/ 0,
/*Merc*/ 0,
@ -794,7 +794,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ 0,
/*Underfoot*/ 0,
/*RoF*/ EmuConstants::MAP_VIEW_MOD_SHARED_BANK_SIZE,
/*RoF2*/ 0,
/*RoF2*/ EmuConstants::MAP_VIEW_MOD_SHARED_BANK_SIZE,
/*NPC*/ 0,
/*Merc*/ 0,
@ -809,7 +809,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ 0,
/*Underfoot*/ 0,
/*RoF*/ EmuConstants::MAP_VIEW_MOD_LIMBO_SIZE,
/*RoF2*/ 0,
/*RoF2*/ EmuConstants::MAP_VIEW_MOD_LIMBO_SIZE,
/*NPC*/ 0,
/*Merc*/ 0,
@ -824,7 +824,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ 0,
/*Underfoot*/ 0,
/*RoF*/ EmuConstants::MAP_ALT_STORAGE_SIZE,
/*RoF2*/ 0,
/*RoF2*/ EmuConstants::MAP_ALT_STORAGE_SIZE,
/*NPC*/ 0,
/*Merc*/ 0,
@ -839,7 +839,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ 0,
/*Underfoot*/ 0,
/*RoF*/ EmuConstants::MAP_ARCHIVED_SIZE,
/*RoF2*/ 0,
/*RoF2*/ EmuConstants::MAP_ARCHIVED_SIZE,
/*NPC*/ 0,
/*Merc*/ 0,
@ -854,7 +854,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ 0,
/*Underfoot*/ 0,
/*RoF*/ EmuConstants::MAP_MAIL_SIZE,
/*RoF2*/ 0,
/*RoF2*/ EmuConstants::MAP_MAIL_SIZE,
/*NPC*/ 0,
/*Merc*/ 0,
@ -869,7 +869,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ 0,
/*Underfoot*/ 0,
/*RoF*/ EmuConstants::MAP_GUILD_TROPHY_TRIBUTE_SIZE,
/*RoF2*/ 0,
/*RoF2*/ EmuConstants::MAP_GUILD_TROPHY_TRIBUTE_SIZE,
/*NPC*/ 0,
/*Merc*/ 0,
@ -884,7 +884,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ NOT_USED,
/*Underfoot*/ NOT_USED,
/*RoF*/ EmuConstants::MAP_KRONO_SIZE,
/*RoF2*/ 0,
/*RoF2*/ EmuConstants::MAP_KRONO_SIZE,
/*NPC*/ 0,
/*Merc*/ 0,
@ -899,7 +899,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ 0,
/*Underfoot*/ 0,
/*RoF*/ EmuConstants::MAP_OTHER_SIZE,
/*RoF2*/ 0,
/*RoF2*/ EmuConstants::MAP_OTHER_SIZE,
/*NPC*/ 0,
/*Merc*/ 0,
@ -1012,7 +1012,7 @@ bool EQLimits::AllowsEmptyBagInBag(uint32 version) {
/*SoD*/ SoD::limits::ALLOWS_EMPTY_BAG_IN_BAG,
/*Underfoot*/ Underfoot::limits::ALLOWS_EMPTY_BAG_IN_BAG,
/*RoF*/ RoF::limits::ALLOWS_EMPTY_BAG_IN_BAG,
/*RoF2*/ false,
/*RoF2*/ RoF2::limits::ALLOWS_EMPTY_BAG_IN_BAG,
/*NPC*/ false,
/*Merc*/ false,
@ -1033,7 +1033,7 @@ bool EQLimits::AllowsClickCastFromBag(uint32 version) {
/*SoD*/ SoD::limits::ALLOWS_CLICK_CAST_FROM_BAG,
/*Underfoot*/ Underfoot::limits::ALLOWS_CLICK_CAST_FROM_BAG,
/*RoF*/ RoF::limits::ALLOWS_CLICK_CAST_FROM_BAG,
/*RoF2*/ false,
/*RoF2*/ RoF2::limits::ALLOWS_CLICK_CAST_FROM_BAG,
/*NPC*/ false,
/*Merc*/ false,
@ -1054,7 +1054,7 @@ uint16 EQLimits::ItemCommonSize(uint32 version) {
/*SoD*/ EmuConstants::ITEM_COMMON_SIZE,
/*Underfoot*/ EmuConstants::ITEM_COMMON_SIZE,
/*RoF*/ EmuConstants::ITEM_COMMON_SIZE,
/*RoF2*/ 0,
/*RoF2*/ EmuConstants::ITEM_COMMON_SIZE,
/*NPC*/ EmuConstants::ITEM_COMMON_SIZE,
/*Merc*/ EmuConstants::ITEM_COMMON_SIZE,
@ -1074,7 +1074,7 @@ uint16 EQLimits::ItemContainerSize(uint32 version) {
/*SoD*/ EmuConstants::ITEM_CONTAINER_SIZE,
/*Underfoot*/ EmuConstants::ITEM_CONTAINER_SIZE,
/*RoF*/ EmuConstants::ITEM_CONTAINER_SIZE,
/*RoF2*/ 0,
/*RoF2*/ EmuConstants::ITEM_CONTAINER_SIZE,
/*NPC*/ EmuConstants::ITEM_CONTAINER_SIZE,
/*Merc*/ EmuConstants::ITEM_CONTAINER_SIZE,
@ -1094,7 +1094,7 @@ bool EQLimits::CoinHasWeight(uint32 version) {
/*SoD*/ SoD::limits::COIN_HAS_WEIGHT,
/*Underfoot*/ Underfoot::limits::COIN_HAS_WEIGHT,
/*RoF*/ RoF::limits::COIN_HAS_WEIGHT,
/*RoF2*/ true,
/*RoF2*/ RoF::limits::COIN_HAS_WEIGHT,
/*NPC*/ true,
/*Merc*/ true,
@ -1114,7 +1114,7 @@ uint32 EQLimits::BandoliersCount(uint32 version) {
/*SoD*/ EmuConstants::BANDOLIERS_COUNT,
/*Underfoot*/ EmuConstants::BANDOLIERS_COUNT,
/*RoF*/ EmuConstants::BANDOLIERS_COUNT,
/*RoF2*/ 0,
/*RoF2*/ EmuConstants::BANDOLIERS_COUNT,
/*NPC*/ NOT_USED,
/*Merc*/ NOT_USED,
@ -1134,7 +1134,7 @@ uint32 EQLimits::BandolierSize(uint32 version) {
/*SoD*/ EmuConstants::BANDOLIER_SIZE,
/*Underfoot*/ EmuConstants::BANDOLIER_SIZE,
/*RoF*/ EmuConstants::BANDOLIER_SIZE,
/*RoF2*/ 0,
/*RoF2*/ EmuConstants::BANDOLIER_SIZE,
/*NPC*/ NOT_USED,
/*Merc*/ NOT_USED,
@ -1154,7 +1154,7 @@ uint32 EQLimits::PotionBeltSize(uint32 version) {
/*SoD*/ EmuConstants::POTION_BELT_SIZE,
/*Underfoot*/ EmuConstants::POTION_BELT_SIZE,
/*RoF*/ EmuConstants::POTION_BELT_SIZE,
/*RoF2*/ 0,
/*RoF2*/ EmuConstants::POTION_BELT_SIZE,
/*NPC*/ NOT_USED,
/*Merc*/ NOT_USED,

View File

@ -32,7 +32,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../common/patches/sod_constants.h"
#include "../common/patches/underfoot_constants.h"
#include "../common/patches/rof_constants.h"
//#include "../common/patches/rof2_constants.h"
#include "../common/patches/rof2_constants.h"
// *** DO NOT CHANGE without a full understanding of the consequences..the server is set up to use these settings explicitly!! ***
// *** You will cause compilation failures and corrupt your database if partial or incorrect attempts to change them are made!! ***

View File

@ -1412,6 +1412,8 @@ ItemInst::ItemInst(const Item_Struct* item, int16 charges) {
m_scaledItem = nullptr;
m_evolveInfo = nullptr;
m_scaling = false;
m_ornamenticon = 0;
m_ornamentidfile = 0;
}
ItemInst::ItemInst(SharedDatabase *db, uint32 item_id, int16 charges) {
@ -1434,6 +1436,8 @@ ItemInst::ItemInst(SharedDatabase *db, uint32 item_id, int16 charges) {
m_scaledItem = nullptr;
m_evolveInfo = nullptr;
m_scaling = false;
m_ornamenticon = 0;
m_ornamentidfile = 0;
}
ItemInst::ItemInst(ItemInstTypes use_type) {
@ -1451,6 +1455,8 @@ ItemInst::ItemInst(ItemInstTypes use_type) {
m_scaledItem = nullptr;
m_evolveInfo = nullptr;
m_scaling = false;
m_ornamenticon = 0;
m_ornamentidfile = 0;
}
// Make a copy of an ItemInst object
@ -1501,6 +1507,8 @@ ItemInst::ItemInst(const ItemInst& copy)
m_evolveInfo = nullptr;
m_scaling = copy.m_scaling;
m_ornamenticon = copy.m_ornamenticon;
m_ornamentidfile = copy.m_ornamentidfile;
}
// Clean up container contents
@ -1789,6 +1797,52 @@ ItemInst* ItemInst::GetOrnamentationAug(int ornamentationAugtype) const
return nullptr;
}
bool ItemInst::CanTransform(const Item_Struct *ItemToTry, const Item_Struct *Container, bool AllowAll) {
if (!ItemToTry || !Container) return false;
if (ItemToTry->ItemType == ItemTypeArrow || strnlen(Container->CharmFile, 30) == 0)
return false;
if (AllowAll && strncasecmp(Container->CharmFile, "ITEMTRANSFIGSHIELD", 18) && strncasecmp(Container->CharmFile, "ITEMTransfigBow", 15)) {
switch (ItemToTry->ItemType) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 35:
case 45:
return true;
}
}
static std::map<std::string, int> types;
types["itemtransfig1hp"] = 2;
types["itemtransfig1hs"] = 0;
types["itemtransfig2hb"] = 4;
types["itemtransfig2hp"] = 35;
types["itemtransfig2hs"] = 1;
types["itemtransfigblunt"] = 3;
types["itemtransfigbow"] = 5;
types["itemtransfighth"] = 45;
types["itemtransfigshield"] = 8;
types["itemtransfigslashing"] = 0;
auto i = types.find(MakeLowerString(Container->CharmFile));
if (i != types.end() && i->second == ItemToTry->ItemType)
return true;
static std::map<std::string, int> typestwo;
typestwo["itemtransfigblunt"] = 4;
typestwo["itemtransfigslashing"] = 1;
i = typestwo.find(MakeLowerString(Container->CharmFile));
if (i != typestwo.end() && i->second == ItemToTry->ItemType)
return true;
return false;
}
uint32 ItemInst::GetAugmentItemID(uint8 slot) const
{
uint32 id = NO_ITEM;

View File

@ -330,6 +330,7 @@ public:
ItemInst* RemoveAugment(uint8 index);
bool IsAugmented();
ItemInst* GetOrnamentationAug(int ornamentationAugtype) const;
static bool CanTransform(const Item_Struct *ItemToTry, const Item_Struct *Container, bool AllowAll = false);
// Has attack/delay?
bool IsWeapon() const;
@ -392,6 +393,10 @@ public:
void SetActivated(bool activated) { m_activated = activated; }
int8 GetEvolveLvl() const { return m_evolveLvl; }
void SetScaling(bool v) { m_scaling = v; }
uint32 GetOrnamentationIcon() const { return m_ornamenticon; }
void SetOrnamentIcon(uint32 ornament_icon) { m_ornamenticon = ornament_icon; }
uint32 GetOrnamentationIDFile() const { return m_ornamentidfile; }
void SetOrnamentationIDFile(uint32 ornament_idfile) { m_ornamentidfile = ornament_idfile; }
void Initialize(SharedDatabase *db = nullptr);
void ScaleItem();
@ -436,6 +441,8 @@ protected:
Item_Struct* m_scaledItem;
EvolveInfo* m_evolveInfo;
bool m_scaling;
uint32 m_ornamenticon;
uint32 m_ornamentidfile;
//
// Items inside of this item (augs or contents);

View File

@ -54,20 +54,6 @@
#include <errno.h>
#endif
static bool WELLRNG_init = false;
static int state_i = 0;
static unsigned int STATE[R];
static unsigned int z0, z1, z2;
unsigned int (*WELLRNG19937)(void);
static unsigned int case_1 (void);
static unsigned int case_2 (void);
static unsigned int case_3 (void);
static unsigned int case_4 (void);
static unsigned int case_5 (void);
static unsigned int case_6 (void);
uint32 rnd_hash(time_t t, clock_t c);
void oneseed(const uint32 seed);
void CoutTimestamp(bool ms) {
time_t rawtime;
struct tm* gmt_t;
@ -179,41 +165,6 @@ const char * itoa(int num, char* a,int b) {
}
#endif
/*
* generate a random integer in the range low-high this
* should be used instead of the rand()%limit method
*/
int MakeRandomInt(int low, int high)
{
if(low >= high)
return(low);
//return (rand()%(high-low+1) + (low));
if(!WELLRNG_init) {
WELLRNG_init = true;
oneseed( rnd_hash( time(nullptr), clock() ) );
WELLRNG19937 = case_1;
}
unsigned int randomnum = ((WELLRNG19937)());
if(randomnum == 0xffffffffUL)
return high;
return int ((randomnum / (double)0xffffffffUL) * (high - low + 1) + low);
}
double MakeRandomFloat(double low, double high)
{
if(low >= high)
return(low);
//return (rand() / (double)RAND_MAX * (high - low) + low);
if(!WELLRNG_init) {
WELLRNG_init = true;
oneseed( rnd_hash( time(nullptr), clock() ) );
WELLRNG19937 = case_1;
}
return ((WELLRNG19937)() / (double)0xffffffffUL * (high - low) + low);
}
uint32 rnd_hash( time_t t, clock_t c )
{
// Get a uint32 from t and c
@ -239,111 +190,6 @@ uint32 rnd_hash( time_t t, clock_t c )
return ( h1 + differ++ ) ^ h2;
}
void oneseed( const uint32 seed )
{
// Initialize generator state with seed
// See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
// In previous versions, most significant bits (MSBs) of the seed affect
// only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto.
register int j = 0;
STATE[j] = seed & 0xffffffffUL;
for (j = 1; j < R; j++)
{
STATE[j] = ( 1812433253UL * ( STATE[j-1] ^ (STATE[j-1] >> 30) ) + j ) & 0xffffffffUL;
}
}
// WELL RNG code
/* ***************************************************************************** */
/* Copyright: Francois Panneton and Pierre L'Ecuyer, University of Montreal */
/* Makoto Matsumoto, Hiroshima University */
/* Notice: This code can be used freely for personal, academic, */
/* or non-commercial purposes. For commercial purposes, */
/* please contact P. L'Ecuyer at: lecuyer@iro.UMontreal.ca */
/* A modified "maximally equidistributed" implementation */
/* by Shin Harase, Hiroshima University. */
/* ***************************************************************************** */
unsigned int case_1 (void){
// state_i == 0
z0 = (VRm1Under & MASKL) | (VRm2Under & MASKU);
z1 = MAT0NEG (-25, V0) ^ MAT0POS (27, VM1);
z2 = MAT3POS (9, VM2) ^ MAT0POS (1, VM3);
newV1 = z1 ^ z2;
newV0Under = MAT1 (z0) ^ MAT0NEG (-9, z1) ^ MAT0NEG (-21, z2) ^ MAT0POS (21, newV1);
state_i = R - 1;
WELLRNG19937 = case_3;
return (STATE[state_i] ^ (newVM2Over & BITMASK));
}
static unsigned int case_2 (void){
// state_i == 1
z0 = (VRm1 & MASKL) | (VRm2Under & MASKU);
z1 = MAT0NEG (-25, V0) ^ MAT0POS (27, VM1);
z2 = MAT3POS (9, VM2) ^ MAT0POS (1, VM3);
newV1 = z1 ^ z2;
newV0 = MAT1 (z0) ^ MAT0NEG (-9, z1) ^ MAT0NEG (-21, z2) ^ MAT0POS (21, newV1);
state_i = 0;
WELLRNG19937 = case_1;
return (STATE[state_i] ^ (newVM2 & BITMASK));
}
static unsigned int case_3 (void){
// state_i+M1 >= R
z0 = (VRm1 & MASKL) | (VRm2 & MASKU);
z1 = MAT0NEG (-25, V0) ^ MAT0POS (27, VM1Over);
z2 = MAT3POS (9, VM2Over) ^ MAT0POS (1, VM3Over);
newV1 = z1 ^ z2;
newV0 = MAT1 (z0) ^ MAT0NEG (-9, z1) ^ MAT0NEG (-21, z2) ^ MAT0POS (21, newV1);
state_i--;
if (state_i + M1 < R)
WELLRNG19937 = case_5;
return (STATE[state_i] ^ (newVM2Over & BITMASK));
}
static unsigned int case_4 (void){
// state_i+M3 >= R
z0 = (VRm1 & MASKL) | (VRm2 & MASKU);
z1 = MAT0NEG (-25, V0) ^ MAT0POS (27, VM1);
z2 = MAT3POS (9, VM2) ^ MAT0POS (1, VM3Over);
newV1 = z1 ^ z2;
newV0 = MAT1 (z0) ^ MAT0NEG (-9, z1) ^ MAT0NEG (-21, z2) ^ MAT0POS (21, newV1);
state_i--;
if (state_i + M3 < R)
WELLRNG19937 = case_6;
return (STATE[state_i] ^ (newVM2 & BITMASK));
}
static unsigned int case_5 (void){
// state_i+M2 >= R
z0 = (VRm1 & MASKL) | (VRm2 & MASKU);
z1 = MAT0NEG (-25, V0) ^ MAT0POS (27, VM1);
z2 = MAT3POS (9, VM2Over) ^ MAT0POS (1, VM3Over);
newV1 = z1 ^ z2;
newV0 = MAT1 (z0) ^ MAT0NEG (-9, z1) ^ MAT0NEG (-21, z2) ^ MAT0POS (21, newV1);
state_i--;
if (state_i + M2 < R)
WELLRNG19937 = case_4;
return (STATE[state_i] ^ (newVM2Over & BITMASK));
}
static unsigned int case_6 (void){
// 2 <= state_i <= (R - M3 - 1)
z0 = (VRm1 & MASKL) | (VRm2 & MASKU);
z1 = MAT0NEG (-25, V0) ^ MAT0POS (27, VM1);
z2 = MAT3POS (9, VM2) ^ MAT0POS (1, VM3);
newV1 = z1 ^ z2;
newV0 = MAT1 (z0) ^ MAT0NEG (-9, z1) ^ MAT0NEG (-21, z2) ^ MAT0POS (21, newV1);
state_i--;
if (state_i == 1)
WELLRNG19937 = case_2;
return (STATE[state_i] ^ (newVM2 & BITMASK));
}
// end WELL RNG code
float EQ13toFloat(int d)
{
return ( float(d)/float(1<<2));

View File

@ -8,7 +8,7 @@
#include "sof.h"
#include "sod.h"
#include "rof.h"
//#include "rof2.h"
#include "rof2.h"
void RegisterAllPatches(EQStreamIdentifier &into) {
Client62::Register(into);
@ -17,6 +17,7 @@ void RegisterAllPatches(EQStreamIdentifier &into) {
SoD::Register(into);
Underfoot::Register(into);
RoF::Register(into);
// Uncomment the line below to enable RoF2 Client
//RoF2::Register(into);
}
@ -27,5 +28,6 @@ void ReloadAllPatches() {
SoD::Reload();
Underfoot::Reload();
RoF::Reload();
// Uncomment the line below to enable RoF2 Client
//RoF2::Reload();
}

View File

@ -4888,6 +4888,16 @@ namespace RoF
//Icon
ornaIcon = aug_weap->Icon;
}
else if (inst->GetOrnamentationIDFile() && inst->GetOrnamentationIcon()) {
char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile());
//Mainhand
ss.write(tmp, strlen(tmp));
ss.write((const char*)&null_term, sizeof(uint8));
//Offhand
ss.write(tmp, strlen(tmp));
ss.write((const char*)&null_term, sizeof(uint8));
ornaIcon = inst->GetOrnamentationIcon();
}
else {
ss.write((const char*)&null_term, sizeof(uint8)); //no mh
ss.write((const char*)&null_term, sizeof(uint8));//no of

5673
common/patches/rof2.cpp Normal file

File diff suppressed because it is too large Load Diff

37
common/patches/rof2.h Normal file
View File

@ -0,0 +1,37 @@
#ifndef RoF2_H_
#define RoF2_H_
#include "../struct_strategy.h"
class EQStreamIdentifier;
namespace RoF2 {
//these are the only public member of this namespace.
extern void Register(EQStreamIdentifier &into);
extern void Reload();
//you should not directly access anything below..
//I just dont feel like making a seperate header for it.
class Strategy : public StructStrategy {
public:
Strategy();
protected:
virtual std::string Describe() const;
virtual const EQClientVersion ClientVersion() const;
//magic macro to declare our opcode processors
#include "ss_declare.h"
#include "rof2_ops.h"
};
};
#endif /*RoF2_H_*/

View File

@ -0,0 +1,217 @@
/*
EQEMu: Everquest Server Emulator
Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef RoF2_CONSTANTS_H_
#define RoF2_CONSTANTS_H_
#include "../types.h"
namespace RoF2 {
namespace maps {
typedef enum : int16 {
MapPossessions = 0,
MapBank,
MapSharedBank,
MapTrade,
MapWorld,
MapLimbo,
MapTribute,
MapTrophyTribute,
MapGuildTribute,
MapMerchant,
MapDeleted,
MapCorpse,
MapBazaar,
MapInspect,
MapRealEstate,
MapViewMODPC,
MapViewMODBank,
MapViewMODSharedBank,
MapViewMODLimbo,
MapAltStorage,
MapArchived,
MapMail,
MapGuildTrophyTribute,
MapKrono,
MapOther,
_MapCount
} InventoryMaps;
}
namespace slots {
typedef enum : int16 {
MainCharm = 0,
MainEar1,
MainHead,
MainFace,
MainEar2,
MainNeck,
MainShoulders,
MainArms,
MainBack,
MainWrist1,
MainWrist2,
MainRange,
MainHands,
MainPrimary,
MainSecondary,
MainFinger1,
MainFinger2,
MainChest,
MainLegs,
MainFeet,
MainWaist,
MainPowerSource,
MainAmmo,
MainGeneral1,
MainGeneral2,
MainGeneral3,
MainGeneral4,
MainGeneral5,
MainGeneral6,
MainGeneral7,
MainGeneral8,
MainGeneral9,
MainGeneral10,
MainCursor,
_MainCount,
_MainEquipmentBegin = MainCharm,
_MainEquipmentEnd = MainAmmo,
_MainEquipmentCount = (_MainEquipmentEnd - _MainEquipmentBegin + 1),
_MainGeneralBegin = MainGeneral1,
_MainGeneralEnd = MainGeneral10,
_MainGeneralCount = (_MainGeneralEnd - _MainGeneralBegin + 1)
} EquipmentSlots;
}
namespace consts {
static const uint16 MAP_POSSESSIONS_SIZE = slots::_MainCount;
static const uint16 MAP_BANK_SIZE = 24;
static const uint16 MAP_SHARED_BANK_SIZE = 2;
static const uint16 MAP_TRADE_SIZE = 8;
static const uint16 MAP_WORLD_SIZE = 10;
static const uint16 MAP_LIMBO_SIZE = 36;
static const uint16 MAP_TRIBUTE_SIZE = 0; //?
static const uint16 MAP_TROPHY_TRIBUTE_SIZE = 0;
static const uint16 MAP_GUILD_TRIBUTE_SIZE = 0;
static const uint16 MAP_MERCHANT_SIZE = 0;
static const uint16 MAP_DELETED_SIZE = 0;
static const uint16 MAP_CORPSE_SIZE = slots::_MainCount;
static const uint16 MAP_BAZAAR_SIZE = 200;
static const uint16 MAP_INSPECT_SIZE = slots::_MainEquipmentCount;
static const uint16 MAP_REAL_ESTATE_SIZE = 0;
static const uint16 MAP_VIEW_MOD_PC_SIZE = MAP_POSSESSIONS_SIZE;
static const uint16 MAP_VIEW_MOD_BANK_SIZE = MAP_BANK_SIZE;
static const uint16 MAP_VIEW_MOD_SHARED_BANK_SIZE = MAP_SHARED_BANK_SIZE;
static const uint16 MAP_VIEW_MOD_LIMBO_SIZE = MAP_LIMBO_SIZE;
static const uint16 MAP_ALT_STORAGE_SIZE = 0;
static const uint16 MAP_ARCHIVED_SIZE = 0;
static const uint16 MAP_MAIL_SIZE = 0;
static const uint16 MAP_GUILD_TROPHY_TRIBUTE_SIZE = 0;
static const uint16 MAP_KRONO_SIZE = NOT_USED;
static const uint16 MAP_OTHER_SIZE = 0;
// most of these definitions will go away with the structure-based system..this maintains compatibility for now
// (bag slots and main slots beyond Possessions are assigned for compatibility with current server coding)
static const int16 EQUIPMENT_BEGIN = slots::MainCharm;
static const int16 EQUIPMENT_END = slots::MainAmmo;
static const uint16 EQUIPMENT_SIZE = slots::_MainEquipmentCount;
static const int16 GENERAL_BEGIN = slots::MainGeneral1;
static const int16 GENERAL_END = slots::MainGeneral10;
static const uint16 GENERAL_SIZE = slots::_MainGeneralCount;
static const int16 GENERAL_BAGS_BEGIN = 251;
static const int16 GENERAL_BAGS_END_OFFSET = 99;
static const int16 GENERAL_BAGS_END = GENERAL_BAGS_BEGIN + GENERAL_BAGS_END_OFFSET;
static const int16 CURSOR = slots::MainCursor;
static const int16 CURSOR_BAG_BEGIN = 351;
static const int16 CURSOR_BAG_END_OFFSET = 9;
static const int16 CURSOR_BAG_END = CURSOR_BAG_BEGIN + CURSOR_BAG_END_OFFSET;
static const int16 BANK_BEGIN = 2000;
static const int16 BANK_END = 2023;
static const int16 BANK_BAGS_BEGIN = 2031;
static const int16 BANK_BAGS_END_OFFSET = 239;
static const int16 BANK_BAGS_END = BANK_BAGS_BEGIN + BANK_BAGS_END_OFFSET;
static const int16 SHARED_BANK_BEGIN = 2500;
static const int16 SHARED_BANK_END = 2501;
static const int16 SHARED_BANK_BAGS_BEGIN = 2531;
static const int16 SHARED_BANK_BAGS_END_OFFSET = 19;
static const int16 SHARED_BANK_BAGS_END = SHARED_BANK_BAGS_BEGIN + SHARED_BANK_BAGS_END_OFFSET;
static const int16 TRADE_BEGIN = 3000;
static const int16 TRADE_END = 3007;
static const int16 TRADE_NPC_END = 3003;
static const int16 TRADE_BAGS_BEGIN = 3031;
static const int16 TRADE_BAGS_END_OFFSET = 79;
static const int16 TRADE_BAGS_END = TRADE_BAGS_BEGIN + TRADE_BAGS_END_OFFSET;
static const int16 WORLD_BEGIN = 4000;
static const int16 WORLD_END = 4009;
static const int16 TRIBUTE_BEGIN = 400;
static const int16 TRIBUTE_END = 404;
static const int16 CORPSE_BEGIN = slots::MainGeneral1;
static const int16 CORPSE_END = slots::MainGeneral1 + slots::MainCursor;
static const uint16 ITEM_COMMON_SIZE = 6;
static const uint16 ITEM_CONTAINER_SIZE = 255; // 255; (server max will be 255..unsure what actual client is - test)
static const uint32 BANDOLIERS_COUNT = 20; // count = number of bandolier instances
static const uint32 BANDOLIER_SIZE = 4; // size = number of equipment slots in bandolier instance
static const uint32 POTION_BELT_SIZE = 5;
}
namespace limits {
static const bool ALLOWS_EMPTY_BAG_IN_BAG = true;
static const bool ALLOWS_CLICK_CAST_FROM_BAG = true;
static const bool COIN_HAS_WEIGHT = false;
}
}; //end namespace RoF2
#endif /*RoF2_CONSTANTS_H_*/
/*
RoF2 Notes:
** Structure-based inventory **
ok Possessions: ( 0, { 0 .. 33 }, -1, -1 ) (Corpse: { 23 .. 56 } [Offset 23])
ok [Equipment: ( 0, { 0 .. 22 }, -1, -1 )]
ok [General: ( 0, { 23 .. 32 }, -1, -1 )]
ok [Cursor: ( 0, 33, -1, -1 )]
General Bags: ( 0, { 23 .. 32 }, { 0 .. (maxsize - 1) }, -1 )
Cursor Bags: ( 0, 33, { 0 .. (maxsize - 1) }, -1 )
Bank: ( 1, { 0 .. 23 }, -1, -1 )
Bank Bags: ( 1, { 0 .. 23 }, { 0 .. (maxsize - 1)}, -1 )
Shared Bank: ( 2, { 0 .. 1 }, -1, -1 )
Shared Bank Bags: ( 2, { 0 .. 1 }, { 0 .. (maxsize - 1) }, -1 )
Trade: ( 3, { 0 .. 8 }, -1, -1 )
(Trade Bags: 3031 - 3110 -- server values)
World: ( 4, { 0 .. 10 }, -1, -1 )
*/

View File

@ -0,0 +1,439 @@
/*
These fields must be in the order of how they are serialized!
*/
#define NEW_TRY
#ifdef NEW_TRY
//* 000 */ I(ItemClass) // Leave this one off on purpose
/* 001 */ S(Name)
/* 002 */ S(Lore)
//* 003 */ C("")//lorefile - Newly Added - Field is Null
/* 004 */ S(IDFile)
/* 005 */ I(ID)
/* 006 */ I(Weight)
/* 007 */ I(NoRent)
/* 008 */ I(NoDrop)
/* 009 */ I(Size)
/* 010 */ I(Slots)
/* 011 */ I(Price)
/* 012 */ I(Icon)
/* 013 */ C("0")//UNK013
/* 014 */ C("0")//UNK014
/* 015 */ I(BenefitFlag)
/* 016 */ I(Tradeskills)
/* 017 */ I(CR)
/* 018 */ I(DR)
/* 019 */ I(PR)
/* 020 */ I(MR)
/* 021 */ I(FR)
/* 022 */ C("0")//svcorruption - Newly Added
/* 023 */ I(AStr)
/* 024 */ I(ASta)
/* 025 */ I(AAgi)
/* 026 */ I(ADex)
/* 027 */ I(ACha)
/* 028 */ I(AInt)
/* 029 */ I(AWis)
/* 030 */ I(HP)
/* 031 */ I(Mana)
/* 032 */ I(Endur) //endur - Relocated
/* 033 */ I(AC)
/* 034 */ I(Classes)//classes - Relocated
/* 035 */ I(Races)//races - Relocated
/* 036 */ I(Deity)
/* 037 */ I(SkillModValue)
/* 038 */ C("0")//UNK038 - Default is 0
/* 039 */ I(SkillModType)
/* 040 */ I(BaneDmgRace)
/* 041 */ I(BaneDmgBody)//banedmgbody - Relocated
/* 042 */ I(BaneDmgRaceAmt)//banedmgraceamt - Relocated
/* 043 */ I(BaneDmgAmt)//banedmgamt - Relocated
/* 044 */ I(Magic)
/* 045 */ I(CastTime_)
/* 046 */ I(ReqLevel)
/* 047 */ I(RecLevel)//reclevel - Relocated
/* 048 */ I(RecSkill)//recskill - Relocated
/* 049 */ I(BardType)
/* 050 */ I(BardValue)
/* 051 */ I(Light)
/* 052 */ I(Delay)
/* 053 */ I(ElemDmgType)
/* 054 */ I(ElemDmgAmt)
/* 055 */ I(Range)
/* 056 */ I(Damage)
/* 057 */ I(Color)
/* 058 */ I(ItemType)
/* 059 */ I(Material)
/* 060 */ C("0")//UNK060 - Default is 0
/* 061 */ C("0")//UNK061 - Default is 0
/* 062 */ F(SellRate)
/* 063 */ I(CombatEffects)
/* 064 */ I(Shielding)
/* 065 */ I(StunResist)
/* 066 */ I(StrikeThrough)
/* 067 */ I(ExtraDmgSkill)
/* 068 */ I(ExtraDmgAmt)
/* 069 */ I(SpellShield)
/* 070 */ I(Avoidance)
/* 071 */ I(Accuracy)
/* 072 */ I(CharmFileID)
/* 073 */ I(FactionMod1)//Swapped these so Faction Amt comes after each Faction Mod
/* 074 */ I(FactionAmt1)//Swapped these so Faction Amt comes after each Faction Mod
/* 075 */ I(FactionMod2)//Swapped these so Faction Amt comes after each Faction Mod
/* 076 */ I(FactionAmt2)//Swapped these so Faction Amt comes after each Faction Mod
/* 077 */ I(FactionMod3)//Swapped these so Faction Amt comes after each Faction Mod
/* 078 */ I(FactionAmt3)//Swapped these so Faction Amt comes after each Faction Mod
/* 079 */ I(FactionMod4)//Swapped these so Faction Amt comes after each Faction Mod
/* 080 */ I(FactionAmt4)//Swapped these so Faction Amt comes after each Faction Mod
/* 081 */ S(CharmFile)
/* 082 */ I(AugType)
/* 083 */ I(AugRestrict)//augrestrict - Relocated
/* 084 */ I(AugDistiller)//augdistiller - Relocated
/* 085 */ I(AugSlotType[0])
/* 086 */ I(AugSlotVisible[0])//augslot1visible - Default 1
/* 087 */ C("0")//augslot1unk2 - Newly Added - Default 0
/* 088 */ I(AugSlotType[1])
/* 089 */ I(AugSlotVisible[1])
/* 090 */ C("0")//augslot2unk2 - Newly Added
/* 091 */ I(AugSlotType[2])
/* 092 */ I(AugSlotVisible[2])
/* 093 */ C("0")//augslot3unk2 - Newly Added
/* 094 */ I(AugSlotType[3])
/* 095 */ I(AugSlotVisible[3])
/* 096 */ C("0")//augslot4unk2 - Newly Added
/* 097 */ I(AugSlotType[4])
/* 098 */ I(AugSlotVisible[4])
/* 099 */ C("0")//augslot5unk2 - Newly Added
/* 100 */ I(PointType)//pointtype - Relocated
/* 101 */ I(LDoNTheme)
/* 102 */ I(LDoNPrice)
/* 103 */ C("70")//UNK098 - Newly Added - Default 70, but some are set to 0
/* 104 */ I(LDoNSold)
/* 105 */ I(BagType)
/* 106 */ I(BagSlots)
/* 107 */ I(BagSize)
/* 108 */ I(BagWR)
/* 109 */ I(Book)
/* 110 */ I(BookType)
/* 111 */ S(Filename)
/* 112 */ I(LoreGroup)
/* 113 */ I(ArtifactFlag)
/* 114 */ C("0")//I(PendingLoreFlag)?//UNK109 - Default 0, but a few are 1
/* 115 */ I(Favor)
/* 116 */ I(GuildFavor)//guildfavor - Relocated
/* 117 */ I(FVNoDrop)
/* 118 */ I(DotShielding)
/* 119 */ I(Attack)
/* 120 */ I(Regen)
/* 121 */ I(ManaRegen)
/* 122 */ I(EnduranceRegen)
/* 123 */ I(Haste)
/* 124 */ I(DamageShield)
/* 125 */ C("-1") //UNK120 - Default is -1
/* 126 */ C("0") //UNK121 - Default is 0
/* 127 */ I(Attuneable)
/* 128 */ I(NoPet)
/* 129 */ C("0") //UNK124 - Default 0, but a few are 1
/* 130 */ I(PotionBelt)
/* 131 */ C("0") //potionbeltslots - Default 0, but a few are 1
/* 132 */ I(StackSize)
/* 133 */ I(NoTransfer)
/* 134 */ I(Stackable)//UNK129 - Default is 0, but some are much higher
/* 135 */ I(QuestItemFlag)//questitemflag - Default is 0 (off), flag on = 1
/* 136 */ C("0")//UNK131 - Default is 0, but there is an item set to 1
/* 137 */ C("0")//UNK132 - Default is 0? 0000000000000000000?
/* 138 */ I(Click.Effect)
/* 139 */ I(Click.Type)
/* 140 */ I(Click.Level2)
/* 141 */ I(Click.Level)
/* 142 */ I(MaxCharges)//maxcharges - Relocated
/* 143 */ I(CastTime_)//casttime - Relocated - Note Duplicate Entries for CastTime_ and none for CastTime
/* 144 */ I(RecastDelay)//recastdelay - Relocated
/* 145 */ I(RecastType)//recasttype - Relocated
/* 146 */ C("0")//clickunk5 - Newly Added - Default is 0
/* 147 */ C("")//clickname - Newly Added - Default is Null
/* 148 */ C("-1")//clickunk7 - Newly Added - Default is -1, but some set to 0 and some much higher
/* 149 */ I(Proc.Effect)
/* 150 */ I(Proc.Type)
/* 151 */ I(Proc.Level2)
/* 152 */ I(Proc.Level)
/* 153 */ C("0")//procunk1 - Newly Added - Default is 0, but some set to -1 and 1
/* 154 */ C("0")//procunk2 - Newly Added - Default is 0
/* 155 */ C("0")//procunk3 - Newly Added - Default is 0
/* 156 */ C("0")//procunk4 - Newly Added - Default is 0
/* 157 */ I(ProcRate)//procrate - Relocated
/* 158 */ C("")//procname - Newly Added - Default is Null
/* 159 */ C("-1")//procunk7 - Newly Added - Default is -1, but some set to 0
/* 160 */ I(Worn.Effect)
/* 161 */ I(Worn.Type)
/* 162 */ I(Worn.Level2)
/* 163 */ I(Worn.Level)
/* 164 */ C("0")//wornunk1 - Newly Added - Default is 0
/* 165 */ C("0")//wornunk2 - Newly Added - Default is 0
/* 166 */ C("0")//wornunk3 - Newly Added - Default is 0
/* 167 */ C("0")//wornunk4 - Newly Added - Default is 0
/* 168 */ C("0")//wornunk5 - Newly Added - Default is 0
/* 169 */ C("")//wornname - Newly Added - Default is Null
/* 170 */ C("-1")//wornunk7 - Newly Added - Default is -1, but some set to 0
/* 171 */ I(Focus.Effect)
/* 172 */ I(Focus.Type)
/* 173 */ I(Focus.Level2)
/* 174 */ I(Focus.Level)
/* 175 */ C("0")//focusunk1 - Newly Added - Default is 0
/* 176 */ C("0")//focusunk2 - Newly Added - Default is 0
/* 177 */ C("0")//focusunk3 - Newly Added - Default is 0
/* 178 */ C("0")//focusunk4 - Newly Added - Default is 0
/* 179 */ C("0")//focusunk5 - Newly Added - Default is 0
/* 180 */ C("")//focusname - Newly Added - Default is Null
/* 181 */ C("-1")//focusunk7 - Newly Added - Default is -1, but some set to 0
/* 182 */ I(Scroll.Effect)
/* 183 */ I(Scroll.Type)
/* 184 */ I(Scroll.Level2)
/* 185 */ I(Scroll.Level)
/* 186 */ C("0")//scrollunk1 - Renumber this***
/* 187 */ C("0")//scrollunk2 - Newly Added - Default is 0
/* 188 */ C("0")//scrollunk3 - Newly Added - Default is 0
/* 189 */ C("0")//scrollunk4 - Newly Added - Default is 0
/* 190 */ C("0")//scrollunk5 - Newly Added - Default is 0
/* 191 */ C("")//scrollname - Newly Added - Default is Null
/* 192 */ C("-1")//scrollunk7 - Newly Added - Default is -1, but some set to 0
/* 193 */ C("0")//UNK193 - Default is 0
/* 194 */ C("0")//purity - Newly Added - Default is 0, but some go up to 75
/* 195 */ C("0")//dsmitigation - Newly Added - Default is 0, but some are up to 2
/* 196 */ C("0")//heroic_str - Newly Added - Default is 0
/* 197 */ C("0")//heroic_int - Newly Added - Default is 0
/* 198 */ C("0")//heroic_wis - Newly Added - Default is 0
/* 199 */ C("0")//heroic_agi - Newly Added - Default is 0
/* 200 */ C("0")//heroic_dex - Newly Added - Default is 0
/* 201 */ C("0")//heroic_sta - Newly Added - Default is 0
/* 202 */ C("0")//heroic_cha - Newly Added - Default is 0
/* 203 */ C("0")//HeroicSvPoison - Newly Added - Default is 0
/* 204 */ C("0")//HeroicSvMagic - Newly Added - Default is 0
/* 205 */ C("0")//HeroicSvFire - Newly Added - Default is 0
/* 206 */ C("0")//HeroicSvDisease - Newly Added - Default is 0
/* 207 */ C("0")//HeroicSvCold - Newly Added - Default is 0
/* 208 */ C("0")//HeroicSvCorruption - Newly Added - Default is 0
/* 209 */ C("0")//healamt - Newly Added - Default is 0, but some are up to 9
/* 210 */ C("0")//spelldmg - Newly Added - Default is 0, but some are up to 9
/* 211 */ C("0")//clairvoyance - Newly Added - Default is 0, but some are up to 10
/* 212 */ C("0")//backstabdmg - Newly Added - Default is 0, but some are up to 65
//* 213 */ C("0")//evolvinglevel - Newly Added - Default is 0, but some are up to 7
//* 214 */ C("0")//MaxPower - Newly Added
//* 215 */ C("0")//Power - Newly Added
//This doesn't appear to be used /* 102 */ S(verified)//verified
//This doesn't appear to be used /* 102 */ S(serialized)//created
//Unsure where this goes right now (or if it is even used) /* 108 */ I(SummonedFlag)
#else
/* 000 */ //I(ItemClass) Leave this one off on purpose
/* 001 */ S(Name)
/* 002 */ S(Lore)
/* 003 */ C("") //LoreFile?
/* 003 */ S(IDFile)
/* 004 */ I(ID)
/* 005 */ I(Weight)
/* 006 */ I(NoRent)
/* 007 */ I(NoDrop)
/* 008 */ I(Size)
/* 009 */ I(Slots)
/* 010 */ I(Price)
/* 011 */ I(Icon)
/* 013 */ C("0")
/* 014 */ C("0")
/* 014 */ I(BenefitFlag)
/* 015 */ I(Tradeskills)
/* 016 */ I(CR)
/* 017 */ I(DR)
/* 018 */ I(PR)
/* 019 */ I(MR)
/* 020 */ I(FR)
C("0") //svcorruption
/* 021 */ I(AStr)
/* 022 */ I(ASta)
/* 023 */ I(AAgi)
/* 024 */ I(ADex)
/* 025 */ I(ACha)
/* 026 */ I(AInt)
/* 027 */ I(AWis)
/* 028 */ I(HP)
/* 029 */ I(Mana)
I(Endur)
/* 030 */ I(AC)
/* 052 */ I(Classes)
/* 053 */ I(Races)
/* 031 */ I(Deity)
/* 032 */ I(SkillModValue)
/* 033 */ C("0")
/* 034 */ I(SkillModType)
/* 035 */ I(BaneDmgRace)
/* 037 */ I(BaneDmgBody)
/* 036 */ I(BaneDmgRaceAmt)
/* 036 */ I(BaneDmgAmt)
/* 038 */ I(Magic)
/* 039 */ I(CastTime_)
/* 040 */ I(ReqLevel)
/* 045 */ I(RecLevel)
/* 046 */ I(RecSkill)
/* 041 */ I(BardType)
/* 042 */ I(BardValue)
/* 043 */ I(Light)
/* 044 */ I(Delay)
/* 047 */ I(ElemDmgType)
/* 048 */ I(ElemDmgAmt)
/* 049 */ I(Range)
/* 050 */ I(Damage)
/* 051 */ I(Color)
/* 056 */ I(ItemType)
/* 057 */ I(Material)
/* 060 */ C("0")
/* 061 */ C("0")
/* 058 */ F(SellRate)
/* 063 */ I(CombatEffects)
/* 064 */ I(Shielding)
/* 065 */ I(StunResist)
/* 059 */ //C("0")
/* 061 */ //C("0")
/* 066 */ I(StrikeThrough)
/* 067 */ I(ExtraDmgSkill)
/* 068 */ I(ExtraDmgAmt)
/* 069 */ I(SpellShield)
/* 070 */ I(Avoidance)
/* 071 */ I(Accuracy)
/* 072 */ I(CharmFileID)
/* 073 */ I(FactionMod1)
/* 077 */ I(FactionAmt1)
/* 074 */ I(FactionMod2)
/* 078 */ I(FactionAmt2)
/* 075 */ I(FactionMod3)
/* 079 */ I(FactionAmt3)
/* 076 */ I(FactionMod4)
/* 080 */ I(FactionAmt4)
/* 081 */ S(CharmFile)
/* 082 */ I(AugType)
/* 082 */ I(AugRestrict)
/* 082 */ I(AugDistiller)
/* 083 */ I(AugSlotType[0])
/* 084 */ I(AugSlotVisible[0])
/* 084 */ I(AugSlotUnk2[0])
/* 085 */ I(AugSlotType[1])
/* 086 */ I(AugSlotVisible[1])
/* 086 */ I(AugSlotUnk2[1])
/* 087 */ I(AugSlotType[2])
/* 088 */ I(AugSlotVisible[2])
/* 088 */ I(AugSlotUnk2[2])
/* 089 */ I(AugSlotType[3])
/* 090 */ I(AugSlotVisible[3])
/* 090 */ I(AugSlotUnk2[3])
/* 091 */ I(AugSlotType[4])
/* 092 */ I(AugSlotVisible[4])
/* 092 */ I(AugSlotUnk2[4])
/* 093 */ I(PointType)
/* 093 */ I(LDoNTheme)
/* 094 */ I(LDoNPrice)
/* 094 */ C("0")
/* 095 */ I(LDoNSold)
/* 096 */ I(BagType)
/* 097 */ I(BagSlots)
/* 098 */ I(BagSize)
/* 099 */ I(BagWR)
/* 100 */ I(Book)
/* 101 */ I(BookType)
/* 102 */ S(Filename)
/* 105 */ I(LoreGroup)
/* 106 */ //I(PendingLoreFlag)
/* 107 */ I(ArtifactFlag)
/* 094 */ C("0")
/* 108 */ //I(SummonedFlag)
/* 109 */ I(Favor)
/* 121 */ I(GuildFavor)
/* 110 */ I(FVNoDrop)
/* 112 */ I(DotShielding)
/* 113 */ I(Attack)
/* 114 */ I(Regen)
/* 115 */ I(ManaRegen)
/* 116 */ I(EnduranceRegen)
/* 117 */ I(Haste)
/* 118 */ I(DamageShield)
/* 120 */ C("0")
/* 121 */ C("0")
/* 125 */ I(Attuneable)
/* 126 */ I(NoPet)
/* 124 */ C("0")
/* 129 */ I(PotionBelt)
/* 130 */ I(PotionBeltSlots)
/* 131 */ I(StackSize)
/* 132 */ I(NoTransfer)
/* 129 */ C("0")
/* 132 */ I(QuestItemFlag)
/* 131 */ C("0")
/* 132 */ C("00000000000000000000000000000000000000")
/* 134 */ I(Click.Effect)
/* 135 */ I(Click.Type)
/* 136 */ I(Click.Level2)
/* 137 */ I(Click.Level)
/* 055 */ I(MaxCharges)
/* 060 */ I(CastTime)
/* 119 */ I(RecastDelay)
/* 120 */ I(RecastType)
/* 138 */ C("0") //clickunk5 (prolly ProcRate)
/* 138 */ C("") //clickunk6
/* 138 */ C("-1") //clickunk7
/* 139 */ I(Proc.Effect)
/* 140 */ I(Proc.Type)
/* 141 */ I(Proc.Level2)
/* 142 */ I(Proc.Level)
/* 143 */ C("0") //procunk1 (prolly MaxCharges)
/* 143 */ C("0") //procunk2 (prolly CastTime)
/* 143 */ C("0") //procunk3 (prolly RecastDelay)
/* 143 */ C("0") //procunk4 (prolly RecastType)
/* 062 */ I(ProcRate)
/* 143 */ C("") //procunk6
/* 143 */ C("-1") //procunk7
/* 144 */ I(Worn.Effect)
/* 145 */ I(Worn.Type)
/* 146 */ I(Worn.Level2)
/* 147 */ I(Worn.Level)
/* 143 */ C("0") //wornunk1 (prolly MaxCharges)
/* 143 */ C("0") //wornunk2 (prolly CastTime)
/* 143 */ C("0") //wornunk3 (prolly RecastDelay)
/* 143 */ C("0") //wornunk4 (prolly RecastType)
/* 143 */ C("0") //wornunk5 (prolly ProcRate)
/* 143 */ C("") //wornunk6
/* 143 */ C("-1") //wornunk7
/* 149 */ I(Focus.Effect)
/* 150 */ I(Focus.Type)
/* 151 */ I(Focus.Level2)
/* 152 */ I(Focus.Level)
/* 143 */ C("0") //focusunk1 (prolly MaxCharges)
/* 143 */ C("0") //focusunk2 (prolly CastTime)
/* 143 */ C("0") //focusunk3 (prolly RecastDelay)
/* 143 */ C("0") //focusunk4 (prolly RecastType)
/* 143 */ C("0") //focusunk5 (prolly ProcRate)
/* 143 */ C("") //focusunk6
/* 143 */ C("-1") //focusunk7
/* 154 */ I(Scroll.Effect)
/* 155 */ I(Scroll.Type)
/* 156 */ I(Scroll.Level2)
/* 157 */ I(Scroll.Level)
/* 143 */ C("0") //scrollunk1 (prolly MaxCharges)
/* 143 */ C("0") //scrollunk2 (prolly CastTime)
/* 143 */ C("0") //scrollunk3 (prolly RecastDelay)
/* 143 */ C("0") //scrollunk4 (prolly RecastType)
/* 143 */ C("0") //scrollunk5 (prolly ProcRate)
/* 143 */ C("") //scrollunk6
/* 143 */ C("-1") //scrollunk7
/* 193 */ C("0") //Power Source Capacity
/* 194 */ C("0") //purity
#endif
#undef I
#undef C
#undef S
#undef F

173
common/patches/rof2_ops.h Normal file
View File

@ -0,0 +1,173 @@
// out-going packets that require an ENCODE translation:
// Begin RoF2 Encodes
// incoming packets that require a DECODE translation:
// Begin RoF2 Decodes
// End RoF2 Encodes/Decodes
// These require Encodes/Decodes for RoF, so they do for RoF2 as well
// Begin RoF Encodes
E(OP_Action)
E(OP_AdventureMerchantSell)
E(OP_AltCurrency)
E(OP_AltCurrencySell)
E(OP_Animation)
E(OP_ApplyPoison)
E(OP_AugmentInfo)
E(OP_Barter)
E(OP_BazaarSearch)
E(OP_BeginCast)
E(OP_BlockedBuffs)
E(OP_Buff)
E(OP_BuffCreate)
E(OP_CancelTrade)
E(OP_CastSpell)
E(OP_ChannelMessage)
E(OP_CharInventory)
E(OP_ClickObjectAction)
E(OP_ClientUpdate)
E(OP_Consider)
E(OP_Damage)
E(OP_DeleteCharge)
E(OP_DeleteItem)
E(OP_DeleteSpawn)
E(OP_DisciplineUpdate)
E(OP_DzCompass)
E(OP_DzExpeditionEndsWarning)
E(OP_DzExpeditionInfo)
E(OP_DzExpeditionList)
E(OP_DzJoinExpeditionConfirm)
E(OP_DzLeaderStatus)
E(OP_DzMemberList)
E(OP_ExpansionInfo)
E(OP_GMLastName)
E(OP_GMTrainSkillConfirm)
E(OP_GroundSpawn)
E(OP_GroupCancelInvite)
E(OP_GroupFollow)
E(OP_GroupFollow2)
E(OP_GroupInvite)
E(OP_GroupUpdate)
E(OP_GuildMemberList)
E(OP_GuildMemberUpdate)
E(OP_GuildsList)
E(OP_HPUpdate)
E(OP_Illusion)
E(OP_InspectBuffs)
E(OP_InspectRequest)
E(OP_InterruptCast)
E(OP_ItemLinkResponse)
E(OP_ItemPacket)
E(OP_ItemVerifyReply)
E(OP_LeadershipExpUpdate)
E(OP_LogServer)
E(OP_LootItem)
E(OP_ManaChange)
E(OP_MercenaryDataResponse)
E(OP_MercenaryDataUpdate)
E(OP_MoveItem)
E(OP_NewSpawn)
E(OP_NewZone)
E(OP_OnLevelMessage)
//E(OP_OpenNewTasksWindow)
E(OP_PetBuffWindow)
E(OP_PlayerProfile)
E(OP_RaidJoin)
E(OP_RaidUpdate)
E(OP_ReadBook)
E(OP_RecipeAutoCombine)
E(OP_RemoveBlockedBuffs)
E(OP_RequestClientZoneChange)
E(OP_RespondAA)
E(OP_RezzRequest)
E(OP_SendAATable)
E(OP_SendCharInfo)
E(OP_SendMembership)
E(OP_SendZonepoints)
E(OP_SetGuildRank)
E(OP_ShopPlayerBuy)
E(OP_ShopPlayerSell)
E(OP_ShopRequest)
E(OP_SkillUpdate)
E(OP_SomeItemPacketMaybe)
E(OP_SpawnAppearance)
E(OP_SpawnDoor)
E(OP_Stun)
E(OP_TargetBuffs)
E(OP_TaskDescription)
E(OP_TaskHistoryReply)
E(OP_Track)
E(OP_Trader)
E(OP_TraderBuy)
E(OP_TributeInfo)
E(OP_TributeItem)
E(OP_VetRewardsAvaliable)
E(OP_WearChange)
E(OP_WhoAllResponse)
E(OP_ZoneChange)
E(OP_ZoneEntry)
E(OP_ZonePlayerToBind)
E(OP_ZoneServerInfo)
E(OP_ZoneSpawns)
// Begin RoF Decodes
D(OP_AdventureMerchantSell)
D(OP_AltCurrencySell)
D(OP_AltCurrencySellSelection)
D(OP_ApplyPoison)
D(OP_AugmentInfo)
D(OP_AugmentItem)
D(OP_BazaarSearch)
D(OP_BlockedBuffs)
D(OP_Buff)
D(OP_BuffRemoveRequest)
D(OP_CastSpell)
D(OP_ChannelMessage)
D(OP_CharacterCreate)
D(OP_ClientUpdate)
D(OP_Consider)
D(OP_ConsiderCorpse)
D(OP_Consume)
D(OP_Damage)
D(OP_DeleteItem)
D(OP_EnvDamage)
D(OP_FaceChange)
D(OP_FindPersonRequest)
D(OP_GMLastName)
D(OP_GroupCancelInvite)
D(OP_GroupDisband)
D(OP_GroupFollow)
D(OP_GroupFollow2)
D(OP_GroupInvite)
D(OP_GroupInvite2)
D(OP_GuildDemote)
D(OP_GuildRemove)
D(OP_GuildStatus)
D(OP_InspectRequest)
D(OP_ItemLinkClick)
D(OP_ItemVerifyRequest)
D(OP_LoadSpellSet)
D(OP_LootItem)
D(OP_MoveItem)
D(OP_PetCommands)
D(OP_RaidInvite)
D(OP_ReadBook)
D(OP_RecipeAutoCombine)
D(OP_RemoveBlockedBuffs)
D(OP_RezzAnswer)
D(OP_Save)
D(OP_SetServerFilter)
D(OP_ShopPlayerBuy)
D(OP_ShopPlayerSell)
D(OP_ShopRequest)
D(OP_Trader)
D(OP_TraderBuy)
D(OP_TradeSkillCombine)
D(OP_TributeItem)
D(OP_WhoAllRequest)
D(OP_ZoneChange)
D(OP_ZoneEntry)
// End RoF Encodes/Decodes
#undef E
#undef D

File diff suppressed because it is too large Load Diff

View File

@ -4169,7 +4169,8 @@ struct Arrow_Struct {
/*070*/ uint8 unknown070;
/*071*/ uint8 item_type;
/*072*/ uint8 skill;
/*073*/ char model_name[43];
/*073*/ uint8 unknown073[16];
/*089*/ char model_name[27];
/*116*/
};

View File

@ -3664,6 +3664,12 @@ namespace Underfoot
ss.write((const char*)&null_term, sizeof(uint8));
ornaIcon = aug_weap->Icon;
}
else if (inst->GetOrnamentationIDFile() && inst->GetOrnamentationIcon()) {
char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile());
ss.write(tmp, strlen(tmp));
ss.write((const char*)&null_term, sizeof(uint8));
ornaIcon = inst->GetOrnamentationIcon();
}
else {
ss.write((const char*)&null_term, sizeof(uint8)); //no idfile
}

84
common/random.h Normal file
View File

@ -0,0 +1,84 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __random_h__
#define __random_h__
#include <random>
#include <utility>
/* This uses mt19937 seeded with the std::random_device
* The idea is to have this be included as a member of another class
* so mocking out for testing is easier
* If you need to reseed random.Reseed()
* Eventually this should be derived from an abstract base class
*/
namespace EQEmu {
class Random {
public:
// AKA old MakeRandomInt
const int Int(int low, int high)
{
if (low > high)
std::swap(low, high);
return std::uniform_int_distribution<int>(low, high)(m_gen); // [low, high]
}
// AKA old MakeRandomFloat
const double Real(double low, double high)
{
if (low > high)
std::swap(low, high);
return std::uniform_real_distribution<double>(low, high)(m_gen); // [low, high)
}
// example Roll(50) would have a 50% success rate
// Roll(100) 100%, etc
// valid values 0-100 (well, higher works too but ...)
const bool Roll(const int required)
{
return Int(0, 99) < required;
}
// valid values 0.0 - 1.0
const bool Roll(const double required)
{
return Real(0.0, 1.0) <= required;
}
void Reseed()
{
// We could do the seed_seq thing here too if we need better seeding
// but that is mostly overkill for us, so just seed once
std::random_device rd;
m_gen.seed(rd());
}
Random()
{
Reseed();
}
private:
std::mt19937 m_gen;
};
}
#endif /* !__random_h__ */

View File

@ -419,6 +419,7 @@ RULE_INT ( Combat, ArcheryBonusChance, 50)
RULE_INT ( Combat, BerserkerFrenzyStart, 35)
RULE_INT ( Combat, BerserkerFrenzyEnd, 45)
RULE_BOOL ( Combat, OneProcPerWeapon, true) //If enabled, One proc per weapon per round
RULE_BOOL ( Combat, ProjectileDmgOnImpact, true) //If enabled, projectiles (ie arrows) will hit on impact, instead of instantly.
RULE_CATEGORY_END()
RULE_CATEGORY( NPC )
@ -586,6 +587,8 @@ RULE_CATEGORY( Inventory )
RULE_BOOL ( Inventory, EnforceAugmentRestriction, true) // Forces augment slot restrictions
RULE_BOOL ( Inventory, EnforceAugmentUsability, true) // Forces augmented item usability
RULE_BOOL ( Inventory, EnforceAugmentWear, true) // Forces augment wear slot validation
RULE_BOOL ( Inventory, DeleteTransformationMold, true) //False if you want mold to last forever
RULE_BOOL ( Inventory, AllowAnyWeaponTransformation, false) //Weapons can use any weapon transformation
RULE_CATEGORY_END()
RULE_CATEGORY( Client )

View File

@ -199,14 +199,14 @@ bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const ItemInst* inst, i
// Update/Insert item
std::string query = StringFormat("REPLACE INTO inventory "
"(charid, slotid, itemid, charges, instnodrop, custom_data, color, "
"augslot1, augslot2, augslot3, augslot4, augslot5) "
"augslot1, augslot2, augslot3, augslot4, augslot5, ornamenticon, ornamentidfile) "
"VALUES( %lu, %lu, %lu, %lu, %lu, '%s', %lu, "
"%lu, %lu, %lu, %lu, %lu)",
"%lu, %lu, %lu, %lu, %lu, %lu, %lu)",
(unsigned long)char_id, (unsigned long)slot_id, (unsigned long)inst->GetItem()->ID,
(unsigned long)charges, (unsigned long)(inst->IsInstNoDrop()? 1: 0),
inst->GetCustomDataString().c_str(), (unsigned long)inst->GetColor(),
(unsigned long)augslot[0], (unsigned long)augslot[1], (unsigned long)augslot[2],
(unsigned long)augslot[3],(unsigned long)augslot[4]);
(unsigned long)augslot[3],(unsigned long)augslot[4], (unsigned long)inst->GetOrnamentationIcon(), (unsigned long)inst->GetOrnamentationIDFile());
auto results = QueryDatabase(query);
// Save bag contents, if slot supports bag contents
@ -488,7 +488,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory* inv, bool is_charid) {
bool SharedDatabase::GetInventory(uint32 char_id, Inventory* inv) {
// Retrieve character inventory
std::string query = StringFormat("SELECT slotid, itemid, charges, color, augslot1, "
"augslot2, augslot3, augslot4, augslot5, instnodrop, custom_data "
"augslot2, augslot3, augslot4, augslot5, instnodrop, custom_data, ornamenticon, ornamentidfile "
"FROM inventory WHERE charid = %i ORDER BY slotid", char_id);
auto results = QueryDatabase(query);
if (!results.Success()) {
@ -513,6 +513,9 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory* inv) {
bool instnodrop = (row[9] && (uint16)atoi(row[9]))? true: false;
uint32 ornament_icon = (uint32)atoul(row[11]);
uint32 ornament_idfile = (uint32)atoul(row[12]);
const Item_Struct* item = GetItem(item_id);
if (!item) {
@ -549,6 +552,11 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory* inv) {
value.push_back(v);
}
}
if (ornament_icon > 0)
inst->SetOrnamentIcon(ornament_icon);
if (ornament_idfile > 0)
inst->SetOrnamentationIDFile(ornament_idfile);
if (instnodrop || (((slot_id >= EmuConstants::EQUIPMENT_BEGIN && slot_id <= EmuConstants::EQUIPMENT_END) || slot_id == MainPowerSource) && inst->GetItem()->Attuneable))
inst->SetInstNoDrop(true);
@ -591,7 +599,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory* inv) {
bool SharedDatabase::GetInventory(uint32 account_id, char* name, Inventory* inv) {
// Retrieve character inventory
std::string query = StringFormat("SELECT slotid, itemid, charges, color, augslot1, "
"augslot2, augslot3, augslot4, augslot5, instnodrop, custom_data "
"augslot2, augslot3, augslot4, augslot5, instnodrop, custom_data, ornamenticon, ornamentidfile "
"FROM inventory INNER JOIN character_data ch "
"ON ch.id = charid WHERE ch.name = '%s' AND ch.account_id = %i ORDER BY slotid",
name, account_id);
@ -617,6 +625,9 @@ bool SharedDatabase::GetInventory(uint32 account_id, char* name, Inventory* inv)
aug[4] = (uint32)atoi(row[8]);
bool instnodrop = (row[9] && (uint16)atoi(row[9])) ? true : false;
uint32 ornament_icon = (uint32)atoul(row[11]);
uint32 ornament_idfile = (uint32)atoul(row[12]);
const Item_Struct* item = GetItem(item_id);
int16 put_slot_id = INVALID_INDEX;
if(!item)
@ -651,6 +662,12 @@ bool SharedDatabase::GetInventory(uint32 account_id, char* name, Inventory* inv)
}
}
if (ornament_icon > 0)
inst->SetOrnamentIcon(ornament_icon);
if (ornament_idfile > 0)
inst->SetOrnamentationIDFile(ornament_idfile);
if (color > 0)
inst->SetColor(color);

View File

@ -30,7 +30,7 @@
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9057
#define CURRENT_BINARY_DATABASE_VERSION 9059
#define COMPILE_DATE __DATE__
#define COMPILE_TIME __TIME__
#ifndef WIN32

View File

@ -389,7 +389,7 @@ void Client::GenerateKey()
'6', '7', '8', '9'
};
key.append((const char*)&key_selection[MakeRandomInt(0, 35)], 1);
key.append((const char*)&key_selection[random.Int(0, 35)], 1);
count++;
}
}

View File

@ -22,6 +22,7 @@
#include "../common/opcodemgr.h"
#include "../common/eq_stream_type.h"
#include "../common/eq_stream_factory.h"
#include "../common/random.h"
#ifndef WIN32
#include "eq_crypto_api.h"
#endif
@ -129,6 +130,8 @@ public:
* Gets the connection for this client.
*/
EQStream *GetConnection() { return connection; }
EQEmu::Random random;
private:
EQStream *connection;
ClientVersion version;

View File

@ -21,7 +21,7 @@ SET(lb_sources
)
SET(lb_headers
)
ADD_LIBRARY(luabind ${lb_sources} ${lb_headers})
@ -29,6 +29,11 @@ ADD_LIBRARY(luabind ${lb_sources} ${lb_headers})
IF(UNIX)
ADD_DEFINITIONS(-fPIC)
set_source_files_properties(${lb_sources} PROPERTY COMPILE_FLAGS -Wno-deprecated-declarations)
ENDIF(UNIX)
IF(MSVC)
set_source_files_properties(${lb_sources} PROPERTY COMPILE_FLAGS " /W0 " )
ENDIF(MSVC)
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)

View File

@ -94,6 +94,7 @@ OP_ClearBlockedBuffs=0x5d3c
OP_WorldObjectsSent=0x7fa8
OP_SendExpZonein=0x25ab
OP_SendAATable=0x7791
OP_ShroudClearAA=0x422e
OP_RespondAA=0x379d
OP_UpdateAA=0x504f
OP_SendAAStats=0x3d1c
@ -367,7 +368,7 @@ OP_DzLeaderStatus=0x4021
OP_DzExpeditionEndsWarning=0x32eb
OP_DzMemberList=0x348f
OP_DzCompass=0x0e01 # Was 0x4f09
OP_DzChooseZone=0x0000 # Maybe 0x29d6
OP_DzChooseZone=0x6e5e # Maybe 0x29d6
# New Opcodes
OP_SpawnPositionUpdate=0x0000 # Actually OP_MobUpdate ?

View File

@ -0,0 +1,660 @@
# ShowEQ Import Notes:
# ZERO THE FILE first
# perl -pi -e 's/0x[0-9a-fA-F]{4}/0x0000/g' opcodes.conf
# Unknown Mapping:
# OP_Action2 -> OP_Damage
# OP_EnvDamage -> OP_Damage ---> might have been a one time mistake
# Name Differences:
# OP_CancelInvite -> OP_GroupCancelInvite
# OP_GMFind -> OP_FindPersonRequest
# OP_CommonMessage -> OP_ChannelMessage
OP_Unknown=0x0000
OP_ExploreUnknown=0x0000 # used for unknown explorer
# world packets
# Required to reach Char Select:
OP_SendLoginInfo=0x7a09
OP_ApproveWorld=0x7499
OP_LogServer=0x7ceb
OP_SendCharInfo=0x00d2
OP_ExpansionInfo=0x590d
OP_GuildsList=0x0000
OP_EnterWorld=0x578f
OP_PostEnterWorld=0x6259
OP_World_Client_CRC1=0x12cc
OP_World_Client_CRC2=0x0f13
OP_SendSpellChecksum=0x0000
OP_SendSkillCapsChecksum=0x0000
# Character Select Related:
OP_SendMaxCharacters=0x5475
OP_SendMembership=0x7acc
OP_SendMembershipDetails=0x057b
OP_CharacterCreateRequest=0x6773
OP_CharacterCreate=0x6bbf
OP_DeleteCharacter=0x1808
OP_RandomNameGenerator=0x5954
OP_ApproveName=0x56a2
OP_MOTD=0x0c22
OP_SetChatServer=0x1bc5
OP_SetChatServer2=0x7eec
OP_ZoneServerInfo=0x4c44
OP_WorldComplete=0x4493
OP_WorldUnknown001=0x2301
OP_FloatListThing=0x46c6
# Reasons for Disconnect:
OP_ZoneUnavail=0x4cb4
OP_WorldClientReady=0x23c1
OP_CharacterStillInZone=0x0000
OP_WorldChecksumFailure=0x0000
OP_WorldLoginFailed=0x0000
OP_WorldLogout=0x0000
OP_WorldLevelTooHigh=0x0000
OP_CharInacessable=0x0000
OP_UserCompInfo=0x0000
OP_SendExeChecksum=0x0000
OP_SendBaseDataChecksum=0x0000
# Zone in opcodes
OP_AckPacket=0x471d
OP_ZoneEntry=0x5089
OP_ReqNewZone=0x7887
OP_NewZone=0x1795
OP_ZoneSpawns=0x5237
OP_PlayerProfile=0x6506
OP_TimeOfDay=0x5070
OP_LevelUpdate=0x1eec
OP_Stamina=0x2a79
OP_RequestClientZoneChange=0x3fcf
OP_ZoneChange=0x2d18
OP_LockoutTimerInfo=0x0000
OP_ZoneServerReady=0x0000
OP_ZoneInUnknown=0x0000
OP_LogoutReply=0x0000
OP_PreLogoutReply=0x0000
# Required to fully log in
OP_SpawnAppearance=0x0971
OP_ChangeSize=0x4707
OP_TributeUpdate=0x5961
OP_TributeTimer=0x073d
OP_SendTributes=0x729b
OP_SendGuildTributes=0x1877
OP_TributeInfo=0x4254
OP_Weather=0x661e
OP_ReqClientSpawn=0x35fa
OP_SpawnDoor=0x7291
OP_GroundSpawn=0x6fca
OP_SendZonepoints=0x69a4
OP_BlockedBuffs=0x3033
OP_RemoveBlockedBuffs=0x0de7
OP_ClearBlockedBuffs=0x34cb
OP_WorldObjectsSent=0x5ae2
OP_SendExpZonein=0x5f8e
OP_SendAATable=0x66b5
OP_RespondAA=0x7a27
OP_UpdateAA=0x66f0
OP_SendAAStats=0x43c8
OP_AAExpUpdate=0x7d14
OP_ExpUpdate=0x20ed
OP_HPUpdate=0x2828
OP_ManaChange=0x5467
OP_TGB=0x0876
OP_SpecialMesg=0x083
OP_GuildMemberList=0x12a6
OP_GuildMOTD=0x3e13
OP_CharInventory=0x5ca6
OP_WearChange=0x7994
OP_ClientUpdate=0x7dfc
OP_ClientReady=0x345d
OP_SetServerFilter=0x444d
# Guild Opcodes - Disabled until crashes are resolved in RoF
OP_GetGuildMOTD=0x36e0
OP_GetGuildMOTDReply=0x4f1f
OP_GuildMemberUpdate=0x69b9
OP_GuildInvite=0x7099
OP_GuildRemove=0x1444
OP_GuildPeace=0x67e3
OP_SetGuildMOTD=0x0b0b
OP_GuildList=0x6279
OP_GuildWar=0x1ffb
OP_GuildLeader=0x7e09
OP_GuildDelete=0x3708
OP_GuildInviteAccept=0x7053
OP_GuildDemote=0x2d4e
OP_GuildPromote=0x0000
OP_GuildPublicNote=0x5053
OP_GuildManageBanker=0x748f
OP_GuildBank=0x5134
OP_SetGuildRank=0x0b9c
OP_GuildUpdateURLAndChannel=0x2958
OP_GuildStatus=0x7326
OP_GuildCreate=0x76d9
OP_GuildMemberLevelUpdate=0x0000 # Unused?
OP_ZoneGuildList=0x0000 # Unused?
OP_GetGuildsList=0x0000 # Unused?
OP_LFGuild=0x0000
OP_GuildManageRemove=0x0000
OP_GuildManageAdd=0x0000
OP_GuildManageStatus=0x0000
# GM/Guide Opcodes
OP_GMServers=0x08c1
OP_GMBecomeNPC=0x3ae1
OP_GMZoneRequest=0x62ac
OP_GMZoneRequest2=0x7e1a
OP_GMGoto=0x7d8e
OP_GMSearchCorpse=0x357c
OP_GMHideMe=0x79c5
OP_GMDelCorpse=0x607e
OP_GMApproval=0x6db5
OP_GMToggle=0x2097
OP_GMSummon=0x486f
OP_GMEmoteZone=0x1cfd
OP_GMEmoteWorld=0x458e
OP_GMFind=0x4a8f
OP_GMKick=0x26a7
OP_GMKill=0x51d3
OP_GMNameChange=0x035f
OP_GMLastName=0x46ce
# Misc Opcodes
OP_InspectRequest=0x57bc
OP_InspectAnswer=0x71ac
OP_InspectMessageUpdate=0x4d25
OP_BeginCast=0x318f
OP_ColoredText=0x43af
OP_ConsentResponse=0x384a
OP_MemorizeSpell=0x217c
OP_SwapSpell=0x0efa
OP_CastSpell=0x1287
OP_Consider=0x742b
OP_FormattedMessage=0x1024
OP_SimpleMessage=0x213f
OP_Buff=0x659c
OP_Illusion=0x312a
OP_MoneyOnCorpse=0x5f44
OP_RandomReply=0x106b
OP_DenyResponse=0x2382
OP_SkillUpdate=0x04c
OP_GMTrainSkillConfirm=0x4b64
OP_RandomReq=0x7b10
OP_Death=0x6517
OP_GMTraining=0x1966
OP_GMEndTraining=0x4d6b
OP_GMTrainSkill=0x2a85
OP_Animation=0x7177
OP_Begging=0x6703
OP_Consent=0x1fd1
OP_ConsentDeny=0x7a45
OP_AutoFire=0x241e
OP_PetCommands=0x0159
OP_DeleteSpell=0x52e5
OP_Surname=0x0423
OP_ClearSurname=0x3fb0
OP_FaceChange=0x5578
OP_SenseHeading=0x260a
OP_Action=0x744c
OP_ConsiderCorpse=0x5204
OP_HideCorpse=0x49e1
OP_CorpseDrag=0x0904
OP_CorpseDrop=0x7037
OP_Bug=0x73f4
OP_Feedback=0x5602
OP_Report=0x1414
OP_Damage=0x6f15
OP_ChannelMessage=0x2b2d
OP_Assist=0x4478
OP_AssistGroup=0x27f8
OP_MoveCoin=0x0bcf
OP_ZonePlayerToBind=0x0ecb
OP_KeyRing=0x6857
OP_WhoAllRequest=0x674b
OP_WhoAllResponse=0x51b8
OP_FriendsWho=0x3956
OP_ConfirmDelete=0x43a3
OP_Logout=0x4ac6
OP_Rewind=0x1745
OP_TargetCommand=0x58e2
OP_Hide=0x67fe
OP_Jump=0x31f4
OP_Camp=0x28ec
OP_Emote=0x373b
OP_SetRunMode=0x009f
OP_BankerChange=0x791e
OP_TargetMouse=0x075d
OP_MobHealth=0x37b1
OP_InitialMobHealth=0x0000 # Unused?
OP_TargetHoTT=0x0272
OP_XTargetResponse=0x672f
OP_XTargetRequest=0x45be
OP_XTargetAutoAddHaters=0x792c
OP_TargetBuffs=0x4f4b
OP_BuffCreate=0x3377
OP_BuffRemoveRequest=0x64f2
OP_DeleteSpawn=0x7280
OP_AutoAttack=0x109d
OP_AutoAttack2=0x3526
OP_Consume=0x4b70
OP_MoveItem=0x32ee
OP_DeleteItem=0x18ad
OP_DeleteCharge=0x01b8
OP_ItemPacket=0x368e
OP_ItemLinkResponse=0x70c0
OP_ItemLinkClick=0x4cef
OP_ItemPreview=0x6b5c
OP_NewSpawn=0x6097
OP_Track=0x17e5
OP_TrackTarget=0x0029
OP_TrackUnknown=0x4577
OP_ClickDoor=0x3a8f
OP_MoveDoor=0x08e8
OP_RemoveAllDoors=0x700c
OP_EnvDamage=0x51fd
OP_BoardBoat=0x4211
OP_Forage=0x5306
OP_LeaveBoat=0x7617
OP_ControlBoat=0x0ae7
OP_SafeFallSuccess=0x2219
OP_RezzComplete=0x760d
OP_RezzRequest=0x3c21
OP_RezzAnswer=0x701c
OP_Shielding=0x48c1
OP_RequestDuel=0x3af1
OP_MobRename=0x2c57
OP_AugmentItem=0x661b
OP_WeaponEquip1=0x34a7
OP_WeaponEquip2=0x559a
OP_WeaponUnequip2=0x2d25
OP_ApplyPoison=0x31e6
OP_Save=0x4a39
OP_TestBuff=0x7cb8
OP_CustomTitles=0x100e
OP_Split=0x3a54
OP_YellForHelp=0x4e56
OP_LoadSpellSet=0x261d
OP_Bandolier=0x7677
OP_PotionBelt=0x1a3e
OP_DuelResponse=0x6a46
OP_DuelResponse2=0x68d3
OP_SaveOnZoneReq=0x600d
OP_ReadBook=0x72df
OP_Dye=0x23b9
OP_InterruptCast=0x048c
OP_AAAction=0x424e
OP_LeadershipExpToggle=0x6c55
OP_LeadershipExpUpdate=0x2797
OP_PurchaseLeadershipAA=0x0026
OP_UpdateLeadershipAA=0x026
OP_MarkNPC=0x5a58
OP_MarkRaidNPC=0x74bd #unimplemented
OP_ClearNPCMarks=0x2003
OP_ClearRaidNPCMarks=0x20d3 #unimplemented
OP_DelegateAbility=0x76b8
OP_SetGroupTarget=0x2814
OP_Charm=0x5d92
OP_Stun=0x36a4
OP_SendFindableNPCs=0x7e62
OP_FindPersonRequest=0x5cea
OP_FindPersonReply=0x7e58
OP_Sound=0x1a30
OP_PetBuffWindow=0x5882
OP_LevelAppearance=0x3bc9
OP_Translocate=0x6580
OP_Sacrifice=0x1821
OP_PopupResponse=0x08a6
OP_OnLevelMessage=0x4d6e
OP_AugmentInfo=0x0afb
OP_Petition=0x3de3
OP_SomeItemPacketMaybe=0x747c
OP_PVPStats=0x4b15
OP_PVPLeaderBoardRequest=0x04aa
OP_PVPLeaderBoardReply=0x071f
OP_PVPLeaderBoardDetailsRequest=0x3707
OP_PVPLeaderBoardDetailsReply=0x25b7
OP_RestState=0x000f
OP_RespawnWindow=0x28bc
OP_LDoNButton=0x5327
OP_SetStartCity=0x6326
OP_VoiceMacroIn=0x17fd
OP_VoiceMacroOut=0x409a
OP_ItemViewUnknown=0x465b
OP_VetRewardsAvaliable=0x590e
OP_VetClaimRequest=0x1126
OP_VetClaimReply=0x16d4
OP_DisciplineUpdate=0x759e
OP_DisciplineTimer=0x6989
OP_BecomeCorpse=0x0000 # Unused?
OP_Action2=0x0000 # Unused?
OP_MobUpdate=0x2c84
OP_NPCMoveUpdate=0x5892
OP_CameraEffect=0x127f
OP_SpellEffect=0x5936
OP_RemoveNimbusEffect=0x7b1e
OP_AltCurrency=0x62ab
OP_AltCurrencyMerchantRequest=0x61cb
OP_AltCurrencyMerchantReply=0x5409
OP_AltCurrencyPurchase=0x0165
OP_AltCurrencySell=0x74ec
OP_AltCurrencySellSelection=0x3788
OP_AltCurrencyReclaim=0x3899
OP_CrystalCountUpdate=0x467f
OP_CrystalCreate=0x7aee
OP_CrystalReclaim=0x2439
OP_Untargetable=0x053c
OP_IncreaseStats=0x70a3
OP_Weblink=0x6f4b
OP_OpenContainer=0x0000
OP_Marquee=0x0000
OP_ItemRecastDelay=0x15a9
#OP_OpenInventory=0x0000 # Likely does not exist in RoF -U
OP_DzQuit=0x205f
OP_DzListTimers=0x0398
OP_DzAddPlayer=0x59ca
OP_DzRemovePlayer=0x4701
OP_DzSwapPlayer=0x1abc
OP_DzMakeLeader=0x405b
OP_DzPlayerList=0x543d
OP_DzJoinExpeditionConfirm=0x14c6
OP_DzJoinExpeditionReply=0x7f4b
OP_DzExpeditionInfo=0x4f7e
OP_DzExpeditionList=0x9119
OP_DzMemberStatus=0xb2e3
OP_DzLeaderStatus=0x32f0
OP_DzExpeditionEndsWarning=0x7e94
OP_DzMemberList=0x3de9
OP_DzCompass=0x3e0e
OP_DzChooseZone=0x0000
# New Opcodes
OP_SpawnPositionUpdate=0x0000 # Actually OP_MobUpdate ?
OP_ManaUpdate=0x3791
OP_EnduranceUpdate=0x5f42
OP_MobManaUpdate=0x2404
OP_MobEnduranceUpdate=0x1c81
# Mercenary Opcodes
OP_MercenaryDataUpdateRequest=0x7b89
OP_MercenaryDataUpdate=0x61a4
OP_MercenaryDataRequest=0x11c1
OP_MercenaryDataResponse=0x72ce
OP_MercenaryHire=0x7169
OP_MercenaryDismiss=0x6e83
OP_MercenaryTimerRequest=0x31e4
OP_MercenaryTimer=0x0763
OP_MercenaryUnknown1=0x5d26
OP_MercenaryCommand=0x27f2
OP_MercenarySuspendRequest=0x4407
OP_MercenarySuspendResponse=0x6f03
OP_MercenaryUnsuspendResponse=0x27a0
# Looting
OP_LootRequest=0x0adf
OP_EndLootRequest=0x30f7
OP_LootItem=0x4dc9
OP_LootComplete=0x55c4
# bazaar trader stuff:
OP_BazaarSearch=0x39d6
OP_TraderDelItem=0x0000
OP_BecomeTrader=0x61b3
OP_TraderShop=0x31df
OP_Trader=0x4ef5
OP_TraderBuy=0x0000
OP_Barter=0x243a
OP_ShopItem=0x0000
OP_BazaarInspect=0x0000
OP_Bazaar=0x0000
OP_TraderItemUpdate=0x0000
# pc/npc trading
OP_TradeRequest=0x77b5
OP_TradeAcceptClick=0x69e2
OP_TradeRequestAck=0x14bf
OP_TradeCoins=0x4206
OP_FinishTrade=0x3993
OP_CancelTrade=0x354c
OP_TradeMoneyUpdate=0x68c2
OP_MoneyUpdate=0x640c
OP_TradeBusy=0x5505
# Sent after canceling trade or after closing tradeskill object
OP_FinishWindow=0x7349
OP_FinishWindow2=0x40ef
# Sent on Live for what seems to be item existance verification
# Ex. Before Right Click Effect happens from items
OP_ItemVerifyRequest=0x189c
OP_ItemVerifyReply=0x097b
# merchant stuff
OP_ShopPlayerSell=0x0000
OP_ShopRequest=0x4fed
OP_ShopEnd=0x30a8
OP_ShopEndConfirm=0x3196
OP_ShopPlayerBuy=0x0ddd
OP_ShopDelItem=0x724f
# tradeskill stuff:
OP_ClickObject=0x4aa1
OP_ClickObjectAction=0x0c1e
OP_ClearObject=0x7a11
OP_RecipeDetails=0x40d7
OP_RecipesFavorite=0x71b1
OP_RecipesSearch=0x1db6
OP_RecipeReply=0x6e02
OP_RecipeAutoCombine=0x6261
OP_TradeSkillCombine=0x579a
# Tribute Packets:
OP_OpenGuildTributeMaster=0x378d
OP_OpenTributeMaster=0x7666
OP_SelectTribute=0x79fc
OP_TributeItem=0x4f3e
OP_TributeMoney=0x58fb
OP_TributeToggle=0x241d
OP_TributePointUpdate=0x5300
OP_TributeNPC=0x0000
OP_GuildTributeInfo=0x0000
OP_OpenTributeReply=0x0000
OP_GuildTributeStatus=0x0000
# Adventure packets:
OP_LeaveAdventure=0x5d18
OP_AdventureFinish=0x400f
OP_AdventureInfoRequest=0x3cb0
OP_AdventureInfo=0x4c54
OP_AdventureRequest=0x2c6c
OP_AdventureDetails=0x5648
OP_AdventureData=0x7171
OP_AdventureUpdate=0x1b01
OP_AdventureMerchantRequest=0x6922
OP_AdventureMerchantResponse=0x3e47
OP_AdventureMerchantPurchase=0x5b72
OP_AdventureMerchantSell=0x2f9b
OP_AdventurePointsUpdate=0x65c3
OP_AdventureStatsRequest=0x5a62
OP_AdventureStatsReply=0x2370
OP_AdventureLeaderboardRequest=0x7093
OP_AdventureLeaderboardReply=0x7f79
# Group Opcodes
OP_GroupDisband=0x4c10
OP_GroupInvite=0x6110
OP_GroupFollow=0x1649
OP_GroupUpdate=0x3abb
OP_GroupUpdateB=0x6194
OP_GroupCancelInvite=0x0000
OP_GroupAcknowledge=0x7323
OP_GroupDelete=0x0f6c
OP_CancelInvite=0x2a50
OP_GroupFollow2=0x2060
OP_GroupInvite2=0x32c2
OP_GroupDisbandYou=0x1ae5
OP_GroupDisbandOther=0x74da
OP_GroupLeaderChange=0x21b4
OP_GroupRoles=0x70e2
OP_GroupMakeLeader=0x4229
OP_DoGroupLeadershipAbility=0x1fb5
OP_GroupLeadershipAAUpdate=0x02cf
OP_GroupMentor=0x3342
OP_InspectBuffs=0x486c
# LFG/LFP Opcodes
OP_LFGCommand=0x6060
OP_LFGGetMatchesRequest=0x0340
OP_LFGGetMatchesResponse=0x5048
OP_LFPGetMatchesRequest=0x4d7d
OP_LFPGetMatchesResponse=0x22c6
OP_LFPCommand=0x49a9
OP_LFGAppearance=0x0000
OP_LFGResponse=0x0000
# Raid Opcodes
OP_RaidInvite=0x55ac
OP_RaidUpdate=0x3973
OP_RaidJoin=0x0000
# Button-push commands
OP_Taunt=0x2703
OP_CombatAbility=0x3eba
OP_SenseTraps=0x02af
OP_PickPocket=0x39e8
OP_DisarmTraps=0x78bf
OP_Disarm=0x5ec8
OP_Sneak=0x5d55
OP_Fishing=0x1e2a
OP_InstillDoubt=0x640e
OP_FeignDeath=0x52fa
OP_Mend=0x0ecf
OP_Bind_Wound=0x0386
OP_LDoNOpen=0x3d5c
# Task packets
OP_TaskDescription=0x3714
OP_TaskActivity=0x08d3
OP_CompletedTasks=0x4eba
OP_TaskActivityComplete=0x5e19
OP_AcceptNewTask=0x0a23
OP_CancelTask=0x39f0
OP_TaskMemberList=0x5727
OP_OpenNewTasksWindow=0x48a2
OP_AvaliableTask=0x36e8
OP_TaskHistoryRequest=0x5f1c
OP_TaskHistoryReply=0x3d05
OP_DeclineAllTasks=0x0000
# Title opcodes
OP_NewTitlesAvailable=0x0d32
OP_RequestTitles=0x6344
OP_SendTitleList=0x2d08
OP_SetTitle=0x6527
OP_SetTitleReply=0x4c21
# mail opcodes
OP_Command=0x0000
OP_MailboxHeader=0x0000
OP_MailHeader=0x0000
OP_MailBody=0x0000
OP_NewMail=0x0000
OP_SentConfirm=0x0000
########### Below this point should not be needed ###########
# This section are all unknown in Titanium
OP_ForceFindPerson=0x0000
OP_LocInfo=0x0000
OP_ReloadUI=0x0000
OP_ItemName=0x0000
OP_ItemLinkText=0x0000
OP_MultiLineMsg=0x0000
OP_MendHPUpdate=0x0000
OP_TargetReject=0x0000
OP_SafePoint=0x0000
OP_ApproveZone=0x0000
OP_ZoneComplete=0x0000
OP_ClientError=0x0000
OP_DumpName=0x0000
OP_Heartbeat=0x0000
OP_CrashDump=0x0000
OP_LoginComplete=0x0000
# discovered opcodes not yet used:
OP_PickLockSuccess=0x0000
OP_PlayMP3=0x0000
OP_ReclaimCrystals=0x0000
OP_DynamicWall=0x0000
OP_OpenDiscordMerchant=0x0000
OP_DiscordMerchantInventory=0x0000
OP_GiveMoney=0x0000
OP_RequestKnowledgeBase=0x0000
OP_KnowledgeBase=0x0000
OP_SlashAdventure=0x0000 # /adventure
OP_BecomePVPPrompt=0x0000
OP_MoveLogRequest=0x0000 # gone I think
OP_MoveLogDisregard=0x0000 # gone I think
# named unknowns, to make looking for real unknown easier
OP_AnnoyingZoneUnknown=0x0000
OP_Some6ByteHPUpdate=0x0000 seems to happen when you target group members
OP_QueryResponseThing=0x0000
# realityincarnate: these are just here to stop annoying several thousand byte packet dumps
#OP_LoginUnknown1=0x46d3 # OP_SendSpellChecksum
#OP_LoginUnknown2=0x040b # OP_SendSkillCapsChecksum
# Petition Opcodes
OP_PetitionSearch=0x0000 search term for petition
OP_PetitionSearchResults=0x0000 (list of?) matches from search
OP_PetitionSearchText=0x0000 text results of search
OP_PetitionUpdate=0x0000
OP_PetitionCheckout=0x0000
OP_PetitionCheckIn=0x0000
OP_PetitionQue=0x0000
OP_PetitionUnCheckout=0x0000
OP_PetitionDelete=0x0000
OP_DeletePetition=0x0000
OP_PetitionResolve=0x0000
OP_PDeletePetition=0x0000
OP_PetitionBug=0x0000
OP_PetitionRefresh=0x0000
OP_PetitionCheckout2=0x0000
OP_PetitionViewPetition=0x0000
# Login opcodes
OP_SessionReady=0x0000
OP_Login=0x0000
OP_ServerListRequest=0x0000
OP_PlayEverquestRequest=0x0000
OP_PlayEverquestResponse=0x0000
OP_ChatMessage=0x0000
OP_LoginAccepted=0x0000
OP_ServerListResponse=0x0000
OP_Poll=0x0000
OP_EnterChat=0x0000
OP_PollResponse=0x0000
# raw opcodes
OP_RAWSessionRequest=0x0000
OP_RAWSessionResponse=0x0000
OP_RAWCombined=0x0000
OP_RAWSessionDisconnect=0x0000
OP_RAWKeepAlive=0x0000
OP_RAWSessionStatRequest=0x0000
OP_RAWSessionStatResponse=0x0000
OP_RAWPacket=0x0000
OP_RAWFragment=0x0000
OP_RAWOutOfOrderAck=0x0000
OP_RAWAck=0x0000
OP_RAWAppCombined=0x0000
OP_RAWOutOfSession=0x0000
# we need to document the differences between these packets to make identifying them easier
OP_Some3ByteHPUpdate=0x0000 # initial HP update for mobs
OP_InitialHPUpdate=0x0000

View File

@ -158,7 +158,7 @@ OP_GMApproval=0x72fa # C
OP_GMToggle=0x7566 # C
OP_GMSummon=0x596d # C
OP_GMEmoteZone=0x3e7c # C
OP_GMEmoteWorld=0x3e7c # C
OP_GMEmoteWorld=0x5298 # C
OP_GMFind=0x6e27 # C
OP_GMKick=0x799c # C
OP_GMKill=0x6685 # C
@ -369,7 +369,7 @@ OP_DzExpeditionEndsWarning=0x1879
OP_DzExpeditionList=0x3657
OP_DzMemberList=0x74e4
OP_DzCompass=0x35d3
OP_DzChooseZone=0xd8a
OP_DzChooseZone=0x0d8a
#0x1d99 was grouped with these too but I don't really know it's purpose.
# New Opcodes
@ -580,7 +580,6 @@ OP_MultiLineMsg=0x0000 #
OP_MendHPUpdate=0x0000 #
OP_TargetReject=0x0000 #
OP_SafePoint=0x0000 #
OP_IncreaseStats=0x0000 #
OP_ApproveZone=0x0000 #
OP_ZoneComplete=0x0000 #
OP_ClientError=0x0000 #

View File

@ -85,6 +85,7 @@ OP_TaskActivity=0x2E60 #SEQ 12/04/08
OP_CompletedTasks=0x75AC #Derision 2009
OP_Weather=0x70A5 #SEQ 12/04/08
OP_SendAATable=0x6F05 #Trevius 12/20/08
OP_ShroudClearAA=0x71b9
OP_UpdateAA=0x45D2 #Trevius 12/20/08
OP_RespondAA=0x4426 #Trevius 12/20/08
OP_ReqClientSpawn=0x014C #SEQ 12/04/08
@ -331,6 +332,7 @@ OP_InspectMessageUpdate=0x67e9 # C
OP_OpenInventory=0x66c8
OP_OpenContainer=0x10e3
OP_Marquee=0x2f75
OP_Untargetable=0x3e36
#expedition
OP_DzQuit=0x20d6
@ -530,7 +532,7 @@ OP_MultiLineMsg=0x0000 #
OP_MendHPUpdate=0x0000 #
OP_TargetReject=0x0000 #
OP_SafePoint=0x0000 #
OP_IncreaseStats=0x0000 #
OP_IncreaseStats=0x5ecb #
OP_ApproveZone=0x0000 #
OP_ZoneComplete=0x0000 #
OP_ClientError=0x0000 #
@ -544,9 +546,11 @@ OP_PickLockSuccess=0x0000 #
OP_VetRewardsAvaliable=0x044b #
OP_VetClaimRequest=0x7503
OP_VetClaimReply=0x01e1
OP_PlayMP3=0x0000 #
OP_PlayMP3=0x0d1c #
OP_ReclaimCrystals=0x0000 #
OP_CrystalCountUpdate=0x64C1 #
OP_CrystalCreate=0x65e2
OP_CrystalReclaim=0x0730
OP_DynamicWall=0x0000 #
OP_OpenDiscordMerchant=0x0000 #
OP_DiscordMerchantInventory=0x0000 #

View File

@ -88,6 +88,7 @@ OP_TaskActivity=0x31f3 # C
OP_CompletedTasks=0x687f # C
OP_Weather=0x4658 # V
OP_SendAATable=0x6ef9 # V
OP_ShroudClearAA=0x2cd4
OP_UpdateAA=0x7bf6 # V
OP_RespondAA=0x1fbd # C 0x2bad
OP_ReqClientSpawn=0x69cd # V
@ -315,7 +316,7 @@ OP_OnLevelMessage=0x24cb # C
OP_AugmentInfo=0x31b1 # C
OP_Petition=0x31d1 # C
OP_SomeItemPacketMaybe=0x2c27 # C
OP_PVPStats=0x0000 #
OP_PVPStats=0x5272 #
OP_PVPLeaderBoardRequest=0x4973 # C
OP_PVPLeaderBoardReply=0x3842 # C
OP_PVPLeaderBoardDetailsRequest=0x6c75 # C
@ -373,7 +374,17 @@ OP_DzExpeditionEndsWarning=0x6ac2
OP_DzExpeditionList=0x70d8
OP_DzMemberList=0x15c4
OP_DzCompass=0x01cb
OP_DzChooseZone=0x0000
OP_DzChooseZone=0x65e1
#shroud
OP_ShroudSelectionWindow=0x72ad
OP_ShroudRequestStats=0x488b
OP_ShroudRespondStats=0x1910
OP_ShroudSelect=0x45d7
OP_ShroudSelectCancel=0x666d
OP_ShroudProgress=0x6016 # This clears current progress and sets
OP_ShroudProgress2=0x66b4 # This just sets progress
OP_Shroud=0x1643
# New Opcodes
OP_SpawnPositionUpdate=0x4656 # C

View File

@ -6,6 +6,21 @@
#::: Purpose: To upgrade databases with ease and maintain versioning
###########################################################
#::: If current version is less than what world is reporting, then download a new one...
$current_version = 1;
if($ARGV[0] eq "V"){
if($ARGV[1] > $current_version){
print "Retrieving latest database manifest...\n";
GetRemoteFile("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/db_update.pl", "db_update.pl");
exit;
}
else{
print "No update necessary \n";
}
exit;
}
$perl_version = $^V;
$perl_version =~s/v//g;
print "Perl Version is " . $perl_version . "\n";
@ -26,14 +41,14 @@ while(<F>) {
elsif(/<db>(.*)<\/db>/i) { $db = $1; }
}
print
$console_output =
"============================================================
EQEmu: Automatic Database Upgrade Check
============================================================
";
use Config;
print " Operating System is: $Config{osname}\n";
$console_output .= " Operating System is: $Config{osname}\n";
if($Config{osname}=~/linux/i){ $OS = "Linux"; }
if($Config{osname}=~/Win|MS/i){ $OS = "Windows"; }
@ -48,9 +63,9 @@ if($OS eq "Windows"){
last;
}
}
print " (Windows) MySQL is in system path \n";
print " Path = " . $path . "\n";
print "============================================================\n";
$console_output .= " (Windows) MySQL is in system path \n";
$console_output .= " Path = " . $path . "\n";
$console_output .= "============================================================\n";
}
}
@ -62,9 +77,9 @@ if($OS eq "Linux"){
}
$path =~s/\n//g;
print " (Linux) MySQL is in system path \n";
print " Path = " . $path . "\n";
print "============================================================\n";
$console_output .= " (Linux) MySQL is in system path \n";
$console_output .= " Path = " . $path . "\n";
$console_output .= "============================================================\n";
}
#::: Path not found, error and exit
@ -93,10 +108,21 @@ if(GetMySQLResult("SHOW TABLES LIKE 'db_version'") eq ""){
}
if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); }
if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); }
if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); }
$bin_db_ver = trim($db_version[1]);
$local_db_ver = trim(GetMySQLResult("SELECT version FROM db_version LIMIT 1"));
#::: If ran from Linux startup script, supress output
if($bin_db_ver == $local_db_ver && $ARGV[0] eq "ran_from_start"){
print "Database up to date...\n";
exit;
}
else{
print $console_output;
}
print " Binary Database Version: (" . $bin_db_ver . ")\n";
print " Local Database Version: (" . $local_db_ver . ")\n\n";
@ -135,7 +161,7 @@ sub ShowMenuPrompt {
while (1) {
{
local $| = 1;
if(!$menu_show && $ARGV[0] eq "ran_from_world"){
if(!$menu_show && ($ARGV[0] eq "ran_from_world" || $ARGV[0] eq "ran_from_start")){
$menu_show++;
next;
}

View File

@ -0,0 +1,3 @@
# Input and Output txt and conf files.
*.txt
*.conf

View File

@ -0,0 +1,66 @@
#!/usr/bin/perl
# File Name: conf_to_oplist.pl
# Converts a Patch File into the Opcode List with Opcode Names for the Spreadsheet.
# Directions to use this script:
# 1. Paste the contents of the current patch file in the patch_OLD.conf file.
# 2. Run this script using "perl conf_to_oplist.pl"
# 3. This updates the opcodelist.txt with the values from the Patch File.
$stopmessage = "Failed to open file";
open OpcodeFile, "<", "opcodelist.txt" or die $stopmessage;
open PatchFile, "<", "patch_OLD.conf" or die $stopmessage;
my @OpcodeList = <OpcodeFile>;
my @PatchFile = <PatchFile>;
my %PatchHash = ();
foreach $line (@PatchFile)
{
@equalssplit = split(/=/, $line);
$ArraySize = @equalssplit;
if ($ArraySize > 1)
{
@OpcodeArray = split(//, $equalssplit[1]);
$CurOpcode = $OpcodeArray[0].$OpcodeArray[1].$OpcodeArray[2].$OpcodeArray[3].$OpcodeArray[4].$OpcodeArray[5];
$CurOpcode = lc($CurOpcode);
# Opcode Name => Opcode
$PatchHash{ $CurOpcode } = $equalssplit[0];
}
}
close(OpcodeFile);
close(PatchFile);
# Clear out file contents
open OpcodeResultFile, ">", "opcodelist.txt" or die $stopmessage;
print OpcodeResultFile "";
close(OpcodeResultFile);
open OpcodeResultFile, ">>", "opcodelist.txt" or die $stopmessage;
while( my ($k, $v) = each %$PatchFile )
{
#print OpcodeResultFile "key: $k, value: $v.\n";
}
$TabSpace = " "; # Tab
foreach $line (@OpcodeList)
{
@LineSplit = split(//, $line);
$CurOpcode = $LineSplit[0].$LineSplit[1].$LineSplit[2].$LineSplit[3].$LineSplit[4].$LineSplit[5];
$CurOpcode = lc($CurOpcode);
$OpcodeName = ""; # Tab
if ($PatchHash{$CurOpcode})
{
$NameKey = $PatchHash{$CurOpcode};
$OpcodeName = $NameKey;
}
$CurLine = $CurOpcode.$TabSpace.$OpcodeName."\n";
print OpcodeResultFile $CurLine;
}
close(OpcodeResultFile);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,88 @@
#!/usr/bin/perl
# File Name: oplist_to_conf.pl
# Converts the Opcode List with Opcode Names from the Spreadsheet into a Patch File.
# Directions to use this script:
# 1. Copy the opcodes and opcode names columns from the opcode spreadsheet
# for the columns you want to create a new .conf file from into the file.
# 2. Remove the header row entries in the newly created text file and save it.
# 3. Paste the contents of the current patch file in the patch_OLD.conf file.
# 4. Run this script using "perl oplist_to_conf.pl"
# 5. This creates a new .conf file named patch_NEW.conf
# 6. Rename patch_NEW.conf to the desired name and you are all done
$stopmessage = "Failed to open file";
# Open the text file that contains the opcode and opcode name rows for a single client from the opcode list spreadsheet
open OpcodeFile, "<", "opcodelist.txt" or die $stopmessage;
# Open the .conf file to copy from
open PatchFile, "<", "patch_OLD.conf" or die $stopmessage;
# Read these files into arrays for looping and close the files
my @OpcodeList = <OpcodeFile>;
my @PatchFile = <PatchFile>;
close(OpcodeFile);
close(PatchFile);
# Open the new/destination .conf file and clear out file contents
open OpcodeResultFile, ">", "patch_NEW.conf" or die $stopmessage;
print OpcodeResultFile "";
# Close out the newly cleared .conf file
close(OpcodeResultFile);
# Open the new/destination .conf file again for appending
open OpcodeResultFile, ">>", "patch_NEW.conf" or die $stopmessage;
my %PatchHash = ();
foreach $line (@OpcodeList)
{
@equalssplit = split(/ /, $line);
$ArraySize = @equalssplit;
if ($ArraySize > 1)
{
my $CurOpcode = "";
my $CurOpcodeName = "";
@OpcodeArray = split(//, $equalssplit[0]);
if ($equalssplit[1] =~ /^OP_(.*)/i)
{
$CurOpcodeName = "OP_".$1;
}
foreach $Letter (@OpcodeArray)
{
if ($Letter =~ /[A-Za-z0-9]/)
{
$CurOpcode .= $Letter;
}
}
if ($CurOpcode && $CurOpcodeName)
{
$CurOpcode = lc($CurOpcode);
$PatchHash{ $CurOpcodeName } = $CurOpcode;
#print $CurOpcodeName."=". $CurOpcode."\n";
}
}
}
$TabSpace = " "; # Tab
foreach $line (@PatchFile)
{
$CurLine = $line;
if ($line =~ /^OP_([^\=]+)=([^\s]+)(.*)/i)
{
$NewOpcode = "0x0000";
$OpcodeName = "OP_".$1;
if ($PatchHash{$OpcodeName})
{
$NewOpcode = $PatchHash{$OpcodeName};
}
$CurLine = $OpcodeName."=".$NewOpcode.$3."\n";
}
print OpcodeResultFile $CurLine;
}
close(OpcodeResultFile);

View File

@ -0,0 +1,661 @@
# ShowEQ Import Notes:
# ZERO THE FILE first
# perl -pi -e 's/0x[0-9a-fA-F]{4}/0x0000/g' opcodes.conf
# Unknown Mapping:
# OP_Action2 -> OP_Damage
# OP_EnvDamage -> OP_Damage ---> might have been a one time mistake
# Name Differences:
# OP_CancelInvite -> OP_GroupCancelInvite
# OP_GMFind -> OP_FindPersonRequest
# OP_CommonMessage -> OP_ChannelMessage
OP_Unknown=0x0000
OP_ExploreUnknown=0x0000 used for unknown explorer
# world packets
# Required to reach Char Select:
OP_SendLoginInfo=0x7a09
OP_ApproveWorld=0x7499
OP_LogServer=0x7ceb
OP_SendCharInfo=0x00d2
OP_ExpansionInfo=0x590d
OP_GuildsList=0x0000
OP_EnterWorld=0x578f
OP_PostEnterWorld=0x6259
OP_World_Client_CRC1=0x12cc
OP_World_Client_CRC2=0x0f13
OP_SendSpellChecksum=0x0000
OP_SendSkillCapsChecksum=0x0000
# Character Select Related:
OP_SendMaxCharacters=0x5475
OP_SendMembership=0x7acc
OP_SendMembershipDetails=0x057b
OP_CharacterCreateRequest=0x6773
OP_CharacterCreate=0x6bbf
OP_DeleteCharacter=0x1808
OP_RandomNameGenerator=0x5954
OP_ApproveName=0x56a2
OP_MOTD=0x0c22
OP_SetChatServer=0x1bc5
OP_SetChatServer2=0x7eec
OP_ZoneServerInfo=0x4c44
OP_WorldComplete=0x4493
OP_WorldUnknown001=0x2301
OP_FloatListThing=0x46c6
# Reasons for Disconnect:
OP_ZoneUnavail=0x4cb4
OP_WorldClientReady=0x23c1
OP_CharacterStillInZone=0x0000
OP_WorldChecksumFailure=0x0000
OP_WorldLoginFailed=0x0000
OP_WorldLogout=0x0000
OP_WorldLevelTooHigh=0x0000
OP_CharInacessable=0x0000
OP_UserCompInfo=0x0000
OP_SendExeChecksum=0x0000
OP_SendBaseDataChecksum=0x0000
# Zone in opcodes
OP_AckPacket=0x471d
OP_ZoneEntry=0x5089
OP_ReqNewZone=0x7887
OP_NewZone=0x1795
OP_ZoneSpawns=0x5237
OP_PlayerProfile=0x6506
OP_TimeOfDay=0x5070
OP_LevelUpdate=0x1eec
OP_Stamina=0x2a79
OP_RequestClientZoneChange=0x3fcf
OP_ZoneChange=0x2d18
OP_LockoutTimerInfo=0x0000
OP_ZoneServerReady=0x0000
OP_ZoneInUnknown=0x0000
OP_LogoutReply=0x0000
OP_PreLogoutReply=0x0000
# Required to fully log in
OP_SpawnAppearance=0x0971
OP_ChangeSize=0x4707
OP_TributeUpdate=0x5961
OP_TributeTimer=0x073d
OP_SendTributes=0x729b
OP_SendGuildTributes=0x1877
OP_TributeInfo=0x4254
OP_Weather=0x661e
OP_ReqClientSpawn=0x35fa
OP_SpawnDoor=0x7291
OP_GroundSpawn=0x6fca
OP_SendZonepoints=0x69a4
OP_BlockedBuffs=0x3033
OP_RemoveBlockedBuffs=0x0de7
OP_ClearBlockedBuffs=0x34cb
OP_WorldObjectsSent=0x5ae2
OP_SendExpZonein=0x5f8e
OP_SendAATable=0x66b5
OP_RespondAA=0x7a27
OP_UpdateAA=0x66f0
OP_SendAAStats=0x43c8
OP_AAExpUpdate=0x7d14
OP_ExpUpdate=0x20ed
OP_HPUpdate=0x2828
OP_ManaChange=0x43af
OP_TGB=0x0876
OP_SpecialMesg=0x0083
OP_GuildMemberList=0x12a6
OP_GuildMOTD=0x3e13
OP_CharInventory=0x5ca6
OP_WearChange=0x7994
OP_ClientUpdate=0x7dfc
OP_ClientReady=0x345d # 0x422d
OP_SetServerFilter=0x444d
# Guild Opcodes - Disabled until crashes are resolved in RoF
OP_GetGuildMOTD=0x36e0 # Was 0x35dc
OP_GetGuildMOTDReply=0x4f1f # Was 0x4586
OP_GuildMemberUpdate=0x69b9 # Was 0x5643
OP_GuildInvite=0x7099
OP_GuildRemove=0x1444
OP_GuildPeace=0x67e3
OP_SetGuildMOTD=0x0b0b
OP_GuildList=0x507a
OP_GuildWar=0x1ffb
OP_GuildLeader=0x7e09
OP_GuildDelete=0x3708
OP_GuildInviteAccept=0x7053
OP_GuildDemote=0x2d4e
OP_GuildPromote=0x0000
OP_GuildPublicNote=0x5053
OP_GuildManageBanker=0x748f # Was 0x0737
OP_GuildBank=0x5134 # Was 0x10c3
OP_SetGuildRank=0x0b9c
OP_GuildUpdateURLAndChannel=0x2958
OP_GuildStatus=0x7326
OP_GuildCreate=0x1dc8 # or maybe 0x086e
OP_GuildMemberLevelUpdate=0x0000 # Unused?
OP_ZoneGuildList=0x0000 # Unused?
OP_GetGuildsList=0x0000 # Unused?
OP_LFGuild=0x0000
OP_GuildManageRemove=0x0000
OP_GuildManageAdd=0x0000
OP_GuildManageStatus=0x0000
# GM/Guide Opcodes
OP_GMServers=0x08c1
OP_GMBecomeNPC=0x3ae1
OP_GMZoneRequest=0x62ac
OP_GMZoneRequest2=0x7e1a
OP_GMGoto=0x7d8e
OP_GMSearchCorpse=0x357c
OP_GMHideMe=0x79c5
OP_GMDelCorpse=0x607e
OP_GMApproval=0x6db5
OP_GMToggle=0x2097
OP_GMSummon=0x486f # Was 0x684f
OP_GMEmoteZone=0x1cfd # Was 0x0655
OP_GMEmoteWorld=0x458e # Was 0x1935
OP_GMFind=0x4a8f
OP_GMKick=0x26a7
OP_GMKill=0x51d3
OP_GMNameChange=0x035f # Was 0x4434
OP_GMLastName=0x46ce # Was 0x3077
# Misc Opcodes
OP_InspectRequest=0x57bc
OP_InspectAnswer=0x71ac
OP_InspectMessageUpdate=0x4d25
OP_BeginCast=0x318f
OP_ColoredText=0x0000
OP_ConsentResponse=0x384a
OP_MemorizeSpell=0x217c
OP_SwapSpell=0x0efa
OP_CastSpell=0x1287
OP_Consider=0x742b
OP_FormattedMessage=0x1024
OP_SimpleMessage=0x213f
OP_Buff=0x659c
OP_Illusion=0x312a
OP_MoneyOnCorpse=0x5f44
OP_RandomReply=0x106b
OP_DenyResponse=0x2382
OP_SkillUpdate=0x004c
OP_GMTrainSkillConfirm=0x66dd # 0x3960
OP_RandomReq=0x7b10
OP_Death=0x6517
OP_GMTraining=0x1966
OP_GMEndTraining=0x4d6b
OP_GMTrainSkill=0x2a85
OP_Animation=0x7177
OP_Begging=0x6703
OP_Consent=0x1fd1
OP_ConsentDeny=0x7a45
OP_AutoFire=0x241e
OP_PetCommands=0x0159
OP_DeleteSpell=0x52e5
OP_Surname=0x0423
OP_ClearSurname=0x7d23
OP_FaceChange=0x5578
OP_SenseHeading=0x260a
OP_Action=0x744c
OP_ConsiderCorpse=0x5204
OP_HideCorpse=0x49e1
OP_CorpseDrag=0x0904
OP_CorpseDrop=0x7037
OP_Bug=0x73f4
OP_Feedback=0x5602
OP_Report=0x1414
OP_Damage=0x6f15
OP_ChannelMessage=0x2b2d
OP_Assist=0x4478
OP_AssistGroup=0x27f8
OP_MoveCoin=0x0bcf
OP_ZonePlayerToBind=0x0ecb
OP_KeyRing=0x6857
OP_WhoAllRequest=0x65ab
OP_WhoAllResponse=0x7c88
OP_FriendsWho=0x3956
OP_ConfirmDelete=0x43a3
OP_Logout=0x4ac6
OP_Rewind=0x1745
OP_TargetCommand=0x58e2
OP_Hide=0x67fe
OP_Jump=0x2060
OP_Camp=0x28ec
OP_Emote=0x373b
OP_SetRunMode=0x009f
OP_BankerChange=0x383c
OP_TargetMouse=0x075d
OP_MobHealth=0x37b1
OP_InitialMobHealth=0x0000 # Unused?
OP_TargetHoTT=0x0272
OP_XTargetResponse=0x672f
OP_XTargetRequest=0x45be
OP_XTargetAutoAddHaters=0x792c
OP_TargetBuffs=0x4f4b
OP_BuffCreate=0x3377
OP_BuffRemoveRequest=0x64f2
OP_DeleteSpawn=0x7280
OP_AutoAttack=0x109d
OP_AutoAttack2=0x3526
OP_Consume=0x4b70
OP_MoveItem=0x32ee
OP_DeleteItem=0x18ad
OP_DeleteCharge=0x01b8
OP_ItemPacket=0x368e
OP_ItemLinkResponse=0x633c
OP_ItemLinkClick=0x4cef
OP_ItemPreview=0x6b5c
OP_NewSpawn=0x6097
OP_Track=0x17e5
OP_TrackTarget=0x0029
OP_TrackUnknown=0x4577
OP_ClickDoor=0x3a8f
OP_MoveDoor=0x08e8
OP_RemoveAllDoors=0x700c
OP_EnvDamage=0x51fd
OP_BoardBoat=0x4211
OP_Forage=0x5306
OP_LeaveBoat=0x7617
OP_ControlBoat=0x0ae7
OP_SafeFallSuccess=0x2219
OP_RezzComplete=0x760d
OP_RezzRequest=0x3c21
OP_RezzAnswer=0x701c
OP_Shielding=0x48c1
OP_RequestDuel=0x3af1
OP_MobRename=0x2c57
OP_AugmentItem=0x661b # Was 0x37cb
OP_WeaponEquip1=0x34a7
OP_WeaponEquip2=0x559a # Was 0x6022
OP_WeaponUnequip2=0x2d25 # Was 0x0110
OP_ApplyPoison=0x31e6
OP_Save=0x4a39
OP_TestBuff=0x7cb8 # Was 0x3772
OP_CustomTitles=0x100e
OP_Split=0x3a54
OP_YellForHelp=0x4e56
OP_LoadSpellSet=0x261d
OP_Bandolier=0x7677
OP_PotionBelt=0x1a3e # Was 0x4d3b
OP_DuelResponse=0x6a46
OP_DuelResponse2=0x68d3
OP_SaveOnZoneReq=0x600d
OP_ReadBook=0x72df
OP_Dye=0x23b9
OP_InterruptCast=0x048c
OP_AAAction=0x424e
OP_LeadershipExpToggle=0x6c55
OP_LeadershipExpUpdate=0x2797
OP_PurchaseLeadershipAA=0x0026
OP_UpdateLeadershipAA=0x026
OP_MarkNPC=0x5a58
OP_MarkRaidNPC=0x74bd #unimplemented
OP_ClearNPCMarks=0x2003
OP_ClearRaidNPCMarks=0x20d3 #unimplemented
OP_DelegateAbility=0x76b8
OP_SetGroupTarget=0x2814
OP_Charm=0x5d92
OP_Stun=0x36a4
OP_SendFindableNPCs=0x3897
OP_FindPersonRequest=0x5cea
OP_FindPersonReply=0x7e58
OP_Sound=0x1a30
OP_PetBuffWindow=0x5882
OP_LevelAppearance=0x3bc9
OP_Translocate=0x6580
OP_Sacrifice=0x1821
OP_PopupResponse=0x214a
OP_OnLevelMessage=0x4fd0
OP_AugmentInfo=0x0afb
OP_Petition=0x5f03
OP_SomeItemPacketMaybe=0x747c
OP_PVPStats=0x6f4b # Unsure
OP_PVPLeaderBoardRequest=0x3707
OP_PVPLeaderBoardReply=0x25b7
OP_PVPLeaderBoardDetailsRequest=0x15a9
OP_PVPLeaderBoardDetailsReply=0x04aa
OP_RestState=0x00f
OP_RespawnWindow=0x28bc
OP_LDoNButton=0x5327
OP_SetStartCity=0x6326 # Was 0x2d1b
OP_VoiceMacroIn=0x17fd
OP_VoiceMacroOut=0x409a
OP_ItemViewUnknown=0x2289
OP_VetRewardsAvaliable=0x590e
OP_VetClaimRequest=0x1126
OP_VetClaimReply=0x16d4
OP_DisciplineUpdate=0x759e # Was 0x2f05
OP_DisciplineTimer=0x6989 # Was 0x5e3f
OP_BecomeCorpse=0x0000 # Unused?
OP_Action2=0x0000 # Unused?
OP_MobUpdate=0x2c84
OP_NPCMoveUpdate=0x189c
OP_CameraEffect=0x127f
OP_SpellEffect=0x5936
OP_RemoveNimbusEffect=0xc693
OP_AltCurrency=0x7121
OP_AltCurrencyMerchantRequest=0x6b6d
OP_AltCurrencyMerchantReply=0x74ec
OP_AltCurrencyPurchase=0x61cb
OP_AltCurrencySell=0x0165
OP_AltCurrencySellSelection=0x5409
OP_AltCurrencyReclaim=0x532a
OP_CrystalCountUpdate=0x467f # Was 0x3f60
OP_CrystalCreate=0x7aee # Was 0x5a82
OP_CrystalReclaim=0x2439 # Was 0x7616
OP_Untargetable=0x053c
OP_IncreaseStats=0x70a3
OP_Weblink=0x18d3
#OP_OpenInventory=0x0000 # Likely does not exist in RoF -U
OP_OpenContainer=0x0000
OP_Marquee=0x0000
OP_DzQuit=0xb2e3
OP_DzListTimers=0x7b68
OP_DzAddPlayer=0x4701
OP_DzRemovePlayer=0x1abc
OP_DzSwapPlayer=0x405b
OP_DzMakeLeader=0x543d
OP_DzPlayerList=0x14c6
OP_DzJoinExpeditionConfirm=0x7f4b
OP_DzJoinExpeditionReply=0x1950
OP_DzExpeditionInfo=0x9119
OP_DzExpeditionList=0x205f
OP_DzMemberStatus=0x32f0
OP_DzLeaderStatus=0x3de9
OP_DzExpeditionEndsWarning=0x5189
OP_DzMemberList=0x5ae4
OP_DzCompass=0x3e0e # Was 0x4f09
OP_DzChooseZone=0x0000 # Maybe 0x29d6
# New Opcodes
OP_SpawnPositionUpdate=0x0000 # Actually OP_MobUpdate ?
OP_ManaUpdate=0x3791
OP_EnduranceUpdate=0x5f42
OP_MobManaUpdate=0x2404
OP_MobEnduranceUpdate=0x1c81
# Mercenary Opcodes
OP_MercenaryDataUpdateRequest=0x7b89
OP_MercenaryDataUpdate=0x61a4
OP_MercenaryDataRequest=0x11c1
OP_MercenaryDataResponse=0x72ce
OP_MercenaryHire=0x7169
OP_MercenaryDismiss=0x6e83
OP_MercenaryTimerRequest=0x31e4
OP_MercenaryTimer=0x0763
OP_MercenaryUnknown1=0x5d26
OP_MercenaryCommand=0x27f2
OP_MercenarySuspendRequest=0x4407
OP_MercenarySuspendResponse=0x6f03
OP_MercenaryUnsuspendResponse=0x27a0
# Looting
OP_LootRequest=0x0adf
OP_EndLootRequest=0x30f7
OP_LootItem=0x4dc9
OP_LootComplete=0x55c4
# bazaar trader stuff:
OP_BazaarSearch=0x39d6
OP_TraderDelItem=0x0000
OP_BecomeTrader=0x61b3
OP_TraderShop=0x31df
OP_Trader=0x4ef5 # Was 0x6790
OP_TraderBuy=0x0000
OP_Barter=0x243a
OP_ShopItem=0x0000
OP_BazaarInspect=0x0000
OP_Bazaar=0x0000
OP_TraderItemUpdate=0x0000
# pc/npc trading
OP_TradeRequest=0x77b5
OP_TradeAcceptClick=0x69e2
OP_TradeRequestAck=0x14bf
OP_TradeCoins=0x4206
OP_FinishTrade=0x3993
OP_CancelTrade=0x354c
OP_TradeMoneyUpdate=0x68c2
OP_MoneyUpdate=0x640c
OP_TradeBusy=0x5505
# Sent after canceling trade or after closing tradeskill object
OP_FinishWindow=0x7349
OP_FinishWindow2=0x40ef
# Sent on Live for what seems to be item existance verification
# Ex. Before Right Click Effect happens from items
OP_ItemVerifyRequest=0x097b
OP_ItemVerifyReply=0x2115
# merchant stuff
OP_ShopPlayerSell=0x1901
OP_ShopRequest=0x4fed
OP_ShopEnd=0x30a8
OP_ShopEndConfirm=0x3196
OP_ShopPlayerBuy=0x04c
OP_ShopDelItem=0x724f
# tradeskill stuff:
OP_ClickObject=0x4aa1
OP_ClickObjectAction=0x0c1e
OP_ClearObject=0x7a11
OP_RecipeDetails=0x40d7
OP_RecipesFavorite=0x5c74
OP_RecipesSearch=0x1db6
OP_RecipeReply=0x6e02
OP_RecipeAutoCombine=0x6261
OP_TradeSkillCombine=0x579a
# Tribute Packets:
OP_OpenGuildTributeMaster=0x378d
OP_OpenTributeMaster=0x7666 # Was 0x40f5
OP_SelectTribute=0x79fc
OP_TributeItem=0x4f3e
OP_TributeMoney=0x58fb # Was 0x6fed
OP_TributeToggle=0x241d
OP_TributePointUpdate=0x5300
OP_TributeNPC=0x0000
OP_GuildTributeInfo=0x0000
OP_OpenTributeReply=0x0000
OP_GuildTributeStatus=0x0000
# Adventure packets:
OP_LeaveAdventure=0x5d18
OP_AdventureFinish=0x400f
OP_AdventureInfoRequest=0x3cb0
OP_AdventureInfo=0x4c54
OP_AdventureRequest=0x2c6c
OP_AdventureDetails=0x5648
OP_AdventureData=0x7171
OP_AdventureUpdate=0x1b01
OP_AdventureMerchantRequest=0x6922 # Was 654d
OP_AdventureMerchantResponse=0x3e47 # Was 7949
OP_AdventureMerchantPurchase=0x5b72 # Was 155a
OP_AdventureMerchantSell=0x2f9b # Was 389c
OP_AdventurePointsUpdate=0x65c3 # Was 7589
OP_AdventureStatsRequest=0x5a62
OP_AdventureStatsReply=0x2370
OP_AdventureLeaderboardRequest=0x7093
OP_AdventureLeaderboardReply=0x7f79
# Group Opcodes
OP_GroupDisband=0x4c10
OP_GroupInvite=0x1649
OP_GroupFollow=0x05ce
OP_GroupUpdate=0x3abb
OP_GroupUpdateB=0x6194
OP_GroupCancelInvite=0x0000
OP_GroupAcknowledge=0x7323
OP_GroupDelete=0x0f6c
OP_CancelInvite=0x32c2
OP_GroupFollow2=0x2a50
OP_GroupInvite2=0x6c65
OP_GroupDisbandYou=0x1ae5
OP_GroupDisbandOther=0x74da
OP_GroupLeaderChange=0x21b4
OP_GroupRoles=0x70e2
OP_GroupMakeLeader=0x4229
OP_DoGroupLeadershipAbility=0x1fb5
OP_GroupLeadershipAAUpdate=0x02cf
OP_GroupMentor=0x5892
OP_InspectBuffs=0x486c
# LFG/LFP Opcodes
OP_LFGCommand=0x6060
OP_LFGGetMatchesRequest=0x0340
OP_LFGGetMatchesResponse=0x5048
OP_LFPGetMatchesRequest=0x4d7d
OP_LFPGetMatchesResponse=0x22c6
OP_LFPCommand=0x49a9
OP_LFGAppearance=0x0000
OP_LFGResponse=0x0000
# Raid Opcodes
OP_RaidInvite=0x55ac
OP_RaidUpdate=0x3973
OP_RaidJoin=0x0000
# Button-push commands
OP_Taunt=0x2703
OP_CombatAbility=0x3eba
OP_SenseTraps=0x02af # Was 0x2ee0
OP_PickPocket=0x39e8
OP_DisarmTraps=0x78bf
OP_Disarm=0x5ec8
OP_Sneak=0x5d55
OP_Fishing=0x1e2a
OP_InstillDoubt=0x640e
OP_FeignDeath=0x52fa
OP_Mend=0x0ecf
OP_Bind_Wound=0x0386
OP_LDoNOpen=0x3d5c
# Task packets
OP_TaskDescription=0x083
OP_TaskActivity=0x3714
OP_CompletedTasks=0x4eba
OP_TaskActivityComplete=0x5e19
OP_AcceptNewTask=0x0a23
OP_CancelTask=0x08d3
OP_TaskMemberList=0x5727 # Was 0x1656
OP_OpenNewTasksWindow=0x48a2 # Was 0x11de
OP_AvaliableTask=0x36e8 # Was 0x2377
OP_TaskHistoryRequest=0x5f1c
OP_TaskHistoryReply=0x3d05
OP_DeclineAllTasks=0x0000
# Title opcodes
OP_NewTitlesAvailable=0x0d32
OP_RequestTitles=0x6344
OP_SendTitleList=0x2d08
OP_SetTitle=0x6527
OP_SetTitleReply=0x4c21
# mail opcodes
OP_Command=0x0000
OP_MailboxHeader=0x0000
OP_MailHeader=0x0000
OP_MailBody=0x0000
OP_NewMail=0x0000
OP_SentConfirm=0x0000
########### Below this point should not be needed ###########
# This section are all unknown in Titanium
OP_ForceFindPerson=0x0000
OP_LocInfo=0x0000
OP_ReloadUI=0x0000
OP_ItemName=0x0000
OP_ItemLinkText=0x0000
OP_MultiLineMsg=0x0000
OP_MendHPUpdate=0x0000
OP_TargetReject=0x0000
OP_SafePoint=0x0000
OP_ApproveZone=0x0000
OP_ZoneComplete=0x0000
OP_ClientError=0x0000
OP_DumpName=0x0000
OP_Heartbeat=0x0000
OP_CrashDump=0x0000
OP_LoginComplete=0x0000
# discovered opcodes not yet used:
OP_PickLockSuccess=0x0000
OP_PlayMP3=0x0000
OP_ReclaimCrystals=0x0000
OP_DynamicWall=0x0000
OP_OpenDiscordMerchant=0x0000
OP_DiscordMerchantInventory=0x0000
OP_GiveMoney=0x0000
OP_RequestKnowledgeBase=0x0000
OP_KnowledgeBase=0x0000
OP_SlashAdventure=0x0000 # /adventure
OP_BecomePVPPrompt=0x0000
OP_MoveLogRequest=0x0000 # gone I think
OP_MoveLogDisregard=0x0000 # gone I think
# named unknowns, to make looking for real unknown easier
OP_AnnoyingZoneUnknown=0x0000
OP_Some6ByteHPUpdate=0x0000 seems to happen when you target group members
OP_QueryResponseThing=0x0000
# realityincarnate: these are just here to stop annoying several thousand byte packet dumps
#OP_LoginUnknown1=0x46d3 # OP_SendSpellChecksum
#OP_LoginUnknown2=0x040b # OP_SendSkillCapsChecksum
# Petition Opcodes
OP_PetitionSearch=0x0000 search term for petition
OP_PetitionSearchResults=0x0000 (list of?) matches from search
OP_PetitionSearchText=0x0000 text results of search
OP_PetitionUpdate=0x0000
OP_PetitionCheckout=0x0000
OP_PetitionCheckIn=0x0000
OP_PetitionQue=0x0000
OP_PetitionUnCheckout=0x0000
OP_PetitionDelete=0x0000
OP_DeletePetition=0x0000
OP_PetitionResolve=0x0000
OP_PDeletePetition=0x0000
OP_PetitionBug=0x0000
OP_PetitionRefresh=0x0000
OP_PetitionCheckout2=0x0000
OP_PetitionViewPetition=0x0000
# Login opcodes
OP_SessionReady=0x0000
OP_Login=0x0000
OP_ServerListRequest=0x0000
OP_PlayEverquestRequest=0x0000
OP_PlayEverquestResponse=0x0000
OP_ChatMessage=0x0000
OP_LoginAccepted=0x0000
OP_ServerListResponse=0x0000
OP_Poll=0x0000
OP_EnterChat=0x0000
OP_PollResponse=0x0000
# raw opcodes
OP_RAWSessionRequest=0x0000
OP_RAWSessionResponse=0x0000
OP_RAWCombined=0x0000
OP_RAWSessionDisconnect=0x0000
OP_RAWKeepAlive=0x0000
OP_RAWSessionStatRequest=0x0000
OP_RAWSessionStatResponse=0x0000
OP_RAWPacket=0x0000
OP_RAWFragment=0x0000
OP_RAWOutOfOrderAck=0x0000
OP_RAWAck=0x0000
OP_RAWAppCombined=0x0000
OP_RAWOutOfSession=0x0000
# we need to document the differences between these packets to make identifying them easier
OP_Some3ByteHPUpdate=0x0000 # initial HP update for mobs
OP_InitialHPUpdate=0x0000
OP_ItemRecastDelay=0x08a6

View File

@ -0,0 +1,661 @@
# ShowEQ Import Notes:
# ZERO THE FILE first
# perl -pi -e 's/0x[0-9a-fA-F]{4}/0x0000/g' opcodes.conf
# Unknown Mapping:
# OP_Action2 -> OP_Damage
# OP_EnvDamage -> OP_Damage ---> might have been a one time mistake
# Name Differences:
# OP_CancelInvite -> OP_GroupCancelInvite
# OP_GMFind -> OP_FindPersonRequest
# OP_CommonMessage -> OP_ChannelMessage
OP_Unknown=0x0000
OP_ExploreUnknown=0x0000 used for unknown explorer
# world packets
# Required to reach Char Select:
OP_SendLoginInfo=0x7a09
OP_ApproveWorld=0x7499
OP_LogServer=0x7ceb
OP_SendCharInfo=0x00d2
OP_ExpansionInfo=0x590d
OP_GuildsList=0x7056
OP_EnterWorld=0x0641
OP_PostEnterWorld=0x6259
OP_World_Client_CRC1=0x12cc
OP_World_Client_CRC2=0x0f13
OP_SendSpellChecksum=0x0000
OP_SendSkillCapsChecksum=0x0000
# Character Select Related:
OP_SendMaxCharacters=0x05a8
OP_SendMembership=0x057b
OP_SendMembershipDetails=0x6a98
OP_CharacterCreateRequest=0x655c
OP_CharacterCreate=0x6bbf
OP_DeleteCharacter=0x1808
OP_RandomNameGenerator=0x5954
OP_ApproveName=0x56a2
OP_MOTD=0x0c22
OP_SetChatServer=0x1bc5
OP_SetChatServer2=0x7db5
OP_ZoneServerInfo=0x6ef5
OP_WorldComplete=0x4493
OP_WorldUnknown001=0x2958
OP_FloatListThing=0x46c6
# Reasons for Disconnect:
OP_ZoneUnavail=0x4c44
OP_WorldClientReady=0x23c1
OP_CharacterStillInZone=0x0000
OP_WorldChecksumFailure=0x0000
OP_WorldLoginFailed=0x0000
OP_WorldLogout=0x0000
OP_WorldLevelTooHigh=0x0000
OP_CharInacessable=0x0000
OP_UserCompInfo=0x0000
OP_SendExeChecksum=0x0000
OP_SendBaseDataChecksum=0x0000
# Zone in opcodes
OP_AckPacket=0x471d
OP_ZoneEntry=0x5089
OP_ReqNewZone=0x7887
OP_NewZone=0x1795
OP_ZoneSpawns=0x5237
OP_PlayerProfile=0x6506
OP_TimeOfDay=0x5070
OP_LevelUpdate=0x1eec
OP_Stamina=0x2a79
OP_RequestClientZoneChange=0x3fcf
OP_ZoneChange=0x2d18
OP_LockoutTimerInfo=0x0000
OP_ZoneServerReady=0x0000
OP_ZoneInUnknown=0x0000
OP_LogoutReply=0x0000
OP_PreLogoutReply=0x0000
# Required to fully log in
OP_SpawnAppearance=0x0971
OP_ChangeSize=0x4707
OP_TributeUpdate=0x5961
OP_TributeTimer=0x073d
OP_SendTributes=0x729b
OP_SendGuildTributes=0x4d5e
OP_TributeInfo=0x4254
OP_Weather=0x661e
OP_ReqClientSpawn=0x35fa
OP_SpawnDoor=0x7291
OP_GroundSpawn=0x6fca
OP_SendZonepoints=0x69a4
OP_BlockedBuffs=0x4d25
OP_RemoveBlockedBuffs=0x3033
OP_ClearBlockedBuffs=0x6b3d
OP_WorldObjectsSent=0x5ae2
OP_SendExpZonein=0x5f8e
OP_SendAATable=0x66b5
OP_RespondAA=0x7a27
OP_UpdateAA=0x66f0
OP_SendAAStats=0x43c8
OP_AAExpUpdate=0x7e92
OP_ExpUpdate=0x20ed
OP_HPUpdate=0x2828
OP_ManaChange=0x1287
OP_TGB=0x0000
OP_SpecialMesg=0x0000
OP_GuildMemberList=0x0e48
OP_GuildMOTD=0x3e13
OP_CharInventory=0x5ca6
OP_WearChange=0x7994
OP_ClientUpdate=0x7dfc
OP_ClientReady=0x345d # 0x422d
OP_SetServerFilter=0x444d
# Guild Opcodes - Disabled until crashes are resolved in RoF
OP_GetGuildMOTD=0x36e0 # Was 0x35dc
OP_GetGuildMOTDReply=0x4f1f # Was 0x4586
OP_GuildMemberUpdate=0x69b9 # Was 0x5643
OP_GuildInvite=0x7099
OP_GuildRemove=0x1444
OP_GuildPeace=0x084e
OP_SetGuildMOTD=0x0b0b
OP_GuildList=0x0000
OP_GuildWar=0x46ce
OP_GuildLeader=0x2f3e
OP_GuildDelete=0x3708
OP_GuildInviteAccept=0x7053
OP_GuildDemote=0x2d4e
OP_GuildPromote=0x0000
OP_GuildPublicNote=0x5053
OP_GuildManageBanker=0x748f # Was 0x0737
OP_GuildBank=0x5134 # Was 0x10c3
OP_SetGuildRank=0x0b9c
OP_GuildUpdateURLAndChannel=0x6084
OP_GuildStatus=0x7326
OP_GuildCreate=0x1dc8 # or maybe 0x086e
OP_GuildMemberLevelUpdate=0x0000 # Unused?
OP_ZoneGuildList=0x0000 # Unused?
OP_GetGuildsList=0x0000 # Unused?
OP_LFGuild=0x0000
OP_GuildManageRemove=0x0000
OP_GuildManageAdd=0x0000
OP_GuildManageStatus=0x0000
# GM/Guide Opcodes
OP_GMServers=0x08c1
OP_GMBecomeNPC=0x3ae1
OP_GMZoneRequest=0x62ac
OP_GMZoneRequest2=0x7e1a
OP_GMGoto=0x7d8e
OP_GMSearchCorpse=0x46b1
OP_GMHideMe=0x79c5
OP_GMDelCorpse=0x607e
OP_GMApproval=0x6db5
OP_GMToggle=0x2097
OP_GMSummon=0x486f # Was 0x684f
OP_GMEmoteZone=0x1cfd # Was 0x0655
OP_GMEmoteWorld=0x458e # Was 0x1935
OP_GMFind=0x4a8f
OP_GMKick=0x26a7
OP_GMKill=0x51d3
OP_GMNameChange=0x035f # Was 0x4434
OP_GMLastName=0x16ce # Was 0x3077
# Misc Opcodes
OP_InspectRequest=0x57bc
OP_InspectAnswer=0x71ac
OP_InspectMessageUpdate=0x6f8b
OP_BeginCast=0x318f
OP_ColoredText=0x0000
OP_ConsentResponse=0x384a
OP_MemorizeSpell=0x6a0d
OP_SwapSpell=0x0efa
OP_CastSpell=0x4466
OP_Consider=0x742b
OP_FormattedMessage=0x1024
OP_SimpleMessage=0x213f
OP_Buff=0x3a54
OP_Illusion=0x312a
OP_MoneyOnCorpse=0x5f44
OP_RandomReply=0x106b
OP_DenyResponse=0x2382
OP_SkillUpdate=0x2264
OP_GMTrainSkillConfirm=0x19aa # 0x3960
OP_RandomReq=0x7b10
OP_Death=0x6517
OP_GMTraining=0x1966
OP_GMEndTraining=0x4d6b
OP_GMTrainSkill=0x2a85
OP_Animation=0x7177
OP_Begging=0x6703
OP_Consent=0x1fd1
OP_ConsentDeny=0x7a45
OP_AutoFire=0x241e
OP_PetCommands=0x0159
OP_DeleteSpell=0x52e5
OP_Surname=0x0423
OP_ClearSurname=0x7d23
OP_FaceChange=0x5578
OP_SenseHeading=0x217c
OP_Action=0x744c
OP_ConsiderCorpse=0x5204
OP_HideCorpse=0x67fc
OP_CorpseDrag=0x7eec
OP_CorpseDrop=0x0904
OP_Bug=0x73f4
OP_Feedback=0x5602
OP_Report=0x1414
OP_Damage=0x6f15
OP_ChannelMessage=0x2b2d
OP_Assist=0x4478
OP_AssistGroup=0x27f8
OP_MoveCoin=0x0bcf
OP_ZonePlayerToBind=0x0ecb
OP_KeyRing=0x6857
OP_WhoAllRequest=0x65ab
OP_WhoAllResponse=0x407a
OP_FriendsWho=0x3956
OP_ConfirmDelete=0x43a3
OP_Logout=0x4ac6
OP_Rewind=0x1745
OP_TargetCommand=0x58e2
OP_Hide=0x5d55
OP_Jump=0x2060
OP_Camp=0x28ec
OP_Emote=0x373b
OP_SetRunMode=0x009f
OP_BankerChange=0x383c
OP_TargetMouse=0x075d
OP_MobHealth=0x2dd3
OP_InitialMobHealth=0x0000 # Unused?
OP_TargetHoTT=0x486c
OP_XTargetResponse=0x4d59
OP_XTargetRequest=0x3763
OP_XTargetAutoAddHaters=0x672f
OP_TargetBuffs=0x4f4b
OP_BuffCreate=0x3377
OP_BuffRemoveRequest=0x49bc
OP_DeleteSpawn=0x7280
OP_AutoAttack=0x109d
OP_AutoAttack2=0x3526
OP_Consume=0x4b70
OP_MoveItem=0x32ee
OP_DeleteItem=0x18ad
OP_DeleteCharge=0x01b8
OP_ItemPacket=0x368e
OP_ItemLinkResponse=0x70c0
OP_ItemLinkClick=0x4cef
OP_ItemPreview=0x7f80
OP_NewSpawn=0x0b04
OP_Track=0x17e5
OP_TrackTarget=0x0029
OP_TrackUnknown=0x0f83
OP_ClickDoor=0x3a8f
OP_MoveDoor=0x08e8
OP_RemoveAllDoors=0x700c
OP_EnvDamage=0x51fd
OP_BoardBoat=0x31e6
OP_Forage=0x5306
OP_LeaveBoat=0x4211
OP_ControlBoat=0x0ae7
OP_SafeFallSuccess=0x6dbc
OP_RezzComplete=0x760d
OP_RezzRequest=0x3c21
OP_RezzAnswer=0x701c
OP_Shielding=0x48c1
OP_RequestDuel=0x3af1
OP_MobRename=0x2c57
OP_AugmentItem=0x661b # Was 0x37cb
OP_WeaponEquip1=0x34a7
OP_WeaponEquip2=0x559a # Was 0x6022
OP_WeaponUnequip2=0x2d25 # Was 0x0110
OP_ApplyPoison=0x1b0c
OP_Save=0x4a39
OP_TestBuff=0x7cb8 # Was 0x3772
OP_CustomTitles=0x100e
OP_Split=0x0522
OP_YellForHelp=0x4e56
OP_LoadSpellSet=0x261d
OP_Bandolier=0x7677
OP_PotionBelt=0x1a3e # Was 0x4d3b
OP_DuelResponse=0x6a46
OP_DuelResponse2=0x68d3
OP_SaveOnZoneReq=0x2c7a
OP_ReadBook=0x72df
OP_Dye=0x23b9
OP_InterruptCast=0x048c
OP_AAAction=0x424e
OP_LeadershipExpToggle=0x74bd
OP_LeadershipExpUpdate=0x4ee2
OP_PurchaseLeadershipAA=0x6c55
OP_UpdateLeadershipAA=0x0026
OP_MarkNPC=0x5a58
OP_MarkRaidNPC=0x0000 #unimplemented
OP_ClearNPCMarks=0x0272
OP_ClearRaidNPCMarks=0x0000 #unimplemented
OP_DelegateAbility=0x4c9d
OP_SetGroupTarget=0x026
OP_Charm=0x5d92
OP_Stun=0x36a4
OP_SendFindableNPCs=0x587e
OP_FindPersonRequest=0x5cea
OP_FindPersonReply=0x7e58
OP_Sound=0x1a30
OP_PetBuffWindow=0x5882
OP_LevelAppearance=0x3bc9
OP_Translocate=0x6580
OP_Sacrifice=0x1821
OP_PopupResponse=0x214a
OP_OnLevelMessage=0x4fd0
OP_AugmentInfo=0x0afb
OP_Petition=0x4101
OP_SomeItemPacketMaybe=0x747c
OP_PVPStats=0x6f4b # Unsure
OP_PVPLeaderBoardRequest=0x3707
OP_PVPLeaderBoardReply=0x25b7
OP_PVPLeaderBoardDetailsRequest=0x15a9
OP_PVPLeaderBoardDetailsReply=0x04aa
OP_RestState=0x000f
OP_RespawnWindow=0x28bc
OP_LDoNButton=0x5327
OP_SetStartCity=0x6326 # Was 0x2d1b
OP_VoiceMacroIn=0x17fd
OP_VoiceMacroOut=0x409a
OP_ItemViewUnknown=0x465b
OP_VetRewardsAvaliable=0x6773
OP_VetClaimRequest=0x1126
OP_VetClaimReply=0x16d4
OP_DisciplineUpdate=0x759e # Was 0x2f05
OP_DisciplineTimer=0x6989 # Was 0x5e3f
OP_BecomeCorpse=0x0000 # Unused?
OP_Action2=0x0000 # Unused?
OP_MobUpdate=0x2c84
OP_NPCMoveUpdate=0x5892
OP_CameraEffect=0x127f
OP_SpellEffect=0x5936
OP_RemoveNimbusEffect=0xc693
OP_AltCurrency=0x3ee6
OP_AltCurrencyMerchantRequest=0x05f0
OP_AltCurrencyMerchantReply=0x0165
OP_AltCurrencyPurchase=0x6b6d
OP_AltCurrencySell=0x61cb
OP_AltCurrencySellSelection=0x74ec
OP_AltCurrencyReclaim=0x27a2
OP_CrystalCountUpdate=0x467f # Was 0x3f60
OP_CrystalCreate=0x7aee # Was 0x5a82
OP_CrystalReclaim=0x2439 # Was 0x7616
OP_Untargetable=0x1456
OP_IncreaseStats=0x70a3
OP_Weblink=0x18d3
#OP_OpenInventory=0x0000 # Likely does not exist in RoF -U
OP_OpenContainer=0x0000
OP_Marquee=0x0000
OP_DzQuit=0xb2e3
OP_DzListTimers=0x7b68
OP_DzAddPlayer=0x4701
OP_DzRemovePlayer=0x1abc
OP_DzSwapPlayer=0x405b
OP_DzMakeLeader=0x543d
OP_DzPlayerList=0x14c6
OP_DzJoinExpeditionConfirm=0x7f4b
OP_DzJoinExpeditionReply=0x1950
OP_DzExpeditionInfo=0x9119
OP_DzExpeditionList=0x205f
OP_DzMemberStatus=0x32f0
OP_DzLeaderStatus=0x3de9
OP_DzExpeditionEndsWarning=0x5189
OP_DzMemberList=0x0000
OP_DzCompass=0x3e0e # Was 0x4f09
OP_DzChooseZone=0x0000 # Maybe 0x29d6
# New Opcodes
OP_SpawnPositionUpdate=0x0000 # Actually OP_MobUpdate ?
OP_ManaUpdate=0x3791
OP_EnduranceUpdate=0x5f42
OP_MobManaUpdate=0x2925
OP_MobEnduranceUpdate=0x7314
# Mercenary Opcodes
OP_MercenaryDataUpdateRequest=0x2bcb
OP_MercenaryDataUpdate=0x7b89
OP_MercenaryDataRequest=0x61a4
OP_MercenaryDataResponse=0x11c1
OP_MercenaryHire=0x72ce
OP_MercenaryDismiss=0x7169
OP_MercenaryTimerRequest=0x6e83
OP_MercenaryTimer=0x31e4
OP_MercenaryUnknown1=0x20b9
OP_MercenaryCommand=0x1b37
OP_MercenarySuspendRequest=0x6e9f
OP_MercenarySuspendResponse=0x4407
OP_MercenaryUnsuspendResponse=0x6f03
# Looting
OP_LootRequest=0x0adf
OP_EndLootRequest=0x30f7
OP_LootItem=0x4dc9
OP_LootComplete=0x55c4
# bazaar trader stuff:
OP_BazaarSearch=0x39d6
OP_TraderDelItem=0x0000
OP_BecomeTrader=0x61b3
OP_TraderShop=0x5eca
OP_Trader=0x4ef5 # Was 0x6790
OP_TraderBuy=0x0000
OP_Barter=0x243a
OP_ShopItem=0x0000
OP_BazaarInspect=0x0000
OP_Bazaar=0x0000
OP_TraderItemUpdate=0x0000
# pc/npc trading
OP_TradeRequest=0x77b5
OP_TradeAcceptClick=0x69e2
OP_TradeRequestAck=0x14bf
OP_TradeCoins=0x4206
OP_FinishTrade=0x3993
OP_CancelTrade=0x354c
OP_TradeMoneyUpdate=0x68c2
OP_MoneyUpdate=0x640c
OP_TradeBusy=0x5505
# Sent after canceling trade or after closing tradeskill object
OP_FinishWindow=0x7349
OP_FinishWindow2=0x40ef
# Sent on Live for what seems to be item existance verification
# Ex. Before Right Click Effect happens from items
OP_ItemVerifyRequest=0x189c
OP_ItemVerifyReply=0x097b
# merchant stuff
OP_ShopPlayerSell=0x3de3
OP_ShopRequest=0x4fed
OP_ShopEnd=0x30a8
OP_ShopEndConfirm=0x3196
OP_ShopPlayerBuy=0x004c
OP_ShopDelItem=0x724f
# tradeskill stuff:
OP_ClickObject=0x4aa1
OP_ClickObjectAction=0x0c1e
OP_ClearObject=0x7a11
OP_RecipeDetails=0x6e02
OP_RecipesFavorite=0x5c74
OP_RecipesSearch=0x6290
OP_RecipeReply=0x1db6
OP_RecipeAutoCombine=0x40d7
OP_TradeSkillCombine=0x579a
# Tribute Packets:
OP_OpenGuildTributeMaster=0x49ea
OP_OpenTributeMaster=0x7666 # Was 0x40f5
OP_SelectTribute=0x79fc
OP_TributeItem=0x4f3e
OP_TributeMoney=0x58fb # Was 0x6fed
OP_TributeToggle=0x4e32
OP_TributePointUpdate=0x5300
OP_TributeNPC=0x0000
OP_GuildTributeInfo=0x0000
OP_OpenTributeReply=0x0000
OP_GuildTributeStatus=0x0000
# Adventure packets:
OP_LeaveAdventure=0x5d18
OP_AdventureFinish=0x400f
OP_AdventureInfoRequest=0x3cb0
OP_AdventureInfo=0x4c54
OP_AdventureRequest=0x2c6c
OP_AdventureDetails=0x5648
OP_AdventureData=0x7171
OP_AdventureUpdate=0x1b01
OP_AdventureMerchantRequest=0x6922 # Was 654d
OP_AdventureMerchantResponse=0x3e47 # Was 7949
OP_AdventureMerchantPurchase=0x5b72 # Was 155a
OP_AdventureMerchantSell=0x2f9b # Was 389c
OP_AdventurePointsUpdate=0x65c3 # Was 7589
OP_AdventureStatsRequest=0x5a62
OP_AdventureStatsReply=0x2370
OP_AdventureLeaderboardRequest=0x7093
OP_AdventureLeaderboardReply=0x7f79
# Group Opcodes
OP_GroupDisband=0x4c10
OP_GroupInvite=0x1649
OP_GroupFollow=0x05ce
OP_GroupUpdate=0x4ced
OP_GroupUpdateB=0x0cbc
OP_GroupCancelInvite=0x0000
OP_GroupAcknowledge=0x04d0
OP_GroupDelete=0x3abb
OP_CancelInvite=0x32c2
OP_GroupFollow2=0x2a50
OP_GroupInvite2=0x6c65
OP_GroupDisbandYou=0x7323
OP_GroupDisbandOther=0x88a1
OP_GroupLeaderChange=0x74da
OP_GroupRoles=0x4d9f
OP_GroupMakeLeader=0x4229
OP_DoGroupLeadershipAbility=0x6eae
OP_GroupLeadershipAAUpdate=0x6298
OP_GroupMentor=0x3342
OP_InspectBuffs=0x0000
# LFG/LFP Opcodes
OP_LFGCommand=0x6060
OP_LFGGetMatchesRequest=0x0340
OP_LFGGetMatchesResponse=0x5048
OP_LFPGetMatchesRequest=0x4d7d
OP_LFPGetMatchesResponse=0x22c6
OP_LFPCommand=0x49a9
OP_LFGAppearance=0x0000
OP_LFGResponse=0x0000
# Raid Opcodes
OP_RaidInvite=0x3973
OP_RaidUpdate=0x56fe
OP_RaidJoin=0x0000
# Button-push commands
OP_Taunt=0x2703
OP_CombatAbility=0x3eba
OP_SenseTraps=0x02af # Was 0x2ee0
OP_PickPocket=0x39e8
OP_DisarmTraps=0x0000
OP_Disarm=0x5ec8
OP_Sneak=0x4577
OP_Fishing=0x1e2a
OP_InstillDoubt=0x640e
OP_FeignDeath=0x52fa
OP_Mend=0x0ecf
OP_Bind_Wound=0x0386
OP_LDoNOpen=0x3d5c
# Task packets
OP_TaskDescription=0x0083
OP_TaskActivity=0x083
OP_CompletedTasks=0x4eba
OP_TaskActivityComplete=0x7037
OP_AcceptNewTask=0x0a23
OP_CancelTask=0x3714
OP_TaskMemberList=0x5727 # Was 0x1656
OP_OpenNewTasksWindow=0x48a2 # Was 0x11de
OP_AvaliableTask=0x36e8 # Was 0x2377
OP_TaskHistoryRequest=0x5f1c
OP_TaskHistoryReply=0x3d05
OP_DeclineAllTasks=0x0000
# Title opcodes
OP_NewTitlesAvailable=0x0d32
OP_RequestTitles=0x6344
OP_SendTitleList=0x2d08
OP_SetTitle=0x6527
OP_SetTitleReply=0x4c21
# mail opcodes
OP_Command=0x0000
OP_MailboxHeader=0x0000
OP_MailHeader=0x0000
OP_MailBody=0x0000
OP_NewMail=0x0000
OP_SentConfirm=0x0000
########### Below this point should not be needed ###########
# This section are all unknown in Titanium
OP_ForceFindPerson=0x0000
OP_LocInfo=0x0000
OP_ReloadUI=0x0000
OP_ItemName=0x0000
OP_ItemLinkText=0x0000
OP_MultiLineMsg=0x0000
OP_MendHPUpdate=0x0000
OP_TargetReject=0x0000
OP_SafePoint=0x0000
OP_ApproveZone=0x0000
OP_ZoneComplete=0x0000
OP_ClientError=0x0000
OP_DumpName=0x0000
OP_Heartbeat=0x0000
OP_CrashDump=0x0000
OP_LoginComplete=0x0000
# discovered opcodes not yet used:
OP_PickLockSuccess=0x0000
OP_PlayMP3=0x0000
OP_ReclaimCrystals=0x0000
OP_DynamicWall=0x0000
OP_OpenDiscordMerchant=0x0000
OP_DiscordMerchantInventory=0x0000
OP_GiveMoney=0x0000
OP_RequestKnowledgeBase=0x0000
OP_KnowledgeBase=0x0000
OP_SlashAdventure=0x0000 # /adventure
OP_BecomePVPPrompt=0x0000
OP_MoveLogRequest=0x0000 # gone I think
OP_MoveLogDisregard=0x0000 # gone I think
# named unknowns, to make looking for real unknown easier
OP_AnnoyingZoneUnknown=0x0000
OP_Some6ByteHPUpdate=0x0000 seems to happen when you target group members
OP_QueryResponseThing=0x0000
# realityincarnate: these are just here to stop annoying several thousand byte packet dumps
#OP_LoginUnknown1=0x46d3 # OP_SendSpellChecksum
#OP_LoginUnknown2=0x040b # OP_SendSkillCapsChecksum
# Petition Opcodes
OP_PetitionSearch=0x0000 search term for petition
OP_PetitionSearchResults=0x0000 (list of?) matches from search
OP_PetitionSearchText=0x0000 text results of search
OP_PetitionUpdate=0x0000
OP_PetitionCheckout=0x0000
OP_PetitionCheckIn=0x0000
OP_PetitionQue=0x0000
OP_PetitionUnCheckout=0x0000
OP_PetitionDelete=0x0000
OP_DeletePetition=0x0000
OP_PetitionResolve=0x0000
OP_PDeletePetition=0x0000
OP_PetitionBug=0x0000
OP_PetitionRefresh=0x0000
OP_PetitionCheckout2=0x0000
OP_PetitionViewPetition=0x0000
# Login opcodes
OP_SessionReady=0x0000
OP_Login=0x0000
OP_ServerListRequest=0x0000
OP_PlayEverquestRequest=0x0000
OP_PlayEverquestResponse=0x0000
OP_ChatMessage=0x0000
OP_LoginAccepted=0x0000
OP_ServerListResponse=0x0000
OP_Poll=0x0000
OP_EnterChat=0x0000
OP_PollResponse=0x0000
# raw opcodes
OP_RAWSessionRequest=0x0000
OP_RAWSessionResponse=0x0000
OP_RAWCombined=0x0000
OP_RAWSessionDisconnect=0x0000
OP_RAWKeepAlive=0x0000
OP_RAWSessionStatRequest=0x0000
OP_RAWSessionStatResponse=0x0000
OP_RAWPacket=0x0000
OP_RAWFragment=0x0000
OP_RAWOutOfOrderAck=0x0000
OP_RAWAck=0x0000
OP_RAWAppCombined=0x0000
OP_RAWOutOfSession=0x0000
# we need to document the differences between these packets to make identifying them easier
OP_Some3ByteHPUpdate=0x0000 # initial HP update for mobs
OP_InitialHPUpdate=0x0000
OP_ItemRecastDelay=0x08a6

View File

@ -311,6 +311,8 @@
9055|2014_10_30_special_abilities_null.sql|SHOW COLUMNS FROM `npc_types` LIKE 'special_abilities'|contains|NO
9056|2014_11_08_RaidMembers.sql|SHOW COLUMNS FROM `raid_members` LIKE 'groupid'|missing|unsigned
9057|2014_11_13_spells_new_updates.sql|SHOW COLUMNS FROM `spells_new` LIKE 'disallow_sit'|empty|
9058|2014_11_26_InventoryTableUpdate.sql|SHOW COLUMNS FROM `inventory` LIKE 'ornamenticon'|empty|
9059|2014_12_01_mercs_table_update.sql|SHOW COLUMNS FROM `mercs` LIKE 'MercSize'|empty|
# Upgrade conditions:
# This won't be needed after this system is implemented, but it is used database that are not
@ -329,4 +331,4 @@
# not_empty = If the query is not empty
# 4 = Text to match
#
#
#

View File

@ -1 +1 @@
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'NPC:EnableMeritBasedFaction', 'false', 'If set to true, faction will given in the same way as experience (solo/group/raid).');
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'NPC:EnableMeritBasedFaction', 'false', 'If set to true, faction will be given in the same way as experience (solo/group/raid).');

View File

@ -0,0 +1,3 @@
/* Optional Transformation Rules */
INSERT INTO `rule_values` VALUES (1, 'Inventory:DeleteTransformationMold', 'true', 'false to keep transformation mold forever');
INSERT INTO `rule_values` VALUES (1, 'Inventory:AllowAnyWeaponTransformation', 'false', 'True allows any MELEE weapon to use the other melee type transformatios');

View File

@ -0,0 +1 @@
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Combat:ProjectileDmgOnImpact', 'true', 'If enabled, projectiles (ie arrows) will hit on impact, instead of instantly.');

View File

@ -0,0 +1,4 @@
-- Inventory table update
ALTER TABLE `inventory`
ADD COLUMN `ornamenticon` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `custom_data`,
ADD COLUMN `ornamentidfile` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `ornamenticon`;

View File

@ -0,0 +1 @@
ALTER TABLE `mercs` ADD `MercSize` float( 0 ) NOT NULL DEFAULT '5' AFTER `Gender`;

View File

@ -4,6 +4,7 @@
#include "../common/rulesys.h"
#include "../common/misc_functions.h"
#include "../common/string_util.h"
#include "../common/random.h"
#include "adventure.h"
#include "adventure_manager.h"
#include "worlddb.h"
@ -14,6 +15,7 @@
extern ZSList zoneserver_list;
extern ClientList client_list;
extern AdventureManager adventure_manager;
extern EQEmu::Random emu_random;
Adventure::Adventure(AdventureTemplate *t)
{
@ -54,10 +56,10 @@ void Adventure::AddPlayer(std::string character_name, bool add_client_to_instanc
{
if(!PlayerExists(character_name))
{
int client_id = database.GetCharacterID(character_name.c_str());
if(add_client_to_instance)
int32 character_id = database.GetCharacterID(character_name.c_str());
if(character_id && add_client_to_instance)
{
database.AddClientToInstance(instance_id, client_id);
database.AddClientToInstance(instance_id, character_id);
}
players.push_back(character_name);
}
@ -70,8 +72,12 @@ void Adventure::RemovePlayer(std::string character_name)
{
if((*iter).compare(character_name) == 0)
{
database.RemoveClientFromInstance(instance_id, database.GetCharacterID(character_name.c_str()));
players.erase(iter);
int32 character_id = database.GetCharacterID(character_name.c_str());
if (character_id)
{
database.RemoveClientFromInstance(instance_id, character_id);
players.erase(iter);
}
return;
}
++iter;
@ -388,8 +394,8 @@ void Adventure::MoveCorpsesToGraveyard()
for (auto iter = dbid_list.begin(); iter != dbid_list.end(); ++iter)
{
float x = GetTemplate()->graveyard_x + MakeRandomFloat(-GetTemplate()->graveyard_radius, GetTemplate()->graveyard_radius);
float y = GetTemplate()->graveyard_y + MakeRandomFloat(-GetTemplate()->graveyard_radius, GetTemplate()->graveyard_radius);
float x = GetTemplate()->graveyard_x + emu_random.Real(-GetTemplate()->graveyard_radius, GetTemplate()->graveyard_radius);
float y = GetTemplate()->graveyard_y + emu_random.Real(-GetTemplate()->graveyard_radius, GetTemplate()->graveyard_radius);
float z = GetTemplate()->graveyard_z;
query = StringFormat("UPDATE character_corpses "

View File

@ -3,6 +3,7 @@
#include "../common/string_util.h"
#include "../common/servertalk.h"
#include "../common/rulesys.h"
#include "../common/random.h"
#include "adventure.h"
#include "adventure_manager.h"
#include "worlddb.h"
@ -14,6 +15,7 @@
extern ZSList zoneserver_list;
extern ClientList client_list;
extern EQEmu::Random emu_random;
AdventureManager::AdventureManager()
{
@ -325,7 +327,7 @@ void AdventureManager::CalculateAdventureRequestReply(const char *data)
if(eligible_adventures.size() > 0)
{
ea_iter = eligible_adventures.begin();
int c_index = MakeRandomInt(0, (eligible_adventures.size()-1));
int c_index = emu_random.Int(0, (eligible_adventures.size()-1));
for(int i = 0; i < c_index; ++i)
{
++ea_iter;

View File

@ -15,6 +15,7 @@
#include "../common/extprofile.h"
#include "../common/string_util.h"
#include "../common/clientversions.h"
#include "../common/random.h"
#include "client.h"
#include "worlddb.h"
@ -61,6 +62,7 @@ std::vector<RaceClassCombos> character_create_race_class_combos;
extern ZSList zoneserver_list;
extern LoginServerList loginserverlist;
extern ClientList client_list;
extern EQEmu::Random emu_random;
extern uint32 numclients;
extern volatile bool RunLoops;
@ -519,7 +521,7 @@ bool Client::HandleGenerateRandomNamePacket(const EQApplicationPacket *app) {
char cons[48]="bcdfghjklmnpqrstvwxzybcdgklmnprstvwbcdgkpstrkd";
char rndname[17]="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
char paircons[33]="ngrkndstshthphsktrdrbrgrfrclcr";
int rndnum=MakeRandomInt(0, 75),n=1;
int rndnum=emu_random.Int(0, 75),n=1;
bool dlc=false;
bool vwl=false;
bool dbl=false;
@ -540,18 +542,18 @@ bool Client::HandleGenerateRandomNamePacket(const EQApplicationPacket *app) {
rndname[0]=vowels[rndnum];
vwl=true;
}
int namlen=MakeRandomInt(5, 10);
int namlen=emu_random.Int(5, 10);
for (int i=n;i<namlen;i++)
{
dlc=false;
if (vwl) //last char was a vowel
{ // so pick a cons or cons pair
rndnum=MakeRandomInt(0, 62);
rndnum=emu_random.Int(0, 62);
if (rndnum>46)
{ // pick a cons pair
if (i>namlen-3) // last 2 chars in name?
{ // name can only end in cons pair "rk" "st" "sh" "th" "ph" "sk" "nd" or "ng"
rndnum=MakeRandomInt(0, 7)*2;
rndnum=emu_random.Int(0, 7)*2;
}
else
{ // pick any from the set
@ -569,12 +571,12 @@ bool Client::HandleGenerateRandomNamePacket(const EQApplicationPacket *app) {
}
else
{ // select a vowel
rndname[i]=vowels[MakeRandomInt(0, 16)];
rndname[i]=vowels[emu_random.Int(0, 16)];
}
vwl=!vwl;
if (!dbl && !dlc)
{ // one chance at double letters in name
if (!MakeRandomInt(0, i+9)) // chances decrease towards end of name
if (!emu_random.Int(0, i+9)) // chances decrease towards end of name
{
rndname[i+1]=rndname[i];
dbl=true;
@ -831,7 +833,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
QueuePacket(outapp);
safe_delete(outapp);
int MailKey = MakeRandomInt(1, INT_MAX);
int MailKey = emu_random.Int(1, INT_MAX);
database.SetMailKey(charid, GetIP(), MailKey);
@ -1242,8 +1244,8 @@ void Client::ZoneUnavail() {
bool Client::GenPassKey(char* key) {
char* passKey=nullptr;
*passKey += ((char)('A'+((int)MakeRandomInt(0, 25))));
*passKey += ((char)('A'+((int)MakeRandomInt(0, 25))));
*passKey += ((char)('A'+((int)emu_random.Int(0, 25))));
*passKey += ((char)('A'+((int)emu_random.Int(0, 25))));
memcpy(key, passKey, strlen(passKey));
return true;
}

View File

@ -69,6 +69,7 @@
#include "../common/emu_tcp_server.h"
#include "../common/patches/patches.h"
#include "../common/random.h"
#include "zoneserver.h"
#include "console.h"
#include "login_server.h"
@ -97,6 +98,7 @@ UCSConnection UCSLink;
QueryServConnection QSLink;
LauncherList launcher_list;
AdventureManager adventure_manager;
EQEmu::Random emu_random;
volatile bool RunLoops = true;
uint32 numclients = 0;
uint32 numzones = 0;

View File

@ -197,6 +197,9 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct*
if (item->GetOrnamentationAug(ornamentationAugtype)) {
idfile = atoi(&item->GetOrnamentationAug(ornamentationAugtype)->GetItem()->IDFile[2]);
}
else if (item->GetOrnamentationIcon() && item->GetOrnamentationIDFile()) {
idfile = item->GetOrnamentationIDFile();
}
else {
idfile = atoi(&item->GetItem()->IDFile[2]);
}

View File

@ -24,10 +24,12 @@
#include "world_config.h"
#include "../common/servertalk.h"
#include "../common/string_util.h"
#include "../common/random.h"
extern uint32 numzones;
extern bool holdzones;
extern ConsoleList console_list;
extern EQEmu::Random emu_random;
void CatchSignal(int sig_num);
ZSList::ZSList()
@ -565,7 +567,7 @@ void ZSList::RebootZone(const char* ip1,uint16 port,const char* ip2, uint32 skip
safe_delete(tmp);
return;
}
uint32 z = MakeRandomInt(0, y-1);
uint32 z = emu_random.Int(0, y-1);
ServerPacket* pack = new ServerPacket(ServerOP_ZoneReboot, sizeof(ServerZoneReboot_Struct));
ServerZoneReboot_Struct* s = (ServerZoneReboot_Struct*) pack->pBuffer;

View File

@ -16,84 +16,34 @@ Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net)
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
// Test 1
#include <iostream>
#include "../common/debug.h"
#include "aa.h"
#include "mob.h"
#include "client.h"
#include "groups.h"
#include "raids.h"
#include "../common/spdat.h"
#include "object.h"
#include "doors.h"
#include "beacon.h"
#include "corpse.h"
#include "titles.h"
#include "../common/races.h"
#include "../common/classes.h"
#include "../common/debug.h"
#include "../common/eq_packet_structs.h"
#include "../common/packet_dump.h"
#include "../common/races.h"
#include "../common/spdat.h"
#include "../common/string_util.h"
#include "../common/logsys.h"
#include "zonedb.h"
#include "string_ids.h"
#include "aa.h"
#include "client.h"
#include "corpse.h"
#include "groups.h"
#include "mob.h"
#include "queryserv.h"
#include "raids.h"
#include "string_ids.h"
#include "titles.h"
#include "zonedb.h"
extern QueryServ* QServ;
//static data arrays, really not big enough to warrant shared mem.
AA_DBAction AA_Actions[aaHighestID][MAX_AA_ACTION_RANKS]; //[aaid][rank]
std::map<uint32,SendAA_Struct*>aas_send;
std::map<uint32, std::map<uint32, AA_Ability> > aa_effects; //stores the effects from the aa_effects table in memory
std::map<uint32, AALevelCost_Struct> AARequiredLevelAndCost;
/*
Schema:
spell_id is spell to cast, SPELL_UNKNOWN == no spell
nonspell_action is action to preform on activation which is not a spell, 0=none
nonspell_mana is mana that the nonspell action consumes
nonspell_duration is a duration which may be used by the nonspell action
redux_aa is the aa which reduces the reuse timer of the skill
redux_rate is the multiplier of redux_aa, as a percentage of total rate (10 == 10% faster)
CREATE TABLE aa_actions (
aaid mediumint unsigned not null,
rank tinyint unsigned not null,
reuse_time mediumint unsigned not null,
spell_id mediumint unsigned not null,
target tinyint unsigned not null,
nonspell_action tinyint unsigned not null,
nonspell_mana mediumint unsigned not null,
nonspell_duration mediumint unsigned not null,
redux_aa mediumint unsigned not null,
redux_rate tinyint not null,
PRIMARY KEY(aaid, rank)
);
CREATE TABLE aa_swarmpets (
spell_id mediumint unsigned not null,
count tinyint unsigned not null,
npc_id int not null,
duration mediumint unsigned not null,
PRIMARY KEY(spell_id)
);
*/
/*
Credits for this function:
-FatherNitwit: Structure and mechanism
-Wiz: Initial set of AAs, original function contents
-Branks: Much updated info and a bunch of higher-numbered AAs
*/
int Client::GetAATimerID(aaID activate)
{
SendAA_Struct* aa2 = zone->FindAA(activate);

View File

@ -2,7 +2,8 @@
#ifndef AA_H
#define AA_H
#include "../common/eq_packet_structs.h"
struct AA_Ability;
struct SendAA_Struct;
#define MANA_BURN 664

View File

@ -329,7 +329,7 @@ bool Mob::CheckWillAggro(Mob *mob) {
||
(
fv == FACTION_THREATENLY
&& MakeRandomInt(0,99) < THREATENLY_ARRGO_CHANCE - heroicCHA_mod
&& zone->random.Roll(THREATENLY_ARRGO_CHANCE - heroicCHA_mod)
)
)
)
@ -1254,7 +1254,7 @@ bool Mob::PassCharismaCheck(Mob* caster, Mob* spellTarget, uint16 spell_id) {
return true;
//1: The mob has a default 25% chance of being allowed a resistance check against the charm.
if (MakeRandomInt(0, 99) > RuleI(Spells, CharmBreakCheckChance))
if (zone->random.Int(0, 99) > RuleI(Spells, CharmBreakCheckChance))
return true;
if (RuleB(Spells, CharismaCharmDuration))
@ -1273,7 +1273,7 @@ bool Mob::PassCharismaCheck(Mob* caster, Mob* spellTarget, uint16 spell_id) {
//3: At maxed ability, Total Domination has a 50% chance of preventing the charm break that otherwise would have occurred.
int16 TotalDominationBonus = caster->aabonuses.CharmBreakChance + caster->spellbonuses.CharmBreakChance + caster->itembonuses.CharmBreakChance;
if (MakeRandomInt(0, 99) < TotalDominationBonus)
if (zone->random.Int(0, 99) < TotalDominationBonus)
return true;
}

View File

@ -21,28 +21,22 @@
#endif
#include "../common/debug.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <iostream>
#include <assert.h>
#include "masterentity.h"
#include "npc_ai.h"
#include "../common/packet_dump.h"
#include "../common/eq_packet_structs.h"
#include "../common/eq_constants.h"
#include "../common/eq_packet_structs.h"
#include "../common/rulesys.h"
#include "../common/skills.h"
#include "../common/spdat.h"
#include "zone.h"
#include "string_ids.h"
#include "../common/string_util.h"
#include "../common/rulesys.h"
#include "queryserv.h"
#include "quest_parser_collection.h"
#include "string_ids.h"
#include "water_map.h"
#include "worldserver.h"
#include "queryserv.h"
#include "zone.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
extern QueryServ* QServ;
extern WorldServer worldserver;
@ -345,7 +339,7 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c
// Did we hit?
//
float tohit_roll = MakeRandomFloat(0, 100);
float tohit_roll = zone->random.Real(0, 100);
mlog(COMBAT__TOHIT, "Final hit chance: %.2f%%. Hit roll %.2f", chancetohit, tohit_roll);
@ -421,7 +415,7 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte)
//Live AA - HightenedAwareness
int BlockBehindChance = aabonuses.BlockBehind + spellbonuses.BlockBehind + itembonuses.BlockBehind;
if (BlockBehindChance && (BlockBehindChance > MakeRandomInt(1, 100))){
if (BlockBehindChance && zone->random.Roll(BlockBehindChance)) {
bBlockFromRear = true;
if (spellbonuses.BlockBehind || itembonuses.BlockBehind)
@ -514,7 +508,7 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte)
}
if(damage > 0){
roll = MakeRandomFloat(0,100);
roll = zone->random.Real(0,100);
if(roll <= RollTable[0]){
damage = -3;
}
@ -680,7 +674,7 @@ void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttac
if (acfail>100) acfail=100;
}
if (acfail<=0 || MakeRandomInt(0, 100)>acfail) {
if (acfail<=0 || zone->random.Int(0, 100)>acfail) {
float acreduction=1;
int acrandom=300;
if (database.GetVariable("ACreduction", tmp, 9))
@ -699,7 +693,7 @@ void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttac
damage -= (int32) (GetAC() * acreduction/100.0f);
}
if (acrandom>0) {
damage -= (myac * MakeRandomInt(0, acrandom) / 10000);
damage -= (myac * zone->random.Int(0, acrandom) / 10000);
}
if (damage<1) damage=1;
mlog(COMBAT__DAMAGE, "AC Damage Reduction: fail chance %d%%. Failed. Reduction %.3f%%, random %d. Resulting damage %d.", acfail, acreduction, acrandom, damage);
@ -727,8 +721,8 @@ int32 Mob::GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit,
float mit_rating, float atk_rating)
{
float d = 10.0;
float mit_roll = MakeRandomFloat(0, mit_rating);
float atk_roll = MakeRandomFloat(0, atk_rating);
float mit_roll = zone->random.Real(0, mit_rating);
float atk_roll = zone->random.Real(0, atk_rating);
if (atk_roll > mit_roll) {
float a_diff = atk_roll - mit_roll;
@ -777,8 +771,8 @@ int32 Client::GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit,
dmg_bonus -= dmg_bonus * (itembonuses.MeleeMitigation / 100.0);
dmg_interval -= dmg_interval * spellMeleeMit;
float mit_roll = MakeRandomFloat(0, mit_rating);
float atk_roll = MakeRandomFloat(0, atk_rating);
float mit_roll = zone->random.Real(0, mit_rating);
float atk_roll = zone->random.Real(0, atk_rating);
if (atk_roll > mit_roll) {
float a_diff = atk_roll - mit_roll;
@ -1278,7 +1272,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
if(RuleB(Combat, UseIntervalAC))
damage = max_hit;
else
damage = MakeRandomInt(min_hit, max_hit);
damage = zone->random.Int(min_hit, max_hit);
damage = mod_client_damage(damage, skillinuse, Hand, weapon, other);
@ -1320,7 +1314,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
OffhandRiposteFail *= -1; //Live uses a negative value for this.
if (OffhandRiposteFail &&
(OffhandRiposteFail > 99 || (MakeRandomInt(0, 100) < OffhandRiposteFail))) {
(OffhandRiposteFail > 99 || zone->random.Roll(OffhandRiposteFail))) {
damage = 0; // Counts as a miss
slippery_attack = true;
} else
@ -1336,7 +1330,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
if (((damage < 0) || slippery_attack) && !bRiposte && !IsStrikethrough) { // Hack to still allow Strikethrough chance w/ Slippery Attacks AA
int32 bonusStrikeThrough = itembonuses.StrikeThrough + spellbonuses.StrikeThrough + aabonuses.StrikeThrough;
if(bonusStrikeThrough && (MakeRandomInt(0, 100) < bonusStrikeThrough)) {
if(bonusStrikeThrough && zone->random.Roll(bonusStrikeThrough)) {
Message_StringID(MT_StrikeThrough, STRIKETHROUGH_STRING); // You strike through your opponents defenses!
Attack(other, Hand, false, true); // Strikethrough only gives another attempted hit
return false;
@ -1362,11 +1356,8 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
MeleeLifeTap(damage);
if (damage > 0){
CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess);
if (HasSkillProcSuccess() && other && other->GetHP() > 0)
TrySkillProc(other, skillinuse, 0, true, Hand);
}
if (damage > 0 && HasSkillProcSuccess() && other && other->GetHP() > 0)
TrySkillProc(other, skillinuse, 0, true, Hand);
CommonBreakInvisible();
@ -1631,14 +1622,14 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
database.GetVariable("PvPitem", tmp2, 9);
int pvpitem = atoi(tmp2);
if(pvpitem>0 && pvpitem<200000)
new_corpse->SetPKItem(pvpitem);
new_corpse->SetPlayerKillItemID(pvpitem);
}
else if(reward==2)
new_corpse->SetPKItem(-1);
new_corpse->SetPlayerKillItemID(-1);
else if(reward==1)
new_corpse->SetPKItem(1);
new_corpse->SetPlayerKillItemID(1);
else
new_corpse->SetPKItem(0);
new_corpse->SetPlayerKillItemID(0);
if(killerMob->CastToClient()->isgrouped) {
Group* group = entity_list.GetGroupByClient(killerMob->CastToClient());
if(group != 0)
@ -1647,7 +1638,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
{
if(group->members[i] != nullptr)
{
new_corpse->AllowMobLoot(group->members[i],i);
new_corpse->AllowPlayerLoot(group->members[i],i);
}
}
}
@ -1852,7 +1843,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
if(RuleB(Combat, UseIntervalAC))
damage = (max_dmg+eleBane);
else
damage = MakeRandomInt((min_dmg+eleBane),(max_dmg+eleBane));
damage = zone->random.Int((min_dmg+eleBane),(max_dmg+eleBane));
//check if we're hitting above our max or below it.
@ -2301,13 +2292,13 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
if(killer != 0 && emoteid != 0)
corpse->CastToNPC()->DoNPCEmote(AFTERDEATH, emoteid);
if(killer != 0 && killer->IsClient()) {
corpse->AllowMobLoot(killer, 0);
corpse->AllowPlayerLoot(killer, 0);
if(killer->IsGrouped()) {
Group* group = entity_list.GetGroupByClient(killer->CastToClient());
if(group != 0) {
for(int i=0;i<6;i++) { // Doesnt work right, needs work
if(group->members[i] != nullptr) {
corpse->AllowMobLoot(group->members[i],i);
corpse->AllowPlayerLoot(group->members[i],i);
}
}
}
@ -2323,30 +2314,30 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
case 0:
case 1:
if(r->members[x].member && r->members[x].IsRaidLeader){
corpse->AllowMobLoot(r->members[x].member, i);
corpse->AllowPlayerLoot(r->members[x].member, i);
i++;
}
break;
case 2:
if(r->members[x].member && r->members[x].IsRaidLeader){
corpse->AllowMobLoot(r->members[x].member, i);
corpse->AllowPlayerLoot(r->members[x].member, i);
i++;
}
else if(r->members[x].member && r->members[x].IsGroupLeader){
corpse->AllowMobLoot(r->members[x].member, i);
corpse->AllowPlayerLoot(r->members[x].member, i);
i++;
}
break;
case 3:
if(r->members[x].member && r->members[x].IsLooter){
corpse->AllowMobLoot(r->members[x].member, i);
corpse->AllowPlayerLoot(r->members[x].member, i);
i++;
}
break;
case 4:
if(r->members[x].member)
{
corpse->AllowMobLoot(r->members[x].member, i);
corpse->AllowPlayerLoot(r->members[x].member, i);
i++;
}
break;
@ -2478,9 +2469,8 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp,
}
}
auto otherPosition = xyz_location(other->GetX(), other->GetY(), other->GetZ());
if(IsNPC() && CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
if(!zone->watermap->InLiquid(otherPosition)) {
if(!zone->watermap->InLiquid(other->GetPosition())) {
return;
}
}
@ -3448,17 +3438,16 @@ bool Client::CheckDoubleAttack(bool tripleAttack) {
chance *= float(100.0f+triple_bonus)/100.0f; //Apply modifiers.
}
if((MakeRandomFloat(0, 1) < chance))
if(zone->random.Roll(chance))
return true;
return false;
}
bool Client::CheckDoubleRangedAttack() {
int32 chance = spellbonuses.DoubleRangedAttack + itembonuses.DoubleRangedAttack + aabonuses.DoubleRangedAttack;
if(chance && (MakeRandomInt(0, 100) < chance))
if(chance && zone->random.Roll(chance))
return true;
return false;
@ -3642,7 +3631,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
}
}
if (stun_chance && MakeRandomInt(0, 99) < stun_chance) {
if (stun_chance && zone->random.Roll(stun_chance)) {
// Passed stun, try to resist now
int stun_resist = itembonuses.StunResist + spellbonuses.StunResist;
int frontal_stun_resist = itembonuses.FrontalStunResist + spellbonuses.FrontalStunResist;
@ -3655,18 +3644,18 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
// frontal stun check for ogres/bonuses
if (((GetBaseRace() == OGRE && IsClient()) ||
(frontal_stun_resist && MakeRandomInt(0, 99) < frontal_stun_resist)) &&
(frontal_stun_resist && zone->random.Roll(frontal_stun_resist))) &&
!attacker->BehindMob(this, attacker->GetX(), attacker->GetY())) {
mlog(COMBAT__HITS, "Frontal stun resisted. %d chance.", frontal_stun_resist);
} else {
// Normal stun resist check.
if (stun_resist && MakeRandomInt(0, 99) < stun_resist) {
if (stun_resist && zone->random.Roll(stun_resist)) {
if (IsClient())
Message_StringID(MT_Stun, SHAKE_OFF_STUN);
mlog(COMBAT__HITS, "Stun Resisted. %d chance.", stun_resist);
} else {
mlog(COMBAT__HITS, "Stunned. %d resist chance.", stun_resist);
Stun(MakeRandomInt(0, 2) * 1000); // 0-2 seconds
Stun(zone->random.Int(0, 2) * 1000); // 0-2 seconds
}
}
} else {
@ -3947,7 +3936,7 @@ void Mob::TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand) {
for (int i = 0; i < MAX_PROCS; i++) {
if (IsValidSpell(DefensiveProcs[i].spellID)) {
float chance = ProcChance * (static_cast<float>(DefensiveProcs[i].chance)/100.0f);
if ((MakeRandomFloat(0, 1) <= chance)) {
if (zone->random.Roll(chance)) {
ExecWeaponProc(nullptr, DefensiveProcs[i].spellID, on);
CheckNumHitsRemaining(NUMHIT_DefensiveSpellProcs,0,DefensiveProcs[i].base_spellID);
}
@ -4009,7 +3998,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on
if (weapon->Proc.Type == ET_CombatProc) {
float WPC = ProcChance * (100.0f + // Proc chance for this weapon
static_cast<float>(weapon->ProcRate)) / 100.0f;
if (MakeRandomFloat(0, 1) <= WPC) { // 255 dex = 0.084 chance of proc. No idea what this number should be really.
if (zone->random.Roll(WPC)) { // 255 dex = 0.084 chance of proc. No idea what this number should be really.
if (weapon->Proc.Level > ourlevel) {
mlog(COMBAT__PROCS,
"Tried to proc (%s), but our level (%d) is lower than required (%d)",
@ -4047,7 +4036,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on
if (aug->Proc.Type == ET_CombatProc) {
float APC = ProcChance * (100.0f + // Proc chance for this aug
static_cast<float>(aug->ProcRate)) / 100.0f;
if (MakeRandomFloat(0, 1) <= APC) {
if (zone->random.Roll(APC)) {
if (aug->Proc.Level > ourlevel) {
if (IsPet()) {
Mob *own = GetOwner();
@ -4100,7 +4089,7 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on,
if (!rangedattk) {
// Perma procs (AAs)
if (PermaProcs[i].spellID != SPELL_UNKNOWN) {
if (MakeRandomInt(0, 99) < PermaProcs[i].chance) { // TODO: Do these get spell bonus?
if (zone->random.Roll(PermaProcs[i].chance)) { // TODO: Do these get spell bonus?
mlog(COMBAT__PROCS,
"Permanent proc %d procing spell %d (%d percent chance)",
i, PermaProcs[i].spellID, PermaProcs[i].chance);
@ -4115,7 +4104,7 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on,
// Spell procs (buffs)
if (SpellProcs[i].spellID != SPELL_UNKNOWN) {
float chance = ProcChance * (static_cast<float>(SpellProcs[i].chance) / 100.0f);
if (MakeRandomFloat(0, 1) <= chance) {
if (zone->random.Roll(chance)) {
mlog(COMBAT__PROCS,
"Spell proc %d procing spell %d (%.2f percent chance)",
i, SpellProcs[i].spellID, chance);
@ -4131,7 +4120,7 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on,
// ranged spell procs (buffs)
if (RangedProcs[i].spellID != SPELL_UNKNOWN) {
float chance = ProcChance * (static_cast<float>(RangedProcs[i].chance) / 100.0f);
if (MakeRandomFloat(0, 1) <= chance) {
if (zone->random.Roll(chance)) {
mlog(COMBAT__PROCS,
"Ranged proc %d procing spell %d (%.2f percent chance)",
i, RangedProcs[i].spellID, chance);
@ -4199,7 +4188,7 @@ void Mob::TryPetCriticalHit(Mob *defender, uint16 skill, int32 &damage)
critChance /= 100;
if(MakeRandomFloat(0, 1) < critChance)
if(zone->random.Roll(critChance))
{
critMod += GetCritDmgMob(skill) * 2; // To account for base crit mod being 200 not 100
damage = (damage * critMod) / 100;
@ -4238,7 +4227,7 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack
int32 SlayRateBonus = aabonuses.SlayUndead[0] + itembonuses.SlayUndead[0] + spellbonuses.SlayUndead[0];
if (SlayRateBonus) {
float slayChance = static_cast<float>(SlayRateBonus) / 10000.0f;
if (MakeRandomFloat(0, 1) < slayChance) {
if (zone->random.Roll(slayChance)) {
int32 SlayDmgBonus = aabonuses.SlayUndead[1] + itembonuses.SlayUndead[1] + spellbonuses.SlayUndead[1];
damage = (damage * SlayDmgBonus * 2.25) / 100;
if (GetGender() == 1) // female
@ -4309,7 +4298,7 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack
critChance /= 100;
if(MakeRandomFloat(0, 1) < critChance)
if(zone->random.Roll(critChance))
{
uint32 critMod = 200;
bool crip_success = false;
@ -4322,7 +4311,7 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack
if (!IsBerserk() && !IsBerskerSPA)
critChance *= float(CripplingBlowChance)/100.0f;
if ((IsBerserk() || IsBerskerSPA) || MakeRandomFloat(0, 1) < critChance) {
if ((IsBerserk() || IsBerskerSPA) || zone->random.Roll(critChance)) {
critMod = 400;
crip_success = true;
}
@ -4332,7 +4321,7 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack
damage = damage * critMod / 100;
bool deadlySuccess = false;
if (deadlyChance && MakeRandomFloat(0, 1) < static_cast<float>(deadlyChance) / 100.0f) {
if (deadlyChance && zone->random.Roll(static_cast<float>(deadlyChance) / 100.0f)) {
if (BehindMob(defender, GetX(), GetY())) {
damage *= deadlyMod;
deadlySuccess = true;
@ -4379,7 +4368,7 @@ bool Mob::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse)
//Proc Chance value of 500 = 5%
uint32 ProcChance = (aabonuses.FinishingBlow[0] + spellbonuses.FinishingBlow[0] + spellbonuses.FinishingBlow[0])/10;
if(FB_Level && FB_Dmg && (defender->GetLevel() <= FB_Level) && (ProcChance >= MakeRandomInt(0, 1000))){
if(FB_Level && FB_Dmg && (defender->GetLevel() <= FB_Level) && (ProcChance >= zone->random.Int(0, 1000))){
entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FINISHING_BLOW, GetName());
DoSpecialAttackDamage(defender, skillinuse, FB_Dmg, 1, -1, 10, false, false);
return true;
@ -4406,7 +4395,7 @@ void Mob::DoRiposte(Mob* defender) {
defender->itembonuses.DoubleRiposte;
//Live AA - Double Riposte
if(DoubleRipChance && (DoubleRipChance >= MakeRandomInt(0, 100))) {
if(DoubleRipChance && zone->random.Roll(DoubleRipChance)) {
mlog(COMBAT__ATTACKS, "Preforming a double riposed (%d percent chance)", DoubleRipChance);
defender->Attack(this, MainPrimary, true);
if (HasDied()) return;
@ -4417,7 +4406,7 @@ void Mob::DoRiposte(Mob* defender) {
DoubleRipChance = defender->aabonuses.GiveDoubleRiposte[1];
if(DoubleRipChance && (DoubleRipChance >= MakeRandomInt(0, 100))) {
if(DoubleRipChance && zone->random.Roll(DoubleRipChance)) {
mlog(COMBAT__ATTACKS, "Preforming a return SPECIAL ATTACK (%d percent chance)", DoubleRipChance);
if (defender->GetClass() == MONK)
@ -4529,7 +4518,6 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
if (spellbonuses.LimitToSkill[skill]){
for(int e = 0; e < MAX_SKILL_PROCS; e++){
if (CanProc &&
(!Success && spellbonuses.SkillProc[e] && IsValidSpell(spellbonuses.SkillProc[e]))
|| (Success && spellbonuses.SkillProcSuccess[e] && IsValidSpell(spellbonuses.SkillProcSuccess[e]))) {
@ -4548,7 +4536,7 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
if (CanProc && spells[base_spell_id].base[i] == skill && IsValidSpell(proc_spell_id)) {
float final_chance = chance * (ProcMod / 100.0f);
if (MakeRandomFloat(0, 1) <= final_chance) {
if (zone->random.Roll(final_chance)) {
ExecWeaponProc(nullptr, proc_spell_id, on);
CheckNumHitsRemaining(NUMHIT_OffensiveSpellProcs,0, base_spell_id);
CanProc = false;
@ -4568,7 +4556,6 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
if (itembonuses.LimitToSkill[skill]){
CanProc = true;
for(int e = 0; e < MAX_SKILL_PROCS; e++){
if (CanProc &&
(!Success && itembonuses.SkillProc[e] && IsValidSpell(itembonuses.SkillProc[e]))
|| (Success && itembonuses.SkillProcSuccess[e] && IsValidSpell(itembonuses.SkillProcSuccess[e]))) {
@ -4587,7 +4574,7 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
if (CanProc && spells[base_spell_id].base[i] == skill && IsValidSpell(proc_spell_id)) {
float final_chance = chance * (ProcMod / 100.0f);
if (MakeRandomFloat(0, 1) <= final_chance) {
if (zone->random.Roll(final_chance)) {
ExecWeaponProc(nullptr, proc_spell_id, on);
CanProc = false;
break;
@ -4612,7 +4599,6 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
uint32 slot = 0;
for(int e = 0; e < MAX_SKILL_PROCS; e++){
if (CanProc &&
(!Success && aabonuses.SkillProc[e])
|| (Success && aabonuses.SkillProcSuccess[e])){
@ -4640,7 +4626,7 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
if (CanProc && base1 == skill && IsValidSpell(proc_spell_id)) {
float final_chance = chance * (ProcMod / 100.0f);
if (MakeRandomFloat(0, 1) <= final_chance) {
if (zone->random.Roll(final_chance)) {
ExecWeaponProc(nullptr, proc_spell_id, on);
CanProc = false;
break;
@ -4680,26 +4666,25 @@ float Mob::GetSkillProcChances(uint16 ReuseTime, uint16 hand) {
bool Mob::TryRootFadeByDamage(int buffslot, Mob* attacker) {
/*Dev Quote 2010: http://forums.station.sony.com/eq/posts/list.m?topic_id=161443
The Viscid Roots AA does the following: Reduces the chance for root to break by X percent.
There is no distinction of any kind between the caster inflicted damage, or anyone
else's damage. There is also no distinction between Direct and DOT damage in the root code.
/*Dev Quote 2010: http://forums.station.sony.com/eq/posts/list.m?topic_id=161443
The Viscid Roots AA does the following: Reduces the chance for root to break by X percent.
There is no distinction of any kind between the caster inflicted damage, or anyone
else's damage. There is also no distinction between Direct and DOT damage in the root code.
/* General Mechanics
- Check buffslot to make sure damage from a root does not cancel the root
- If multiple roots on target, always and only checks first root slot and if broken only removes that slots root.
- Only roots on determental spells can be broken by damage.
General Mechanics
- Check buffslot to make sure damage from a root does not cancel the root
- If multiple roots on target, always and only checks first root slot and if broken only removes that slots root.
- Only roots on determental spells can be broken by damage.
- Root break chance values obtained from live parses.
*/
*/
if (!attacker || !spellbonuses.Root[0] || spellbonuses.Root[1] < 0)
return false;
return false;
if (IsDetrimentalSpell(spellbonuses.Root[1]) && spellbonuses.Root[1] != buffslot){
if (IsDetrimentalSpell(spellbonuses.Root[1]) && spellbonuses.Root[1] != buffslot){
int BreakChance = RuleI(Spells, RootBreakFromSpells);
int BreakChance = RuleI(Spells, RootBreakFromSpells);
BreakChance -= BreakChance*buffs[spellbonuses.Root[1]].RootBreakChance/100;
BreakChance -= BreakChance*buffs[spellbonuses.Root[1]].RootBreakChance/100;
int level_diff = attacker->GetLevel() - GetLevel();
//Use baseline if level difference <= 1 (ie. If target is (1) level less than you, or equal or greater level)
@ -4713,10 +4698,10 @@ bool Mob::TryRootFadeByDamage(int buffslot, Mob* attacker) {
else if (level_diff > 21)
BreakChance = (BreakChance * 20) /100; //Decrease by 80%;
if (BreakChance < 1)
BreakChance = 1;
if (BreakChance < 1)
BreakChance = 1;
if (MakeRandomInt(0, 99) < BreakChance) {
if (zone->random.Roll(BreakChance)) {
if (!TryFadeEffect(spellbonuses.Root[1])) {
BuffFadeBySlot(spellbonuses.Root[1]);

5054
zone/attack.cpp.orig Normal file

File diff suppressed because it is too large Load Diff

View File

@ -775,49 +775,49 @@ void Bot::GenerateAppearance() {
// Randomize facial appearance
int iFace = 0;
if(this->GetRace() == 2) { // Barbarian w/Tatoo
iFace = MakeRandomInt(0, 79);
iFace = zone->random.Int(0, 79);
}
else {
iFace = MakeRandomInt(0, 7);
iFace = zone->random.Int(0, 7);
}
int iHair = 0;
int iBeard = 0;
int iBeardColor = 1;
if(this->GetRace() == 522) {
iHair = MakeRandomInt(0, 8);
iBeard = MakeRandomInt(0, 11);
iBeardColor = MakeRandomInt(0, 3);
iHair = zone->random.Int(0, 8);
iBeard = zone->random.Int(0, 11);
iBeardColor = zone->random.Int(0, 3);
}
else if(this->GetGender()) {
iHair = MakeRandomInt(0, 2);
iHair = zone->random.Int(0, 2);
if(this->GetRace() == 8) { // Dwarven Females can have a beard
if(MakeRandomInt(1, 100) < 50) {
if(zone->random.Int(1, 100) < 50) {
iFace += 10;
}
}
}
else {
iHair = MakeRandomInt(0, 3);
iBeard = MakeRandomInt(0, 5);
iBeardColor = MakeRandomInt(0, 19);
iHair = zone->random.Int(0, 3);
iBeard = zone->random.Int(0, 5);
iBeardColor = zone->random.Int(0, 19);
}
int iHairColor = 0;
if(this->GetRace() == 522) {
iHairColor = MakeRandomInt(0, 3);
iHairColor = zone->random.Int(0, 3);
}
else {
iHairColor = MakeRandomInt(0, 19);
iHairColor = zone->random.Int(0, 19);
}
uint8 iEyeColor1 = (uint8)MakeRandomInt(0, 9);
uint8 iEyeColor1 = (uint8)zone->random.Int(0, 9);
uint8 iEyeColor2 = 0;
if(this->GetRace() == 522) {
iEyeColor1 = iEyeColor2 = (uint8)MakeRandomInt(0, 11);
iEyeColor1 = iEyeColor2 = (uint8)zone->random.Int(0, 11);
}
else if(MakeRandomInt(1, 100) > 96) {
iEyeColor2 = MakeRandomInt(0, 9);
else if(zone->random.Int(1, 100) > 96) {
iEyeColor2 = zone->random.Int(0, 9);
}
else {
iEyeColor2 = iEyeColor1;
@ -827,9 +827,9 @@ void Bot::GenerateAppearance() {
int iTattoo = 0;
int iDetails = 0;
if(this->GetRace() == 522) {
iHeritage = MakeRandomInt(0, 6);
iTattoo = MakeRandomInt(0, 7);
iDetails = MakeRandomInt(0, 7);
iHeritage = zone->random.Int(0, 6);
iTattoo = zone->random.Int(0, 7);
iDetails = zone->random.Int(0, 7);
}
this->luclinface = iFace;
@ -3098,7 +3098,7 @@ bool Bot::CheckBotDoubleAttack(bool tripleAttack) {
chance *= float(100.0f+triple_bonus)/100.0f; //Apply modifiers.
}
if((MakeRandomFloat(0, 1) < chance))
if((zone->random.Real(0, 1) < chance))
return true;
return false;
@ -3148,7 +3148,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes
if(RuleB(Combat, UseIntervalAC))
damage = max_hit;
else
damage = MakeRandomInt(min_hit, max_hit);
damage = zone->random.Int(min_hit, max_hit);
if(!other->CheckHitChance(this, skillinuse, Hand, chance_mod)) {
damage = 0;
@ -3203,7 +3203,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes
if (damage > 0)
CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess);
if((skillinuse == SkillDragonPunch) && GetAA(aaDragonPunch) && MakeRandomInt(0, 99) < 25){
if((skillinuse == SkillDragonPunch) && GetAA(aaDragonPunch) && zone->random.Int(0, 99) < 25){
SpellFinished(904, other, 10, 0, -1, spells[904].ResistDiff);
other->Stun(100);
}
@ -3483,7 +3483,7 @@ void Bot::AI_Process() {
meleeDistance = meleeDistance * .30;
}
else {
meleeDistance *= (float)MakeRandomFloat(.50, .85);
meleeDistance *= (float)zone->random.Real(.50, .85);
}
bool atArcheryRange = IsArcheryRange(GetTarget());
@ -3616,7 +3616,7 @@ void Bot::AI_Process() {
if (GetTarget() && flurrychance)
{
if(MakeRandomInt(0, 100) < flurrychance)
if(zone->random.Int(0, 100) < flurrychance)
{
Message_StringID(MT_NPCFlurry, YOU_FLURRY);
Attack(GetTarget(), MainPrimary, false);
@ -3633,7 +3633,7 @@ void Bot::AI_Process() {
wpn->GetItem()->ItemType == ItemType2HBlunt ||
wpn->GetItem()->ItemType == ItemType2HPiercing )
{
if(MakeRandomInt(0, 100) < ExtraAttackChanceBonus)
if(zone->random.Int(0, 100) < ExtraAttackChanceBonus)
{
Attack(GetTarget(), MainPrimary, false);
}
@ -3678,7 +3678,7 @@ void Bot::AI_Process() {
int32 DWBonus = spellbonuses.DualWieldChance + itembonuses.DualWieldChance;
DualWieldProbability += DualWieldProbability*float(DWBonus)/ 100.0f;
float random = MakeRandomFloat(0, 1);
float random = zone->random.Real(0, 1);
if (random < DualWieldProbability){ // Max 78% of DW
@ -3912,7 +3912,7 @@ void Bot::PetAIProcess() {
if (botPet->GetTarget()) // Do we still have a target?
{
// We're a pet so we re able to dual attack
int32 RandRoll = MakeRandomInt(0, 99);
int32 RandRoll = zone->random.Int(0, 99);
if (botPet->CanThisClassDoubleAttack() && (RandRoll < (botPet->GetLevel() + NPCDualAttackModifier)))
{
if(botPet->Attack(botPet->GetTarget(), MainPrimary))
@ -3945,7 +3945,7 @@ void Bot::PetAIProcess() {
//aa_chance += botPet->GetOwner()->GetAA(aaCompanionsAlacrity) * 3;
if (MakeRandomInt(1, 100) < aa_chance)
if (zone->random.Int(1, 100) < aa_chance)
Flurry(nullptr);
}
@ -3955,12 +3955,12 @@ void Bot::PetAIProcess() {
if(botPet->GetOwner()->GetLevel() >= 24)
{
float DualWieldProbability = (botPet->GetSkill(SkillDualWield) + botPet->GetLevel()) / 400.0f;
DualWieldProbability -= MakeRandomFloat(0, 1);
DualWieldProbability -= zone->random.Real(0, 1);
if(DualWieldProbability < 0){
botPet->Attack(botPet->GetTarget(), MainSecondary);
if (botPet->CanThisClassDoubleAttack())
{
int32 RandRoll = MakeRandomInt(0, 99);
int32 RandRoll = zone->random.Int(0, 99);
if (RandRoll < (botPet->GetLevel() + 20))
{
botPet->Attack(botPet->GetTarget(), MainSecondary);
@ -6213,7 +6213,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b
if(RuleB(Combat, UseIntervalAC))
damage = max_hit;
else
damage = MakeRandomInt(min_hit, max_hit);
damage = zone->random.Int(min_hit, max_hit);
mlog(COMBAT__DAMAGE, "Damage calculated to %d (min %d, max %d, str %d, skill %d, DMG %d, lv %d)",
damage, min_hit, max_hit, GetSTR(), GetSkill(skillinuse), weapon_damage, GetLevel());
@ -6258,7 +6258,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b
OffhandRiposteFail *= -1; //Live uses a negative value for this.
if (OffhandRiposteFail &&
(OffhandRiposteFail > 99 || (MakeRandomInt(0, 100) < OffhandRiposteFail))) {
(OffhandRiposteFail > 99 || (zone->random.Int(0, 100) < OffhandRiposteFail))) {
damage = 0; // Counts as a miss
slippery_attack = true;
} else
@ -6274,7 +6274,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b
if (((damage < 0) || slippery_attack) && !FromRiposte && !IsStrikethrough) { // Hack to still allow Strikethrough chance w/ Slippery Attacks AA
int32 bonusStrikeThrough = itembonuses.StrikeThrough + spellbonuses.StrikeThrough + aabonuses.StrikeThrough;
if(bonusStrikeThrough && (MakeRandomInt(0, 100) < bonusStrikeThrough)) {
if(bonusStrikeThrough && (zone->random.Int(0, 100) < bonusStrikeThrough)) {
Message_StringID(MT_StrikeThrough, STRIKETHROUGH_STRING); // You strike through your opponents defenses!
Attack(other, Hand, false, true); // Strikethrough only gives another attempted hit
return false;
@ -6623,7 +6623,7 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id)
{
if(type == focusTriggerOnCast)
{
if(MakeRandomInt(0, 100) <= base1){
if(zone->random.Int(0, 100) <= base1){
value = base2;
}
@ -6646,7 +6646,7 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id)
{
if(type == focusBlockNextSpell)
{
if(MakeRandomInt(1, 100) <= base1)
if(zone->random.Int(1, 100) <= base1)
value = 1;
}
break;
@ -6670,7 +6670,7 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id)
int32 cast_time = GetActSpellCasttime(spell_id, spells[spell_id].cast_time);
GetSympatheticProcChances(ProcBonus, ProcChance, cast_time, ProcRateMod);
if(MakeRandomFloat(0, 1) <= ProcChance)
if(zone->random.Real(0, 1) <= ProcChance)
value = focus_id;
else
@ -7147,7 +7147,7 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
value = focus_spell.base[i];
}
else {
value = MakeRandomInt(focus_spell.base[i], focus_spell.base2[i]);
value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]);
}
}
break;
@ -7165,7 +7165,7 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
value = focus_spell.base[i];
}
else {
value = MakeRandomInt(focus_spell.base[i], focus_spell.base2[i]);
value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]);
}
}
break;
@ -7183,7 +7183,7 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
value = focus_spell.base[i];
}
else {
value = MakeRandomInt(focus_spell.base[i], focus_spell.base2[i]);
value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]);
}
}
break;
@ -7273,7 +7273,7 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
{
if(bottype == BotfocusTriggerOnCast)
if(MakeRandomInt(0, 100) <= focus_spell.base[i])
if(zone->random.Int(0, 100) <= focus_spell.base[i])
value = focus_spell.base2[i];
else
@ -7293,7 +7293,7 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
{
if(bottype == BotfocusBlockNextSpell)
{
if(MakeRandomInt(1, 100) <= focus_spell.base[i])
if(zone->random.Int(1, 100) <= focus_spell.base[i])
value = 1;
}
break;
@ -7313,7 +7313,7 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
float ProcChance = GetSympatheticProcChances(spell_id, focus_spell.base[i]);
if(MakeRandomFloat(0, 1) <= ProcChance)
if(zone->random.Real(0, 1) <= ProcChance)
value = focus_id;
else
@ -7503,7 +7503,7 @@ bool Bot::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte)
//Live AA - HightenedAwareness
int BlockBehindChance = aabonuses.BlockBehind + spellbonuses.BlockBehind + itembonuses.BlockBehind;
if (BlockBehindChance && (BlockBehindChance > MakeRandomInt(1, 100))){
if (BlockBehindChance && (BlockBehindChance > zone->random.Int(1, 100))){
bBlockFromRear = true;
if (spellbonuses.BlockBehind || itembonuses.BlockBehind)
@ -7595,7 +7595,7 @@ bool Bot::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte)
if(damage > 0)
{
roll = MakeRandomFloat(0,100);
roll = zone->random.Real(0,100);
if(roll <= RollTable[0]){
damage = -3;
}
@ -7662,7 +7662,7 @@ bool Bot::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse)
uint32 damage = aabonuses.FinishingBlow[1];
uint16 levelreq = aabonuses.FinishingBlowLvl[0];
if(defender->GetLevel() <= levelreq && (chance >= MakeRandomInt(0, 1000))){
if(defender->GetLevel() <= levelreq && (chance >= zone->random.Int(0, 1000))){
mlog(COMBAT__ATTACKS, "Landed a finishing blow: levelreq at %d, other level %d", levelreq , defender->GetLevel());
entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FINISHING_BLOW, GetName());
defender->Damage(this, damage, SPELL_UNKNOWN, skillinuse);
@ -7690,7 +7690,7 @@ void Bot::DoRiposte(Mob* defender) {
defender->GetSpellBonuses().GiveDoubleRiposte[0] +
defender->GetItemBonuses().GiveDoubleRiposte[0];
if(DoubleRipChance && (DoubleRipChance >= MakeRandomInt(0, 100))) {
if(DoubleRipChance && (DoubleRipChance >= zone->random.Int(0, 100))) {
mlog(COMBAT__ATTACKS, "Preforming a double riposte (%d percent chance)", DoubleRipChance);
defender->Attack(this, MainPrimary, true);
@ -7700,7 +7700,7 @@ void Bot::DoRiposte(Mob* defender) {
//Coded narrowly: Limit to one per client. Limit AA only. [1 = Skill Attack Chance, 2 = Skill]
DoubleRipChance = defender->GetAABonuses().GiveDoubleRiposte[1];
if(DoubleRipChance && (DoubleRipChance >= MakeRandomInt(0, 100))) {
if(DoubleRipChance && (DoubleRipChance >= zone->random.Int(0, 100))) {
if (defender->GetClass() == MONK)
defender->MonkSpecialAttack(this, defender->GetAABonuses().GiveDoubleRiposte[2]);
else if (defender->IsBot())
@ -7766,7 +7766,7 @@ void Bot::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage,
int kb_chance = 25;
kb_chance += kb_chance*(100-aabonuses.SpecialAttackKBProc[0])/100;
if (MakeRandomInt(0, 99) < kb_chance)
if (zone->random.Int(0, 99) < kb_chance)
SpellFinished(904, who, 10, 0, -1, spells[904].ResistDiff);
//who->Stun(100); Kayen: This effect does not stun on live, it only moves the NPC.
}
@ -7807,7 +7807,7 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) {
//Live AA - Seized Opportunity
int FrontalBSChance = itembonuses.FrontalBackstabChance + spellbonuses.FrontalBackstabChance + aabonuses.FrontalBackstabChance;
if (FrontalBSChance && (FrontalBSChance > MakeRandomInt(0, 100)))
if (FrontalBSChance && (FrontalBSChance > zone->random.Int(0, 100)))
bCanFrontalBS = true;
}
@ -7821,7 +7821,7 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) {
!other->CastToNPC()->IsEngaged() && // not aggro
other->GetHP()<=32000
&& other->IsNPC()
&& MakeRandomFloat(0, 99) < chance // chance
&& zone->random.Real(0, 99) < chance // chance
) {
entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, ASSASSINATES, GetName());
RogueAssassinate(other);
@ -7832,12 +7832,12 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) {
float DoubleAttackProbability = (GetSkill(SkillDoubleAttack) + GetLevel()) / 500.0f; // 62.4 max
// Check for double attack with main hand assuming maxed DA Skill (MS)
if(MakeRandomFloat(0, 1) < DoubleAttackProbability) // Max 62.4 % chance of DA
if(zone->random.Real(0, 1) < DoubleAttackProbability) // Max 62.4 % chance of DA
{
if(other->GetHP() > 0)
RogueBackstab(other,false,ReuseTime);
if (tripleChance && other->GetHP() > 0 && tripleChance > MakeRandomInt(0, 100))
if (tripleChance && other->GetHP() > 0 && tripleChance > zone->random.Int(0, 100))
RogueBackstab(other,false,ReuseTime);
}
}
@ -7851,11 +7851,11 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) {
if (level > 54) {
float DoubleAttackProbability = (GetSkill(SkillDoubleAttack) + GetLevel()) / 500.0f; // 62.4 max
// Check for double attack with main hand assuming maxed DA Skill (MS)
if(MakeRandomFloat(0, 1) < DoubleAttackProbability) // Max 62.4 % chance of DA
if(zone->random.Real(0, 1) < DoubleAttackProbability) // Max 62.4 % chance of DA
if(other->GetHP() > 0)
RogueBackstab(other,true, ReuseTime);
if (tripleChance && other->GetHP() > 0 && tripleChance > MakeRandomInt(0, 100))
if (tripleChance && other->GetHP() > 0 && tripleChance > zone->random.Int(0, 100))
RogueBackstab(other,false,ReuseTime);
}
}
@ -7929,7 +7929,7 @@ void Bot::RogueBackstab(Mob* other, bool min_damage, int ReuseTime)
if(RuleB(Combat, UseIntervalAC))
ndamage = max_hit;
else
ndamage = MakeRandomInt(min_hit, max_hit);
ndamage = zone->random.Int(min_hit, max_hit);
}
}
@ -8036,7 +8036,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
canBash = true;
}
if(!canBash || MakeRandomInt(0, 100) > 25) { //tested on live, warrior mobs both kick and bash, kick about 75% of the time, casting doesn't seem to make a difference.
if(!canBash || zone->random.Int(0, 100) > 25) { //tested on live, warrior mobs both kick and bash, kick about 75% of the time, casting doesn't seem to make a difference.
skill_to_use = SkillKick;
}
else {
@ -8117,7 +8117,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
if(RuleB(Combat, UseIntervalAC))
dmg = GetBashDamage();
else
dmg = MakeRandomInt(1, GetBashDamage());
dmg = zone->random.Int(1, GetBashDamage());
}
}
@ -8164,7 +8164,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
//Live parses show around 55% Triple 35% Double 10% Single, you will always get first hit.
while(AtkRounds > 0) {
if (GetTarget() && (AtkRounds == 1 || MakeRandomInt(0,100) < 75)){
if (GetTarget() && (AtkRounds == 1 || zone->random.Int(0,100) < 75)){
DoSpecialAttackDamage(GetTarget(), SkillFrenzy, max_dmg, min_dmg, max_dmg , reuse, true);
}
AtkRounds--;
@ -8192,7 +8192,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
if(RuleB(Combat, UseIntervalAC))
dmg = GetKickDamage();
else
dmg = MakeRandomInt(1, GetKickDamage());
dmg = zone->random.Int(1, GetKickDamage());
}
}
@ -8215,18 +8215,18 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
//Live AA - Technique of Master Wu
uint32 bDoubleSpecialAttack = itembonuses.DoubleSpecialAttack + spellbonuses.DoubleSpecialAttack + aabonuses.DoubleSpecialAttack;
if( bDoubleSpecialAttack && (bDoubleSpecialAttack >= 100 || bDoubleSpecialAttack > MakeRandomInt(0,100))) {
if( bDoubleSpecialAttack && (bDoubleSpecialAttack >= 100 || bDoubleSpecialAttack > zone->random.Int(0,100))) {
int MonkSPA [5] = { SkillFlyingKick, SkillDragonPunch, SkillEagleStrike, SkillTigerClaw, SkillRoundKick };
MonkSpecialAttack(target, MonkSPA[MakeRandomInt(0,4)]);
MonkSpecialAttack(target, MonkSPA[zone->random.Int(0,4)]);
int TripleChance = 25;
if (bDoubleSpecialAttack > 100)
TripleChance += TripleChance*(100-bDoubleSpecialAttack)/100;
if(TripleChance > MakeRandomInt(0,100)) {
MonkSpecialAttack(target, MonkSPA[MakeRandomInt(0,4)]);
if(TripleChance > zone->random.Int(0,100)) {
MonkSpecialAttack(target, MonkSPA[zone->random.Int(0,4)]);
}
}
@ -8259,7 +8259,7 @@ bool Bot::TryHeadShot(Mob* defender, SkillUseTypes skillInUse) {
// WildcardX: These chance formula's below are arbitrary. If someone has a better formula that is more
// consistent with live, feel free to update these.
float AttackerChance = 0.20f + ((float)(rangerLevel - 51) * 0.005f);
float DefenderChance = (float)MakeRandomFloat(0.00f, 1.00f);
float DefenderChance = (float)zone->random.Real(0.00f, 1.00f);
if(AttackerChance > DefenderChance) {
mlog(COMBAT__ATTACKS, "Landed a headshot: Attacker chance was %f and Defender chance was %f.", AttackerChance, DefenderChance);
// WildcardX: At the time I wrote this, there wasnt a string id for something like HEADSHOT_BLOW
@ -8734,14 +8734,14 @@ int32 Bot::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
if (spell_id == SPELL_IMP_HARM_TOUCH && (GetAA(aaSpellCastingFury) > 0) && (GetAA(aaUnholyTouch) > 0))
chance = 100;
if (MakeRandomInt(1,100) <= chance){
if (zone->random.Int(1,100) <= chance){
Critical = true;
ratio += itembonuses.SpellCritDmgIncrease + spellbonuses.SpellCritDmgIncrease + aabonuses.SpellCritDmgIncrease;
ratio += itembonuses.SpellCritDmgIncNoStack + spellbonuses.SpellCritDmgIncNoStack + aabonuses.SpellCritDmgIncNoStack;
}
else if (GetClass() == WIZARD && (GetLevel() >= RuleI(Spells, WizCritLevel)) && (MakeRandomInt(1,100) <= RuleI(Spells, WizCritChance))) {
ratio = MakeRandomInt(1,100); //Wizard innate critical chance is calculated seperately from spell effect and is not a set ratio.
else if (GetClass() == WIZARD && (GetLevel() >= RuleI(Spells, WizCritLevel)) && (zone->random.Int(1,100) <= RuleI(Spells, WizCritChance))) {
ratio = zone->random.Int(1,100); //Wizard innate critical chance is calculated seperately from spell effect and is not a set ratio.
Critical = true;
}
@ -8820,7 +8820,7 @@ int32 Bot::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
if (spellbonuses.CriticalHealDecay)
chance += GetDecayEffectValue(spell_id, SE_CriticalHealDecay);
if(chance && (MakeRandomInt(0,99) < chance)) {
if(chance && (zone->random.Int(0,99) < chance)) {
Critical = true;
modifier = 2; //At present time no critical heal amount modifier SPA exists.
}
@ -8851,7 +8851,7 @@ int32 Bot::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
if (spellbonuses.CriticalRegenDecay)
chance += GetDecayEffectValue(spell_id, SE_CriticalRegenDecay);
if(chance && (MakeRandomInt(0,99) < chance))
if(chance && (zone->random.Int(0,99) < chance))
return (value * 2);
}
@ -8950,7 +8950,7 @@ int32 Bot::GetActSpellCost(uint16 spell_id, int32 cost) {
// Formula = Unknown exact, based off a random percent chance up to mana cost(after focuses) of the cast spell
if(this->itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5)
{
int32 mana_back = this->itembonuses.Clairvoyance * MakeRandomInt(1, 100) / 100;
int32 mana_back = this->itembonuses.Clairvoyance * zone->random.Int(1, 100) / 100;
// Doesnt generate mana, so best case is a free spell
if(mana_back > cost)
mana_back = cost;
@ -8963,7 +8963,7 @@ int32 Bot::GetActSpellCost(uint16 spell_id, int32 cost) {
// WildcardX
float PercentManaReduction = 0;
float SpecializeSkill = GetSpecializeSkillValue(spell_id);
int SuccessChance = MakeRandomInt(0, 100);
int SuccessChance = zone->random.Int(0, 100);
float bonus = 1.0;
switch(GetAA(aaSpellCastingMastery))
@ -9015,7 +9015,7 @@ int32 Bot::GetActSpellCost(uint16 spell_id, int32 cost) {
if(focus_redux > 0)
{
PercentManaReduction += MakeRandomFloat(1, (double)focus_redux);
PercentManaReduction += zone->random.Real(1, (double)focus_redux);
}
cost -= (cost * (PercentManaReduction / 100));
@ -11864,7 +11864,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) {
}
if(!strcasecmp(sep->arg[1], "inventory") && !strcasecmp(sep->arg[2], "remove")) {
if((c->GetTarget() == nullptr) || (sep->arg[3] == '\0') || !c->GetTarget()->IsBot())
if((c->GetTarget() == nullptr) || (sep->arg[3][0] == '\0') || !c->GetTarget()->IsBot())
{
c->Message(15, "Usage: #bot inventory remove [slotid] (You must have a bot targetted) ");
return;
@ -15580,7 +15580,7 @@ bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, fl
return false;
if (iChance < 100) {
uint8 tmp = MakeRandomInt(1, 100);
uint8 tmp = zone->random.Int(1, 100);
if (tmp > iChance)
return false;
}

View File

@ -13,7 +13,7 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
return false;
if (iChance < 100) {
if (MakeRandomInt(0, 100) > iChance){
if (zone->random.Int(0, 100) > iChance){
return false;
}
}
@ -485,7 +485,7 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
if(botClass == PALADIN)
stunChance = 50;
if(!tar->GetSpecialAbility(UNSTUNABLE) && !tar->IsStunned() && (MakeRandomInt(1, 100) <= stunChance)) {
if(!tar->GetSpecialAbility(UNSTUNABLE) && !tar->IsStunned() && (zone->random.Int(1, 100) <= stunChance)) {
botSpell = GetBestBotSpellForStunByTargetType(this, ST_Target);
}
}
@ -1843,7 +1843,7 @@ std::string Bot::GetBotMagicianPetType(Bot* botCaster) {
result = std::string("SumEarth");
else if(botCaster->GetLevel() < 30) {
// Under level 30
int counter = MakeRandomInt(0, 3);
int counter = zone->random.Int(0, 3);
switch(counter) {
case 0:
@ -1865,7 +1865,7 @@ std::string Bot::GetBotMagicianPetType(Bot* botCaster) {
}
else {
// Over level 30
int counter = MakeRandomInt(0, 4);
int counter = zone->random.Int(0, 4);
switch(counter) {
case 0:

View File

@ -17,13 +17,9 @@
*/
#include "../common/debug.h"
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <math.h>
// for windows compile
#ifdef _WINDOWS
@ -39,27 +35,17 @@
extern volatile bool RunLoops;
#include "../common/features.h"
#include "../common/misc.h"
#include "../common/spdat.h"
#include "../common/packet_dump.h"
#include "../common/packet_functions.h"
#include "../common/serverinfo.h"
#include "../common/zone_numbers.h"
#include "../common/moremath.h"
#include "../common/guilds.h"
#include "../common/breakdowns.h"
#include "../common/rulesys.h"
#include "../common/string_util.h"
#include "../common/data_verification.h"
#include "net.h"
#include "masterentity.h"
#include "worldserver.h"
#include "zonedb.h"
#include "petitions.h"
#include "forage.h"
#include "command.h"
#include "string_ids.h"
#include "npc_ai.h"
#include "client_logs.h"
#include "guild_mgr.h"
#include "quest_parser_collection.h"
@ -1879,6 +1865,9 @@ void Client::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
if (strlen(item->IDFile) > 2)
ns->spawn.equipment[MaterialPrimary] = atoi(&item->IDFile[2]);
}
else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) {
ns->spawn.equipment[MaterialPrimary] = inst->GetOrnamentationIDFile();
}
else {
item = inst->GetItem();
if (strlen(item->IDFile) > 2)
@ -1891,6 +1880,9 @@ void Client::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
if (strlen(item->IDFile) > 2)
ns->spawn.equipment[MaterialSecondary] = atoi(&item->IDFile[2]);
}
else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) {
ns->spawn.equipment[MaterialSecondary] = inst->GetOrnamentationIDFile();
}
else {
item = inst->GetItem();
if (strlen(item->IDFile) > 2)
@ -2326,7 +2318,7 @@ bool Client::CheckIncreaseSkill(SkillUseTypes skillid, Mob *against_who, int cha
if(Chance < 1)
Chance = 1; // Make it always possible
if(MakeRandomFloat(0, 99) < Chance)
if(zone->random.Real(0, 99) < Chance)
{
SetSkill(skillid, GetRawSkill(skillid) + 1);
_log(SKILLS__GAIN, "Skill %d at value %d successfully gain with %.4f%%chance (mod %d)", skillid, skillval, Chance, chancemodi);
@ -2354,7 +2346,7 @@ void Client::CheckLanguageSkillIncrease(uint8 langid, uint8 TeacherSkill) {
int32 Chance = 5 + ((TeacherSkill - LangSkill)/10); // greater chance to learn if teacher's skill is much higher than yours
Chance = (Chance * RuleI(Character, SkillUpModifier)/100);
if(MakeRandomFloat(0,100) < Chance) { // if they make the roll
if(zone->random.Real(0,100) < Chance) { // if they make the roll
IncreaseLanguageSkill(langid); // increase the language skill by 1
_log(SKILLS__GAIN, "Language %d at value %d successfully gain with %.4f%%chance", langid, LangSkill, Chance);
}
@ -2756,6 +2748,9 @@ void Client::SetMaterial(int16 in_slot, uint32 item_id) {
item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem();
m_pp.item_material[MaterialPrimary] = atoi(item->IDFile + 2);
}
else if (inst && inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) {
m_pp.item_material[MaterialPrimary] = inst->GetOrnamentationIDFile();
}
else {
m_pp.item_material[MaterialPrimary] = atoi(item->IDFile + 2);
}
@ -2766,6 +2761,9 @@ void Client::SetMaterial(int16 in_slot, uint32 item_id) {
item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem();
m_pp.item_material[MaterialSecondary] = atoi(item->IDFile + 2);
}
else if (inst && inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) {
m_pp.item_material[MaterialSecondary] = inst->GetOrnamentationIDFile();
}
else {
m_pp.item_material[MaterialSecondary] = atoi(item->IDFile + 2);
}
@ -4896,7 +4894,7 @@ int Client::LDoNChest_SkillCheck(NPC *target, int skill)
chance = 100.0f - base_difficulty;
}
float d100 = (float)MakeRandomFloat(0, 100);
float d100 = (float)zone->random.Real(0, 100);
if(d100 <= chance)
return 1;
@ -5815,6 +5813,10 @@ void Client::ProcessInspectRequest(Client* requestee, Client* requester) {
strcpy(insr->itemnames[L], item->Name);
insr->itemicons[L] = aug_weap->Icon;
}
else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) {
strcpy(insr->itemnames[L], item->Name);
insr->itemicons[L] = inst->GetOrnamentationIcon();
}
else {
strcpy(insr->itemnames[L], item->Name);
insr->itemicons[L] = item->Icon;
@ -7591,9 +7593,9 @@ void Client::GarbleMessage(char *message, uint8 variance)
const char alpha_list[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; // only change alpha characters for now
for (size_t i = 0; i < strlen(message); i++) {
uint8 chance = (uint8)MakeRandomInt(0, 115); // variation just over worst possible scrambling
uint8 chance = (uint8)zone->random.Int(0, 115); // variation just over worst possible scrambling
if (isalpha(message[i]) && (chance <= variance)) {
uint8 rand_char = (uint8)MakeRandomInt(0,51); // choose a random character from the alpha list
uint8 rand_char = (uint8)zone->random.Int(0,51); // choose a random character from the alpha list
message[i] = alpha_list[rand_char];
}
}
@ -7711,7 +7713,7 @@ void Client::SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, ui
// If our result is truncated, then double a mob's value every once and a while to equal what they would have got
else
{
if (MakeRandomInt(0, 100) < faction_mod)
if (zone->random.Int(0, 100) < faction_mod)
npc_value[i] *= 2;
}
}
@ -7804,11 +7806,11 @@ void Client::MerchantRejectMessage(Mob *merchant, int primaryfaction)
}
// If no primary faction or biggest influence is your faction hit
if (primaryfaction <= 0 || lowestvalue == tmpFactionValue) {
merchant->Say_StringID(MakeRandomInt(WONT_SELL_DEEDS1, WONT_SELL_DEEDS6));
merchant->Say_StringID(zone->random.Int(WONT_SELL_DEEDS1, WONT_SELL_DEEDS6));
} else if (lowestvalue == fmod.race_mod) { // race biggest
// Non-standard race (ex. illusioned to wolf)
if (GetRace() > PLAYER_RACE_COUNT) {
messageid = MakeRandomInt(1, 3); // these aren't sequential StringIDs :(
messageid = zone->random.Int(1, 3); // these aren't sequential StringIDs :(
switch (messageid) {
case 1:
messageid = WONT_SELL_NONSTDRACE1;
@ -7825,7 +7827,7 @@ void Client::MerchantRejectMessage(Mob *merchant, int primaryfaction)
}
merchant->Say_StringID(messageid);
} else { // normal player races
messageid = MakeRandomInt(1, 4);
messageid = zone->random.Int(1, 4);
switch (messageid) {
case 1:
messageid = WONT_SELL_RACE1;
@ -7846,7 +7848,7 @@ void Client::MerchantRejectMessage(Mob *merchant, int primaryfaction)
merchant->Say_StringID(messageid, itoa(GetRace()));
}
} else if (lowestvalue == fmod.class_mod) {
merchant->Say_StringID(MakeRandomInt(WONT_SELL_CLASS1, WONT_SELL_CLASS5), itoa(GetClass()));
merchant->Say_StringID(zone->random.Int(WONT_SELL_CLASS1, WONT_SELL_CLASS5), itoa(GetClass()));
}
return;
}
@ -7949,7 +7951,7 @@ void Client::TryItemTick(int slot)
if(zone->tick_items.count(iid) > 0)
{
if( GetLevel() >= zone->tick_items[iid].level && MakeRandomInt(0, 100) >= (100 - zone->tick_items[iid].chance) && (zone->tick_items[iid].bagslot || slot <= EmuConstants::EQUIPMENT_END) )
if( GetLevel() >= zone->tick_items[iid].level && zone->random.Int(0, 100) >= (100 - zone->tick_items[iid].chance) && (zone->tick_items[iid].bagslot || slot <= EmuConstants::EQUIPMENT_END) )
{
ItemInst* e_inst = (ItemInst*)inst;
parse->EventItem(EVENT_ITEM_TICK, this, e_inst, nullptr, "", slot);
@ -7968,7 +7970,7 @@ void Client::TryItemTick(int slot)
if(zone->tick_items.count(iid) > 0)
{
if( GetLevel() >= zone->tick_items[iid].level && MakeRandomInt(0, 100) >= (100 - zone->tick_items[iid].chance) )
if( GetLevel() >= zone->tick_items[iid].level && zone->random.Int(0, 100) >= (100 - zone->tick_items[iid].chance) )
{
ItemInst* e_inst = (ItemInst*)a_inst;
parse->EventItem(EVENT_ITEM_TICK, this, e_inst, nullptr, "", slot);

8389
zone/client.cpp.orig Normal file

File diff suppressed because it is too large Load Diff

View File

@ -810,7 +810,7 @@ public:
void QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call = false);
void PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootItem_Struct** bag_item_data = 0);
bool AutoPutLootInInventory(ItemInst& inst, bool try_worn = false, bool try_cursor = true, ServerLootItem_Struct** bag_item_data = 0);
bool SummonItem(uint32 item_id, int16 charges = -1, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, bool attuned = false, uint16 to_slot = MainCursor);
bool SummonItem(uint32 item_id, int16 charges = -1, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, bool attuned = false, uint16 to_slot = MainCursor, uint32 ornament_icon = 0, uint32 ornament_idfile = 0);
void SetStats(uint8 type,int16 set_val);
void IncStats(uint8 type,int16 increase_val);
void DropItem(int16 slot_id);

View File

@ -18,23 +18,17 @@
#include <algorithm>
#include "../common/debug.h"
#include "../common/spdat.h"
#include "../common/packet_dump.h"
#include "../common/packet_functions.h"
#include "../common/serverinfo.h"
#include "../common/zone_numbers.h"
#include "../common/moremath.h"
#include "../common/guilds.h"
#include "../common/logsys.h"
#include "../common/spdat.h"
#include "../common/rulesys.h"
#include "masterentity.h"
#include "worldserver.h"
#include "zonedb.h"
#include "npc_ai.h"
#include "petitions.h"
#include "string_ids.h"
#include "npc_ai.h"
#include "worldserver.h"
#include "zonedb.h"
// Return max stat value for level
int32 Client::GetMaxStat() const {
if((RuleI(Character, StatCap)) > 0)

View File

@ -16,14 +16,11 @@
*/
#include "../common/debug.h"
#include <assert.h>
#include <iomanip>
#include <iostream>
#include <math.h>
#include <set>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <zlib.h>
@ -38,39 +35,28 @@
#include <unistd.h>
#endif
#include "../common/packet_functions.h"
#include "../common/packet_dump.h"
#include "worldserver.h"
#include "../common/rdtsc.h"
#include "../common/packet_dump_file.h"
#include "../common/string_util.h"
#include "../common/breakdowns.h"
#include "../common/guilds.h"
#include "../common/rulesys.h"
#include "../common/spdat.h"
#include "../common/data_verification.h"
#include "petitions.h"
#include "npc_ai.h"
#include "../common/skills.h"
#include "forage.h"
#include "zone.h"
#include "event_codes.h"
#include "../common/faction.h"
#include "../common/crc32.h"
#include "../common/data_verification.h"
#include "../common/faction.h"
#include "../common/guilds.h"
#include "../common/rdtsc.h"
#include "../common/rulesys.h"
#include "../common/skills.h"
#include "../common/spdat.h"
#include "../common/string_util.h"
#include "../common/zone_numbers.h"
#include "event_codes.h"
#include "guild_mgr.h"
#include "merc.h"
#include "petitions.h"
#include "pets.h"
#include "queryserv.h"
#include "quest_parser_collection.h"
#include "string_ids.h"
#include "titles.h"
#include "water_map.h"
#include "worldserver.h"
#include "zone.h"
#include "zone_config.h"
#include "guild_mgr.h"
#include "pathing.h"
#include "water_map.h"
#include "merc.h"
#include "pets.h"
#include "../common/zone_numbers.h"
#include "quest_parser_collection.h"
#include "queryserv.h"
extern QueryServ* QServ;
extern Zone* zone;
@ -474,10 +460,10 @@ int Client::HandlePacket(const EQApplicationPacket *app)
mlog(CLIENT__NET_ERR, "Unhandled incoming opcode: %s", buffer);
if(app->size < 1000)
DumpPacket(app->pBuffer, app->size);
DumpPacket(app, app->size);
else{
std::cout << "Dump limited to 1000 characters:\n";
DumpPacket(app->pBuffer, 1000);
DumpPacket(app, 1000);
}
#endif
break;
@ -2968,7 +2954,7 @@ void Client::Handle_OP_ApplyPoison(const EQApplicationPacket *app)
if ((PrimaryWeapon && PrimaryWeapon->GetItem()->ItemType == ItemType1HPiercing) ||
(SecondaryWeapon && SecondaryWeapon->GetItem()->ItemType == ItemType1HPiercing)) {
float SuccessChance = (GetSkill(SkillApplyPoison) + GetLevel()) / 400.0f;
double ChanceRoll = MakeRandomFloat(0, 1);
double ChanceRoll = zone->random.Real(0, 1);
CheckIncreaseSkill(SkillApplyPoison, nullptr, 10);
@ -3642,14 +3628,14 @@ void Client::Handle_OP_Begging(const EQApplicationPacket *app)
return;
}
int RandomChance = MakeRandomInt(0, 100);
int RandomChance = zone->random.Int(0, 100);
int ChanceToAttack = 0;
if (GetLevel() > GetTarget()->GetLevel())
ChanceToAttack = MakeRandomInt(0, 15);
ChanceToAttack = zone->random.Int(0, 15);
else
ChanceToAttack = MakeRandomInt(((this->GetTarget()->GetLevel() - this->GetLevel()) * 10) - 5, ((this->GetTarget()->GetLevel() - this->GetLevel()) * 10));
ChanceToAttack = zone->random.Int(((this->GetTarget()->GetLevel() - this->GetLevel()) * 10) - 5, ((this->GetTarget()->GetLevel() - this->GetLevel()) * 10));
if (ChanceToAttack < 0)
ChanceToAttack = -ChanceToAttack;
@ -3668,7 +3654,7 @@ void Client::Handle_OP_Begging(const EQApplicationPacket *app)
if (RandomChance < ChanceToBeg)
{
brs->Amount = MakeRandomInt(1, 10);
brs->Amount = zone->random.Int(1, 10);
// This needs some work to determine how much money they can beg, based on skill level etc.
if (CurrentSkill < 50)
{
@ -4537,7 +4523,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app)
m_Delta = xyz_heading(ppu->delta_x, ppu->delta_y, ppu->delta_z, ppu->delta_heading);
if(IsTracking() && ((m_Position.m_X!=ppu->x_pos) || (m_Position.m_Y!=ppu->y_pos))){
if(MakeRandomFloat(0, 100) < 70)//should be good
if(zone->random.Real(0, 100) < 70)//should be good
CheckIncreaseSkill(SkillTracking, nullptr, -20);
}
@ -5235,16 +5221,16 @@ void Client::Handle_OP_DisarmTraps(const EQApplicationPacket *app)
if (trap && trap->detected)
{
int uskill = GetSkill(SkillDisarmTraps);
if ((MakeRandomInt(0, 49) + uskill) >= (MakeRandomInt(0, 49) + trap->skill))
if ((zone->random.Int(0, 49) + uskill) >= (zone->random.Int(0, 49) + trap->skill))
{
Message(MT_Skills, "You disarm a trap.");
trap->disarmed = true;
trap->chkarea_timer.Disable();
trap->respawn_timer.Start((trap->respawn_time + MakeRandomInt(0, trap->respawn_var)) * 1000);
trap->respawn_timer.Start((trap->respawn_time + zone->random.Int(0, trap->respawn_var)) * 1000);
}
else
{
if (MakeRandomInt(0, 99) < 25){
if (zone->random.Int(0, 99) < 25){
Message(MT_Skills, "You set off the trap while trying to disarm it!");
trap->Trigger(this);
}
@ -5605,7 +5591,7 @@ void Client::Handle_OP_FeignDeath(const EQApplicationPacket *app)
secfeign = 0;
uint16 totalfeign = primfeign + secfeign;
if (MakeRandomFloat(0, 160) > totalfeign) {
if (zone->random.Real(0, 160) > totalfeign) {
SetFeigned(false);
entity_list.MessageClose_StringID(this, false, 200, 10, STRING_FEIGNFAILED, GetName());
}
@ -7869,7 +7855,7 @@ void Client::Handle_OP_Hide(const EQApplicationPacket *app)
p_timers.Start(pTimerHide, reuse - 1);
float hidechance = ((GetSkill(SkillHide) / 250.0f) + .25) * 100;
float random = MakeRandomFloat(0, 100);
float random = zone->random.Real(0, 100);
CheckIncreaseSkill(SkillHide, nullptr, 5);
if (random < hidechance) {
EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct));
@ -7893,7 +7879,7 @@ void Client::Handle_OP_Hide(const EQApplicationPacket *app)
Mob *evadetar = GetTarget();
if (!auto_attack && (evadetar && evadetar->CheckAggro(this)
&& evadetar->IsNPC())) {
if (MakeRandomInt(0, 260) < (int)GetSkill(SkillHide)) {
if (zone->random.Int(0, 260) < (int)GetSkill(SkillHide)) {
msg->string_id = EVADE_SUCCESS;
RogueEvade(evadetar);
}
@ -8000,6 +7986,10 @@ void Client::Handle_OP_InspectAnswer(const EQApplicationPacket *app)
strcpy(insr->itemnames[L], item->Name);
insr->itemicons[L] = aug_weap->Icon;
}
else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) {
strcpy(insr->itemnames[L], item->Name);
insr->itemicons[L] = inst->GetOrnamentationIcon();
}
else {
strcpy(insr->itemnames[L], item->Name);
insr->itemicons[L] = item->Icon;
@ -9272,11 +9262,11 @@ void Client::Handle_OP_Mend(const EQApplicationPacket *app)
int mendhp = GetMaxHP() / 4;
int currenthp = GetHP();
if (MakeRandomInt(0, 199) < (int)GetSkill(SkillMend)) {
if (zone->random.Int(0, 199) < (int)GetSkill(SkillMend)) {
int criticalchance = spellbonuses.CriticalMend + itembonuses.CriticalMend + aabonuses.CriticalMend;
if (MakeRandomInt(0, 99) < criticalchance){
if (zone->random.Int(0, 99) < criticalchance){
mendhp *= 2;
Message_StringID(4, MEND_CRITICAL);
}
@ -9291,7 +9281,7 @@ void Client::Handle_OP_Mend(const EQApplicationPacket *app)
0 skill - 25% chance to worsen
20 skill - 23% chance to worsen
50 skill - 16% chance to worsen */
if ((GetSkill(SkillMend) <= 75) && (MakeRandomInt(GetSkill(SkillMend), 100) < 75) && (MakeRandomInt(1, 3) == 1))
if ((GetSkill(SkillMend) <= 75) && (zone->random.Int(GetSkill(SkillMend), 100) < 75) && (zone->random.Int(1, 3) == 1))
{
SetHP(currenthp > mendhp ? (GetHP() - mendhp) : 1);
SendHPUpdate();
@ -9598,7 +9588,7 @@ void Client::Handle_OP_MercenaryHire(const EQApplicationPacket *app)
TakeMoneyFromPP(cost, true);
}
// 0 is approved hire request
// approved hire request
SendMercMerchantResponsePacket(0);
}
else
@ -10596,37 +10586,28 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app)
case RaidCommandInviteIntoExisting:
case RaidCommandInvite: {
Client *i = entity_list.GetClientByName(ri->player_name);
if (i){
Group *g = i->GetGroup();
if (g){
if (g->IsLeader(i) == false)
Message(13, "You can only invite an ungrouped player or group leader to join your raid.");
else{
//This sends an "invite" to the client in question.
EQApplicationPacket* outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct));
RaidGeneral_Struct *rg = (RaidGeneral_Struct*)outapp->pBuffer;
strn0cpy(rg->leader_name, ri->leader_name, 64);
strn0cpy(rg->player_name, ri->player_name, 64);
rg->parameter = 0;
rg->action = 20;
i->QueuePacket(outapp);
safe_delete(outapp);
}
}
else{
//This sends an "invite" to the client in question.
EQApplicationPacket* outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct));
RaidGeneral_Struct *rg = (RaidGeneral_Struct*)outapp->pBuffer;
strn0cpy(rg->leader_name, ri->leader_name, 64);
strn0cpy(rg->player_name, ri->player_name, 64);
rg->parameter = 0;
rg->action = 20;
i->QueuePacket(outapp);
safe_delete(outapp);
}
if (!i)
break;
Group *g = i->GetGroup();
// These two messages should be generated by the client I think, just do this for now
if (i->HasRaid()) {
Message(13, "%s is already in a raid.", i->GetName());
break;
}
if (g && !g->IsLeader(i)) {
Message(13, "You can only invite an ungrouped player or group leader to join your raid.");
break;
}
//This sends an "invite" to the client in question.
EQApplicationPacket* outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct));
RaidGeneral_Struct *rg = (RaidGeneral_Struct*)outapp->pBuffer;
strn0cpy(rg->leader_name, ri->leader_name, 64);
strn0cpy(rg->player_name, ri->player_name, 64);
rg->parameter = 0;
rg->action = 20;
i->QueuePacket(outapp);
safe_delete(outapp);
break;
}
case RaidCommandAcceptInvite: {
@ -11192,7 +11173,7 @@ void Client::Handle_OP_RandomReq(const EQApplicationPacket *app)
randLow = 0;
randHigh = 100;
}
randResult = MakeRandomInt(randLow, randHigh);
randResult = zone->random.Int(randLow, randHigh);
EQApplicationPacket* outapp = new EQApplicationPacket(OP_RandomReply, sizeof(RandomReply_Struct));
RandomReply_Struct* rr = (RandomReply_Struct*)outapp->pBuffer;
@ -11682,7 +11663,7 @@ void Client::Handle_OP_SenseTraps(const EQApplicationPacket *app)
if (trap && trap->skill > 0) {
int uskill = GetSkill(SkillSenseTraps);
if ((MakeRandomInt(0, 99) + uskill) >= (MakeRandomInt(0, 99) + trap->skill*0.75))
if ((zone->random.Int(0, 99) + uskill) >= (zone->random.Int(0, 99) + trap->skill*0.75))
{
auto diff = trap->m_Position - GetPosition();
@ -12425,7 +12406,7 @@ void Client::Handle_OP_ShopRequest(const EQApplicationPacket *app)
// 1199 I don't have time for that now. etc
if (!tmp->CastToNPC()->IsMerchantOpen()) {
tmp->Say_StringID(MakeRandomInt(1199, 1202));
tmp->Say_StringID(zone->random.Int(1199, 1202));
action = 0;
}
@ -12480,7 +12461,7 @@ void Client::Handle_OP_Sneak(const EQApplicationPacket *app)
CheckIncreaseSkill(SkillSneak, nullptr, 5);
}
float hidechance = ((GetSkill(SkillSneak) / 300.0f) + .25) * 100;
float random = MakeRandomFloat(0, 99);
float random = zone->random.Real(0, 99);
if (!was && random < hidechance) {
sneaking = true;
}

14039
zone/client_packet.cpp.orig Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
// connecting opcode handlers
/* Connecting OpCode Handlers */
void Handle_Connect_0x3e33(const EQApplicationPacket *app);
void Handle_Connect_OP_ApproveZone(const EQApplicationPacket *app);
void Handle_Connect_OP_ClientError(const EQApplicationPacket *app);
@ -20,7 +20,7 @@
void Handle_Connect_OP_WorldObjectsSent(const EQApplicationPacket *app);
void Handle_Connect_OP_ZoneComplete(const EQApplicationPacket *app);
void Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app);
// connected opcode handlers
/* Connected opcode handlers*/
void Handle_0x0193(const EQApplicationPacket *app);
void Handle_0x01e7(const EQApplicationPacket *app);
void Handle_OP_AAAction(const EQApplicationPacket *app);

View File

@ -20,13 +20,8 @@
*/
#include "../common/debug.h"
#include <iostream>
#include <iomanip>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <zlib.h>
#include <assert.h>
#ifdef _WINDOWS
#include <windows.h>
@ -41,29 +36,20 @@
#include <unistd.h>
#endif
#include "masterentity.h"
#include "zonedb.h"
#include "../common/packet_functions.h"
#include "../common/packet_dump.h"
#include "worldserver.h"
#include "../common/packet_dump_file.h"
#include "../common/string_util.h"
#include "../common/spdat.h"
#include "petitions.h"
#include "npc_ai.h"
#include "../common/skills.h"
#include "forage.h"
#include "zone.h"
#include "event_codes.h"
#include "../common/faction.h"
#include "../common/crc32.h"
#include "../common/rulesys.h"
#include "string_ids.h"
#include "map.h"
#include "../common/skills.h"
#include "../common/spdat.h"
#include "../common/string_util.h"
#include "event_codes.h"
#include "guild_mgr.h"
#include <string>
#include "quest_parser_collection.h"
#include "map.h"
#include "petitions.h"
#include "queryserv.h"
#include "quest_parser_collection.h"
#include "string_ids.h"
#include "worldserver.h"
#include "zone.h"
#include "zonedb.h"
extern QueryServ* QServ;
extern Zone* zone;
@ -440,7 +426,7 @@ bool Client::Process() {
if (auto_attack_target && flurrychance)
{
if(MakeRandomInt(0, 99) < flurrychance)
if(zone->random.Int(0, 99) < flurrychance)
{
Message_StringID(MT_NPCFlurry, YOU_FLURRY);
Attack(auto_attack_target, MainPrimary, false);
@ -457,7 +443,7 @@ bool Client::Process() {
wpn->GetItem()->ItemType == ItemType2HBlunt ||
wpn->GetItem()->ItemType == ItemType2HPiercing )
{
if(MakeRandomInt(0, 99) < ExtraAttackChanceBonus)
if(zone->random.Int(0, 99) < ExtraAttackChanceBonus)
{
Attack(auto_attack_target, MainPrimary, false);
}
@ -502,7 +488,7 @@ bool Client::Process() {
int16 DWBonus = spellbonuses.DualWieldChance + itembonuses.DualWieldChance;
DualWieldProbability += DualWieldProbability*float(DWBonus)/ 100.0f;
float random = MakeRandomFloat(0, 1);
float random = zone->random.Real(0, 1);
CheckIncreaseSkill(SkillDualWield, auto_attack_target, -10);
if (random < DualWieldProbability){ // Max 78% of DW
if(CheckAAEffect(aaEffectRampage)) {
@ -567,9 +553,8 @@ bool Client::Process() {
viral_timer_counter = 0;
}
if(projectile_timer.Check())
SpellProjectileEffect();
ProjectileAttack();
if(spellbonuses.GravityEffect == 1) {
if(gravity_timer.Check())
DoGravityEffect();
@ -1006,7 +991,7 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) {
if (fac != 0 && GetModCharacterFactionLevel(fac) < ml.faction_required)
continue;
handychance = MakeRandomInt(0, merlist.size() + tmp_merlist.size() - 1);
handychance = zone->random.Int(0, merlist.size() + tmp_merlist.size() - 1);
item = database.GetItem(ml.item);
if (item) {
@ -1082,7 +1067,7 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) {
zone->tmpmerchanttable[npcid] = tmp_merlist;
if (merch != nullptr && handyitem) {
char handy_id[8] = { 0 };
int greeting = MakeRandomInt(0, 4);
int greeting = zone->random.Int(0, 4);
int greet_id = 0;
switch (greeting) {
case 1:
@ -1643,7 +1628,7 @@ void Client::OPGMTraining(const EQApplicationPacket *app)
// welcome message
if (pTrainer && pTrainer->IsNPC())
{
pTrainer->Say_StringID(MakeRandomInt(1204, 1207), GetCleanName());
pTrainer->Say_StringID(zone->random.Int(1204, 1207), GetCleanName());
}
}
@ -1670,7 +1655,7 @@ void Client::OPGMEndTraining(const EQApplicationPacket *app)
// goodbye message
if (pTrainer->IsNPC())
{
pTrainer->Say_StringID(MakeRandomInt(1208, 1211), GetCleanName());
pTrainer->Say_StringID(zone->random.Int(1208, 1211), GetCleanName());
}
}
@ -2162,7 +2147,7 @@ void Client::HandleRespawnFromHover(uint32 Option)
_log(SPELLS__REZ, "Found corpse. Marking corpse as rezzed.");
corpse->IsRezzed(true);
corpse->CompleteRezz();
corpse->CompleteResurrection();
}
}
else //Not rez

2427
zone/client_process.cpp.orig Normal file

File diff suppressed because it is too large Load Diff

View File

@ -42,38 +42,34 @@
#endif
#include "../common/debug.h"
#include "../common/ptimer.h"
#include "../common/packet_functions.h"
#include "../common/packet_dump.h"
#include "../common/serverinfo.h"
#include "../common/opcodemgr.h"
#include "../common/eq_packet.h"
#include "../common/guilds.h"
#include "../common/rulesys.h"
#include "../common/string_util.h"
//#include "../common/servertalk.h" // for oocmute and revoke
#include "worldserver.h"
#include "masterentity.h"
#include "map.h"
#include "water_map.h"
#include "../common/features.h"
#include "pathing.h"
#include "client_logs.h"
#include "guild_mgr.h"
#include "titles.h"
#include "../common/guilds.h"
#include "../common/patches/patches.h"
#include "../common/ptimer.h"
#include "../common/rulesys.h"
#include "../common/serverinfo.h"
#include "../common/string_util.h"
#include "client_logs.h"
#include "command.h"
#include "guild_mgr.h"
#include "map.h"
#include "pathing.h"
#include "qglobals.h"
#include "queryserv.h"
#include "quest_parser_collection.h"
#include "string_ids.h"
#include "titles.h"
#include "water_map.h"
#include "worldserver.h"
extern QueryServ* QServ;
extern WorldServer worldserver;
extern TaskManager *taskmanager;
void CatchSignal(int sig_num);
#include "quest_parser_collection.h"
#include "string_ids.h"
#include "command.h"
#include "qglobals.h"
//struct cl_struct *commandlist; // the actual linked list of commands
int commandcount; // how many commands we have
@ -3416,7 +3412,7 @@ void command_corpse(Client *c, const Seperator *sep)
c->Message(0, "Error: Target must be a player corpse.");
else if (c->Admin() >= commandEditPlayerCorpses && target->IsPlayerCorpse()) {
c->Message(0, "Depoping %s.", target->GetName());
target->CastToCorpse()->DepopCorpse();
target->CastToCorpse()->DepopPlayerCorpse();
if(!sep->arg[2][0] || atoi(sep->arg[2]) != 0)
target->CastToCorpse()->Bury();
}
@ -3901,7 +3897,7 @@ void command_save(Client *c, const Seperator *sep)
}
else if (c->GetTarget()->IsPlayerCorpse()) {
if (c->GetTarget()->CastToMob()->Save())
c->Message(0, "%s successfully saved. (dbid=%u)", c->GetTarget()->GetName(), c->GetTarget()->CastToCorpse()->GetDBID());
c->Message(0, "%s successfully saved. (dbid=%u)", c->GetTarget()->GetName(), c->GetTarget()->CastToCorpse()->GetCorpseDBID());
else
c->Message(0, "Manual save for %s failed.", c->GetTarget()->GetName());
}
@ -4984,189 +4980,10 @@ void command_randomfeatures(Client *c, const Seperator *sep)
c->Message(0,"Error: This command requires a target");
else
{
uint16 Race = target->GetRace();
if (Race <= 12 || Race == 128 || Race == 130 || Race == 330 || Race == 522) {
uint8 Gender = target->GetGender();
uint8 Texture = 0xFF;
uint8 HelmTexture = 0xFF;
uint8 HairColor = 0xFF;
uint8 BeardColor = 0xFF;
uint8 EyeColor1 = 0xFF;
uint8 EyeColor2 = 0xFF;
uint8 HairStyle = 0xFF;
uint8 LuclinFace = 0xFF;
uint8 Beard = 0xFF;
uint32 DrakkinHeritage = 0xFFFFFFFF;
uint32 DrakkinTattoo = 0xFFFFFFFF;
uint32 DrakkinDetails = 0xFFFFFFFF;
// Set some common feature settings
EyeColor1 = MakeRandomInt(0, 9);
EyeColor2 = MakeRandomInt(0, 9);
LuclinFace = MakeRandomInt(0, 7);
// Adjust all settings based on the min and max for each feature of each race and gender
switch (Race)
{
case 1: // Human
HairColor = MakeRandomInt(0, 19);
if (Gender == 0) {
BeardColor = HairColor;
HairStyle = MakeRandomInt(0, 3);
Beard = MakeRandomInt(0, 5);
}
if (Gender == 1) {
HairStyle = MakeRandomInt(0, 2);
}
break;
case 2: // Barbarian
HairColor = MakeRandomInt(0, 19);
LuclinFace = MakeRandomInt(0, 87);
if (Gender == 0) {
BeardColor = HairColor;
HairStyle = MakeRandomInt(0, 3);
Beard = MakeRandomInt(0, 5);
}
if (Gender == 1) {
HairStyle = MakeRandomInt(0, 2);
}
break;
case 3: // Erudite
if (Gender == 0) {
BeardColor = MakeRandomInt(0, 19);
Beard = MakeRandomInt(0, 5);
LuclinFace = MakeRandomInt(0, 57);
}
if (Gender == 1) {
LuclinFace = MakeRandomInt(0, 87);
}
break;
case 4: // WoodElf
HairColor = MakeRandomInt(0, 19);
if (Gender == 0) {
HairStyle = MakeRandomInt(0, 3);
}
if (Gender == 1) {
HairStyle = MakeRandomInt(0, 2);
}
break;
case 5: // HighElf
HairColor = MakeRandomInt(0, 14);
if (Gender == 0) {
HairStyle = MakeRandomInt(0, 3);
LuclinFace = MakeRandomInt(0, 37);
BeardColor = HairColor;
}
if (Gender == 1) {
HairStyle = MakeRandomInt(0, 2);
}
break;
case 6: // DarkElf
HairColor = MakeRandomInt(13, 18);
if (Gender == 0) {
HairStyle = MakeRandomInt(0, 3);
LuclinFace = MakeRandomInt(0, 37);
BeardColor = HairColor;
}
if (Gender == 1) {
HairStyle = MakeRandomInt(0, 2);
}
break;
case 7: // HalfElf
HairColor = MakeRandomInt(0, 19);
if (Gender == 0) {
HairStyle = MakeRandomInt(0, 3);
LuclinFace = MakeRandomInt(0, 37);
BeardColor = HairColor;
}
if (Gender == 1) {
HairStyle = MakeRandomInt(0, 2);
}
break;
case 8: // Dwarf
HairColor = MakeRandomInt(0, 19);
BeardColor = HairColor;
if (Gender == 0) {
HairStyle = MakeRandomInt(0, 3);
Beard = MakeRandomInt(0, 5);
}
if (Gender == 1) {
HairStyle = MakeRandomInt(0, 2);
LuclinFace = MakeRandomInt(0, 17);
}
break;
case 9: // Troll
EyeColor1 = MakeRandomInt(0, 10);
EyeColor2 = MakeRandomInt(0, 10);
if (Gender == 1) {
HairStyle = MakeRandomInt(0, 3);
HairColor = MakeRandomInt(0, 23);
}
break;
case 10: // Ogre
if (Gender == 1) {
HairStyle = MakeRandomInt(0, 3);
HairColor = MakeRandomInt(0, 23);
}
break;
case 11: // Halfling
HairColor = MakeRandomInt(0, 19);
if (Gender == 0) {
BeardColor = HairColor;
HairStyle = MakeRandomInt(0, 3);
Beard = MakeRandomInt(0, 5);
}
if (Gender == 1) {
HairStyle = MakeRandomInt(0, 2);
}
break;
case 12: // Gnome
HairColor = MakeRandomInt(0, 24);
if (Gender == 0) {
BeardColor = HairColor;
HairStyle = MakeRandomInt(0, 3);
Beard = MakeRandomInt(0, 5);
}
if (Gender == 1) {
HairStyle = MakeRandomInt(0, 2);
}
break;
case 128: // Iksar
case 130: // VahShir
break;
case 330: // Froglok
LuclinFace = MakeRandomInt(0, 9);
case 522: // Drakkin
HairColor = MakeRandomInt(0, 3);
BeardColor = HairColor;
EyeColor1 = MakeRandomInt(0, 11);
EyeColor2 = MakeRandomInt(0, 11);
LuclinFace = MakeRandomInt(0, 6);
DrakkinHeritage = MakeRandomInt(0, 6);
DrakkinTattoo = MakeRandomInt(0, 7);
DrakkinDetails = MakeRandomInt(0, 7);
if (Gender == 0) {
Beard = MakeRandomInt(0, 12);
HairStyle = MakeRandomInt(0, 8);
}
if (Gender == 1) {
Beard = MakeRandomInt(0, 3);
HairStyle = MakeRandomInt(0, 7);
}
break;
default:
break;
}
target->SendIllusionPacket(Race, Gender, Texture, HelmTexture, HairColor, BeardColor,
EyeColor1, EyeColor2, HairStyle, LuclinFace, Beard, 0xFF,
DrakkinHeritage, DrakkinTattoo, DrakkinDetails);
c->Message(0,"NPC Features Randomized");
}
if (target->RandomizeFeatures())
c->Message(0,"Features Randomized");
else
c->Message(0,"This command requires a Playable Race as the Target");
c->Message(0,"This command requires a Playable Race as the target");
}
}
@ -9999,7 +9816,8 @@ void command_object(Client *c, const Seperator *sep)
// Couldn't copy the object.
if (results.ErrorMessage().c_str() != '\0') {
// got an error message
if (!results.Success()) {
c->Message(0, "Database Error: %s", results.ErrorMessage().c_str());
return;
}

View File

@ -20,9 +20,10 @@
#ifndef COMMAND_H
#define COMMAND_H
#include "../common/seperator.h"
#include "../common/eq_stream.h"
#include "client.h"
class Client;
class Seperator;
#include "../common/types.h"
#define COMMAND_CHAR '#'
#define CMDALIASES 5

View File

@ -459,6 +459,24 @@ struct Shielders_Struct {
uint16 shielder_bonus;
};
typedef struct
{
uint16 increment;
uint16 hit_increment;
uint16 target_id;
int32 wpn_dmg;
float origin_x;
float origin_y;
float origin_z;
float tlast_x;
float tlast_y;
uint32 ranged_id;
uint32 ammo_id;
int ammo_slot;
uint8 skill;
float speed_mod;
} tProjatk;
//eventually turn this into a typedef and
//make DoAnim take it instead of int, to enforce its use.
enum { //type arguments to DoAnim

View File

@ -63,7 +63,7 @@ void Corpse::SendLootReqErrorPacket(Client* client, uint8 response) {
safe_delete(outapp);
}
Corpse* Corpse::LoadFromDBData(uint32 in_dbid, uint32 in_charid, std::string in_charname, const xyz_heading& position, std::string time_of_death, bool rezzed, bool was_at_graveyard)
Corpse* Corpse::LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std::string in_charname, const xyz_heading& position, std::string time_of_death, bool rezzed, bool was_at_graveyard)
{
uint32 item_count = database.GetCharacterCorpseItemCount(in_dbid);
char *buffer = new char[sizeof(PlayerCorpse_Struct) + (item_count * sizeof(player_lootitem::ServerLootItem_Struct))];
@ -76,7 +76,6 @@ Corpse* Corpse::LoadFromDBData(uint32 in_dbid, uint32 in_charid, std::string in_
for (unsigned int i = 0; i < pcs->itemcount; i++) {
tmp = new ServerLootItem_Struct;
memcpy(tmp, &pcs->items[i], sizeof(player_lootitem::ServerLootItem_Struct));
tmp->equip_slot = CorpseToServerSlot(tmp->equip_slot);
itemlist.push_back(tmp);
}
@ -147,13 +146,15 @@ Corpse::Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NP
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0xff,0,0,0,0,0,0,0,0,0),
corpse_decay_timer(in_decaytime),
corpse_res_timer(0),
corpse_rez_timer(0),
corpse_delay_timer(RuleI(NPC, CorpseUnlockTimer)),
corpse_graveyard_timer(0),
loot_cooldown_timer(10)
{
corpse_graveyard_timer.Disable();
memset(item_tint, 0, sizeof(item_tint));
is_corpse_changed = false;
is_player_corpse = false;
is_locked = false;
@ -166,11 +167,11 @@ Corpse::Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NP
SetCash(in_npc->GetCopper(), in_npc->GetSilver(), in_npc->GetGold(), in_npc->GetPlatinum());
npctype_id = in_npctypeid;
SetPKItem(0);
SetPlayerKillItemID(0);
char_id = 0;
corpse_db_id = 0;
player_corpse_depop = false;
strcpy(orgname, in_npc->GetName());
strcpy(corpse_name, in_npc->GetName());
strcpy(name, in_npc->GetName());
// Added By Hogie
for(int count = 0; count < 100; count++) {
@ -183,6 +184,7 @@ Corpse::Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NP
corpse_decay_timer.SetTimer(RuleI(NPC,EmptyNPCCorpseDecayTimeMS)+1000);
}
if(in_npc->HasPrivateCorpse()) {
corpse_delay_timer.SetTimer(corpse_decay_timer.GetRemainingTime() + 1000);
}
@ -191,7 +193,7 @@ Corpse::Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NP
for (int i = 0; i < MAX_LOOTERS; i++){
allowed_looters[i] = 0;
}
this->rezzexp = 0;
this->rez_experience = 0;
}
Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
@ -244,7 +246,7 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
0 // uint32 in_scalerate
),
corpse_decay_timer(RuleI(Character, CorpseDecayTimeMS)),
corpse_res_timer(RuleI(Character, CorpseResTimeMS)),
corpse_rez_timer(RuleI(Character, CorpseResTimeMS)),
corpse_delay_timer(RuleI(NPC, CorpseUnlockTimer)),
corpse_graveyard_timer(RuleI(Zone, GraveyardTimeMS)),
loot_cooldown_timer(10)
@ -266,8 +268,8 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
}
is_corpse_changed = true;
rezzexp = in_rezexp;
can_rez = true;
rez_experience = in_rezexp;
can_corpse_be_rezzed = true;
is_player_corpse = true;
is_locked = false;
being_looted_by = 0xFFFFFFFF;
@ -279,13 +281,13 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
gold = 0;
platinum = 0;
strcpy(orgname, pp->name);
strcpy(corpse_name, pp->name);
strcpy(name, pp->name);
/* become_npc was not being initialized which led to some pretty funky things with newly created corpses */
become_npc = false;
SetPKItem(0);
SetPlayerKillItemID(0);
/* Check Rule to see if we can leave corpses */
if(!RuleB(Character, LeaveNakedCorpses) ||
@ -335,9 +337,9 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
// this was mainly for client profile state reflection..should match db player inventory entries now.
iter_queue it;
for(it=client->GetInv().cursor_begin(),i=8001; it!=client->GetInv().cursor_end(); ++it,i++) {
for (it = client->GetInv().cursor_begin(), i = 8001; it != client->GetInv().cursor_end(); ++it, i++) {
item = *it;
if((item && (!client->IsBecomeNPC())) || (item && client->IsBecomeNPC() && !item->GetItem()->NoRent)) {
if ((item && (!client->IsBecomeNPC())) || (item && client->IsBecomeNPC() && !item->GetItem()->NoRent)) {
std::list<uint32> slot_list = MoveItemToCorpse(client, item, i);
removed_list.merge(slot_list);
cursor = true;
@ -346,16 +348,17 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
}
database.TransactionBegin();
if(removed_list.size() != 0) {
if (removed_list.size() != 0) {
std::stringstream ss("");
ss << "DELETE FROM inventory WHERE charid=" << client->CharacterID();
ss << " AND (";
std::list<uint32>::const_iterator iter = removed_list.begin();
bool first = true;
while(iter != removed_list.end()) {
if(first) {
while (iter != removed_list.end()) {
if (first) {
first = false;
} else {
}
else {
ss << " OR ";
}
ss << "slotid=" << (*iter);
@ -365,8 +368,8 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
database.QueryDatabase(ss.str().c_str());
}
if(cursor) { // all cursor items should be on corpse (client < SoF or RespawnFromHover = false)
while(!client->GetInv().CursorEmpty())
if (cursor) { // all cursor items should be on corpse (client < SoF or RespawnFromHover = false)
while (!client->GetInv().CursorEmpty())
client->DeleteItemInInventory(MainCursor, 0, false, false);
}
else { // only visible cursor made it to corpse (client >= Sof and RespawnFromHover = true)
@ -401,13 +404,13 @@ std::list<uint32> Corpse::MoveItemToCorpse(Client *client, ItemInst *item, int16
returnlist.push_back(equipslot);
// Qualified bag slot iterations. processing bag slots that don't exist is probably not a good idea.
if(item->IsType(ItemClassContainer) && ((equipslot >= EmuConstants::GENERAL_BEGIN && equipslot <= MainCursor))) {
for(bagindex = SUB_BEGIN; bagindex <= EmuConstants::ITEM_CONTAINER_SIZE; bagindex++) {
if (item->IsType(ItemClassContainer) && ((equipslot >= EmuConstants::GENERAL_BEGIN && equipslot <= MainCursor))) {
for (bagindex = SUB_BEGIN; bagindex <= EmuConstants::ITEM_CONTAINER_SIZE; bagindex++) {
// For empty bags in cursor queue, slot was previously being resolved as SLOT_INVALID (-1)
interior_slot = Inventory::CalcSlotId(equipslot, bagindex);
interior_item = client->GetInv().GetItem(interior_slot);
if(interior_item) {
if (interior_item) {
AddItem(interior_item->GetItem()->ID, interior_item->GetCharges(), interior_slot, interior_item->GetAugmentItemID(0), interior_item->GetAugmentItemID(1), interior_item->GetAugmentItemID(2), interior_item->GetAugmentItemID(3), interior_item->GetAugmentItemID(4));
returnlist.push_back(Inventory::CalcSlotId(equipslot, bagindex));
client->DeleteItemInInventory(interior_slot, 0, true, false);
@ -469,7 +472,7 @@ in_helmtexture,
0,
0),
corpse_decay_timer(RuleI(Character, CorpseDecayTimeMS)),
corpse_res_timer(RuleI(Character, CorpseResTimeMS)),
corpse_rez_timer(RuleI(Character, CorpseResTimeMS)),
corpse_delay_timer(RuleI(NPC, CorpseUnlockTimer)),
corpse_graveyard_timer(RuleI(Zone, GraveyardTimeMS)),
loot_cooldown_timer(10)
@ -477,7 +480,7 @@ in_helmtexture,
LoadPlayerCorpseDecayTime(in_dbid);
if(!zone->HasGraveyard() || wasAtGraveyard)
if (!zone->HasGraveyard() || wasAtGraveyard)
corpse_graveyard_timer.Disable();
memset(item_tint, 0, sizeof(item_tint));
@ -492,23 +495,25 @@ in_helmtexture,
itemlist = *in_itemlist;
in_itemlist->clear();
strcpy(orgname, in_charname);
strcpy(corpse_name, in_charname);
strcpy(name, in_charname);
this->copper = in_copper;
this->silver = in_silver;
this->gold = in_gold;
this->platinum = in_plat;
rezzexp = in_rezexp;
for (int i = 0; i < MAX_LOOTERS; i++)
rez_experience = in_rezexp;
for (int i = 0; i < MAX_LOOTERS; i++){
allowed_looters[i] = 0;
SetPKItem(0);
}
SetPlayerKillItemID(0);
}
Corpse::~Corpse() {
if (is_player_corpse && !(player_corpse_depop && corpse_db_id == 0)) {
Save();
Save();
}
ItemList::iterator cur,end;
cur = itemlist.begin();
@ -562,7 +567,7 @@ bool Corpse::Save() {
dbpc->level = level;
dbpc->texture = this->texture;
dbpc->helmtexture = this->helmtexture;
dbpc->exp = rezzexp;
dbpc->exp = rez_experience;
memcpy(dbpc->item_tint, item_tint, sizeof(dbpc->item_tint));
dbpc->haircolor = haircolor;
@ -581,17 +586,16 @@ bool Corpse::Save() {
end = itemlist.end();
for (; cur != end; ++cur) {
ServerLootItem_Struct* item = *cur;
item->equip_slot = ServerToCorpseSlot(item->equip_slot); // temp hack until corpse blobs are removed
memcpy((char*)&dbpc->items[x++], (char*)item, sizeof(ServerLootItem_Struct));
}
/* Create New Corpse*/
if (corpse_db_id == 0) {
corpse_db_id = database.SaveCharacterCorpse(char_id, orgname, zone->GetZoneID(), zone->GetInstanceID(), dbpc, m_Position);
corpse_db_id = database.SaveCharacterCorpse(char_id, corpse_name, zone->GetZoneID(), zone->GetInstanceID(), dbpc, m_Position);
}
/* Update Corpse Data */
else{
corpse_db_id = database.UpdateCharacterCorpse(corpse_db_id, char_id, orgname, zone->GetZoneID(), zone->GetInstanceID(), dbpc, m_Position, IsRezzed());
corpse_db_id = database.UpdateCharacterCorpse(corpse_db_id, char_id, corpse_name, zone->GetZoneID(), zone->GetInstanceID(), dbpc, m_Position, IsRezzed());
}
safe_delete_array(dbpc);
@ -615,13 +619,13 @@ void Corpse::Bury() {
player_corpse_depop = true;
}
void Corpse::Depop() {
void Corpse::DepopNPCCorpse() {
if (IsNPCCorpse())
player_corpse_depop = true;
}
void Corpse::DepopCorpse() {
player_corpse_depop = true;
void Corpse::DepopPlayerCorpse() {
player_corpse_depop = true;
}
uint32 Corpse::CountItems() {
@ -633,7 +637,9 @@ void Corpse::AddItem(uint32 itemnum, uint16 charges, int16 slot, uint32 aug1, ui
return;
is_corpse_changed = true;
ServerLootItem_Struct* item = new ServerLootItem_Struct;
memset(item, 0, sizeof(ServerLootItem_Struct));
item->item_id = itemnum;
item->charges = charges;
@ -665,9 +671,9 @@ ServerLootItem_Struct* Corpse::GetItem(uint16 lootslot, ServerLootItem_Struct**
cur = itemlist.begin();
end = itemlist.end();
for(; cur != end; ++cur) {
for (; cur != end; ++cur) {
sitem2 = *cur;
if(sitem2->equip_slot >= bagstart && sitem2->equip_slot < bagstart + 10) {
if (sitem2->equip_slot >= bagstart && sitem2->equip_slot < bagstart + 10) {
bag_item_data[sitem2->equip_slot - bagstart] = sitem2;
}
}
@ -697,7 +703,7 @@ void Corpse::RemoveItem(uint16 lootslot) {
ItemList::iterator cur,end;
cur = itemlist.begin();
end = itemlist.end();
for(; cur != end; ++cur) {
for (; cur != end; ++cur) {
ServerLootItem_Struct* sitem = *cur;
if (sitem->lootslot == lootslot) {
RemoveItem(sitem);
@ -747,6 +753,7 @@ void Corpse::RemoveCash() {
bool Corpse::IsEmpty() const {
if (copper != 0 || silver != 0 || gold != 0 || platinum != 0)
return false;
return(itemlist.size() == 0);
}
@ -754,8 +761,8 @@ bool Corpse::Process() {
if (player_corpse_depop)
return false;
if(corpse_delay_timer.Check()) {
for (int i=0; i<MAX_LOOTERS; i++)
if (corpse_delay_timer.Check()) {
for (int i = 0; i < MAX_LOOTERS; i++)
allowed_looters[i] = 0;
corpse_delay_timer.Disable();
return true;
@ -787,18 +794,26 @@ bool Corpse::Process() {
corpse_res_timer.Disable();
}
*/
if(corpse_decay_timer.Check()) {
if(!RuleB(Zone, EnableShadowrest))
/* This is when a corpse hits decay timer and does checks*/
if (corpse_decay_timer.Check()) {
/* NPC */
if (IsNPCCorpse()){
corpse_decay_timer.Disable();
return false;
}
/* Client */
if (!RuleB(Zone, EnableShadowrest)){
Delete();
}
else {
if(database.BuryCharacterCorpse(corpse_db_id)) {
if (database.BuryCharacterCorpse(corpse_db_id)) {
Save();
player_corpse_depop = true;
corpse_db_id = 0;
LogFile->write(EQEMuLog::Debug, "Tagged %s player corpse has burried.", this->GetName());
}
else
{
else {
LogFile->write(EQEMuLog::Error, "Unable to bury %s player corpse.", this->GetName());
return true;
}
@ -817,22 +832,21 @@ void Corpse::SetDecayTimer(uint32 decaytime) {
corpse_decay_timer.Start(decaytime);
}
bool Corpse::CanMobLoot(int charid) {
uint8 z=0;
for(int i=0; i<MAX_LOOTERS; i++) {
if(allowed_looters[i] != 0)
z++;
bool Corpse::CanPlayerLoot(int charid) {
uint8 looters = 0;
for (int i = 0; i < MAX_LOOTERS; i++) {
if (allowed_looters[i] != 0){
looters++;
}
if (allowed_looters[i] == charid)
return true;
}
if(z == 0)
return true;
else
return false;
/* If we have no looters, obviously client can loot */
return looters == 0;
}
void Corpse::AllowMobLoot(Mob *them, uint8 slot) {
void Corpse::AllowPlayerLoot(Mob *them, uint8 slot) {
if(slot >= MAX_LOOTERS)
return;
if(them == nullptr || !them->IsClient())
@ -863,31 +877,48 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
return;
}
if(being_looted_by == 0) { being_looted_by = 0xFFFFFFFF; }
if(being_looted_by == 0)
being_looted_by = 0xFFFFFFFF;
if(this->being_looted_by != 0xFFFFFFFF) {
// lets double check....
Entity* looter = entity_list.GetID(this->being_looted_by);
if(looter == 0) { this->being_looted_by = 0xFFFFFFFF; }
if(looter == 0)
this->being_looted_by = 0xFFFFFFFF;
}
uint8 tCanLoot = 1;
bool lootcoin = false;
if(database.GetVariable("LootCoin", tmp, 9)) { lootcoin = (atoi(tmp) == 1); }
uint8 Loot_Request_Type = 1;
bool loot_coin = false;
if(database.GetVariable("LootCoin", tmp, 9))
loot_coin = (atoi(tmp) == 1);
if(this->being_looted_by != 0xFFFFFFFF && this->being_looted_by != client->GetID()) {
if (this->being_looted_by != 0xFFFFFFFF && this->being_looted_by != client->GetID()) {
SendLootReqErrorPacket(client, 0);
tCanLoot = 0;
Loot_Request_Type = 0;
}
else if (IsPlayerCorpse() && char_id == client->CharacterID()) {
Loot_Request_Type = 2;
}
else if ((IsNPCCorpse() || become_npc) && CanPlayerLoot(client->CharacterID())) {
Loot_Request_Type = 2;
}
else if (GetPlayerKillItem() == -1 && CanPlayerLoot(client->CharacterID())) { /* PVP loot all items, variable cash */
Loot_Request_Type = 3;
}
else if (GetPlayerKillItem() == 1 && CanPlayerLoot(client->CharacterID())) { /* PVP loot 1 item, variable cash */
Loot_Request_Type = 4;
}
else if (GetPlayerKillItem() > 1 && CanPlayerLoot(client->CharacterID())) { /* PVP loot 1 set item, variable cash */
Loot_Request_Type = 5;
}
else if(IsPlayerCorpse() && char_id == client->CharacterID()) { tCanLoot = 2; }
else if((IsNPCCorpse() || become_npc) && CanMobLoot(client->CharacterID())) { tCanLoot = 2; }
else if(GetPKItem() == -1 && CanMobLoot(client->CharacterID())) { tCanLoot = 3; } //pvp loot all items, variable cash
else if(GetPKItem() == 1 && CanMobLoot(client->CharacterID())) { tCanLoot = 4; } //pvp loot 1 item, variable cash
else if(GetPKItem() > 1 && CanMobLoot(client->CharacterID())) { tCanLoot = 5; } //pvp loot 1 set item, variable cash
if(tCanLoot == 1) { if(client->Admin() < 100 || !client->GetGM()) { SendLootReqErrorPacket(client, 2); } }
if (Loot_Request_Type == 1) {
if (client->Admin() < 100 || !client->GetGM()) {
SendLootReqErrorPacket(client, 2);
}
}
if(tCanLoot >= 2 || (tCanLoot == 1 && client->Admin() >= 100 && client->GetGM())) {
if(Loot_Request_Type >= 2 || (Loot_Request_Type == 1 && client->Admin() >= 100 && client->GetGM())) {
this->being_looted_by = client->GetID();
EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoneyOnCorpse, sizeof(moneyOnCorpseStruct));
moneyOnCorpseStruct* d = (moneyOnCorpseStruct*) outapp->pBuffer;
@ -895,8 +926,9 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
d->response = 1;
d->unknown1 = 0x42;
d->unknown2 = 0xef;
if(tCanLoot == 2 || (tCanLoot >= 3 && lootcoin)) { // dont take the coin off if it's a gm peeking at the corpse
/* Dont take the coin off if it's a gm peeking at the corpse */
if(Loot_Request_Type == 2 || (Loot_Request_Type >= 3 && loot_coin)) {
if(!IsPlayerCorpse() && client->IsGrouped() && client->AutoSplitEnabled() && client->GetGroup()) {
d->copper = 0;
d->silver = 0;
@ -920,15 +952,15 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
outapp->priority = 6;
client->QueuePacket(outapp);
safe_delete(outapp);
if(tCanLoot == 5) {
int pkitem = GetPKItem();
if(Loot_Request_Type == 5) {
int pkitem = GetPlayerKillItem();
const Item_Struct* item = database.GetItem(pkitem);
ItemInst* inst = database.CreateItem(item, item->MaxCharges);
if(inst) {
client->SendItemPacket(EmuConstants::CORPSE_BEGIN, inst, ItemPacketLoot);
safe_delete(inst);
}
else { client->Message(13, "Could not find item number %i to send!!", GetPKItem()); }
else { client->Message(13, "Could not find item number %i to send!!", GetPlayerKillItem()); }
client->QueuePacket(app);
return;
@ -940,8 +972,6 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
cur = itemlist.begin();
end = itemlist.end();
uint8 containercount = 0;
int corpselootlimit = EQLimits::InventoryMapSize(MapCorpse, client->GetClientVersion());
for(; cur != end; ++cur) {
@ -951,7 +981,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
// Dont display the item if it's in a bag
// Added cursor queue slots to corpse item visibility list. Nothing else should be making it to corpse.
if(!IsPlayerCorpse() || item_data->equip_slot <= MainCursor || item_data->equip_slot == MainPowerSource || tCanLoot>=3 ||
if(!IsPlayerCorpse() || item_data->equip_slot <= MainCursor || item_data->equip_slot == MainPowerSource || Loot_Request_Type>=3 ||
(item_data->equip_slot >= 8000 && item_data->equip_slot <= 8999)) {
if(i < corpselootlimit) {
item = database.GetItem(item_data->item_id);
@ -981,14 +1011,14 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
if(IsPlayerCorpse() && i == 0 && itemlist.size() > 0) { // somehow, player corpse contains items, but client doesn't see them...
client->Message(13, "This corpse contains items that are inaccessable!");
client->Message(15, "Contact a GM for item replacement, if necessary.");
client->Message(15, "BUGGED CORPSE [DBID: %i, Name: %s, Item Count: %i]", GetDBID(), GetName(), itemlist.size());
client->Message(15, "BUGGED CORPSE [DBID: %i, Name: %s, Item Count: %i]", GetCorpseDBID(), GetName(), itemlist.size());
cur = itemlist.begin();
end = itemlist.end();
for(; cur != end; ++cur) {
ServerLootItem_Struct* item_data = *cur;
item = database.GetItem(item_data->item_id);
LogFile->write(EQEMuLog::Debug, "Corpse Looting: %s was not sent to client loot window (corpse_dbid: %i, charname: %s(%s))", item->Name, GetDBID(), client->GetName(), client->GetGM() ? "GM" : "Owner");
LogFile->write(EQEMuLog::Debug, "Corpse Looting: %s was not sent to client loot window (corpse_dbid: %i, charname: %s(%s))", item->Name, GetCorpseDBID(), client->GetName(), client->GetGM() ? "GM" : "Owner");
client->Message(0, "Inaccessable Corpse Item: %s", item->Name);
}
}
@ -1034,7 +1064,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) {
SendEndLootErrorPacket(client);
return;
}
if (IsPlayerCorpse() && !CanMobLoot(client->CharacterID()) && !become_npc && (char_id != client->CharacterID() && client->Admin() < 150)) {
if (IsPlayerCorpse() && !CanPlayerLoot(client->CharacterID()) && !become_npc && (char_id != client->CharacterID() && client->Admin() < 150)) {
client->Message(13, "Error: This is a player corpse and you dont own it.");
SendEndLootErrorPacket(client);
return;
@ -1044,7 +1074,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) {
client->Message(13, "Error: Corpse locked by GM.");
return;
}
if (IsPlayerCorpse() && (char_id != client->CharacterID()) && CanMobLoot(client->CharacterID()) && GetPKItem() == 0){
if (IsPlayerCorpse() && (char_id != client->CharacterID()) && CanPlayerLoot(client->CharacterID()) && GetPlayerKillItem() == 0){
client->Message(13, "Error: You cannot loot any more items from this corpse.");
SendEndLootErrorPacket(client);
being_looted_by = 0xFFFFFFFF;
@ -1055,17 +1085,17 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) {
ServerLootItem_Struct* item_data = nullptr, *bag_item_data[10];
memset(bag_item_data, 0, sizeof(bag_item_data));
if (GetPKItem() > 1){
item = database.GetItem(GetPKItem());
if (GetPlayerKillItem() > 1){
item = database.GetItem(GetPlayerKillItem());
}
else if (GetPKItem() == -1 || GetPKItem() == 1){
else if (GetPlayerKillItem() == -1 || GetPlayerKillItem() == 1){
item_data = GetItem(lootitem->slot_id - EmuConstants::CORPSE_BEGIN); //dont allow them to loot entire bags of items as pvp reward
}
else{
item_data = GetItem(lootitem->slot_id - EmuConstants::CORPSE_BEGIN, bag_item_data);
}
if (GetPKItem()<=1 && item_data != 0) {
if (GetPlayerKillItem()<=1 && item_data != 0) {
item = database.GetItem(item_data->item_id);
}
@ -1104,7 +1134,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) {
char buf[88];
char corpse_name[64];
strcpy(corpse_name, orgname);
strcpy(corpse_name, corpse_name);
snprintf(buf, 87, "%d %d %s", inst->GetItem()->ID, inst->GetCharges(), EntityList::RemoveNumbers(corpse_name));
buf[87] = '\0';
std::vector<EQEmu::Any> args;
@ -1149,7 +1179,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) {
}
/* Remove Bag Contents */
if (item->ItemClass == ItemClassContainer && (GetPKItem() != -1 || GetPKItem() != 1)) {
if (item->ItemClass == ItemClassContainer && (GetPlayerKillItem() != -1 || GetPlayerKillItem() != 1)) {
for (int i = SUB_BEGIN; i < EmuConstants::ITEM_CONTAINER_SIZE; i++) {
if (bag_item_data[i]) {
/* Delete needs to be before RemoveItem because its deletes the pointer for item_data/bag_item_data */
@ -1160,8 +1190,8 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) {
}
}
if (GetPKItem() != -1){
SetPKItem(0);
if (GetPlayerKillItem() != -1){
SetPlayerKillItemID(0);
}
/* Send message with item link to groups and such */
@ -1211,7 +1241,6 @@ void Corpse::EndLoot(Client* client, const EQApplicationPacket* app) {
client->QueuePacket(outapp);
safe_delete(outapp);
//client->Save(); //inventory operations auto-commit
this->being_looted_by = 0xFFFFFFFF;
if (this->IsEmpty())
Delete();
@ -1275,7 +1304,7 @@ void Corpse::QueryLoot(Client* to) {
}
if (IsPlayerCorpse()) {
to->Message(0, "%i visible %s (%i total) on %s (DBID: %i).", x, x==1?"item":"items", y, this->GetName(), this->GetDBID());
to->Message(0, "%i visible %s (%i total) on %s (DBID: %i).", x, x==1?"item":"items", y, this->GetName(), this->GetCorpseDBID());
}
else {
to->Message(0, "%i %s on %s.", y, y==1?"item":"items", this->GetName());
@ -1330,8 +1359,8 @@ bool Corpse::Summon(Client* client, bool spell, bool CheckDistance) {
return true;
}
void Corpse::CompleteRezz(){
rezzexp = 0;
void Corpse::CompleteResurrection(){
rez_experience = 0;
is_corpse_changed = true;
this->Save();
}
@ -1375,7 +1404,7 @@ uint32 Corpse::GetEquipmentColor(uint8 material_slot) const {
}
void Corpse::AddLooter(Mob* who) {
for (int i=0; i<MAX_LOOTERS; i++) {
for (int i = 0; i < MAX_LOOTERS; i++) {
if (allowed_looters[i] == 0) {
allowed_looters[i] = who->CastToClient()->CharacterID();
break;
@ -1400,111 +1429,5 @@ void Corpse::LoadPlayerCorpseDecayTime(uint32 corpse_db_id){
else {
corpse_graveyard_timer.SetTimer(3000);
}
}
/*
** Corpse slot translations are needed until corpse database blobs are converted
**
** To account for the addition of MainPowerSource, MainGeneral9 and MainGeneral10 into
** the contiguous possessions slot enumeration, the following designations will be used:
**
** Designatiom Server Corpse Offset
** --------------------------------------------------
** MainCharm 0 0 0
** ... ... ... 0
** MainWaist 20 20 0
** MainPowerSource 21 9999 +9978
** MainAmmo 22 21 -1
**
** MainGeneral1 23 22 -1
** ... ... ... -1
** MainGeneral8 30 29 -1
** MainGeneral9 31 9997 +9966
** MainGeneral10 32 9998 +9966
**
** MainCursor 33 30 -3
**
** MainGeneral1_1 251 251 0
** ... ... ... 0
** MainGeneral8_10 330 330 0
** MainGeneral9_1 331 341 +10
** ... ... ... +10
** MainGeneral10_10 350 360 +10
**
** MainCursor_1 351 331 -20
** ... ... ... -20
** MainCursor_10 360 340 -20
**
** (Not all slot designations are valid to all clients..see <client>##_constants.h files for valid slot enumerations)
*/
int16 Corpse::ServerToCorpseSlot(int16 server_slot)
{
return server_slot; // temporary return
/*
switch (server_slot)
{
case MainPowerSource:
return 9999;
case MainGeneral9:
return 9997;
case MainGeneral10:
return 9998;
case MainCursor:
return 30;
case MainAmmo:
case MainGeneral1:
case MainGeneral2:
case MainGeneral3:
case MainGeneral4:
case MainGeneral5:
case MainGeneral6:
case MainGeneral7:
case MainGeneral8:
return server_slot - 1;
default:
if (server_slot >= EmuConstants::CURSOR_BAG_BEGIN && server_slot <= EmuConstants::CURSOR_BAG_END)
return server_slot - 20;
else if (server_slot >= EmuConstants::GENERAL_BAGS_END - 19 && server_slot <= EmuConstants::GENERAL_BAGS_END)
return server_slot + 10;
else
return server_slot;
}
*/
}
int16 Corpse::CorpseToServerSlot(int16 corpse_slot)
{
return corpse_slot; // temporary return
/*
switch (corpse_slot)
{
case 9999:
return MainPowerSource;
case 9997:
return MainGeneral9;
case 9998:
return MainGeneral10;
case 30:
return MainCursor;
case 21: // old SLOT_AMMO
case 22: // old PERSONAL_BEGIN
case 23:
case 24:
case 25:
case 26:
case 27:
case 28:
case 29: // old PERSONAL_END
return corpse_slot + 1;
default:
if (corpse_slot >= 331 && corpse_slot <= 340)
return corpse_slot + 20;
else if (corpse_slot >= 341 && corpse_slot <= 360)
return corpse_slot - 10;
else
return corpse_slot;
}
*/
}

1676
zone/corpse.cpp.orig Normal file

File diff suppressed because it is too large Load Diff

View File

@ -27,7 +27,7 @@ class NPC;
#define MAX_LOOTERS 72
class Corpse : public Mob {
public:
public:
static void SendEndLootErrorPacket(Client* client);
static void SendLootReqErrorPacket(Client* client, uint8 response = 2);
@ -35,114 +35,118 @@ public:
Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NPCType** in_npctypedata, uint32 in_decaytime = 600000);
Corpse(Client* client, int32 in_rezexp);
Corpse(uint32 in_corpseid, uint32 in_charid, const char* in_charname, ItemList* in_itemlist, uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_plat, const xyz_heading& position, float in_size, uint8 in_gender, uint16 in_race, uint8 in_class, uint8 in_deity, uint8 in_level, uint8 in_texture, uint8 in_helmtexture, uint32 in_rezexp, bool wasAtGraveyard = false);
~Corpse();
static Corpse* LoadFromDBData(uint32 in_dbid, uint32 in_charid, std::string in_charname, const xyz_heading& position, std::string time_of_death, bool rezzed, bool was_at_graveyard);
//abstract virtual function implementations requird by base abstract class
~Corpse();
static Corpse* LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std::string in_charname, const xyz_heading& position, std::string time_of_death, bool rezzed, bool was_at_graveyard);
/* Corpse: General */
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) { return true; }
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false) { return; }
virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false,
bool IsStrikethrough = true, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) { return false; }
virtual bool HasRaid() { return false; }
virtual bool HasGroup() { return false; }
virtual Raid* GetRaid() { return 0; }
virtual Group* GetGroup() { return 0; }
void LoadPlayerCorpseDecayTime(uint32 dbid);
virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = true, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) { return false; }
virtual bool HasRaid() { return false; }
virtual bool HasGroup() { return false; }
virtual Raid* GetRaid() { return 0; }
virtual Group* GetGroup() { return 0; }
inline uint32 GetCorpseDBID() { return corpse_db_id; }
inline char* GetOwnerName() { return corpse_name; }
bool IsEmpty() const;
bool IsCorpse() const { return true; }
bool IsPlayerCorpse() const { return is_player_corpse; }
bool IsNPCCorpse() const { return !is_player_corpse; }
bool IsBecomeNPCCorpse() const { return become_npc; }
virtual void DepopNPCCorpse();
virtual void DepopPlayerCorpse();
bool Process();
bool Save();
uint32 GetCharID() { return char_id; }
uint32 SetCharID(uint32 iCharID) { if (IsPlayerCorpse()) { return (char_id = iCharID); } return 0xFFFFFFFF; };
uint32 GetDecayTime() { if (!corpse_decay_timer.Enabled()) return 0xFFFFFFFF; else return corpse_decay_timer.GetRemainingTime(); }
uint32 GetResTime() { if (!corpse_res_timer.Enabled()) return 0; else return corpse_res_timer.GetRemainingTime(); }
void CalcCorpseName();
inline void Lock() { is_locked = true; }
inline void UnLock() { is_locked = false; }
inline bool IsLocked() { return is_locked; }
inline void ResetLooter() { being_looted_by = 0xFFFFFFFF; }
inline bool IsBeingLooted() { return (being_looted_by != 0xFFFFFFFF); }
inline uint32 GetDBID() { return corpse_db_id; }
inline char* GetOwnerName() { return orgname;}
uint32 GetCharID() { return char_id; }
uint32 SetCharID(uint32 iCharID) { if (IsPlayerCorpse()) { return (char_id = iCharID); } return 0xFFFFFFFF; };
uint32 GetDecayTime() { if (!corpse_decay_timer.Enabled()) return 0xFFFFFFFF; else return corpse_decay_timer.GetRemainingTime(); }
uint32 GetRezTime() { if (!corpse_rez_timer.Enabled()) return 0; else return corpse_rez_timer.GetRemainingTime(); }
void SetDecayTimer(uint32 decay_time);
void SetDecayTimer(uint32 decaytime);
bool IsEmpty() const;
void AddItem(uint32 itemnum, uint16 charges, int16 slot = 0, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0);
void Delete();
void Bury();
void CalcCorpseName();
void LoadPlayerCorpseDecayTime(uint32 dbid);
/* Corpse: Items */
uint32 GetWornItem(int16 equipSlot) const;
ServerLootItem_Struct* GetItem(uint16 lootslot, ServerLootItem_Struct** bag_item_data = 0);
void RemoveItem(uint16 lootslot);
void RemoveItem(ServerLootItem_Struct* item_data);
void SetCash(uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_platinum);
void RemoveCash();
void QueryLoot(Client* to);
uint32 CountItems();
void Delete();
void Bury();
virtual void Depop();
virtual void DepopCorpse();
void SetPlayerKillItemID(int32 pk_item_id) { player_kill_item = pk_item_id; }
int32 GetPlayerKillItem() { return player_kill_item; }
void RemoveItem(uint16 lootslot);
void RemoveItem(ServerLootItem_Struct* item_data);
void AddItem(uint32 itemnum, uint16 charges, int16 slot = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0);
/* Corpse: Coin */
void SetCash(uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_platinum);
void RemoveCash();
uint32 GetCopper() { return copper; }
uint32 GetSilver() { return silver; }
uint32 GetGold() { return gold; }
uint32 GetPlatinum() { return platinum; }
void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
void MakeLootRequestPackets(Client* client, const EQApplicationPacket* app);
void LootItem(Client* client, const EQApplicationPacket* app);
void EndLoot(Client* client, const EQApplicationPacket* app);
bool Summon(Client* client, bool spell, bool CheckDistance);
void CastRezz(uint16 spellid, Mob* Caster);
void CompleteRezz();
void SetPKItem(int32 id) { player_kill_item = id; }
int32 GetPKItem() { return player_kill_item; }
bool CanMobLoot(int charid);
void AllowMobLoot(Mob *them, uint8 slot);
void AddLooter(Mob *who);
/* Corpse: Resurrection */
bool IsRezzed() { return rez; }
void IsRezzed(bool in_rez) { rez = in_rez; }
void Spawn();
void CastRezz(uint16 spellid, Mob* Caster);
void CompleteResurrection();
char orgname[64];
uint32 GetEquipment(uint8 material_slot) const; // returns item id
/* Corpse: Loot */
void QueryLoot(Client* to);
void LootItem(Client* client, const EQApplicationPacket* app);
void EndLoot(Client* client, const EQApplicationPacket* app);
void MakeLootRequestPackets(Client* client, const EQApplicationPacket* app);
void AllowPlayerLoot(Mob *them, uint8 slot);
void AddLooter(Mob *who);
uint32 CountItems();
bool CanPlayerLoot(int charid);
inline void Lock() { is_locked = true; }
inline void UnLock() { is_locked = false; }
inline bool IsLocked() { return is_locked; }
inline void ResetLooter() { being_looted_by = 0xFFFFFFFF; }
inline bool IsBeingLooted() { return (being_looted_by != 0xFFFFFFFF); }
/* Mob */
void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
bool Summon(Client* client, bool spell, bool CheckDistance);
void Spawn();
char corpse_name[64];
uint32 GetEquipment(uint8 material_slot) const;
uint32 GetEquipmentColor(uint8 material_slot) const;
inline int GetRezzExp() { return rezzexp; }
// these are a temporary work-around until corpse inventory is removed from the database blob
static int16 ServerToCorpseSlot(int16 server_slot); // encode
static int16 CorpseToServerSlot(int16 corpse_slot); // decode
inline int GetRezExp() { return rez_experience; }
protected:
std::list<uint32> MoveItemToCorpse(Client *client, ItemInst *item, int16 equipslot);
private:
bool is_player_corpse;
bool is_corpse_changed;
bool is_locked;
int32 player_kill_item;
uint32 corpse_db_id;
uint32 char_id;
ItemList itemlist;
bool is_player_corpse; /* Determines if Player Corpse or not */
bool is_corpse_changed; /* Determines if corpse has changed or not */
bool is_locked; /* Determines if corpse is locked */
int32 player_kill_item; /* Determines if Player Kill Item */
uint32 corpse_db_id; /* Corpse Database ID (Player Corpse) */
uint32 char_id; /* Character ID */
ItemList itemlist; /* Internal Item list used for corpses */
uint32 copper;
uint32 silver;
uint32 gold;
uint32 platinum;
bool player_corpse_depop;
uint32 being_looted_by;
uint32 rezzexp;
bool player_corpse_depop; /* Sets up Corpse::Process to depop the player corpse */
uint32 being_looted_by; /* Determines what the corpse is being looted by internally for logic */
uint32 rez_experience; /* Amount of experience that the corpse would rez for */
bool rez;
bool can_rez;
bool can_corpse_be_rezzed; /* Bool declaring whether or not a corpse can be rezzed */
bool become_npc;
int allowed_looters[MAX_LOOTERS]; // People allowed to loot the corpse, character id
Timer corpse_decay_timer;
Timer corpse_res_timer;
int allowed_looters[MAX_LOOTERS]; /* People allowed to loot the corpse, character id */
Timer corpse_decay_timer; /* The amount of time in millseconds in which a corpse will take to decay (Depop/Poof) */
Timer corpse_rez_timer; /* The amount of time in millseconds in which a corpse can be rezzed */
Timer corpse_delay_timer;
Timer corpse_graveyard_timer;
Timer loot_cooldown_timer;
Timer loot_cooldown_timer; /* Delay between loot actions on the corpse entity */
Color_Struct item_tint[9];
};
#endif

190
zone/corpse.h.orig Normal file
View File

@ -0,0 +1,190 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef CORPSE_H
#define CORPSE_H
#include "mob.h"
class Client;
class NPC;
#define MAX_LOOTERS 72
class Corpse : public Mob {
public:
static void SendEndLootErrorPacket(Client* client);
static void SendLootReqErrorPacket(Client* client, uint8 response = 2);
Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NPCType** in_npctypedata, uint32 in_decaytime = 600000);
Corpse(Client* client, int32 in_rezexp);
<<<<<<< HEAD
Corpse(uint32 in_corpseid, uint32 in_charid, const char* in_charname, ItemList* in_itemlist, uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_plat, const xyz_heading& position, float in_size, uint8 in_gender, uint16 in_race, uint8 in_class, uint8 in_deity, uint8 in_level, uint8 in_texture, uint8 in_helmtexture, uint32 in_rezexp, bool wasAtGraveyard = false);
~Corpse();
static Corpse* LoadFromDBData(uint32 in_dbid, uint32 in_charid, std::string in_charname, const xyz_heading& position, std::string time_of_death, bool rezzed, bool was_at_graveyard);
=======
Corpse(uint32 in_corpseid, uint32 in_charid, const char* in_charname, ItemList* in_itemlist, uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_plat, float in_x, float in_y, float in_z, float in_heading, float in_size, uint8 in_gender, uint16 in_race, uint8 in_class, uint8 in_deity, uint8 in_level, uint8 in_texture, uint8 in_helmtexture, uint32 in_rezexp, bool wasAtGraveyard = false);
~Corpse();
static Corpse* LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std::string in_charname, float in_x, float in_y, float in_z, float in_heading, std::string time_of_death, bool rezzed, bool was_at_graveyard);
>>>>>>> master
/* Corpse: General */
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) { return true; }
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false) { return; }
virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false,
<<<<<<< HEAD
bool IsStrikethrough = true, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) { return false; }
virtual bool HasRaid() { return false; }
virtual bool HasGroup() { return false; }
virtual Raid* GetRaid() { return 0; }
virtual Group* GetGroup() { return 0; }
void LoadPlayerCorpseDecayTime(uint32 dbid);
=======
bool IsStrikethrough = true, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) {
return false;
}
virtual bool HasRaid() { return false; }
virtual bool HasGroup() { return false; }
virtual Raid* GetRaid() { return 0; }
virtual Group* GetGroup() { return 0; }
inline uint32 GetCorpseDBID() { return corpse_db_id; }
inline char* GetOwnerName() { return corpse_name; }
bool IsEmpty() const;
>>>>>>> master
bool IsCorpse() const { return true; }
bool IsPlayerCorpse() const { return is_player_corpse; }
bool IsNPCCorpse() const { return !is_player_corpse; }
bool IsBecomeNPCCorpse() const { return become_npc; }
virtual void DepopNPCCorpse();
virtual void DepopPlayerCorpse();
bool Process();
bool Save();
uint32 GetCharID() { return char_id; }
uint32 SetCharID(uint32 iCharID) { if (IsPlayerCorpse()) { return (char_id = iCharID); } return 0xFFFFFFFF; };
uint32 GetDecayTime() { if (!corpse_decay_timer.Enabled()) return 0xFFFFFFFF; else return corpse_decay_timer.GetRemainingTime(); }
uint32 GetRezTime() { if (!corpse_rez_timer.Enabled()) return 0; else return corpse_rez_timer.GetRemainingTime(); }
void SetDecayTimer(uint32 decay_time);
void Delete();
void Bury();
void CalcCorpseName();
void LoadPlayerCorpseDecayTime(uint32 dbid);
/* Corpse: Items */
uint32 GetWornItem(int16 equipSlot) const;
ServerLootItem_Struct* GetItem(uint16 lootslot, ServerLootItem_Struct** bag_item_data = 0);
void SetPlayerKillItemID(int32 pk_item_id) { player_kill_item = pk_item_id; }
int32 GetPlayerKillItem() { return player_kill_item; }
void RemoveItem(uint16 lootslot);
void RemoveItem(ServerLootItem_Struct* item_data);
void AddItem(uint32 itemnum, uint16 charges, int16 slot = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0);
/* Corpse: Coin */
void SetCash(uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_platinum);
void RemoveCash();
uint32 GetCopper() { return copper; }
uint32 GetSilver() { return silver; }
uint32 GetGold() { return gold; }
uint32 GetPlatinum() { return platinum; }
/* Corpse: Resurrection */
bool IsRezzed() { return rez; }
void IsRezzed(bool in_rez) { rez = in_rez; }
void CastRezz(uint16 spellid, Mob* Caster);
void CompleteResurrection();
/* Corpse: Loot */
void QueryLoot(Client* to);
void LootItem(Client* client, const EQApplicationPacket* app);
void EndLoot(Client* client, const EQApplicationPacket* app);
void MakeLootRequestPackets(Client* client, const EQApplicationPacket* app);
void AllowPlayerLoot(Mob *them, uint8 slot);
void AddLooter(Mob *who);
uint32 CountItems();
bool CanPlayerLoot(int charid);
inline void Lock() { is_locked = true; }
inline void UnLock() { is_locked = false; }
inline bool IsLocked() { return is_locked; }
inline void ResetLooter() { being_looted_by = 0xFFFFFFFF; }
inline bool IsBeingLooted() { return (being_looted_by != 0xFFFFFFFF); }
/* Mob */
void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
bool Summon(Client* client, bool spell, bool CheckDistance);
void Spawn();
char corpse_name[64];
uint32 GetEquipment(uint8 material_slot) const;
uint32 GetEquipmentColor(uint8 material_slot) const;
inline int GetRezExp() { return rez_experience; }
protected:
std::list<uint32> MoveItemToCorpse(Client *client, ItemInst *item, int16 equipslot);
private:
<<<<<<< HEAD
bool is_player_corpse;
bool is_corpse_changed;
bool is_locked;
int32 player_kill_item;
uint32 corpse_db_id;
uint32 char_id;
ItemList itemlist;
uint32 copper;
=======
bool is_player_corpse; /* Determines if Player Corpse or not */
bool is_corpse_changed; /* Determines if corpse has changed or not */
bool is_locked; /* Determines if corpse is locked */
int32 player_kill_item; /* Determines if Player Kill Item */
uint32 corpse_db_id; /* Corpse Database ID (Player Corpse) */
uint32 char_id; /* Character ID */
ItemList itemlist; /* Internal Item list used for corpses */
uint32 copper;
>>>>>>> master
uint32 silver;
uint32 gold;
uint32 platinum;
bool player_corpse_depop; /* Sets up Corpse::Process to depop the player corpse */
uint32 being_looted_by; /* Determines what the corpse is being looted by internally for logic */
uint32 rez_experience; /* Amount of experience that the corpse would rez for */
bool rez;
bool can_corpse_be_rezzed; /* Bool declaring whether or not a corpse can be rezzed */
bool become_npc;
<<<<<<< HEAD
int allowed_looters[MAX_LOOTERS]; // People allowed to loot the corpse, character id
Timer corpse_decay_timer;
Timer corpse_res_timer;
Timer corpse_delay_timer;
=======
int allowed_looters[MAX_LOOTERS]; /* People allowed to loot the corpse, character id */
Timer corpse_decay_timer; /* The amount of time in millseconds in which a corpse will take to decay (Depop/Poof) */
Timer corpse_rez_timer; /* The amount of time in millseconds in which a corpse can be rezzed */
Timer corpse_delay_timer;
>>>>>>> master
Timer corpse_graveyard_timer;
Timer loot_cooldown_timer; /* Delay between loot actions on the corpse entity */
Color_Struct item_tint[9];
};
#endif

View File

@ -55,30 +55,25 @@ int32 NPC::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
else
value -= target->GetFcDamageAmtIncoming(this, spell_id)/spells[spell_id].buffduration;
}
value += dmg*GetSpellFocusDMG()/100;
value += dmg*GetSpellFocusDMG()/100;
if (AI_HasSpellsEffects()){
int16 chance = 0;
int ratio = 0;
if (spells[spell_id].buffduration == 0) {
chance += spellbonuses.CriticalSpellChance + spellbonuses.FrenziedDevastation;
if (chance && MakeRandomInt(1,100) <= chance){
if (chance && zone->random.Roll(chance)) {
ratio += spellbonuses.SpellCritDmgIncrease + spellbonuses.SpellCritDmgIncNoStack;
value += (value*ratio)/100;
entity_list.MessageClose_StringID(this, true, 100, MT_SpellCrits, OTHER_CRIT_BLAST, GetCleanName(), itoa(-value));
}
}
else {
chance += spellbonuses.CriticalDoTChance;
if (chance && MakeRandomInt(1,100) <= chance){
if (chance && zone->random.Roll(chance)) {
ratio += spellbonuses.DotCritDmgIncrease;
value += (value*ratio)/100;
}
@ -119,14 +114,14 @@ int32 Client::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
if (spell_id == SPELL_IMP_HARM_TOUCH && (GetAA(aaSpellCastingFury) > 0) && (GetAA(aaUnholyTouch) > 0))
chance = 100;
if (MakeRandomInt(1,100) <= chance){
if (zone->random.Roll(chance)) {
Critical = true;
ratio += itembonuses.SpellCritDmgIncrease + spellbonuses.SpellCritDmgIncrease + aabonuses.SpellCritDmgIncrease;
ratio += itembonuses.SpellCritDmgIncNoStack + spellbonuses.SpellCritDmgIncNoStack + aabonuses.SpellCritDmgIncNoStack;
}
else if (GetClass() == WIZARD && (GetLevel() >= RuleI(Spells, WizCritLevel)) && (MakeRandomInt(1,100) <= RuleI(Spells, WizCritChance))) {
ratio += MakeRandomInt(20,70); //Wizard innate critical chance is calculated seperately from spell effect and is not a set ratio. (20-70 is parse confirmed)
else if (GetClass() == WIZARD && (GetLevel() >= RuleI(Spells, WizCritLevel)) && (zone->random.Roll(RuleI(Spells, WizCritChance)))) {
ratio += zone->random.Int(20,70); //Wizard innate critical chance is calculated seperately from spell effect and is not a set ratio. (20-70 is parse confirmed)
Critical = true;
}
@ -193,22 +188,16 @@ int32 Client::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) {
if (spellbonuses.CriticalDotDecay)
chance += GetDecayEffectValue(spell_id, SE_CriticalDotDecay);
value_BaseEffect = value + (value*GetFocusEffect(focusFcBaseEffects, spell_id)/100);
if (chance > 0 && (MakeRandomInt(1, 100) <= chance)) {
if (chance > 0 && (zone->random.Roll(chance))) {
int32 ratio = 200;
ratio += itembonuses.DotCritDmgIncrease + spellbonuses.DotCritDmgIncrease + aabonuses.DotCritDmgIncrease;
value = value_BaseEffect*ratio/100;
value += int(value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100)*ratio/100;
value = value_BaseEffect*ratio/100;
value += int(value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100)*ratio/100;
value += int(value_BaseEffect*GetFocusEffect(focusFcDamagePctCrit, spell_id)/100)*ratio/100;
value += int(value_BaseEffect*target->GetVulnerability(this, spell_id, 0)/100)*ratio/100;
value += int(value_BaseEffect*target->GetVulnerability(this, spell_id, 0)/100)*ratio/100;
extra_dmg = target->GetFcDamageAmtIncoming(this, spell_id) +
int(GetFocusEffect(focusFcDamageAmtCrit, spell_id)*ratio/100) +
GetFocusEffect(focusFcDamageAmt, spell_id);
@ -216,7 +205,7 @@ int32 Client::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) {
if (extra_dmg) {
int duration = CalcBuffDuration(this, this, spell_id);
if (duration > 0)
extra_dmg /= duration;
extra_dmg /= duration;
}
value -= extra_dmg;
@ -224,25 +213,20 @@ int32 Client::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) {
return value;
}
value = value_BaseEffect;
value += value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100;
value += value_BaseEffect*GetFocusEffect(focusFcDamagePctCrit, spell_id)/100;
value += value_BaseEffect*target->GetVulnerability(this, spell_id, 0)/100;
extra_dmg = target->GetFcDamageAmtIncoming(this, spell_id) +
value += value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100;
value += value_BaseEffect*GetFocusEffect(focusFcDamagePctCrit, spell_id)/100;
value += value_BaseEffect*target->GetVulnerability(this, spell_id, 0)/100;
extra_dmg = target->GetFcDamageAmtIncoming(this, spell_id) +
GetFocusEffect(focusFcDamageAmtCrit, spell_id) +
GetFocusEffect(focusFcDamageAmt, spell_id);
GetFocusEffect(focusFcDamageAmt, spell_id);
if (extra_dmg) {
int duration = CalcBuffDuration(this, this, spell_id);
if (duration > 0)
extra_dmg /= duration;
}
extra_dmg /= duration;
}
value -= extra_dmg;
return value;
@ -275,28 +259,26 @@ int32 NPC::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
//Scale all NPC spell healing via SetSpellFocusHeal(value)
value += value*GetSpellFocusHeal()/100;
value += value*GetSpellFocusHeal()/100;
if (target) {
value += target->GetFocusIncoming(focusFcHealAmtIncoming, SE_FcHealAmtIncoming, this, spell_id);
value += target->GetFocusIncoming(focusFcHealAmtIncoming, SE_FcHealAmtIncoming, this, spell_id);
value += value*target->GetHealRate(spell_id, this)/100;
}
//Allow for critical heal chance if NPC is loading spell effect bonuses.
if (AI_HasSpellsEffects()){
if(spells[spell_id].buffduration < 1) {
if(spellbonuses.CriticalHealChance && (MakeRandomInt(0,99) < spellbonuses.CriticalHealChance)) {
value = value*2;
if(spellbonuses.CriticalHealChance && (zone->random.Roll(spellbonuses.CriticalHealChance))) {
value = value*2;
entity_list.MessageClose_StringID(this, true, 100, MT_SpellCrits, OTHER_CRIT_HEAL, GetCleanName(), itoa(value));
}
}
else if(spellbonuses.CriticalHealOverTime && (MakeRandomInt(0,99) < spellbonuses.CriticalHealOverTime)) {
value = value*2;
else if(spellbonuses.CriticalHealOverTime && (zone->random.Roll(spellbonuses.CriticalHealOverTime))) {
value = value*2;
}
}
return value;
}
@ -326,7 +308,7 @@ int32 Client::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
if (spellbonuses.CriticalHealDecay)
chance += GetDecayEffectValue(spell_id, SE_CriticalHealDecay);
if(chance && (MakeRandomInt(0,99) < chance)) {
if(chance && (zone->random.Roll(chance))) {
Critical = true;
modifier = 2; //At present time no critical heal amount modifier SPA exists.
}
@ -360,7 +342,7 @@ int32 Client::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
if (spellbonuses.CriticalRegenDecay)
chance += GetDecayEffectValue(spell_id, SE_CriticalRegenDecay);
if(chance && (MakeRandomInt(0,99) < chance))
if(chance && zone->random.Roll(chance))
return (value * 2);
}
@ -374,12 +356,12 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost)
int16 FrenziedDevastation = itembonuses.FrenziedDevastation + spellbonuses.FrenziedDevastation + aabonuses.FrenziedDevastation;
if (FrenziedDevastation && IsPureNukeSpell(spell_id))
cost *= 2;
cost *= 2;
// Formula = Unknown exact, based off a random percent chance up to mana cost(after focuses) of the cast spell
if(this->itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5)
{
int16 mana_back = this->itembonuses.Clairvoyance * MakeRandomInt(1, 100) / 100;
int16 mana_back = this->itembonuses.Clairvoyance * zone->random.Int(1, 100) / 100;
// Doesnt generate mana, so best case is a free spell
if(mana_back > cost)
mana_back = cost;
@ -392,7 +374,7 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost)
// WildcardX
float PercentManaReduction = 0;
float SpecializeSkill = GetSpecializeSkillValue(spell_id);
int SuccessChance = MakeRandomInt(0, 100);
int SuccessChance = zone->random.Int(0, 100);
float bonus = 1.0;
switch(GetAA(aaSpellCastingMastery))
@ -444,7 +426,7 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost)
if(focus_redux > 0)
{
PercentManaReduction += MakeRandomFloat(1, (double)focus_redux);
PercentManaReduction += zone->random.Real(1, (double)focus_redux);
}
cost -= (cost * (PercentManaReduction / 100));

View File

@ -1515,7 +1515,7 @@ XS(XS__ChooseRandom)
if (items < 1)
Perl_croak(aTHX_ "Usage: ChooseRandom(... list ...)");
int index = MakeRandomInt(0, items-1);
int index = zone->random.Int(0, items-1);
SV *tmp = ST(0);
ST(0) = ST(index);

View File

@ -19,7 +19,6 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>
#include <string.h>
#include <iostream>
@ -30,19 +29,16 @@
#include "../common/unix.h"
#endif
#include "net.h"
#include "masterentity.h"
#include "worldserver.h"
#include "../common/guilds.h"
#include "../common/packet_dump.h"
#include "../common/packet_functions.h"
#include "petitions.h"
#include "../common/spdat.h"
#include "../common/features.h"
#include "string_ids.h"
#include "../common/guilds.h"
#include "../common/spdat.h"
#include "guild_mgr.h"
#include "raids.h"
#include "net.h"
#include "petitions.h"
#include "quest_parser_collection.h"
#include "raids.h"
#include "string_ids.h"
#include "worldserver.h"
#ifdef _WINDOWS
#define snprintf _snprintf
@ -632,7 +628,7 @@ void EntityList::AddCorpse(Corpse *corpse, uint32 in_id)
void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue)
{
npc->SetID(GetFreeID());
npc->SetMerchantProbability((uint8) MakeRandomInt(0, 99));
npc->SetMerchantProbability((uint8) zone->random.Int(0, 99));
parse->EventNPC(EVENT_SPAWN, npc, nullptr, "", 0);
uint16 emoteid = npc->GetEmoteID();
@ -662,10 +658,12 @@ void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue)
void EntityList::AddMerc(Merc *merc, bool SendSpawnPacket, bool dontqueue)
{
if (merc) {
if (merc)
{
merc->SetID(GetFreeID());
if (SendSpawnPacket) {
if (SendSpawnPacket)
{
if (dontqueue) {
// Send immediately
EQApplicationPacket *outapp = new EQApplicationPacket();
@ -677,12 +675,10 @@ void EntityList::AddMerc(Merc *merc, bool SendSpawnPacket, bool dontqueue)
// Queue the packet
NewSpawn_Struct *ns = new NewSpawn_Struct;
memset(ns, 0, sizeof(NewSpawn_Struct));
merc->FillSpawnStruct(ns, merc);
merc->FillSpawnStruct(ns, 0);
AddToSpawnQueue(merc->GetID(), &ns);
safe_delete(ns);
}
//parse->EventMERC(EVENT_SPAWN, merc, nullptr, "", 0);
}
merc_list.insert(std::pair<uint16, Merc *>(merc->GetID(), merc));
@ -1573,7 +1569,7 @@ Client *EntityList::GetRandomClient(const xyz_location& location, float Distance
if (ClientsInRange.empty())
return nullptr;
return ClientsInRange[MakeRandomInt(0, ClientsInRange.size() - 1)];
return ClientsInRange[zone->random.Int(0, ClientsInRange.size() - 1)];
}
Corpse *EntityList::GetCorpseByOwner(Client *client)
@ -1605,7 +1601,7 @@ Corpse *EntityList::GetCorpseByDBID(uint32 dbid)
{
auto it = corpse_list.begin();
while (it != corpse_list.end()) {
if (it->second->GetDBID() == dbid)
if (it->second->GetCorpseDBID() == dbid)
return it->second;
++it;
}
@ -1659,7 +1655,7 @@ void EntityList::RemoveCorpseByDBID(uint32 dbid)
{
auto it = corpse_list.begin();
while (it != corpse_list.end()) {
if (it->second->GetDBID() == dbid) {
if (it->second->GetCorpseDBID() == dbid) {
safe_delete(it->second);
free_ids.push(it->first);
it = corpse_list.erase(it);
@ -1676,9 +1672,9 @@ int EntityList::RezzAllCorpsesByCharID(uint32 charid)
auto it = corpse_list.begin();
while (it != corpse_list.end()) {
if (it->second->GetCharID() == charid) {
RezzExp += it->second->GetRezzExp();
RezzExp += it->second->GetRezExp();
it->second->IsRezzed(true);
it->second->CompleteRezz();
it->second->CompleteResurrection();
}
++it;
}
@ -2654,7 +2650,7 @@ int32 EntityList::DeleteNPCCorpses()
auto it = corpse_list.begin();
while (it != corpse_list.end()) {
if (it->second->IsNPCCorpse()) {
it->second->Depop();
it->second->DepopNPCCorpse();
x++;
}
++it;
@ -2893,7 +2889,7 @@ void EntityList::ClearFeignAggro(Mob *targ)
it->second->RemoveFromHateList(targ);
if (targ->IsClient()) {
if (it->second->GetLevel() >= 35 && MakeRandomInt(1, 100) <= 60)
if (it->second->GetLevel() >= 35 && zone->random.Roll(60))
it->second->AddFeignMemory(targ->CastToClient());
else
targ->CastToClient()->RemoveXTarget(it->second, false);
@ -3640,7 +3636,8 @@ void EntityList::AddTempPetsToHateList(Mob *owner, Mob* other, bool bFrenzy)
NPC* n = it->second;
if (n->GetSwarmInfo()) {
if (n->GetSwarmInfo()->owner_id == owner->GetID()) {
n->CastToNPC()->hate_list.Add(other, 0, 0, bFrenzy);
if (!n->GetSpecialAbility(IMMUNE_AGGRO))
n->hate_list.Add(other, 0, 0, bFrenzy);
}
}
++it;
@ -4499,7 +4496,7 @@ void EntityList::AddLootToNPCS(uint32 item_id, uint32 count)
selection.push_back(j);
while (selection.size() > 0 && count > 0) {
int k = MakeRandomInt(0, selection.size() - 1);
int k = zone->random.Int(0, selection.size() - 1);
counts[selection[k]]++;
count--;
selection.erase(selection.begin() + k);
@ -4681,6 +4678,6 @@ Mob *EntityList::GetTargetForVirus(Mob *spreader, int range)
if(TargetsInRange.size() == 0)
return nullptr;
return TargetsInRange[MakeRandomInt(0, TargetsInRange.size() - 1)];
return TargetsInRange[zone->random.Int(0, TargetsInRange.size() - 1)];
}

View File

@ -184,8 +184,8 @@ void Mob::CalculateNewFearpoint()
{
int ran = 250 - (loop*2);
loop++;
ranx = GetX()+MakeRandomInt(0, ran-1)-MakeRandomInt(0, ran-1);
rany = GetY()+MakeRandomInt(0, ran-1)-MakeRandomInt(0, ran-1);
ranx = GetX()+zone->random.Int(0, ran-1)-zone->random.Int(0, ran-1);
rany = GetY()+zone->random.Int(0, ran-1)-zone->random.Int(0, ran-1);
ranz = FindGroundZ(ranx,rany);
if (ranz == -999999)
continue;

View File

@ -15,75 +15,33 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include <iostream>
#include <stdlib.h>
#include <math.h>
#ifdef _WINDOWS
#define snprintf _snprintf
#endif
#include "forage.h"
#include "entity.h"
#include "masterentity.h"
#include "npc.h"
#include "water_map.h"
#include "titles.h"
#include "string_ids.h"
#include "../common/misc_functions.h"
#include "../common/string_util.h"
#include "../common/rulesys.h"
#include "../common/string_util.h"
#include "entity.h"
#include "forage.h"
#include "npc.h"
#include "quest_parser_collection.h"
#include "string_ids.h"
#include "titles.h"
#include "water_map.h"
#include "zonedb.h"
#include <iostream>
#ifdef _WINDOWS
#define snprintf _snprintf
#endif
#include "quest_parser_collection.h"
struct NPCType;
//max number of items which can be in the foraging table
//for a given zone.
#define FORAGE_ITEM_LIMIT 50
/*
The fishing and foraging need some work...
foraging currently gives each item an equal chance of dropping
fishing gives items which come in last from the select a very
very low chance of dropping.
Schema:
CREATE TABLE forage (
id int(11) NOT NULL auto_increment,
zoneid int(4) NOT NULL default '0',
Itemid int(11) NOT NULL default '0',
level smallint(6) NOT NULL default '0',
chance smallint(6) NOT NULL default '0',
PRIMARY KEY (id)
) TYPE=MyISAM;
old table upgrade:
alter table forage add chance smallint(6) NOT NULL default '0';
update forage set chance=100;
CREATE TABLE fishing (
id int(11) NOT NULL auto_increment,
zoneid int(4) NOT NULL default '0',
Itemid int(11) NOT NULL default '0',
skill_level smallint(6) NOT NULL default '0',
chance smallint(6) NOT NULL default '0',
npc_id int NOT NULL default 0,
npc_chance int NOT NULL default 0,
PRIMARY KEY (id)
) TYPE=MyISAM;
*/
// This allows EqEmu to have zone specific foraging - BoB
uint32 ZoneDatabase::GetZoneForage(uint32 ZoneID, uint8 skill) {
uint32 item[FORAGE_ITEM_LIMIT];
@ -125,7 +83,7 @@ uint32 ZoneDatabase::GetZoneForage(uint32 ZoneID, uint8 skill) {
ret = 0;
uint32 rindex = MakeRandomInt(1, chancepool);
uint32 rindex = zone->random.Int(1, chancepool);
for(int i = 0; i < index; i++) {
if(rindex <= chance[i]) {
@ -178,7 +136,7 @@ uint32 ZoneDatabase::GetZoneFishing(uint32 ZoneID, uint8 skill, uint32 &npc_id,
if (index <= 0)
return 0;
uint32 random = MakeRandomInt(1, chancepool);
uint32 random = zone->random.Int(1, chancepool);
for (int i = 0; i < index; i++)
{
if (random > chance[i])
@ -301,18 +259,18 @@ void Client::GoFish()
fishing_skill = 100+((fishing_skill-100)/2);
}
if (MakeRandomInt(0,175) < fishing_skill) {
if (zone->random.Int(0,175) < fishing_skill) {
uint32 food_id = 0;
//25% chance to fish an item.
if (MakeRandomInt(0, 399) <= fishing_skill ) {
if (zone->random.Int(0, 399) <= fishing_skill ) {
uint32 npc_id = 0;
uint8 npc_chance = 0;
food_id = database.GetZoneFishing(m_pp.zone_id, fishing_skill, npc_id, npc_chance);
//check for add NPC
if(npc_chance > 0 && npc_id) {
if(npc_chance < MakeRandomInt(0, 99)) {
if(npc_chance < zone->random.Int(0, 99)) {
const NPCType* tmp = database.GetNPCType(npc_id);
if(tmp != nullptr) {
auto positionNPC = GetPosition();
@ -334,7 +292,7 @@ void Client::GoFish()
DeleteItemInInventory(bslot, 1, true); //do we need client update?
if(food_id == 0) {
int index = MakeRandomInt(0, MAX_COMMON_FISH_IDS-1);
int index = zone->random.Int(0, MAX_COMMON_FISH_IDS-1);
food_id = common_fish_ids[index];
}
@ -369,11 +327,11 @@ void Client::GoFish()
else
{
//chance to use bait when you dont catch anything...
if (MakeRandomInt(0, 4) == 1) {
if (zone->random.Int(0, 4) == 1) {
DeleteItemInInventory(bslot, 1, true); //do we need client update?
Message_StringID(MT_Skills, FISHING_LOST_BAIT); //You lost your bait!
} else {
if (MakeRandomInt(0, 15) == 1) //give about a 1 in 15 chance to spill your beer. we could make this a rule, but it doesn't really seem worth it
if (zone->random.Int(0, 15) == 1) //give about a 1 in 15 chance to spill your beer. we could make this a rule, but it doesn't really seem worth it
//TODO: check for & consume an alcoholic beverage from inventory when this triggers, and set it as a rule that's disabled by default
Message_StringID(MT_Skills, FISHING_SPILL_BEER); //You spill your beer while bringing in your line.
else
@ -386,7 +344,7 @@ void Client::GoFish()
//chance to break fishing pole...
//this is potentially exploitable in that they can fish
//and then swap out items in primary slot... too lazy to fix right now
if (MakeRandomInt(0, 49) == 1) {
if (zone->random.Int(0, 49) == 1) {
Message_StringID(MT_Skills, FISHING_POLE_BROKE); //Your fishing pole broke!
DeleteItemInInventory(MainPrimary, 0, true);
}
@ -415,18 +373,18 @@ void Client::ForageItem(bool guarantee) {
};
// these may need to be fine tuned, I am just guessing here
if (guarantee || MakeRandomInt(0,199) < skill_level) {
if (guarantee || zone->random.Int(0,199) < skill_level) {
uint32 foragedfood = 0;
uint32 stringid = FORAGE_NOEAT;
if (MakeRandomInt(0,99) <= 25) {
if (zone->random.Roll(25)) {
foragedfood = database.GetZoneForage(m_pp.zone_id, skill_level);
}
//not an else in case theres no DB food
if(foragedfood == 0) {
uint8 index = 0;
index = MakeRandomInt(0, MAX_COMMON_FOOD_IDS-1);
index = zone->random.Int(0, MAX_COMMON_FOOD_IDS-1);
foragedfood = common_food_ids[index];
}
@ -483,7 +441,7 @@ void Client::ForageItem(bool guarantee) {
}
int ChanceSecondForage = aabonuses.ForageAdditionalItems + itembonuses.ForageAdditionalItems + spellbonuses.ForageAdditionalItems;
if(!guarantee && MakeRandomInt(0,99) < ChanceSecondForage) {
if(!guarantee && zone->random.Roll(ChanceSecondForage)) {
Message_StringID(MT_Skills, FORAGE_MASTERY);
ForageItem(true);
}

View File

@ -592,12 +592,15 @@ bool Group::DelMemberOOZ(const char *Name) {
bool Group::DelMember(Mob* oldmember,bool ignoresender)
{
if (oldmember == nullptr){
if (oldmember == nullptr)
{
return false;
}
for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) {
if (members[i] == oldmember) {
for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++)
{
if (members[i] == oldmember)
{
members[i] = nullptr;
membername[i][0] = '\0';
memset(membername[i],0,64);
@ -606,16 +609,6 @@ bool Group::DelMember(Mob* oldmember,bool ignoresender)
}
}
//handle leader quitting group gracefully
if (oldmember == GetLeader() && GroupCount() >= 2) {
for(uint32 nl = 0; nl < MAX_GROUP_MEMBERS; nl++) {
if(members[nl]) {
ChangeLeader(members[nl]);
break;
}
}
}
/* This may seem pointless but the case above does not cover the following situation:
* Group has Leader a, member b, member c
* b and c are out of zone
@ -624,10 +617,33 @@ bool Group::DelMember(Mob* oldmember,bool ignoresender)
* a is still "leader" from GetLeader()'s perspective and will crash the zone when we DelMember(b)
* Ultimately we should think up a better solution to this.
*/
if(oldmember == GetLeader()) {
if(oldmember == GetLeader())
{
SetLeader(nullptr);
}
//handle leader quitting group gracefully
if (oldmember == GetLeader() && GroupCount() >= 2)
{
for(uint32 nl = 0; nl < MAX_GROUP_MEMBERS; nl++)
{
if(members[nl])
{
if (members[nl]->IsClient())
{
ChangeLeader(members[nl]);
break;
}
}
}
}
if (GetLeader() == nullptr)
{
DisbandGroup();
return true;
}
ServerPacket* pack = new ServerPacket(ServerOP_GroupLeave, sizeof(ServerGroupLeave_Struct));
ServerGroupLeave_Struct* gl = (ServerGroupLeave_Struct*)pack->pBuffer;
gl->gid = GetID();

View File

@ -15,23 +15,13 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "masterentity.h"
#include "worldserver.h"
#include "net.h"
#include "../common/database.h"
#include "../common/spdat.h"
#include "../common/packet_dump.h"
#include "../common/packet_functions.h"
#include "petitions.h"
#include "../common/serverinfo.h"
#include "../common/zone_numbers.h"
#include "../common/moremath.h"
#include "../common/guilds.h"
#include "../common/string_util.h"
#include "guild_mgr.h"
#include "string_ids.h"
#include "npc_ai.h"
#include "worldserver.h"
extern WorldServer worldserver;

View File

@ -487,7 +487,7 @@ Mob *HateList::GetRandom()
}
auto iterator = list.begin();
int random = MakeRandomInt(0, count - 1);
int random = zone->random.Int(0, count - 1);
for (int i = 0; i < random; i++)
++iterator;

View File

@ -15,24 +15,14 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "masterentity.h"
#include "worldserver.h"
#include "net.h"
#include "zonedb.h"
#include "../common/spdat.h"
#include "../common/packet_dump.h"
#include "../common/packet_functions.h"
#include "petitions.h"
#include "../common/serverinfo.h"
#include "../common/zone_numbers.h"
#include "../common/moremath.h"
#include "../common/guilds.h"
#include "../common/logsys.h"
#include "../common/string_util.h"
#include "string_ids.h"
#include "npc_ai.h"
#include "quest_parser_collection.h"
#include "worldserver.h"
#include "zonedb.h"
extern WorldServer worldserver;
// @merth: this needs to be touched up
@ -199,7 +189,7 @@ bool Client::CheckLoreConflict(const Item_Struct* item) {
return (m_inv.HasItemByLoreGroup(item->LoreGroup, ~invWhereSharedBank) != INVALID_INDEX);
}
bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, bool attuned, uint16 to_slot) {
bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, bool attuned, uint16 to_slot, uint32 ornament_icon, uint32 ornament_idfile) {
this->EVENT_ITEM_ScriptStopReturn();
// TODO: update calling methods and script apis to handle a failure return
@ -557,6 +547,11 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
// attune item
if(attuned && inst->GetItem()->Attuneable)
inst->SetInstNoDrop(true);
if(ornament_icon > 0 && ornament_idfile > 0) {
inst->SetOrnamentIcon(ornament_icon);
inst->SetOrnamentationIDFile(ornament_idfile);
}
// check to see if item is usable in requested slot
if(enforceusable && (((to_slot >= MainCharm) && (to_slot <= MainAmmo)) || (to_slot == MainPowerSource))) {

View File

@ -22,6 +22,7 @@
#include "npc.h"
#include "masterentity.h"
#include "zonedb.h"
#include "../common/loottable.h"
#include "../common/misc_functions.h"
#ifdef _WINDOWS
#define snprintf _snprintf
@ -48,15 +49,15 @@ void ZoneDatabase::AddLootTableToNPC(NPC* npc,uint32 loottable_id, ItemList* ite
if (lts->mincash == lts->maxcash)
cash = lts->mincash;
else
cash = MakeRandomInt(lts->mincash, lts->maxcash);
cash = zone->random.Int(lts->mincash, lts->maxcash);
if (cash != 0) {
if (lts->avgcoin != 0) {
//this is some crazy ass stuff... and makes very little sense... dont use it, k?
uint32 mincoin = (uint32) (lts->avgcoin * 0.75 + 1);
uint32 maxcoin = (uint32) (lts->avgcoin * 1.25 + 1);
*copper = MakeRandomInt(mincoin, maxcoin);
*silver = MakeRandomInt(mincoin, maxcoin);
*gold = MakeRandomInt(mincoin, maxcoin);
*copper = zone->random.Int(mincoin, maxcoin);
*silver = zone->random.Int(mincoin, maxcoin);
*gold = zone->random.Int(mincoin, maxcoin);
if(*copper > cash) { *copper = cash; }
cash -= *copper;
if(*silver>(cash/10)) { *silver = (cash/10); }
@ -91,7 +92,7 @@ void ZoneDatabase::AddLootTableToNPC(NPC* npc,uint32 loottable_id, ItemList* ite
float drop_chance = 0.0f;
if(ltchance > 0.0 && ltchance < 100.0) {
drop_chance = MakeRandomFloat(0.0, 100.0);
drop_chance = zone->random.Real(0.0, 100.0);
}
if (ltchance != 0.0 && (ltchance == 100.0 || drop_chance < ltchance)) {
@ -117,7 +118,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml
uint8 limit = 0;
// Start at a random point in itemlist.
uint32 item = MakeRandomInt(0, lds->NumEntries-1);
uint32 item = zone->random.Int(0, lds->NumEntries-1);
// Main loop.
for (uint32 i=0; i<lds->NumEntries;)
{
@ -136,7 +137,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml
float drop_chance = 0.0;
if(thischance != 100.0)
drop_chance = MakeRandomFloat(0.0, 100.0);
drop_chance = zone->random.Real(0.0, 100.0);
#if EQDEBUG>=11
LogFile->write(EQEMuLog::Debug, "Drop chance for npc: %s, this chance:%f, drop roll:%f", npc->GetName(), thischance, drop_chance);
@ -281,7 +282,7 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge
eslot = MaterialPrimary;
}
else if (foundslot == MainSecondary
&& (GetOwner() != nullptr || (GetLevel() >= 13 && MakeRandomInt(0,99) < NPC_DW_CHANCE) || (item2->Damage==0)) &&
&& (GetOwner() != nullptr || (GetLevel() >= 13 && zone->random.Roll(NPC_DW_CHANCE)) || (item2->Damage==0)) &&
(item2->ItemType == ItemType1HSlash || item2->ItemType == ItemType1HBlunt || item2->ItemType == ItemTypeShield ||
item2->ItemType == ItemType1HPiercing))
{

View File

@ -39,7 +39,7 @@ void Lua_Corpse::ResetLooter() {
uint32 Lua_Corpse::GetDBID() {
Lua_Safe_Call_Int();
return self->GetDBID();
return self->GetCorpseDBID();
}
bool Lua_Corpse::IsRezzed() {
@ -114,12 +114,12 @@ void Lua_Corpse::SetDecayTimer(uint32 decaytime) {
bool Lua_Corpse::CanMobLoot(int charid) {
Lua_Safe_Call_Bool();
return self->CanMobLoot(charid);
return self->CanPlayerLoot(charid);
}
void Lua_Corpse::AllowMobLoot(Lua_Mob them, uint8 slot) {
Lua_Safe_Call_Void();
self->AllowMobLoot(them, slot);
self->AllowPlayerLoot(them, slot);
}
bool Lua_Corpse::Summon(Lua_Client client, bool spell, bool checkdistance) {

View File

@ -62,7 +62,7 @@ Merc::Merc(const NPCType* d, float x, float y, float z, float heading)
skills[r] = database.GetSkillCap(GetClass(),(SkillUseTypes)r,GetLevel());
}
GetMercSize();
size = d->size;
CalcBonuses();
SetHP(GetMaxHP());
@ -112,131 +112,66 @@ void Merc::CalcBonuses()
rooted = FindType(SE_Root);
}
void Merc::GetMercSize() {
float Merc::GetDefaultSize() {
float MercSize = GetSize();
switch(this->GetRace()) {
case 1: // Humans have no race bonus
break;
case 2: // Barbarian
MercSize = 7.0;
break;
case 3: // Erudite
break;
case 4: // Wood Elf
MercSize = 5.0;
break;
case 5: // High Elf
break;
case 6: // Dark Elf
MercSize = 5.0;
break;
case 7: // Half Elf
MercSize = 5.5;
break;
case 8: // Dwarf
MercSize = 4.0;
break;
case 9: // Troll
MercSize = 8.0;
break;
case 10: // Ogre
MercSize = 9.0;
break;
case 11: // Halfling
MercSize = 3.5;
break;
case 12: // Gnome
MercSize = 3.0;
break;
case 128: // Iksar
break;
case 130: // Vah Shir
MercSize = 7.0;
break;
case 330: // Froglok
MercSize = 5.0;
break;
case 522: // Drakkin
MercSize = 5.0;
break;
switch(this->GetRace())
{
case 1: // Humans
MercSize = 6.0;
break;
case 2: // Barbarian
MercSize = 7.0;
break;
case 3: // Erudite
MercSize = 6.0;
break;
case 4: // Wood Elf
MercSize = 5.0;
break;
case 5: // High Elf
MercSize = 6.0;
break;
case 6: // Dark Elf
MercSize = 5.0;
break;
case 7: // Half Elf
MercSize = 5.5;
break;
case 8: // Dwarf
MercSize = 4.0;
break;
case 9: // Troll
MercSize = 8.0;
break;
case 10: // Ogre
MercSize = 9.0;
break;
case 11: // Halfling
MercSize = 3.5;
break;
case 12: // Gnome
MercSize = 3.0;
break;
case 128: // Iksar
MercSize = 6.0;
break;
case 130: // Vah Shir
MercSize = 7.0;
break;
case 330: // Froglok
MercSize = 5.0;
break;
case 522: // Drakkin
MercSize = 5.0;
break;
default:
MercSize = 6.0;
break;
}
this->size = MercSize;
}
void Merc::GenerateAppearance() {
// Randomize facial appearance
int iFace = 0;
if(this->GetRace() == 2) { // Barbarian w/Tatoo
iFace = MakeRandomInt(0, 79);
}
else {
iFace = MakeRandomInt(0, 7);
}
int iHair = 0;
int iBeard = 0;
int iBeardColor = 1;
if(this->GetRace() == 522) {
iHair = MakeRandomInt(0, 8);
iBeard = MakeRandomInt(0, 11);
iBeardColor = MakeRandomInt(0, 3);
}
else if(this->GetGender()) {
iHair = MakeRandomInt(0, 2);
if(this->GetRace() == 8) { // Dwarven Females can have a beard
if(MakeRandomInt(1, 100) < 50) {
iFace += 10;
}
}
}
else {
iHair = MakeRandomInt(0, 3);
iBeard = MakeRandomInt(0, 5);
iBeardColor = MakeRandomInt(0, 19);
}
int iHairColor = 0;
if(this->GetRace() == 522) {
iHairColor = MakeRandomInt(0, 3);
}
else {
iHairColor = MakeRandomInt(0, 19);
}
uint8 iEyeColor1 = (uint8)MakeRandomInt(0, 9);
uint8 iEyeColor2 = 0;
if(this->GetRace() == 522) {
iEyeColor1 = iEyeColor2 = (uint8)MakeRandomInt(0, 11);
}
else if(MakeRandomInt(1, 100) > 96) {
iEyeColor2 = MakeRandomInt(0, 9);
}
else {
iEyeColor2 = iEyeColor1;
}
int iHeritage = 0;
int iTattoo = 0;
int iDetails = 0;
if(this->GetRace() == 522) {
iHeritage = MakeRandomInt(0, 6);
iTattoo = MakeRandomInt(0, 7);
iDetails = MakeRandomInt(0, 7);
}
this->luclinface = iFace;
this->hairstyle = iHair;
this->beard = iBeard;
this->beardcolor = iBeardColor;
this->haircolor = iHairColor;
this->eyecolor1 = iEyeColor1;
this->eyecolor2 = iEyeColor2;
this->drakkin_heritage = iHeritage;
this->drakkin_tattoo = iTattoo;
this->drakkin_details = iDetails;
return MercSize;
}
int Merc::CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat)
@ -1258,7 +1193,6 @@ void Merc::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
ns->spawn.guildrank = 0;
ns->spawn.showhelm = 1;
ns->spawn.flymode = 0;
ns->spawn.size = 0;
ns->spawn.NPC = 1; // 0=player,1=npc,2=pc corpse,3=npc corpse
ns->spawn.IsMercenary = 1;
@ -1523,7 +1457,7 @@ void Merc::AI_Process() {
meleeDistance = meleeDistance * .30;
}
else {
meleeDistance *= (float)MakeRandomFloat(.50, .85);
meleeDistance *= (float)zone->random.Real(.50, .85);
}
if(IsMercCaster() && GetLevel() > 12) {
if(IsMercCasterCombatRange(GetTarget()))
@ -1624,7 +1558,7 @@ void Merc::AI_Process() {
if (GetTarget() && flurrychance)
{
if(MakeRandomInt(0, 100) < flurrychance)
if(zone->random.Roll(flurrychance))
{
Message_StringID(MT_NPCFlurry, YOU_FLURRY);
Attack(GetTarget(), MainPrimary, false);
@ -1635,7 +1569,7 @@ void Merc::AI_Process() {
int16 ExtraAttackChanceBonus = spellbonuses.ExtraAttackChance + itembonuses.ExtraAttackChance + aabonuses.ExtraAttackChance;
if (GetTarget() && ExtraAttackChanceBonus) {
if(MakeRandomInt(0, 100) < ExtraAttackChanceBonus)
if(zone->random.Roll(ExtraAttackChanceBonus))
{
Attack(GetTarget(), MainPrimary, false);
}
@ -1669,10 +1603,8 @@ void Merc::AI_Process() {
int16 DWBonus = spellbonuses.DualWieldChance + itembonuses.DualWieldChance;
DualWieldProbability += DualWieldProbability*float(DWBonus)/ 100.0f;
float random = MakeRandomFloat(0, 1);
// Max 78% of DW
if (random < DualWieldProbability)
if (zone->random.Roll(DualWieldProbability))
{
Attack(GetTarget(), MainSecondary); // Single attack with offhand
@ -1934,7 +1866,7 @@ bool EntityList::Merc_AICheckCloseBeneficialSpells(Merc* caster, uint8 iChance,
return false;
if (iChance < 100) {
int8 tmp = MakeRandomInt(1, 100);
int8 tmp = zone->random.Int(1, 100);
if (tmp > iChance)
return false;
}
@ -2030,7 +1962,7 @@ bool Merc::AICastSpell(int8 iChance, int32 iSpellTypes) {
return false;
if (iChance < 100) {
if (MakeRandomInt(0, 100) > iChance){
if (zone->random.Int(0, 100) > iChance){
return false;
}
}
@ -2315,14 +2247,14 @@ bool Merc::AICastSpell(int8 iChance, int32 iSpellTypes) {
if(selectedMercSpell.spellid == 0 && !tar->GetSpecialAbility(UNSTUNABLE) && !tar->IsStunned()) {
uint8 stunChance = 15;
if(MakeRandomInt(1, 100) <= stunChance) {
if(zone->random.Roll(stunChance)) {
selectedMercSpell = GetBestMercSpellForStun(this);
}
}
if(selectedMercSpell.spellid == 0) {
uint8 lureChance = 25;
if(MakeRandomInt(1, 100) <= lureChance) {
if(zone->random.Roll(lureChance)) {
selectedMercSpell = GetBestMercSpellForNukeByTargetResists(this, tar);
}
}
@ -2742,14 +2674,14 @@ int32 Merc::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
int32 ratio = RuleI(Spells, BaseCritRatio); //Critical modifier is applied from spell effects only. Keep at 100 for live like criticals.
if (MakeRandomInt(1,100) <= chance){
if (zone->random.Roll(chance)) {
Critical = true;
ratio += itembonuses.SpellCritDmgIncrease + spellbonuses.SpellCritDmgIncrease + aabonuses.SpellCritDmgIncrease;
ratio += itembonuses.SpellCritDmgIncNoStack + spellbonuses.SpellCritDmgIncNoStack + aabonuses.SpellCritDmgIncNoStack;
}
else if (GetClass() == CASTERDPS && (GetLevel() >= RuleI(Spells, WizCritLevel)) && (MakeRandomInt(1,100) <= RuleI(Spells, WizCritChance))) {
ratio = MakeRandomInt(1,100); //Wizard innate critical chance is calculated seperately from spell effect and is not a set ratio.
else if (GetClass() == CASTERDPS && (GetLevel() >= RuleI(Spells, WizCritLevel)) && (zone->random.Roll(RuleI(Spells, WizCritChance)))) {
ratio = zone->random.Int(1,100); //Wizard innate critical chance is calculated seperately from spell effect and is not a set ratio.
Critical = true;
}
@ -2833,7 +2765,7 @@ int32 Merc::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
if (spellbonuses.CriticalHealDecay)
chance += GetDecayEffectValue(spell_id, SE_CriticalHealDecay);
if(chance && (MakeRandomInt(0,99) < chance)) {
if(chance && zone->random.Roll(chance)) {
Critical = true;
modifier = 2; //At present time no critical heal amount modifier SPA exists.
}
@ -2864,7 +2796,7 @@ int32 Merc::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
if (spellbonuses.CriticalRegenDecay)
chance += GetDecayEffectValue(spell_id, SE_CriticalRegenDecay);
if(chance && (MakeRandomInt(0,99) < chance))
if(chance && zone->random.Roll(chance))
return (value * 2);
}
@ -2876,7 +2808,7 @@ int32 Merc::GetActSpellCost(uint16 spell_id, int32 cost)
// Formula = Unknown exact, based off a random percent chance up to mana cost(after focuses) of the cast spell
if(this->itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5)
{
int16 mana_back = this->itembonuses.Clairvoyance * MakeRandomInt(1, 100) / 100;
int16 mana_back = this->itembonuses.Clairvoyance * zone->random.Int(1, 100) / 100;
// Doesnt generate mana, so best case is a free spell
if(mana_back > cost)
mana_back = cost;
@ -2893,7 +2825,7 @@ int32 Merc::GetActSpellCost(uint16 spell_id, int32 cost)
if(focus_redux > 0)
{
PercentManaReduction += MakeRandomFloat(1, (double)focus_redux);
PercentManaReduction += zone->random.Real(1, (double)focus_redux);
}
cost -= (cost * (PercentManaReduction / 100));
@ -3825,17 +3757,17 @@ MercSpell Merc::GetBestMercSpellForAENuke(Merc* caster, Mob* tar) {
}
//check of we even want to cast an AE nuke
if(MakeRandomInt(1, 100) <= initialCastChance) {
if(zone->random.Roll(initialCastChance)) {
result = GetBestMercSpellForAERainNuke(caster, tar);
//check if we have a spell & allow for other AE nuke types
if(result.spellid == 0 && MakeRandomInt(1, 100) <= castChanceFalloff) {
if(result.spellid == 0 && zone->random.Roll(castChanceFalloff)) {
result = GetBestMercSpellForPBAENuke(caster, tar);
//check if we have a spell & allow for other AE nuke types
if(result.spellid == 0 && MakeRandomInt(1, 100) <= castChanceFalloff) {
if(result.spellid == 0 && zone->random.Roll(castChanceFalloff)) {
result = GetBestMercSpellForTargetedAENuke(caster, tar);
}
@ -3879,7 +3811,7 @@ MercSpell Merc::GetBestMercSpellForTargetedAENuke(Merc* caster, Mob* tar) {
&& !IsPBAENukeSpell(mercSpellListItr->spellid) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) {
uint8 numTargets = 0;
if(CheckAENuke(caster, tar, mercSpellListItr->spellid, numTargets)) {
if(numTargets >= numTargetsCheck && MakeRandomInt(1, 100) <= castChance) {
if(numTargets >= numTargetsCheck && zone->random.Roll(castChance)) {
result.spellid = mercSpellListItr->spellid;
result.stance = mercSpellListItr->stance;
result.type = mercSpellListItr->type;
@ -3929,7 +3861,7 @@ MercSpell Merc::GetBestMercSpellForPBAENuke(Merc* caster, Mob* tar) {
if(IsPBAENukeSpell(mercSpellListItr->spellid) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) {
uint8 numTargets = 0;
if(CheckAENuke(caster, caster, mercSpellListItr->spellid, numTargets)) {
if(numTargets >= numTargetsCheck && MakeRandomInt(1, 100) <= castChance) {
if(numTargets >= numTargetsCheck && zone->random.Roll(castChance)) {
result.spellid = mercSpellListItr->spellid;
result.stance = mercSpellListItr->stance;
result.type = mercSpellListItr->type;
@ -3976,7 +3908,7 @@ MercSpell Merc::GetBestMercSpellForAERainNuke(Merc* caster, Mob* tar) {
for(std::list<MercSpell>::iterator mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) {
// Assuming all the spells have been loaded into this list by level and in descending order
if(IsAERainNukeSpell(mercSpellListItr->spellid) && MakeRandomInt(1, 100) <= castChance && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) {
if(IsAERainNukeSpell(mercSpellListItr->spellid) && zone->random.Roll(castChance) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) {
uint8 numTargets = 0;
if(CheckAENuke(caster, tar, mercSpellListItr->spellid, numTargets)) {
if(numTargets >= numTargetsCheck) {
@ -4015,7 +3947,7 @@ MercSpell Merc::GetBestMercSpellForNuke(Merc* caster) {
for(std::list<MercSpell>::iterator mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) {
// Assuming all the spells have been loaded into this list by level and in descending order
if(IsPureNukeSpell(mercSpellListItr->spellid) && !IsAENukeSpell(mercSpellListItr->spellid)
&& MakeRandomInt(1, 100) <= castChance && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) {
&& zone->random.Roll(castChance) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) {
result.spellid = mercSpellListItr->spellid;
result.stance = mercSpellListItr->stance;
result.type = mercSpellListItr->type;
@ -4447,7 +4379,7 @@ bool Merc::CheckConfidence() {
ConfidenceLossChance = 25 - ( 5 * (GetTierID() - 1));
}
if(MakeRandomInt(0 ,100) < ConfidenceLossChance) {
if(zone->random.Roll(ConfidenceLossChance)) {
result = false;
}
@ -4593,7 +4525,7 @@ void Merc::DoClassAttacks(Mob *target) {
break;
case TANK:{
if(level >= RuleI(Combat, NPCBashKickLevel)){
if(MakeRandomInt(0, 100) > 25) //tested on live, warrior mobs both kick and bash, kick about 75% of the time, casting doesn't seem to make a difference.
if(zone->random.Int(0, 100) > 25) //tested on live, warrior mobs both kick and bash, kick about 75% of the time, casting doesn't seem to make a difference.
{
DoAnim(animKick);
int32 dmg = 0;
@ -4606,7 +4538,7 @@ void Merc::DoClassAttacks(Mob *target) {
if(RuleB(Combat, UseIntervalAC))
dmg = GetKickDamage();
else
dmg = MakeRandomInt(1, GetKickDamage());
dmg = zone->random.Int(1, GetKickDamage());
}
}
@ -4628,7 +4560,7 @@ void Merc::DoClassAttacks(Mob *target) {
if(RuleB(Combat, UseIntervalAC))
dmg = GetBashDamage();
else
dmg = MakeRandomInt(1, GetBashDamage());
dmg = zone->random.Int(1, GetBashDamage());
}
}
@ -4756,7 +4688,7 @@ const char* Merc::GetRandomName(){
bool valid = false;
while(!valid) {
int rndnum=MakeRandomInt(0, 75),n=1;
int rndnum=zone->random.Int(0, 75),n=1;
bool dlc=false;
bool vwl=false;
bool dbl=false;
@ -4777,18 +4709,18 @@ const char* Merc::GetRandomName(){
rndname[0]=vowels[rndnum];
vwl=true;
}
int namlen=MakeRandomInt(5, 10);
int namlen=zone->random.Int(5, 10);
for (int i=n;i<namlen;i++)
{
dlc=false;
if (vwl) //last char was a vowel
{ // so pick a cons or cons pair
rndnum=MakeRandomInt(0, 62);
rndnum=zone->random.Int(0, 62);
if (rndnum>46)
{ // pick a cons pair
if (i>namlen-3) // last 2 chars in name?
{ // name can only end in cons pair "rk" "st" "sh" "th" "ph" "sk" "nd" or "ng"
rndnum=MakeRandomInt(0, 7)*2;
rndnum=zone->random.Int(0, 7)*2;
}
else
{ // pick any from the set
@ -4806,12 +4738,12 @@ const char* Merc::GetRandomName(){
}
else
{ // select a vowel
rndname[i]=vowels[MakeRandomInt(0, 16)];
rndname[i]=vowels[zone->random.Int(0, 16)];
}
vwl=!vwl;
if (!dbl && !dlc)
{ // one chance at double letters in name
if (!MakeRandomInt(0, i+9)) // chances decrease towards end of name
if (!zone->random.Int(0, i+9)) // chances decrease towards end of name
{
rndname[i+1]=rndname[i];
dbl=true;
@ -4940,22 +4872,37 @@ Merc* Merc::LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id,
}
snprintf(npc_type->name, 64, "%s", c->GetMercInfo().merc_name);
}
uint8 gender = 0;
if(merchant_id > 0) {
npc_type->race = merc_template->RaceID;
// Use the Gender and Size of the Merchant if possible
uint8 tmpgender = 0;
float tmpsize = 6.0f;
if(merchant_id > 0)
{
NPC* tar = entity_list.GetNPCByID(merchant_id);
if(tar) {
gender = Mob::GetDefaultGender(npc_type->race, tar->GetGender());
if(tar)
{
tmpgender = tar->GetGender();
tmpsize = tar->GetSize();
}
else
{
tmpgender = Mob::GetDefaultGender(npc_type->race, c->GetMercInfo().Gender);
}
}
else {
gender = c->GetMercInfo().Gender;
else
{
tmpgender = c->GetMercInfo().Gender;
tmpsize = c->GetMercInfo().MercSize;
}
sprintf(npc_type->lastname, "%s's %s", c->GetName(), "Mercenary");
npc_type->gender = gender;
sprintf(npc_type->lastname, "%s's Mercenary", c->GetName());
npc_type->gender = tmpgender;
npc_type->size = tmpsize;
npc_type->loottable_id = 0; // Loottable has to be 0, otherwise we'll be leavin' some corpses!
npc_type->npc_id = 0; //NPC ID has to be 0, otherwise db gets all confuzzled.
npc_type->race = merc_template->RaceID;
npc_type->class_ = merc_template->ClassID;
npc_type->maxlevel = 0; //We should hard-set this to override scalerate's functionality in the NPC class when it is constructed.
@ -4975,6 +4922,7 @@ Merc* Merc::LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id,
snprintf(merc->name, 64, "%s", c->GetMercInfo().merc_name);
merc->SetSuspended(c->GetMercInfo().IsSuspended);
merc->gender = c->GetMercInfo().Gender;
merc->size = c->GetMercInfo().MercSize;
merc->SetHP(c->GetMercInfo().hp <= 0 ? merc->GetMaxHP() : c->GetMercInfo().hp);
merc->SetMana(c->GetMercInfo().hp <= 0 ? merc->GetMaxMana() : c->GetMercInfo().mana);
merc->SetEndurance(c->GetMercInfo().endurance);
@ -4989,6 +4937,11 @@ Merc* Merc::LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id,
merc->drakkin_tattoo = c->GetMercInfo().drakkinTattoo;
merc->drakkin_details = c->GetMercInfo().drakkinDetails;
}
else
{
// Give Random Features to newly hired Mercs
merc->RandomizeFeatures(false, true);
}
if(merc->GetMercID()) {
database.LoadMercBuffs(merc);
@ -5008,7 +4961,8 @@ void Merc::UpdateMercInfo(Client *c) {
snprintf(c->GetMercInfo().merc_name, 64, "%s", name);
c->GetMercInfo().mercid = GetMercID();
c->GetMercInfo().IsSuspended = IsSuspended();
c->GetMercInfo().Gender = gender;
c->GetMercInfo().Gender = GetGender();
c->GetMercInfo().MercSize = GetSize();
c->GetMercInfo().hp = GetHP();
c->GetMercInfo().mana = GetMana();
c->GetMercInfo().endurance = GetEndurance();
@ -5540,7 +5494,7 @@ void Client::SpawnMercOnZone() {
}
else
{
int32 TimeDiff = GetMercInfo().SuspendedTime + RuleI(Mercs, SuspendIntervalS) - time(nullptr);
int32 TimeDiff = GetMercInfo().SuspendedTime - time(nullptr);
if (TimeDiff > 0)
{
if (!GetPTimers().Enabled(pTimerMercSuspend))
@ -5558,6 +5512,11 @@ void Client::SpawnMercOnZone() {
Message(7, "Mercenary Debug: SpawnMercOnZone Suspended Merc.");
}
}
else
{
// No Merc Hired
SendClearMercInfo();
}
}
void Client::SendMercTimer(Merc* merc) {
@ -5604,9 +5563,6 @@ void Client::SpawnMerc(Merc* merc, bool setMaxStats) {
SetMerc(merc);
merc->Unsuspend(setMaxStats);
merc->SetStance(GetMercInfo().Stance);
GetMercInfo().SuspendedTime = 0;
//SendMercTimer(merc);
if (MERC_DEBUG > 0)
Message(7, "Mercenary Debug: SpawnMerc Success.");
@ -5666,7 +5622,6 @@ bool Client::MercOnlyOrNoGroup() {
bool Merc::Unsuspend(bool setMaxStats) {
Client* mercOwner = nullptr;
bool loaded = false;
if(GetMercOwner()) {
mercOwner = GetMercOwner();
@ -5694,12 +5649,8 @@ bool Merc::Unsuspend(bool setMaxStats) {
if(!mercOwner->GetPTimers().Expired(&database, pTimerMercSuspend, false))
mercOwner->GetPTimers().Clear(&database, pTimerMercSuspend);
MercJoinClientGroup();
if(loaded)
if (MercJoinClientGroup())
{
LoadMercSpells();
if(setMaxStats)
{
SetHP(GetMaxHP());
@ -5977,7 +5928,7 @@ Merc* Client::GetMerc() {
if(GetMercID() == 0)
{
if (MERC_DEBUG > 0)
//Message(7, "Mercenary Debug: GetMerc 0.");
Message(7, "Mercenary Debug: GetMerc 0.");
return (nullptr);
}
@ -5998,9 +5949,6 @@ Merc* Client::GetMerc() {
return (nullptr);
}
if (MERC_DEBUG > 0)
//Message(7, "Mercenary Debug: GetMerc Success.");
return (tmp);
}
@ -6073,7 +6021,7 @@ void Client::SetMerc(Merc* newmerc) {
GetMercInfo().IsSuspended = newmerc->IsSuspended();
GetMercInfo().SuspendedTime = 0;
GetMercInfo().Gender = newmerc->GetGender();
//GetMercInfo().State = newmerc->GetStance();
GetMercInfo().State = newmerc->IsSuspended() ? MERC_STATE_SUSPENDED : MERC_STATE_NORMAL;
snprintf(GetMercInfo().merc_name, 64, "%s", newmerc->GetName());
if (MERC_DEBUG > 0)
Message(7, "Mercenary Debug: SetMerc New Merc.");

6329
zone/merc.cpp.orig Normal file

File diff suppressed because it is too large Load Diff

View File

@ -332,9 +332,7 @@ private:
int GroupLeadershipAAHealthRegeneration();
int GroupLeadershipAAOffenseEnhancement();
void GetMercSize();
void GenerateAppearance();
float GetDefaultSize();
bool LoadMercSpells();
bool CheckStance(int16 stance);

View File

@ -15,17 +15,17 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "masterentity.h"
#include "../common/spdat.h"
#include "string_ids.h"
#include "worldserver.h"
#include "quest_parser_collection.h"
#include "../common/string_util.h"
#include <sstream>
#include <math.h>
#include "quest_parser_collection.h"
#include "string_ids.h"
#include "worldserver.h"
#include <limits.h>
#include <math.h>
#include <sstream>
extern EntityList entity_list;
@ -260,13 +260,24 @@ Mob::Mob(const char* in_name,
casting_spell_inventory_slot = 0;
target = 0;
for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { projectile_spell_id[i] = 0; }
for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { projectile_target_id[i] = 0; }
for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { projectile_increment[i] = 0; }
for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { projectile_x[i] = 0; }
for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { projectile_y[i] = 0; }
for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { projectile_z[i] = 0; }
projectile_timer.Disable();
ActiveProjectileATK = false;
for (int i = 0; i < MAX_SPELL_PROJECTILE; i++)
{
ProjectileAtk[i].increment = 0;
ProjectileAtk[i].hit_increment = 0;
ProjectileAtk[i].target_id = 0;
ProjectileAtk[i].wpn_dmg = 0;
ProjectileAtk[i].origin_x = 0.0f;
ProjectileAtk[i].origin_y = 0.0f;
ProjectileAtk[i].origin_z = 0.0f;
ProjectileAtk[i].tlast_x = 0.0f;
ProjectileAtk[i].tlast_y = 0.0f;
ProjectileAtk[i].ranged_id = 0;
ProjectileAtk[i].ammo_id = 0;
ProjectileAtk[i].ammo_slot = 0;
ProjectileAtk[i].skill = 0;
ProjectileAtk[i].speed_mod = 0.0f;
}
memset(&itembonuses, 0, sizeof(StatBonuses));
memset(&spellbonuses, 0, sizeof(StatBonuses));
@ -702,7 +713,8 @@ void Mob::CreateSpawnPacket(EQApplicationPacket* app, Mob* ForWho) {
NewSpawn_Struct* ns = (NewSpawn_Struct*)app->pBuffer;
FillSpawnStruct(ns, ForWho);
if(strlen(ns->spawn.lastName) == 0) {
if(strlen(ns->spawn.lastName) == 0)
{
switch(ns->spawn.class_)
{
case TRIBUTE_MASTER:
@ -780,70 +792,78 @@ void Mob::CreateSpawnPacket(EQApplicationPacket* app, NewSpawn_Struct* ns) {
// Custom packet data
NewSpawn_Struct* ns2 = (NewSpawn_Struct*)app->pBuffer;
strcpy(ns2->spawn.name, ns->spawn.name);
switch(ns->spawn.class_)
{
case TRIBUTE_MASTER:
strcpy(ns2->spawn.lastName, "Tribute Master");
break;
case ADVENTURERECRUITER:
strcpy(ns2->spawn.lastName, "Adventure Recruiter");
break;
case BANKER:
strcpy(ns2->spawn.lastName, "Banker");
break;
case ADVENTUREMERCHANT:
strcpy(ns->spawn.lastName,"Adventure Merchant");
break;
case WARRIORGM:
strcpy(ns2->spawn.lastName, "GM Warrior");
break;
case PALADINGM:
strcpy(ns2->spawn.lastName, "GM Paladin");
break;
case RANGERGM:
strcpy(ns2->spawn.lastName, "GM Ranger");
break;
case SHADOWKNIGHTGM:
strcpy(ns2->spawn.lastName, "GM Shadowknight");
break;
case DRUIDGM:
strcpy(ns2->spawn.lastName, "GM Druid");
break;
case BARDGM:
strcpy(ns2->spawn.lastName, "GM Bard");
break;
case ROGUEGM:
strcpy(ns2->spawn.lastName, "GM Rogue");
break;
case SHAMANGM:
strcpy(ns2->spawn.lastName, "GM Shaman");
break;
case NECROMANCERGM:
strcpy(ns2->spawn.lastName, "GM Necromancer");
break;
case WIZARDGM:
strcpy(ns2->spawn.lastName, "GM Wizard");
break;
case MAGICIANGM:
strcpy(ns2->spawn.lastName, "GM Magician");
break;
case ENCHANTERGM:
strcpy(ns2->spawn.lastName, "GM Enchanter");
break;
case BEASTLORDGM:
strcpy(ns2->spawn.lastName, "GM Beastlord");
break;
case BERSERKERGM:
strcpy(ns2->spawn.lastName, "GM Berserker");
break;
case MERCERNARY_MASTER:
strcpy(ns->spawn.lastName, "Mercenary Recruiter");
break;
default:
strcpy(ns2->spawn.lastName, ns->spawn.lastName);
break;
}
// Set default Last Names for certain Classes if not defined
if (strlen(ns->spawn.lastName) == 0)
{
switch (ns->spawn.class_)
{
case TRIBUTE_MASTER:
strcpy(ns2->spawn.lastName, "Tribute Master");
break;
case ADVENTURERECRUITER:
strcpy(ns2->spawn.lastName, "Adventure Recruiter");
break;
case BANKER:
strcpy(ns2->spawn.lastName, "Banker");
break;
case ADVENTUREMERCHANT:
strcpy(ns2->spawn.lastName, "Adventure Merchant");
break;
case WARRIORGM:
strcpy(ns2->spawn.lastName, "GM Warrior");
break;
case PALADINGM:
strcpy(ns2->spawn.lastName, "GM Paladin");
break;
case RANGERGM:
strcpy(ns2->spawn.lastName, "GM Ranger");
break;
case SHADOWKNIGHTGM:
strcpy(ns2->spawn.lastName, "GM Shadowknight");
break;
case DRUIDGM:
strcpy(ns2->spawn.lastName, "GM Druid");
break;
case BARDGM:
strcpy(ns2->spawn.lastName, "GM Bard");
break;
case ROGUEGM:
strcpy(ns2->spawn.lastName, "GM Rogue");
break;
case SHAMANGM:
strcpy(ns2->spawn.lastName, "GM Shaman");
break;
case NECROMANCERGM:
strcpy(ns2->spawn.lastName, "GM Necromancer");
break;
case WIZARDGM:
strcpy(ns2->spawn.lastName, "GM Wizard");
break;
case MAGICIANGM:
strcpy(ns2->spawn.lastName, "GM Magician");
break;
case ENCHANTERGM:
strcpy(ns2->spawn.lastName, "GM Enchanter");
break;
case BEASTLORDGM:
strcpy(ns2->spawn.lastName, "GM Beastlord");
break;
case BERSERKERGM:
strcpy(ns2->spawn.lastName, "GM Berserker");
break;
case MERCERNARY_MASTER:
strcpy(ns2->spawn.lastName, "Mercenary liaison");
break;
default:
strcpy(ns2->spawn.lastName, ns->spawn.lastName);
break;
}
}
else
{
strcpy(ns2->spawn.lastName, ns->spawn.lastName);
}
memset(&app->pBuffer[sizeof(Spawn_Struct)-7], 0xFF, 7);
}
@ -904,7 +924,7 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
}
ns->spawn.guildrank = 0xFF;
ns->spawn.size = size;
ns->spawn.size = size;
ns->spawn.bodytype = bodytype;
// The 'flymode' settings have the following effect:
// 0 - Mobs in water sink like a stone to the bottom
@ -1229,7 +1249,7 @@ void Mob::ShowStats(Client* client)
}
else if (IsCorpse()) {
if (IsPlayerCorpse()) {
client->Message(0, " CharID: %i PlayerCorpse: %i", CastToCorpse()->GetCharID(), CastToCorpse()->GetDBID());
client->Message(0, " CharID: %i PlayerCorpse: %i", CastToCorpse()->GetCharID(), CastToCorpse()->GetCorpseDBID());
}
else {
client->Message(0, " NPCCorpse", GetID());
@ -1350,147 +1370,150 @@ void Mob::SendIllusionPacket(uint16 in_race, uint8 in_gender, uint8 in_texture,
uint16 BaseRace = GetBaseRace();
if (in_race == 0) {
this->race = BaseRace;
if (in_race == 0)
{
race = BaseRace;
if (in_gender == 0xFF)
this->gender = GetBaseGender();
else
this->gender = in_gender;
}
else {
this->race = in_race;
if (in_gender == 0xFF) {
uint8 tmp = Mob::GetDefaultGender(this->race, gender);
if (tmp == 2)
gender = 2;
else if (gender == 2 && GetBaseGender() == 2)
gender = tmp;
else if (gender == 2)
gender = GetBaseGender();
}
gender = GetBaseGender();
else
gender = in_gender;
}
if (in_texture == 0xFF) {
if (in_race <= 12 || in_race == 128 || in_race == 130 || in_race == 330 || in_race == 522)
this->texture = 0xFF;
else
this->texture = GetTexture();
}
else
this->texture = in_texture;
{
race = in_race;
if (in_gender == 0xFF)
gender = GetDefaultGender(race, gender);
else
gender = in_gender;
}
if (in_helmtexture == 0xFF) {
if (in_race <= 12 || in_race == 128 || in_race == 130 || in_race == 330 || in_race == 522)
this->helmtexture = 0xFF;
else if (in_texture != 0xFF)
this->helmtexture = in_texture;
if (in_texture == 0xFF)
{
if (IsPlayerRace(in_race))
texture = 0xFF;
else
this->helmtexture = GetHelmTexture();
texture = GetTexture();
}
else
this->helmtexture = in_helmtexture;
{
texture = in_texture;
}
if (in_helmtexture == 0xFF)
{
if (IsPlayerRace(in_race))
helmtexture = 0xFF;
else if (in_texture != 0xFF)
helmtexture = in_texture;
else
helmtexture = GetHelmTexture();
}
else
{
helmtexture = in_helmtexture;
}
if (in_haircolor == 0xFF)
this->haircolor = GetHairColor();
haircolor = GetHairColor();
else
this->haircolor = in_haircolor;
haircolor = in_haircolor;
if (in_beardcolor == 0xFF)
this->beardcolor = GetBeardColor();
beardcolor = GetBeardColor();
else
this->beardcolor = in_beardcolor;
beardcolor = in_beardcolor;
if (in_eyecolor1 == 0xFF)
this->eyecolor1 = GetEyeColor1();
eyecolor1 = GetEyeColor1();
else
this->eyecolor1 = in_eyecolor1;
eyecolor1 = in_eyecolor1;
if (in_eyecolor2 == 0xFF)
this->eyecolor2 = GetEyeColor2();
eyecolor2 = GetEyeColor2();
else
this->eyecolor2 = in_eyecolor2;
eyecolor2 = in_eyecolor2;
if (in_hairstyle == 0xFF)
this->hairstyle = GetHairStyle();
hairstyle = GetHairStyle();
else
this->hairstyle = in_hairstyle;
hairstyle = in_hairstyle;
if (in_luclinface == 0xFF)
this->luclinface = GetLuclinFace();
luclinface = GetLuclinFace();
else
this->luclinface = in_luclinface;
luclinface = in_luclinface;
if (in_beard == 0xFF)
this->beard = GetBeard();
beard = GetBeard();
else
this->beard = in_beard;
beard = in_beard;
this->aa_title = 0xFF;
aa_title = in_aa_title;
if (in_drakkin_heritage == 0xFFFFFFFF)
this->drakkin_heritage = GetDrakkinHeritage();
drakkin_heritage = GetDrakkinHeritage();
else
this->drakkin_heritage = in_drakkin_heritage;
drakkin_heritage = in_drakkin_heritage;
if (in_drakkin_tattoo == 0xFFFFFFFF)
this->drakkin_tattoo = GetDrakkinTattoo();
drakkin_tattoo = GetDrakkinTattoo();
else
this->drakkin_tattoo = in_drakkin_tattoo;
drakkin_tattoo = in_drakkin_tattoo;
if (in_drakkin_details == 0xFFFFFFFF)
this->drakkin_details = GetDrakkinDetails();
drakkin_details = GetDrakkinDetails();
else
this->drakkin_details = in_drakkin_details;
drakkin_details = in_drakkin_details;
if (in_size <= 0.0f)
this->size = GetSize();
size = GetSize();
else
this->size = in_size;
size = in_size;
// Forces the feature information to be pulled from the Player Profile
if (this->IsClient() && in_race == 0) {
this->race = CastToClient()->GetBaseRace();
this->gender = CastToClient()->GetBaseGender();
this->texture = 0xFF;
this->helmtexture = 0xFF;
this->haircolor = CastToClient()->GetBaseHairColor();
this->beardcolor = CastToClient()->GetBaseBeardColor();
this->eyecolor1 = CastToClient()->GetBaseEyeColor();
this->eyecolor2 = CastToClient()->GetBaseEyeColor();
this->hairstyle = CastToClient()->GetBaseHairStyle();
this->luclinface = CastToClient()->GetBaseFace();
this->beard = CastToClient()->GetBaseBeard();
this->aa_title = 0xFF;
this->drakkin_heritage = CastToClient()->GetBaseHeritage();
this->drakkin_tattoo = CastToClient()->GetBaseTattoo();
this->drakkin_details = CastToClient()->GetBaseDetails();
// Reset features to Base from the Player Profile
if (IsClient() && in_race == 0)
{
race = CastToClient()->GetBaseRace();
gender = CastToClient()->GetBaseGender();
texture = 0xFF;
helmtexture = 0xFF;
haircolor = CastToClient()->GetBaseHairColor();
beardcolor = CastToClient()->GetBaseBeardColor();
eyecolor1 = CastToClient()->GetBaseEyeColor();
eyecolor2 = CastToClient()->GetBaseEyeColor();
hairstyle = CastToClient()->GetBaseHairStyle();
luclinface = CastToClient()->GetBaseFace();
beard = CastToClient()->GetBaseBeard();
aa_title = 0xFF;
drakkin_heritage = CastToClient()->GetBaseHeritage();
drakkin_tattoo = CastToClient()->GetBaseTattoo();
drakkin_details = CastToClient()->GetBaseDetails();
switch(race){
case OGRE:
this->size = 9;
size = 9;
break;
case TROLL:
this->size = 8;
size = 8;
break;
case VAHSHIR:
case BARBARIAN:
this->size = 7;
size = 7;
break;
case HALF_ELF:
case WOOD_ELF:
case DARK_ELF:
case FROGLOK:
this->size = 5;
size = 5;
break;
case DWARF:
this->size = 4;
size = 4;
break;
case HALFLING:
case GNOME:
this->size = 3;
size = 3;
break;
default:
this->size = 6;
size = 6;
break;
}
}
@ -1498,39 +1521,250 @@ void Mob::SendIllusionPacket(uint16 in_race, uint8 in_gender, uint8 in_texture,
EQApplicationPacket* outapp = new EQApplicationPacket(OP_Illusion, sizeof(Illusion_Struct));
memset(outapp->pBuffer, 0, sizeof(outapp->pBuffer));
Illusion_Struct* is = (Illusion_Struct*) outapp->pBuffer;
is->spawnid = this->GetID();
is->spawnid = GetID();
strcpy(is->charname, GetCleanName());
is->race = this->race;
is->gender = this->gender;
is->texture = this->texture;
is->helmtexture = this->helmtexture;
is->haircolor = this->haircolor;
is->beardcolor = this->beardcolor;
is->beard = this->beard;
is->eyecolor1 = this->eyecolor1;
is->eyecolor2 = this->eyecolor2;
is->hairstyle = this->hairstyle;
is->face = this->luclinface;
//is->aa_title = this->aa_title;
is->drakkin_heritage = this->drakkin_heritage;
is->drakkin_tattoo = this->drakkin_tattoo;
is->drakkin_details = this->drakkin_details;
is->size = this->size;
is->race = race;
is->gender = gender;
is->texture = texture;
is->helmtexture = helmtexture;
is->haircolor = haircolor;
is->beardcolor = beardcolor;
is->beard = beard;
is->eyecolor1 = eyecolor1;
is->eyecolor2 = eyecolor2;
is->hairstyle = hairstyle;
is->face = luclinface;
is->drakkin_heritage = drakkin_heritage;
is->drakkin_tattoo = drakkin_tattoo;
is->drakkin_details = drakkin_details;
is->size = size;
entity_list.QueueClients(this, outapp);
safe_delete(outapp);
mlog(CLIENT__SPELLS, "Illusion: Race = %i, Gender = %i, Texture = %i, HelmTexture = %i, HairColor = %i, BeardColor = %i, EyeColor1 = %i, EyeColor2 = %i, HairStyle = %i, Face = %i, DrakkinHeritage = %i, DrakkinTattoo = %i, DrakkinDetails = %i, Size = %f",
this->race, this->gender, this->texture, this->helmtexture, this->haircolor, this->beardcolor, this->eyecolor1, this->eyecolor2, this->hairstyle, this->luclinface, this->drakkin_heritage, this->drakkin_tattoo, this->drakkin_details, this->size);
race, gender, texture, helmtexture, haircolor, beardcolor, eyecolor1, eyecolor2, hairstyle, luclinface, drakkin_heritage, drakkin_tattoo, drakkin_details, size);
}
bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables)
{
if (IsPlayerRace(GetRace()))
{
uint8 Gender = GetGender();
uint8 Texture = 0xFF;
uint8 HelmTexture = 0xFF;
uint8 HairColor = 0xFF;
uint8 BeardColor = 0xFF;
uint8 EyeColor1 = 0xFF;
uint8 EyeColor2 = 0xFF;
uint8 HairStyle = 0xFF;
uint8 LuclinFace = 0xFF;
uint8 Beard = 0xFF;
uint32 DrakkinHeritage = 0xFFFFFFFF;
uint32 DrakkinTattoo = 0xFFFFFFFF;
uint32 DrakkinDetails = 0xFFFFFFFF;
// Set some common feature settings
EyeColor1 = zone->random.Int(0, 9);
EyeColor2 = zone->random.Int(0, 9);
LuclinFace = zone->random.Int(0, 7);
// Adjust all settings based on the min and max for each feature of each race and gender
switch (GetRace())
{
case 1: // Human
HairColor = zone->random.Int(0, 19);
if (Gender == 0) {
BeardColor = HairColor;
HairStyle = zone->random.Int(0, 3);
Beard = zone->random.Int(0, 5);
}
if (Gender == 1) {
HairStyle = zone->random.Int(0, 2);
}
break;
case 2: // Barbarian
HairColor = zone->random.Int(0, 19);
LuclinFace = zone->random.Int(0, 87);
if (Gender == 0) {
BeardColor = HairColor;
HairStyle = zone->random.Int(0, 3);
Beard = zone->random.Int(0, 5);
}
if (Gender == 1) {
HairStyle = zone->random.Int(0, 2);
}
break;
case 3: // Erudite
if (Gender == 0) {
BeardColor = zone->random.Int(0, 19);
Beard = zone->random.Int(0, 5);
LuclinFace = zone->random.Int(0, 57);
}
if (Gender == 1) {
LuclinFace = zone->random.Int(0, 87);
}
break;
case 4: // WoodElf
HairColor = zone->random.Int(0, 19);
if (Gender == 0) {
HairStyle = zone->random.Int(0, 3);
}
if (Gender == 1) {
HairStyle = zone->random.Int(0, 2);
}
break;
case 5: // HighElf
HairColor = zone->random.Int(0, 14);
if (Gender == 0) {
HairStyle = zone->random.Int(0, 3);
LuclinFace = zone->random.Int(0, 37);
BeardColor = HairColor;
}
if (Gender == 1) {
HairStyle = zone->random.Int(0, 2);
}
break;
case 6: // DarkElf
HairColor = zone->random.Int(13, 18);
if (Gender == 0) {
HairStyle = zone->random.Int(0, 3);
LuclinFace = zone->random.Int(0, 37);
BeardColor = HairColor;
}
if (Gender == 1) {
HairStyle = zone->random.Int(0, 2);
}
break;
case 7: // HalfElf
HairColor = zone->random.Int(0, 19);
if (Gender == 0) {
HairStyle = zone->random.Int(0, 3);
LuclinFace = zone->random.Int(0, 37);
BeardColor = HairColor;
}
if (Gender == 1) {
HairStyle = zone->random.Int(0, 2);
}
break;
case 8: // Dwarf
HairColor = zone->random.Int(0, 19);
BeardColor = HairColor;
if (Gender == 0) {
HairStyle = zone->random.Int(0, 3);
Beard = zone->random.Int(0, 5);
}
if (Gender == 1) {
HairStyle = zone->random.Int(0, 2);
LuclinFace = zone->random.Int(0, 17);
}
break;
case 9: // Troll
EyeColor1 = zone->random.Int(0, 10);
EyeColor2 = zone->random.Int(0, 10);
if (Gender == 1) {
HairStyle = zone->random.Int(0, 3);
HairColor = zone->random.Int(0, 23);
}
break;
case 10: // Ogre
if (Gender == 1) {
HairStyle = zone->random.Int(0, 3);
HairColor = zone->random.Int(0, 23);
}
break;
case 11: // Halfling
HairColor = zone->random.Int(0, 19);
if (Gender == 0) {
BeardColor = HairColor;
HairStyle = zone->random.Int(0, 3);
Beard = zone->random.Int(0, 5);
}
if (Gender == 1) {
HairStyle = zone->random.Int(0, 2);
}
break;
case 12: // Gnome
HairColor = zone->random.Int(0, 24);
if (Gender == 0) {
BeardColor = HairColor;
HairStyle = zone->random.Int(0, 3);
Beard = zone->random.Int(0, 5);
}
if (Gender == 1) {
HairStyle = zone->random.Int(0, 2);
}
break;
case 128: // Iksar
case 130: // VahShir
break;
case 330: // Froglok
LuclinFace = zone->random.Int(0, 9);
case 522: // Drakkin
HairColor = zone->random.Int(0, 3);
BeardColor = HairColor;
EyeColor1 = zone->random.Int(0, 11);
EyeColor2 = zone->random.Int(0, 11);
LuclinFace = zone->random.Int(0, 6);
DrakkinHeritage = zone->random.Int(0, 6);
DrakkinTattoo = zone->random.Int(0, 7);
DrakkinDetails = zone->random.Int(0, 7);
if (Gender == 0) {
Beard = zone->random.Int(0, 12);
HairStyle = zone->random.Int(0, 8);
}
if (Gender == 1) {
Beard = zone->random.Int(0, 3);
HairStyle = zone->random.Int(0, 7);
}
break;
default:
break;
}
if (set_variables)
{
haircolor = HairColor;
beardcolor = BeardColor;
eyecolor1 = EyeColor1;
eyecolor2 = EyeColor2;
hairstyle = HairStyle;
luclinface = LuclinFace;
beard = Beard;
drakkin_heritage = DrakkinHeritage;
drakkin_tattoo = DrakkinTattoo;
drakkin_details = DrakkinDetails;
}
if (send_illusion)
{
SendIllusionPacket(GetRace(), Gender, Texture, HelmTexture, HairColor, BeardColor,
EyeColor1, EyeColor2, HairStyle, LuclinFace, Beard, 0xFF, DrakkinHeritage,
DrakkinTattoo, DrakkinDetails);
}
return true;
}
return false;
}
bool Mob::IsPlayerRace(uint16 in_race) {
if ((in_race >= HUMAN && in_race <= GNOME) || in_race == IKSAR || in_race == VAHSHIR || in_race == FROGLOK || in_race == DRAKKIN)
{
return true;
}
return false;
}
uint8 Mob::GetDefaultGender(uint16 in_race, uint8 in_gender) {
//std::cout << "Gender in: " << (int)in_gender << std::endl; // undefined cout [CODEBUG]
if ((in_race > 0 && in_race <= GNOME )
|| in_race == IKSAR || in_race == VAHSHIR || in_race == FROGLOK || in_race == DRAKKIN
|| in_race == 15 || in_race == 50 || in_race == 57 || in_race == 70 || in_race == 98 || in_race == 118) {
if (Mob::IsPlayerRace(in_race) || in_race == 15 || in_race == 50 || in_race == 57 || in_race == 70 || in_race == 98 || in_race == 118) {
if (in_gender >= 2) {
// Female default for PC Races
return 1;
// Male default for PC Races
return 0;
}
else
return in_gender;
@ -2317,7 +2551,7 @@ uint32 Mob::RandomTimer(int min,int max) {
int r = 14000;
if(min != 0 && max != 0 && min < max)
{
r = MakeRandomInt(min, max);
r = zone->random.Int(min, max);
}
return r;
}
@ -2427,6 +2661,9 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const
item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem();
return atoi(&item->IDFile[2]);
}
else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) {
return inst->GetOrnamentationIDFile();
}
else {
if (strlen(item->IDFile) > 2)
return atoi(&item->IDFile[2]);
@ -2707,7 +2944,7 @@ void Mob::ExecWeaponProc(const ItemInst *inst, uint16 spell_id, Mob *on) {
if(IsClient())
twinproc_chance = CastToClient()->GetFocusEffect(focusTwincast, spell_id);
if(twinproc_chance && (MakeRandomInt(0,99) < twinproc_chance))
if(twinproc_chance && zone->random.Roll(twinproc_chance))
twinproc = true;
if (IsBeneficialSpell(spell_id)) {
@ -3024,7 +3261,7 @@ void Mob::TriggerOnCast(uint32 focus_spell, uint32 spell_id, bool aa_trigger)
if(IsValidSpell(trigger_spell_id) && GetTarget()){
SpellFinished(trigger_spell_id, GetTarget(),10, 0, -1, spells[trigger_spell_id].ResistDiff);
CheckNumHitsRemaining(NUMHIT_MatchingSpells,0, focus_spell);
CheckNumHitsRemaining(NUMHIT_MatchingSpells,-1, focus_spell);
}
}
}
@ -3049,7 +3286,7 @@ bool Mob::TrySpellTrigger(Mob *target, uint32 spell_id, int effect)
{
if (spells[spell_id].effectid[i] == SE_SpellTrigger)
{
if(MakeRandomInt(0, trig_chance) <= spells[spell_id].base[i])
if(zone->random.Int(0, trig_chance) <= spells[spell_id].base[i])
{
// If we trigger an effect then its over.
if (IsValidSpell(spells[spell_id].base2[i])){
@ -3069,7 +3306,7 @@ bool Mob::TrySpellTrigger(Mob *target, uint32 spell_id, int effect)
// if the chances don't add to 100, then each effect gets a chance to fire, chance for no trigger as well.
else
{
if(MakeRandomInt(0, 100) <= spells[spell_id].base[effect])
if(zone->random.Int(0, 100) <= spells[spell_id].base[effect])
{
if (IsValidSpell(spells[spell_id].base2[effect])){
SpellFinished(spells[spell_id].base2[effect], target, 10, 0, -1, spells[spells[spell_id].base2[effect]].ResistDiff);
@ -3174,7 +3411,7 @@ void Mob::TryTwincast(Mob *caster, Mob *target, uint32 spell_id)
if (focus > 0)
{
if(MakeRandomInt(0, 100) <= focus)
if(zone->random.Roll(focus))
{
Message(MT_Spells,"You twincast %s!",spells[spell_id].name);
SpellFinished(spell_id, target, 10, 0, -1, spells[spell_id].ResistDiff);
@ -3193,7 +3430,7 @@ void Mob::TryTwincast(Mob *caster, Mob *target, uint32 spell_id)
int32 focus = CalcFocusEffect(focusTwincast, buffs[i].spellid, spell_id);
if(focus > 0)
{
if(MakeRandomInt(0, 100) <= focus)
if(zone->random.Roll(focus))
{
SpellFinished(spell_id, target, 10, 0, -1, spells[spell_id].ResistDiff);
}
@ -3361,7 +3598,7 @@ void Mob::TrySympatheticProc(Mob *target, uint32 spell_id)
SpellFinished(focus_trigger, target, 10, 0, -1, spells[focus_trigger].ResistDiff);
}
CheckNumHitsRemaining(NUMHIT_MatchingSpells, 0, focus_spell);
CheckNumHitsRemaining(NUMHIT_MatchingSpells, -1, focus_spell);
}
}
@ -3974,7 +4211,7 @@ void Mob::TrySpellOnKill(uint8 level, uint16 spell_id)
{
if (IsValidSpell(spells[spell_id].base2[i]) && spells[spell_id].max[i] <= level)
{
if(MakeRandomInt(0,99) < spells[spell_id].base[i])
if(zone->random.Roll(spells[spell_id].base[i]))
SpellFinished(spells[spell_id].base2[i], this, 10, 0, -1, spells[spells[spell_id].base2[i]].ResistDiff);
}
}
@ -3989,17 +4226,17 @@ void Mob::TrySpellOnKill(uint8 level, uint16 spell_id)
for(int i = 0; i < MAX_SPELL_TRIGGER*3; i+=3) {
if(aabonuses.SpellOnKill[i] && IsValidSpell(aabonuses.SpellOnKill[i]) && (level >= aabonuses.SpellOnKill[i + 2])) {
if(MakeRandomInt(0, 99) < static_cast<int>(aabonuses.SpellOnKill[i + 1]))
if(zone->random.Roll(static_cast<int>(aabonuses.SpellOnKill[i + 1])))
SpellFinished(aabonuses.SpellOnKill[i], this, 10, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff);
}
if(itembonuses.SpellOnKill[i] && IsValidSpell(itembonuses.SpellOnKill[i]) && (level >= itembonuses.SpellOnKill[i + 2])){
if(MakeRandomInt(0, 99) < static_cast<int>(itembonuses.SpellOnKill[i + 1]))
if(zone->random.Roll(static_cast<int>(itembonuses.SpellOnKill[i + 1])))
SpellFinished(itembonuses.SpellOnKill[i], this, 10, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff);
}
if(spellbonuses.SpellOnKill[i] && IsValidSpell(spellbonuses.SpellOnKill[i]) && (level >= spellbonuses.SpellOnKill[i + 2])) {
if(MakeRandomInt(0, 99) < static_cast<int>(spellbonuses.SpellOnKill[i + 1]))
if(zone->random.Roll(static_cast<int>(spellbonuses.SpellOnKill[i + 1])))
SpellFinished(spellbonuses.SpellOnKill[i], this, 10, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff);
}
@ -4016,19 +4253,19 @@ bool Mob::TrySpellOnDeath()
for(int i = 0; i < MAX_SPELL_TRIGGER*2; i+=2) {
if(IsClient() && aabonuses.SpellOnDeath[i] && IsValidSpell(aabonuses.SpellOnDeath[i])) {
if(MakeRandomInt(0, 99) < static_cast<int>(aabonuses.SpellOnDeath[i + 1])) {
if(zone->random.Roll(static_cast<int>(aabonuses.SpellOnDeath[i + 1]))) {
SpellFinished(aabonuses.SpellOnDeath[i], this, 10, 0, -1, spells[aabonuses.SpellOnDeath[i]].ResistDiff);
}
}
if(itembonuses.SpellOnDeath[i] && IsValidSpell(itembonuses.SpellOnDeath[i])) {
if(MakeRandomInt(0, 99) < static_cast<int>(itembonuses.SpellOnDeath[i + 1])) {
if(zone->random.Roll(static_cast<int>(itembonuses.SpellOnDeath[i + 1]))) {
SpellFinished(itembonuses.SpellOnDeath[i], this, 10, 0, -1, spells[itembonuses.SpellOnDeath[i]].ResistDiff);
}
}
if(spellbonuses.SpellOnDeath[i] && IsValidSpell(spellbonuses.SpellOnDeath[i])) {
if(MakeRandomInt(0, 99) < static_cast<int>(spellbonuses.SpellOnDeath[i + 1])) {
if(zone->random.Roll(static_cast<int>(spellbonuses.SpellOnDeath[i + 1]))) {
SpellFinished(spellbonuses.SpellOnDeath[i], this, 10, 0, -1, spells[spellbonuses.SpellOnDeath[i]].ResistDiff);
}
}
@ -4191,55 +4428,12 @@ bool Mob::TryReflectSpell(uint32 spell_id)
int chance = itembonuses.reflect_chance + spellbonuses.reflect_chance + aabonuses.reflect_chance;
if(chance && MakeRandomInt(0, 99) < chance)
if(chance && zone->random.Roll(chance))
return true;
return false;
}
void Mob::SpellProjectileEffect()
{
bool time_disable = false;
for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) {
if (projectile_increment[i] == 0){
continue;
}
Mob* target = entity_list.GetMobID(projectile_target_id[i]);
float dist = 0;
if (target)
dist = target->CalculateDistance(projectile_x[i], projectile_y[i], projectile_z[i]);
int increment_end = 0;
increment_end = static_cast<int>(dist / 10) - 1; //This pretty accurately determines end time for speed for 1.5 and timer of 250 ms
if (increment_end <= projectile_increment[i]){
if (target && IsValidSpell(projectile_spell_id[i]))
SpellOnTarget(projectile_spell_id[i], target, false, true, spells[projectile_spell_id[i]].ResistDiff, true);
projectile_spell_id[i] = 0;
projectile_target_id[i] = 0;
projectile_x[i] = 0, projectile_y[i] = 0, projectile_z[i] = 0;
projectile_increment[i] = 0;
time_disable = true;
}
else {
projectile_increment[i]++;
time_disable = false;
}
}
if (time_disable)
projectile_timer.Disable();
}
void Mob::DoGravityEffect()
{
Mob *caster = nullptr;

View File

@ -18,7 +18,6 @@
#ifndef MOB_H
#define MOB_H
#include "../common/features.h"
#include "common.h"
#include "entity.h"
#include "hate_list.h"
@ -26,14 +25,22 @@
#include "position.h"
#include <set>
#include <vector>
#include <string>
char* strn0cpy(char* dest, const char* source, uint32 size);
#define MAX_SPECIAL_ATTACK_PARAMS 8
class EGNode;
class MobFearState;
class Client;
class EQApplicationPacket;
class Group;
class ItemInst;
class NPC;
class Raid;
struct Item_Struct;
struct NewSpawn_Struct;
struct PlayerPositionUpdateServer_Struct;
class Mob : public Entity {
public:
enum CLIENT_CONN_STATUS { CLIENT_CONNECTING, CLIENT_CONNECTED, CLIENT_LINKDEAD,
@ -228,8 +235,7 @@ public:
uint16 CastingSpellID() const { return casting_spell_id; }
bool DoCastingChecks();
bool TryDispel(uint8 caster_level, uint8 buff_level, int level_modifier);
void SpellProjectileEffect();
bool TrySpellProjectile(Mob* spell_target, uint16 spell_id);
bool TrySpellProjectile(Mob* spell_target, uint16 spell_id, float speed = 1.5f);
void ResourceTap(int32 damage, uint16 spell_id);
void TryTriggerThreshHold(int32 damage, int effect_id, Mob* attacker);
bool CheckSpellCategory(uint16 spell_id, int category_id, int effect_id);
@ -273,7 +279,7 @@ public:
int16 GetBuffSlotFromType(uint16 type);
uint16 GetSpellIDFromSlot(uint8 slot);
int CountDispellableBuffs();
void CheckNumHitsRemaining(uint8 type, uint32 buff_slot=0, uint16 spell_id=SPELL_UNKNOWN);
void CheckNumHitsRemaining(uint8 type, int32 buff_slot=-1, uint16 spell_id=SPELL_UNKNOWN);
bool HasNumhits() const { return has_numhits; }
inline void Numhits(bool val) { has_numhits = val; }
bool HasMGB() const { return has_MGB; }
@ -490,6 +496,7 @@ public:
//Util
static uint32 RandomTimer(int min, int max);
static uint8 GetDefaultGender(uint16 in_race, uint8 in_gender = 0xFF);
static bool IsPlayerRace(uint16 in_race);
uint16 GetSkillByItemType(int ItemType);
uint8 GetItemTypeBySkill(SkillUseTypes skill);
virtual void MakePet(uint16 spell_id, const char* pettype, const char *petname = nullptr);
@ -570,6 +577,7 @@ public:
uint8 in_hairstyle = 0xFF, uint8 in_luclinface = 0xFF, uint8 in_beard = 0xFF, uint8 in_aa_title = 0xFF,
uint32 in_drakkin_heritage = 0xFFFFFFFF, uint32 in_drakkin_tattoo = 0xFFFFFFFF,
uint32 in_drakkin_details = 0xFFFFFFFF, float in_size = -1.0f);
bool RandomizeFeatures(bool send_illusion = true, bool set_variables = true);
virtual void Stun(int duration);
virtual void UnStun();
inline void Silence(bool newval) { silenced = newval; }
@ -721,9 +729,14 @@ public:
int32 ReduceAllDamage(int32 damage);
virtual void DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool HitChance=false, bool CanAvoid=true);
virtual void DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const Item_Struct* item=nullptr, uint16 weapon_damage=0, int16 chance_mod=0,int16 focus=0, int ReuseTime=0);
virtual void DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const Item_Struct* AmmoItem=nullptr, uint16 weapon_damage=0, int16 chance_mod=0,int16 focus=0, int ReuseTime=0, uint32 range_id=0, int AmmoSlot=0, float speed = 4.0f);
virtual void DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse, int16 chance_mod=0, int16 focus=0, bool CanRiposte=false, int ReuseTime=0);
virtual void DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const ItemInst* Ammo=nullptr, uint16 weapon_damage=0, int16 chance_mod=0, int16 focus=0, int ReuseTime=0);
virtual void DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const ItemInst* Ammo=nullptr, uint16 weapon_damage=0, int16 chance_mod=0, int16 focus=0, int ReuseTime=0, uint32 range_id=0, uint32 ammo_id=0, const Item_Struct *AmmoItem=nullptr, int AmmoSlot=0, float speed= 4.0f);
bool TryProjectileAttack(Mob* other, const Item_Struct *item, SkillUseTypes skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo, int AmmoSlot, float speed);
void ProjectileAttack();
inline bool HasProjectileAttack() const { return ActiveProjectileATK; }
inline void SetProjectileAttack(bool value) { ActiveProjectileATK = value; }
float GetRangeDistTargetSizeMod(Mob* other);
bool CanDoSpecialAttack(Mob *other);
bool Flurry(ExtraAttackOptions *opts);
bool Rampage(ExtraAttackOptions *opts);
@ -839,7 +852,7 @@ public:
// HP Event
inline int GetNextHPEvent() const { return nexthpevent; }
void SetNextHPEvent( int hpevent );
void SendItemAnimation(Mob *to, const Item_Struct *item, SkillUseTypes skillInUse);
void SendItemAnimation(Mob *to, const Item_Struct *item, SkillUseTypes skillInUse, float velocity= 4.0);
inline int& GetNextIncHPEvent() { return nextinchpevent; }
void SetNextIncHPEvent( int inchpevent );
@ -1079,11 +1092,8 @@ protected:
uint8 bardsong_slot;
uint32 bardsong_target_id;
Timer projectile_timer;
uint32 projectile_spell_id[MAX_SPELL_PROJECTILE];
uint16 projectile_target_id[MAX_SPELL_PROJECTILE];
uint8 projectile_increment[MAX_SPELL_PROJECTILE];
float projectile_x[MAX_SPELL_PROJECTILE], projectile_y[MAX_SPELL_PROJECTILE], projectile_z[MAX_SPELL_PROJECTILE];
bool ActiveProjectileATK;
tProjatk ProjectileAtk[MAX_SPELL_PROJECTILE];
xyz_location m_RewindLocation;

View File

@ -57,7 +57,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
return false;
if (iChance < 100) {
if (MakeRandomInt(0, 100) >= iChance)
if (zone->random.Int(0, 100) >= iChance)
return false;
}
@ -94,7 +94,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
dist2 <= spells[AIspells[i].spellid].range*spells[AIspells[i].spellid].range
)
&& (mana_cost <= GetMana() || GetMana() == GetMaxMana())
&& (AIspells[i].time_cancast + (MakeRandomInt(0, 4) * 1000)) <= Timer::GetCurrentTime() //break up the spelling casting over a period of time.
&& (AIspells[i].time_cancast + (zone->random.Int(0, 4) * 1000)) <= Timer::GetCurrentTime() //break up the spelling casting over a period of time.
) {
#if MobAI_DEBUG_Spells >= 21
@ -126,7 +126,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
}
case SpellType_Root: {
Mob *rootee = GetHateRandom();
if (rootee && !rootee->IsRooted() && MakeRandomInt(0, 99) < 50
if (rootee && !rootee->IsRooted() && zone->random.Roll(50)
&& rootee->DontRootMeBefore() < Timer::GetCurrentTime()
&& rootee->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0
) {
@ -165,7 +165,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
}
case SpellType_InCombatBuff: {
if(MakeRandomInt(0, 99) < 50)
if(zone->random.Roll(50))
{
AIDoSpellCast(i, tar, mana_cost);
return true;
@ -184,7 +184,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
case SpellType_Slow:
case SpellType_Debuff: {
Mob * debuffee = GetHateRandom();
if (debuffee && manaR >= 10 && MakeRandomInt(0, 99 < 70) &&
if (debuffee && manaR >= 10 && zone->random.Roll(70) &&
debuffee->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0) {
if (!checked_los) {
if (!CheckLosFN(debuffee))
@ -198,7 +198,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
}
case SpellType_Nuke: {
if (
manaR >= 10 && MakeRandomInt(0, 99) < 70
manaR >= 10 && zone->random.Roll(70)
&& tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0
) {
if(!checked_los) {
@ -212,7 +212,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
break;
}
case SpellType_Dispel: {
if(MakeRandomInt(0, 99) < 15)
if(zone->random.Roll(15))
{
if(!checked_los) {
if(!CheckLosFN(tar))
@ -228,7 +228,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
break;
}
case SpellType_Mez: {
if(MakeRandomInt(0, 99) < 20)
if(zone->random.Roll(20))
{
Mob * mezTar = nullptr;
mezTar = entity_list.GetTargetForMez(this);
@ -244,7 +244,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
case SpellType_Charm:
{
if(!IsPet() && MakeRandomInt(0, 99) < 20)
if(!IsPet() && zone->random.Roll(20))
{
Mob * chrmTar = GetHateRandom();
if(chrmTar && chrmTar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0)
@ -258,7 +258,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
case SpellType_Pet: {
//keep mobs from recasting pets when they have them.
if (!IsPet() && !GetPetID() && MakeRandomInt(0, 99) < 25) {
if (!IsPet() && !GetPetID() && zone->random.Roll(25)) {
AIDoSpellCast(i, tar, mana_cost);
return true;
}
@ -266,7 +266,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
}
case SpellType_Lifetap: {
if (GetHPRatio() <= 95
&& MakeRandomInt(0, 99) < 50
&& zone->random.Roll(50)
&& tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0
) {
if(!checked_los) {
@ -282,7 +282,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
case SpellType_Snare: {
if (
!tar->IsRooted()
&& MakeRandomInt(0, 99) < 50
&& zone->random.Roll(50)
&& tar->DontSnareMeBefore() < Timer::GetCurrentTime()
&& tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0
) {
@ -300,7 +300,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
}
case SpellType_DOT: {
if (
MakeRandomInt(0, 99) < 60
zone->random.Roll(60)
&& tar->DontDotMeBefore() < Timer::GetCurrentTime()
&& tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0
) {
@ -369,7 +369,7 @@ bool EntityList::AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float
return false;
if (iChance < 100) {
uint8 tmp = MakeRandomInt(0, 99);
uint8 tmp = zone->random.Int(0, 99);
if (tmp >= iChance)
return false;
}
@ -594,7 +594,6 @@ void Mob::AI_ShutDown() {
tic_timer.Disable();
mana_timer.Disable();
spellend_timer.Disable();
projectile_timer.Disable();
rewind_timer.Disable();
bindwound_timer.Disable();
stunned_timer.Disable();
@ -685,7 +684,7 @@ void Client::AI_SpellCast()
}
else
{
uint32 idx = MakeRandomInt(0, (valid_spells.size()-1));
uint32 idx = zone->random.Int(0, (valid_spells.size()-1));
spell_to_cast = valid_spells[idx];
slot_to_use = slots[idx];
}
@ -873,7 +872,7 @@ void Client::AI_Process()
if (flurrychance)
{
if(MakeRandomInt(0, 100) < flurrychance)
if(zone->random.Roll(flurrychance))
{
Message_StringID(MT_NPCFlurry, YOU_FLURRY);
Attack(GetTarget(), MainPrimary, false);
@ -890,7 +889,7 @@ void Client::AI_Process()
wpn->GetItem()->ItemType == ItemType2HBlunt ||
wpn->GetItem()->ItemType == ItemType2HPiercing )
{
if(MakeRandomInt(0, 100) < ExtraAttackChanceBonus)
if(zone->random.Roll(ExtraAttackChanceBonus))
{
Attack(GetTarget(), MainPrimary, false);
}
@ -929,7 +928,7 @@ void Client::AI_Process()
int16 DWBonus = spellbonuses.DualWieldChance + itembonuses.DualWieldChance;
DualWieldProbability += DualWieldProbability*float(DWBonus)/ 100.0f;
if(MakeRandomFloat(0.0, 1.0) < DualWieldProbability)
if(zone->random.Roll(DualWieldProbability))
{
Attack(GetTarget(), MainSecondary);
if(CheckDoubleAttack())
@ -1190,7 +1189,7 @@ void Mob::AI_Process() {
//we use this random value in three comparisons with different
//thresholds, and if its truely random, then this should work
//out reasonably and will save us compute resources.
int32 RandRoll = MakeRandomInt(0, 99);
int32 RandRoll = zone->random.Int(0, 99);
if ((CanThisClassDoubleAttack() || GetSpecialAbility(SPECATK_TRIPLE)
|| GetSpecialAbility(SPECATK_QUAD))
//check double attack, this is NOT the same rules that clients use...
@ -1214,7 +1213,7 @@ void Mob::AI_Process() {
int flurry_chance = GetSpecialAbilityParam(SPECATK_FLURRY, 0);
flurry_chance = flurry_chance > 0 ? flurry_chance : RuleI(Combat, NPCFlurryChance);
if (MakeRandomInt(0, 99) < flurry_chance) {
if (zone->random.Roll(flurry_chance)) {
ExtraAttackOptions opts;
int cur = GetSpecialAbilityParam(SPECATK_FLURRY, 2);
if (cur > 0)
@ -1256,7 +1255,7 @@ void Mob::AI_Process() {
int16 flurry_chance = owner->aabonuses.PetFlurry +
owner->spellbonuses.PetFlurry + owner->itembonuses.PetFlurry;
if (flurry_chance && (MakeRandomInt(0, 99) < flurry_chance))
if (flurry_chance && zone->random.Roll(flurry_chance))
Flurry(nullptr);
}
}
@ -1265,7 +1264,7 @@ void Mob::AI_Process() {
{
int rampage_chance = GetSpecialAbilityParam(SPECATK_RAMPAGE, 0);
rampage_chance = rampage_chance > 0 ? rampage_chance : 20;
if(MakeRandomInt(0, 99) < rampage_chance) {
if(zone->random.Roll(rampage_chance)) {
ExtraAttackOptions opts;
int cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 2);
if(cur > 0) {
@ -1304,7 +1303,7 @@ void Mob::AI_Process() {
{
int rampage_chance = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 0);
rampage_chance = rampage_chance > 0 ? rampage_chance : 20;
if(MakeRandomInt(0, 99) < rampage_chance) {
if(zone->random.Roll(rampage_chance)) {
ExtraAttackOptions opts;
int cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 2);
if(cur > 0) {
@ -1348,13 +1347,12 @@ void Mob::AI_Process() {
//can only dual wield without a weapon if your a monk
if(GetSpecialAbility(SPECATK_INNATE_DW) || (GetEquipment(MaterialSecondary) != 0 && GetLevel() > 29) || myclass == MONK || myclass == MONKGM) {
float DualWieldProbability = (GetSkill(SkillDualWield) + GetLevel()) / 400.0f;
if(MakeRandomFloat(0.0, 1.0) < DualWieldProbability)
if(zone->random.Roll(DualWieldProbability))
{
Attack(target, MainSecondary);
if (CanThisClassDoubleAttack())
{
int32 RandRoll = MakeRandomInt(0, 99);
if (RandRoll < (GetLevel() + 20))
if (zone->random.Roll(GetLevel() + 20))
{
Attack(target, MainSecondary);
}
@ -1619,12 +1617,12 @@ void NPC::AI_DoMovement() {
)
{
float movedist = roambox_distance*roambox_distance;
float movex = MakeRandomFloat(0, movedist);
float movex = zone->random.Real(0, movedist);
float movey = movedist - movex;
movex = sqrtf(movex);
movey = sqrtf(movey);
movex *= MakeRandomInt(0, 1) ? 1 : -1;
movey *= MakeRandomInt(0, 1) ? 1 : -1;
movex *= zone->random.Int(0, 1) ? 1 : -1;
movey *= zone->random.Int(0, 1) ? 1 : -1;
roambox_movingto_x = GetX() + movex;
roambox_movingto_y = GetY() + movey;
//Try to calculate new coord using distance.
@ -1635,9 +1633,9 @@ void NPC::AI_DoMovement() {
//New coord is still invalid, ignore distance and just pick a new random coord.
//If we're here we may have a roambox where one side is shorter than the specified distance. Commons, Wkarana, etc.
if (roambox_movingto_x > roambox_max_x || roambox_movingto_x < roambox_min_x)
roambox_movingto_x = MakeRandomFloat(roambox_min_x+1,roambox_max_x-1);
roambox_movingto_x = zone->random.Real(roambox_min_x+1,roambox_max_x-1);
if (roambox_movingto_y > roambox_max_y || roambox_movingto_y < roambox_min_y)
roambox_movingto_y = MakeRandomFloat(roambox_min_y+1,roambox_max_y-1);
roambox_movingto_y = zone->random.Real(roambox_min_y+1,roambox_max_y-1);
}
mlog(AI__WAYPOINTS, "Roam Box: d=%.3f (%.3f->%.3f,%.3f->%.3f): Go To (%.3f,%.3f)",
@ -1879,7 +1877,7 @@ void Mob::AI_Event_NoLongerEngaged() {
if (minLastFightingDelayMoving == maxLastFightingDelayMoving)
pLastFightingDelayMoving += minLastFightingDelayMoving;
else
pLastFightingDelayMoving += MakeRandomInt(minLastFightingDelayMoving, maxLastFightingDelayMoving);
pLastFightingDelayMoving += zone->random.Int(minLastFightingDelayMoving, maxLastFightingDelayMoving);
// So mobs don't keep running as a ghost until AIwalking_timer fires
// if they were moving prior to losing all hate
if(IsMoving()){

View File

@ -1,22 +1,15 @@
#include "../common/debug.h"
#include "../common/timer.h"
#include <cmath>
#include <stdlib.h>
#include "spawn2.h"
#include "entity.h"
#include "masterentity.h"
#include "zone.h"
#include "spawngroup.h"
#include "zonedb.h"
#include "npc.h"
#include "mob.h"
#include "client.h"
#include "entity.h"
#include "mob.h"
#include "npc.h"
#include "worldserver.h"
#include "quest_parser_collection.h"
#include "event_codes.h"
#include "embparser.h"
#include <string>
#include <iostream>
#include "zone.h"
class ItemInst;
class Spawn2;
struct Consider_Struct;
struct DBTradeskillRecipe_Struct;
struct Item_Struct;
extern EntityList entity_list;
extern Zone* zone;

View File

@ -97,7 +97,7 @@ extern Zone* zone;
EQStreamFactory eqsf(ZoneStream);
npcDecayTimes_Struct npcCorpseDecayTimes[100];
TitleManager title_manager;
QueryServ *QServ = 0;
QueryServ *QServ = 0;
TaskManager *taskmanager = 0;
QuestParserCollection *parse = 0;
@ -642,4 +642,3 @@ void UpdateWindowTitle(char* iNewTitle) {
SetConsoleTitle(tmp);
#endif
}

View File

@ -26,9 +26,6 @@
#include <netdb.h>
#endif
#include <errno.h>
#include <fcntl.h>
#include "../common/types.h"
#include "../common/timer.h"
void CatchSignal(int);

View File

@ -15,15 +15,34 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/bodytypes.h"
#include "../common/classes.h"
#include "../common/debug.h"
#include <iostream>
#include <string>
#include <cctype>
#include <math.h>
#include "../common/moremath.h"
#include <stdio.h>
#include "../common/packet_dump_file.h"
#include "../common/misc_functions.h"
#include "../common/rulesys.h"
#include "../common/seperator.h"
#include "../common/spdat.h"
#include "../common/string_util.h"
#include "../common/clientversions.h"
#include "../common/features.h"
#include "../common/item.h"
#include "../common/item_struct.h"
#include "../common/linked_list.h"
#include "../common/servertalk.h"
#include "aa.h"
#include "client.h"
#include "entity.h"
#include "npc.h"
#include "string_ids.h"
#include "spawn2.h"
#include "zone.h"
#include <cctype>
#include <stdio.h>
#include <string>
#ifdef _WINDOWS
#define snprintf _snprintf
#define strncasecmp _strnicmp
@ -33,27 +52,10 @@
#include <pthread.h>
#endif
#include "npc.h"
#include "map.h"
#include "entity.h"
#include "masterentity.h"
#include "../common/spdat.h"
#include "../common/bodytypes.h"
#include "spawngroup.h"
#include "../common/misc_functions.h"
#include "../common/string_util.h"
#include "../common/rulesys.h"
#include "string_ids.h"
//#define SPELLQUEUE //Use only if you want to be spammed by spell testing
extern Zone* zone;
extern volatile bool ZoneLoaded;
extern EntityList entity_list;
#include "quest_parser_collection.h"
NPC::NPC(const NPCType* d, Spawn2* in_respawn, const xyz_heading& position, int iflymode, bool IsCorpse)
: Mob(d->name,
d->lastname,
@ -283,7 +285,7 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, const xyz_heading& position, int
if(trap_list.size() > 0)
{
std::list<LDoNTrapTemplate*>::iterator trap_list_iter = trap_list.begin();
std::advance(trap_list_iter, MakeRandomInt(0, trap_list.size() - 1));
std::advance(trap_list_iter, zone->random.Int(0, trap_list.size() - 1));
LDoNTrapTemplate* tt = (*trap_list_iter);
if(tt)
{
@ -536,10 +538,10 @@ void NPC::AddCash(uint16 in_copper, uint16 in_silver, uint16 in_gold, uint16 in_
}
void NPC::AddCash() {
copper = MakeRandomInt(1, 100);
silver = MakeRandomInt(1, 50);
gold = MakeRandomInt(1, 10);
platinum = MakeRandomInt(1, 5);
copper = zone->random.Int(1, 100);
silver = zone->random.Int(1, 50);
gold = zone->random.Int(1, 10);
platinum = zone->random.Int(1, 5);
}
void NPC::RemoveCash() {
@ -656,8 +658,7 @@ bool NPC::Process()
viral_timer_counter = 0;
}
if(projectile_timer.Check())
SpellProjectileEffect();
ProjectileAttack();
if(spellbonuses.GravityEffect == 1) {
if(gravity_timer.Check())
@ -1359,7 +1360,7 @@ void NPC::PickPocket(Client* thief) {
return;
}
if(MakeRandomInt(0, 100) > 95){
if(zone->random.Roll(5)) {
AddToHateList(thief, 50);
Say("Stop thief!");
thief->Message(13, "You are noticed trying to steal!");
@ -1388,7 +1389,7 @@ void NPC::PickPocket(Client* thief) {
memset(charges,0,50);
//Determine wheter to steal money or an item.
bool no_coin = ((money[0] + money[1] + money[2] + money[3]) == 0);
bool steal_item = (MakeRandomInt(0, 99) < 50 || no_coin);
bool steal_item = (zone->random.Roll(50) || no_coin);
if (steal_item)
{
ItemList::iterator cur,end;
@ -1418,7 +1419,7 @@ void NPC::PickPocket(Client* thief) {
}
if (x > 0)
{
int random = MakeRandomInt(0, x-1);
int random = zone->random.Int(0, x-1);
inst = database.CreateItem(steal_items[random], charges[random]);
if (inst)
{
@ -1453,7 +1454,7 @@ void NPC::PickPocket(Client* thief) {
}
if (!steal_item) //Steal money
{
uint32 amt = MakeRandomInt(1, (steal_skill/25)+1);
uint32 amt = zone->random.Int(1, (steal_skill/25)+1);
int steal_type = 0;
if (!money[0])
{
@ -1468,7 +1469,7 @@ void NPC::PickPocket(Client* thief) {
}
}
if (MakeRandomInt(0, 100) <= stealchance)
if (zone->random.Roll(stealchance))
{
switch (steal_type)
{
@ -1949,7 +1950,7 @@ void NPC::ModifyNPCStat(const char *identifier, const char *newValue)
void NPC::LevelScale() {
uint8 random_level = (MakeRandomInt(level, maxlevel));
uint8 random_level = (zone->random.Int(level, maxlevel));
float scaling = (((random_level / (float)level) - 1) * (scalerate / 100.0f));

2446
zone/npc.cpp.orig Normal file

File diff suppressed because it is too large Load Diff

View File

@ -18,20 +18,17 @@
#ifndef NPC_H
#define NPC_H
class NPC;
#include "zonedb.h"
#include "mob.h"
//#include "spawn.h"
#include <list>
#include <deque>
#include "spawn2.h"
#include "../common/loottable.h"
#include "zonedump.h"
#include "qglobals.h"
#include "../common/rulesys.h"
#include "mob.h"
#include "qglobals.h"
#include "zonedb.h"
#include "zonedump.h"
#include <deque>
#include <list>
#ifdef _WINDOWS
#define M_PI 3.141592
#endif
@ -88,8 +85,12 @@ struct AISpellsVar_Struct {
uint8 idle_beneficial_chance;
};
class AA_SwarmPetInfo;
class Client;
class Group;
class Raid;
class Spawn2;
struct Item_Struct;
class NPC : public Mob
{
@ -353,8 +354,9 @@ public:
const bool GetCombatEvent() const { return combat_event; }
void SetCombatEvent(bool b) { combat_event = b; }
//The corpse we make can only be looted by people who got credit for the kill
/* Only allows players that killed corpse to loot */
const bool HasPrivateCorpse() const { return NPCTypedata->private_corpse; }
const bool IsUnderwaterOnly() const { return NPCTypedata->underwater; }
const char* GetRawNPCTypeName() const { return NPCTypedata->name; }

View File

@ -441,8 +441,8 @@ void Object::RandomSpawn(bool send_packet) {
if(!m_ground_spawn)
return;
m_data.x = MakeRandomFloat(m_min_x, m_max_x);
m_data.y = MakeRandomFloat(m_min_y, m_max_y);
m_data.x = zone->random.Real(m_min_x, m_max_x);
m_data.y = zone->random.Real(m_min_y, m_max_y);
respawn_timer.Disable();
if(send_packet) {

View File

@ -1346,7 +1346,7 @@ PathNode* PathManager::FindPathNodeByCoordinates(float x, float y, float z)
int PathManager::GetRandomPathNode()
{
return MakeRandomInt(0, Head.PathNodeCount - 1);
return zone->random.Int(0, Head.PathNodeCount - 1);
}

View File

@ -208,7 +208,7 @@ XS(XS_Corpse_GetDBID)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetDBID();
RETVAL = THIS->GetCorpseDBID();
XSprePUSH; PUSHu((UV)RETVAL);
}
XSRETURN(1);
@ -662,7 +662,7 @@ XS(XS_Corpse_CompleteRezz)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
THIS->CompleteRezz();
THIS->CompleteResurrection();
}
XSRETURN_EMPTY;
}
@ -687,7 +687,7 @@ XS(XS_Corpse_CanMobLoot)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->CanMobLoot(charid);
RETVAL = THIS->CanPlayerLoot(charid);
ST(0) = boolSV(RETVAL);
sv_2mortal(ST(0));
}
@ -723,7 +723,7 @@ XS(XS_Corpse_AllowMobLoot)
if(them == nullptr)
Perl_croak(aTHX_ "them is nullptr, avoiding crash.");
THIS->AllowMobLoot(them, slot);
THIS->AllowPlayerLoot(them, slot);
}
XSRETURN_EMPTY;
}

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