mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 01:11:29 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
a56f17a9e5
@ -1,5 +1,59 @@
|
||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||
-------------------------------------------------------
|
||||
== 12/29/2015 ==
|
||||
Akkadius: Implemented standardized zone controller scripts (Rule Zone, UseZoneController) Defaulted to true
|
||||
- When a zone boots, it will spawn an invisible npc by the name of zone_controller
|
||||
- Lua and Perl scripts can be represented with this npc as zone_controller.pl/lua
|
||||
- This NPC's ID is ruled be define ZONE_CONTROLLER_NPC_ID 10
|
||||
- Two EVENT's uniquely are handled with this NPC/controller (They only work with the zone_controller NPC)
|
||||
- EVENT_SPAWN_ZONE :: All NPC spawns in the zone trigger the controller and pass the following variables:
|
||||
$spawned_entity_id
|
||||
$spawned_npc_id
|
||||
- EVENT_DEATH_ZONE :: All NPC deaths in the zone trigger the controller event and pass the following variables:
|
||||
$killer_id
|
||||
$killer_damage
|
||||
$killer_spell
|
||||
$killer_skill
|
||||
$killed_npc_id
|
||||
|
||||
== 12/28/2015 ==
|
||||
Kinglykrab: Added GetInstanceTimer() to Perl and Lua.
|
||||
- Added GetInstanceTimerByID(instance_id) to Perl and Lua.
|
||||
- Note: If you do not provide an instance id in the method it defaults to instance id 0 and returns 0 for time remaining.
|
||||
- Added UpdateZoneHeader(type, value) to Perl and Lua.
|
||||
- Note: UpdateZoneHeader allows you to manipulate fog color, fog density, and many other zone header settings on the fly in Perl and Lua.
|
||||
|
||||
== 12/21/2015 ==
|
||||
Natedog: Updated item table fields and added a few missing fields for evolving items
|
||||
-DO NOT implement Heirloom items till the inventory code is fixed to allow placing NO DROP
|
||||
items in your shared bank. (but item field located on items table)
|
||||
-NYI - SkillModMax: Max skill point modification from the percent mods. EX:
|
||||
100% 2HSlashing (Max 50) - can only increase 2hslash by 50 MAX! (item field located though)
|
||||
Kinglykrab: Added GetMeleeMitigation() for NPCs and Clients in Perl and Lua.
|
||||
- This allows you to check total item, spell, and AA melee mitigation contribution.
|
||||
|
||||
== 12/19/2015 ==
|
||||
Kinglykrab: Added many methods to Perl and Lua, list below:
|
||||
- SeeInvisible()
|
||||
- SeeInvisibleUndead()
|
||||
- SeeHide()
|
||||
- SeeImprovedHide()
|
||||
- GetNimbusEffect1() - returns first nimbus effect
|
||||
- GetNimbusEffect2() - returns second nimbus effect
|
||||
- GetNimbusEffect3() - returns third nimbus effect
|
||||
- IsTargetable()
|
||||
- HasShieldEquiped()
|
||||
- HasTwoHandBluntEquiped()
|
||||
- HasTwoHanderEquiped()
|
||||
- GetHerosForgeModel() - returns int32 Hero's Forge model
|
||||
- IsEliteMaterialItem() - returns uint32 Hero's Forge Model
|
||||
- GetBaseSize() - returns Mob's base size
|
||||
- HasOwner()
|
||||
- IsPet()
|
||||
- HasPet()
|
||||
- IsSilenced()
|
||||
- IsAmnesiad()
|
||||
|
||||
== 12/16/2015 ==
|
||||
Noudess: Repaired issue with Bind Wounds on someone else. Message was not coming out on client (hold still) and a bind wounds on someone already binding their wounds would interrupt their bind and make them stand. Also removed some duplicate messaging.
|
||||
|
||||
|
||||
@ -24,20 +24,27 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
#include "types.h"
|
||||
|
||||
static const uint32 BIT_Client62 = 1;
|
||||
static const uint32 BIT_Titanium = 2;
|
||||
static const uint32 BIT_SoF = 4;
|
||||
static const uint32 BIT_SoD = 8;
|
||||
static const uint32 BIT_UF = 16;
|
||||
static const uint32 BIT_RoF = 32;
|
||||
static const uint32 BIT_RoF2 = 64;
|
||||
static const uint32 BIT_Client62 = 0x00000001; // 1 (unsupported - placeholder for scripts)
|
||||
|
||||
static const uint32 BIT_Titanium = 0x00000002; // 2
|
||||
static const uint32 BIT_SoF = 0x00000004; // 4
|
||||
static const uint32 BIT_SoD = 0x00000008; // 8
|
||||
static const uint32 BIT_UF = 0x00000010; // 16
|
||||
static const uint32 BIT_RoF = 0x00000020; // 32
|
||||
static const uint32 BIT_RoF2 = 0x00000040; // 64
|
||||
|
||||
static const uint32 BIT_TitaniumAndEarlier = 0x00000003; // 3
|
||||
static const uint32 BIT_SoFAndEarlier = 0x00000007; // 7
|
||||
static const uint32 BIT_SoDAndEarlier = 0x0000000F; // 15
|
||||
static const uint32 BIT_UFAndEarlier = 0x0000001F; // 31
|
||||
static const uint32 BIT_RoFAndEarlier = 0x0000003F; // 63
|
||||
|
||||
static const uint32 BIT_SoFAndLater = 0xFFFFFFFC; // 4294967292
|
||||
static const uint32 BIT_SoDAndLater = 0xFFFFFFF8; // 4294967288
|
||||
static const uint32 BIT_UFAndLater = 0xFFFFFFF0; // 4294967280
|
||||
static const uint32 BIT_RoFAndLater = 0xFFFFFFE0; // 4294967264
|
||||
static const uint32 BIT_RoF2AndLater = 0xFFFFFFC0; // 4294967232
|
||||
|
||||
static const uint32 BIT_TitaniumAndEarlier = 0x00000003;
|
||||
static const uint32 BIT_SoFAndLater = 0xFFFFFFFC;
|
||||
static const uint32 BIT_SoDAndLater = 0xFFFFFFF8;
|
||||
static const uint32 BIT_UFAndLater = 0xFFFFFFF0;
|
||||
static const uint32 BIT_RoFAndLater = 0xFFFFFFE0;
|
||||
static const uint32 BIT_RoF2AndLater = 0xFFFFFFC0;
|
||||
static const uint32 BIT_AllClients = 0xFFFFFFFF;
|
||||
|
||||
enum class ClientVersion
|
||||
|
||||
@ -1183,21 +1183,16 @@ bool Database::CheckNameFilter(const char* name, bool surname)
|
||||
{
|
||||
std::string str_name = name;
|
||||
|
||||
if(surname)
|
||||
// the minimum 4 is enforced by the client too
|
||||
if (!name || strlen(name) < 4)
|
||||
{
|
||||
// the minimum 4 is enforced by the client too
|
||||
if(!name || strlen(name) < 3)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
|
||||
// Given name length is enforced by the client too
|
||||
if (!surname && strlen(name) > 15)
|
||||
{
|
||||
// the minimum 4 is enforced by the client too
|
||||
if(!name || strlen(name) < 4 || strlen(name) > 15)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < str_name.size(); i++)
|
||||
@ -1564,7 +1559,7 @@ void Database::AddReport(std::string who, std::string against, std::string lines
|
||||
char *escape_str = new char[lines.size()*2+1];
|
||||
DoEscapeString(escape_str, lines.c_str(), lines.size());
|
||||
|
||||
std::string query = StringFormat("INSERT INTO reports (name, reported, reported_text) VALUES('%s', '%s', '%s')", who.c_str(), against.c_str(), escape_str);
|
||||
std::string query = StringFormat("INSERT INTO reports (name, reported, reported_text) VALUES('%s', '%s', '%s')", EscapeString(who).c_str(), EscapeString(against).c_str(), escape_str);
|
||||
QueryDatabase(query);
|
||||
safe_delete_array(escape_str);
|
||||
}
|
||||
@ -2182,3 +2177,42 @@ void Database::ClearInvSnapshots(bool use_rule)
|
||||
std::string query = StringFormat("DELETE FROM inventory_snapshots WHERE time_index <= %lu", (unsigned long)del_time);
|
||||
QueryDatabase(query);
|
||||
}
|
||||
|
||||
struct TimeOfDay_Struct Database::LoadTime(time_t &realtime)
|
||||
{
|
||||
|
||||
TimeOfDay_Struct eqTime;
|
||||
std::string query = StringFormat("SELECT minute,hour,day,month,year,realtime FROM eqtime limit 1");
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
if (!results.Success() || results.RowCount() == 0)
|
||||
{
|
||||
Log.Out(Logs::Detail, Logs::World_Server, "Loading EQ time of day failed. Using defaults.");
|
||||
eqTime.minute = 0;
|
||||
eqTime.hour = 9;
|
||||
eqTime.day = 1;
|
||||
eqTime.month = 1;
|
||||
eqTime.year = 3100;
|
||||
realtime = time(0);
|
||||
}
|
||||
|
||||
auto row = results.begin();
|
||||
|
||||
eqTime.minute = atoi(row[0]);
|
||||
eqTime.hour = atoi(row[1]);
|
||||
eqTime.day = atoi(row[2]);
|
||||
eqTime.month = atoi(row[3]);
|
||||
eqTime.year = atoi(row[4]);
|
||||
realtime = atoi(row[5]);
|
||||
|
||||
return eqTime;
|
||||
}
|
||||
|
||||
bool Database::SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year)
|
||||
{
|
||||
std::string query = StringFormat("UPDATE eqtime set minute = %d, hour = %d, day = %d, month = %d, year = %d, realtime = %d limit 1", minute, hour, day, month, year, time(0));
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
return results.Success();
|
||||
|
||||
}
|
||||
@ -241,6 +241,8 @@ public:
|
||||
uint8 GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 in_level);
|
||||
|
||||
void AddReport(std::string who, std::string against, std::string lines);
|
||||
struct TimeOfDay_Struct LoadTime(time_t &realtime);
|
||||
bool SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year);
|
||||
void ClearMerchantTemp();
|
||||
void ClearPTimers(uint32 charid);
|
||||
void SetFirstLogon(uint32 CharID, uint8 firstlogon);
|
||||
|
||||
@ -493,7 +493,7 @@ bool Database::CheckDatabaseConversions() {
|
||||
/* 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 eqemu_update.pl V 13");
|
||||
system("perl eqemu_update.pl V 14");
|
||||
|
||||
/* Run Automatic Database Upgrade Script */
|
||||
system("perl eqemu_update.pl ran_from_world");
|
||||
|
||||
@ -254,10 +254,6 @@ void EQEmuConfig::do_files(TiXmlElement *ele)
|
||||
if (text) {
|
||||
OpCodesFile = text;
|
||||
}
|
||||
text = ParseTextBlock(ele, "eqtime", true);
|
||||
if (text) {
|
||||
EQTimeFile = text;
|
||||
}
|
||||
}
|
||||
|
||||
void EQEmuConfig::do_directories(TiXmlElement *ele)
|
||||
@ -408,9 +404,6 @@ std::string EQEmuConfig::GetByName(const std::string &var_name) const
|
||||
if (var_name == "OpCodesFile") {
|
||||
return (OpCodesFile);
|
||||
}
|
||||
if (var_name == "EQTimeFile") {
|
||||
return (EQTimeFile);
|
||||
}
|
||||
if (var_name == "MapDir") {
|
||||
return (MapDir);
|
||||
}
|
||||
@ -475,7 +468,6 @@ void EQEmuConfig::Dump() const
|
||||
std::cout << "QSDatabasePort = " << QSDatabasePort << std::endl;
|
||||
std::cout << "SpellsFile = " << SpellsFile << std::endl;
|
||||
std::cout << "OpCodesFile = " << OpCodesFile << std::endl;
|
||||
std::cout << "EQTimeFile = " << EQTimeFile << std::endl;
|
||||
std::cout << "MapDir = " << MapDir << std::endl;
|
||||
std::cout << "QuestDir = " << QuestDir << std::endl;
|
||||
std::cout << "PluginDir = " << PluginDir << std::endl;
|
||||
|
||||
@ -79,7 +79,6 @@ class EQEmuConfig : public XMLParser
|
||||
// From <files/>
|
||||
std::string SpellsFile;
|
||||
std::string OpCodesFile;
|
||||
std::string EQTimeFile;
|
||||
|
||||
// From <directories/>
|
||||
std::string MapDir;
|
||||
@ -154,7 +153,6 @@ class EQEmuConfig : public XMLParser
|
||||
// Files
|
||||
SpellsFile = "spells_us.txt";
|
||||
OpCodesFile = "opcodes.conf";
|
||||
EQTimeFile = "eqtime.cfg";
|
||||
// Dirs
|
||||
MapDir = "Maps";
|
||||
QuestDir = "quests";
|
||||
|
||||
@ -133,72 +133,6 @@ int EQTime::SetCurrentEQTimeOfDay(TimeOfDay_Struct start_eq, time_t start_real)
|
||||
return 1;
|
||||
}
|
||||
|
||||
//saveFile and loadFile need to use long for the save datatype...
|
||||
//For some reason, ifstream/ofstream have problems with EQEmu datatypes in files.
|
||||
bool EQTime::saveFile(const char *filename)
|
||||
{
|
||||
std::ofstream of;
|
||||
of.open(filename);
|
||||
if (!of)
|
||||
{
|
||||
Log.Out(Logs::General, Logs::Error, "EQTime::saveFile failed: Unable to open file '%s'", filename);
|
||||
return false;
|
||||
}
|
||||
//Enable for debugging
|
||||
of << EQT_VERSION << std::endl;
|
||||
of << (long)eqTime.start_eqtime.day << std::endl;
|
||||
of << (long)eqTime.start_eqtime.hour << std::endl;
|
||||
of << (long)eqTime.start_eqtime.minute << std::endl;
|
||||
of << (long)eqTime.start_eqtime.month << std::endl;
|
||||
of << eqTime.start_eqtime.year << std::endl;
|
||||
of << eqTime.start_realtime << std::endl;
|
||||
of.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EQTime::loadFile(const char *filename)
|
||||
{
|
||||
int version=0;
|
||||
long in_data=0;
|
||||
std::ifstream in;
|
||||
in.open(filename);
|
||||
if(!in)
|
||||
{
|
||||
Log.Out(Logs::General, Logs::Error, "Could not load EQTime file %s", filename);
|
||||
return false;
|
||||
}
|
||||
in >> version;
|
||||
in.ignore(80, '\n');
|
||||
if(version != EQT_VERSION)
|
||||
{
|
||||
Log.Out(Logs::General, Logs::Error, "'%s' is NOT a valid EQTime file. File version is %i, EQTime version is %i", filename, version, EQT_VERSION);
|
||||
return false;
|
||||
}
|
||||
//in >> eqTime.start_eqtime.day;
|
||||
in >> in_data;
|
||||
in.ignore(80, '\n');
|
||||
eqTime.start_eqtime.day = in_data;
|
||||
//in >> eqTime.start_eqtime.hour;
|
||||
in >> in_data;
|
||||
eqTime.start_eqtime.hour = in_data;
|
||||
in.ignore(80, '\n');
|
||||
//in >> eqTime.start_eqtime.minute;
|
||||
in >> in_data;
|
||||
in.ignore(80, '\n');
|
||||
eqTime.start_eqtime.minute = in_data;
|
||||
//in >> eqTime.start_eqtime.month;
|
||||
in >> in_data;
|
||||
in.ignore(80, '\n');
|
||||
eqTime.start_eqtime.month = in_data;
|
||||
in >> eqTime.start_eqtime.year;
|
||||
in.ignore(80, '\n');
|
||||
in >> eqTime.start_realtime;
|
||||
//Enable for debugging...
|
||||
in.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool EQTime::IsTimeBefore(TimeOfDay_Struct *base, TimeOfDay_Struct *test) {
|
||||
if (base->year > test->year)
|
||||
return(true);
|
||||
|
||||
@ -39,12 +39,6 @@ public:
|
||||
|
||||
static void ToString(TimeOfDay_Struct *t, std::string &str);
|
||||
|
||||
//Database functions
|
||||
//bool loadDB(Database q);
|
||||
//bool setDB(Database q);
|
||||
bool loadFile(const char *filename);
|
||||
bool saveFile(const char *filename);
|
||||
|
||||
private:
|
||||
//This is our reference clock.
|
||||
eqTimeOfDay eqTime;
|
||||
|
||||
@ -233,6 +233,8 @@ enum { //some random constants
|
||||
#define GROUP_EXP_PER_POINT 1000
|
||||
#define RAID_EXP_PER_POINT 2000
|
||||
|
||||
#define ZONE_CONTROLLER_NPC_ID 10
|
||||
|
||||
//Some hard coded statuses from commands and other places:
|
||||
enum {
|
||||
minStatusToBeGM = 40,
|
||||
|
||||
@ -41,6 +41,7 @@ F(ac)
|
||||
F(deity)
|
||||
F(skillmodvalue)
|
||||
F(UNK033)
|
||||
F(skillmodmax)
|
||||
F(skillmodtype)
|
||||
F(banedmgrace)
|
||||
F(banedmgamt)
|
||||
@ -172,7 +173,10 @@ F(bardlevel)
|
||||
F(questitemflag)
|
||||
F(svcorruption)
|
||||
F(purity)
|
||||
F(evoitem)
|
||||
F(evoid)
|
||||
F(evolvinglevel)
|
||||
F(evomax)
|
||||
F(backstabdmg)
|
||||
F(dsmitigation)
|
||||
F(heroic_str)
|
||||
|
||||
@ -130,6 +130,7 @@ struct Item_Struct {
|
||||
uint32 Deity; // Bitmask of Deities that can equip this item
|
||||
//uint32 Unk033
|
||||
int32 SkillModValue; // % Mod to skill specified in SkillModType
|
||||
int32 SkillModMax; // Max skill point modification
|
||||
uint32 SkillModType; // Type of skill for SkillModValue to apply to
|
||||
uint32 BaneDmgRace; // Bane Damage Race
|
||||
int8 BaneDmgAmt; // Bane Damage Body Amount
|
||||
@ -218,7 +219,10 @@ struct Item_Struct {
|
||||
// Begin SoF Fields
|
||||
int32 SVCorruption;
|
||||
uint32 Purity;
|
||||
uint8 EvolvingItem;
|
||||
uint32 EvolvingID;
|
||||
uint8 EvolvingLevel;
|
||||
uint8 EvolvingMax;
|
||||
uint32 BackstabDmg;
|
||||
uint32 DSMitigation;
|
||||
int32 HeroicStr;
|
||||
|
||||
@ -5231,19 +5231,19 @@ namespace RoF
|
||||
hdr.unknown044 = 0;
|
||||
hdr.unknown048 = 0;
|
||||
hdr.unknown052 = 0;
|
||||
hdr.isEvolving = item->EvolvingLevel > 0 ? 1 : 0;
|
||||
hdr.isEvolving = item->EvolvingItem;
|
||||
ss.write((const char*)&hdr, sizeof(RoF::structs::ItemSerializationHeader));
|
||||
|
||||
if (item->EvolvingLevel > 0) {
|
||||
if (item->EvolvingItem > 0) {
|
||||
RoF::structs::EvolvingItem evotop;
|
||||
evotop.unknown001 = 0;
|
||||
evotop.unknown002 = 0;
|
||||
evotop.unknown003 = 0;
|
||||
evotop.unknown004 = 0;
|
||||
evotop.evoLevel = item->EvolvingLevel;
|
||||
evotop.progress = 95.512;
|
||||
evotop.progress = 0;
|
||||
evotop.Activated = 1;
|
||||
evotop.evomaxlevel = 7;
|
||||
evotop.evomaxlevel = item->EvolvingMax;
|
||||
ss.write((const char*)&evotop, sizeof(RoF::structs::EvolvingItem));
|
||||
}
|
||||
//ORNAMENT IDFILE / ICON
|
||||
@ -5353,7 +5353,7 @@ namespace RoF
|
||||
ibs.Races = item->Races;
|
||||
ibs.Deity = item->Deity;
|
||||
ibs.SkillModValue = item->SkillModValue;
|
||||
ibs.SkillModMax = 0xffffffff;
|
||||
ibs.SkillModMax = item->SkillModMax;
|
||||
ibs.SkillModType = (int8)(item->SkillModType);
|
||||
ibs.SkillModExtra = 0;
|
||||
ibs.BaneDmgRace = item->BaneDmgRace;
|
||||
|
||||
@ -5432,19 +5432,19 @@ namespace RoF2
|
||||
hdr.unknown044 = 0;
|
||||
hdr.unknown048 = 0;
|
||||
hdr.unknown052 = 0;
|
||||
hdr.isEvolving = item->EvolvingLevel > 0 ? 1 : 0;
|
||||
hdr.isEvolving = item->EvolvingItem;
|
||||
ss.write((const char*)&hdr, sizeof(RoF2::structs::ItemSerializationHeader));
|
||||
|
||||
if (item->EvolvingLevel > 0) {
|
||||
if (item->EvolvingItem > 0) {
|
||||
RoF2::structs::EvolvingItem evotop;
|
||||
evotop.unknown001 = 0;
|
||||
evotop.unknown002 = 0;
|
||||
evotop.unknown003 = 0;
|
||||
evotop.unknown004 = 0;
|
||||
evotop.evoLevel = item->EvolvingLevel;
|
||||
evotop.progress = 95.512;
|
||||
evotop.progress = 0;
|
||||
evotop.Activated = 1;
|
||||
evotop.evomaxlevel = 7;
|
||||
evotop.evomaxlevel = item->EvolvingMax;
|
||||
ss.write((const char*)&evotop, sizeof(RoF2::structs::EvolvingItem));
|
||||
}
|
||||
//ORNAMENT IDFILE / ICON
|
||||
@ -5554,7 +5554,7 @@ namespace RoF2
|
||||
ibs.Races = item->Races;
|
||||
ibs.Deity = item->Deity;
|
||||
ibs.SkillModValue = item->SkillModValue;
|
||||
ibs.SkillModMax = 0xffffffff;
|
||||
ibs.SkillModMax = item->SkillModMax;
|
||||
ibs.SkillModType = (int8)(item->SkillModType);
|
||||
ibs.SkillModExtra = 0;
|
||||
ibs.BaneDmgRace = item->BaneDmgRace;
|
||||
|
||||
@ -3835,19 +3835,19 @@ namespace UF
|
||||
hdr.unknown044 = 0;
|
||||
hdr.unknown048 = 0;
|
||||
hdr.unknown052 = 0;
|
||||
hdr.isEvolving = item->EvolvingLevel > 0 ? 1 : 0;
|
||||
hdr.isEvolving = item->EvolvingItem;
|
||||
ss.write((const char*)&hdr, sizeof(UF::structs::ItemSerializationHeader));
|
||||
|
||||
if (item->EvolvingLevel > 0) {
|
||||
if (item->EvolvingItem > 0) {
|
||||
UF::structs::EvolvingItem evotop;
|
||||
evotop.unknown001 = 0;
|
||||
evotop.unknown002 = 0;
|
||||
evotop.unknown003 = 0;
|
||||
evotop.unknown004 = 0;
|
||||
evotop.evoLevel = item->EvolvingLevel;
|
||||
evotop.progress = 95.512;
|
||||
evotop.progress = 0;
|
||||
evotop.Activated = 1;
|
||||
evotop.evomaxlevel = 7;
|
||||
evotop.evomaxlevel = item->EvolvingMax;
|
||||
ss.write((const char*)&evotop, sizeof(UF::structs::EvolvingItem));
|
||||
}
|
||||
//ORNAMENT IDFILE / ICON -
|
||||
@ -3947,7 +3947,7 @@ namespace UF
|
||||
ibs.Races = item->Races;
|
||||
ibs.Deity = item->Deity;
|
||||
ibs.SkillModValue = item->SkillModValue;
|
||||
ibs.unknown5 = 0;
|
||||
ibs.SkillModMax = item->SkillModMax;
|
||||
ibs.SkillModType = item->SkillModType;
|
||||
ibs.BaneDmgRace = item->BaneDmgRace;
|
||||
ibs.BaneDmgBody = item->BaneDmgBody;
|
||||
|
||||
@ -4103,7 +4103,7 @@ struct ItemBodyStruct
|
||||
uint32 Races;
|
||||
uint32 Deity;
|
||||
int32 SkillModValue;
|
||||
uint32 unknown5;
|
||||
uint32 SkillModMax;
|
||||
uint32 SkillModType;
|
||||
uint32 BaneDmgRace;
|
||||
uint32 BaneDmgBody;
|
||||
|
||||
@ -236,7 +236,7 @@ void RuleManager::SaveRules(Database *database, const char *ruleset_name) {
|
||||
}
|
||||
|
||||
bool RuleManager::LoadRules(Database *database, const char *ruleset_name) {
|
||||
|
||||
|
||||
int ruleset_id = GetRulesetID(database, ruleset_name);
|
||||
if (ruleset_id < 0) {
|
||||
Log.Out(Logs::Detail, Logs::Rules, "Failed to find ruleset '%s' for load operation. Canceling.", ruleset_name);
|
||||
@ -248,6 +248,26 @@ bool RuleManager::LoadRules(Database *database, const char *ruleset_name) {
|
||||
m_activeRuleset = ruleset_id;
|
||||
m_activeName = ruleset_name;
|
||||
|
||||
/* Load default ruleset values first if we're loading something other than default */
|
||||
if (strcasecmp(ruleset_name, "default") != 0){
|
||||
std::string default_ruleset_name = "default";
|
||||
int default_ruleset_id = GetRulesetID(database, default_ruleset_name.c_str());
|
||||
if (default_ruleset_id < 0) {
|
||||
Log.Out(Logs::Detail, Logs::Rules, "Failed to find default ruleset '%s' for load operation. Canceling.", default_ruleset_name.c_str());
|
||||
return(false);
|
||||
}
|
||||
Log.Out(Logs::Detail, Logs::Rules, "Loading rule set '%s' (%d)", default_ruleset_name.c_str(), default_ruleset_id);
|
||||
|
||||
std::string query = StringFormat("SELECT rule_name, rule_value FROM rule_values WHERE ruleset_id = %d", default_ruleset_id);
|
||||
auto results = database->QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return false;
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row)
|
||||
if (!SetRule(row[0], row[1], nullptr, false))
|
||||
Log.Out(Logs::Detail, Logs::Rules, "Unable to interpret rule record for %s", row[0]);
|
||||
}
|
||||
|
||||
std::string query = StringFormat("SELECT rule_name, rule_value FROM rule_values WHERE ruleset_id=%d", ruleset_id);
|
||||
auto results = database->QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
|
||||
@ -233,6 +233,7 @@ RULE_BOOL(Zone, LevelBasedEXPMods, false) // Allows you to use the level_exp_mod
|
||||
RULE_INT(Zone, WeatherTimer, 600) // Weather timer when no duration is available
|
||||
RULE_BOOL(Zone, EnableLoggedOffReplenishments, true)
|
||||
RULE_INT(Zone, MinOfflineTimeToReplenishments, 21600) // 21600 seconds is 6 Hours
|
||||
RULE_BOOL(Zone, UseZoneController, true) // Enables the ability to use persistent quest based zone controllers (zone_controller.pl/lua)
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Map)
|
||||
@ -459,6 +460,8 @@ RULE_BOOL(Combat, ProjectileDmgOnImpact, true) //If enabled, projectiles (ie arr
|
||||
RULE_BOOL(Combat, MeleePush, true) // enable melee push
|
||||
RULE_INT(Combat, MeleePushChance, 50) // (NPCs) chance the target will be pushed. Made up, 100 actually isn't that bad
|
||||
RULE_BOOL(Combat, UseLiveCombatRounds, true) // turn this false if you don't want to worry about fixing up combat rounds for NPCs
|
||||
RULE_INT(Combat, NPCAssistCap, 5) // Maxiumium number of NPCs that will assist another NPC at once
|
||||
RULE_INT(Combat, NPCAssistCapTimer, 6000) // Time in milliseconds a NPC will take to clear assist aggro cap space
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(NPC)
|
||||
@ -494,6 +497,7 @@ RULE_INT(Aggro, PetSpellAggroMod, 10)
|
||||
RULE_REAL(Aggro, TunnelVisionAggroMod, 0.75) //people not currently the top hate generate this much hate on a Tunnel Vision mob
|
||||
RULE_INT(Aggro, MaxScalingProcAggro, 400) // Set to -1 for no limit. Maxmimum amount of aggro that HP scaling SPA effect in a proc will add.
|
||||
RULE_INT(Aggro, IntAggroThreshold, 75) // Int <= this will aggro regardless of level difference.
|
||||
RULE_BOOL(Aggro, AllowTickPulling, false) // tick pulling is an exploit in an NPC's call for help fixed sometime in 2006 on live
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(TaskSystem)
|
||||
|
||||
@ -1,6 +1,10 @@
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1800
|
||||
#include <algorithm>
|
||||
#endif
|
||||
|
||||
#include "classes.h"
|
||||
#include "eq_packet_structs.h"
|
||||
#include "eqemu_exception.h"
|
||||
@ -802,36 +806,37 @@ bool SharedDatabase::LoadItems(const std::string &prefix) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_item_id) {
|
||||
EQEmu::FixedMemoryHashSet<Item_Struct> hash(reinterpret_cast<uint8*>(data), size, items, max_item_id);
|
||||
void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_item_id)
|
||||
{
|
||||
EQEmu::FixedMemoryHashSet<Item_Struct> hash(reinterpret_cast<uint8 *>(data), size, items, max_item_id);
|
||||
|
||||
char ndbuffer[4];
|
||||
bool disableNoRent = false;
|
||||
if(GetVariable("disablenorent", ndbuffer, 4)) {
|
||||
if(ndbuffer[0] == '1' && ndbuffer[1] == '\0') {
|
||||
if (GetVariable("disablenorent", ndbuffer, 4)) {
|
||||
if (ndbuffer[0] == '1' && ndbuffer[1] == '\0') {
|
||||
disableNoRent = true;
|
||||
}
|
||||
}
|
||||
bool disableNoDrop = false;
|
||||
if(GetVariable("disablenodrop", ndbuffer, 4)) {
|
||||
if(ndbuffer[0] == '1' && ndbuffer[1] == '\0') {
|
||||
if (GetVariable("disablenodrop", ndbuffer, 4)) {
|
||||
if (ndbuffer[0] == '1' && ndbuffer[1] == '\0') {
|
||||
disableNoDrop = true;
|
||||
}
|
||||
}
|
||||
bool disableLoreGroup = false;
|
||||
if(GetVariable("disablelore", ndbuffer, 4)) {
|
||||
if(ndbuffer[0] == '1' && ndbuffer[1] == '\0') {
|
||||
if (GetVariable("disablelore", ndbuffer, 4)) {
|
||||
if (ndbuffer[0] == '1' && ndbuffer[1] == '\0') {
|
||||
disableLoreGroup = true;
|
||||
}
|
||||
}
|
||||
bool disableNoTransfer = false;
|
||||
if(GetVariable("disablenotransfer", ndbuffer, 4)) {
|
||||
if(ndbuffer[0] == '1' && ndbuffer[1] == '\0') {
|
||||
if (GetVariable("disablenotransfer", ndbuffer, 4)) {
|
||||
if (ndbuffer[0] == '1' && ndbuffer[1] == '\0') {
|
||||
disableNoTransfer = true;
|
||||
}
|
||||
}
|
||||
|
||||
Item_Struct item;
|
||||
Item_Struct item;
|
||||
|
||||
const std::string query = "SELECT source,"
|
||||
#define F(x) "`"#x"`,"
|
||||
@ -839,224 +844,226 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_
|
||||
#undef F
|
||||
"updated FROM items ORDER BY id";
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return;
|
||||
}
|
||||
if (!results.Success()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for(auto row = results.begin(); row != results.end(); ++row) {
|
||||
memset(&item, 0, sizeof(Item_Struct));
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
memset(&item, 0, sizeof(Item_Struct));
|
||||
|
||||
item.ItemClass = (uint8)atoi(row[ItemField::itemclass]);
|
||||
strcpy(item.Name,row[ItemField::name]);
|
||||
strcpy(item.Lore,row[ItemField::lore]);
|
||||
strcpy(item.IDFile,row[ItemField::idfile]);
|
||||
item.ItemClass = (uint8)atoi(row[ItemField::itemclass]);
|
||||
strcpy(item.Name, row[ItemField::name]);
|
||||
strcpy(item.Lore, row[ItemField::lore]);
|
||||
strcpy(item.IDFile, row[ItemField::idfile]);
|
||||
|
||||
item.ID = (uint32)atoul(row[ItemField::id]);
|
||||
item.Weight = (uint8)atoi(row[ItemField::weight]);
|
||||
item.NoRent = disableNoRent ? (uint8)atoi("255") : (uint8)atoi(row[ItemField::norent]);
|
||||
item.NoDrop = disableNoDrop ? (uint8)atoi("255") : (uint8)atoi(row[ItemField::nodrop]);
|
||||
item.Size = (uint8)atoi(row[ItemField::size]);
|
||||
item.Slots = (uint32)atoul(row[ItemField::slots]);
|
||||
item.Price = (uint32)atoul(row[ItemField::price]);
|
||||
item.Icon = (uint32)atoul(row[ItemField::icon]);
|
||||
item.BenefitFlag = (atoul(row[ItemField::benefitflag]) != 0);
|
||||
item.Tradeskills = (atoi(row[ItemField::tradeskills])==0) ? false : true;
|
||||
item.CR = (int8)atoi(row[ItemField::cr]);
|
||||
item.DR = (int8)atoi(row[ItemField::dr]);
|
||||
item.PR = (int8)atoi(row[ItemField::pr]);
|
||||
item.MR = (int8)atoi(row[ItemField::mr]);
|
||||
item.FR = (int8)atoi(row[ItemField::fr]);
|
||||
item.AStr = (int8)atoi(row[ItemField::astr]);
|
||||
item.ASta = (int8)atoi(row[ItemField::asta]);
|
||||
item.AAgi = (int8)atoi(row[ItemField::aagi]);
|
||||
item.ADex = (int8)atoi(row[ItemField::adex]);
|
||||
item.ACha = (int8)atoi(row[ItemField::acha]);
|
||||
item.AInt = (int8)atoi(row[ItemField::aint]);
|
||||
item.AWis = (int8)atoi(row[ItemField::awis]);
|
||||
item.HP = (int32)atoul(row[ItemField::hp]);
|
||||
item.Mana = (int32)atoul(row[ItemField::mana]);
|
||||
item.AC = (int32)atoul(row[ItemField::ac]);
|
||||
item.Deity = (uint32)atoul(row[ItemField::deity]);
|
||||
item.SkillModValue = (int32)atoul(row[ItemField::skillmodvalue]);
|
||||
item.ID = (uint32)atoul(row[ItemField::id]);
|
||||
item.Weight = (uint8)atoi(row[ItemField::weight]);
|
||||
item.NoRent = disableNoRent ? (uint8)atoi("255") : (uint8)atoi(row[ItemField::norent]);
|
||||
item.NoDrop = disableNoDrop ? (uint8)atoi("255") : (uint8)atoi(row[ItemField::nodrop]);
|
||||
item.Size = (uint8)atoi(row[ItemField::size]);
|
||||
item.Slots = (uint32)atoul(row[ItemField::slots]);
|
||||
item.Price = (uint32)atoul(row[ItemField::price]);
|
||||
item.Icon = (uint32)atoul(row[ItemField::icon]);
|
||||
item.BenefitFlag = (atoul(row[ItemField::benefitflag]) != 0);
|
||||
item.Tradeskills = (atoi(row[ItemField::tradeskills]) == 0) ? false : true;
|
||||
item.CR = (int8)atoi(row[ItemField::cr]);
|
||||
item.DR = (int8)atoi(row[ItemField::dr]);
|
||||
item.PR = (int8)atoi(row[ItemField::pr]);
|
||||
item.MR = (int8)atoi(row[ItemField::mr]);
|
||||
item.FR = (int8)atoi(row[ItemField::fr]);
|
||||
item.AStr = (int8)atoi(row[ItemField::astr]);
|
||||
item.ASta = (int8)atoi(row[ItemField::asta]);
|
||||
item.AAgi = (int8)atoi(row[ItemField::aagi]);
|
||||
item.ADex = (int8)atoi(row[ItemField::adex]);
|
||||
item.ACha = (int8)atoi(row[ItemField::acha]);
|
||||
item.AInt = (int8)atoi(row[ItemField::aint]);
|
||||
item.AWis = (int8)atoi(row[ItemField::awis]);
|
||||
item.HP = (int32)atoul(row[ItemField::hp]);
|
||||
item.Mana = (int32)atoul(row[ItemField::mana]);
|
||||
item.AC = (int32)atoul(row[ItemField::ac]);
|
||||
item.Deity = (uint32)atoul(row[ItemField::deity]);
|
||||
item.SkillModValue = (int32)atoul(row[ItemField::skillmodvalue]);
|
||||
item.SkillModMax = (int32)atoul(row[ItemField::skillmodmax]);
|
||||
item.SkillModType = (uint32)atoul(row[ItemField::skillmodtype]);
|
||||
item.BaneDmgRace = (uint32)atoul(row[ItemField::banedmgrace]);
|
||||
item.BaneDmgAmt = (int8)atoi(row[ItemField::banedmgamt]);
|
||||
item.BaneDmgBody = (uint32)atoul(row[ItemField::banedmgbody]);
|
||||
item.Magic = (atoi(row[ItemField::magic]) == 0) ? false : true;
|
||||
item.CastTime_ = (int32)atoul(row[ItemField::casttime_]);
|
||||
item.ReqLevel = (uint8)atoi(row[ItemField::reqlevel]);
|
||||
item.BardType = (uint32)atoul(row[ItemField::bardtype]);
|
||||
item.BardValue = (int32)atoul(row[ItemField::bardvalue]);
|
||||
item.Light = (int8)atoi(row[ItemField::light]);
|
||||
item.Delay = (uint8)atoi(row[ItemField::delay]);
|
||||
item.RecLevel = (uint8)atoi(row[ItemField::reclevel]);
|
||||
item.RecSkill = (uint8)atoi(row[ItemField::recskill]);
|
||||
item.ElemDmgType = (uint8)atoi(row[ItemField::elemdmgtype]);
|
||||
item.ElemDmgAmt = (uint8)atoi(row[ItemField::elemdmgamt]);
|
||||
item.Range = (uint8)atoi(row[ItemField::range]);
|
||||
item.Damage = (uint32)atoi(row[ItemField::damage]);
|
||||
item.Color = (uint32)atoul(row[ItemField::color]);
|
||||
item.Classes = (uint32)atoul(row[ItemField::classes]);
|
||||
item.Races = (uint32)atoul(row[ItemField::races]);
|
||||
|
||||
item.SkillModType = (uint32)atoul(row[ItemField::skillmodtype]);
|
||||
item.BaneDmgRace = (uint32)atoul(row[ItemField::banedmgrace]);
|
||||
item.BaneDmgAmt = (int8)atoi(row[ItemField::banedmgamt]);
|
||||
item.BaneDmgBody = (uint32)atoul(row[ItemField::banedmgbody]);
|
||||
item.Magic = (atoi(row[ItemField::magic])==0) ? false : true;
|
||||
item.CastTime_ = (int32)atoul(row[ItemField::casttime_]);
|
||||
item.ReqLevel = (uint8)atoi(row[ItemField::reqlevel]);
|
||||
item.BardType = (uint32)atoul(row[ItemField::bardtype]);
|
||||
item.BardValue = (int32)atoul(row[ItemField::bardvalue]);
|
||||
item.Light = (int8)atoi(row[ItemField::light]);
|
||||
item.Delay = (uint8)atoi(row[ItemField::delay]);
|
||||
item.RecLevel = (uint8)atoi(row[ItemField::reclevel]);
|
||||
item.RecSkill = (uint8)atoi(row[ItemField::recskill]);
|
||||
item.ElemDmgType = (uint8)atoi(row[ItemField::elemdmgtype]);
|
||||
item.ElemDmgAmt = (uint8)atoi(row[ItemField::elemdmgamt]);
|
||||
item.Range = (uint8)atoi(row[ItemField::range]);
|
||||
item.Damage = (uint32)atoi(row[ItemField::damage]);
|
||||
item.Color = (uint32)atoul(row[ItemField::color]);
|
||||
item.Classes = (uint32)atoul(row[ItemField::classes]);
|
||||
item.Races = (uint32)atoul(row[ItemField::races]);
|
||||
|
||||
item.MaxCharges = (int16)atoi(row[ItemField::maxcharges]);
|
||||
item.ItemType = (uint8)atoi(row[ItemField::itemtype]);
|
||||
item.MaxCharges = (int16)atoi(row[ItemField::maxcharges]);
|
||||
item.ItemType = (uint8)atoi(row[ItemField::itemtype]);
|
||||
item.Material = (uint8)atoi(row[ItemField::material]);
|
||||
item.HerosForgeModel = (uint32)atoi(row[ItemField::herosforgemodel]);
|
||||
item.SellRate = (float)atof(row[ItemField::sellrate]);
|
||||
item.CastTime = (uint32)atoul(row[ItemField::casttime]);
|
||||
item.EliteMaterial = (uint32)atoul(row[ItemField::elitematerial]);
|
||||
item.ProcRate = (int32)atoi(row[ItemField::procrate]);
|
||||
item.CombatEffects = (int8)atoi(row[ItemField::combateffects]);
|
||||
item.Shielding = (int8)atoi(row[ItemField::shielding]);
|
||||
item.StunResist = (int8)atoi(row[ItemField::stunresist]);
|
||||
item.StrikeThrough = (int8)atoi(row[ItemField::strikethrough]);
|
||||
item.ExtraDmgSkill = (uint32)atoul(row[ItemField::extradmgskill]);
|
||||
item.ExtraDmgAmt = (uint32)atoul(row[ItemField::extradmgamt]);
|
||||
item.SpellShield = (int8)atoi(row[ItemField::spellshield]);
|
||||
item.Avoidance = (int8)atoi(row[ItemField::avoidance]);
|
||||
item.Accuracy = (int8)atoi(row[ItemField::accuracy]);
|
||||
item.CharmFileID = (uint32)atoul(row[ItemField::charmfileid]);
|
||||
item.FactionMod1 = (int32)atoul(row[ItemField::factionmod1]);
|
||||
item.FactionMod2 = (int32)atoul(row[ItemField::factionmod2]);
|
||||
item.FactionMod3 = (int32)atoul(row[ItemField::factionmod3]);
|
||||
item.FactionMod4 = (int32)atoul(row[ItemField::factionmod4]);
|
||||
item.FactionAmt1 = (int32)atoul(row[ItemField::factionamt1]);
|
||||
item.FactionAmt2 = (int32)atoul(row[ItemField::factionamt2]);
|
||||
item.FactionAmt3 = (int32)atoul(row[ItemField::factionamt3]);
|
||||
item.FactionAmt4 = (int32)atoul(row[ItemField::factionamt4]);
|
||||
item.SellRate = (float)atof(row[ItemField::sellrate]);
|
||||
item.CastTime = (uint32)atoul(row[ItemField::casttime]);
|
||||
item.EliteMaterial = (uint32)atoul(row[ItemField::elitematerial]);
|
||||
item.ProcRate = (int32)atoi(row[ItemField::procrate]);
|
||||
item.CombatEffects = (int8)atoi(row[ItemField::combateffects]);
|
||||
item.Shielding = (int8)atoi(row[ItemField::shielding]);
|
||||
item.StunResist = (int8)atoi(row[ItemField::stunresist]);
|
||||
item.StrikeThrough = (int8)atoi(row[ItemField::strikethrough]);
|
||||
item.ExtraDmgSkill = (uint32)atoul(row[ItemField::extradmgskill]);
|
||||
item.ExtraDmgAmt = (uint32)atoul(row[ItemField::extradmgamt]);
|
||||
item.SpellShield = (int8)atoi(row[ItemField::spellshield]);
|
||||
item.Avoidance = (int8)atoi(row[ItemField::avoidance]);
|
||||
item.Accuracy = (int8)atoi(row[ItemField::accuracy]);
|
||||
item.CharmFileID = (uint32)atoul(row[ItemField::charmfileid]);
|
||||
item.FactionMod1 = (int32)atoul(row[ItemField::factionmod1]);
|
||||
item.FactionMod2 = (int32)atoul(row[ItemField::factionmod2]);
|
||||
item.FactionMod3 = (int32)atoul(row[ItemField::factionmod3]);
|
||||
item.FactionMod4 = (int32)atoul(row[ItemField::factionmod4]);
|
||||
item.FactionAmt1 = (int32)atoul(row[ItemField::factionamt1]);
|
||||
item.FactionAmt2 = (int32)atoul(row[ItemField::factionamt2]);
|
||||
item.FactionAmt3 = (int32)atoul(row[ItemField::factionamt3]);
|
||||
item.FactionAmt4 = (int32)atoul(row[ItemField::factionamt4]);
|
||||
|
||||
strcpy(item.CharmFile,row[ItemField::charmfile]);
|
||||
strcpy(item.CharmFile, row[ItemField::charmfile]);
|
||||
|
||||
item.AugType = (uint32)atoul(row[ItemField::augtype]);
|
||||
item.AugSlotType[0] = (uint8)atoi(row[ItemField::augslot1type]);
|
||||
item.AugSlotVisible[0] = (uint8)atoi(row[ItemField::augslot1visible]);
|
||||
item.AugSlotUnk2[0] = 0;
|
||||
item.AugSlotType[1] = (uint8)atoi(row[ItemField::augslot2type]);
|
||||
item.AugSlotVisible[1] = (uint8)atoi(row[ItemField::augslot2visible]);
|
||||
item.AugSlotUnk2[1] = 0;
|
||||
item.AugSlotType[2] = (uint8)atoi(row[ItemField::augslot3type]);
|
||||
item.AugSlotVisible[2] = (uint8)atoi(row[ItemField::augslot3visible]);
|
||||
item.AugSlotUnk2[2] = 0;
|
||||
item.AugSlotType[3] = (uint8)atoi(row[ItemField::augslot4type]);
|
||||
item.AugSlotVisible[3] = (uint8)atoi(row[ItemField::augslot4visible]);
|
||||
item.AugSlotUnk2[3] = 0;
|
||||
item.AugSlotType[4] = (uint8)atoi(row[ItemField::augslot5type]);
|
||||
item.AugSlotVisible[4] = (uint8)atoi(row[ItemField::augslot5visible]);
|
||||
item.AugSlotUnk2[4] = 0;
|
||||
item.AugType = (uint32)atoul(row[ItemField::augtype]);
|
||||
item.AugSlotType[0] = (uint8)atoi(row[ItemField::augslot1type]);
|
||||
item.AugSlotVisible[0] = (uint8)atoi(row[ItemField::augslot1visible]);
|
||||
item.AugSlotUnk2[0] = 0;
|
||||
item.AugSlotType[1] = (uint8)atoi(row[ItemField::augslot2type]);
|
||||
item.AugSlotVisible[1] = (uint8)atoi(row[ItemField::augslot2visible]);
|
||||
item.AugSlotUnk2[1] = 0;
|
||||
item.AugSlotType[2] = (uint8)atoi(row[ItemField::augslot3type]);
|
||||
item.AugSlotVisible[2] = (uint8)atoi(row[ItemField::augslot3visible]);
|
||||
item.AugSlotUnk2[2] = 0;
|
||||
item.AugSlotType[3] = (uint8)atoi(row[ItemField::augslot4type]);
|
||||
item.AugSlotVisible[3] = (uint8)atoi(row[ItemField::augslot4visible]);
|
||||
item.AugSlotUnk2[3] = 0;
|
||||
item.AugSlotType[4] = (uint8)atoi(row[ItemField::augslot5type]);
|
||||
item.AugSlotVisible[4] = (uint8)atoi(row[ItemField::augslot5visible]);
|
||||
item.AugSlotUnk2[4] = 0;
|
||||
item.AugSlotType[5] = (uint8)atoi(row[ItemField::augslot6type]);
|
||||
item.AugSlotVisible[5] = (uint8)atoi(row[ItemField::augslot6visible]);
|
||||
item.AugSlotUnk2[5] = 0;
|
||||
|
||||
item.LDoNTheme = (uint32)atoul(row[ItemField::ldontheme]);
|
||||
item.LDoNPrice = (uint32)atoul(row[ItemField::ldonprice]);
|
||||
item.LDoNSold = (uint32)atoul(row[ItemField::ldonsold]);
|
||||
item.BagType = (uint8)atoi(row[ItemField::bagtype]);
|
||||
item.BagSlots = (uint8)atoi(row[ItemField::bagslots]);
|
||||
item.BagSize = (uint8)atoi(row[ItemField::bagsize]);
|
||||
item.BagWR = (uint8)atoi(row[ItemField::bagwr]);
|
||||
item.Book = (uint8)atoi(row[ItemField::book]);
|
||||
item.BookType = (uint32)atoul(row[ItemField::booktype]);
|
||||
item.LDoNTheme = (uint32)atoul(row[ItemField::ldontheme]);
|
||||
item.LDoNPrice = (uint32)atoul(row[ItemField::ldonprice]);
|
||||
item.LDoNSold = (uint32)atoul(row[ItemField::ldonsold]);
|
||||
item.BagType = (uint8)atoi(row[ItemField::bagtype]);
|
||||
item.BagSlots = (uint8)std::min(atoi(row[ItemField::bagslots]), 10); // FIXME: remove when big bags supported
|
||||
item.BagSize = (uint8)atoi(row[ItemField::bagsize]);
|
||||
item.BagWR = (uint8)atoi(row[ItemField::bagwr]);
|
||||
item.Book = (uint8)atoi(row[ItemField::book]);
|
||||
item.BookType = (uint32)atoul(row[ItemField::booktype]);
|
||||
|
||||
strcpy(item.Filename,row[ItemField::filename]);
|
||||
strcpy(item.Filename, row[ItemField::filename]);
|
||||
|
||||
item.BaneDmgRaceAmt = (uint32)atoul(row[ItemField::banedmgraceamt]);
|
||||
item.AugRestrict = (uint32)atoul(row[ItemField::augrestrict]);
|
||||
item.LoreGroup = disableLoreGroup ? (uint8)atoi("0") : atoi(row[ItemField::loregroup]);
|
||||
item.LoreFlag = item.LoreGroup!=0;
|
||||
item.PendingLoreFlag = (atoi(row[ItemField::pendingloreflag])==0) ? false : true;
|
||||
item.ArtifactFlag = (atoi(row[ItemField::artifactflag])==0) ? false : true;
|
||||
item.SummonedFlag = (atoi(row[ItemField::summonedflag])==0) ? false : true;
|
||||
item.Favor = (uint32)atoul(row[ItemField::favor]);
|
||||
item.FVNoDrop = (atoi(row[ItemField::fvnodrop])==0) ? false : true;
|
||||
item.Endur = (uint32)atoul(row[ItemField::endur]);
|
||||
item.DotShielding = (uint32)atoul(row[ItemField::dotshielding]);
|
||||
item.Attack = (uint32)atoul(row[ItemField::attack]);
|
||||
item.Regen = (uint32)atoul(row[ItemField::regen]);
|
||||
item.ManaRegen = (uint32)atoul(row[ItemField::manaregen]);
|
||||
item.EnduranceRegen = (uint32)atoul(row[ItemField::enduranceregen]);
|
||||
item.Haste = (uint32)atoul(row[ItemField::haste]);
|
||||
item.DamageShield = (uint32)atoul(row[ItemField::damageshield]);
|
||||
item.RecastDelay = (uint32)atoul(row[ItemField::recastdelay]);
|
||||
item.RecastType = (uint32)atoul(row[ItemField::recasttype]);
|
||||
item.GuildFavor = (uint32)atoul(row[ItemField::guildfavor]);
|
||||
item.AugDistiller = (uint32)atoul(row[ItemField::augdistiller]);
|
||||
item.Attuneable = (atoi(row[ItemField::attuneable])==0) ? false : true;
|
||||
item.NoPet = (atoi(row[ItemField::nopet])==0) ? false : true;
|
||||
item.PointType = (uint32)atoul(row[ItemField::pointtype]);
|
||||
item.PotionBelt = (atoi(row[ItemField::potionbelt])==0) ? false : true;
|
||||
item.PotionBeltSlots = (atoi(row[ItemField::potionbeltslots])==0) ? false : true;
|
||||
item.StackSize = (uint16)atoi(row[ItemField::stacksize]);
|
||||
item.NoTransfer = disableNoTransfer ? false : (atoi(row[ItemField::notransfer])==0) ? false : true;
|
||||
item.Stackable = (atoi(row[ItemField::stackable])==0) ? false : true;
|
||||
item.Click.Effect = (uint32)atoul(row[ItemField::clickeffect]);
|
||||
item.Click.Type = (uint8)atoul(row[ItemField::clicktype]);
|
||||
item.Click.Level = (uint8)atoul(row[ItemField::clicklevel]);
|
||||
item.Click.Level2 = (uint8)atoul(row[ItemField::clicklevel2]);
|
||||
item.BaneDmgRaceAmt = (uint32)atoul(row[ItemField::banedmgraceamt]);
|
||||
item.AugRestrict = (uint32)atoul(row[ItemField::augrestrict]);
|
||||
item.LoreGroup = disableLoreGroup ? (uint8)atoi("0") : atoi(row[ItemField::loregroup]);
|
||||
item.LoreFlag = item.LoreGroup != 0;
|
||||
item.PendingLoreFlag = (atoi(row[ItemField::pendingloreflag]) == 0) ? false : true;
|
||||
item.ArtifactFlag = (atoi(row[ItemField::artifactflag]) == 0) ? false : true;
|
||||
item.SummonedFlag = (atoi(row[ItemField::summonedflag]) == 0) ? false : true;
|
||||
item.Favor = (uint32)atoul(row[ItemField::favor]);
|
||||
item.FVNoDrop = (atoi(row[ItemField::fvnodrop]) == 0) ? false : true;
|
||||
item.Endur = (uint32)atoul(row[ItemField::endur]);
|
||||
item.DotShielding = (uint32)atoul(row[ItemField::dotshielding]);
|
||||
item.Attack = (uint32)atoul(row[ItemField::attack]);
|
||||
item.Regen = (uint32)atoul(row[ItemField::regen]);
|
||||
item.ManaRegen = (uint32)atoul(row[ItemField::manaregen]);
|
||||
item.EnduranceRegen = (uint32)atoul(row[ItemField::enduranceregen]);
|
||||
item.Haste = (uint32)atoul(row[ItemField::haste]);
|
||||
item.DamageShield = (uint32)atoul(row[ItemField::damageshield]);
|
||||
item.RecastDelay = (uint32)atoul(row[ItemField::recastdelay]);
|
||||
item.RecastType = (uint32)atoul(row[ItemField::recasttype]);
|
||||
item.GuildFavor = (uint32)atoul(row[ItemField::guildfavor]);
|
||||
item.AugDistiller = (uint32)atoul(row[ItemField::augdistiller]);
|
||||
item.Attuneable = (atoi(row[ItemField::attuneable]) == 0) ? false : true;
|
||||
item.NoPet = (atoi(row[ItemField::nopet]) == 0) ? false : true;
|
||||
item.PointType = (uint32)atoul(row[ItemField::pointtype]);
|
||||
item.PotionBelt = (atoi(row[ItemField::potionbelt]) == 0) ? false : true;
|
||||
item.PotionBeltSlots = (atoi(row[ItemField::potionbeltslots]) == 0) ? false : true;
|
||||
item.StackSize = (uint16)atoi(row[ItemField::stacksize]);
|
||||
item.NoTransfer = disableNoTransfer ? false : (atoi(row[ItemField::notransfer]) == 0) ? false : true;
|
||||
item.Stackable = (atoi(row[ItemField::stackable]) == 0) ? false : true;
|
||||
item.Click.Effect = (uint32)atoul(row[ItemField::clickeffect]);
|
||||
item.Click.Type = (uint8)atoul(row[ItemField::clicktype]);
|
||||
item.Click.Level = (uint8)atoul(row[ItemField::clicklevel]);
|
||||
item.Click.Level2 = (uint8)atoul(row[ItemField::clicklevel2]);
|
||||
|
||||
strcpy(item.CharmFile,row[ItemField::charmfile]);
|
||||
strcpy(item.CharmFile, row[ItemField::charmfile]);
|
||||
|
||||
item.Proc.Effect = (int32)atoul(row[ItemField::proceffect]);
|
||||
item.Proc.Type = (uint8)atoul(row[ItemField::proctype]);
|
||||
item.Proc.Level = (uint8)atoul(row[ItemField::proclevel]);
|
||||
item.Proc.Level2 = (uint8)atoul(row[ItemField::proclevel2]);
|
||||
item.Worn.Effect = (int32)atoul(row[ItemField::worneffect]);
|
||||
item.Worn.Type = (uint8)atoul(row[ItemField::worntype]);
|
||||
item.Worn.Level = (uint8)atoul(row[ItemField::wornlevel]);
|
||||
item.Worn.Level2 = (uint8)atoul(row[ItemField::wornlevel2]);
|
||||
item.Focus.Effect = (int32)atoul(row[ItemField::focuseffect]);
|
||||
item.Focus.Type = (uint8)atoul(row[ItemField::focustype]);
|
||||
item.Focus.Level = (uint8)atoul(row[ItemField::focuslevel]);
|
||||
item.Focus.Level2 = (uint8)atoul(row[ItemField::focuslevel2]);
|
||||
item.Scroll.Effect = (int32)atoul(row[ItemField::scrolleffect]);
|
||||
item.Scroll.Type = (uint8)atoul(row[ItemField::scrolltype]);
|
||||
item.Scroll.Level = (uint8)atoul(row[ItemField::scrolllevel]);
|
||||
item.Scroll.Level2 = (uint8)atoul(row[ItemField::scrolllevel2]);
|
||||
item.Bard.Effect = (int32)atoul(row[ItemField::bardeffect]);
|
||||
item.Bard.Type = (uint8)atoul(row[ItemField::bardtype]);
|
||||
item.Bard.Level = (uint8)atoul(row[ItemField::bardlevel]);
|
||||
item.Bard.Level2 = (uint8)atoul(row[ItemField::bardlevel2]);
|
||||
item.QuestItemFlag = (atoi(row[ItemField::questitemflag])==0) ? false : true;
|
||||
item.SVCorruption = (int32)atoi(row[ItemField::svcorruption]);
|
||||
item.Purity = (uint32)atoul(row[ItemField::purity]);
|
||||
item.EvolvingLevel = (uint8)atoul(row[ItemField::evolvinglevel]);
|
||||
item.BackstabDmg = (uint32)atoul(row[ItemField::backstabdmg]);
|
||||
item.DSMitigation = (uint32)atoul(row[ItemField::dsmitigation]);
|
||||
item.HeroicStr = (int32)atoi(row[ItemField::heroic_str]);
|
||||
item.HeroicInt = (int32)atoi(row[ItemField::heroic_int]);
|
||||
item.HeroicWis = (int32)atoi(row[ItemField::heroic_wis]);
|
||||
item.HeroicAgi = (int32)atoi(row[ItemField::heroic_agi]);
|
||||
item.HeroicDex = (int32)atoi(row[ItemField::heroic_dex]);
|
||||
item.HeroicSta = (int32)atoi(row[ItemField::heroic_sta]);
|
||||
item.HeroicCha = (int32)atoi(row[ItemField::heroic_cha]);
|
||||
item.HeroicMR = (int32)atoi(row[ItemField::heroic_mr]);
|
||||
item.HeroicFR = (int32)atoi(row[ItemField::heroic_fr]);
|
||||
item.HeroicCR = (int32)atoi(row[ItemField::heroic_cr]);
|
||||
item.HeroicDR = (int32)atoi(row[ItemField::heroic_dr]);
|
||||
item.HeroicPR = (int32)atoi(row[ItemField::heroic_pr]);
|
||||
item.HeroicSVCorrup = (int32)atoi(row[ItemField::heroic_svcorrup]);
|
||||
item.HealAmt = (int32)atoi(row[ItemField::healamt]);
|
||||
item.SpellDmg = (int32)atoi(row[ItemField::spelldmg]);
|
||||
item.LDoNSellBackRate = (uint32)atoul(row[ItemField::ldonsellbackrate]);
|
||||
item.ScriptFileID = (uint32)atoul(row[ItemField::scriptfileid]);
|
||||
item.ExpendableArrow = (uint16)atoul(row[ItemField::expendablearrow]);
|
||||
item.Clairvoyance = (uint32)atoul(row[ItemField::clairvoyance]);
|
||||
item.Proc.Effect = (int32)atoul(row[ItemField::proceffect]);
|
||||
item.Proc.Type = (uint8)atoul(row[ItemField::proctype]);
|
||||
item.Proc.Level = (uint8)atoul(row[ItemField::proclevel]);
|
||||
item.Proc.Level2 = (uint8)atoul(row[ItemField::proclevel2]);
|
||||
item.Worn.Effect = (int32)atoul(row[ItemField::worneffect]);
|
||||
item.Worn.Type = (uint8)atoul(row[ItemField::worntype]);
|
||||
item.Worn.Level = (uint8)atoul(row[ItemField::wornlevel]);
|
||||
item.Worn.Level2 = (uint8)atoul(row[ItemField::wornlevel2]);
|
||||
item.Focus.Effect = (int32)atoul(row[ItemField::focuseffect]);
|
||||
item.Focus.Type = (uint8)atoul(row[ItemField::focustype]);
|
||||
item.Focus.Level = (uint8)atoul(row[ItemField::focuslevel]);
|
||||
item.Focus.Level2 = (uint8)atoul(row[ItemField::focuslevel2]);
|
||||
item.Scroll.Effect = (int32)atoul(row[ItemField::scrolleffect]);
|
||||
item.Scroll.Type = (uint8)atoul(row[ItemField::scrolltype]);
|
||||
item.Scroll.Level = (uint8)atoul(row[ItemField::scrolllevel]);
|
||||
item.Scroll.Level2 = (uint8)atoul(row[ItemField::scrolllevel2]);
|
||||
item.Bard.Effect = (int32)atoul(row[ItemField::bardeffect]);
|
||||
item.Bard.Type = (uint8)atoul(row[ItemField::bardtype]);
|
||||
item.Bard.Level = (uint8)atoul(row[ItemField::bardlevel]);
|
||||
item.Bard.Level2 = (uint8)atoul(row[ItemField::bardlevel2]);
|
||||
item.QuestItemFlag = (atoi(row[ItemField::questitemflag]) == 0) ? false : true;
|
||||
item.SVCorruption = (int32)atoi(row[ItemField::svcorruption]);
|
||||
item.Purity = (uint32)atoul(row[ItemField::purity]);
|
||||
item.EvolvingItem = (uint8)atoul(row[ItemField::evoitem]);
|
||||
item.EvolvingID = (uint8)atoul(row[ItemField::evoid]);
|
||||
item.EvolvingLevel = (uint8)atoul(row[ItemField::evolvinglevel]);
|
||||
item.EvolvingMax = (uint8)atoul(row[ItemField::evomax]);
|
||||
item.BackstabDmg = (uint32)atoul(row[ItemField::backstabdmg]);
|
||||
item.DSMitigation = (uint32)atoul(row[ItemField::dsmitigation]);
|
||||
item.HeroicStr = (int32)atoi(row[ItemField::heroic_str]);
|
||||
item.HeroicInt = (int32)atoi(row[ItemField::heroic_int]);
|
||||
item.HeroicWis = (int32)atoi(row[ItemField::heroic_wis]);
|
||||
item.HeroicAgi = (int32)atoi(row[ItemField::heroic_agi]);
|
||||
item.HeroicDex = (int32)atoi(row[ItemField::heroic_dex]);
|
||||
item.HeroicSta = (int32)atoi(row[ItemField::heroic_sta]);
|
||||
item.HeroicCha = (int32)atoi(row[ItemField::heroic_cha]);
|
||||
item.HeroicMR = (int32)atoi(row[ItemField::heroic_mr]);
|
||||
item.HeroicFR = (int32)atoi(row[ItemField::heroic_fr]);
|
||||
item.HeroicCR = (int32)atoi(row[ItemField::heroic_cr]);
|
||||
item.HeroicDR = (int32)atoi(row[ItemField::heroic_dr]);
|
||||
item.HeroicPR = (int32)atoi(row[ItemField::heroic_pr]);
|
||||
item.HeroicSVCorrup = (int32)atoi(row[ItemField::heroic_svcorrup]);
|
||||
item.HealAmt = (int32)atoi(row[ItemField::healamt]);
|
||||
item.SpellDmg = (int32)atoi(row[ItemField::spelldmg]);
|
||||
item.LDoNSellBackRate = (uint32)atoul(row[ItemField::ldonsellbackrate]);
|
||||
item.ScriptFileID = (uint32)atoul(row[ItemField::scriptfileid]);
|
||||
item.ExpendableArrow = (uint16)atoul(row[ItemField::expendablearrow]);
|
||||
item.Clairvoyance = (uint32)atoul(row[ItemField::clairvoyance]);
|
||||
|
||||
strcpy(item.ClickName,row[ItemField::clickname]);
|
||||
strcpy(item.ProcName,row[ItemField::procname]);
|
||||
strcpy(item.WornName,row[ItemField::wornname]);
|
||||
strcpy(item.FocusName,row[ItemField::focusname]);
|
||||
strcpy(item.ScrollName,row[ItemField::scrollname]);
|
||||
|
||||
try {
|
||||
hash.insert(item.ID, item);
|
||||
} catch(std::exception &ex) {
|
||||
Log.Out(Logs::General, Logs::Error, "Database::LoadItems: %s", ex.what());
|
||||
break;
|
||||
}
|
||||
}
|
||||
strcpy(item.ClickName, row[ItemField::clickname]);
|
||||
strcpy(item.ProcName, row[ItemField::procname]);
|
||||
strcpy(item.WornName, row[ItemField::wornname]);
|
||||
strcpy(item.FocusName, row[ItemField::focusname]);
|
||||
strcpy(item.ScrollName, row[ItemField::scrollname]);
|
||||
|
||||
try {
|
||||
hash.insert(item.ID, item);
|
||||
} catch (std::exception &ex) {
|
||||
Log.Out(Logs::General, Logs::Error, "Database::LoadItems: %s", ex.what());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Item_Struct* SharedDatabase::GetItem(uint32 id) {
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
||||
*/
|
||||
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9091
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9094
|
||||
#ifdef BOTS
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9000
|
||||
#else
|
||||
|
||||
@ -23,7 +23,7 @@ if($Config{osname}=~/linux/i){ $OS = "Linux"; }
|
||||
if($Config{osname}=~/Win|MS/i){ $OS = "Windows"; }
|
||||
|
||||
#::: If current version is less than what world is reporting, then download a new one...
|
||||
$current_version = 13;
|
||||
$current_version = 14;
|
||||
|
||||
if($ARGV[0] eq "V"){
|
||||
if($ARGV[1] > $current_version){
|
||||
@ -107,6 +107,38 @@ if($path eq ""){
|
||||
exit;
|
||||
}
|
||||
|
||||
if($ARGV[0] eq "install_peq_db"){
|
||||
|
||||
$db_name = "peq";
|
||||
if($ARGV[1]){
|
||||
$db_name = $ARGV[1];
|
||||
}
|
||||
|
||||
$db = $db_name;
|
||||
|
||||
#::: Database Routines
|
||||
print "MariaDB :: Creating Database '" . $db_name . "'\n";
|
||||
print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS $db_name;"`;
|
||||
print `"$path" --host $host --user $user --password="$pass" -N -B -e "CREATE DATABASE $db_name"`;
|
||||
if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); }
|
||||
if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); }
|
||||
$bin_db_ver = trim($db_version[1]);
|
||||
check_db_version_table();
|
||||
$local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1"));
|
||||
fetch_peq_db_full();
|
||||
print "\nFetching Latest Database Updates...\n";
|
||||
main_db_management();
|
||||
print "\nApplying Latest Database Updates...\n";
|
||||
main_db_management();
|
||||
|
||||
print get_mysql_result("UPDATE `launcher` SET `dynamics` = 30 WHERE `name` = 'zone'");
|
||||
}
|
||||
|
||||
if($ARGV[0] eq "remove_duplicate_rules"){
|
||||
remove_duplicate_rule_values();
|
||||
exit;
|
||||
}
|
||||
|
||||
if($ARGV[0] eq "installer"){
|
||||
print "Running EQEmu Server installer routines...\n";
|
||||
mkdir('logs');
|
||||
@ -152,6 +184,7 @@ if($ARGV[0] eq "installer"){
|
||||
|
||||
if($OS eq "Windows"){
|
||||
check_windows_firewall_rules();
|
||||
do_windows_login_server_setup();
|
||||
}
|
||||
exit;
|
||||
}
|
||||
@ -251,6 +284,7 @@ sub show_menu_prompt {
|
||||
11 => \&fetch_latest_windows_binaries,
|
||||
12 => \&fetch_server_dlls,
|
||||
13 => \&do_windows_login_server_setup,
|
||||
14 => \&remove_duplicate_rule_values,
|
||||
19 => \&do_bots_db_schema_drop,
|
||||
20 => \&do_update_self,
|
||||
0 => \&script_exit,
|
||||
@ -328,6 +362,7 @@ return <<EO_MENU;
|
||||
11) [Windows Server Build] :: Download Latest and Stable Server Build (Overwrites existing .exe's, includes .dll's)
|
||||
12) [Windows Server .dll's] :: Download Pre-Requisite Server .dll's
|
||||
13) [Windows Server Loginserver Setup] :: Download and install Windows Loginserver
|
||||
14) [Remove Duplicate Rule Values] :: Looks for redundant rule_values entries and removes them
|
||||
19) [EQEmu DB Drop Bots Schema] :: Remove Bots schema and return database to normal state
|
||||
20) [Update the updater] Force update this script (Redownload)
|
||||
0) Exit
|
||||
@ -521,6 +556,33 @@ sub opcodes_fetch{
|
||||
print "\nDone...\n\n";
|
||||
}
|
||||
|
||||
sub remove_duplicate_rule_values{
|
||||
$ruleset_id = trim(get_mysql_result("SELECT `ruleset_id` FROM `rule_sets` WHERE `name` = 'default'"));
|
||||
print "Default Ruleset ID: " . $ruleset_id . "\n";
|
||||
|
||||
$total_removed = 0;
|
||||
#::: Store Default values...
|
||||
$mysql_result = get_mysql_result("SELECT * FROM `rule_values` WHERE `ruleset_id` = " . $ruleset_id);
|
||||
my @lines = split("\n", $mysql_result);
|
||||
foreach my $val (@lines){
|
||||
my @values = split("\t", $val);
|
||||
$rule_set_values{$values[1]}[0] = $values[2];
|
||||
}
|
||||
#::: Compare default values against other rulesets to check for duplicates...
|
||||
$mysql_result = get_mysql_result("SELECT * FROM `rule_values` WHERE `ruleset_id` != " . $ruleset_id);
|
||||
my @lines = split("\n", $mysql_result);
|
||||
foreach my $val (@lines){
|
||||
my @values = split("\t", $val);
|
||||
if($values[2] == $rule_set_values{$values[1]}[0]){
|
||||
print "DUPLICATE : " . $values[1] . " (Ruleset (" . $values[0] . ")) matches default value of : " . $values[2] . ", removing...\n";
|
||||
get_mysql_result("DELETE FROM `rule_values` WHERE `ruleset_id` = " . $values[0] . " AND `rule_name` = '" . $values[1] . "'");
|
||||
$total_removed++;
|
||||
}
|
||||
}
|
||||
|
||||
print "Total duplicate rules removed... " . $total_removed . "\n";
|
||||
}
|
||||
|
||||
sub copy_file{
|
||||
$l_source_file = $_[0];
|
||||
$l_dest_file = $_[1];
|
||||
@ -1316,8 +1378,14 @@ sub run_database_check{
|
||||
|
||||
@total_updates = ();
|
||||
|
||||
#::: This is where we set checkpoints for where a database might be so we don't check so far back in the manifest...
|
||||
$revision_check = 1000;
|
||||
if(get_mysql_result("SHOW TABLES LIKE 'character_data'") ne ""){
|
||||
$revision_check = 9000;
|
||||
}
|
||||
|
||||
#::: Iterate through Manifest backwards from binary version down to local version...
|
||||
for($i = $bin_db_ver; $i > 1000; $i--){
|
||||
for($i = $bin_db_ver; $i > $revision_check; $i--){
|
||||
if(!defined($m_d{$i}[0])){ next; }
|
||||
|
||||
$file_name = trim($m_d{$i}[1]);
|
||||
|
||||
255
utils/scripts/import_13th_floor.pl
Normal file
255
utils/scripts/import_13th_floor.pl
Normal file
@ -0,0 +1,255 @@
|
||||
#! /usr/bin/perl
|
||||
|
||||
########################################################################
|
||||
#::: 13th floor import script
|
||||
#::: Current Source: http://items.sodeq.org/download.php
|
||||
#::: Authors: (Natedog, Akkadius)
|
||||
########################################################################
|
||||
|
||||
use DBI;
|
||||
use DBD::mysql;
|
||||
|
||||
my $database_name = "";
|
||||
my $total_items = 0;
|
||||
my $read_items_file = "items.txt"; #default
|
||||
my $dbh = LoadMysql();
|
||||
|
||||
read_items_file_from_13th_floor_text();
|
||||
update_items_table();
|
||||
|
||||
sub LoadMysql{
|
||||
#::: Config Variables
|
||||
my $confile = "eqemu_config.xml";
|
||||
open(F, "<$confile") or die "Unable to open config: $confile\n";
|
||||
my $indb = 0;
|
||||
while(<F>) {
|
||||
s/\r//g;
|
||||
if(/<database>/i) { $indb = 1; }
|
||||
next unless($indb == 1);
|
||||
if(/<\/database>/i) { $indb = 0; last; }
|
||||
if(/<host>(.*)<\/host>/i) { $host = $1; }
|
||||
elsif(/<username>(.*)<\/username>/i) { $user = $1; }
|
||||
elsif(/<password>(.*)<\/password>/i) { $pass = $1; }
|
||||
elsif(/<db>(.*)<\/db>/i) { $db = $1; }
|
||||
}
|
||||
$database_name = $db;
|
||||
#::: DATA SOURCE NAME
|
||||
$dsn = "dbi:mysql:$db:localhost:3306";
|
||||
#::: PERL DBI CONNECT
|
||||
$connect = DBI->connect($dsn, $user, $pass);
|
||||
return $connect;
|
||||
}
|
||||
|
||||
sub read_items_file_from_13th_floor_text {
|
||||
|
||||
#::: Read from file and place into array
|
||||
open(F, "<" . $read_items_file) or die "Unable to open itemfile: " . $read_items_file . "\n";
|
||||
my @item_file_lines = <F>;
|
||||
close(F);
|
||||
|
||||
#::: Chomp this array...
|
||||
my @newitem_file_lines;
|
||||
chomp($item_file_lines[0]);
|
||||
@fields = split("(?<!\\\\)\\|", $item_file_lines[0]);
|
||||
|
||||
my $sth = $dbh->prepare("SHOW TABLES LIKE 'items_floor'");
|
||||
$sth->execute();
|
||||
my $has_items_floor = $sth->fetchrow_array();
|
||||
|
||||
#::: If we have items_floor
|
||||
if ($has_items_floor eq '') {
|
||||
$dbh->do("CREATE TABLE `items_floor` (`" . join("` VARCHAR(64) NOT NULL DEFAULT '', `", @fields). "` VARCHAR(64) NOT NULL DEFAULT '', UNIQUE INDEX `ID` (`id`)) COLLATE='latin1_swedish_ci' ENGINE=MyISAM");
|
||||
$dbh->do("ALTER TABLE `items_floor` CHANGE `id` `id` INT(11) NOT NULL DEFAULT '0'");
|
||||
printf "Database items_floor created\n";
|
||||
}
|
||||
|
||||
#::: Create REPLACE INTO header and define worker variables...
|
||||
$master_insert = "REPLACE INTO `items_floor` (" . join(",", @fields) . ") VALUES ";
|
||||
$query_insert_ph = ""; #::: Used for building placeholder values in query Ex: (?, ?, ?)
|
||||
@field_values = (); #::: Used for stuffing mysql field values
|
||||
$query_count = 0; #::: Used for chunking query updates
|
||||
$print_cycle = 0; #::: Counter for console updates
|
||||
$start_time = time(); #::: Start time for import
|
||||
$total_items_file = scalar(grep $_, @item_file_lines) - 1; #::: Total items in text file
|
||||
|
||||
#::: Iterate through each item in items.txt
|
||||
for (1 .. $#item_file_lines) {
|
||||
@f = split("(?<!\\\\)\\|", $item_file_lines[$_]);
|
||||
|
||||
#::: Build our individual prepared statement (?, ?) values in the insert_ph
|
||||
#::: ?, ? placeholders will be resolved via @field_values in the execute
|
||||
$query_insert_ph .= " (";
|
||||
foreach (@f) {
|
||||
push (@field_values, trim($_));
|
||||
$query_insert_ph .= "?, ";
|
||||
}
|
||||
$query_insert_ph = substr($query_insert_ph, 0, -2);
|
||||
$query_insert_ph .= "), ";
|
||||
|
||||
#::: Let's chunk our updates so we can break up the amount of individual queries
|
||||
if($query_count > 500){
|
||||
$query_insert_ph = substr($query_insert_ph, 0, -2);
|
||||
$dbh->prepare($master_insert . " " . $query_insert_ph)->execute(@field_values);
|
||||
$query_count = 0;
|
||||
$query_insert_ph = "";
|
||||
@field_values = ();
|
||||
}
|
||||
|
||||
#::: Print updates to console
|
||||
if($print_cycle > 25){
|
||||
print "Processing (" . $read_items_file . ") :: (Items: " . $total_items . "/" . $total_items_file . ") \r";
|
||||
$print_cycle = 0;
|
||||
}
|
||||
|
||||
#::: Counters
|
||||
$total_items++;
|
||||
$query_count++;
|
||||
$print_cycle++;
|
||||
}
|
||||
|
||||
#::: One last processing print
|
||||
print "Processing (" . $read_items_file . ") :: (Items: " . $total_items . "/" . $total_items_file . ") \r";
|
||||
|
||||
printf "\n" . $total_items . " items added to database... Took " . (time() - $start_time) . " second(s)... \n";
|
||||
|
||||
print "Flipping slots 21 and 22...";
|
||||
$rows_affected = $dbh->prepare("
|
||||
UPDATE `items_floor`
|
||||
SET `slots` = (`slots` ^ 6291456)
|
||||
WHERE (`slots` & 6291456)
|
||||
IN (2097152, 4194304)")->execute();
|
||||
print " Rows affected (" . $rows_affected . ")\n";
|
||||
}
|
||||
|
||||
sub update_items_table {
|
||||
|
||||
#::: Keep Items table sane
|
||||
$query_handle = $dbh->prepare("
|
||||
ALTER TABLE `items`
|
||||
MODIFY COLUMN `UNK132` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL;
|
||||
");
|
||||
$query_handle->execute();
|
||||
|
||||
my @matching_table;
|
||||
my @missing_items_table;
|
||||
my @missing_items_floor_table;
|
||||
|
||||
#::: Get columns from `items`
|
||||
my $sth = $dbh->prepare("SHOW COLUMNS FROM `items`;");
|
||||
$sth->execute();
|
||||
my @items_table;
|
||||
while (my @row = $sth->fetchrow_array()) {
|
||||
push(@items_table, $row[0]);
|
||||
}
|
||||
|
||||
#::: Get columns from `items_floor`
|
||||
$sth2 = $dbh->prepare("SHOW COLUMNS FROM `items_floor`");
|
||||
$sth2->execute();
|
||||
my @items_floor_table;
|
||||
while (my @row = $sth2->fetchrow_array()) {
|
||||
push(@items_floor_table, $row[0]);
|
||||
}
|
||||
|
||||
#::: Go through the original items table columns and line them up with what columns match on 13th floor
|
||||
#::: This is so we can use the matching columns to update and insert item data into `items` table
|
||||
foreach $value (@items_table) {
|
||||
if ( grep( /^$value$/i, @items_floor_table ) ) {
|
||||
push(@matching_table, $value);
|
||||
} else {
|
||||
#::: What values are we missing from EMU items table..
|
||||
push(@missing_items_table, $value);
|
||||
}
|
||||
}
|
||||
|
||||
#::: What values are we missing from.. 13thFloor
|
||||
foreach $value (@items_floor_table) {
|
||||
if ( grep( /^$value$/i, @items_table ) ) {
|
||||
#DO NOTHING...
|
||||
} else {
|
||||
push(@missing_items_floor_table, $value);
|
||||
}
|
||||
}
|
||||
|
||||
#::: Go through the matched columns and build our query strings...
|
||||
|
||||
my $items_field_list = ""; #::: Build the field list for the INSERT (field1, field2)
|
||||
my $items_floor_field_list = ""; #::: What fields we will select from items_floor table to insert into items (matched columns)
|
||||
my $update_fields = ""; #::: To update an existing item entry if it exists...
|
||||
|
||||
foreach $match (@matching_table) {
|
||||
$match = lc($match);
|
||||
$update_fields .= "`" . $match . "` = fi.`" . $match . "`, ";
|
||||
$items_field_list .= "`" . $match . "`, ";
|
||||
$items_floor_field_list .= "fi.`" . $match . "`, ";
|
||||
}
|
||||
#::: Trim ', ' off the ends
|
||||
$update_fields = substr($update_fields, 0, -2);
|
||||
$items_field_list = substr($items_field_list, 0, -2);
|
||||
$items_floor_field_list = substr($items_floor_field_list, 0, -2);
|
||||
|
||||
#::: Mixed up fields...
|
||||
$items_floor_field_list =~ s/booktype/booklang/g; #our booktype is mixed with theirs...
|
||||
$update_fields =~ s/`booktype` = fi.`booktype`/`booktype` = fi.`booklang`/g;
|
||||
|
||||
#::: FIELDS THAT DO NOT MATCH GO HERE
|
||||
my @items_add = (
|
||||
"casttime_", "endur", "range", "attuneable", "evolvinglevel", "herosforgemodel", "scrolltype",
|
||||
"scriptfileid", "powersourcecapacity", "augslot1unk2", "augslot2unk2", "augslot3unk2", "augslot4unk2",
|
||||
"augslot5unk2", "augslot6unk2", "recskill", "book"
|
||||
);
|
||||
my @items_floor_add = (
|
||||
"foodduration", "endurance", "therange", "attunable", "evolvl", "heroforge1", "scrolleffecttype",
|
||||
"rightclickscriptid", "powersourcecap", "augslot1unk", "augslot2unk", "augslot3unk", "augslot4unk",
|
||||
"augslot5unk", "augslot6unk", "reqskill", "booktype"
|
||||
);
|
||||
|
||||
#::: Match the mis-matched fields...
|
||||
my $spot = 0;
|
||||
foreach $value (@items_add) {
|
||||
$items_field_list .= ", `" . $value . "`";
|
||||
$update_fields .= ", `" . $value . "` = fi.`" . $items_floor_add[$spot] . "`";
|
||||
$spot++;
|
||||
@missing_items_table = grep {$_ ne $value} @missing_items_table;
|
||||
}
|
||||
foreach $value (@items_floor_add) {
|
||||
$items_floor_field_list .= ", fi.`" . $value . "`";
|
||||
@missing_items_floor_table = grep {$_ ne $value} @missing_items_floor_table;
|
||||
}
|
||||
|
||||
my $update_query = "
|
||||
INSERT INTO items (" . $items_field_list . ")
|
||||
SELECT " . $items_floor_field_list . "
|
||||
FROM items_floor fi
|
||||
ON DUPLICATE KEY UPDATE " . $update_fields;
|
||||
|
||||
#::: Print missing fields to file
|
||||
my $write_file = "missing_item_fields.txt";
|
||||
|
||||
open(F, ">$write_file") or die "Unable to open questfile: $write_file\n";
|
||||
print F "$update_query \n\n";
|
||||
print F "EQEMU items Table missing fields\n";
|
||||
foreach $value (@missing_items_table) {
|
||||
print F "$value\n";
|
||||
}
|
||||
print F "\n\n13thFloor items Table missing fields\n";
|
||||
foreach $value (@missing_items_floor_table) {
|
||||
print F "$value\n";
|
||||
}
|
||||
close(F);
|
||||
|
||||
#::: Number of rows affected by query
|
||||
$rows = $dbh->do($update_query);
|
||||
|
||||
#::: Update stackables
|
||||
$dbh->do("UPDATE items i SET i.stackable = 1 WHERE i.stacksize > 1");
|
||||
|
||||
print "Added all new items to Items table (" . $rows . ")!\n";
|
||||
|
||||
}
|
||||
|
||||
sub trim($) {
|
||||
my $string = shift;
|
||||
$string =~ s/^\s+//;
|
||||
$string =~ s/\s+$//;
|
||||
return $string;
|
||||
}
|
||||
@ -1,77 +0,0 @@
|
||||
#! /usr/bin/perl
|
||||
|
||||
use DBI;
|
||||
use Getopt::Std;
|
||||
|
||||
getopts('d:h');
|
||||
$conf = "eqemu_config.xml";
|
||||
if($opt_h) {
|
||||
die "Usage: load_13thfloor_items.pl [-d path/to/eqemu_config.xml]\n";
|
||||
}
|
||||
if($opt_d) {
|
||||
$conf = $opt_d;
|
||||
}
|
||||
|
||||
$db = "eq";
|
||||
$user = "eq";
|
||||
$pass = "eq";
|
||||
$host = "localhost";
|
||||
open(F, "<$conf") or die "Unable to open config $conf\n";
|
||||
$indb = 0;
|
||||
while(<F>) {
|
||||
s/\r//g;
|
||||
if(/<database>/i) {
|
||||
$indb = 1;
|
||||
}
|
||||
next unless($indb == 1);
|
||||
if(/<\/database>/i) {
|
||||
$indb = 0;
|
||||
last;
|
||||
}
|
||||
if(/<host>(.*)<\/host>/i) {
|
||||
$host = $1;
|
||||
} elsif(/<username>(.*)<\/username>/i) {
|
||||
$user = $1;
|
||||
} elsif(/<password>(.*)<\/password>/i) {
|
||||
$pass = $1;
|
||||
} elsif(/<db>(.*)<\/db>/i) {
|
||||
$db = $1;
|
||||
}
|
||||
}
|
||||
if(!$db || !$user || !$pass || !$host) {
|
||||
die "Invalid db.ini, missing one of: host, user, password, database\n";
|
||||
}
|
||||
|
||||
$source="DBI:mysql:database=$db;host=$host";
|
||||
|
||||
my $dbh = DBI->connect($source, $user, $pass) || die "Could not create db handle\n";
|
||||
|
||||
$_=<STDIN>;
|
||||
chomp();
|
||||
s/'/\\'/g;
|
||||
@fields=split("(?<!\\\\)\\|", $_);
|
||||
|
||||
%conversions = (
|
||||
"itemtype" => "itemuse"
|
||||
);
|
||||
|
||||
$insert="replace into items (".join(",",@fields).",source,updated) values ('";
|
||||
$insert=~s/UNK130/potionbeltslots/;
|
||||
$insert=~s/UNK133/stackable/;
|
||||
|
||||
#select(STDOUT); $|=1;
|
||||
while(<STDIN>) {
|
||||
chomp();
|
||||
s/'/\\'/g;
|
||||
@f=split("(?<!\\\\)\\|", $_);
|
||||
$insert2=join("','",@f);
|
||||
$#f--;
|
||||
grep(s/\\\|/\\\\\|/g,@f);
|
||||
grep(s/"/\\\\"/g,@f);
|
||||
$statement=sprintf("%s%s','13THFLOOR',now())",$insert,$insert2,join('|',@f));
|
||||
$dbh->do($statement);
|
||||
printf("Processing: %d %s \r",$f[4],$f[1]);
|
||||
++$count;
|
||||
}
|
||||
printf("Processed: %d items(s) \n",$count);
|
||||
|
||||
@ -1,261 +1,261 @@
|
||||
5001|1_task_system.sql
|
||||
5001|1_task_system.sql|SHOW TABLES LIKE 'tasks'|empty|
|
||||
# 5002|2_optional_maxclients.sql
|
||||
# 5003|14_optional_merchantlist.sql
|
||||
5004|35_task_stepped.sql
|
||||
5005|42_task_min_maxlevel.sql
|
||||
5006|55_zone_shutdowndeleay.sql
|
||||
5004|35_task_stepped.sql|SHOW COLUMNS FROM `tasks` LIKE 'stepped'|not_empty|
|
||||
5005|42_task_min_maxlevel.sql|SHOW COLUMNS FROM `tasks` LIKE 'minlevel'|empty|
|
||||
5006|55_zone_shutdowndeleay.sql|SHOW COLUMNS FROM `zone` LIKE 'shutdowndelay'|empty|
|
||||
# 5007|68_optional_character_maxexplevel.sql
|
||||
# 5008|103_optional_chat_rules.sql
|
||||
5009|104_traps.sql
|
||||
5009|104_traps.sql|SHOW COLUMNS FROM `traps` LIKE 'respawn_time'|empty|
|
||||
# 5010|106_optional_proc_rules.sql
|
||||
5011|120_damageshieldtypes.sql
|
||||
5012|125_aggrozone.sql
|
||||
5011|120_damageshieldtypes.sql|SHOW TABLES LIKE 'damageshieldtypes'|empty|
|
||||
# 5012|125_aggrozone.sql
|
||||
# 5013|127_optional_spell_rules.sql
|
||||
# 5014|129_optional_shared_plat_rule.sql
|
||||
# 5015|131_optional_combat_rules.sql
|
||||
5016|133_task_repeatable.sql
|
||||
5017|142_deathpeace_and_lifetap_aas.sql
|
||||
5016|133_task_repeatable.sql|SHOW COLUMNS FROM `tasks` LIKE 'repeatable'|empty|
|
||||
5017|142_deathpeace_and_lifetap_aas.sql|SELECT * FROM db_version WHERE version > 5016|empty|
|
||||
# 5018|158_optional_death_exp_loss.sql
|
||||
5019|176_melody.sql
|
||||
5020|189_character_.sql
|
||||
5021|196_trader.sql
|
||||
5022|210_undyeme.sql
|
||||
5023|222_buyer.sql
|
||||
5024|226_account_limiting.sql
|
||||
5025|230_spells_table.sql
|
||||
5026|235_horses_table.sql
|
||||
5027|243_spawn_timers.sql
|
||||
5028|247_mail.sql
|
||||
5029|249_chatchannels.sql
|
||||
5030|250_bot_spell_update.sql
|
||||
# 5019|176_melody.sql
|
||||
5020|189_character_.sql|SELECT * FROM db_version WHERE version >= 5020|empty|
|
||||
5021|196_trader.sql|SHOW TABLES LIKE 'trader'|empty|
|
||||
# 5022|210_undyeme.sql
|
||||
5023|222_buyer.sql|SHOW TABLES LIKE 'buyer'|empty|
|
||||
# 5024|226_account_limiting.sql
|
||||
5025|230_spells_table.sql|SHOW TABLES LIKE 'spells_new'|empty|
|
||||
5026|235_horses_table.sql|SHOW TABLES LIKE 'horses'|empty|
|
||||
5027|243_spawn_timers.sql|SHOW TABLES LIKE 'respawn_times'|empty|
|
||||
5028|247_mail.sql|SHOW TABLES LIKE 'mail'|empty|
|
||||
5029|249_chatchannels.sql|SHOW TABLES LIKE 'chatchannels'|empty|
|
||||
# 5030|250_bot_spell_update.sql
|
||||
# 5031|250_optional_bot_spell_update.sql
|
||||
# 5032|285_optional_bot_spell_update.sql
|
||||
5033|292_augslots.sql
|
||||
5034|294_merchant_logging.sql
|
||||
5035|304_faction_list.sql
|
||||
5036|326_aas.sql
|
||||
5037|328_bot_management.sql
|
||||
# 5033|292_augslots.sql|SELECT * FROM db_version WHERE version >= 5033|empty|
|
||||
5034|294_merchant_logging.sql|SHOW COLUMNS FROM `eventlog` LIKE 'event_nid'|empty|
|
||||
5035|304_faction_list.sql|SELECT * FROM db_version WHERE version >= 5035|empty|
|
||||
5036|326_aas.sql|SELECT * FROM db_version WHERE version > 5035|empty|
|
||||
# 5037|328_bot_management.sql
|
||||
# 5038|328_optional_bot_management.sql
|
||||
5039|340_gm_ips.sql
|
||||
5040|356_combat.sql
|
||||
5041|360_peqzone.sql
|
||||
5042|364_ranged_dist_rule.sql
|
||||
5043|386_bot_save_raid.sql
|
||||
5039|340_gm_ips.sql|SHOW TABLES LIKE 'gm_ips'|empty|
|
||||
# 5040|356_combat.sql
|
||||
# 5041|360_peqzone.sql
|
||||
# 5042|364_ranged_dist_rule.sql
|
||||
# 5043|386_bot_save_raid.sql
|
||||
# 5044|434_optional_rest_state_rules.sql
|
||||
5045|447_sof_startzone_rule.sql
|
||||
5046|463_altadv_vars.sql
|
||||
5047|475_aa_actions.sql
|
||||
5048|500_spawn2_optimization.sql
|
||||
5049|503_bugs.sql
|
||||
5050|518_drakkin_npc_type_features.sql
|
||||
5051|524_rule_values_notes.sql
|
||||
5052|527_npc_armor_tint.sql
|
||||
5053|553_saylink_table.sql
|
||||
5054|564_nokeyring.sql
|
||||
5055|600_group_leadership.sql
|
||||
5056|612_instance_changes.sql
|
||||
5057|615_adventure_assassination.sql
|
||||
5058|619_Adventure_Recruiter_Flavor.sql
|
||||
5059|621_LDoNTraps.sql
|
||||
5060|633_ucs.sql
|
||||
5061|634_TrapTemplateDefaultValue.sql
|
||||
5062|643_BotsTable.sql
|
||||
5063|646_archery_penalty_rule.sql
|
||||
5064|665_heroic_resists.sql
|
||||
5065|667_titles.sql
|
||||
5066|687_aa_table_changes.sql
|
||||
5067|699_peqzone_rule.sql
|
||||
5068|702_aashieldblock_tint_table.sql
|
||||
5069|703_peqzone_rule.sql
|
||||
5070|704_rules.sql
|
||||
5071|710_tint_set_naming.sql
|
||||
5072|721_pathing_rules.sql
|
||||
5073|730_smart_delay_moving.sql
|
||||
5074|731_rule_assist_notarget_self.sql
|
||||
5075|732_sacrifice_rules.sql
|
||||
5076|745_slow_mitigation.sql
|
||||
5077|754_archery_base_damage_rule.sql
|
||||
5078|755_sof_altadv_vars_updates.sql
|
||||
5079|773_monk_rules.sql
|
||||
# 5045|447_sof_startzone_rule.sql
|
||||
# 5046|463_altadv_vars.sql
|
||||
# 5047|475_aa_actions.sql
|
||||
5048|500_spawn2_optimization.sql|SELECT * FROM db_version WHERE version >= 5048|empty|
|
||||
5049|503_bugs.sql|SHOW TABLES LIKE 'bugs'|empty|
|
||||
5050|518_drakkin_npc_type_features.sql|SHOW TABLES LIKE 'bugs'|empty|
|
||||
5051|524_rule_values_notes.sql|SELECT * FROM db_version WHERE version >= 5051|empty|
|
||||
5052|527_npc_armor_tint.sql|SELECT * FROM db_version WHERE version >= 5052|empty|
|
||||
5053|553_saylink_table.sql|SHOW TABLES LIKE 'saylink'|empty|
|
||||
5054|564_nokeyring.sql|SHOW COLUMNS FROM `doors` LIKE 'nokeyring'|empty|
|
||||
5055|600_group_leadership.sql|SELECT * FROM db_version WHERE version >= 5055|empty|
|
||||
5056|612_instance_changes.sql|SELECT * FROM db_version WHERE version >= 5056|empty|
|
||||
5057|615_adventure_assassination.sql|SELECT * FROM db_version WHERE version >= 5057|empty|
|
||||
5058|619_Adventure_Recruiter_Flavor.sql|SELECT * FROM db_version WHERE version >= 5058|empty|
|
||||
5059|621_LDoNTraps.sql|SHOW TABLES LIKE 'ldon_trap_templates'|empty|
|
||||
5060|633_ucs.sql|SHOW TABLES LIKE 'friends'|empty|
|
||||
5061|634_TrapTemplateDefaultValue.sql|SHOW COLUMNS FROM `npc_types` LIKE 'trap_template'|empty|
|
||||
# 5062|643_BotsTable.sql
|
||||
# 5063|646_archery_penalty_rule.sql
|
||||
5064|665_heroic_resists.sql|SELECT * FROM db_version WHERE version >= 5064|empty|
|
||||
5065|667_titles.sql|SHOW TABLES LIKE 'titles'|empty|
|
||||
5066|687_aa_table_changes.sql|SELECT * FROM db_version WHERE version >= 5066|empty|
|
||||
# 5067|699_peqzone_rule.sql
|
||||
5068|702_aashieldblock_tint_table.sql|SHOW TABLES LIKE 'npc_types_tint'|empty|
|
||||
# 5069|703_peqzone_rule.sql
|
||||
# 5070|704_rules.sql
|
||||
5071|710_tint_set_naming.sql|SELECT * FROM db_version WHERE version >= 5071|empty|
|
||||
5072|721_pathing_rules.sql|SELECT * FROM db_version WHERE version >= 5072|empty|
|
||||
# 5073|730_smart_delay_moving.sql
|
||||
# 5074|731_rule_assist_notarget_self.sql
|
||||
# 5075|732_sacrifice_rules.sql
|
||||
5076|745_slow_mitigation.sql|SELECT * FROM db_version WHERE version >= 5076|empty|
|
||||
# 5077|754_archery_base_damage_rule.sql
|
||||
5078|755_sof_altadv_vars_updates.sql|SELECT * FROM db_version WHERE version >= 5078|empty|
|
||||
# 5079|773_monk_rules.sql
|
||||
# 5080|853_optional_rule_aaexp.sql
|
||||
# 5081|858_optional_rule_ip_limit_by_status.sql
|
||||
# 5082|892_optional_bots_table_mod.sql
|
||||
# 5083|893_optional_bots_table_mod.sql
|
||||
5084|898_npc_maxlevel_scalerate.sql
|
||||
5084|898_npc_maxlevel_scalerate.sql|SHOW COLUMNS FROM `npc_types` LIKE 'maxlevel'|empty|
|
||||
# 5085|902_optional_rule_snareflee.sql
|
||||
5086|923_spawn2_enabled.sql
|
||||
5087|962_hot_zone.sql
|
||||
5088|964_reports.sql
|
||||
5089|971_veteran_rewards.sql
|
||||
5090|977_raid_npc_private_corpses.sql
|
||||
5091|979_unique_spawn_by_name.sql
|
||||
5092|980_account_ip.sql
|
||||
5093|1022_botadventuring.sql
|
||||
5094|1027_botactives.sql
|
||||
5095|1030_botzoningsupport.sql
|
||||
5096|1036_botbuffs.sql
|
||||
5097|1038_botpetstatepersists.sql
|
||||
5098|1038_grouptablesuniquecolumndefinitions.sql
|
||||
5099|1039_botguilds.sql
|
||||
5100|1040_DeprecatedBotRaidsSystems.sql
|
||||
5101|1057_titles.sql
|
||||
5102|1077_botgroups.sql
|
||||
5103|1136_spell_globals.sql
|
||||
5086|923_spawn2_enabled.sql|SHOW COLUMNS FROM `spawn2` LIKE 'enabled'|empty|
|
||||
5087|962_hot_zone.sql|SHOW COLUMNS FROM `zone` LIKE 'hotzone'|empty|
|
||||
5088|964_reports.sql|SHOW TABLES LIKE 'reports'|empty|
|
||||
5089|971_veteran_rewards.sql|SHOW TABLES LIKE 'veteran_reward_templates'|empty|
|
||||
5090|977_raid_npc_private_corpses.sql|SELECT * FROM db_version WHERE version >= 5090|empty|
|
||||
5091|979_unique_spawn_by_name.sql|SHOW COLUMNS FROM `npc_types` LIKE 'unique_spawn_by_name'|empty|
|
||||
5092|980_account_ip.sql|SHOW TABLES LIKE 'account_ip'|empty|
|
||||
# 5093|1022_botadventuring.sql
|
||||
# 5094|1027_botactives.sql
|
||||
# 5095|1030_botzoningsupport.sql
|
||||
# 5096|1036_botbuffs.sql
|
||||
# 5097|1038_botpetstatepersists.sql
|
||||
5098|1038_grouptablesuniquecolumndefinitions.sql|SELECT * FROM db_version WHERE version >= 5098|empty|
|
||||
# 5099|1039_botguilds.sql
|
||||
# 5100|1040_DeprecatedBotRaidsSystems.sql
|
||||
5101|1057_titles.sql|SHOW TABLES LIKE 'player_titlesets'|empty|
|
||||
# 5102|1077_botgroups.sql
|
||||
5103|1136_spell_globals.sql|SHOW TABLES LIKE 'spell_globals'|empty|
|
||||
# 5104|1144_optional_rule_return_nodrop.sql
|
||||
5105|1195_account_suspendeduntil.sql
|
||||
5106|1259_npc_skill_types.sql
|
||||
5107|1280_bot_augs.sql
|
||||
5105|1195_account_suspendeduntil.sql|SELECT * FROM db_version WHERE version >= 5105|empty|
|
||||
5106|1259_npc_skill_types.sql|SHOW COLUMNS FROM `npc_types` LIKE 'prim_melee_type'|empty|
|
||||
# 5107|1280_bot_augs.sql
|
||||
# 5108|1290_optional_exp_loss_rule.sql
|
||||
5109|1293_guild_bank.sql
|
||||
5110|1379_loginserver_trusted_server.sql
|
||||
5111|1392_recipe_learning.sql
|
||||
5109|1293_guild_bank.sql|SHOW TABLES LIKE 'guild_bank'|empty|
|
||||
# 5110|1379_loginserver_trusted_server.sql
|
||||
5111|1392_recipe_learning.sql|SELECT * FROM db_version WHERE version >= 5111|empty|
|
||||
# 5112|1394_optional_rule_sod_hp_mana_end.sql
|
||||
5113|1404_faction_list.sql
|
||||
5113|1404_faction_list.sql|SELECT * FROM db_version WHERE version >= 5113|empty|
|
||||
# 5114|1410_optional_sod_aas_ht_and_loh.sql
|
||||
5115|1436_login_server_table_fix.sql
|
||||
5116|1446_allowrest_optional.sql
|
||||
5117|1446_allowrest_required.sql
|
||||
5118|1450_cvs.sql
|
||||
5119|1451_guilds.sql
|
||||
5120|1498_instance_adventure.sql
|
||||
5121|1510_global_instances.sql
|
||||
5122|1511_map_path_loading.sql
|
||||
5123|1513_zone_points.sql
|
||||
5124|1519_zone_primary_key_id.sql
|
||||
5125|1542_items_table_cleanup.sql
|
||||
5126|1548_nimbuseffect_required.sql
|
||||
5127|1562_instanced_spawnconditions.sql
|
||||
5128|1586_waypoints_optional.sql
|
||||
5129|1610_tradeskill_required.sql
|
||||
5130|1618_zone.sql
|
||||
# 5115|1436_login_server_table_fix.sql
|
||||
# 5116|1446_allowrest_optional.sql
|
||||
5117|1446_allowrest_required.sql|SELECT * FROM db_version WHERE version >= 5117|empty|
|
||||
# 5118|1450_cvs.sql
|
||||
5119|1451_guilds.sql|SELECT * FROM db_version WHERE version >= 5119|empty|
|
||||
5120|1498_instance_adventure.sql|SELECT * FROM db_version WHERE version >= 5120|empty|
|
||||
5121|1510_global_instances.sql|SELECT * FROM db_version WHERE version >= 5121|empty|
|
||||
5122|1511_map_path_loading.sql|SHOW COLUMNS FROM `zone` LIKE 'map_file_name'|empty|
|
||||
5123|1513_zone_points.sql|SELECT * FROM db_version WHERE version >= 5123|empty|
|
||||
5124|1519_zone_primary_key_id.sql|SELECT * FROM db_version WHERE version >= 5124|empty|
|
||||
5125|1542_items_table_cleanup.sql|SELECT * FROM db_version WHERE version >= 5125|empty|
|
||||
5126|1548_nimbuseffect_required.sql|SELECT * FROM db_version WHERE version >= 5126|empty|
|
||||
5127|1562_instanced_spawnconditions.sql|SHOW TABLES LIKE 'spawn_condition_values'|empty|
|
||||
# 5128|1586_waypoints_optional.sql
|
||||
5129|1610_tradeskill_required.sql|SELECT * FROM db_version WHERE version >= 5129|empty|
|
||||
5130|1618_zone.sql|SELECT * FROM db_version WHERE version >= 5130|empty|
|
||||
# 5131|1625_optional_rule_class_race_exp_bonus.sql
|
||||
# 5132|1672_optional_rules_respawn_window.sql
|
||||
# 5133|1679_optional_rules_blocked_buffs.sql
|
||||
5134|1696_modify_zone_and_object_tables.sql
|
||||
5135|1711_account_restricted_aa.sql
|
||||
5134|1696_modify_zone_and_object_tables.sql|SELECT * FROM db_version WHERE version >= 5134|empty|
|
||||
5135|1711_account_restricted_aa.sql|SHOW COLUMNS FROM `account` LIKE 'time_creation'|empty|
|
||||
# 5136|1717_optional_rule_bash_stun_chance.sql
|
||||
# 5137|1718_optional_rules_mod3s.sql
|
||||
# 5138|1719_optional_triggerOnCastAAs.sql
|
||||
# 5139|1720_optional_sql_AAs.sql
|
||||
5140|1720_required_sql_AA_effects_update.sql
|
||||
# 5140|1720_required_sql_AA_effects_update.sql
|
||||
# 5141|1721_optional_sql_drakkin_breath_update.sql
|
||||
5142|1721_required_sql_altadv_vars_update.sql
|
||||
# 5142|1721_required_sql_altadv_vars_update.sql
|
||||
# 5143|1723_optional_sql_new_stats_window_rule.sql
|
||||
5144|1723_required_sql_corruption.sql
|
||||
5144|1723_required_sql_corruption.sql|SELECT * FROM db_version WHERE version >= 5144|empty|
|
||||
# 5145|1736_optional_sql_feral_swipe.sql
|
||||
5146|1737_required_sql_rule_and_aa_update.sql
|
||||
# 5146|1737_required_sql_rule_and_aa_update.sql
|
||||
# 5147|1746_optional_sql_bot_manaregen.sql
|
||||
# 5148|1747_optional_HoT_zone_and_zonepoints.sql
|
||||
# 5149|1750_optional_sql_reflect_rule.sql
|
||||
# 5150|1753_optional_haste_cap_rule.sql
|
||||
5151|1753_required_sql_healing_adept_aa.sql
|
||||
5152|1754_required_sql_healing_adept_aa_fix.sql
|
||||
5153|1755_required_sql_fear_resist_aas.sql
|
||||
# 5151|1753_required_sql_healing_adept_aa.sql
|
||||
# 5152|1754_required_sql_healing_adept_aa_fix.sql
|
||||
# 5153|1755_required_sql_fear_resist_aas.sql
|
||||
# 5154|1784_optional_corpsedrag_rules.sql
|
||||
5155|1786_required_update_to_aas.sql
|
||||
5156|1790_required_aa_required_level_cost.sql
|
||||
5157|1793_resist_adjust.sql
|
||||
# 5155|1786_required_update_to_aas.sql
|
||||
# 5156|1790_required_aa_required_level_cost.sql
|
||||
5157|1793_resist_adjust.sql|SHOW COLUMNS FROM `npc_spells_entries` LIKE 'resist_adjust'|empty|
|
||||
# 5158|1799_optional_rest_regen_endurance_rule.sql
|
||||
5159|1802_required_doppelganger.sql
|
||||
5160|1803_required_tasks_xpreward_signed.sql
|
||||
5161|1804_required_ae_melee_updates.sql
|
||||
5159|1802_required_doppelganger.sql|SELECT * FROM db_version WHERE version >= 5159|empty|
|
||||
5160|1803_required_tasks_xpreward_signed.sql|SELECT * FROM db_version WHERE version >= 5160|empty|
|
||||
5161|1804_required_ae_melee_updates.sql|SELECT * FROM db_version WHERE version >= 5161|empty|
|
||||
# 5162|1809_optional_rules.sql
|
||||
5163|1813_required_doppelganger_npcid_change.sql
|
||||
5163|1813_required_doppelganger_npcid_change.sql|SELECT * FROM db_version WHERE version >= 5163|empty|
|
||||
# 5164|1817_optional_npc_archery_bonus_rule.sql
|
||||
# 5165|1823_optional_delay_death.sql
|
||||
5166|1847_required_doors_dest_zone_size_32.sql
|
||||
5166|1847_required_doors_dest_zone_size_32.sql|SELECT * FROM db_version WHERE version >= 5166|empty|
|
||||
# 5167|1859_optional_item_casts_use_focus_rule.sql
|
||||
# 5168|1884_optional_bot_spells_update.sql
|
||||
# 5169|1885_optional_rules_fv_pvp_expansions.sql
|
||||
# 5170|1889_optional_skill_cap_rule.sql
|
||||
5171|1908_required_npc_types_definitions.sql
|
||||
5171|1908_required_npc_types_definitions.sql|SHOW COLUMNS FROM `npc_types` LIKE 'attack_count'|empty|
|
||||
# 5172|1926_optional_stat_cap.sql
|
||||
5173|1944_spawn2.sql
|
||||
5174|1946_doors.sql
|
||||
5173|1944_spawn2.sql|SHOW COLUMNS FROM `spawn2` LIKE 'animation'|empty|
|
||||
5174|1946_doors.sql|SELECT * FROM db_version WHERE version >= 5166|empty|
|
||||
# 5175|1960_optional_console_timeout_rule.sql
|
||||
# 5176|1962_optional_guild_creation_window_rules.sql
|
||||
# 5177|1963_optional_rule_live_like_focuses.sql
|
||||
# 5178|1968_optional_enrage_rules.sql
|
||||
# 5179|1972_optional_extradmg_item_cap.sql
|
||||
5180|1974_required_bot_spells_update.sql
|
||||
5181|1977_underwater.sql
|
||||
# 5180|1974_required_bot_spells_update.sql
|
||||
5181|1977_underwater.sql|SHOW COLUMNS FROM `npc_types` LIKE 'underwater'|empty|
|
||||
# 5182|1998_optional_intoxication_and_looting_rules.sql
|
||||
5183|2004_charges_alt_currency.sql
|
||||
5183|2004_charges_alt_currency.sql|SHOW TABLES LIKE 'alternate_currency'|empty|
|
||||
# 5184|2015_optional_specialization_training_rule.sql
|
||||
# 5185|2016_optional_rule_bot_aa_expansion.sql
|
||||
# 5186|2023_optional_mysqlcli.sql
|
||||
# 5187|2024_optional_update_crystals.sql
|
||||
5188|2024_required_update.sql
|
||||
5189|2057_required_discovered_items.sql
|
||||
5188|2024_required_update.sql|SHOW TABLES LIKE 'char_create_combinations'|empty|
|
||||
5189|2057_required_discovered_items.sql|SHOW TABLES LIKE 'discovered_items'|empty|
|
||||
# 5190|2058_optional_rule_discovered_items.sql
|
||||
5191|2062_required_version_changes.sql
|
||||
5192|2069_required_pets.sql
|
||||
5193|2079_player_speech.sql
|
||||
5194|2087_required_bots_hp_and_mana_and_spell_updates.sql
|
||||
5195|2098_required_zonepoint_version_changes.sql
|
||||
5196|2099_required_discovered_items_account_status.sql
|
||||
5197|2104_required_group_roles.sql
|
||||
5198|2107_required_bot_stances.sql
|
||||
5199|2129_required_lfguild.sql
|
||||
5200|2133_required_faction_loot_despawn.sql
|
||||
5201|2136_extended_targets.sql
|
||||
5202|2142_emotes.sql
|
||||
5191|2062_required_version_changes.sql|SELECT * FROM db_version WHERE version >= 5191|empty|
|
||||
5192|2069_required_pets.sql|SHOW TABLES LIKE 'pets_equipmentset'|empty|
|
||||
# 5193|2079_player_speech.sql
|
||||
# 5194|2087_required_bots_hp_and_mana_and_spell_updates.sql
|
||||
5195|2098_required_zonepoint_version_changes.sql|SELECT * FROM db_version WHERE version >= 5195|empty|
|
||||
5196|2099_required_discovered_items_account_status.sql|SELECT * FROM db_version WHERE version >= 5196|empty|
|
||||
5197|2104_required_group_roles.sql|SELECT * FROM db_version WHERE version >= 5197|empty|
|
||||
# 5198|2107_required_bot_stances.sql
|
||||
5199|2129_required_lfguild.sql|SHOW TABLES LIKE 'lfguild'|empty|
|
||||
5200|2133_required_faction_loot_despawn.sql|SELECT * FROM db_version WHERE version >= 5200|empty|
|
||||
5201|2136_extended_targets.sql|SELECT * FROM db_version WHERE version >= 5201|empty|
|
||||
5202|2142_emotes.sql|SELECT * FROM db_version WHERE version >= 5202|empty|
|
||||
# 5203|2154_optional_rule_spell_procs_resists_falloff.sql
|
||||
# 5204|2156_optional_charm_break_rule.sql
|
||||
# 5205|2159_optional_defensiveproc_rules.sql
|
||||
5206|2164_require_bots_bottimers.sql
|
||||
# 5206|2164_require_bots_bottimers.sql
|
||||
# 5207|2171_optional_SpecialAttackACBonus_rule.sql
|
||||
# 5208|2176_optional_aa_expansion_SOF_fix.sql
|
||||
# 5209|2176_optional_FrenzyBonus_rule.sql
|
||||
5210|2176_required_aa_updates.sql
|
||||
5211|2178_required_aa_updates.sql
|
||||
5210|2176_required_aa_updates.sql|SELECT * FROM db_version WHERE version >= 5210|empty|
|
||||
5211|2178_required_aa_updates.sql|SELECT * FROM db_version WHERE version >= 5211|empty|
|
||||
# 5212|2183_optional_bot_xp_rule.sql
|
||||
# 5213|2185_optional_NPCFlurryChacne_rule
|
||||
# 5214|2185_optional_NPCFlurryChacne_rule.sql
|
||||
# 5215|2185_optional_NPCFlurryChance_rule.sql
|
||||
5216|2185_required_aa_updates
|
||||
5217|2185_required_aa_updates.sql
|
||||
5216|2185_required_aa_updates|SELECT * FROM db_version WHERE version >= 5216|empty|
|
||||
5217|2185_required_aa_updates.sql|SELECT * FROM db_version WHERE version >= 5217|empty|
|
||||
# 5218|2188_optional_miscspelleffect_rules
|
||||
# 5219|2188_optional_miscspelleffect_rules.sql
|
||||
5220|2188_required_aa_updates
|
||||
5221|2188_required_aa_updates.sql
|
||||
# 5220|2188_required_aa_updates
|
||||
5221|2188_required_aa_updates.sql|SELECT * FROM db_version WHERE version >= 5221|empty|
|
||||
# 5222|2189_optional_taunt_rules
|
||||
# 5223|2189_optional_taunt_rules.sql
|
||||
5224|2195_required_sharedplatupdates.sql
|
||||
5224|2195_required_sharedplatupdates.sql|SELECT * FROM db_version WHERE version >= 5224|empty|
|
||||
# 5225|2208_optional_aa_stacking_rule.sql
|
||||
# 5226|2208_optional_EnableSoulAbrasionAA.sql
|
||||
5227|2208_required_aa_updates.sql
|
||||
5227|2208_required_aa_updates.sql|SELECT * FROM db_version WHERE version >= 5227|empty|
|
||||
# 5228|2209_optional_additive_bonus_rule.sql
|
||||
5229|2213_loot_changes.sql
|
||||
5230|2214_faction_list_mod.sql
|
||||
5231|2215_required_aa_updates.sql
|
||||
5229|2213_loot_changes.sql|SELECT * FROM db_version WHERE version >= 5229|empty|
|
||||
5230|2214_faction_list_mod.sql|SHOW TABLES LIKE 'faction_list_mod'|empty|
|
||||
5231|2215_required_aa_updates.sql|SELECT * FROM db_version WHERE version >= 5231|empty|
|
||||
# 5232|2243_optional_char_max_level_rule.sql
|
||||
5233|2260_probability.sql
|
||||
5234|2262_required_pet_discipline_update.sql
|
||||
5235|2264_required_aa_updates.sql
|
||||
5236|2268_QueryServ.sql
|
||||
5237|2268_required_updates.sql
|
||||
# 5233|2260_probability.sql
|
||||
5234|2262_required_pet_discipline_update.sql|SELECT * FROM db_version WHERE version >= 5234|empty|
|
||||
5235|2264_required_aa_updates.sql|SELECT * FROM db_version WHERE version >= 5235|empty|
|
||||
# 5236|2268_QueryServ.sql
|
||||
5237|2268_required_updates.sql|SELECT * FROM db_version WHERE version >= 5237|empty|
|
||||
# 5238|2274_optional_rule_iplimitdisconnectall.sql
|
||||
# 5239|2278_optional_rule_targetableswarmpet.sql
|
||||
# 5240|2280_optional_rule_targetableswarmpet-rename.sql
|
||||
5241|2283_required_npc_changes.sql
|
||||
5242|2299_required_inspectmessage_fields.sql
|
||||
5241|2283_required_npc_changes.sql|SHOW COLUMNS FROM `npc_types` LIKE 'spellscale'|empty|
|
||||
5242|2299_required_inspectmessage_fields.sql|SELECT * FROM db_version WHERE version >= 5242|empty|
|
||||
# 5243|2300_optional_loot_changes.sql
|
||||
5244|2304_QueryServ.sql
|
||||
5245|2340_required_maxbuffslotspet.sql
|
||||
5246|2361_QueryServ.sql
|
||||
5247|2361_required_qs_rule_values.sql
|
||||
5248|2370_required_aa_updates.sql
|
||||
5249|2376_required_aa_updates.sql
|
||||
# 5250|2380_optional_merc_data.sql
|
||||
# 5251|2380_optional_merc_merchant_npctypes_update.sql
|
||||
# 5252|2380_optional_merc_rules.sql
|
||||
5253|2383_required_group_ismerc.sql
|
||||
# 5244|2304_QueryServ.sql
|
||||
# 5245|2340_required_maxbuffslotspet.sql
|
||||
# 5246|2361_QueryServ.sql
|
||||
# 5247|2361_required_qs_rule_values.sql
|
||||
5248|2370_required_aa_updates.sql|SELECT * FROM db_version WHERE version >= 5248|empty|
|
||||
5249|2376_required_aa_updates.sql|SELECT * FROM db_version WHERE version >= 5249|empty|
|
||||
5250|2380_optional_merc_data.sql|SELECT * FROM db_version WHERE version >= 5250|empty|
|
||||
5251|2380_optional_merc_merchant_npctypes_update.sql|SELECT * FROM db_version WHERE version >= 5251|empty|
|
||||
5252|2380_optional_merc_rules.sql|SELECT * FROM db_version WHERE version >= 5252|empty|
|
||||
5253|2383_required_group_ismerc.sql|SELECT * FROM db_version WHERE version >= 5253|empty|
|
||||
# 5254|2428_optional_levelbasedexpmods.sql
|
||||
# 5255|2448_optional_stun_proc_aggro_rule.sql
|
||||
5256|2471_required_aa_updates.sql
|
||||
5257|2482_required_start_zones.sql
|
||||
5258|2504_required_aa_updates.sql
|
||||
5256|2471_required_aa_updates.sql|SELECT * FROM db_version WHERE version >= 5256|empty|
|
||||
5257|2482_required_start_zones.sql|SELECT * FROM db_version WHERE version >= 5257|empty|
|
||||
5258|2504_required_aa_updates.sql|SELECT * FROM db_version WHERE version >= 5258|empty|
|
||||
8000|mercs.sql|SHOW TABLES LIKE 'merc_stats'|empty|
|
||||
9000|2013_02_18_Merc_Rules_and_Tables.sql|SELECT * FROM `rule_values` WHERE `rule_name` LIKE '%Mercs:ResurrectRadius%'|empty|
|
||||
9001|2013_02_25_Impr_HT_LT.sql|SHOW TABLES LIKE 'merc_inventory'|empty|
|
||||
@ -345,6 +345,9 @@
|
||||
9089|2015_11_02_ai_idle_no_spell_recast_default_changes.sql|SELECT * FROM `rule_values` WHERE `rule_name` LIKE '%Spells:AI_IdleNoSpellMinRecast%' AND `rule_value` = '500'|not_empty|
|
||||
9090|2015_12_01_spell_scribe_restriction_rule.sql|SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Character:RestrictSpellScribing'|empty|
|
||||
9091|2015_12_07_command_settings.sql|SHOW TABLES LIKE 'command_settings'|empty|
|
||||
9092|2015_12_17_eqtime.sql|SHOW TABLES LIKE 'eqtime'|empty|
|
||||
9093|2015_12_21_items_updates_evoitem.sql|SHOW COLUMNS FROM `items` LIKE 'evoitem'|empty|
|
||||
9094|2015_12_29_quest_zone_events.sql|SELECT * FROM perl_event_export_settings WHERE event_description = 'EVENT_SPAWN_ZONE'|empty|
|
||||
|
||||
# Upgrade conditions:
|
||||
# This won't be needed after this system is implemented, but it is used database that are not
|
||||
|
||||
3
utils/sql/git/optional/2015_12_26_oow_aa_missing.sql
Normal file
3
utils/sql/git/optional/2015_12_26_oow_aa_missing.sql
Normal file
@ -0,0 +1,3 @@
|
||||
INSERT INTO `aa_ranks` (`id`, `upper_hotkey_sid`, `lower_hotkey_sid`, `title_sid`, `desc_sid`, `cost`, `level_req`, `spell`, `spell_type`, `recast_time`, `expansion`, `prev_id`, `next_id`) VALUES (1015, -1, -1, 1011, 1011, 0, 51, -1, 0, 0, 8, 1014, 1016);
|
||||
|
||||
INSERT INTO `aa_rank_effects` (`rank_id`, `slot`, `effect_id`, `base1`, `base2`) VALUES (1015, 1, 262, 40, 7), (1015, 2, 262, 40, 8), (1015, 3, 262, 40, 9), (1015, 4, 262, 40, 10), (1015, 5, 262, 40, 11);
|
||||
11
utils/sql/git/required/2015_12_17_eqtime.sql
Normal file
11
utils/sql/git/required/2015_12_17_eqtime.sql
Normal file
@ -0,0 +1,11 @@
|
||||
DROP TABLE IF EXISTS `eqtime`;
|
||||
CREATE TABLE `eqtime` (
|
||||
`minute` tinyint(4) not null default 0,
|
||||
`hour` tinyint(4) not null default 0,
|
||||
`day` tinyint(4) not null default 0,
|
||||
`month` tinyint(4) not null default 0,
|
||||
`year` int(4) not null default 0,
|
||||
`realtime` int(11) not null default 0
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
INSERT INTO eqtime values (0,1,28,12,3766,1444035661);
|
||||
@ -0,0 +1,8 @@
|
||||
ALTER TABLE `items`
|
||||
ADD COLUMN `evoitem` INT(11) NOT NULL DEFAULT '0' AFTER `purity`,
|
||||
ADD COLUMN `evoid` INT(11) NOT NULL DEFAULT '0' AFTER `evoitem`,
|
||||
ADD COLUMN `evomax` INT(11) NOT NULL DEFAULT '0' AFTER `evolvinglevel`,
|
||||
CHANGE `UNK038` `skillmodmax` INT(11) NOT NULL DEFAULT '0',
|
||||
CHANGE `UNK222` `heirloom` INT(11) NOT NULL DEFAULT '0',
|
||||
CHANGE `UNK235` `placeable` INT(11) NOT NULL DEFAULT '0',
|
||||
CHANGE `UNK242` `epicitem` INT(11) NOT NULL DEFAULT '0';
|
||||
4
utils/sql/git/required/2015_12_29_quest_zone_events.sql
Normal file
4
utils/sql/git/required/2015_12_29_quest_zone_events.sql
Normal file
@ -0,0 +1,4 @@
|
||||
INSERT INTO `perl_event_export_settings` (`event_id`, `event_description`, `export_qglobals`, `export_mob`, `export_zone`, `export_item`, `export_event`) VALUES (81, 'EVENT_SPAWN_ZONE', 0, 0, 0, 0, 1);
|
||||
INSERT INTO `perl_event_export_settings` (`event_id`, `event_description`, `export_qglobals`, `export_mob`, `export_zone`, `export_item`, `export_event`) VALUES (82, 'EVENT_DEATH_ZONE', 0, 0, 0, 0, 1);
|
||||
ALTER TABLE `rule_values`
|
||||
MODIFY COLUMN `notes` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL AFTER `rule_value`;
|
||||
@ -2532,6 +2532,7 @@ INSERT INTO `aa_ranks` (`id`, `upper_hotkey_sid`, `lower_hotkey_sid`, `title_sid
|
||||
(1012, -1, -1, 1011, 1011, 0, 51, -1, 0, 0, 8, 1011, 1013),
|
||||
(1013, -1, -1, 1011, 1011, 0, 51, -1, 0, 0, 8, 1012, 1014),
|
||||
(1014, -1, -1, 1011, 1011, 0, 51, -1, 0, 0, 8, 1013, 1015),
|
||||
(1015, -1, -1, 1011, 1011, 0, 51, -1, 0, 0, 8, 1014, 1016),
|
||||
(1016, -1, -1, 1011, 1011, 0, 51, -1, 0, 0, 8, 1015, -1),
|
||||
(1017, 1017, 1017, 1017, 1017, 6, 59, 16531, 75, 15, 15, -1, 13726),
|
||||
(1018, 1018, 1018, 1018, 1018, 2, 63, 16455, 69, 1, 15, -1, -1),
|
||||
@ -9526,6 +9527,11 @@ INSERT INTO `aa_rank_effects` (`rank_id`, `slot`, `effect_id`, `base1`, `base2`)
|
||||
(1014, 3, 262, 32, 9),
|
||||
(1014, 4, 262, 32, 10),
|
||||
(1014, 5, 262, 32, 11),
|
||||
(1015, 1, 262, 40, 7),
|
||||
(1015, 2, 262, 40, 8),
|
||||
(1015, 3, 262, 40, 9),
|
||||
(1015, 4, 262, 40, 10),
|
||||
(1015, 5, 262, 40, 11),
|
||||
(1016, 1, 262, 50, 7),
|
||||
(1016, 2, 262, 50, 8),
|
||||
(1016, 3, 262, 50, 9),
|
||||
|
||||
@ -345,8 +345,13 @@ int main(int argc, char** argv) {
|
||||
database.ClearMerchantTemp();
|
||||
}
|
||||
Log.Out(Logs::General, Logs::World_Server, "Loading EQ time of day..");
|
||||
if (!zoneserver_list.worldclock.loadFile(Config->EQTimeFile.c_str()))
|
||||
Log.Out(Logs::General, Logs::World_Server, "Unable to load %s", Config->EQTimeFile.c_str());
|
||||
TimeOfDay_Struct eqTime;
|
||||
time_t realtime;
|
||||
eqTime = database.LoadTime(realtime);
|
||||
zoneserver_list.worldclock.SetCurrentEQTimeOfDay(eqTime, realtime);
|
||||
Timer EQTimeTimer(600000);
|
||||
EQTimeTimer.Start(600000);
|
||||
|
||||
Log.Out(Logs::General, Logs::World_Server, "Loading launcher list..");
|
||||
launcher_list.LoadList();
|
||||
|
||||
@ -470,6 +475,16 @@ int main(int argc, char** argv) {
|
||||
database.PurgeExpiredInstances();
|
||||
}
|
||||
|
||||
if (EQTimeTimer.Check())
|
||||
{
|
||||
TimeOfDay_Struct tod;
|
||||
zoneserver_list.worldclock.GetCurrentEQTimeOfDay(time(0), &tod);
|
||||
if (!database.SaveTime(tod.minute, tod.hour, tod.day, tod.month, tod.year))
|
||||
Log.Out(Logs::General, Logs::World_Server, "Failed to save eqtime.");
|
||||
else
|
||||
Log.Out(Logs::Detail, Logs::World_Server, "EQTime successfully saved.");
|
||||
}
|
||||
|
||||
//check for timeouts in other threads
|
||||
timeout_manager.CheckTimeouts();
|
||||
loginserverlist.Process();
|
||||
@ -519,8 +534,6 @@ int main(int argc, char** argv) {
|
||||
|
||||
void CatchSignal(int sig_num) {
|
||||
Log.Out(Logs::General, Logs::World_Server,"Caught signal %d",sig_num);
|
||||
if(zoneserver_list.worldclock.saveFile(WorldConfig::get()->EQTimeFile.c_str())==false)
|
||||
Log.Out(Logs::General, Logs::World_Server,"Failed to save time file.");
|
||||
RunLoops = false;
|
||||
}
|
||||
|
||||
|
||||
@ -989,8 +989,8 @@ bool ZoneServer::Process() {
|
||||
Log.Out(Logs::Detail, Logs::World_Server,"Received SetWorldTime");
|
||||
eqTimeOfDay* newtime = (eqTimeOfDay*) pack->pBuffer;
|
||||
zoneserver_list.worldclock.SetCurrentEQTimeOfDay(newtime->start_eqtime, newtime->start_realtime);
|
||||
Log.Out(Logs::Detail, Logs::World_Server,"New time = %d-%d-%d %d:%d (%d)\n", newtime->start_eqtime.year, newtime->start_eqtime.month, (int)newtime->start_eqtime.day, (int)newtime->start_eqtime.hour, (int)newtime->start_eqtime.minute, (int)newtime->start_realtime);
|
||||
zoneserver_list.worldclock.saveFile(WorldConfig::get()->EQTimeFile.c_str());
|
||||
Log.Out(Logs::Detail, Logs::World_Server, "New time = %d-%d-%d %d:%d (%d)\n", newtime->start_eqtime.year, newtime->start_eqtime.month, (int)newtime->start_eqtime.day, (int)newtime->start_eqtime.hour, (int)newtime->start_eqtime.minute, (int)newtime->start_realtime);
|
||||
database.SaveTime((int)newtime->start_eqtime.minute, (int)newtime->start_eqtime.hour, (int)newtime->start_eqtime.day, newtime->start_eqtime.month, newtime->start_eqtime.year);
|
||||
zoneserver_list.SendTimeSync();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -431,11 +431,20 @@ void EntityList::AIYellForHelp(Mob* sender, Mob* attacker) {
|
||||
if (sender->GetPrimaryFaction() == 0 )
|
||||
return; // well, if we dont have a faction set, we're gonna be indiff to everybody
|
||||
|
||||
if (sender->HasAssistAggro())
|
||||
return;
|
||||
|
||||
for (auto it = npc_list.begin(); it != npc_list.end(); ++it) {
|
||||
NPC *mob = it->second;
|
||||
if (!mob)
|
||||
continue;
|
||||
|
||||
if (mob->CheckAggro(attacker))
|
||||
continue;
|
||||
|
||||
if (sender->NPCAssistCap() >= RuleI(Combat, NPCAssistCap))
|
||||
break;
|
||||
|
||||
float r = mob->GetAssistRange();
|
||||
r = r * r;
|
||||
|
||||
@ -476,7 +485,8 @@ void EntityList::AIYellForHelp(Mob* sender, Mob* attacker) {
|
||||
attacker->GetName(), DistanceSquared(mob->GetPosition(),
|
||||
sender->GetPosition()), fabs(sender->GetZ()+mob->GetZ()));
|
||||
#endif
|
||||
mob->AddToHateList(attacker, 1, 0, false);
|
||||
mob->AddToHateList(attacker, 25, 0, false);
|
||||
sender->AddAssistCap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2009,15 +2009,15 @@ void NPC::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack
|
||||
}
|
||||
}
|
||||
|
||||
bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack_skill) {
|
||||
Log.Out(Logs::Detail, Logs::Combat, "Fatal blow dealt by %s with %d damage, spell %d, skill %d", killerMob->GetName(), damage, spell, attack_skill);
|
||||
bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attack_skill) {
|
||||
Log.Out(Logs::Detail, Logs::Combat, "Fatal blow dealt by %s with %d damage, spell %d, skill %d", killer_mob->GetName(), damage, spell, attack_skill);
|
||||
|
||||
Mob *oos = nullptr;
|
||||
if(killerMob) {
|
||||
oos = killerMob->GetOwnerOrSelf();
|
||||
if(killer_mob) {
|
||||
oos = killer_mob->GetOwnerOrSelf();
|
||||
|
||||
char buffer[48] = { 0 };
|
||||
snprintf(buffer, 47, "%d %d %d %d", killerMob ? killerMob->GetID() : 0, damage, spell, static_cast<int>(attack_skill));
|
||||
snprintf(buffer, 47, "%d %d %d %d", killer_mob ? killer_mob->GetID() : 0, damage, spell, static_cast<int>(attack_skill));
|
||||
if(parse->EventNPC(EVENT_DEATH, this, oos, buffer, 0) != 0)
|
||||
{
|
||||
if(GetHP() < 0) {
|
||||
@ -2026,15 +2026,15 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
|
||||
return false;
|
||||
}
|
||||
|
||||
if(killerMob && killerMob->IsClient() && (spell != SPELL_UNKNOWN) && damage > 0) {
|
||||
if(killer_mob && killer_mob->IsClient() && (spell != SPELL_UNKNOWN) && damage > 0) {
|
||||
char val1[20]={0};
|
||||
entity_list.MessageClose_StringID(this, false, 100, MT_NonMelee, HIT_NON_MELEE,
|
||||
killerMob->GetCleanName(), GetCleanName(), ConvertArray(damage, val1));
|
||||
killer_mob->GetCleanName(), GetCleanName(), ConvertArray(damage, val1));
|
||||
}
|
||||
} else {
|
||||
|
||||
char buffer[48] = { 0 };
|
||||
snprintf(buffer, 47, "%d %d %d %d", killerMob ? killerMob->GetID() : 0, damage, spell, static_cast<int>(attack_skill));
|
||||
snprintf(buffer, 47, "%d %d %d %d", killer_mob ? killer_mob->GetID() : 0, damage, spell, static_cast<int>(attack_skill));
|
||||
if(parse->EventNPC(EVENT_DEATH, this, nullptr, buffer, 0) != 0)
|
||||
{
|
||||
if(GetHP() < 0) {
|
||||
@ -2072,21 +2072,21 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
|
||||
EQApplicationPacket* app= new EQApplicationPacket(OP_Death,sizeof(Death_Struct));
|
||||
Death_Struct* d = (Death_Struct*)app->pBuffer;
|
||||
d->spawn_id = GetID();
|
||||
d->killer_id = killerMob ? killerMob->GetID() : 0;
|
||||
d->killer_id = killer_mob ? killer_mob->GetID() : 0;
|
||||
d->bindzoneid = 0;
|
||||
d->spell_id = spell == SPELL_UNKNOWN ? 0xffffffff : spell;
|
||||
d->attack_skill = SkillDamageTypes[attack_skill];
|
||||
d->damage = damage;
|
||||
app->priority = 6;
|
||||
entity_list.QueueClients(killerMob, app, false);
|
||||
entity_list.QueueClients(killer_mob, app, false);
|
||||
|
||||
if(respawn2) {
|
||||
respawn2->DeathReset(1);
|
||||
}
|
||||
|
||||
if (killerMob) {
|
||||
if (killer_mob) {
|
||||
if(GetClass() != LDON_TREASURE)
|
||||
hate_list.AddEntToHateList(killerMob, damage);
|
||||
hate_list.AddEntToHateList(killer_mob, damage);
|
||||
}
|
||||
|
||||
safe_delete(app);
|
||||
@ -2148,8 +2148,8 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
|
||||
{
|
||||
if(!IsLdonTreasure && MerchantType == 0) {
|
||||
kr->SplitExp((finalxp), this);
|
||||
if(killerMob && (kr->IsRaidMember(killerMob->GetName()) || kr->IsRaidMember(killerMob->GetUltimateOwner()->GetName())))
|
||||
killerMob->TrySpellOnKill(killed_level,spell);
|
||||
if(killer_mob && (kr->IsRaidMember(killer_mob->GetName()) || kr->IsRaidMember(killer_mob->GetUltimateOwner()->GetName())))
|
||||
killer_mob->TrySpellOnKill(killed_level,spell);
|
||||
}
|
||||
/* Send the EVENT_KILLED_MERIT event for all raid members */
|
||||
for (int i = 0; i < MAX_RAID_MEMBERS; i++) {
|
||||
@ -2193,8 +2193,8 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
|
||||
{
|
||||
if(!IsLdonTreasure && MerchantType == 0) {
|
||||
kg->SplitExp((finalxp), this);
|
||||
if(killerMob && (kg->IsGroupMember(killerMob->GetName()) || kg->IsGroupMember(killerMob->GetUltimateOwner()->GetName())))
|
||||
killerMob->TrySpellOnKill(killed_level,spell);
|
||||
if(killer_mob && (kg->IsGroupMember(killer_mob->GetName()) || kg->IsGroupMember(killer_mob->GetUltimateOwner()->GetName())))
|
||||
killer_mob->TrySpellOnKill(killed_level,spell);
|
||||
}
|
||||
/* Send the EVENT_KILLED_MERIT event and update kill tasks
|
||||
* for all group members */
|
||||
@ -2244,8 +2244,8 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
|
||||
if(!GetOwner() || (GetOwner() && !GetOwner()->IsClient()))
|
||||
{
|
||||
give_exp_client->AddEXP((finalxp), conlevel);
|
||||
if(killerMob && (killerMob->GetID() == give_exp_client->GetID() || killerMob->GetUltimateOwner()->GetID() == give_exp_client->GetID()))
|
||||
killerMob->TrySpellOnKill(killed_level,spell);
|
||||
if(killer_mob && (killer_mob->GetID() == give_exp_client->GetID() || killer_mob->GetUltimateOwner()->GetID() == give_exp_client->GetID()))
|
||||
killer_mob->TrySpellOnKill(killed_level,spell);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2393,20 +2393,30 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
|
||||
uint16 emoteid = oos->GetEmoteID();
|
||||
if(emoteid != 0)
|
||||
oos->CastToNPC()->DoNPCEmote(KILLEDNPC, emoteid);
|
||||
killerMob->TrySpellOnKill(killed_level, spell);
|
||||
killer_mob->TrySpellOnKill(killed_level, spell);
|
||||
}
|
||||
}
|
||||
|
||||
WipeHateList();
|
||||
p_depop = true;
|
||||
if(killerMob && killerMob->GetTarget() == this) //we can kill things without having them targeted
|
||||
killerMob->SetTarget(nullptr); //via AE effects and such..
|
||||
if(killer_mob && killer_mob->GetTarget() == this) //we can kill things without having them targeted
|
||||
killer_mob->SetTarget(nullptr); //via AE effects and such..
|
||||
|
||||
entity_list.UpdateFindableNPCState(this, true);
|
||||
|
||||
char buffer[48] = { 0 };
|
||||
snprintf(buffer, 47, "%d %d %d %d", killerMob ? killerMob->GetID() : 0, damage, spell, static_cast<int>(attack_skill));
|
||||
snprintf(buffer, 47, "%d %d %d %d", killer_mob ? killer_mob->GetID() : 0, damage, spell, static_cast<int>(attack_skill));
|
||||
parse->EventNPC(EVENT_DEATH_COMPLETE, this, oos, buffer, 0);
|
||||
|
||||
/* Zone controller process EVENT_DEATH_ZONE (Death events) */
|
||||
if (RuleB(Zone, UseZoneController)) {
|
||||
if (entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID) && this->GetNPCTypeID() != ZONE_CONTROLLER_NPC_ID){
|
||||
char data_pass[100] = { 0 };
|
||||
snprintf(data_pass, 99, "%d %d %d %d %d", killer_mob ? killer_mob->GetID() : 0, damage, spell, static_cast<int>(attack_skill), this->GetNPCTypeID());
|
||||
parse->EventNPC(EVENT_DEATH_ZONE, entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID)->CastToNPC(), nullptr, data_pass, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2422,6 +2432,11 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b
|
||||
hate = 1;
|
||||
}
|
||||
|
||||
if (iYellForHelp)
|
||||
SetPrimaryAggro(true);
|
||||
else
|
||||
SetAssistAggro(true);
|
||||
|
||||
bool wasengaged = IsEngaged();
|
||||
Mob* owner = other->GetOwner();
|
||||
Mob* mypet = this->GetPet();
|
||||
@ -2688,16 +2703,38 @@ uint8 Mob::GetWeaponDamageBonus(const Item_Struct *weapon, bool offhand)
|
||||
}
|
||||
} else {
|
||||
// 2h damage bonus
|
||||
int damage_bonus = 1 + (level - 28) / 3;
|
||||
if (delay <= 27)
|
||||
return 1 + ((level - 28) / 3);
|
||||
else if (delay < 40)
|
||||
return 1 + ((level - 28) / 3) + ((level - 30) / 5);
|
||||
else if (delay < 43)
|
||||
return 2 + ((level - 28) / 3) + ((level - 30) / 5) + ((delay - 40) / 3);
|
||||
else if (delay < 45)
|
||||
return 3 + ((level - 28) / 3) + ((level - 30) / 5) + ((delay - 40) / 3);
|
||||
else if (delay >= 45)
|
||||
return 4 + ((level - 28) / 3) + ((level - 30) / 5) + ((delay - 40) / 3);
|
||||
return damage_bonus + 1;
|
||||
// Client isn't reflecting what the dev quoted, this matches better
|
||||
if (level > 29) {
|
||||
int level_bonus = (level - 30) / 5 + 1;
|
||||
if (level > 50) {
|
||||
level_bonus++;
|
||||
int level_bonus2 = level - 50;
|
||||
if (level > 67)
|
||||
level_bonus2 += 5;
|
||||
else if (level > 59)
|
||||
level_bonus2 += 4;
|
||||
else if (level > 58)
|
||||
level_bonus2 += 3;
|
||||
else if (level > 56)
|
||||
level_bonus2 += 2;
|
||||
else if (level > 54)
|
||||
level_bonus2++;
|
||||
level_bonus += level_bonus2 * delay / 40;
|
||||
}
|
||||
damage_bonus += level_bonus;
|
||||
}
|
||||
if (delay >= 40) {
|
||||
int delay_bonus = (delay - 40) / 3 + 1;
|
||||
if (delay >= 45)
|
||||
delay_bonus += 2;
|
||||
else if (delay >= 43)
|
||||
delay_bonus++;
|
||||
damage_bonus += delay_bonus;
|
||||
}
|
||||
return damage_bonus;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -490,6 +490,7 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAu
|
||||
(item->SkillModValue < 0 && newbon->skillmod[item->SkillModType] > item->SkillModValue))
|
||||
{
|
||||
newbon->skillmod[item->SkillModType] = item->SkillModValue;
|
||||
newbon->skillmodmax[item->SkillModType] = item->SkillModMax;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -679,7 +679,7 @@ public:
|
||||
|
||||
void IncreaseSkill(int skill_id, int value = 1) { if (skill_id <= HIGHEST_SKILL) { m_pp.skills[skill_id] += value; } }
|
||||
void IncreaseLanguageSkill(int skill_id, int value = 1);
|
||||
virtual uint16 GetSkill(SkillUseTypes skill_id) const { if (skill_id <= HIGHEST_SKILL) { return((itembonuses.skillmod[skill_id] > 0) ? m_pp.skills[skill_id] * (100 + itembonuses.skillmod[skill_id]) / 100 : m_pp.skills[skill_id]); } return 0; }
|
||||
virtual uint16 GetSkill(SkillUseTypes skill_id) const {if (skill_id <= HIGHEST_SKILL) {return(itembonuses.skillmod[skill_id] > 0 ? (itembonuses.skillmodmax[skill_id] > 0 ? std::min(m_pp.skills[skill_id] + itembonuses.skillmodmax[skill_id], m_pp.skills[skill_id] * (100 + itembonuses.skillmod[skill_id]) / 100) : m_pp.skills[skill_id] * (100 + itembonuses.skillmod[skill_id]) / 100) : m_pp.skills[skill_id]);} return 0;}
|
||||
uint32 GetRawSkill(SkillUseTypes skill_id) const { if (skill_id <= HIGHEST_SKILL) { return(m_pp.skills[skill_id]); } return 0; }
|
||||
bool HasSkill(SkillUseTypes skill_id) const;
|
||||
bool CanHaveSkill(SkillUseTypes skill_id) const;
|
||||
|
||||
@ -2925,150 +2925,292 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app)
|
||||
return;
|
||||
}
|
||||
|
||||
// Delegate to tradeskill object to perform combine
|
||||
AugmentItem_Struct* in_augment = (AugmentItem_Struct*)app->pBuffer;
|
||||
bool deleteItems = false;
|
||||
if (GetClientVersion() >= ClientVersion::RoF)
|
||||
{
|
||||
ItemInst *itemOneToPush = nullptr, *itemTwoToPush = nullptr;
|
||||
|
||||
//Message(15, "%i %i %i %i %i %i", in_augment->container_slot, in_augment->augment_slot, in_augment->container_index, in_augment->augment_index, in_augment->augment_action, in_augment->dest_inst_id);
|
||||
//Log.Out(Logs::DebugLevel::Moderate, Logs::Debug, "cslot: %i aslot: %i cidx: %i aidx: %i act: %i dest: %i",
|
||||
// in_augment->container_slot, in_augment->augment_slot, in_augment->container_index, in_augment->augment_index, in_augment->augment_action, in_augment->dest_inst_id);
|
||||
|
||||
// Adding augment
|
||||
if (in_augment->augment_action == 0)
|
||||
ItemInst *tobe_auged = nullptr, *old_aug = nullptr, *new_aug = nullptr, *aug = nullptr, *solvent = nullptr;
|
||||
Inventory& user_inv = GetInv();
|
||||
|
||||
uint16 item_slot = in_augment->container_slot;
|
||||
uint16 solvent_slot = in_augment->augment_slot;
|
||||
uint8 mat = Inventory::CalcMaterialFromSlot(item_slot); // for when player is augging a piece of equipment while they're wearing it
|
||||
|
||||
if (item_slot == INVALID_INDEX || solvent_slot == INVALID_INDEX)
|
||||
{
|
||||
ItemInst *tobe_auged = nullptr, *auged_with = nullptr;
|
||||
int8 slot = -1;
|
||||
Inventory& user_inv = GetInv();
|
||||
Message(13, "Error: Invalid Aug Index.");
|
||||
return;
|
||||
}
|
||||
|
||||
uint16 slot_id = in_augment->container_slot;
|
||||
uint16 aug_slot_id = in_augment->augment_slot;
|
||||
if (slot_id == INVALID_INDEX || aug_slot_id == INVALID_INDEX)
|
||||
tobe_auged = user_inv.GetItem(item_slot);
|
||||
solvent = user_inv.GetItem(solvent_slot);
|
||||
|
||||
if (!tobe_auged)
|
||||
{
|
||||
Message(13, "Error: Invalid item passed for augmenting.");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((in_augment->augment_action == 1) || (in_augment->augment_action == 2))
|
||||
{
|
||||
// Check for valid distiller if safely removing / swapping an augmentation
|
||||
|
||||
if (!solvent)
|
||||
{
|
||||
Message(13, "Error: Invalid Aug Index.");
|
||||
Log.Out(Logs::General, Logs::Error, "Player tried to safely remove an augment without a distiller.");
|
||||
Message(13, "Error: Missing an augmentation distiller for safely removing this augment.");
|
||||
return;
|
||||
}
|
||||
|
||||
tobe_auged = user_inv.GetItem(slot_id);
|
||||
auged_with = user_inv.GetItem(MainCursor);
|
||||
|
||||
if (tobe_auged && auged_with)
|
||||
else if (solvent->GetItem()->ItemType == ItemUseTypes::ItemTypeAugmentationDistiller)
|
||||
{
|
||||
if (((tobe_auged->IsAugmentSlotAvailable(auged_with->GetAugmentType(), in_augment->augment_index)) != -1) &&
|
||||
(tobe_auged->AvailableWearSlot(auged_with->GetItem()->Slots)))
|
||||
old_aug = tobe_auged->GetAugment(in_augment->augment_index);
|
||||
|
||||
if (!old_aug)
|
||||
{
|
||||
tobe_auged->PutAugment(in_augment->augment_index, *auged_with);
|
||||
tobe_auged->UpdateOrnamentationInfo();
|
||||
Log.Out(Logs::General, Logs::Error, "Player tried to safely remove a nonexistent augment.");
|
||||
Message(13, "Error: No augment found in slot %i for safely removing.", in_augment->augment_index);
|
||||
return;
|
||||
}
|
||||
else if (solvent->GetItem()->ID != old_aug->GetItem()->AugDistiller)
|
||||
{
|
||||
Log.Out(Logs::General, Logs::Error, "Player tried to safely remove an augment with the wrong distiller (item %u vs expected %u).", solvent->GetItem()->ID, old_aug->GetItem()->AugDistiller);
|
||||
Message(13, "Error: Wrong augmentation distiller for safely removing this augment.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (solvent->GetItem()->ItemType != ItemUseTypes::ItemTypePerfectedAugmentationDistiller)
|
||||
{
|
||||
Log.Out(Logs::General, Logs::Error, "Player tried to safely remove an augment with a non-distiller item.");
|
||||
Message(13, "Error: Invalid augmentation distiller for safely removing this augment.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ItemInst *aug = tobe_auged->GetAugment(in_augment->augment_index);
|
||||
if (aug) {
|
||||
std::vector<EQEmu::Any> args;
|
||||
args.push_back(aug);
|
||||
parse->EventItem(EVENT_AUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args);
|
||||
|
||||
args.assign(1, tobe_auged);
|
||||
parse->EventItem(EVENT_AUGMENT_INSERT, this, aug, nullptr, "", in_augment->augment_index, &args);
|
||||
}
|
||||
else
|
||||
{
|
||||
Message(13, "Error: Could not find augmentation at index %i. Aborting.", in_augment->augment_index);
|
||||
return;
|
||||
}
|
||||
|
||||
itemOneToPush = tobe_auged->Clone();
|
||||
// Must push items after the items in inventory are deleted - necessary due to lore items...
|
||||
if (itemOneToPush)
|
||||
{
|
||||
DeleteItemInInventory(slot_id, 0, true);
|
||||
DeleteItemInInventory(MainCursor, 0, true);
|
||||
|
||||
if (PutItemInInventory(slot_id, *itemOneToPush, true))
|
||||
{
|
||||
CalcBonuses();
|
||||
// Successfully added an augment to the item
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
Message(13, "Error: No available slot for end result. Please free up the augment slot.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Message(13, "Error in cloning item for augment. Aborted.");
|
||||
}
|
||||
switch (in_augment->augment_action)
|
||||
{
|
||||
case 0: // Adding an augment
|
||||
case 2: // Swapping augment
|
||||
new_aug = user_inv.GetItem(MainCursor);
|
||||
|
||||
if (!new_aug) // Shouldn't get the OP code without the augment on the user's cursor, but maybe it's h4x.
|
||||
{
|
||||
Log.Out(Logs::General, Logs::Error, "AugmentItem OpCode with 'Insert' or 'Swap' action received, but no augment on client's cursor.");
|
||||
Message(13, "Error: No augment found on cursor for inserting.");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
Message(13, "Error: No available slot for augment in that item.");
|
||||
if (((tobe_auged->IsAugmentSlotAvailable(new_aug->GetAugmentType(), in_augment->augment_index)) != -1) &&
|
||||
(tobe_auged->AvailableWearSlot(new_aug->GetItem()->Slots)))
|
||||
{
|
||||
old_aug = tobe_auged->RemoveAugment(in_augment->augment_index);
|
||||
if (old_aug)
|
||||
{
|
||||
// An old augment was removed in order to be replaced with the new one (augment_action 2)
|
||||
|
||||
CalcBonuses();
|
||||
|
||||
std::vector<EQEmu::Any> args;
|
||||
args.push_back(old_aug);
|
||||
parse->EventItem(EVENT_UNAUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args);
|
||||
|
||||
args.assign(1, tobe_auged);
|
||||
args.push_back(false);
|
||||
parse->EventItem(EVENT_AUGMENT_REMOVE, this, old_aug, nullptr, "", in_augment->augment_index, &args);
|
||||
}
|
||||
|
||||
tobe_auged->PutAugment(in_augment->augment_index, *new_aug);
|
||||
tobe_auged->UpdateOrnamentationInfo();
|
||||
|
||||
aug = tobe_auged->GetAugment(in_augment->augment_index);
|
||||
if (aug)
|
||||
{
|
||||
std::vector<EQEmu::Any> args;
|
||||
args.push_back(aug);
|
||||
parse->EventItem(EVENT_AUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args);
|
||||
|
||||
args.assign(1, tobe_auged);
|
||||
parse->EventItem(EVENT_AUGMENT_INSERT, this, aug, nullptr, "", in_augment->augment_index, &args);
|
||||
}
|
||||
else
|
||||
{
|
||||
Message(13, "Error: Could not properly insert augmentation into augment slot %i. Aborting.", in_augment->augment_index);
|
||||
return;
|
||||
}
|
||||
|
||||
itemOneToPush = tobe_auged->Clone();
|
||||
if (old_aug)
|
||||
{
|
||||
itemTwoToPush = old_aug->Clone();
|
||||
}
|
||||
|
||||
// Must push items after the items in inventory are deleted - necessary due to lore items...
|
||||
if (itemOneToPush)
|
||||
{
|
||||
DeleteItemInInventory(item_slot, 0, true);
|
||||
DeleteItemInInventory(MainCursor, new_aug->IsStackable() ? 1 : 0, true);
|
||||
|
||||
if (solvent)
|
||||
{
|
||||
// Consume the augment distiller
|
||||
DeleteItemInInventory(solvent_slot, solvent->IsStackable() ? 1 : 0, true);
|
||||
}
|
||||
|
||||
if (itemTwoToPush)
|
||||
{
|
||||
// This is a swap. Return the old aug to the player's cursor.
|
||||
if (!PutItemInInventory(MainCursor, *itemTwoToPush, true))
|
||||
{
|
||||
Log.Out(Logs::General, Logs::Error, "Problem returning old augment to player's cursor after augmentation swap.");
|
||||
Message(15, "Error: Failed to retrieve old augment after augmentation swap!");
|
||||
}
|
||||
}
|
||||
|
||||
if (PutItemInInventory(item_slot, *itemOneToPush, true))
|
||||
{
|
||||
// Successfully added an augment to the item
|
||||
|
||||
CalcBonuses();
|
||||
|
||||
if (mat != _MaterialInvalid)
|
||||
{
|
||||
SendWearChange(mat); // Visible item augged while equipped. Send WC in case ornamentation changed.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Message(13, "Error: No available slot for end result. Please free up the augment slot.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Message(13, "Error in cloning item for augment. Aborted.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Message(13, "Error: No available slot for augment in that item.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (in_augment->augment_action == 1)
|
||||
{
|
||||
ItemInst *tobe_auged = nullptr, *auged_with = nullptr;
|
||||
int8 slot = -1;
|
||||
Inventory& user_inv = GetInv();
|
||||
|
||||
uint16 slot_id = in_augment->container_slot;
|
||||
uint16 aug_slot_id = in_augment->augment_slot; //it's actually solvent slot
|
||||
if (slot_id == INVALID_INDEX || aug_slot_id == INVALID_INDEX)
|
||||
{
|
||||
Message(13, "Error: Invalid Aug Index.");
|
||||
return;
|
||||
}
|
||||
|
||||
tobe_auged = user_inv.GetItem(slot_id);
|
||||
auged_with = user_inv.GetItem(aug_slot_id);
|
||||
|
||||
ItemInst *old_aug = nullptr;
|
||||
if (!auged_with)
|
||||
return;
|
||||
const uint32 id = auged_with->GetID();
|
||||
ItemInst *aug = tobe_auged->GetAugment(in_augment->augment_index);
|
||||
if (aug) {
|
||||
std::vector<EQEmu::Any> args;
|
||||
args.push_back(aug);
|
||||
parse->EventItem(EVENT_UNAUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args);
|
||||
|
||||
args.assign(1, tobe_auged);
|
||||
|
||||
args.push_back(false);
|
||||
|
||||
parse->EventItem(EVENT_AUGMENT_REMOVE, this, aug, nullptr, "", in_augment->augment_index, &args);
|
||||
}
|
||||
else
|
||||
{
|
||||
Message(13, "Error: Could not find augmentation at index %i. Aborting.");
|
||||
return;
|
||||
}
|
||||
old_aug = tobe_auged->RemoveAugment(in_augment->augment_index);
|
||||
tobe_auged->UpdateOrnamentationInfo();
|
||||
|
||||
itemOneToPush = tobe_auged->Clone();
|
||||
if (old_aug)
|
||||
itemTwoToPush = old_aug->Clone();
|
||||
if (itemOneToPush && itemTwoToPush && auged_with)
|
||||
{
|
||||
DeleteItemInInventory(slot_id, 0, true);
|
||||
DeleteItemInInventory(aug_slot_id, auged_with->IsStackable() ? 1 : 0, true);
|
||||
|
||||
if (!PutItemInInventory(slot_id, *itemOneToPush, true))
|
||||
break;
|
||||
case 1: // Removing augment safely (distiller)
|
||||
aug = tobe_auged->GetAugment(in_augment->augment_index);
|
||||
if (aug)
|
||||
{
|
||||
Message(15, "Failed to remove augment properly!");
|
||||
std::vector<EQEmu::Any> args;
|
||||
args.push_back(aug);
|
||||
parse->EventItem(EVENT_UNAUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args);
|
||||
|
||||
args.assign(1, tobe_auged);
|
||||
|
||||
args.push_back(false);
|
||||
|
||||
parse->EventItem(EVENT_AUGMENT_REMOVE, this, aug, nullptr, "", in_augment->augment_index, &args);
|
||||
}
|
||||
|
||||
if (PutItemInInventory(MainCursor, *itemTwoToPush, true))
|
||||
else
|
||||
{
|
||||
Message(13, "Error: Could not find augmentation to remove at index %i. Aborting.", in_augment->augment_index);
|
||||
return;
|
||||
}
|
||||
|
||||
old_aug = tobe_auged->RemoveAugment(in_augment->augment_index);
|
||||
tobe_auged->UpdateOrnamentationInfo();
|
||||
|
||||
itemOneToPush = tobe_auged->Clone();
|
||||
if (old_aug)
|
||||
itemTwoToPush = old_aug->Clone();
|
||||
|
||||
if (itemOneToPush && itemTwoToPush)
|
||||
{
|
||||
// Consume the augment distiller
|
||||
DeleteItemInInventory(solvent_slot, solvent->IsStackable() ? 1 : 0, true);
|
||||
|
||||
// Remove the augmented item
|
||||
DeleteItemInInventory(item_slot, 0, true);
|
||||
|
||||
// Replace it with the unaugmented item
|
||||
if (!PutItemInInventory(item_slot, *itemOneToPush, true))
|
||||
{
|
||||
Log.Out(Logs::General, Logs::Error, "Problem returning equipment item to player's inventory after safe augment removal.");
|
||||
Message(15, "Error: Failed to return item after de-augmentation!");
|
||||
}
|
||||
|
||||
CalcBonuses();
|
||||
//Message(15, "Successfully removed an augmentation!");
|
||||
|
||||
if (mat != _MaterialInvalid)
|
||||
{
|
||||
SendWearChange(mat); // Visible item augged while equipped. Send WC in case ornamentation changed.
|
||||
}
|
||||
|
||||
// Drop the removed augment on the player's cursor
|
||||
if (!PutItemInInventory(MainCursor, *itemTwoToPush, true))
|
||||
{
|
||||
Log.Out(Logs::General, Logs::Error, "Problem returning augment to player's cursor after safe removal.");
|
||||
Message(15, "Error: Failed to return augment after removal from item!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3: // Destroying augment (formerly done in birdbath/sealer with a solvent)
|
||||
|
||||
// RoF client does not require an augmentation solvent for destroying an augmentation in an item.
|
||||
// Augments can be destroyed with a right click -> Destroy at any time.
|
||||
|
||||
aug = tobe_auged->GetAugment(in_augment->augment_index);
|
||||
if (aug)
|
||||
{
|
||||
std::vector<EQEmu::Any> args;
|
||||
args.push_back(aug);
|
||||
parse->EventItem(EVENT_UNAUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args);
|
||||
|
||||
args.assign(1, tobe_auged);
|
||||
|
||||
args.push_back(true);
|
||||
|
||||
parse->EventItem(EVENT_AUGMENT_REMOVE, this, aug, nullptr, "", in_augment->augment_index, &args);
|
||||
}
|
||||
else
|
||||
{
|
||||
Message(13, "Error: Could not find augmentation to remove at index %i. Aborting.");
|
||||
return;
|
||||
}
|
||||
|
||||
tobe_auged->DeleteAugment(in_augment->augment_index);
|
||||
tobe_auged->UpdateOrnamentationInfo();
|
||||
|
||||
itemOneToPush = tobe_auged->Clone();
|
||||
if (itemOneToPush)
|
||||
{
|
||||
DeleteItemInInventory(item_slot, 0, true);
|
||||
|
||||
if (!PutItemInInventory(item_slot, *itemOneToPush, true))
|
||||
{
|
||||
Log.Out(Logs::General, Logs::Error, "Problem returning equipment item to player's inventory after augment deletion.");
|
||||
Message(15, "Error: Failed to return item after destroying augment!");
|
||||
}
|
||||
}
|
||||
|
||||
CalcBonuses();
|
||||
|
||||
if (mat != _MaterialInvalid)
|
||||
{
|
||||
SendWearChange(mat);
|
||||
}
|
||||
break;
|
||||
default: // Unknown
|
||||
Log.Out(Logs::General, Logs::Inventory, "Unrecognized augmentation action - cslot: %i aslot: %i cidx: %i aidx: %i act: %i dest: %i",
|
||||
in_augment->container_slot, in_augment->augment_slot, in_augment->container_index, in_augment->augment_index, in_augment->augment_action, in_augment->dest_inst_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Delegate to tradeskill object to perform combine
|
||||
Object::HandleAugmentation(this, in_augment, m_tradeskill_object);
|
||||
}
|
||||
return;
|
||||
|
||||
@ -278,6 +278,7 @@ struct StatBonuses {
|
||||
float AggroRange; // when calculate just replace original value with this
|
||||
float AssistRange;
|
||||
int32 skillmod[HIGHEST_SKILL+1];
|
||||
int32 skillmodmax[HIGHEST_SKILL+1];
|
||||
int effective_casting_level;
|
||||
int reflect_chance; // chance to reflect incoming spell
|
||||
uint32 singingMod;
|
||||
|
||||
@ -114,7 +114,9 @@ const char *QuestEventSubroutines[_LargestEventID] = {
|
||||
"EVENT_RESPAWN",
|
||||
"EVENT_DEATH_COMPLETE",
|
||||
"EVENT_UNHANDLED_OPCODE",
|
||||
"EVENT_TICK"
|
||||
"EVENT_TICK",
|
||||
"EVENT_SPAWN_ZONE",
|
||||
"EVENT_DEATH_ZONE",
|
||||
};
|
||||
|
||||
PerlembParser::PerlembParser() : perl(nullptr) {
|
||||
@ -1424,6 +1426,21 @@ void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID
|
||||
ExportVar(package_name.c_str(), "slotid", extradata);
|
||||
break;
|
||||
}
|
||||
case EVENT_SPAWN_ZONE: {
|
||||
Seperator sep(data);
|
||||
ExportVar(package_name.c_str(), "spawned_entity_id", sep.arg[0]);
|
||||
ExportVar(package_name.c_str(), "spawned_npc_id", sep.arg[1]);
|
||||
break;
|
||||
}
|
||||
case EVENT_DEATH_ZONE: {
|
||||
Seperator sep(data);
|
||||
ExportVar(package_name.c_str(), "killer_id", sep.arg[0]);
|
||||
ExportVar(package_name.c_str(), "killer_damage", sep.arg[1]);
|
||||
ExportVar(package_name.c_str(), "killer_spell", sep.arg[2]);
|
||||
ExportVar(package_name.c_str(), "killer_skill", sep.arg[3]);
|
||||
ExportVar(package_name.c_str(), "killed_npc_id", sep.arg[4]);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
break;
|
||||
|
||||
@ -2919,6 +2919,29 @@ XS(XS__UpdateInstanceTimer) {
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS__GetInstanceTimer);
|
||||
XS(XS__GetInstanceTimer) {
|
||||
dXSARGS;
|
||||
if (items != 0)
|
||||
Perl_croak(aTHX_ "Usage: GetInstanceTimer()");
|
||||
|
||||
uint32 timer = quest_manager.GetInstanceTimer();
|
||||
|
||||
XSRETURN_UV(timer);
|
||||
}
|
||||
|
||||
XS(XS__GetInstanceTimerByID);
|
||||
XS(XS__GetInstanceTimerByID) {
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: GetInstanceTimerByID(instance_id)");
|
||||
|
||||
uint16 instance_id = (uint16)SvUV(ST(0));
|
||||
uint32 timer = quest_manager.GetInstanceTimerByID(instance_id);
|
||||
|
||||
XSRETURN_UV(timer);
|
||||
}
|
||||
|
||||
XS(XS__GetInstanceID);
|
||||
XS(XS__GetInstanceID) {
|
||||
dXSARGS;
|
||||
@ -3614,6 +3637,19 @@ XS(XS__debug)
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS__UpdateZoneHeader);
|
||||
XS(XS__UpdateZoneHeader) {
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: UpdateZoneHeader(type, value)");
|
||||
|
||||
std::string type = (std::string)SvPV_nolen(ST(0));
|
||||
std::string value = (std::string)SvPV_nolen(ST(1));
|
||||
quest_manager.UpdateZoneHeader(type, value);
|
||||
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
This is the callback perl will look for to setup the
|
||||
@ -3650,6 +3686,8 @@ EXTERN_C XS(boot_quest)
|
||||
newXS(strcpy(buf, "CreateInstance"), XS__CreateInstance, file);
|
||||
newXS(strcpy(buf, "DestroyInstance"), XS__DestroyInstance, file);
|
||||
newXS(strcpy(buf, "UpdateInstanceTimer"), XS__UpdateInstanceTimer, file);
|
||||
newXS(strcpy(buf, "GetInstanceTimer"), XS__GetInstanceTimer, file);
|
||||
newXS(strcpy(buf, "GetInstanceTimerByID"), XS__GetInstanceTimerByID, file);
|
||||
newXS(strcpy(buf, "FlagInstanceByGroupLeader"), XS__FlagInstanceByGroupLeader, file);
|
||||
newXS(strcpy(buf, "FlagInstanceByRaidLeader"), XS__FlagInstanceByRaidLeader, file);
|
||||
newXS(strcpy(buf, "FlyMode"), XS__FlyMode, file);
|
||||
@ -3841,6 +3879,7 @@ EXTERN_C XS(boot_quest)
|
||||
newXS(strcpy(buf, "untraindiscs"), XS__untraindiscs, file);
|
||||
newXS(strcpy(buf, "updatespawntimer"), XS__UpdateSpawnTimer, file);
|
||||
newXS(strcpy(buf, "updatetaskactivity"), XS__updatetaskactivity, file);
|
||||
newXS(strcpy(buf, "UpdateZoneHeader"), XS__UpdateZoneHeader, file);
|
||||
newXS(strcpy(buf, "varlink"), XS__varlink, file);
|
||||
newXS(strcpy(buf, "voicetell"), XS__voicetell, file);
|
||||
newXS(strcpy(buf, "we"), XS__we, file);
|
||||
|
||||
@ -641,8 +641,18 @@ void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue)
|
||||
{
|
||||
npc->SetID(GetFreeID());
|
||||
npc->SetMerchantProbability((uint8) zone->random.Int(0, 99));
|
||||
|
||||
parse->EventNPC(EVENT_SPAWN, npc, nullptr, "", 0);
|
||||
|
||||
/* Zone controller process EVENT_SPAWN_ZONE */
|
||||
if (RuleB(Zone, UseZoneController)) {
|
||||
if (entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID) && npc->GetNPCTypeID() != ZONE_CONTROLLER_NPC_ID){
|
||||
char data_pass[100] = { 0 };
|
||||
snprintf(data_pass, 99, "%d %d", npc->GetID(), npc->GetNPCTypeID());
|
||||
parse->EventNPC(EVENT_SPAWN_ZONE, entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID)->CastToNPC(), nullptr, data_pass, 0);
|
||||
}
|
||||
}
|
||||
|
||||
uint16 emoteid = npc->GetEmoteID();
|
||||
if (emoteid != 0)
|
||||
npc->DoNPCEmote(ONSPAWN, emoteid);
|
||||
|
||||
@ -83,7 +83,8 @@ typedef enum {
|
||||
EVENT_DEATH_COMPLETE,
|
||||
EVENT_UNHANDLED_OPCODE,
|
||||
EVENT_TICK,
|
||||
|
||||
EVENT_SPAWN_ZONE,
|
||||
EVENT_DEATH_ZONE,
|
||||
_LargestEventID
|
||||
} QuestEventID;
|
||||
|
||||
|
||||
@ -808,6 +808,14 @@ void lua_update_instance_timer(uint16 instance_id, uint32 new_duration) {
|
||||
quest_manager.UpdateInstanceTimer(instance_id, new_duration);
|
||||
}
|
||||
|
||||
uint32 lua_get_instance_timer() {
|
||||
return quest_manager.GetInstanceTimer();
|
||||
}
|
||||
|
||||
uint32 lua_get_instance_timer_by_id(uint16 instance_id) {
|
||||
return quest_manager.GetInstanceTimerByID(instance_id);
|
||||
}
|
||||
|
||||
int lua_get_instance_id(const char *zone, uint32 version) {
|
||||
return quest_manager.GetInstanceID(zone, version);
|
||||
}
|
||||
@ -1296,6 +1304,10 @@ void lua_debug(std::string message, int level) {
|
||||
Log.Out(static_cast<Logs::DebugLevel>(level), Logs::QuestDebug, message);
|
||||
}
|
||||
|
||||
void lua_update_zone_header(std::string type, std::string value) {
|
||||
quest_manager.UpdateZoneHeader(type, value);
|
||||
}
|
||||
|
||||
#define LuaCreateNPCParse(name, c_type, default_value) do { \
|
||||
cur = table[#name]; \
|
||||
if(luabind::type(cur) != LUA_TNIL) { \
|
||||
@ -1719,7 +1731,9 @@ luabind::scope lua_register_events() {
|
||||
luabind::value("leave_area", static_cast<int>(EVENT_LEAVE_AREA)),
|
||||
luabind::value("death_complete", static_cast<int>(EVENT_DEATH_COMPLETE)),
|
||||
luabind::value("unhandled_opcode", static_cast<int>(EVENT_UNHANDLED_OPCODE)),
|
||||
luabind::value("tick", static_cast<int>(EVENT_TICK))
|
||||
luabind::value("tick", static_cast<int>(EVENT_TICK)),
|
||||
luabind::value("spawn_zone", static_cast<int>(EVENT_SPAWN_ZONE)),
|
||||
luabind::value("death_zone", static_cast<int>(EVENT_DEATH_ZONE))
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
122
zone/lua_mob.cpp
122
zone/lua_mob.cpp
@ -1881,6 +1881,106 @@ bool Lua_Mob::IsBlind() {
|
||||
return self->IsBlind();
|
||||
}
|
||||
|
||||
uint8 Lua_Mob::SeeInvisible() {
|
||||
Lua_Safe_Call_Int();
|
||||
return self->SeeInvisible();
|
||||
}
|
||||
|
||||
bool Lua_Mob::SeeInvisibleUndead() {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->SeeInvisibleUndead();
|
||||
}
|
||||
|
||||
bool Lua_Mob::SeeHide() {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->SeeHide();
|
||||
}
|
||||
|
||||
bool Lua_Mob::SeeImprovedHide() {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->SeeImprovedHide();
|
||||
}
|
||||
|
||||
uint8 Lua_Mob::GetNimbusEffect1() {
|
||||
Lua_Safe_Call_Int();
|
||||
return self->GetNimbusEffect1();
|
||||
}
|
||||
|
||||
uint8 Lua_Mob::GetNimbusEffect2() {
|
||||
Lua_Safe_Call_Int();
|
||||
return self->GetNimbusEffect2();
|
||||
}
|
||||
|
||||
uint8 Lua_Mob::GetNimbusEffect3() {
|
||||
Lua_Safe_Call_Int();
|
||||
return self->GetNimbusEffect3();
|
||||
}
|
||||
|
||||
bool Lua_Mob::IsTargetable() {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->IsTargetable();
|
||||
}
|
||||
|
||||
bool Lua_Mob::HasShieldEquiped() {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->HasShieldEquiped();
|
||||
}
|
||||
|
||||
bool Lua_Mob::HasTwoHandBluntEquiped() {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->HasTwoHandBluntEquiped();
|
||||
}
|
||||
|
||||
bool Lua_Mob::HasTwoHanderEquipped() {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->HasTwoHanderEquipped();
|
||||
}
|
||||
|
||||
uint32 Lua_Mob::GetHerosForgeModel(uint8 material_slot) {
|
||||
Lua_Safe_Call_Int();
|
||||
return self->GetHerosForgeModel(material_slot);
|
||||
}
|
||||
|
||||
uint32 Lua_Mob::IsEliteMaterialItem(uint8 material_slot) {
|
||||
Lua_Safe_Call_Int();
|
||||
return self->IsEliteMaterialItem(material_slot);
|
||||
}
|
||||
|
||||
float Lua_Mob::GetBaseSize() {
|
||||
Lua_Safe_Call_Real();
|
||||
return self->GetBaseSize();
|
||||
}
|
||||
|
||||
bool Lua_Mob::HasOwner() {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->HasOwner();
|
||||
}
|
||||
|
||||
bool Lua_Mob::IsPet() {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->IsPet();
|
||||
}
|
||||
|
||||
bool Lua_Mob::HasPet() {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->HasPet();
|
||||
}
|
||||
|
||||
bool Lua_Mob::IsSilenced() {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->IsSilenced();
|
||||
}
|
||||
|
||||
bool Lua_Mob::IsAmnesiad() {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->IsAmnesiad();
|
||||
}
|
||||
|
||||
int32 Lua_Mob::GetMeleeMitigation() {
|
||||
Lua_Safe_Call_Int();
|
||||
return self->GetMeleeMitigation();
|
||||
}
|
||||
|
||||
luabind::scope lua_register_mob() {
|
||||
return luabind::class_<Lua_Mob, Lua_Entity>("Mob")
|
||||
.def(luabind::constructor<>())
|
||||
@ -2203,7 +2303,27 @@ luabind::scope lua_register_mob() {
|
||||
.def("BuffFadeBySlot", (void(Lua_Mob::*)(int,bool))&Lua_Mob::BuffFadeBySlot)
|
||||
.def("CanBuffStack", (int(Lua_Mob::*)(int,int))&Lua_Mob::CanBuffStack)
|
||||
.def("CanBuffStack", (int(Lua_Mob::*)(int,int,bool))&Lua_Mob::CanBuffStack)
|
||||
.def("SetPseudoRoot", (void(Lua_Mob::*)(bool))&Lua_Mob::SetPseudoRoot);
|
||||
.def("SetPseudoRoot", (void(Lua_Mob::*)(bool))&Lua_Mob::SetPseudoRoot)
|
||||
.def("SeeInvisible", (uint8(Lua_Mob::*)(void))&Lua_Mob::SeeInvisible)
|
||||
.def("SeeInvisibleUndead", (bool(Lua_Mob::*)(void))&Lua_Mob::SeeInvisibleUndead)
|
||||
.def("SeeHide", (bool(Lua_Mob::*)(void))&Lua_Mob::SeeHide)
|
||||
.def("SeeImprovedHide", (bool(Lua_Mob::*)(bool))&Lua_Mob::SeeImprovedHide)
|
||||
.def("GetNimbusEffect1", (uint8(Lua_Mob::*)(void))&Lua_Mob::GetNimbusEffect1)
|
||||
.def("GetNimbusEffect2", (uint8(Lua_Mob::*)(void))&Lua_Mob::GetNimbusEffect2)
|
||||
.def("GetNimbusEffect3", (uint8(Lua_Mob::*)(void))&Lua_Mob::GetNimbusEffect3)
|
||||
.def("IsTargetable", (bool(Lua_Mob::*)(void))&Lua_Mob::IsTargetable)
|
||||
.def("HasShieldEquiped", (bool(Lua_Mob::*)(void))&Lua_Mob::HasShieldEquiped)
|
||||
.def("HasTwoHandBluntEquiped", (bool(Lua_Mob::*)(void))&Lua_Mob::HasTwoHandBluntEquiped)
|
||||
.def("HasTwoHanderEquipped", (bool(Lua_Mob::*)(void))&Lua_Mob::HasTwoHanderEquipped)
|
||||
.def("GetHerosForgeModel", (int32(Lua_Mob::*)(uint8))&Lua_Mob::GetHerosForgeModel)
|
||||
.def("IsEliteMaterialItem", (uint32(Lua_Mob::*)(uint8))&Lua_Mob::IsEliteMaterialItem)
|
||||
.def("GetBaseSize", (double(Lua_Mob::*)(void))&Lua_Mob::GetBaseSize)
|
||||
.def("HasOwner", (bool(Lua_Mob::*)(void))&Lua_Mob::HasOwner)
|
||||
.def("IsPet", (bool(Lua_Mob::*)(void))&Lua_Mob::IsPet)
|
||||
.def("HasPet", (bool(Lua_Mob::*)(void))&Lua_Mob::HasPet)
|
||||
.def("IsSilenced", (bool(Lua_Mob::*)(void))&Lua_Mob::IsSilenced)
|
||||
.def("IsAmnesiad", (bool(Lua_Mob::*)(void))&Lua_Mob::IsAmnesiad)
|
||||
.def("GetMeleeMitigation", (int32(Lua_Mob::*)(void))&Lua_Mob::GetMeleeMitigation);
|
||||
}
|
||||
|
||||
luabind::scope lua_register_special_abilities() {
|
||||
|
||||
@ -358,6 +358,26 @@ public:
|
||||
int CanBuffStack(int spell_id, int caster_level);
|
||||
int CanBuffStack(int spell_id, int caster_level, bool fail_if_overwrite);
|
||||
void SetPseudoRoot(bool in);
|
||||
uint8 SeeInvisible();
|
||||
bool SeeInvisibleUndead();
|
||||
bool SeeHide();
|
||||
bool SeeImprovedHide();
|
||||
uint8 GetNimbusEffect1();
|
||||
uint8 GetNimbusEffect2();
|
||||
uint8 GetNimbusEffect3();
|
||||
bool IsTargetable();
|
||||
bool HasShieldEquiped();
|
||||
bool HasTwoHandBluntEquiped();
|
||||
bool HasTwoHanderEquipped();
|
||||
uint32 GetHerosForgeModel(uint8 material_slot);
|
||||
uint32 IsEliteMaterialItem(uint8 material_slot);
|
||||
float GetBaseSize();
|
||||
bool HasOwner();
|
||||
bool IsPet();
|
||||
bool HasPet();
|
||||
bool IsSilenced();
|
||||
bool IsAmnesiad();
|
||||
int32 GetMeleeMitigation();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -117,7 +117,9 @@ const char *LuaEvents[_LargestEventID] = {
|
||||
"event_respawn",
|
||||
"event_death_complete",
|
||||
"event_unhandled_opcode",
|
||||
"event_tick"
|
||||
"event_tick",
|
||||
"event_spawn_zone",
|
||||
"event_death_zone"
|
||||
};
|
||||
|
||||
extern Zone *zone;
|
||||
|
||||
13
zone/mob.cpp
13
zone/mob.cpp
@ -433,6 +433,9 @@ Mob::Mob(const char* in_name,
|
||||
|
||||
emoteid = 0;
|
||||
endur_upkeep = false;
|
||||
PrimaryAggro = false;
|
||||
AssistAggro = false;
|
||||
npc_assist_cap = 0;
|
||||
}
|
||||
|
||||
Mob::~Mob()
|
||||
@ -2693,6 +2696,8 @@ bool Mob::RemoveFromHateList(Mob* mob)
|
||||
{
|
||||
AI_Event_NoLongerEngaged();
|
||||
zone->DelAggroMob();
|
||||
if (IsNPC() && !RuleB(Aggro, AllowTickPulling))
|
||||
ResetAssistCap();
|
||||
}
|
||||
}
|
||||
if(GetTarget() == mob)
|
||||
@ -5677,3 +5682,11 @@ void Mob::SetCurrentSpeed(int in){
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32 Mob::GetMeleeMitigation() {
|
||||
int32 mitigation = 0;
|
||||
mitigation += spellbonuses.MeleeMitigationEffect;
|
||||
mitigation += itembonuses.MeleeMitigationEffect;
|
||||
mitigation += aabonuses.MeleeMitigationEffect;
|
||||
return mitigation;
|
||||
}
|
||||
15
zone/mob.h
15
zone/mob.h
@ -504,6 +504,10 @@ public:
|
||||
Mob* GetHateRandom() { return hate_list.GetRandomEntOnHateList();}
|
||||
Mob* GetHateMost() { return hate_list.GetEntWithMostHateOnList();}
|
||||
bool IsEngaged() { return(!hate_list.IsHateListEmpty()); }
|
||||
bool HasPrimaryAggro() { return PrimaryAggro; }
|
||||
bool HasAssistAggro() { return AssistAggro; }
|
||||
void SetPrimaryAggro(bool value) { PrimaryAggro = value; if (value) AssistAggro = false; }
|
||||
void SetAssistAggro(bool value) { AssistAggro = value; if (PrimaryAggro) AssistAggro = false; }
|
||||
bool HateSummon();
|
||||
void FaceTarget(Mob* MobToFace = 0);
|
||||
void SetHeading(float iHeading) { if(m_Position.w != iHeading) { pLastChange = Timer::GetCurrentTime();
|
||||
@ -748,6 +752,7 @@ public:
|
||||
inline bool GetInvul(void) { return invulnerable; }
|
||||
inline void SetExtraHaste(int Haste) { ExtraHaste = Haste; }
|
||||
virtual int GetHaste();
|
||||
int32 GetMeleeMitigation();
|
||||
|
||||
uint8 GetWeaponDamageBonus(const Item_Struct* weapon, bool offhand = false);
|
||||
uint16 GetDamageTable(SkillUseTypes skillinuse);
|
||||
@ -993,6 +998,11 @@ public:
|
||||
void ApplyAABonuses(const AA::Rank &rank, StatBonuses* newbon);
|
||||
bool CheckAATimer(int timer);
|
||||
|
||||
int NPCAssistCap() { return npc_assist_cap; }
|
||||
void AddAssistCap() { ++npc_assist_cap; }
|
||||
void DelAssistCap() { --npc_assist_cap; }
|
||||
void ResetAssistCap() { npc_assist_cap = 0; }
|
||||
|
||||
protected:
|
||||
void CommonDamage(Mob* other, int32 &damage, const uint16 spell_id, const SkillUseTypes attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic, int special = 0);
|
||||
static uint16 GetProcID(uint16 spell_id, uint8 effect_index);
|
||||
@ -1293,6 +1303,11 @@ protected:
|
||||
glm::vec4 m_CurrentWayPoint;
|
||||
int cur_wp_pause;
|
||||
|
||||
bool PrimaryAggro;
|
||||
bool AssistAggro;
|
||||
int npc_assist_cap;
|
||||
Timer assist_cap_timer; // clear assist cap so more nearby mobs can be called for help
|
||||
|
||||
|
||||
int patrol;
|
||||
glm::vec3 m_FearWalkTarget;
|
||||
|
||||
@ -1735,8 +1735,10 @@ void Mob::AI_Event_Engaged(Mob* attacker, bool iYellForHelp) {
|
||||
if (iYellForHelp) {
|
||||
if(IsPet()) {
|
||||
GetOwner()->AI_Event_Engaged(attacker, iYellForHelp);
|
||||
} else {
|
||||
} else if (!HasAssistAggro() && NPCAssistCap() < RuleI(Combat, NPCAssistCap)) {
|
||||
entity_list.AIYellForHelp(this, attacker);
|
||||
if (NPCAssistCap() > 0 && !assist_cap_timer.Enabled())
|
||||
assist_cap_timer.Start(RuleI(Combat, NPCAssistCapTimer));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1787,6 +1789,8 @@ void Mob::AI_Event_NoLongerEngaged() {
|
||||
|
||||
if(IsNPC())
|
||||
{
|
||||
SetPrimaryAggro(false);
|
||||
SetAssistAggro(false);
|
||||
if(CastToNPC()->GetCombatEvent() && GetHP() > 0)
|
||||
{
|
||||
if(entity_list.GetNPCByID(this->GetID()))
|
||||
|
||||
59
zone/npc.cpp
59
zone/npc.cpp
@ -712,8 +712,18 @@ bool NPC::Process()
|
||||
}
|
||||
|
||||
//Handle assists...
|
||||
if(assist_timer.Check() && IsEngaged() && !Charmed()) {
|
||||
if (assist_cap_timer.Check()) {
|
||||
if (NPCAssistCap() > 0)
|
||||
DelAssistCap();
|
||||
else
|
||||
assist_cap_timer.Disable();
|
||||
}
|
||||
|
||||
if (assist_timer.Check() && IsEngaged() && !Charmed() && !HasAssistAggro() &&
|
||||
NPCAssistCap() < RuleI(Combat, NPCAssistCap)) {
|
||||
entity_list.AIYellForHelp(this, GetTarget());
|
||||
if (NPCAssistCap() > 0 && !assist_cap_timer.Enabled())
|
||||
assist_cap_timer.Start(RuleI(Combat, NPCAssistCapTimer));
|
||||
}
|
||||
|
||||
if(qGlobals)
|
||||
@ -833,6 +843,53 @@ bool NPC::DatabaseCastAccepted(int spell_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NPC::SpawnZoneController(){
|
||||
|
||||
if (!RuleB(Zone, UseZoneController))
|
||||
return false;
|
||||
|
||||
NPCType* npc_type = new NPCType;
|
||||
memset(npc_type, 0, sizeof(NPCType));
|
||||
|
||||
strncpy(npc_type->name, "zone_controller", 60);
|
||||
npc_type->cur_hp = 2000000000;
|
||||
npc_type->max_hp = 2000000000;
|
||||
npc_type->hp_regen = 100000000;
|
||||
npc_type->race = 240;
|
||||
npc_type->gender = 2;
|
||||
npc_type->class_ = 1;
|
||||
npc_type->deity = 1;
|
||||
npc_type->level = 200;
|
||||
npc_type->npc_id = ZONE_CONTROLLER_NPC_ID;
|
||||
npc_type->loottable_id = 0;
|
||||
npc_type->texture = 3;
|
||||
npc_type->runspeed = 0;
|
||||
npc_type->d_melee_texture1 = 0;
|
||||
npc_type->d_melee_texture2 = 0;
|
||||
npc_type->merchanttype = 0;
|
||||
npc_type->bodytype = 11;
|
||||
|
||||
npc_type->prim_melee_type = 28;
|
||||
npc_type->sec_melee_type = 28;
|
||||
|
||||
npc_type->findable = 0;
|
||||
npc_type->trackable = 0;
|
||||
|
||||
strcpy(npc_type->special_abilities, "12,1^13,1^14,1^15,1^16,1^17,1^19,1^22,1^24,1^25,1^28,1^31,1^35,1^39,1^42,1");
|
||||
|
||||
glm::vec4 point;
|
||||
point.x = 5000;
|
||||
point.y = 5000;
|
||||
point.z = -5000;
|
||||
|
||||
NPC* npc = new NPC(npc_type, nullptr, point, FlyMode3);
|
||||
npc->GiveNPCTypeData(npc_type);
|
||||
|
||||
entity_list.AddNPC(npc);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
NPC* NPC::SpawnNPC(const char* spawncommand, const glm::vec4& position, Client* client) {
|
||||
if(spawncommand == 0 || spawncommand[0] == 0) {
|
||||
return 0;
|
||||
|
||||
@ -96,6 +96,7 @@ class NPC : public Mob
|
||||
{
|
||||
public:
|
||||
static NPC* SpawnNPC(const char* spawncommand, const glm::vec4& position, Client* client = nullptr);
|
||||
static bool SpawnZoneController();
|
||||
static int8 GetAILevel(bool iForceReRead = false);
|
||||
|
||||
NPC(const NPCType* data, Spawn2* respawn, const glm::vec4& position, int iflymode, bool IsCorpse = false);
|
||||
|
||||
@ -8490,6 +8490,524 @@ XS(XS_Mob_IsBlind) {
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Mob_SeeInvisible);
|
||||
XS(XS_Mob_SeeInvisible) {
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Mob::SeeInvisible(THIS)");
|
||||
{
|
||||
Mob* THIS;
|
||||
uint8 RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Mob*, tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Mob");
|
||||
|
||||
if (THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->SeeInvisible();
|
||||
XSprePUSH;
|
||||
PUSHu((UV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Mob_SeeInvisibleUndead);
|
||||
XS(XS_Mob_SeeInvisibleUndead) {
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Mob::SeeInvisibleUndead(THIS)");
|
||||
{
|
||||
Mob* THIS;
|
||||
bool RETVAL;
|
||||
if (sv_derived_from(ST(0), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Mob*, tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Mob");
|
||||
|
||||
if (THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->SeeInvisibleUndead();
|
||||
ST(0) = boolSV(RETVAL);
|
||||
sv_2mortal(ST(0));
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Mob_SeeHide);
|
||||
XS(XS_Mob_SeeHide) {
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Mob::SeeHide(THIS)");
|
||||
{
|
||||
Mob* THIS;
|
||||
bool RETVAL;
|
||||
if (sv_derived_from(ST(0), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Mob*, tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Mob");
|
||||
|
||||
if (THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->SeeHide();
|
||||
ST(0) = boolSV(RETVAL);
|
||||
sv_2mortal(ST(0));
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Mob_SeeImprovedHide);
|
||||
XS(XS_Mob_SeeImprovedHide) {
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Mob::SeeImprovedHide(THIS)");
|
||||
{
|
||||
Mob* THIS;
|
||||
bool RETVAL;
|
||||
if (sv_derived_from(ST(0), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Mob*, tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Mob");
|
||||
|
||||
if (THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->SeeImprovedHide();
|
||||
ST(0) = boolSV(RETVAL);
|
||||
sv_2mortal(ST(0));
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Mob_GetNimbusEffect1);
|
||||
XS(XS_Mob_GetNimbusEffect1) {
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Mob::GetNimbusEffect1(THIS)");
|
||||
{
|
||||
Mob* THIS;
|
||||
uint8 RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Mob*, tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Mob");
|
||||
|
||||
if (THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetNimbusEffect1();
|
||||
XSprePUSH;
|
||||
PUSHu((UV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Mob_GetNimbusEffect2);
|
||||
XS(XS_Mob_GetNimbusEffect2) {
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Mob::GetNimbusEffect2(THIS)");
|
||||
{
|
||||
Mob* THIS;
|
||||
uint8 RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Mob*, tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Mob");
|
||||
|
||||
if (THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetNimbusEffect2();
|
||||
XSprePUSH;
|
||||
PUSHu((UV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Mob_GetNimbusEffect3);
|
||||
XS(XS_Mob_GetNimbusEffect3) {
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Mob::GetNimbusEffect3(THIS)");
|
||||
{
|
||||
Mob* THIS;
|
||||
uint8 RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Mob*, tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Mob");
|
||||
|
||||
if (THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetNimbusEffect3();
|
||||
XSprePUSH;
|
||||
PUSHu((UV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Mob_IsTargetable);
|
||||
XS(XS_Mob_IsTargetable) {
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Mob::IsTargetable(THIS)");
|
||||
{
|
||||
Mob* THIS;
|
||||
bool RETVAL;
|
||||
if (sv_derived_from(ST(0), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Mob*, tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Mob");
|
||||
|
||||
if (THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->IsTargetable();
|
||||
ST(0) = boolSV(RETVAL);
|
||||
sv_2mortal(ST(0));
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Mob_HasShieldEquiped);
|
||||
XS(XS_Mob_HasShieldEquiped) {
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Mob::HasShieldEquiped(THIS)");
|
||||
{
|
||||
Mob* THIS;
|
||||
bool RETVAL;
|
||||
if (sv_derived_from(ST(0), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Mob*, tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Mob");
|
||||
|
||||
if (THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->HasShieldEquiped();
|
||||
ST(0) = boolSV(RETVAL);
|
||||
sv_2mortal(ST(0));
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Mob_HasTwoHandBluntEquiped);
|
||||
XS(XS_Mob_HasTwoHandBluntEquiped) {
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Mob::HasTwoHandBluntEquiped(THIS)");
|
||||
{
|
||||
Mob* THIS;
|
||||
bool RETVAL;
|
||||
if (sv_derived_from(ST(0), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Mob*, tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Mob");
|
||||
|
||||
if (THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->HasTwoHandBluntEquiped();
|
||||
ST(0) = boolSV(RETVAL);
|
||||
sv_2mortal(ST(0));
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Mob_HasTwoHanderEquipped);
|
||||
XS(XS_Mob_HasTwoHanderEquipped) {
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Mob::HasTwoHanderEquipped(THIS)");
|
||||
{
|
||||
Mob* THIS;
|
||||
bool RETVAL;
|
||||
if (sv_derived_from(ST(0), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Mob*, tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Mob");
|
||||
|
||||
if (THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->HasTwoHanderEquipped();
|
||||
ST(0) = boolSV(RETVAL);
|
||||
sv_2mortal(ST(0));
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Mob_GetHerosForgeModel);
|
||||
XS(XS_Mob_GetHerosForgeModel) {
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Mob::GetHerosForgeModel(THIS, material_slot)");
|
||||
{
|
||||
Mob* THIS;
|
||||
int32 RETVAL;
|
||||
uint8 material_slot = (uint8)SvUV(ST(1));
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Mob*, tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Mob");
|
||||
|
||||
if (THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetHerosForgeModel(material_slot);
|
||||
XSprePUSH;
|
||||
PUSHi((IV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Mob_IsEliteMaterialItem);
|
||||
XS(XS_Mob_IsEliteMaterialItem) {
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Mob::IsEliteMaterialItem(THIS, material_slot)");
|
||||
{
|
||||
Mob* THIS;
|
||||
uint32 RETVAL;
|
||||
uint8 material_slot = (uint8)SvUV(ST(1));
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Mob*, tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Mob");
|
||||
|
||||
if (THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->IsEliteMaterialItem(material_slot);
|
||||
XSprePUSH;
|
||||
PUSHu((UV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Mob_GetBaseSize);
|
||||
XS(XS_Mob_GetBaseSize) {
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Mob::GetBaseSize(THIS)");
|
||||
{
|
||||
Mob* THIS;
|
||||
float RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Mob*, tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Mob");
|
||||
|
||||
if (THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetBaseSize();
|
||||
XSprePUSH;
|
||||
PUSHn((double)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Mob_HasOwner);
|
||||
XS(XS_Mob_HasOwner) {
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Mob::HasOwner(THIS)");
|
||||
{
|
||||
Mob* THIS;
|
||||
bool RETVAL;
|
||||
if (sv_derived_from(ST(0), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Mob*, tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Mob");
|
||||
|
||||
if (THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->HasOwner();
|
||||
ST(0) = boolSV(RETVAL);
|
||||
sv_2mortal(ST(0));
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Mob_IsPet);
|
||||
XS(XS_Mob_IsPet) {
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Mob::IsPet(THIS)");
|
||||
{
|
||||
Mob* THIS;
|
||||
bool RETVAL;
|
||||
if (sv_derived_from(ST(0), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Mob*, tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Mob");
|
||||
|
||||
if (THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->IsPet();
|
||||
ST(0) = boolSV(RETVAL);
|
||||
sv_2mortal(ST(0));
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Mob_HasPet);
|
||||
XS(XS_Mob_HasPet) {
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Mob::HasPet(THIS)");
|
||||
{
|
||||
Mob* THIS;
|
||||
bool RETVAL;
|
||||
if (sv_derived_from(ST(0), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Mob*, tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Mob");
|
||||
|
||||
if (THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->HasPet();
|
||||
ST(0) = boolSV(RETVAL);
|
||||
sv_2mortal(ST(0));
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Mob_IsSilenced);
|
||||
XS(XS_Mob_IsSilenced) {
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Mob::IsSilenced(THIS)");
|
||||
{
|
||||
Mob* THIS;
|
||||
bool RETVAL;
|
||||
if (sv_derived_from(ST(0), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Mob*, tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Mob");
|
||||
|
||||
if (THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->IsSilenced();
|
||||
ST(0) = boolSV(RETVAL);
|
||||
sv_2mortal(ST(0));
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Mob_IsAmnesiad);
|
||||
XS(XS_Mob_IsAmnesiad) {
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Mob::IsAmnesiad(THIS)");
|
||||
{
|
||||
Mob* THIS;
|
||||
bool RETVAL;
|
||||
if (sv_derived_from(ST(0), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Mob*, tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Mob");
|
||||
|
||||
if (THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->IsAmnesiad();
|
||||
ST(0) = boolSV(RETVAL);
|
||||
sv_2mortal(ST(0));
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Mob_GetMeleeMitigation);
|
||||
XS(XS_Mob_GetMeleeMitigation) {
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Mob::GetMeleeMitigation(THIS)");
|
||||
{
|
||||
Mob* THIS;
|
||||
int32 RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(Mob*, tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type Mob");
|
||||
|
||||
if (THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetMeleeMitigation();
|
||||
XSprePUSH;
|
||||
PUSHi((IV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
@ -8803,6 +9321,26 @@ XS(boot_Mob)
|
||||
newXSproto(strcpy(buf, "CanClassEquipItem"), XS_Mob_CanClassEquipItem, file, "$$");
|
||||
newXSproto(strcpy(buf, "IsFeared"), XS_Mob_IsFeared, file, "$");
|
||||
newXSproto(strcpy(buf, "IsBlind"), XS_Mob_IsBlind, file, "$");
|
||||
newXSproto(strcpy(buf, "SeeInvisible"), XS_Mob_SeeInvisible, file, "$");
|
||||
newXSproto(strcpy(buf, "SeeInvisibleUndead"), XS_Mob_SeeInvisibleUndead, file, "$");
|
||||
newXSproto(strcpy(buf, "SeeHide"), XS_Mob_SeeHide, file, "$");
|
||||
newXSproto(strcpy(buf, "SeeImprovedHide"), XS_Mob_SeeImprovedHide, file, "$");
|
||||
newXSproto(strcpy(buf, "GetNimbusEffect1"), XS_Mob_GetNimbusEffect1, file, "$");
|
||||
newXSproto(strcpy(buf, "GetNimbusEffect2"), XS_Mob_GetNimbusEffect2, file, "$");
|
||||
newXSproto(strcpy(buf, "GetNimbusEffect3"), XS_Mob_GetNimbusEffect3, file, "$");
|
||||
newXSproto(strcpy(buf, "IsTargetable"), XS_Mob_IsTargetable, file, "$");
|
||||
newXSproto(strcpy(buf, "HasShieldEquiped"), XS_Mob_HasShieldEquiped, file, "$");
|
||||
newXSproto(strcpy(buf, "HasTwoHandBluntEquiped"), XS_Mob_HasTwoHandBluntEquiped, file, "$");
|
||||
newXSproto(strcpy(buf, "HasTwoHanderEquipped"), XS_Mob_HasTwoHanderEquipped, file, "$");
|
||||
newXSproto(strcpy(buf, "GetHerosForgeModel"), XS_Mob_GetHerosForgeModel, file, "$$");
|
||||
newXSproto(strcpy(buf, "IsEliteMaterialItem"), XS_Mob_IsEliteMaterialItem, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetBaseSize"), XS_Mob_GetBaseSize, file, "$");
|
||||
newXSproto(strcpy(buf, "HasOwner"), XS_Mob_HasOwner, file, "$");
|
||||
newXSproto(strcpy(buf, "IsPet"), XS_Mob_IsPet, file, "$");
|
||||
newXSproto(strcpy(buf, "HasPet"), XS_Mob_HasPet, file, "$");
|
||||
newXSproto(strcpy(buf, "IsSilenced"), XS_Mob_IsSilenced, file, "$");
|
||||
newXSproto(strcpy(buf, "IsAmnesiad"), XS_Mob_IsAmnesiad, file, "$");
|
||||
newXSproto(strcpy(buf, "GetMeleeMitigation"), XS_Mob_GetMeleeMitigation, file, "$");
|
||||
XSRETURN_YES;
|
||||
}
|
||||
|
||||
|
||||
@ -484,10 +484,17 @@ QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string
|
||||
|
||||
//second look for /quests/zone/npcname.ext (precedence)
|
||||
const NPCType *npc_type = database.LoadNPCTypesData(npcid);
|
||||
if(!npc_type) {
|
||||
if (!npc_type && npcid != ZONE_CONTROLLER_NPC_ID) {
|
||||
return nullptr;
|
||||
}
|
||||
std::string npc_name = npc_type->name;
|
||||
|
||||
std::string npc_name;
|
||||
if (npcid == ZONE_CONTROLLER_NPC_ID){
|
||||
npc_name = "zone_controller";
|
||||
}
|
||||
else{
|
||||
npc_name = npc_type->name;
|
||||
}
|
||||
int sz = static_cast<int>(npc_name.length());
|
||||
for(int i = 0; i < sz; ++i) {
|
||||
if(npc_name[i] == '`') {
|
||||
|
||||
@ -2598,6 +2598,29 @@ void QuestManager::UpdateInstanceTimer(uint16 instance_id, uint32 new_duration)
|
||||
}
|
||||
}
|
||||
|
||||
uint32 QuestManager::GetInstanceTimer() {
|
||||
if (zone && zone->GetInstanceID() > 0 && zone->GetInstanceTimer()) {
|
||||
uint32 ttime = zone->GetInstanceTimer()->GetRemainingTime();
|
||||
return ttime;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 QuestManager::GetInstanceTimerByID(uint16 instance_id) {
|
||||
if (instance_id == 0)
|
||||
return 0;
|
||||
|
||||
std::string query = StringFormat("SELECT ((start_time + duration) - UNIX_TIMESTAMP()) AS `remaining` FROM `instance_list` WHERE `id` = %lu", (unsigned long)instance_id);
|
||||
auto results = database.QueryDatabase(query);
|
||||
|
||||
if (results.Success()) {
|
||||
auto row = results.begin();
|
||||
uint32 timer = atoi(row[0]);
|
||||
return timer;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16 QuestManager::GetInstanceID(const char *zone, int16 version)
|
||||
{
|
||||
QuestManagerCurrentQuestVars();
|
||||
@ -3070,3 +3093,75 @@ std::string QuestManager::GetEncounter() const {
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
void QuestManager::UpdateZoneHeader(std::string type, std::string value) {
|
||||
if (strcasecmp(type.c_str(), "ztype") == 0)
|
||||
zone->newzone_data.ztype = atoi(value.c_str());
|
||||
else if (strcasecmp(type.c_str(), "fog_red") == 0) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
zone->newzone_data.fog_red[i] = atoi(value.c_str());
|
||||
}
|
||||
} else if (strcasecmp(type.c_str(), "fog_green") == 0) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
zone->newzone_data.fog_green[i] = atoi(value.c_str());
|
||||
}
|
||||
} else if (strcasecmp(type.c_str(), "fog_blue") == 0) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
zone->newzone_data.fog_blue[i] = atoi(value.c_str());
|
||||
}
|
||||
} else if (strcasecmp(type.c_str(), "fog_minclip") == 0) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
zone->newzone_data.fog_minclip[i] = atof(value.c_str());
|
||||
}
|
||||
} else if (strcasecmp(type.c_str(), "fog_maxclip") == 0) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
zone->newzone_data.fog_maxclip[i] = atof(value.c_str());
|
||||
}
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "gravity") == 0)
|
||||
zone->newzone_data.gravity = atof(value.c_str());
|
||||
else if (strcasecmp(type.c_str(), "time_type") == 0)
|
||||
zone->newzone_data.time_type = atoi(value.c_str());
|
||||
else if (strcasecmp(type.c_str(), "rain_chance") == 0) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
zone->newzone_data.rain_chance[i] = atoi(value.c_str());
|
||||
}
|
||||
} else if (strcasecmp(type.c_str(), "rain_duration") == 0) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
zone->newzone_data.rain_duration[i] = atoi(value.c_str());
|
||||
}
|
||||
} else if (strcasecmp(type.c_str(), "snow_chance") == 0) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
zone->newzone_data.snow_chance[i] = atoi(value.c_str());
|
||||
}
|
||||
} else if (strcasecmp(type.c_str(), "snow_duration") == 0) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
zone->newzone_data.snow_duration[i] = atoi(value.c_str());
|
||||
}
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "sky") == 0)
|
||||
zone->newzone_data.sky = atoi(value.c_str());
|
||||
else if (strcasecmp(type.c_str(), "safe_x") == 0)
|
||||
zone->newzone_data.safe_x = atof(value.c_str());
|
||||
else if (strcasecmp(type.c_str(), "safe_y") == 0)
|
||||
zone->newzone_data.safe_y = atof(value.c_str());
|
||||
else if (strcasecmp(type.c_str(), "safe_z") == 0)
|
||||
zone->newzone_data.safe_z = atof(value.c_str());
|
||||
else if (strcasecmp(type.c_str(), "max_z") == 0)
|
||||
zone->newzone_data.max_z = atof(value.c_str());
|
||||
else if (strcasecmp(type.c_str(), "underworld") == 0)
|
||||
zone->newzone_data.underworld = atof(value.c_str());
|
||||
else if (strcasecmp(type.c_str(), "minclip") == 0)
|
||||
zone->newzone_data.minclip = atof(value.c_str());
|
||||
else if (strcasecmp(type.c_str(), "maxclip") == 0)
|
||||
zone->newzone_data.maxclip = atof(value.c_str());
|
||||
else if (strcasecmp(type.c_str(), "fog_density") == 0)
|
||||
zone->newzone_data.fog_density = atof(value.c_str());
|
||||
else if (strcasecmp(type.c_str(), "suspendbuffs") == 0)
|
||||
zone->newzone_data.SuspendBuffs = atoi(value.c_str());
|
||||
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_NewZone, sizeof(NewZone_Struct));
|
||||
memcpy(outapp->pBuffer, &zone->newzone_data, outapp->size);
|
||||
entity_list.QueueClients(0, outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
@ -218,6 +218,9 @@ public:
|
||||
uint32 MerchantCountItem(uint32 NPCid, uint32 itemid);
|
||||
uint16 CreateInstance(const char *zone, int16 version, uint32 duration);
|
||||
void UpdateInstanceTimer(uint16 instance_id, uint32 new_duration);
|
||||
void UpdateZoneHeader(std::string type, std::string value);
|
||||
uint32 GetInstanceTimer();
|
||||
uint32 GetInstanceTimerByID(uint16 instance_id = 0);
|
||||
void DestroyInstance(uint16 instance_id);
|
||||
uint16 GetInstanceID(const char *zone, int16 version);
|
||||
void AssignToInstance(uint16 instance_id);
|
||||
|
||||
@ -549,6 +549,8 @@ bool ZoneDatabase::PopulateZoneSpawnList(uint32 zoneid, LinkedList<Spawn2*> &spa
|
||||
spawn2_list.Insert(new_spawn);
|
||||
}
|
||||
|
||||
NPC::SpawnZoneController();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -166,25 +166,34 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme
|
||||
else
|
||||
{
|
||||
ItemInst *old_aug = nullptr;
|
||||
const uint32 id = auged_with->GetID();
|
||||
bool isSolvent = auged_with->GetItem()->ItemType == ItemUseTypes::ItemTypeAugmentationSolvent;
|
||||
if (!isSolvent && auged_with->GetItem()->ItemType != ItemUseTypes::ItemTypeAugmentationDistiller)
|
||||
{
|
||||
Log.Out(Logs::General, Logs::Error, "Player tried to remove an augment without a solvent or distiller.");
|
||||
user->Message(13, "Error: Missing an augmentation solvent or distiller for removing this augment.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ItemInst *aug = tobe_auged->GetAugment(in_augment->augment_slot);
|
||||
if(aug) {
|
||||
if (aug) {
|
||||
if (!isSolvent && auged_with->GetItem()->ID != aug->GetItem()->AugDistiller)
|
||||
{
|
||||
Log.Out(Logs::General, Logs::Error, "Player tried to safely remove an augment with the wrong distiller (item %u vs expected %u).", auged_with->GetItem()->ID, aug->GetItem()->AugDistiller);
|
||||
user->Message(13, "Error: Wrong augmentation distiller for safely removing this augment.");
|
||||
return;
|
||||
}
|
||||
std::vector<EQEmu::Any> args;
|
||||
args.push_back(aug);
|
||||
parse->EventItem(EVENT_UNAUGMENT_ITEM, user, tobe_auged, nullptr, "", slot, &args);
|
||||
|
||||
args.assign(1, tobe_auged);
|
||||
bool destroyed = false;
|
||||
if(id == 40408 || id == 40409 || id == 40410) {
|
||||
destroyed = true;
|
||||
}
|
||||
|
||||
args.push_back(&destroyed);
|
||||
args.push_back(&isSolvent);
|
||||
|
||||
parse->EventItem(EVENT_AUGMENT_REMOVE, user, aug, nullptr, "", slot, &args);
|
||||
}
|
||||
|
||||
if(id == 40408 || id == 40409 || id == 40410)
|
||||
if (isSolvent)
|
||||
tobe_auged->DeleteAugment(in_augment->augment_slot);
|
||||
else
|
||||
old_aug = tobe_auged->RemoveAugment(in_augment->augment_slot);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user