Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Paul Coene 2015-11-20 12:04:11 -05:00
commit 0c56660692
65 changed files with 1484 additions and 377 deletions

View File

@ -1,5 +1,64 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50)
-------------------------------------------------------
== 11/7/2015 ==
Akkadius: Implemented #repopclose [distance in units] - Used for development purposes, defaults to 500 units
- Real case use: Large zones with 700 NPC's and you are making fast quick tweaks to nearby NPC's you can refresh just the NPC's around you instead of all in the zone
- This can be quite the time saver
- This command will depop all NPC's and only respawn the NPC's that are 500 units around you or unless you specify otherwise
== 11/2/2015 ==
Akkadius: Performance boost (exponential) - Adjusted default idle cast check timers in rules
- Spells:AI_IdleNoSpellMinRecast 500 (Now 6000) 6 seconds
- Spells:AI_IdleNoSpellMaxRecast 2000 (Now 60000) 60 seconds
- Database version 9089 will take care of this update automatically only if you used the default values
- The CPU cost of NPC's checking the entire entity list to cast beneficial spells (Heals/Buffs) becomes extremely high when higher NPC count zones exist (Based off of process profiling)
- Distance checks for every single NPC to every single other NPC who are casting beneficial spells occur every .5 - 2 seconds unless npc_spells dictates other values, which most of the time it does not
- Zones that once fluctuated from 1-8% CPU with no activity (Idle but players present) now idle at .5% based on my testings due
to this change in conjunction with the past few performance commits, these are zones that have 600-800 NPC's in them
- These values normally are overidden by the spells table (npc_spells), fields (idle_no_sp_recast_min, idle_no_sp_recast_max)
== 11/1/2015 ==
Akkadius: Made many performance optimizing oriented code changes in the source
- Added Rate limit the rate in which signals are processed for NPC's (.5 seconds instead of .01 seconds)
Akkadius: Added Perl Export Settings which should heavily reduce the Perl footprint
- Normally when any sub EVENT_ gets triggered, all kinds of variables have to get exported every single time an event is triggered and
this can make Perl very slow when events are triggered constantly
- The two most taxing variable exports are the item variables ($itemcount{} $hasitem{} $oncursor{}) and qglobals ($qglobals{})
- qglobals can pose to be an issue quickly when global qglobals build up, it is highly recommend to use the GetGlobal() and SetGlobal()
methods instead as they don't reference the hashmap $qglobals{} that is rebuilt every single time a sub event is triggered
- A stress test conducted with 10,000 samples shows an excess of time taken to export variables: http://i.imgur.com/NEpW1tS.png
- After the Perl Export Settings table is implemented, and all exports are shut off you see the following test result:
http://i.imgur.com/Du5hth9.png
- The difference of eliminating uneeded exports brings the overhead and footprint of 10,000 triggers from 54 seconds to 2 seconds
- In a 10,000 sample test (10,000 sub event triggers), exporting item variables adds 12 seconds alone, when item variables are only needed in
EVENT_ITEM and EVENT_SAY a majority of the time if at all
- In a 10,000 sample test (10,000 sub event triggers), exporting qglobals with approximately 1,000 global qglobals in the database creates
about 11-20 seconds of delay on its own (Depending on hardware of course)
- I've written a parser that has determined which of these exports are needed in which sub routines and have turned off all of the unneeded
exports in sub routines that do not need them and used it to create the default table that will be installed in the database.
- The export table is called 'perl_event_export_settings' and it resembles the following structure and contains all current 81 EVENTS
- If an entry doesn't exist in this table and a new subroutine is added to the source, all exports will be on by default for that routine
+----------+-----------------------------------------+-----------------+------------+-------------+-------------+--------------+
| event_id | event_description | export_qglobals | export_mob | export_zone | export_item | export_event |
+----------+-----------------------------------------+-----------------+------------+-------------+-------------+--------------+
| 0 | EVENT_SAY | 1 | 1 | 1 | 1 | 1 |
| 1 | EVENT_ITEM | 1 | 1 | 1 | 0 | 1 |
| 2 | EVENT_DEATH | 1 | 1 | 1 | 0 | 1 |
| 3 | EVENT_SPAWN | 1 | 1 | 1 | 0 | 1 |
| 4 | EVENT_ATTACK | 0 | 1 | 1 | 0 | 1 |
| 5 | EVENT_COMBAT | 1 | 1 | 1 | 0 | 1 |
+----------+-----------------------------------------+-----------------+------------+-------------+-------------+--------------+
- If a change is made to this table while the server is live and running, you can hot reload all zone process settings via:
#reloadperlexportsettings
- For those who wonder what "exports" are, they are reference to variables that are made available at runtime of the sub event, such as:
(export_qglobals) (Heavy) : $qglobals https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L916
(export_item) (Heavy) : $itemcount{} $hasitem{} $oncursor{} https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L1103
(export_zone) : $zoneid, $instanceid, $zoneln etc. https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L1083
(export_mob) : $x, $y, $z, $h, $hpratio etc. https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L1032
(export_event) : (event specific) IE: EVENT_SAY ($text) https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L1141
== 10/16/2015 ==
Uleat: Added command '#bot clearfollowdistance [ <target> | spawned | all ]' to coincide with the activation of the load/save feature for follow_distance

View File

@ -21,6 +21,12 @@ IF(MYSQL_ROOT)
NAMES mysql.h
PATHS ${MYSQL_ROOT}/include
PATH_SUFFIXES mysql
NO_DEFAULT_PATH
NO_SYSTEM_ENVIRONMENT_PATH
)
FIND_PATH(MySQL_INCLUDE_DIR
NAMES mysql.h
PATH_SUFFIXES mysql
)
ELSE(MYSQL_ROOT)
FIND_PATH(MySQL_INCLUDE_DIR
@ -30,49 +36,46 @@ ELSE(MYSQL_ROOT)
ENDIF(MYSQL_ROOT)
# Library
SET(MySQL_NAMES libmysql mysqlclient_r mysqlclient)
SET(MySQL_NAMES libmysql)
IF(MYSQL_ROOT)
FIND_LIBRARY(MySQL_LIBRARY_DEBUG
FIND_LIBRARY(MySQL_LIBRARY
NAMES ${MySQL_NAMES}
PATHS ${MYSQL_ROOT}/lib/debug /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64
PATHS ${MYSQL_ROOT}/lib
PATH_SUFFIXES mysql
NO_DEFAULT_PATH
NO_SYSTEM_ENVIRONMENT_PATH
)
FIND_LIBRARY(MySQL_LIBRARY_RELEASE
FIND_LIBRARY(MySQL_LIBRARY
NAMES ${MySQL_NAMES}
PATHS ${MYSQL_ROOT}/lib /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64
PATH_SUFFIXES mysql
)
ELSE(MYSQL_ROOT)
FIND_LIBRARY(MySQL_LIBRARY_DEBUG
NAMES ${MySQL_NAMES}
PATHS /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64
PATH_SUFFIXES mysql
)
FIND_LIBRARY(MySQL_LIBRARY_RELEASE
NAMES ${MySQL_NAMES}
FIND_LIBRARY(MySQL_LIBRARY
NAMES ${MySQL_NAMES} mysqlclient_r mysqlclient
PATHS /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64
PATH_SUFFIXES mysql
)
ENDIF(MYSQL_ROOT)
IF (MySQL_INCLUDE_DIR AND MySQL_LIBRARY_DEBUG AND MySQL_LIBRARY_RELEASE)
IF (MySQL_INCLUDE_DIR AND MySQL_LIBRARY)
SET(MySQL_FOUND TRUE)
SET( MySQL_LIBRARIES ${MySQL_LIBRARY_DEBUG} ${MySQL_LIBRARY_RELEASE} )
ELSE (MySQL_INCLUDE_DIR AND MySQL_LIBRARY_DEBUG AND MySQL_LIBRARY_RELEASE)
SET( MySQL_LIBRARIES ${MySQL_LIBRARY} )
ELSE (MySQL_INCLUDE_DIR AND MySQL_LIBRARY)
SET(MySQL_FOUND FALSE)
SET( MySQL_LIBRARIES )
ENDIF (MySQL_INCLUDE_DIR AND MySQL_LIBRARY_DEBUG AND MySQL_LIBRARY_RELEASE)
ENDIF (MySQL_INCLUDE_DIR AND MySQL_LIBRARY)
# handle the QUIETLY and REQUIRED arguments and set MySQL_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(MySQL DEFAULT_MSG MySQL_LIBRARY_DEBUG MySQL_LIBRARY_RELEASE MySQL_INCLUDE_DIR)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(MySQL DEFAULT_MSG MySQL_LIBRARY MySQL_INCLUDE_DIR)
IF(MySQL_FOUND)
SET( MySQL_LIBRARIES ${MySQL_LIBRARY_DEBUG} ${MySQL_LIBRARY_RELEASE} )
SET( MySQL_LIBRARY_RELEASE ${MySQL_LIBRARY} )
SET( MySQL_LIBRARY_DEBUG ${MySQL_LIBRARY} )
SET( MySQL_LIBRARIES ${MySQL_LIBRARY_RELEASE} ${MySQL_LIBRARY_DEBUG} )
ELSE(MySQL_FOUND)
SET( MySQL_LIBRARIES )
ENDIF(MySQL_FOUND)

View File

@ -67,6 +67,8 @@ public:
uint8 ReadUInt8() { uint8 value = *(uint8 *)(pBuffer + _rpos); _rpos += sizeof(uint8); return value; }
uint8 ReadUInt8(uint32 Offset) const { uint8 value = *(uint8 *)(pBuffer + Offset); return value; }
uint16 ReadUInt16() { uint16 value = *(uint16 *)(pBuffer + _rpos); _rpos += sizeof(uint16); return value; }
uint16 ReadUInt16(uint32 Offset) const { uint16 value = *(uint16 *)(pBuffer + Offset); return value; }
uint32 ReadUInt32() { uint32 value = *(uint32 *)(pBuffer + _rpos); _rpos += sizeof(uint32); return value; }
uint32 ReadUInt32(uint32 Offset) const { uint32 value = *(uint32 *)(pBuffer + Offset); return value; }
void ReadString(char *str) { uint32 len = static_cast<uint32>(strlen((char *)(pBuffer + _rpos))) + 1; memcpy(str, pBuffer + _rpos, len); _rpos += len; }

View File

@ -23,6 +23,7 @@
#include "global_define.h"
#include "eqemu_logsys.h"
#include "types.h"
#include "dbcore.h"
#include "linked_list.h"

View File

@ -128,7 +128,12 @@ MySQLRequestResult DBcore::QueryDatabase(const char* query, uint32 querylen, boo
MySQLRequestResult requestResult(res, (uint32)mysql_affected_rows(&mysql), rowCount, (uint32)mysql_field_count(&mysql), (uint32)mysql_insert_id(&mysql));
if (Log.log_settings[Logs::MySQLQuery].is_category_enabled == 1)
Log.Out(Logs::General, Logs::MySQLQuery, "%s (%u rows returned)", query, rowCount, requestResult.RowCount());
{
if ((strncasecmp(query, "select", 6) == 0))
Log.Out(Logs::General, Logs::MySQLQuery, "%s (%u row%s returned)", query, requestResult.RowCount(), requestResult.RowCount() == 1 ? "" : "s");
else
Log.Out(Logs::General, Logs::MySQLQuery, "%s (%u row%s affected)", query, requestResult.RowsAffected(), requestResult.RowsAffected() == 1 ? "" : "s");
}
return requestResult;
}

View File

@ -215,6 +215,7 @@ N(OP_GroupUpdate),
N(OP_GroupUpdateB),
N(OP_GroupUpdateLeaderAA),
N(OP_GuildBank),
N(OP_GuildBankItemList),
N(OP_GuildCreate),
N(OP_GuildDelete),
N(OP_GuildDemote),
@ -535,6 +536,8 @@ N(OP_WorldLogout),
N(OP_WorldObjectsSent),
N(OP_WorldUnknown001),
N(OP_XTargetAutoAddHaters),
N(OP_XTargetOpen),
N(OP_XTargetOpenResponse),
N(OP_XTargetRequest),
N(OP_XTargetResponse),
N(OP_YellForHelp),

View File

@ -4724,6 +4724,22 @@ struct GuildBankItemUpdate_Struct
/*226*/ uint16 Unknown226;
};
// newer clients (RoF+) send a list that contains 240 entries
// The packets don't actually use all 64 chars in the strings, but we'll just overallocate for these
struct GuildBankItemListEntry_Struct
{
uint8 vaild;
uint32 permissions;
char whofor[64];
char donator[64];
uint32 item_id;
uint32 item_icon;
uint32 quantity;
uint8 allow_merge; // 1 here for non-full stacks
uint8 usable;
char item_name[64];
};
struct GuildBankClear_Struct
{
/*00*/ uint32 Action;

View File

@ -116,7 +116,7 @@ void EQEmuLogSys::LoadLogSettingsDefaults()
platform_file_name = "ucs";
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLogin)
platform_file_name = "login";
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLogin)
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLaunch)
platform_file_name = "launcher";
}

View File

@ -154,11 +154,12 @@ enum { //reuse times
enum { //timer settings, all in milliseconds
AImovement_duration = 100,
AIthink_duration = 150,
AIscanarea_delay = 500,
AIscanarea_delay = 6000,
AIfeignremember_delay = 500,
AItarget_check_duration = 500,
AIClientScanarea_delay = 750, //used in REVERSE_AGGRO
AIassistcheck_delay = 3000, //now often a fighting NPC will yell for help
AI_check_signal_timer_delay = 500, // How often EVENT_SIGNAL checks are processed
ClientProximity_interval = 150,
CombatEventTimer_expire = 12000,
Tribute_duration = 600000,

View File

@ -51,7 +51,7 @@
**
*/
struct ItemEffect_Struct {
int16 Effect;
int32 Effect;
uint8 Type;
uint8 Level;
uint8 Level2;

View File

@ -1179,6 +1179,54 @@ namespace RoF
dest->FastQueuePacket(&outapp);
}
ENCODE(OP_GuildBank)
{
auto in = *p;
*p = nullptr;
auto outapp = new EQApplicationPacket(OP_GuildBank, in->size + 4); // all of them are 4 bytes bigger
// The first action in the enum was removed, everything 1 less
// Normally we cast them to their structs, but there are so many here! will only do when it's easier
switch (in->ReadUInt32()) {
case 10: // GuildBankAcknowledge
outapp->WriteUInt32(9);
outapp->WriteUInt32(in->ReadUInt32());
outapp->WriteUInt32(0);
break;
case 5: // GuildBankDeposit (ack)
outapp->WriteUInt32(4);
outapp->WriteUInt32(in->ReadUInt32());
outapp->WriteUInt32(0);
outapp->WriteUInt32(in->ReadUInt32());
break;
case 1: { // GuildBankItemUpdate
auto emu = (GuildBankItemUpdate_Struct *)in->pBuffer;
auto eq = (structs::GuildBankItemUpdate_Struct *)outapp->pBuffer;
eq->Action = 0;
OUT(Unknown004);
eq->Unknown08 = 0;
OUT(SlotID);
OUT(Area);
OUT(Unknown012);
OUT(ItemID);
OUT(Icon);
OUT(Quantity);
OUT(Permissions);
OUT(AllowMerge);
OUT(Useable);
OUT_str(ItemName);
OUT_str(Donator);
OUT_str(WhoFor);
OUT(Unknown226);
break;
}
default:
break;
}
delete in;
dest->FastQueuePacket(&outapp);
}
ENCODE(OP_GuildMemberList)
{
//consume the packet
@ -4590,6 +4638,92 @@ namespace RoF
DECODE_FORWARD(OP_GroupInvite);
}
DECODE(OP_GuildBank)
{
// all actions are 1 off due to the removal of one of enums
switch (__packet->ReadUInt32()) {
case 2: {// GuildBankPromote
DECODE_LENGTH_EXACT(structs::GuildBankPromote_Struct);
SETUP_DIRECT_DECODE(GuildBankPromote_Struct, structs::GuildBankPromote_Struct);
emu->Action = 3;
IN(Unknown04);
IN(Slot);
IN(Slot2);
FINISH_DIRECT_DECODE();
return;
}
case 3: { // GuildBankViewItem
DECODE_LENGTH_EXACT(structs::GuildBankViewItem_Struct);
SETUP_DIRECT_DECODE(GuildBankViewItem_Struct, structs::GuildBankViewItem_Struct);
emu->Action = 4;
IN(Unknown04);
IN(SlotID);
IN(Area);
IN(Unknown12);
IN(Unknown16);
FINISH_DIRECT_DECODE();
return;
}
case 4: { // GuildBankDeposit
__packet->WriteUInt32(5);
return;
}
case 5: { // GuildBankPermissions
DECODE_LENGTH_EXACT(structs::GuildBankPermissions_Struct);
SETUP_DIRECT_DECODE(GuildBankPermissions_Struct, structs::GuildBankPermissions_Struct);
emu->Action = 6;
IN(Unknown04);
IN(SlotID);
IN(Unknown10);
IN(ItemID);
IN(Permissions);
strn0cpy(emu->MemberName, eq->MemberName, 64);
FINISH_DIRECT_DECODE();
return;
}
case 6: { // GuildBankWithdraw
DECODE_LENGTH_EXACT(structs::GuildBankWithdrawItem_Struct);
SETUP_DIRECT_DECODE(GuildBankWithdrawItem_Struct, structs::GuildBankWithdrawItem_Struct);
emu->Action = 7;
IN(Unknown04);
IN(SlotID);
IN(Area);
IN(Unknown12);
IN(Quantity);
FINISH_DIRECT_DECODE();
return;
}
case 7: { // GuildBankSplitStacks
DECODE_LENGTH_EXACT(structs::GuildBankWithdrawItem_Struct);
SETUP_DIRECT_DECODE(GuildBankWithdrawItem_Struct, structs::GuildBankWithdrawItem_Struct);
emu->Action = 8;
IN(Unknown04);
IN(SlotID);
IN(Area);
IN(Unknown12);
IN(Quantity);
FINISH_DIRECT_DECODE();
return;
}
case 8: { // GuildBankMergeStacks
DECODE_LENGTH_EXACT(structs::GuildBankWithdrawItem_Struct);
SETUP_DIRECT_DECODE(GuildBankWithdrawItem_Struct, structs::GuildBankWithdrawItem_Struct);
emu->Action = 9;
IN(Unknown04);
IN(SlotID);
IN(Area);
IN(Unknown12);
IN(Quantity);
FINISH_DIRECT_DECODE();
return;
}
default:
Log.Out(Logs::Detail, Logs::Netcode, "Unhandled OP_GuildBank action");
__packet->SetOpcode(OP_Unknown); /* invalidate the packet */
return;
}
}
DECODE(OP_GuildDemote)
{
DECODE_LENGTH_EXACT(structs::GuildDemoteStruct);

View File

@ -1250,6 +1250,54 @@ namespace RoF2
dest->FastQueuePacket(&outapp);
}
ENCODE(OP_GuildBank)
{
auto in = *p;
*p = nullptr;
auto outapp = new EQApplicationPacket(OP_GuildBank, in->size + 4); // all of them are 4 bytes bigger
// The first action in the enum was removed, everything 1 less
// Normally we cast them to their structs, but there are so many here! will only do when it's easier
switch (in->ReadUInt32()) {
case 10: // GuildBankAcknowledge
outapp->WriteUInt32(9);
outapp->WriteUInt32(in->ReadUInt32());
outapp->WriteUInt32(0);
break;
case 5: // GuildBankDeposit (ack)
outapp->WriteUInt32(4);
outapp->WriteUInt32(in->ReadUInt32());
outapp->WriteUInt32(0);
outapp->WriteUInt32(in->ReadUInt32());
break;
case 1: { // GuildBankItemUpdate
auto emu = (GuildBankItemUpdate_Struct *)in->pBuffer;
auto eq = (structs::GuildBankItemUpdate_Struct *)outapp->pBuffer;
eq->Action = 0;
OUT(Unknown004);
eq->Unknown08 = 0;
OUT(SlotID);
OUT(Area);
OUT(Unknown012);
OUT(ItemID);
OUT(Icon);
OUT(Quantity);
OUT(Permissions);
OUT(AllowMerge);
OUT(Useable);
OUT_str(ItemName);
OUT_str(Donator);
OUT_str(WhoFor);
OUT(Unknown226);
break;
}
default:
break;
}
delete in;
dest->FastQueuePacket(&outapp);
}
ENCODE(OP_GuildMemberList)
{
//consume the packet
@ -4739,6 +4787,92 @@ namespace RoF2
DECODE_FORWARD(OP_GroupInvite);
}
DECODE(OP_GuildBank)
{
// all actions are 1 off due to the removal of one of enums
switch (__packet->ReadUInt32()) {
case 2: {// GuildBankPromote
DECODE_LENGTH_EXACT(structs::GuildBankPromote_Struct);
SETUP_DIRECT_DECODE(GuildBankPromote_Struct, structs::GuildBankPromote_Struct);
emu->Action = 3;
IN(Unknown04);
IN(Slot);
IN(Slot2);
FINISH_DIRECT_DECODE();
return;
}
case 3: { // GuildBankViewItem
DECODE_LENGTH_EXACT(structs::GuildBankViewItem_Struct);
SETUP_DIRECT_DECODE(GuildBankViewItem_Struct, structs::GuildBankViewItem_Struct);
emu->Action = 4;
IN(Unknown04);
IN(SlotID);
IN(Area);
IN(Unknown12);
IN(Unknown16);
FINISH_DIRECT_DECODE();
return;
}
case 4: { // GuildBankDeposit
__packet->WriteUInt32(5);
return;
}
case 5: { // GuildBankPermissions
DECODE_LENGTH_EXACT(structs::GuildBankPermissions_Struct);
SETUP_DIRECT_DECODE(GuildBankPermissions_Struct, structs::GuildBankPermissions_Struct);
emu->Action = 6;
IN(Unknown04);
IN(SlotID);
IN(Unknown10);
IN(ItemID);
IN(Permissions);
strn0cpy(emu->MemberName, eq->MemberName, 64);
FINISH_DIRECT_DECODE();
return;
}
case 6: { // GuildBankWithdraw
DECODE_LENGTH_EXACT(structs::GuildBankWithdrawItem_Struct);
SETUP_DIRECT_DECODE(GuildBankWithdrawItem_Struct, structs::GuildBankWithdrawItem_Struct);
emu->Action = 7;
IN(Unknown04);
IN(SlotID);
IN(Area);
IN(Unknown12);
IN(Quantity);
FINISH_DIRECT_DECODE();
return;
}
case 7: { // GuildBankSplitStacks
DECODE_LENGTH_EXACT(structs::GuildBankWithdrawItem_Struct);
SETUP_DIRECT_DECODE(GuildBankWithdrawItem_Struct, structs::GuildBankWithdrawItem_Struct);
emu->Action = 8;
IN(Unknown04);
IN(SlotID);
IN(Area);
IN(Unknown12);
IN(Quantity);
FINISH_DIRECT_DECODE();
return;
}
case 8: { // GuildBankMergeStacks
DECODE_LENGTH_EXACT(structs::GuildBankWithdrawItem_Struct);
SETUP_DIRECT_DECODE(GuildBankWithdrawItem_Struct, structs::GuildBankWithdrawItem_Struct);
emu->Action = 9;
IN(Unknown04);
IN(SlotID);
IN(Area);
IN(Unknown12);
IN(Quantity);
FINISH_DIRECT_DECODE();
return;
}
default:
Log.Out(Logs::Detail, Logs::Netcode, "Unhandled OP_GuildBank action");
__packet->SetOpcode(OP_Unknown); /* invalidate the packet */
return;
}
}
DECODE(OP_GuildDemote)
{
DECODE_LENGTH_EXACT(structs::GuildDemoteStruct);

View File

@ -57,6 +57,7 @@ E(OP_GroupFollow)
E(OP_GroupFollow2)
E(OP_GroupInvite)
E(OP_GroupUpdate)
E(OP_GuildBank)
E(OP_GuildMemberList)
E(OP_GuildMemberUpdate)
E(OP_GuildsList)
@ -152,6 +153,7 @@ D(OP_GroupFollow)
D(OP_GroupFollow2)
D(OP_GroupInvite)
D(OP_GroupInvite2)
D(OP_GuildBank)
D(OP_GuildDemote)
D(OP_GuildRemove)
D(OP_GuildStatus)

View File

@ -1859,6 +1859,114 @@ struct GuildUpdate_Struct {
GuildsListEntry_Struct entry;
};
struct GuildBankAck_Struct
{
/*00*/ uint32 Action; // 10
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
};
struct GuildBankDepositAck_Struct
{
/*00*/ uint32 Action; // 10
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*08*/ uint32 Fail; //1 = Fail, 0 = Success
};
struct GuildBankPromote_Struct
{
/*00*/ uint32 Action; // 3
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*12*/ uint32 Slot;
/*16*/ uint32 Slot2; // Always appears to be the same as Slot for Action code 3
/*20*/ uint32 unknown20;
};
struct GuildBankPermissions_Struct
{
/*00*/ uint32 Action; // 6
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*08*/ uint16 SlotID;
/*10*/ uint16 Unknown10; // Saw 1, probably indicating it is the main area rather than deposits
/*12*/ uint32 ItemID;
/*16*/ uint32 Permissions;
/*20*/ char MemberName[64];
};
struct GuildBankViewItem_Struct
{
/*00*/ uint32 Action;
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*08*/ uint16 SlotID; // 0 = Deposit area, 1 = Main area
/*10*/ uint16 Area;
/*12*/ uint32 Unknown12;
/*16*/ uint32 Unknown16;
};
struct GuildBankWithdrawItem_Struct
{
/*00*/ uint32 Action;
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*08*/ uint16 SlotID;
/*10*/ uint16 Area;
/*12*/ uint32 Unknown12;
/*16*/ uint32 Quantity;
/*20*/
};
struct GuildBankItemUpdate_Struct
{
void Init(uint32 inAction, uint32 inUnknown004, uint16 inSlotID, uint16 inArea, uint16 inUnknown012, uint32 inItemID, uint32 inIcon, uint32 inQuantity,
uint32 inPermissions, uint32 inAllowMerge, bool inUseable)
{
Action = inAction;
Unknown004 = inUnknown004;
SlotID = inSlotID;
Area = inArea;
Unknown012 = inUnknown012;
ItemID = inItemID;
Icon = inIcon;
Quantity = inQuantity;
Permissions = inPermissions;
AllowMerge = inAllowMerge;
Useable = inUseable;
ItemName[0] = '\0';
Donator[0] = '\0';
WhoFor[0] = '\0';
};
/*000*/ uint32 Action;
/*004*/ uint32 Unknown004;
/*008*/ uint32 Unknown08;
/*012*/ uint16 SlotID;
/*014*/ uint16 Area;
/*016*/ uint32 Unknown012;
/*020*/ uint32 ItemID;
/*024*/ uint32 Icon;
/*028*/ uint32 Quantity;
/*032*/ uint32 Permissions;
/*036*/ uint8 AllowMerge;
/*037*/ uint8 Useable; // Used in conjunction with the Public-if-useable permission.
/*038*/ char ItemName[64];
/*102*/ char Donator[64];
/*166*/ char WhoFor[64];
/*230*/ uint16 Unknown226;
};
struct GuildBankClear_Struct
{
/*00*/ uint32 Action;
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*12*/ uint32 DepositAreaCount;
/*16*/ uint32 MainAreaCount;
};
/*
** Money Loot
** Length: 22 Bytes
@ -4624,7 +4732,7 @@ struct ClickEffectStruct
struct ProcEffectStruct
{
uint32 effect;
int32 effect;
uint8 level2;
uint32 type;
uint8 level;
@ -4639,7 +4747,7 @@ struct ProcEffectStruct
struct WornEffectStruct //worn, focus and scroll effect
{
uint32 effect;
int32 effect;
uint8 level2;
uint32 type;
uint8 level;

View File

@ -42,6 +42,7 @@ E(OP_GroupFollow)
E(OP_GroupFollow2)
E(OP_GroupInvite)
E(OP_GroupUpdate)
E(OP_GuildBank)
E(OP_GuildMemberList)
E(OP_GuildMemberUpdate)
E(OP_GuildsList)
@ -137,6 +138,7 @@ D(OP_GroupFollow)
D(OP_GroupFollow2)
D(OP_GroupInvite)
D(OP_GroupInvite2)
D(OP_GuildBank)
D(OP_GuildDemote)
D(OP_GuildRemove)
D(OP_GuildStatus)

View File

@ -1889,6 +1889,114 @@ struct GuildUpdate_Struct {
GuildsListEntry_Struct entry;
};
struct GuildBankAck_Struct
{
/*00*/ uint32 Action; // 10
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
};
struct GuildBankDepositAck_Struct
{
/*00*/ uint32 Action; // 10
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*08*/ uint32 Fail; //1 = Fail, 0 = Success
};
struct GuildBankPromote_Struct
{
/*00*/ uint32 Action; // 3
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*12*/ uint32 Slot;
/*16*/ uint32 Slot2; // Always appears to be the same as Slot for Action code 3
/*20*/ uint32 unknown20;
};
struct GuildBankPermissions_Struct
{
/*00*/ uint32 Action; // 6
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*08*/ uint16 SlotID;
/*10*/ uint16 Unknown10; // Saw 1, probably indicating it is the main area rather than deposits
/*12*/ uint32 ItemID;
/*16*/ uint32 Permissions;
/*20*/ char MemberName[64];
};
struct GuildBankViewItem_Struct
{
/*00*/ uint32 Action;
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*08*/ uint16 SlotID; // 0 = Deposit area, 1 = Main area
/*10*/ uint16 Area;
/*12*/ uint32 Unknown12;
/*16*/ uint32 Unknown16;
};
struct GuildBankWithdrawItem_Struct
{
/*00*/ uint32 Action;
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*08*/ uint16 SlotID;
/*10*/ uint16 Area;
/*12*/ uint32 Unknown12;
/*16*/ uint32 Quantity;
/*20*/
};
struct GuildBankItemUpdate_Struct
{
void Init(uint32 inAction, uint32 inUnknown004, uint16 inSlotID, uint16 inArea, uint16 inUnknown012, uint32 inItemID, uint32 inIcon, uint32 inQuantity,
uint32 inPermissions, uint32 inAllowMerge, bool inUseable)
{
Action = inAction;
Unknown004 = inUnknown004;
SlotID = inSlotID;
Area = inArea;
Unknown012 = inUnknown012;
ItemID = inItemID;
Icon = inIcon;
Quantity = inQuantity;
Permissions = inPermissions;
AllowMerge = inAllowMerge;
Useable = inUseable;
ItemName[0] = '\0';
Donator[0] = '\0';
WhoFor[0] = '\0';
};
/*000*/ uint32 Action;
/*004*/ uint32 Unknown004;
/*008*/ uint32 Unknown08;
/*012*/ uint16 SlotID;
/*014*/ uint16 Area;
/*016*/ uint32 Unknown012;
/*020*/ uint32 ItemID;
/*024*/ uint32 Icon;
/*028*/ uint32 Quantity;
/*032*/ uint32 Permissions;
/*036*/ uint8 AllowMerge;
/*037*/ uint8 Useable; // Used in conjunction with the Public-if-useable permission.
/*038*/ char ItemName[64];
/*102*/ char Donator[64];
/*166*/ char WhoFor[64];
/*230*/ uint16 Unknown226;
};
struct GuildBankClear_Struct
{
/*00*/ uint32 Action;
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*12*/ uint32 DepositAreaCount;
/*16*/ uint32 MainAreaCount;
};
/*
** Money Loot
** Length: 22 Bytes
@ -4623,7 +4731,7 @@ struct ClickEffectStruct
struct ProcEffectStruct
{
uint32 effect;
int32 effect;
uint8 level2;
uint32 type;
uint8 level;
@ -4638,7 +4746,7 @@ struct ProcEffectStruct
struct WornEffectStruct //worn, focus and scroll effect
{
uint32 effect;
int32 effect;
uint8 level2;
uint32 type;
uint8 level;

View File

@ -4111,7 +4111,7 @@ struct ClickEffectStruct
struct ProcEffectStruct
{
uint32 effect;
int32 effect;
uint8 level2;
uint32 type;
uint8 level;
@ -4126,7 +4126,7 @@ struct ProcEffectStruct
struct WornEffectStruct //worn, focus and scroll effect
{
uint32 effect;
int32 effect;
uint8 level2;
uint32 type;
uint8 level;

View File

@ -3965,7 +3965,7 @@ struct ClickEffectStruct
struct ProcEffectStruct
{
uint32 effect;
int32 effect;
uint8 level2;
uint32 type;
uint8 level;
@ -3980,7 +3980,7 @@ struct ProcEffectStruct
struct WornEffectStruct //worn, focus and scroll effect
{
uint32 effect;
int32 effect;
uint8 level2;
uint32 type;
uint8 level;

View File

@ -4206,7 +4206,7 @@ struct ClickEffectStruct
struct ProcEffectStruct
{
uint32 effect;
int32 effect;
uint8 level2;
uint32 type;
uint8 level;
@ -4221,7 +4221,7 @@ struct ProcEffectStruct
struct WornEffectStruct //worn, focus and scroll effect
{
uint32 effect;
int32 effect;
uint8 level2;
uint32 type;
uint8 level;

View File

@ -347,8 +347,8 @@ RULE_INT(Spells, AI_EngagedDetrimentalChance, 20) // Chance during third AI Cast
RULE_INT(Spells, AI_PursueNoSpellMinRecast, 500) // AI spell recast time(MS) check when no spell is cast while chasing target. (min time in random)
RULE_INT(Spells, AI_PursueNoSpellMaxRecast, 2000) // AI spell recast time(MS) check when no spell is cast while chasing target. (max time in random)
RULE_INT(Spells, AI_PursueDetrimentalChance, 90) // Chance while chasing target to cast a detrimental spell.
RULE_INT(Spells, AI_IdleNoSpellMinRecast, 500) // AI spell recast time(MS) check when no spell is cast while idle. (min time in random)
RULE_INT(Spells, AI_IdleNoSpellMaxRecast, 2000) // AI spell recast time(MS) check when no spell is cast while chasing target. (max time in random)
RULE_INT(Spells, AI_IdleNoSpellMinRecast, 6000) // AI spell recast time(MS) check when no spell is cast while idle. (min time in random)
RULE_INT(Spells, AI_IdleNoSpellMaxRecast, 60000) // AI spell recast time(MS) check when no spell is cast while chasing target. (max time in random)
RULE_INT(Spells, AI_IdleBeneficialChance, 100) // Chance while idle to do a beneficial spell on self or others.
RULE_BOOL(Spells, SHDProcIDOffByOne, true) // pre June 2009 SHD spell procs were off by 1, they stopped doing this in June 2009 (so UF+ spell files need this false)
RULE_BOOL(Spells, Jun182014HundredHandsRevamp, false) // this should be true for if you import a spell file newer than June 18, 2014
@ -475,6 +475,8 @@ RULE_BOOL(NPC, ReturnNonQuestNoDropItems, false) // Returns NO DROP items on NPC
RULE_INT(NPC, StartEnrageValue, 9) // % HP that an NPC will begin to enrage
RULE_BOOL(NPC, LiveLikeEnrage, false) // If set to true then only player controlled pets will enrage
RULE_BOOL(NPC, EnableMeritBasedFaction, false) // If set to true, faction will given in the same way as experience (solo/group/raid)
RULE_INT(NPC, NPCToNPCAggroTimerMin, 500)
RULE_INT(NPC, NPCToNPCAggroTimerMax, 6000)
RULE_CATEGORY_END()
RULE_CATEGORY(Aggro)

View File

@ -182,6 +182,7 @@
#define ServerOP_CZMessagePlayer 0x4008
#define ServerOP_ReloadWorld 0x4009
#define ServerOP_ReloadLogs 0x4010
#define ServerOP_ReloadPerlExportSettings 0x4011
/* Query Server OP Codes */
#define ServerOP_QSPlayerLogTrades 0x5010
#define ServerOP_QSPlayerLogHandins 0x5011
@ -548,6 +549,7 @@ struct ServerConnectInfo {
char address[250];
char local_address[250];
uint16 port;
uint32 process_id;
};
struct ServerGMGoto_Struct {

View File

@ -997,23 +997,23 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_
strcpy(item.CharmFile,row[ItemField::charmfile]);
item.Proc.Effect = (uint16)atoul(row[ItemField::proceffect]);
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 = (uint16)atoul(row[ItemField::worneffect]);
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 = (uint16)atoul(row[ItemField::focuseffect]);
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 = (uint16)atoul(row[ItemField::scrolleffect]);
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 = (uint16)atoul(row[ItemField::bardeffect]);
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]);

View File

@ -30,7 +30,7 @@
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9087
#define CURRENT_BINARY_DATABASE_VERSION 9089
#ifdef BOTS
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9000
#else

View File

@ -131,6 +131,7 @@ OP_GuildPromote=0x2945
OP_GuildPublicNote=0x3c2c
OP_GuildManageBanker=0x389c # Was 0x096d
OP_GuildBank=0x2ab0 # Was 0x10c3
OP_GuildBankItemList=0x1cbf
OP_SetGuildRank=0x3599
OP_GuildUpdateURLAndChannel=0x7851
OP_GuildStatus=0x25a5
@ -235,6 +236,8 @@ OP_TargetHoTT=0x3af5
OP_XTargetResponse=0x7f64
OP_XTargetRequest=0x6753
OP_XTargetAutoAddHaters=0x5f51
OP_XTargetOpen=0x7423
OP_XTargetOpenResponse=0x27e8
OP_TargetBuffs=0x1c71
OP_BuffCreate=0x71f5
OP_BuffRemoveRequest=0x7efd

View File

@ -130,6 +130,7 @@ OP_GuildPromote=0x6a98
OP_GuildPublicNote=0x5053
OP_GuildManageBanker=0x3f35
OP_GuildBank=0x5134
OP_GuildBankItemList=0x7850
OP_SetGuildRank=0x0b9c
OP_GuildUpdateURLAndChannel=0x2958
OP_GuildStatus=0x7326
@ -235,6 +236,8 @@ OP_TargetBuffs=0x4f4b
OP_XTargetResponse=0x4d59
OP_XTargetRequest=0x3763
OP_XTargetAutoAddHaters=0x672f
OP_XTargetOpen=0x61df
OP_XTargetOpenResponse=0x3ef8
OP_BuffCreate=0x3377
OP_BuffRemoveRequest=0x64f2
OP_DeleteSpawn=0x7280

View File

@ -239,6 +239,8 @@ OP_TargetHoTT=0x790c # C
OP_XTargetResponse=0x6eb5 #
OP_XTargetRequest=0x4750 #
OP_XTargetAutoAddHaters=0x1a28 #
OP_XTargetOpen=0x11ae
OP_XTargetOpenResponse=0x45d3
OP_TargetBuffs=0x3f24 # C
OP_BuffCreate=0x2121 # V
OP_BuffRemoveRequest=0x4065

View File

@ -341,6 +341,8 @@
9085|2015_07_01_Marquee_Rule.sql|SELECT * FROM `rule_values` WHERE `rule_name` LIKE '%Character:MarqueeHPUpdates%'|empty|
9086|2015_07_02_aa_rework.sql|SHOW TABLES LIKE 'aa_ranks'|empty|
9087|2015_09_25_inventory_snapshots.sql|SHOW TABLES LIKE 'inventory_snapshots'|empty|
9088|2015_11_01_perl_event_export_settings.sql|SHOW TABLES LIKE 'perl_event_export_settings'|empty|
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|
# Upgrade conditions:
# This won't be needed after this system is implemented, but it is used database that are not

View File

@ -0,0 +1,95 @@
CREATE TABLE `perl_event_export_settings` (
`event_id` int(11) NOT NULL,
`event_description` varchar(150) DEFAULT NULL,
`export_qglobals` smallint(11) DEFAULT '0',
`export_mob` smallint(11) DEFAULT '0',
`export_zone` smallint(11) DEFAULT '0',
`export_item` smallint(11) DEFAULT '0',
`export_event` smallint(11) DEFAULT '0',
PRIMARY KEY (`event_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-- ----------------------------
-- Records of perl_event_export_settings
-- ----------------------------
INSERT INTO `perl_event_export_settings` VALUES ('0', 'EVENT_SAY', '1', '1', '1', '1', '1');
INSERT INTO `perl_event_export_settings` VALUES ('1', 'EVENT_ITEM', '1', '1', '1', '1', '1');
INSERT INTO `perl_event_export_settings` VALUES ('2', 'EVENT_DEATH', '1', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('3', 'EVENT_SPAWN', '1', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('4', 'EVENT_ATTACK', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('5', 'EVENT_COMBAT', '1', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('6', 'EVENT_AGGRO', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('7', 'EVENT_SLAY', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('8', 'EVENT_NPC_SLAY', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('9', 'EVENT_WAYPOINT_ARRIVE', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('10', 'EVENT_WAYPOINT_DEPART', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('11', 'EVENT_TIMER', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('12', 'EVENT_SIGNAL', '1', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('13', 'EVENT_HP', '1', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('14', 'EVENT_ENTER', '1', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('15', 'EVENT_EXIT', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('16', 'EVENT_ENTERZONE', '1', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('17', 'EVENT_CLICKDOOR', '1', '1', '1', '1', '1');
INSERT INTO `perl_event_export_settings` VALUES ('18', 'EVENT_LOOT', '1', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('19', 'EVENT_ZONE', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('20', 'EVENT_LEVEL_UP', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('21', 'EVENT_KILLED_MERIT', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('22', 'EVENT_CAST_ON', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('23', 'EVENT_TASKACCEPTED', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('24', 'EVENT_TASK_STAGE_COMPLETE', '1', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('25', 'EVENT_TASK_UPDATE', '1', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('26', 'EVENT_TASK_COMPLETE', '1', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('27', 'EVENT_TASK_FAIL', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('28', 'EVENT_AGGRO_SAY', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('29', 'EVENT_PLAYER_PICKUP', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('30', 'EVENT_POPUPRESPONSE', '1', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('31', 'EVENT_ENVIRONMENTAL_DAMAGE', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('32', 'EVENT_PROXIMITY_SAY', '1', '1', '1', '1', '1');
INSERT INTO `perl_event_export_settings` VALUES ('33', 'EVENT_CAST', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('34', 'EVENT_CAST_BEGIN', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('35', 'EVENT_SCALE_CALC', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('36', 'EVENT_ITEM_ENTER_ZONE', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('37', 'EVENT_TARGET_CHANGE', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('38', 'EVENT_HATE_LIST', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('39', 'EVENT_SPELL_EFFECT_CLIENT', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('40', 'EVENT_SPELL_EFFECT_NPC', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('41', 'EVENT_SPELL_EFFECT_BUFF_TIC_CLIENT', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('42', 'EVENT_SPELL_EFFECT_BUFF_TIC_NPC', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('43', 'EVENT_SPELL_FADE', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('44', 'EVENT_SPELL_EFFECT_TRANSLOCATE_COMPLETE', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('45', 'EVENT_COMBINE_SUCCESS', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('46', 'EVENT_COMBINE_FAILURE', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('47', 'EVENT_ITEM_CLICK', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('48', 'EVENT_ITEM_CLICK_CAST', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('49', 'EVENT_GROUP_CHANGE', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('50', 'EVENT_FORAGE_SUCCESS', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('51', 'EVENT_FORAGE_FAILURE', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('52', 'EVENT_FISH_START', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('53', 'EVENT_FISH_SUCCESS', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('54', 'EVENT_FISH_FAILURE', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('55', 'EVENT_CLICK_OBJECT', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('56', 'EVENT_DISCOVER_ITEM', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('57', 'EVENT_DISCONNECT', '1', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('58', 'EVENT_CONNECT', '1', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('59', 'EVENT_ITEM_TICK', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('60', 'EVENT_DUEL_WIN', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('61', 'EVENT_DUEL_LOSE', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('62', 'EVENT_ENCOUNTER_LOAD', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('63', 'EVENT_ENCOUNTER_UNLOAD', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('64', 'EVENT_SAY', '1', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('65', 'EVENT_DROP_ITEM', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('66', 'EVENT_DESTROY_ITEM', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('67', 'EVENT_FEIGN_DEATH', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('68', 'EVENT_WEAPON_PROC', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('69', 'EVENT_EQUIP_ITEM', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('70', 'EVENT_UNEQUIP_ITEM', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('71', 'EVENT_AUGMENT_ITEM', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('72', 'EVENT_UNAUGMENT_ITEM', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('73', 'EVENT_AUGMENT_INSERT', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('74', 'EVENT_AUGMENT_REMOVE', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('75', 'EVENT_ENTER_AREA', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('76', 'EVENT_LEAVE_AREA', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('77', 'EVENT_RESPAWN', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('78', 'EVENT_DEATH_COMPLETE', '1', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('79', 'EVENT_UNHANDLED_OPCODE', '0', '1', '1', '0', '1');
INSERT INTO `perl_event_export_settings` VALUES ('80', 'EVENT_TICK', '0', '1', '1', '0', '1');

View File

@ -0,0 +1,2 @@
UPDATE `rule_values` SET `rule_value` = '6000' WHERE `rule_value` = '500' AND `rule_name` = 'Spells:AI_IdleNoSpellMinRecast';
UPDATE `rule_values` SET `rule_value` = '60000' WHERE `rule_value` = '2000' AND `rule_name` = 'Spells:AI_IdleNoSpellMaxRecast';

View File

@ -283,57 +283,84 @@ void ZSList::ListLockedZones(const char* to, WorldTCPConnection* connection) {
}
void ZSList::SendZoneStatus(const char* to, int16 admin, WorldTCPConnection* connection) {
LinkedListIterator<ZoneServer*> iterator(list);
struct in_addr in;
iterator.Reset();
char locked[4];
if (WorldConfig::get()->Locked == true)
if (WorldConfig::get()->Locked == true){
strcpy(locked, "Yes");
else
}
else {
strcpy(locked, "No");
}
char* output = 0;
uint32 outsize = 0, outlen = 0;
if (connection->IsConsole())
if (connection->IsConsole()){
AppendAnyLenString(&output, &outsize, &outlen, "World Locked: %s\r\n", locked);
else
}
else{
AppendAnyLenString(&output, &outsize, &outlen, "World Locked: %s^", locked);
if (connection->IsConsole())
}
if (connection->IsConsole()){
AppendAnyLenString(&output, &outsize, &outlen, "Zoneservers online:\r\n");
else
}
else{
AppendAnyLenString(&output, &outsize, &outlen, "Zoneservers online:^");
// connection->SendEmoteMessage(to, 0, 0, 0, "World Locked: %s", locked);
// connection->SendEmoteMessage(to, 0, 0, 0, "Zoneservers online:");
int v=0, w=0, x=0, y=0, z=0;
char tmpStatic[2] = { 0, 0 }, tmpZone[64];
memset(tmpZone, 0, sizeof(tmpZone));
ZoneServer* zs = 0;
while(iterator.MoreElements()) {
zs = iterator.GetData();
in.s_addr = zs->GetIP();
}
if(zs->IsStaticZone())
int v = 0, w = 0, x = 0, y = 0, z = 0;
char is_static_string[2] = { 0, 0 }, zone_data_string[64];
memset(zone_data_string, 0, sizeof(zone_data_string));
ZoneServer* zone_server_data = 0;
while (iterator.MoreElements()) {
zone_server_data = iterator.GetData();
in.s_addr = zone_server_data->GetIP();
if (zone_server_data->IsStaticZone()){
z++;
else if (zs->GetZoneID() != 0)
}
else if (zone_server_data->GetZoneID() != 0){
w++;
else if(zs->GetZoneID() == 0 && !zs->IsBootingUp())
}
else if (zone_server_data->GetZoneID() == 0 && !zone_server_data->IsBootingUp()){
v++;
}
if (zs->IsStaticZone())
tmpStatic[0] = 'S';
if (zone_server_data->IsStaticZone())
is_static_string[0] = 'S';
else
tmpStatic[0] = ' ';
is_static_string[0] = 'D';
if (admin >= 150) {
if (zs->GetZoneID())
snprintf(tmpZone, sizeof(tmpZone), "%s (%i)", zs->GetZoneName(), zs->GetZoneID());
else if (zs->IsBootingUp())
strcpy(tmpZone, "...");
else
tmpZone[0] = 0;
if (zone_server_data->GetZoneID()){
snprintf(zone_data_string, sizeof(zone_data_string), "%s (%i)", zone_server_data->GetZoneName(), zone_server_data->GetZoneID());
}
else if (zone_server_data->IsBootingUp()){
strcpy(zone_data_string, "...");
}
else{
zone_data_string[0] = 0;
}
AppendAnyLenString(&output, &outsize, &outlen, " #%-3i %s %15s:%-5i %2i %s:%i %s", zs->GetID(), tmpStatic, inet_ntoa(in), zs->GetPort(), zs->NumPlayers(), zs->GetCAddress(), zs->GetCPort(), tmpZone);
AppendAnyLenString(&output, &outsize, &outlen,
"#%-3i :: %s :: %15s:%-5i :: %2i :: %s:%i :: %s :: (%u)",
zone_server_data->GetID(),
is_static_string,
inet_ntoa(in),
zone_server_data->GetPort(),
zone_server_data->NumPlayers(),
zone_server_data->GetCAddress(),
zone_server_data->GetCPort(),
zone_data_string,
zone_server_data->GetZoneOSProcessID()
);
if (outlen >= 3584) {
connection->SendEmoteMessageRaw(to, 0, 0, 10, output);
safe_delete(output);
@ -348,12 +375,12 @@ void ZSList::SendZoneStatus(const char* to, int16 admin, WorldTCPConnection* con
}
x++;
}
else if (zs->GetZoneID() != 0) {
if (zs->GetZoneID())
strcpy(tmpZone, zs->GetZoneName());
else if (zone_server_data->GetZoneID() != 0) {
if (zone_server_data->GetZoneID())
strcpy(zone_data_string, zone_server_data->GetZoneName());
else
tmpZone[0] = 0;
AppendAnyLenString(&output, &outsize, &outlen, " #%i %s %s", zs->GetID(), tmpStatic, tmpZone);
zone_data_string[0] = 0;
AppendAnyLenString(&output, &outsize, &outlen, " #%i %s %s", zone_server_data->GetID(), is_static_string, zone_data_string);
if (outlen >= 3584) {
connection->SendEmoteMessageRaw(to, 0, 0, 10, output);
safe_delete(output);
@ -361,25 +388,32 @@ void ZSList::SendZoneStatus(const char* to, int16 admin, WorldTCPConnection* con
outlen = 0;
}
else {
if (connection->IsConsole())
if (connection->IsConsole()){
AppendAnyLenString(&output, &outsize, &outlen, "\r\n");
else
}
else{
AppendAnyLenString(&output, &outsize, &outlen, "^");
}
}
x++;
}
y++;
iterator.Advance();
}
if (connection->IsConsole())
if (connection->IsConsole()){
AppendAnyLenString(&output, &outsize, &outlen, "%i servers listed. %i servers online.\r\n", x, y);
else
}
else {
AppendAnyLenString(&output, &outsize, &outlen, "%i servers listed. %i servers online.^", x, y);
AppendAnyLenString(&output, &outsize, &outlen, "%i zones are static zones, %i zones are booted zones, %i zones available.",z,w,v);
// connection->SendEmoteMessage(to, 0, 0, "%i servers listed. %i servers online.", x, y);
// connection->SendEmoteMessage(to,0,0,"%i zones are static zones, %i zones are booted zones, %i zones available.",z,w,v);
if (output)
}
AppendAnyLenString(&output, &outsize, &outlen, "%i zones are static zones, %i zones are booted zones, %i zones available.", z, w, v);
if (output){
connection->SendEmoteMessageRaw(to, 0, 0, 10, output);
}
safe_delete(output);
}

View File

@ -49,20 +49,24 @@ extern QueryServConnection QSLink;
void CatchSignal(int sig_num);
ZoneServer::ZoneServer(EmuTCPConnection* itcpc)
: WorldTCPConnection(), tcpc(itcpc), ls_zboot(5000) {
ID = zoneserver_list.GetNextID();
: WorldTCPConnection(), tcpc(itcpc), zone_boot_timer(5000) {
/* Set Process tracking variable defaults */
memset(zone_name, 0, sizeof(zone_name));
memset(compiled, 0, sizeof(compiled));
zoneID = 0;
instanceID = 0;
memset(client_address, 0, sizeof(client_address));
memset(client_local_address, 0, sizeof(client_local_address));
memset(clientaddress, 0, sizeof(clientaddress));
memset(clientlocaladdress, 0, sizeof(clientlocaladdress));
clientport = 0;
BootingUp = false;
authenticated = false;
staticzone = false;
pNumPlayers = 0;
zone_server_id = zoneserver_list.GetNextID();
zone_server_zone_id = 0;
instance_id = 0;
zone_os_process_id = 0;
client_port = 0;
is_booting_up = false;
is_authenticated = false;
is_static_zone = false;
zone_player_count = 0;
}
ZoneServer::~ZoneServer() {
@ -72,7 +76,7 @@ ZoneServer::~ZoneServer() {
}
bool ZoneServer::SetZone(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) {
BootingUp = false;
is_booting_up = false;
const char* zn = MakeLowerString(database.GetZoneName(iZoneID));
char* longname;
@ -81,17 +85,17 @@ bool ZoneServer::SetZone(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) {
Log.Out(Logs::Detail, Logs::World_Server,"Setting to '%s' (%d:%d)%s",(zn) ? zn : "",iZoneID, iInstanceID,
iStaticZone ? " (Static)" : "");
zoneID = iZoneID;
instanceID = iInstanceID;
zone_server_zone_id = iZoneID;
instance_id = iInstanceID;
if(iZoneID!=0)
oldZoneID = iZoneID;
if (zoneID == 0) {
zone_server_previous_zone_id = iZoneID;
if (zone_server_zone_id == 0) {
client_list.CLERemoveZSRef(this);
pNumPlayers = 0;
zone_player_count = 0;
LSSleepUpdate(GetPrevZoneID());
}
staticzone = iStaticZone;
is_static_zone = iStaticZone;
if (zn)
{
@ -111,7 +115,7 @@ bool ZoneServer::SetZone(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) {
}
client_list.ZoneBootup(this);
ls_zboot.Start();
zone_boot_timer.Start();
return true;
}
@ -172,19 +176,19 @@ void ZoneServer::LSSleepUpdate(uint32 zoneid){
bool ZoneServer::Process() {
if (!tcpc->Connected())
return false;
if(ls_zboot.Check()){
if(zone_boot_timer.Check()){
LSBootUpdate(GetZoneID(), true);
ls_zboot.Disable();
zone_boot_timer.Disable();
}
ServerPacket *pack = 0;
while((pack = tcpc->PopPacket())) {
if (!authenticated) {
if (!is_authenticated) {
if (WorldConfig::get()->SharedKey.length() > 0) {
if (pack->opcode == ServerOP_ZAAuth && pack->size == 16) {
uint8 tmppass[16];
MD5::Generate((const uchar*) WorldConfig::get()->SharedKey.c_str(), WorldConfig::get()->SharedKey.length(), tmppass);
if (memcmp(pack->pBuffer, tmppass, 16) == 0)
authenticated = true;
is_authenticated = true;
else {
struct in_addr in;
in.s_addr = GetIP();
@ -210,7 +214,7 @@ bool ZoneServer::Process() {
else
{
Log.Out(Logs::Detail, Logs::World_Server,"**WARNING** You have not configured a world shared key in your config file. You should add a <key>STRING</key> element to your <world> element to prevent unauthroized zone access.");
authenticated = true;
is_authenticated = true;
}
}
switch(pack->opcode) {
@ -582,29 +586,33 @@ bool ZoneServer::Process() {
ServerConnectInfo* sci = (ServerConnectInfo*) pack->pBuffer;
if (!sci->port) {
clientport = zoneserver_list.GetAvailableZonePort();
client_port = zoneserver_list.GetAvailableZonePort();
ServerPacket p(ServerOP_SetConnectInfo, sizeof(ServerConnectInfo));
memset(p.pBuffer,0,sizeof(ServerConnectInfo));
ServerConnectInfo* sci = (ServerConnectInfo*) p.pBuffer;
sci->port = clientport;
sci->port = client_port;
SendPacket(&p);
Log.Out(Logs::Detail, Logs::World_Server,"Auto zone port configuration. Telling zone to use port %d",clientport);
Log.Out(Logs::Detail, Logs::World_Server,"Auto zone port configuration. Telling zone to use port %d",client_port);
} else {
clientport = sci->port;
Log.Out(Logs::Detail, Logs::World_Server,"Zone specified port %d.",clientport);
client_port = sci->port;
Log.Out(Logs::Detail, Logs::World_Server,"Zone specified port %d.",client_port);
}
if(sci->address[0]) {
strn0cpy(clientaddress, sci->address, 250);
strn0cpy(client_address, sci->address, 250);
Log.Out(Logs::Detail, Logs::World_Server, "Zone specified address %s.", sci->address);
}
if(sci->local_address[0]) {
strn0cpy(clientlocaladdress, sci->local_address, 250);
strn0cpy(client_local_address, sci->local_address, 250);
Log.Out(Logs::Detail, Logs::World_Server, "Zone specified local address %s.", sci->address);
}
if (sci->process_id){
zone_os_process_id = sci->process_id;
}
}
case ServerOP_SetLaunchName: {
if(pack->size != sizeof(LaunchName_Struct))
@ -818,6 +826,11 @@ bool ZoneServer::Process() {
RuleManager::Instance()->LoadRules(&database, "default");
break;
}
case ServerOP_ReloadPerlExportSettings:
{
zoneserver_list.SendPacket(pack);
break;
}
case ServerOP_CameraShake:
{
zoneserver_list.SendPacket(pack);
@ -1411,13 +1424,13 @@ void ZoneServer::ChangeWID(uint32 iCharID, uint32 iWID) {
void ZoneServer::TriggerBootup(uint32 iZoneID, uint32 iInstanceID, const char* adminname, bool iMakeStatic) {
BootingUp = true;
zoneID = iZoneID;
instanceID = iInstanceID;
is_booting_up = true;
zone_server_zone_id = iZoneID;
instance_id = iInstanceID;
auto pack = new ServerPacket(ServerOP_ZoneBootup, sizeof(ServerZoneStateChange_struct));
ServerZoneStateChange_struct* s = (ServerZoneStateChange_struct *) pack->pBuffer;
s->ZoneServerID = ID;
s->ZoneServerID = zone_server_id;
if (adminname != 0)
strcpy(s->adminname, adminname);
@ -1434,7 +1447,7 @@ void ZoneServer::TriggerBootup(uint32 iZoneID, uint32 iInstanceID, const char* a
}
void ZoneServer::IncomingClient(Client* client) {
BootingUp = true;
is_booting_up = true;
auto pack = new ServerPacket(ServerOP_ZoneIncClient, sizeof(ServerZoneIncomingClient_Struct));
ServerZoneIncomingClient_Struct* s = (ServerZoneIncomingClient_Struct*) pack->pBuffer;
s->zoneid = GetZoneID();

View File

@ -44,7 +44,7 @@ public:
void LSBootUpdate(uint32 zoneid, uint32 iInstanceID = 0, bool startup = false);
void LSSleepUpdate(uint32 zoneid);
void LSShutDownUpdate(uint32 zoneid);
uint32 GetPrevZoneID() { return oldZoneID; }
uint32 GetPrevZoneID() { return zone_server_previous_zone_id; }
void ChangeWID(uint32 iCharID, uint32 iWID);
void SendGroupIDs();
@ -52,41 +52,45 @@ public:
inline const char* GetZoneLongName() const { return long_name; }
const char* GetCompileTime() const{ return compiled; }
void SetCompile(char* in_compile){ strcpy(compiled,in_compile); }
inline uint32 GetZoneID() const { return zoneID; }
inline uint32 GetZoneID() const { return zone_server_zone_id; }
inline uint32 GetIP() const { return tcpc->GetrIP(); }
inline uint16 GetPort() const { return tcpc->GetrPort(); }
inline const char* GetCAddress() const { return clientaddress; }
inline const char* GetCLocalAddress() const { return clientlocaladdress; }
inline uint16 GetCPort() const { return clientport; }
inline uint32 GetID() const { return ID; }
inline bool IsBootingUp() const { return BootingUp; }
inline bool IsStaticZone() const{ return staticzone; }
inline uint32 NumPlayers() const { return pNumPlayers; }
inline void AddPlayer() { pNumPlayers++; }
inline void RemovePlayer() { pNumPlayers--; }
inline const char* GetCAddress() const { return client_address; }
inline const char* GetCLocalAddress() const { return client_local_address; }
inline uint16 GetCPort() const { return client_port; }
inline uint32 GetID() const { return zone_server_id; }
inline bool IsBootingUp() const { return is_booting_up; }
inline bool IsStaticZone() const{ return is_static_zone; }
inline uint32 NumPlayers() const { return zone_player_count; }
inline void AddPlayer() { zone_player_count++; }
inline void RemovePlayer() { zone_player_count--; }
inline const char * GetLaunchName() const { return(launcher_name.c_str()); }
inline const char * GetLaunchedName() const { return(launched_name.c_str()); }
inline uint32 GetInstanceID() { return instanceID; }
inline void SetInstanceID(uint32 i) { instanceID = i; }
inline uint32 GetInstanceID() { return instance_id; }
inline void SetInstanceID(uint32 i) { instance_id = i; }
inline uint32 GetZoneOSProcessID() { return zone_os_process_id; }
private:
EmuTCPConnection* const tcpc;
uint32 ID;
char clientaddress[250];
char clientlocaladdress[250];
uint16 clientport;
bool BootingUp;
bool staticzone;
bool authenticated;
uint32 pNumPlayers;
uint32 zone_server_id;
char client_address[250];
char client_local_address[250];
uint16 client_port;
bool is_booting_up;
bool is_static_zone;
bool is_authenticated;
uint32 zone_player_count;
char compiled[25];
char zone_name[32];
char long_name[256];
uint32 zoneID;
uint32 oldZoneID;
Timer ls_zboot;
uint32 instanceID; //instance ids contain a zone id, and a zone version
uint32 zone_server_zone_id;
uint32 zone_server_previous_zone_id;
Timer zone_boot_timer;
uint32 instance_id; //instance ids contain a zone id, and a zone version
uint32 zone_os_process_id;
std::string launcher_name; //the launcher which started us
std::string launched_name; //the name of the zone we launched.
};

View File

@ -1189,21 +1189,21 @@ int32 Mob::CheckHealAggroAmount(uint16 spell_id, Mob *target, uint32 heal_possib
}
void Mob::AddFeignMemory(Client* attacker) {
if(feign_memory_list.empty() && AIfeignremember_timer != nullptr)
AIfeignremember_timer->Start(AIfeignremember_delay);
if(feign_memory_list.empty() && AI_feign_remember_timer != nullptr)
AI_feign_remember_timer->Start(AIfeignremember_delay);
feign_memory_list.insert(attacker->CharacterID());
}
void Mob::RemoveFromFeignMemory(Client* attacker) {
feign_memory_list.erase(attacker->CharacterID());
if(feign_memory_list.empty() && AIfeignremember_timer != nullptr)
AIfeignremember_timer->Disable();
if(feign_memory_list.empty() && AI_feign_remember_timer != nullptr)
AI_feign_remember_timer->Disable();
if(feign_memory_list.empty())
{
minLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMin);
maxLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMax);
if(AIfeignremember_timer != nullptr)
AIfeignremember_timer->Disable();
if(AI_feign_remember_timer != nullptr)
AI_feign_remember_timer->Disable();
}
}
@ -1220,8 +1220,8 @@ void Mob::ClearFeignMemory() {
feign_memory_list.clear();
minLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMin);
maxLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMax);
if(AIfeignremember_timer != nullptr)
AIfeignremember_timer->Disable();
if(AI_feign_remember_timer != nullptr)
AI_feign_remember_timer->Disable();
}
bool Mob::PassCharismaCheck(Mob* caster, uint16 spell_id) {

View File

@ -6,7 +6,7 @@
#include "quest_parser_collection.h"
#include "../common/string_util.h"
extern volatile bool ZoneLoaded;
extern volatile bool is_zone_loaded;
// This constructor is used during the bot create command
Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm::vec4(), 0, false), rest_timer(1) {
@ -2286,7 +2286,7 @@ bool Bot::Process() {
BuffProcess();
CalcRestState();
if(curfp)
if(currently_fleeing)
ProcessFlee();
if(GetHP() < GetMaxHP())
@ -2685,7 +2685,7 @@ void Bot::AI_Process() {
if(GetHasBeenSummoned()) {
if(IsBotCaster() || IsBotArcher()) {
if (AImovement_timer->Check()) {
if (AI_movement_timer->Check()) {
if(!GetTarget() || (IsBotCaster() && !IsBotCasterCombatRange(GetTarget())) || (IsBotArcher() && IsArcheryRange(GetTarget())) || (DistanceSquaredNoZ(static_cast<glm::vec3>(m_Position), m_PreSummonLocation) < 10)) {
if(GetTarget())
FaceTarget(GetTarget());
@ -2831,7 +2831,7 @@ void Bot::AI_Process() {
}
}
if(AImovement_timer->Check()) {
if(AI_movement_timer->Check()) {
if(!IsMoving() && GetClass() == ROGUE && !BehindMob(GetTarget(), GetX(), GetY())) {
// Move the rogue to behind the mob
float newX = 0;
@ -2967,7 +2967,7 @@ void Bot::AI_Process() {
AI_PursueCastCheck();
}
if (AImovement_timer->Check()) {
if (AI_movement_timer->Check()) {
if(!IsRooted()) {
Log.Out(Logs::Detail, Logs::AI, "Pursuing %s while engaged.", GetTarget()->GetCleanName());
CalculateNewPosition2(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), GetRunspeed());
@ -2995,7 +2995,7 @@ void Bot::AI_Process() {
if (m_PlayerState & static_cast<uint32>(PlayerState::Aggressive))
SendRemovePlayerState(PlayerState::Aggressive);
if(!IsMoving() && AIthink_timer->Check() && !spellend_timer.Enabled()) {
if(!IsMoving() && AI_think_timer->Check() && !spellend_timer.Enabled()) {
if(GetBotStance() != BotStancePassive) {
if(!AI_IdleCastCheck() && !IsCasting())
BotMeditate(true);
@ -3004,7 +3004,7 @@ void Bot::AI_Process() {
BotMeditate(true);
}
if(AImovement_timer->Check()) {
if(AI_movement_timer->Check()) {
if(GetFollowID()) {
Mob* follow = entity_list.GetMob(GetFollowID());
if(follow) {
@ -3737,9 +3737,9 @@ Bot* Bot::LoadBot(uint32 botID, std::string* errorMessage)
" `drakkin_tattoo`,"
" `drakkin_details`,"
" `ac`," /*not in-use[26]*/
" `atk`,"
" `atk`," /*not in-use[27]*/
" `hp`,"
" `mana`," /*not in-use[29]*/
" `mana`,"
" `str`," /*not in-use[30]*/
" `sta`," /*not in-use[31]*/
" `cha`," /*not in-use[32]*/
@ -3753,8 +3753,8 @@ Bot* Bot::LoadBot(uint32 botID, std::string* errorMessage)
" `poison`," /*not in-use[40]*/
" `disease`," /*not in-use[41]*/
" `corruption`," /*not in-use[42]*/
" `show_helm`,"
" `follow_distance`"
" `show_helm`,"//43
" `follow_distance`"//44
" FROM `bot_data`"
" WHERE `bot_id` = '%u'",
botID
@ -3791,8 +3791,8 @@ Bot* Bot::LoadBot(uint32 botID, std::string* errorMessage)
atoi(row[23]),
atoi(row[24]),
atoi(row[25]),
atoi(row[27]),
atoi(row[28]),
atoi(row[29]),
defaultNPCTypeStruct.MR,
defaultNPCTypeStruct.CR,
defaultNPCTypeStruct.DR,

View File

@ -53,7 +53,7 @@ extern volatile bool RunLoops;
extern QueryServ* QServ;
extern EntityList entity_list;
extern Zone* zone;
extern volatile bool ZoneLoaded;
extern volatile bool is_zone_loaded;
extern WorldServer worldserver;
extern uint32 numclients;
extern PetitionList petition_list;
@ -371,7 +371,7 @@ Client::~Client() {
GetTarget()->IsTargeted(-1);
//if we are in a group and we are not zoning, force leave the group
if(isgrouped && !zoning && ZoneLoaded)
if(isgrouped && !zoning && is_zone_loaded)
LeaveGroup();
UpdateWho(2);

View File

@ -66,7 +66,7 @@
extern QueryServ* QServ;
extern Zone* zone;
extern volatile bool ZoneLoaded;
extern volatile bool is_zone_loaded;
extern WorldServer worldserver;
extern PetitionList petition_list;
extern EntityList entity_list;
@ -386,6 +386,7 @@ void MapOpcodes()
ConnectedOpcodes[OP_WhoAllRequest] = &Client::Handle_OP_WhoAllRequest;
ConnectedOpcodes[OP_WorldUnknown001] = &Client::Handle_OP_Ignore;
ConnectedOpcodes[OP_XTargetAutoAddHaters] = &Client::Handle_OP_XTargetAutoAddHaters;
ConnectedOpcodes[OP_XTargetOpen] = &Client::Handle_OP_XTargetOpen;
ConnectedOpcodes[OP_XTargetRequest] = &Client::Handle_OP_XTargetRequest;
ConnectedOpcodes[OP_YellForHelp] = &Client::Handle_OP_YellForHelp;
ConnectedOpcodes[OP_ZoneChange] = &Client::Handle_OP_ZoneChange;
@ -6682,20 +6683,6 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app)
uint32 Action = VARSTRUCT_DECODE_TYPE(uint32, Buffer);
uint32 sentAction = Action;
if (GetClientVersion() >= ClientVersion::RoF)
{
Action += 1;
/*
// Need to find all of the action types for RoF and switch case here
switch(Action)
{
case 4:
Action = 5;
break;
}
*/
}
if (!IsInAGuild())
{
Message(13, "You must be in a Guild to use the Guild Bank.");
@ -13925,6 +13912,18 @@ void Client::Handle_OP_XTargetAutoAddHaters(const EQApplicationPacket *app)
XTargetAutoAddHaters = app->ReadUInt8(0);
}
void Client::Handle_OP_XTargetOpen(const EQApplicationPacket *app)
{
if (app->size != 4) {
Log.Out(Logs::General, Logs::None, "Size mismatch in OP_XTargetOpen, expected 1, got %i", app->size);
DumpPacket(app);
return;
}
auto outapp = new EQApplicationPacket(OP_XTargetOpenResponse, 0);
FastQueuePacket(&outapp);
}
void Client::Handle_OP_XTargetRequest(const EQApplicationPacket *app)
{
if (app->size < 12)

View File

@ -292,6 +292,7 @@
void Handle_OP_WearChange(const EQApplicationPacket *app);
void Handle_OP_WhoAllRequest(const EQApplicationPacket *app);
void Handle_OP_XTargetAutoAddHaters(const EQApplicationPacket *app);
void Handle_OP_XTargetOpen(const EQApplicationPacket *app);
void Handle_OP_XTargetRequest(const EQApplicationPacket *app);
void Handle_OP_YellForHelp(const EQApplicationPacket *app);
void Handle_OP_ZoneChange(const EQApplicationPacket *app);

View File

@ -55,7 +55,7 @@
extern QueryServ* QServ;
extern Zone* zone;
extern volatile bool ZoneLoaded;
extern volatile bool is_zone_loaded;
extern WorldServer worldserver;
extern PetitionList petition_list;
extern EntityList entity_list;

View File

@ -334,6 +334,7 @@ int command_init(void) {
command_add("reloadallrules", "Executes a reload of all rules.", 80, command_reloadallrules) ||
command_add("reloademote", "Reloads NPC Emotes", 80, command_reloademote) ||
command_add("reloadlevelmods", nullptr,255, command_reloadlevelmods) ||
command_add("reloadperlexportsettings", nullptr, 255, command_reloadperlexportsettings) ||
command_add("reloadqst", " - Clear quest cache (any argument causes it to also stop all timers)", 150, command_reloadqst) ||
command_add("reloadquest", " - Clear quest cache (any argument causes it to also stop all timers)", 150, command_reloadqst) ||
command_add("reloadrulesworld", "Executes a reload of all rules in world specifically.", 80, command_reloadworldrules) ||
@ -343,6 +344,7 @@ int command_init(void) {
command_add("reloadzonepoints", "- Reload zone points from database", 150, command_reloadzps) ||
command_add("reloadzps", nullptr,0, command_reloadzps) ||
command_add("repop", "[delay] - Repop the zone with optional delay", 100, command_repop) ||
command_add("repopclose", "[distance in units] Repops only NPC's nearby for fast development purposes", 100, command_repopclose) ||
command_add("resetaa", "- Resets a Player's AA in their profile and refunds spent AA's to unspent, may disconnect player.", 200, command_resetaa) ||
command_add("resetaa_timer", "Command to reset AA cooldown timers.", 200, command_resetaa_timer) ||
command_add("revoke", "[charname] [1/0] - Makes charname unable to talk on OOC", 200, command_revoke) ||
@ -3920,9 +3922,11 @@ void command_repop(Client *c, const Seperator *sep)
LinkedListIterator<Spawn2*> iterator(zone->spawn2_list);
iterator.Reset();
while (iterator.MoreElements()) {
std::string query = StringFormat("DELETE FROM respawn_times WHERE id = %lu AND instance_id = %lu",
(unsigned long)iterator.GetData()->GetID(),
(unsigned long)zone->GetInstanceID());
std::string query = StringFormat(
"DELETE FROM respawn_times WHERE id = %lu AND instance_id = %lu",
(unsigned long)iterator.GetData()->GetID(),
(unsigned long)zone->GetInstanceID()
);
auto results = database.QueryDatabase(query);
iterator.Advance();
}
@ -3939,6 +3943,33 @@ void command_repop(Client *c, const Seperator *sep)
zone->Repop(atoi(sep->arg[timearg])*1000);
}
void command_repopclose(Client *c, const Seperator *sep)
{
int repop_distance = 500;
if (sep->arg[1] && strcasecmp(sep->arg[1], "force") == 0) {
LinkedListIterator<Spawn2*> iterator(zone->spawn2_list);
iterator.Reset();
while (iterator.MoreElements()) {
std::string query = StringFormat(
"DELETE FROM respawn_times WHERE id = %lu AND instance_id = %lu",
(unsigned long)iterator.GetData()->GetID(),
(unsigned long)zone->GetInstanceID()
);
auto results = database.QueryDatabase(query);
iterator.Advance();
}
c->Message(0, "Zone depop: Force resetting spawn timers.");
}
if (sep->IsNumber(1)) {
repop_distance = atoi(sep->arg[1]);
}
c->Message(0, "Zone depoped. Repopping NPC's within %i distance units", repop_distance);
zone->RepopClose(c->GetPosition(), repop_distance);
}
void command_spawnstatus(Client *c, const Seperator *sep)
{
if((sep->arg[1][0] == 'e') | (sep->arg[1][0] == 'E'))
@ -10768,4 +10799,16 @@ void command_apply_shared_memory(Client *c, const Seperator *sep) {
strcpy((char*)pack.pBuffer, hotfix_name.c_str());
}
worldserver.SendPacket(&pack);
}
void command_reloadperlexportsettings(Client *c, const Seperator *sep)
{
if (c)
{
ServerPacket *pack = new ServerPacket(ServerOP_ReloadPerlExportSettings, 0);
worldserver.SendPacket(pack);
c->Message(13, "Successfully sent the packet to world to reload Perl Export settings");
safe_delete(pack);
}
}

View File

@ -187,6 +187,7 @@ void command_myskills(Client *c, const Seperator *sep);
void command_depop(Client *c, const Seperator *sep);
void command_depopzone(Client *c, const Seperator *sep);
void command_repop(Client *c, const Seperator *sep);
void command_repopclose(Client *c, const Seperator *sep);
void command_spawnstatus(Client *c, const Seperator *sep);
void command_nukebuffs(Client *c, const Seperator *sep);
void command_zuwcoords(Client *c, const Seperator *sep);
@ -332,6 +333,7 @@ void command_load_shared_memory(Client *c, const Seperator *sep);
void command_apply_shared_memory(Client *c, const Seperator *sep);
void command_untraindisc(Client *c, const Seperator *sep);
void command_untraindiscs(Client *c, const Seperator *sep);
void command_reloadperlexportsettings(Client *c, const Seperator *sep);
#ifdef EQPROFILE
void command_profiledump(Client *c, const Seperator *sep);

View File

@ -183,15 +183,31 @@ int PerlembParser::EventCommon(QuestEventID event, uint32 objid, const char * da
int char_id = 0;
ExportCharID(package_name, char_id, npcmob, mob);
ExportQGlobals(isPlayerQuest, isGlobalPlayerQuest, isGlobalNPC, isItemQuest, isSpellQuest,
package_name, npcmob, mob, char_id);
/* Check for QGlobal export event enable */
if (parse->perl_event_export_settings[event].qglobals){
ExportQGlobals(isPlayerQuest, isGlobalPlayerQuest, isGlobalNPC, isItemQuest, isSpellQuest, package_name, npcmob, mob, char_id);
}
//ExportGenericVariables();
ExportMobVariables(isPlayerQuest, isGlobalPlayerQuest, isGlobalNPC, isItemQuest, isSpellQuest,
package_name, mob, npcmob);
ExportZoneVariables(package_name);
ExportItemVariables(package_name, mob);
ExportEventVariables(package_name, event, objid, data, npcmob, iteminst, mob, extradata, extra_pointers);
/* Check for Mob export event enable */
if (parse->perl_event_export_settings[event].mob){
ExportMobVariables(isPlayerQuest, isGlobalPlayerQuest, isGlobalNPC, isItemQuest, isSpellQuest, package_name, mob, npcmob);
}
/* Check for Zone export event enable */
if (parse->perl_event_export_settings[event].zone){
ExportZoneVariables(package_name);
}
/* Check for Item export event enable */
if (parse->perl_event_export_settings[event].item){
ExportItemVariables(package_name, mob);
}
/* Check for Event export event enable */
if (parse->perl_event_export_settings[event].event_variables){
ExportEventVariables(package_name, event, objid, data, npcmob, iteminst, mob, extradata, extra_pointers);
}
if(isPlayerQuest || isGlobalPlayerQuest){
return SendCommands(package_name.c_str(), sub_name, 0, mob, mob, nullptr);
@ -199,8 +215,7 @@ int PerlembParser::EventCommon(QuestEventID event, uint32 objid, const char * da
else if(isItemQuest) {
return SendCommands(package_name.c_str(), sub_name, 0, mob, mob, iteminst);
}
else if(isSpellQuest)
{
else if(isSpellQuest){
if(mob) {
return SendCommands(package_name.c_str(), sub_name, 0, mob, mob, nullptr);
} else {

View File

@ -75,6 +75,7 @@ public:
virtual std::string GetVar(std::string name);
virtual void ReloadQuests();
virtual uint32 GetIdentifier() { return 0xf8b05c11; }
private:
Embperl *perl;

View File

@ -51,7 +51,7 @@
#endif
extern Zone *zone;
extern volatile bool ZoneLoaded;
extern volatile bool is_zone_loaded;
extern WorldServer worldserver;
extern NetConnection net;
extern uint32 numclients;
@ -2350,7 +2350,7 @@ void EntityList::Clear()
void EntityList::UpdateWho(bool iSendFullUpdate)
{
if ((!worldserver.Connected()) || !ZoneLoaded)
if ((!worldserver.Connected()) || !is_zone_loaded)
return;
uint32 tmpNumUpdates = numclients + 5;
ServerPacket* pack = 0;
@ -2448,6 +2448,8 @@ void EntityList::Depop(bool StartSpawnTimer)
if (pnpc->IsFindable())
UpdateFindableNPCState(pnpc, true);
pnpc->WipeHateList();
pnpc->Depop(StartSpawnTimer);
}
}

View File

@ -33,7 +33,7 @@ extern Zone* zone;
//this is called whenever we are damaged to process possible fleeing
void Mob::CheckFlee() {
//if were allready fleeing, dont need to check more...
if(flee_mode && curfp)
if(flee_mode && currently_fleeing)
return;
//dont bother if we are immune to fleeing
@ -101,7 +101,7 @@ void Mob::ProcessFlee()
//When ImmuneToFlee effect fades it will turn fear back on and check if it can still flee.
if (flee_mode && (GetSpecialAbility(IMMUNE_FLEEING) || spellbonuses.ImmuneToFlee) &&
!spellbonuses.IsFeared && !spellbonuses.IsBlind) {
curfp = false;
currently_fleeing = false;
return;
}
@ -118,7 +118,7 @@ void Mob::ProcessFlee()
//see if we are legitimately feared or blind now
if (!spellbonuses.IsFeared && !spellbonuses.IsBlind) {
//not feared or blind... were done...
curfp = false;
currently_fleeing = false;
return;
}
}
@ -140,7 +140,7 @@ void Mob::CalculateNewFearpoint()
if(Route.size() > 0)
{
m_FearWalkTarget = glm::vec3(Loc.x, Loc.y, Loc.z);
curfp = true;
currently_fleeing = true;
Log.Out(Logs::Detail, Logs::None, "Feared to node %i (%8.3f, %8.3f, %8.3f)", Node, Loc.x, Loc.y, Loc.z);
return;
@ -151,7 +151,7 @@ void Mob::CalculateNewFearpoint()
int loop = 0;
float ranx, rany, ranz;
curfp = false;
currently_fleeing = false;
while (loop < 100) //Max 100 tries
{
int ran = 250 - (loop*2);
@ -164,11 +164,11 @@ void Mob::CalculateNewFearpoint()
float fdist = ranz - GetZ();
if (fdist >= -12 && fdist <= 12 && CheckCoordLosNoZLeaps(GetX(),GetY(),GetZ(),ranx,rany,ranz))
{
curfp = true;
currently_fleeing = true;
break;
}
}
if (curfp)
if (currently_fleeing)
m_FearWalkTarget = glm::vec3(ranx, rany, ranz);
else //Break fear
BuffFadeByEffect(SE_Fear);

View File

@ -248,7 +248,9 @@ void Client::RefreshGuildInfo()
if((guild_id != OldGuildID) && GuildBanks)
{
ClearGuildBank();
// Unsure about this for RoF+ ... But they don't have that action anymore so fuck it
if (GetClientVersion() < ClientVersion::RoF)
ClearGuildBank();
if(guild_id != GUILD_NONE)
GuildBanks->SendGuildBank(this);

View File

@ -29,7 +29,7 @@ ZoneGuildManager guild_mgr;
GuildBankManager *GuildBanks;
extern WorldServer worldserver;
extern volatile bool ZoneLoaded;
extern volatile bool is_zone_loaded;
void ZoneGuildManager::SendGuildRefresh(uint32 guild_id, bool name, bool motd, bool rank, bool relation) {
Log.Out(Logs::Detail, Logs::Guilds, "Sending guild refresh for %d to world, changes: name=%d, motd=%d, rank=d, relation=%d", guild_id, name, motd, rank, relation);
@ -334,7 +334,7 @@ void ZoneGuildManager::ProcessWorldPacket(ServerPacket *pack) {
case ServerOP_GuildRankUpdate:
{
if(ZoneLoaded)
if(is_zone_loaded)
{
if(pack->size != sizeof(ServerGuildRankUpdate_Struct))
{
@ -388,7 +388,7 @@ void ZoneGuildManager::ProcessWorldPacket(ServerPacket *pack) {
{
ServerGuildMemberUpdate_Struct *sgmus = (ServerGuildMemberUpdate_Struct*)pack->pBuffer;
if(ZoneLoaded)
if(is_zone_loaded)
{
EQApplicationPacket *outapp = new EQApplicationPacket(OP_GuildMemberUpdate, sizeof(GuildMemberUpdate_Struct));
@ -407,7 +407,7 @@ void ZoneGuildManager::ProcessWorldPacket(ServerPacket *pack) {
break;
}
case ServerOP_OnlineGuildMembersResponse:
if (ZoneLoaded)
if (is_zone_loaded)
{
char *Buffer = (char *)pack->pBuffer;
@ -443,7 +443,7 @@ void ZoneGuildManager::ProcessWorldPacket(ServerPacket *pack) {
case ServerOP_LFGuildUpdate:
{
if(ZoneLoaded)
if(is_zone_loaded)
{
char GuildName[33];
char Comments[257];
@ -688,11 +688,68 @@ void GuildBankManager::SendGuildBank(Client *c)
return;
}
auto &guild_bank = *Iterator;
// RoF+ uses a bulk list packet -- This is also how the Action 0 of older clients basically works
if (c->GetClientVersionBit() & BIT_RoFAndLater) {
auto outapp = new EQApplicationPacket(OP_GuildBankItemList, sizeof(GuildBankItemListEntry_Struct) * 240);
for (int i = 0; i < GUILD_BANK_DEPOSIT_AREA_SIZE; ++i) {
const Item_Struct *Item = database.GetItem(guild_bank->Items.DepositArea[i].ItemID);
if (Item) {
outapp->WriteUInt8(1);
outapp->WriteUInt32(guild_bank->Items.DepositArea[i].Permissions);
outapp->WriteString(guild_bank->Items.DepositArea[i].WhoFor);
outapp->WriteString(guild_bank->Items.DepositArea[i].Donator);
outapp->WriteUInt32(Item->ID);
outapp->WriteUInt32(Item->Icon);
if (Item->Stackable) {
outapp->WriteUInt32(guild_bank->Items.DepositArea[i].Quantity);
outapp->WriteUInt8(Item->StackSize == guild_bank->Items.DepositArea[i].Quantity ? 0 : 1);
} else {
outapp->WriteUInt32(1);
outapp->WriteUInt8(0);
}
outapp->WriteUInt8(Item->IsEquipable(c->GetBaseRace(), c->GetBaseClass()) ? 1 : 0);
outapp->WriteString(Item->Name);
} else {
outapp->WriteUInt8(0); // empty
}
}
outapp->SetWritePosition(outapp->GetWritePosition() + 20); // newer clients have 40 deposit slots, keep them 0 for now
for (int i = 0; i < GUILD_BANK_MAIN_AREA_SIZE; ++i) {
const Item_Struct *Item = database.GetItem(guild_bank->Items.MainArea[i].ItemID);
if (Item) {
outapp->WriteUInt8(1);
outapp->WriteUInt32(guild_bank->Items.MainArea[i].Permissions);
outapp->WriteString(guild_bank->Items.MainArea[i].WhoFor);
outapp->WriteString(guild_bank->Items.MainArea[i].Donator);
outapp->WriteUInt32(Item->ID);
outapp->WriteUInt32(Item->Icon);
if (Item->Stackable) {
outapp->WriteUInt32(guild_bank->Items.MainArea[i].Quantity);
outapp->WriteUInt8(Item->StackSize == guild_bank->Items.MainArea[i].Quantity ? 0 : 1);
} else {
outapp->WriteUInt32(1);
outapp->WriteUInt8(0);
}
outapp->WriteUInt8(Item->IsEquipable(c->GetBaseRace(), c->GetBaseClass()) ? 1 : 0);
outapp->WriteString(Item->Name);
} else {
outapp->WriteUInt8(0); // empty
}
}
outapp->size = outapp->GetWritePosition(); // truncate to used size
c->FastQueuePacket(&outapp);
return;
}
for(int i = 0; i < GUILD_BANK_DEPOSIT_AREA_SIZE; ++i)
{
if((*Iterator)->Items.DepositArea[i].ItemID > 0)
if(guild_bank->Items.DepositArea[i].ItemID > 0)
{
const Item_Struct *Item = database.GetItem((*Iterator)->Items.DepositArea[i].ItemID);
const Item_Struct *Item = database.GetItem(guild_bank->Items.DepositArea[i].ItemID);
if(!Item)
continue;
@ -703,22 +760,22 @@ void GuildBankManager::SendGuildBank(Client *c)
if(!Item->Stackable)
gbius->Init(GuildBankItemUpdate, 1, i, GuildBankDepositArea, 1, Item->ID, Item->Icon, 1,
(*Iterator)->Items.DepositArea[i].Permissions, 0, 0);
guild_bank->Items.DepositArea[i].Permissions, 0, 0);
else
{
if((*Iterator)->Items.DepositArea[i].Quantity == Item->StackSize)
if(guild_bank->Items.DepositArea[i].Quantity == Item->StackSize)
gbius->Init(GuildBankItemUpdate, 1, i, GuildBankDepositArea, 1, Item->ID, Item->Icon,
(*Iterator)->Items.DepositArea[i].Quantity, (*Iterator)->Items.DepositArea[i].Permissions, 0, 0);
guild_bank->Items.DepositArea[i].Quantity, guild_bank->Items.DepositArea[i].Permissions, 0, 0);
else
gbius->Init(GuildBankItemUpdate, 1, i, GuildBankDepositArea, 1, Item->ID, Item->Icon,
(*Iterator)->Items.DepositArea[i].Quantity, (*Iterator)->Items.DepositArea[i].Permissions, 1, 0);
guild_bank->Items.DepositArea[i].Quantity, guild_bank->Items.DepositArea[i].Permissions, 1, 0);
}
strn0cpy(gbius->ItemName, Item->Name, sizeof(gbius->ItemName));
strn0cpy(gbius->Donator, (*Iterator)->Items.DepositArea[i].Donator, sizeof(gbius->Donator));
strn0cpy(gbius->Donator, guild_bank->Items.DepositArea[i].Donator, sizeof(gbius->Donator));
strn0cpy(gbius->WhoFor, (*Iterator)->Items.DepositArea[i].WhoFor, sizeof(gbius->WhoFor));
strn0cpy(gbius->WhoFor, guild_bank->Items.DepositArea[i].WhoFor, sizeof(gbius->WhoFor));
c->FastQueuePacket(&outapp);
}
@ -726,9 +783,9 @@ void GuildBankManager::SendGuildBank(Client *c)
for(int i = 0; i < GUILD_BANK_MAIN_AREA_SIZE; ++i)
{
if((*Iterator)->Items.MainArea[i].ItemID > 0)
if(guild_bank->Items.MainArea[i].ItemID > 0)
{
const Item_Struct *Item = database.GetItem((*Iterator)->Items.MainArea[i].ItemID);
const Item_Struct *Item = database.GetItem(guild_bank->Items.MainArea[i].ItemID);
if(!Item)
continue;
@ -741,22 +798,22 @@ void GuildBankManager::SendGuildBank(Client *c)
if(!Item->Stackable)
gbius->Init(GuildBankItemUpdate, 1, i, GuildBankMainArea, 1, Item->ID, Item->Icon, 1,
(*Iterator)->Items.MainArea[i].Permissions, 0, Useable);
guild_bank->Items.MainArea[i].Permissions, 0, Useable);
else
{
if((*Iterator)->Items.MainArea[i].Quantity == Item->StackSize)
if(guild_bank->Items.MainArea[i].Quantity == Item->StackSize)
gbius->Init(GuildBankItemUpdate, 1, i, GuildBankMainArea, 1, Item->ID, Item->Icon,
(*Iterator)->Items.MainArea[i].Quantity, (*Iterator)->Items.MainArea[i].Permissions, 0, Useable);
guild_bank->Items.MainArea[i].Quantity, guild_bank->Items.MainArea[i].Permissions, 0, Useable);
else
gbius->Init(GuildBankItemUpdate, 1, i, GuildBankMainArea, 1, Item->ID, Item->Icon,
(*Iterator)->Items.MainArea[i].Quantity, (*Iterator)->Items.MainArea[i].Permissions, 1, Useable);
guild_bank->Items.MainArea[i].Quantity, guild_bank->Items.MainArea[i].Permissions, 1, Useable);
}
strn0cpy(gbius->ItemName, Item->Name, sizeof(gbius->ItemName));
strn0cpy(gbius->Donator, (*Iterator)->Items.MainArea[i].Donator, sizeof(gbius->Donator));
strn0cpy(gbius->Donator, guild_bank->Items.MainArea[i].Donator, sizeof(gbius->Donator));
strn0cpy(gbius->WhoFor, (*Iterator)->Items.MainArea[i].WhoFor, sizeof(gbius->WhoFor));
strn0cpy(gbius->WhoFor, guild_bank->Items.MainArea[i].WhoFor, sizeof(gbius->WhoFor));
c->FastQueuePacket(&outapp);
}

View File

@ -18,7 +18,7 @@
#include "../common/string_util.h"
#include "../common/rulesys.h"
extern volatile bool ZoneLoaded;
extern volatile bool is_zone_loaded;
Merc::Merc(const NPCType* d, float x, float y, float z, float heading)
: NPC(d, nullptr, glm::vec4(x, y, z, heading), 0, false), endupkeep_timer(1000), rest_timer(1), confidence_timer(6000), check_target_timer(2000)
@ -1428,7 +1428,7 @@ void Merc::AI_Process() {
if(RuleB(Combat, EnableFearPathing)) {
CalculateNewFearpoint();
if(curfp) {
if(currently_fleeing) {
return;
}
}
@ -1500,7 +1500,7 @@ void Merc::AI_Process() {
}
}
if(AImovement_timer->Check())
if(AI_movement_timer->Check())
{
if(!IsMoving() && GetClass() == ROGUE && !BehindMob(GetTarget(), GetX(), GetY()))
{
@ -1645,7 +1645,7 @@ void Merc::AI_Process() {
AI_PursueCastCheck();
}
if (AImovement_timer->Check())
if (AI_movement_timer->Check())
{
if(!IsRooted()) {
Log.Out(Logs::Detail, Logs::AI, "Pursuing %s while engaged.", GetTarget()->GetCleanName());
@ -1687,7 +1687,7 @@ void Merc::AI_Process() {
if(!check_target_timer.Enabled())
check_target_timer.Start(2000, false);
if(!IsMoving() && AIthink_timer->Check() && !spellend_timer.Enabled())
if(!IsMoving() && AI_think_timer->Check() && !spellend_timer.Enabled())
{
//TODO: Implement passive stances.
//if(GetStance() != MercStancePassive) {
@ -1698,7 +1698,7 @@ void Merc::AI_Process() {
}
}
if(AImovement_timer->Check())
if(AI_movement_timer->Check())
{
if(GetFollowID())
{
@ -5777,7 +5777,7 @@ bool Merc::RemoveMercFromGroup(Merc* merc, Group* group) {
{
merc->SetFollowID(0);
if (group->GroupCount() <= 2 && merc->GetGroup() == group && ZoneLoaded)
if (group->GroupCount() <= 2 && merc->GetGroup() == group && is_zone_loaded)
{
group->DisbandGroup();
}

View File

@ -192,6 +192,7 @@ public:
virtual void ScaleStats(int scalepercent, bool setmax = false);
virtual void CalcBonuses();
int32 GetEndurance() const {return cur_end;} //This gets our current endurance
inline uint8 GetEndurancePercent() { return (uint8)((float)cur_end / (float)max_end * 100.0f); }
inline virtual int32 GetAC() const { return AC; }
inline virtual int32 GetATK() const { return ATK; }
inline virtual int32 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; }

View File

@ -113,7 +113,7 @@ Mob::Mob(const char* in_name,
targeted = 0;
tar_ndx=0;
tar_vector=0;
curfp = false;
currently_fleeing = false;
AI_Init();
SetMoving(false);
@ -371,7 +371,7 @@ Mob::Mob(const char* in_name,
follow=0;
follow_dist = 100; // Default Distance for Follow
flee_mode = false;
curfp = false;
currently_fleeing = false;
flee_timer.Start();
permarooted = (runspeed > 0) ? false : true;
@ -503,13 +503,9 @@ void Mob::SetInvisible(uint8 state)
SendAppearancePacket(AT_Invis, invisible);
// Invis and hide breaks charms
if ((this->GetPetType() == petCharmed) && (invisible || hidden || improved_hidden))
{
Mob* formerpet = this->GetPet();
if(formerpet)
formerpet->BuffFadeByEffect(SE_Charm);
}
auto formerpet = GetPet();
if (formerpet && formerpet->GetPetType() == petCharmed && (invisible || hidden || improved_hidden))
formerpet->BuffFadeByEffect(SE_Charm);
}
//check to see if `this` is invisible to `other`

View File

@ -925,8 +925,8 @@ public:
virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther) { return FACTION_INDIFFERENT; }
inline bool IsTrackable() const { return(trackable); }
Timer* GetAIThinkTimer() { return AIthink_timer.get(); }
Timer* GetAIMovementTimer() { return AImovement_timer.get(); }
Timer* GetAIThinkTimer() { return AI_think_timer.get(); }
Timer* GetAIMovementTimer() { return AI_movement_timer.get(); }
Timer GetAttackTimer() { return attack_timer; }
Timer GetAttackDWTimer() { return attack_dw_timer; }
inline bool IsFindable() { return findable; }
@ -1254,14 +1254,15 @@ protected:
uint32 maxLastFightingDelayMoving;
float pAggroRange;
float pAssistRange;
std::unique_ptr<Timer> AIthink_timer;
std::unique_ptr<Timer> AImovement_timer;
std::unique_ptr<Timer> AItarget_check_timer;
std::unique_ptr<Timer> AI_think_timer;
std::unique_ptr<Timer> AI_movement_timer;
std::unique_ptr<Timer> AI_target_check_timer;
bool movetimercompleted;
bool permarooted;
std::unique_ptr<Timer> AIscanarea_timer;
std::unique_ptr<Timer> AIwalking_timer;
std::unique_ptr<Timer> AIfeignremember_timer;
std::unique_ptr<Timer> AI_scan_area_timer;
std::unique_ptr<Timer> AI_walking_timer;
std::unique_ptr<Timer> AI_feign_remember_timer;
std::unique_ptr<Timer> AI_check_signal_timer;
uint32 pLastFightingDelayMoving;
HateList hate_list;
std::set<uint32> feign_memory_list;
@ -1295,7 +1296,7 @@ protected:
int patrol;
glm::vec3 m_FearWalkTarget;
bool curfp;
bool currently_fleeing;
// Pathing
//

View File

@ -423,12 +423,14 @@ bool EntityList::AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float
void Mob::AI_Init()
{
pAIControlled = false;
AIthink_timer.reset(nullptr);
AIwalking_timer.reset(nullptr);
AImovement_timer.reset(nullptr);
AItarget_check_timer.reset(nullptr);
AIfeignremember_timer.reset(nullptr);
AIscanarea_timer.reset(nullptr);
AI_think_timer.reset(nullptr);
AI_walking_timer.reset(nullptr);
AI_movement_timer.reset(nullptr);
AI_target_check_timer.reset(nullptr);
AI_feign_remember_timer.reset(nullptr);
AI_scan_area_timer.reset(nullptr);
AI_check_signal_timer.reset(nullptr);
minLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMin);
maxLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMax);
@ -472,16 +474,18 @@ void Mob::AI_Start(uint32 iMoveDelay) {
pLastFightingDelayMoving = 0;
pAIControlled = true;
AIthink_timer = std::unique_ptr<Timer>(new Timer(AIthink_duration));
AIthink_timer->Trigger();
AIwalking_timer = std::unique_ptr<Timer>(new Timer(0));
AImovement_timer = std::unique_ptr<Timer>(new Timer(AImovement_duration));
AItarget_check_timer = std::unique_ptr<Timer>(new Timer(AItarget_check_duration));
AIfeignremember_timer = std::unique_ptr<Timer>(new Timer(AIfeignremember_delay));
AIscanarea_timer = std::unique_ptr<Timer>(new Timer(AIscanarea_delay));
AI_think_timer = std::unique_ptr<Timer>(new Timer(AIthink_duration));
AI_think_timer->Trigger();
AI_walking_timer = std::unique_ptr<Timer>(new Timer(0));
AI_movement_timer = std::unique_ptr<Timer>(new Timer(AImovement_duration));
AI_target_check_timer = std::unique_ptr<Timer>(new Timer(AItarget_check_duration));
AI_feign_remember_timer = std::unique_ptr<Timer>(new Timer(AIfeignremember_delay));
AI_scan_area_timer = std::unique_ptr<Timer>(new Timer(RandomTimer(RuleI(NPC, NPCToNPCAggroTimerMin), RuleI(NPC, NPCToNPCAggroTimerMax))));
AI_check_signal_timer = std::unique_ptr<Timer>(new Timer(AI_check_signal_timer_delay));
#ifdef REVERSE_AGGRO
if(IsNPC() && !CastToNPC()->WillAggroNPCs())
AIscanarea_timer->Disable();
AI_scan_area_timer->Disable();
#endif
if (GetAggroRange() == 0)
@ -538,12 +542,13 @@ void Mob::AI_Stop() {
pAIControlled = false;
AIthink_timer.reset(nullptr);
AIwalking_timer.reset(nullptr);
AImovement_timer.reset(nullptr);
AItarget_check_timer.reset(nullptr);
AIscanarea_timer.reset(nullptr);
AIfeignremember_timer.reset(nullptr);
AI_think_timer.reset(nullptr);
AI_walking_timer.reset(nullptr);
AI_movement_timer.reset(nullptr);
AI_target_check_timer.reset(nullptr);
AI_scan_area_timer.reset(nullptr);
AI_feign_remember_timer.reset(nullptr);
AI_check_signal_timer.reset(nullptr);
hate_list.WipeHateList();
}
@ -725,7 +730,7 @@ void Client::AI_Process()
if (!IsAIControlled())
return;
if (!(AIthink_timer->Check() || attack_timer.Check(false)))
if (!(AI_think_timer->Check() || attack_timer.Check(false)))
return;
if (IsCasting())
@ -759,7 +764,7 @@ void Client::AI_Process()
}
if(RuleB(Combat, EnableFearPathing)){
if(curfp) {
if(currently_fleeing) {
if(IsRooted()) {
//make sure everybody knows were not moving, for appearance sake
if(IsMoving())
@ -771,7 +776,7 @@ void Client::AI_Process()
//continue on to attack code, ensuring that we execute the engaged code
engaged = true;
} else {
if(AImovement_timer->Check()) {
if(AI_movement_timer->Check()) {
int speed = GetFearSpeed();
animation = speed;
speed *= 2;
@ -808,7 +813,7 @@ void Client::AI_Process()
SetTarget(hate_list.GetClosestEntOnHateList(this));
else
{
if(AItarget_check_timer->Check())
if(AI_target_check_timer->Check())
{
SetTarget(hate_list.GetEntWithMostHateOnList(this));
}
@ -832,7 +837,7 @@ void Client::AI_Process()
DoClassAttacks(GetTarget());
}
if (AImovement_timer->Check()) {
if (AI_movement_timer->Check()) {
if (CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()) !=
m_Position.w) {
SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()));
@ -858,7 +863,7 @@ void Client::AI_Process()
} else {
if(!IsRooted())
{
if(AImovement_timer->Check())
if(AI_movement_timer->Check())
{
int newspeed = GetRunspeed();
animation = newspeed;
@ -889,7 +894,7 @@ void Client::AI_Process()
}
else
{
if(AIfeignremember_timer->Check()) {
if(AI_feign_remember_timer->Check()) {
std::set<uint32>::iterator RememberedCharID;
RememberedCharID = feign_memory_list.begin();
while (RememberedCharID != feign_memory_list.end()) {
@ -917,7 +922,7 @@ void Client::AI_Process()
float dist = DistanceSquared(m_Position, owner->GetPosition());
if (dist >= 400)
{
if(AImovement_timer->Check())
if(AI_movement_timer->Check())
{
int nspeed = (dist >= 5625 ? GetRunspeed() : GetWalkspeed());
animation = nspeed;
@ -943,7 +948,7 @@ void Mob::AI_Process() {
if (!IsAIControlled())
return;
if (!(AIthink_timer->Check() || attack_timer.Check(false)))
if (!(AI_think_timer->Check() || attack_timer.Check(false)))
return;
if (IsCasting())
@ -955,7 +960,7 @@ void Mob::AI_Process() {
// Begin: Additions for Wiz Fear Code
//
if(RuleB(Combat, EnableFearPathing)){
if(curfp) {
if(currently_fleeing) {
if(IsRooted() || (IsBlind() && CombatRange(hate_list.GetClosestEntOnHateList(this)))) {
//make sure everybody knows were not moving, for appearance sake
if(IsMoving())
@ -968,7 +973,7 @@ void Mob::AI_Process() {
//continue on to attack code, ensuring that we execute the engaged code
engaged = true;
} else {
if(AImovement_timer->Check()) {
if(AI_movement_timer->Check()) {
// Check if we have reached the last fear point
if ((std::abs(GetX() - m_FearWalkTarget.x) < 0.1) &&
(std::abs(GetY() - m_FearWalkTarget.y) < 0.1)) {
@ -998,7 +1003,7 @@ void Mob::AI_Process() {
}
// trigger EVENT_SIGNAL if required
if(IsNPC()) {
if (AI_check_signal_timer->Check() && IsNPC()) {
CastToNPC()->CheckSignal();
}
@ -1012,7 +1017,7 @@ void Mob::AI_Process() {
SetTarget(hate_list.GetClosestEntOnHateList(this));
else
{
if(AItarget_check_timer->Check())
if(AI_target_check_timer->Check())
{
if (IsFocused()) {
if (!target) {
@ -1074,7 +1079,7 @@ void Mob::AI_Process() {
if (is_combat_range)
{
if (AImovement_timer->Check())
if (AI_movement_timer->Check())
{
if(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()) != m_Position.w)
{
@ -1268,7 +1273,7 @@ void Mob::AI_Process() {
WipeHateList();
Heal();
BuffFadeAll();
AIwalking_timer->Start(100);
AI_walking_timer->Start(100);
pLastFightingDelayMoving = Timer::GetCurrentTime();
return;
} else if(tar != nullptr) {
@ -1290,7 +1295,7 @@ void Mob::AI_Process() {
if(AI_PursueCastCheck()){
//we did something, so do not process movement.
}
else if (AImovement_timer->Check())
else if (AI_movement_timer->Check())
{
if(!IsRooted()) {
Log.Out(Logs::Detail, Logs::AI, "Pursuing %s while engaged.", target->GetName());
@ -1323,7 +1328,7 @@ void Mob::AI_Process() {
{
if (m_PlayerState & static_cast<uint32>(PlayerState::Aggressive))
SendRemovePlayerState(PlayerState::Aggressive);
if(AIfeignremember_timer->Check()) {
if(AI_feign_remember_timer->Check()) {
// 6/14/06
// Improved Feign Death Memory
// check to see if any of our previous feigned targets have gotten up.
@ -1348,7 +1353,7 @@ void Mob::AI_Process() {
{
//we processed a spell action, so do nothing else.
}
else if (AIscanarea_timer->Check())
else if (AI_scan_area_timer->Check())
{
/*
* This is where NPCs look around to see if they want to attack anybody.
@ -1359,11 +1364,16 @@ void Mob::AI_Process() {
*
*/
Mob* tmptar = entity_list.AICheckCloseAggro(this, GetAggroRange(), GetAssistRange());
if (tmptar)
AddToHateList(tmptar);
Mob* temp_target = entity_list.AICheckCloseAggro(this, GetAggroRange(), GetAssistRange());
if (temp_target){
AddToHateList(temp_target);
}
AI_scan_area_timer->Disable();
AI_scan_area_timer->Start(RandomTimer(RuleI(NPC, NPCToNPCAggroTimerMin), RuleI(NPC, NPCToNPCAggroTimerMax)), false);
}
else if (AImovement_timer->Check() && !IsRooted())
else if (AI_movement_timer->Check() && !IsRooted())
{
if (IsPet())
{
@ -1534,10 +1544,10 @@ void NPC::AI_DoMovement() {
}
else if (roamer)
{
if (AIwalking_timer->Check())
if (AI_walking_timer->Check())
{
movetimercompleted=true;
AIwalking_timer->Disable();
AI_walking_timer->Disable();
}
@ -1547,7 +1557,7 @@ void NPC::AI_DoMovement() {
if (movetimercompleted==true) { // time to pause at wp is over
AI_SetupNextWaypoint();
} // endif (movetimercompleted==true)
else if (!(AIwalking_timer->Enabled()))
else if (!(AI_walking_timer->Enabled()))
{ // currently moving
bool doMove = true;
if (m_CurrentWayPoint.x == GetX() && m_CurrentWayPoint.y == GetY())
@ -1568,7 +1578,7 @@ void NPC::AI_DoMovement() {
sprintf(temp, "%d", cur_wp);
parse->EventNPC(EVENT_WAYPOINT_ARRIVE, CastToNPC(), nullptr, temp, 0);
// start moving directly to next waypoint if we're at a 0 pause waypoint and we didn't get quest halted.
if (!AIwalking_timer->Enabled())
if (!AI_walking_timer->Enabled())
AI_SetupNextWaypoint();
else
doMove = false;
@ -1759,7 +1769,7 @@ void Mob::AI_Event_Engaged(Mob* attacker, bool iYellForHelp) {
void Mob::AI_Event_NoLongerEngaged() {
if (!IsAIControlled())
return;
this->AIwalking_timer->Start(RandomTimer(3000,20000));
this->AI_walking_timer->Start(RandomTimer(3000,20000));
pLastFightingDelayMoving = Timer::GetCurrentTime();
if (minLastFightingDelayMoving == maxLastFightingDelayMoving)
pLastFightingDelayMoving += minLastFightingDelayMoving;
@ -1856,15 +1866,15 @@ bool NPC::AI_PursueCastCheck() {
bool NPC::AI_IdleCastCheck() {
if (AIautocastspell_timer->Check(false)) {
#if MobAI_DEBUG_Spells >= 25
std::cout << "Non-Engaged autocast check triggered: " << this->GetName() << std::endl;
#endif
AIautocastspell_timer->Disable(); //prevent the timer from going off AGAIN while we are casting.
if (!AICastSpell(this, AISpellVar.idle_beneficial_chance, SpellType_Heal | SpellType_Buff | SpellType_Pet)) {
if(!entity_list.AICheckCloseBeneficialSpells(this, 33, MobAISpellRange, SpellType_Heal | SpellType_Buff)) {
//if we didnt cast any spells, our autocast timer just resets to the
//last duration it was set to... try to put up a more reasonable timer...
AIautocastspell_timer->Start(RandomTimer(AISpellVar.idle_no_sp_recast_min, AISpellVar.idle_no_sp_recast_max), false);
Log.Out(Logs::Moderate, Logs::Spells, "Triggering AI_IdleCastCheck :: Mob %s - Min : %u Max : %u", this->GetCleanName(), AISpellVar.idle_no_sp_recast_min, AISpellVar.idle_no_sp_recast_max);
} //else, spell casting finishing will reset the timer.
} //else, spell casting finishing will reset the timer.
return(true);

View File

@ -84,7 +84,7 @@
#endif
volatile bool RunLoops = true;
extern volatile bool ZoneLoaded;
extern volatile bool is_zone_loaded;
TimeoutManager timeout_manager;
NetConnection net;
@ -110,6 +110,7 @@ extern void MapOpcodes();
int main(int argc, char** argv) {
RegisterExecutablePlatform(ExePlatformZone);
Log.LoadLogSettingsDefaults();
set_exception_handler();
QServ = new QueryServ;
@ -339,6 +340,10 @@ int main(int argc, char** argv) {
#ifdef EMBPERL
PerlembParser *perl_parser = new PerlembParser();
parse->RegisterQuestInterface(perl_parser, "pl");
/* Load Perl Event Export Settings */
parse->LoadPerlEventExportSettings(parse->perl_event_export_settings);
#endif
//now we have our parser, load the quests
@ -388,10 +393,10 @@ int main(int argc, char** argv) {
worldserver.Process();
if (!eqsf.IsOpen() && Config->ZonePort!=0) {
Log.Out(Logs::General, Logs::Zone_Server, "Starting EQ Network server on port %d",Config->ZonePort);
if (!eqsf.IsOpen() && Config->ZonePort != 0) {
Log.Out(Logs::General, Logs::Zone_Server, "Starting EQ Network server on port %d", Config->ZonePort);
if (!eqsf.Open(Config->ZonePort)) {
Log.Out(Logs::General, Logs::Error, "Failed to open port %d",Config->ZonePort);
Log.Out(Logs::General, Logs::Error, "Failed to open port %d", Config->ZonePort);
ZoneConfig::SetZonePort(0);
worldserver.Disconnect();
worldwasconnected = false;
@ -405,7 +410,7 @@ int main(int argc, char** argv) {
//structures and opcodes for that patch.
struct in_addr in;
in.s_addr = eqss->GetRemoteIP();
Log.Out(Logs::Detail, Logs::World_Server, "New connection from %s:%d", inet_ntoa(in),ntohs(eqss->GetRemotePort()));
Log.Out(Logs::Detail, Logs::World_Server, "New connection from %s:%d", inet_ntoa(in), ntohs(eqss->GetRemotePort()));
stream_identifier.AddStream(eqss); //takes the stream
}
@ -437,12 +442,12 @@ int main(int argc, char** argv) {
worldwasconnected = true;
}
else {
if (worldwasconnected && ZoneLoaded)
if (worldwasconnected && is_zone_loaded)
entity_list.ChannelMessageFromWorld(0, 0, 6, 0, 0, "WARNING: World server connection lost");
worldwasconnected = false;
}
if (ZoneLoaded && zoneupdate_timer.Check()) {
if (is_zone_loaded && zoneupdate_timer.Check()) {
{
if(net.group_timer.Enabled() && net.group_timer.Check())
entity_list.GroupProcess();

View File

@ -53,7 +53,7 @@
#endif
extern Zone* zone;
extern volatile bool ZoneLoaded;
extern volatile bool is_zone_loaded;
extern EntityList entity_list;
NPC::NPC(const NPCType* d, Spawn2* in_respawn, const glm::vec4& position, int iflymode, bool IsCorpse)
@ -605,7 +605,7 @@ bool NPC::Process()
parse->EventNPC(EVENT_TICK, this, nullptr, "", 0);
BuffProcess();
if(curfp)
if(currently_fleeing)
ProcessFlee();
uint32 bonus = 0;

View File

@ -1032,3 +1032,42 @@ int QuestParserCollection::DispatchEventSpell(QuestEventID evt, NPC* npc, Client
}
return ret;
}
void QuestParserCollection::LoadPerlEventExportSettings(PerlEventExportSettings* perl_event_export_settings) {
Log.Out(Logs::General, Logs::Zone_Server, "Loading Perl Event Export Settings...");
/* Write Defaults First (All Enabled) */
for (int i = 0; i < _LargestEventID; i++){
perl_event_export_settings[i].qglobals = 1;
perl_event_export_settings[i].mob = 1;
perl_event_export_settings[i].zone = 1;
perl_event_export_settings[i].item = 1;
perl_event_export_settings[i].event_variables = 1;
}
std::string query =
"SELECT "
"event_id, "
"event_description, "
"export_qglobals, "
"export_mob, "
"export_zone, "
"export_item, "
"export_event "
"FROM "
"perl_event_export_settings "
"ORDER BY event_id";
int event_id = 0;
auto results = database.QueryDatabase(query);
for (auto row = results.begin(); row != results.end(); ++row) {
event_id = atoi(row[0]);
perl_event_export_settings[event_id].qglobals = atoi(row[2]);
perl_event_export_settings[event_id].mob = atoi(row[3]);
perl_event_export_settings[event_id].zone = atoi(row[4]);
perl_event_export_settings[event_id].item = atoi(row[5]);
perl_event_export_settings[event_id].event_variables = atoi(row[6]);
}
}

View File

@ -77,6 +77,27 @@ public:
void GetErrors(std::list<std::string> &err);
/*
Internally used memory reference for all Perl Event Export Settings
Some exports are very taxing on CPU given how much an event is called.
These are loaded via DB and have defaults loaded in PerlEventExportSettingsDefaults.
Database loaded via Database::LoadPerlEventExportSettings(log_settings)
*/
struct PerlEventExportSettings {
uint8 qglobals;
uint8 mob;
uint8 zone;
uint8 item;
uint8 event_variables;
};
PerlEventExportSettings perl_event_export_settings[_LargestEventID];
void LoadPerlEventExportSettings(PerlEventExportSettings* perl_event_export_settings);
private:
bool HasQuestSubLocal(uint32 npcid, QuestEventID evt);
bool HasQuestSubGlobal(QuestEventID evt);

View File

@ -351,6 +351,112 @@ void Spawn2::DeathReset(bool realdeath)
}
}
bool ZoneDatabase::PopulateZoneSpawnListClose(uint32 zoneid, LinkedList<Spawn2*> &spawn2_list, int16 version, const glm::vec4& client_position, uint32 repop_distance)
{
std::unordered_map<uint32, uint32> spawn_times;
float mob_distance = 0;
timeval tv;
gettimeofday(&tv, nullptr);
/* Bulk Load NPC Types Data into the cache */
database.LoadNPCTypesData(0, true);
std::string spawn_query = StringFormat(
"SELECT "
"respawn_times.id, "
"respawn_times.`start`, "
"respawn_times.duration "
"FROM "
"respawn_times "
"WHERE instance_id = %u",
zone->GetInstanceID()
);
auto results = QueryDatabase(spawn_query);
for (auto row = results.begin(); row != results.end(); ++row) {
uint32 start_duration = atoi(row[1]) > 0 ? atoi(row[1]) : 0;
uint32 end_duration = atoi(row[2]) > 0 ? atoi(row[2]) : 0;
/* Our current time was expired */
if ((start_duration + end_duration) <= tv.tv_sec) {
spawn_times[atoi(row[0])] = 0;
}
/* We still have time left on this timer */
else {
spawn_times[atoi(row[0])] = ((start_duration + end_duration) - tv.tv_sec) * 1000;
}
}
const char *zone_name = database.GetZoneName(zoneid);
std::string query = StringFormat(
"SELECT "
"id, "
"spawngroupID, "
"x, "
"y, "
"z, "
"heading, "
"respawntime, "
"variance, "
"pathgrid, "
"_condition, "
"cond_value, "
"enabled, "
"animation "
"FROM "
"spawn2 "
"WHERE zone = '%s' AND version = %u",
zone_name,
version
);
results = QueryDatabase(query);
if (!results.Success()) {
return false;
}
for (auto row = results.begin(); row != results.end(); ++row) {
uint32 spawn_time_left = 0;
Spawn2* new_spawn = 0;
bool perl_enabled = atoi(row[11]) == 1 ? true : false;
if (spawn_times.count(atoi(row[0])) != 0)
spawn_time_left = spawn_times[atoi(row[0])];
glm::vec4 point;
point.x = atof(row[2]);
point.y = atof(row[3]);
mob_distance = DistanceNoZ(client_position, point);
if (mob_distance > repop_distance)
continue;
new_spawn = new Spawn2( //
atoi(row[0]), // uint32 in_spawn2_id
atoi(row[1]), // uint32 spawngroup_id
atof(row[2]), // float in_x
atof(row[3]), // float in_y
atof(row[4]), // float in_z
atof(row[5]), // float in_heading
atoi(row[6]), // uint32 respawn
atoi(row[7]), // uint32 variance
spawn_time_left, // uint32 timeleft
atoi(row[8]), // uint32 grid
atoi(row[9]), // uint16 in_cond_id
atoi(row[10]), // int16 in_min_value
perl_enabled, // bool in_enabled
(EmuAppearance)atoi(row[12]) // EmuAppearance anim
);
spawn2_list.Insert(new_spawn);
}
return true;
}
bool ZoneDatabase::PopulateZoneSpawnList(uint32 zoneid, LinkedList<Spawn2*> &spawn2_list, int16 version, uint32 repopdelay) {
std::unordered_map<uint32, uint32> spawn_times;

View File

@ -38,7 +38,7 @@
extern Zone* zone;
extern volatile bool ZoneLoaded;
extern volatile bool is_zone_loaded;
extern WorldServer worldserver;
@ -283,9 +283,13 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
//do any AAs apply to these spells?
if(dmg < 0) {
if (!PassCastRestriction(false, spells[spell_id].base2[i], true))
break;
dmg = -dmg;
Damage(caster, dmg, spell_id, spell.skill, false, buffslot, false);
} else {
if (!PassCastRestriction(false, spells[spell_id].base2[i], false))
break;
HealDamage(dmg, caster);
}
break;
@ -864,7 +868,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
}
CalculateNewFearpoint();
if(curfp)
if(currently_fleeing)
{
break;
}
@ -3429,6 +3433,8 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster)
switch (effect) {
case SE_CurrentHP: {
if (!PassCastRestriction(false, spells[buff.spellid].base2[i], true))
break;
effect_value = CalcSpellEffectValue(buff.spellid, i, buff.casterlevel, buff.instrument_mod,
caster, buff.ticsremaining);
// Handle client cast DOTs here.
@ -3944,8 +3950,8 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
}
case SE_Blind:
if (curfp && !FindType(SE_Fear))
curfp = false;
if (currently_fleeing && !FindType(SE_Fear))
currently_fleeing = false;
break;
case SE_Fear:
@ -3958,8 +3964,8 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
CastToClient()->AI_Stop();
}
if(curfp) {
curfp = false;
if(currently_fleeing) {
currently_fleeing = false;
break;
}
}
@ -3974,7 +3980,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
{
if(RuleB(Combat, EnableFearPathing)){
if(flee_mode) {
curfp = true;
currently_fleeing = true;
CheckFlee();
break;
}
@ -6224,16 +6230,17 @@ bool Mob::PassCastRestriction(bool UseCastRestriction, int16 value, bool IsDama
Range 410 - 411 : UNKOWN
Range 500 - 599 : Heal if HP less than a specified value
Range 600 - 699 : Limit to Body Type [base2 - 600 = Body]
Range 700 : UNKNOWN
Range 700 : NPC only -- from patch notes "Wizard - Arcane Fusion no longer deals damage to non-NPC targets. This should ensure that wizards who fail their Bucolic Gambit are slightly less likely to annihilate themselves."
Range 701 : NOT PET
Range 800 : UKNOWN
Range 818 - 819 : If Undead/If Not Undead
Range 820 - 822 : UKNOWN
Range 835 : Unknown *not implemented
Range 836 - 837 : Progression Server / Live Server *not implemented
Range 839 : Unknown *not implemented
Range 836 - 837 : Progression Server / Live Server *not fully implemented
Range 839 : Progression Server and GoD released -- broken until Oct 21 2015 on live *not fully implemented
Range 842 - 844 : Humaniod lv MAX ((842 - 800) * 2)
Range 845 - 847 : UNKNOWN
Range 860 - 871 : Humanoid lv MAX 860 = 90, 871 = 104 *not implemented
Range 10000 - 11000 : Limit to Race [base2 - 10000 = Race] (*Not on live: Too useful a function to not implement)
THIS IS A WORK IN PROGRESS
*/
@ -6387,6 +6394,11 @@ bool Mob::PassCastRestriction(bool UseCastRestriction, int16 value, bool IsDama
return true;
break;
case 700:
if (IsNPC())
return true;
break;
case 701:
if (!IsPet())
return true;
@ -6402,6 +6414,15 @@ bool Mob::PassCastRestriction(bool UseCastRestriction, int16 value, bool IsDama
return true;
break;
case 836:
return true; // todo implement progression flag assume not progression for now
case 837:
return false; // todo implement progression flag assume not progression for now
case 839:
return true; // todo implement progression flag assume not progression for now, this one is a check if GoD is live
case 842:
if (GetBodyType() == BT_Humanoid && GetLevel() <= 84)
return true;
@ -6789,4 +6810,4 @@ void Client::BreakFeignDeathWhenCastOn(bool IsResisted)
SetFeigned(false);
Message_StringID(MT_SpellFailure,FD_CAST_ON);
}
}
}

View File

@ -101,7 +101,7 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
extern Zone* zone;
extern volatile bool ZoneLoaded;
extern volatile bool is_zone_loaded;
extern WorldServer worldserver;
// this is run constantly for every mob
@ -2267,7 +2267,9 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16
}
}
// one may want to check if this is a disc or not, but we actually don't, there are non disc stuff that have end cost
if (spells[spell_id].EndurCost) {
// lets not consume end for custom items that have disc procs.
// One might also want to filter out USE_ITEM_SPELL_SLOT, but DISCIPLINE_SPELL_SLOT are both #defined to the same thing ...
if (spells[spell_id].EndurCost && !isproc) {
auto end_cost = spells[spell_id].EndurCost;
if (mgb)
end_cost *= 2;

View File

@ -94,7 +94,7 @@ void NPC::ResumeWandering()
{
if (GetGrid() < 0)
{ // we were paused by a quest
AIwalking_timer->Disable();
AI_walking_timer->Disable();
SetGrid( 0 - GetGrid());
if (cur_wp==-1)
{ // got here by a MoveTo()
@ -103,10 +103,10 @@ void NPC::ResumeWandering()
}
Log.Out(Logs::Detail, Logs::Pathing, "Resume Wandering requested. Grid %d, wp %d", GetGrid(), cur_wp);
}
else if (AIwalking_timer->Enabled())
else if (AI_walking_timer->Enabled())
{ // we are at a waypoint paused normally
Log.Out(Logs::Detail, Logs::Pathing, "Resume Wandering on timed pause. Grid %d, wp %d", GetGrid(), cur_wp);
AIwalking_timer->Trigger(); // disable timer to end pause now
AI_walking_timer->Trigger(); // disable timer to end pause now
}
else
{
@ -145,7 +145,7 @@ void NPC::PauseWandering(int pausetime)
}
else
{ // specified waiting time, he'll resume after that
AIwalking_timer->Start(pausetime*1000); // set the timer
AI_walking_timer->Start(pausetime*1000); // set the timer
}
} else {
Log.Out(Logs::General, Logs::Error, "NPC not on grid - can't pause wandering: %lu", (unsigned long)GetNPCTypeID());
@ -162,7 +162,7 @@ void NPC::MoveTo(const glm::vec4& position, bool saveguardspot)
SetGrid( 0 - GetGrid()); // get him moving again
Log.Out(Logs::Detail, Logs::AI, "MoveTo during quest wandering. Canceling quest wandering and going back to grid %d when MoveTo is done.", GetGrid());
}
AIwalking_timer->Disable(); // disable timer in case he is paused at a wp
AI_walking_timer->Disable(); // disable timer in case he is paused at a wp
if (cur_wp>=0)
{ // we've not already done a MoveTo()
save_wp=cur_wp; // save the current waypoint
@ -193,8 +193,8 @@ void NPC::MoveTo(const glm::vec4& position, bool saveguardspot)
m_CurrentWayPoint = position;
cur_wp_pause = 0;
pLastFightingDelayMoving = 0;
if(AIwalking_timer->Enabled())
AIwalking_timer->Start(100);
if(AI_walking_timer->Enabled())
AI_walking_timer->Start(100);
}
void NPC::UpdateWaypoint(int wp_index)
@ -393,8 +393,8 @@ void NPC::SetWaypointPause()
//Declare time to wait on current WP
if (cur_wp_pause == 0) {
AIwalking_timer->Start(100);
AIwalking_timer->Trigger();
AI_walking_timer->Start(100);
AI_walking_timer->Trigger();
}
else
{
@ -402,13 +402,13 @@ void NPC::SetWaypointPause()
switch (pausetype)
{
case 0: //Random Half
AIwalking_timer->Start((cur_wp_pause - zone->random.Int(0, cur_wp_pause-1)/2)*1000);
AI_walking_timer->Start((cur_wp_pause - zone->random.Int(0, cur_wp_pause-1)/2)*1000);
break;
case 1: //Full
AIwalking_timer->Start(cur_wp_pause*1000);
AI_walking_timer->Start(cur_wp_pause*1000);
break;
case 2: //Random Full
AIwalking_timer->Start(zone->random.Int(0, cur_wp_pause-1)*1000);
AI_walking_timer->Start(zone->random.Int(0, cur_wp_pause-1)*1000);
break;
}
}
@ -484,7 +484,7 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo
Log.Out(Logs::Detail, Logs::AI, "Calc Position2 (%.3f, %.3f, %.3f): Jumping pure Z.", x, y, z);
return true;
}
Log.Out(Logs::Detail, Logs::AI, "Calc Position2 (%.3f, %.3f, %.3f) inWater=%d: We are there.", x, y, z, inWater);
// Log.Out(Logs::Detail, Logs::AI, "Calc Position2 (%.3f, %.3f, %.3f) inWater=%d: We are there.", x, y, z, inWater);
return false;
} else if ((std::abs(m_Position.x - x) < 0.1) && (std::abs(m_Position.y - y) < 0.1)) {
Log.Out(Logs::Detail, Logs::AI, "Calc Position2 (%.3f, %.3f, %.3f): X/Y difference <0.1, Jumping to target.", x, y, z);

View File

@ -39,6 +39,7 @@
#include "client.h"
#include "corpse.h"
#include "entity.h"
#include "quest_parser_collection.h"
#include "guild_mgr.h"
#include "mob.h"
#include "net.h"
@ -53,13 +54,16 @@
extern EntityList entity_list;
extern Zone* zone;
extern volatile bool ZoneLoaded;
extern volatile bool is_zone_loaded;
extern void CatchSignal(int);
extern WorldServer worldserver;
extern NetConnection net;
extern PetitionList petition_list;
extern uint32 numclients;
extern volatile bool RunLoops;
extern QuestParserCollection *parse;
// QuestParserCollection *parse = 0;
WorldServer::WorldServer()
: WorldConnection(EmuTCPConnection::packetModeZone)
@ -85,7 +89,7 @@ WorldServer::~WorldServer() {
safe_delete(pack);
}*/
void WorldServer::SetZone(uint32 iZoneID, uint32 iInstanceID) {
void WorldServer::SetZoneData(uint32 iZoneID, uint32 iInstanceID) {
ServerPacket* pack = new ServerPacket(ServerOP_SetZone, sizeof(SetZone_Struct));
SetZone_Struct* szs = (SetZone_Struct*) pack->pBuffer;
szs->zoneid = iZoneID;
@ -99,10 +103,9 @@ void WorldServer::SetZone(uint32 iZoneID, uint32 iInstanceID) {
void WorldServer::OnConnected() {
WorldConnection::OnConnected();
ServerPacket* pack;
//tell the launcher what name we were started with.
/* Tell the launcher what our information is */
pack = new ServerPacket(ServerOP_SetLaunchName,sizeof(LaunchName_Struct));
LaunchName_Struct* ln = (LaunchName_Struct*)pack->pBuffer;
strn0cpy(ln->launcher_name, m_launcherName.c_str(), 32);
@ -110,28 +113,38 @@ void WorldServer::OnConnected() {
SendPacket(pack);
safe_delete(pack);
/* Tell the Worldserver basic information about this zone process */
pack = new ServerPacket(ServerOP_SetConnectInfo, sizeof(ServerConnectInfo));
ServerConnectInfo* sci = (ServerConnectInfo*) pack->pBuffer;
auto config = ZoneConfig::get();
sci->port = ZoneConfig::get()->ZonePort;
if(config->WorldAddress.length() > 0) {
strn0cpy(sci->address, config->WorldAddress.c_str(), 250);
}
if(config->LocalAddress.length() > 0) {
strn0cpy(sci->local_address, config->LocalAddress.c_str(), 250);
}
/* Fetch process ID */
if (getpid()){
sci->process_id = getpid();
}
else {
sci->process_id = 0;
}
SendPacket(pack);
safe_delete(pack);
if (ZoneLoaded) {
this->SetZone(zone->GetZoneID(), zone->GetInstanceID());
if (is_zone_loaded) {
this->SetZoneData(zone->GetZoneID(), zone->GetInstanceID());
entity_list.UpdateWho(true);
this->SendEmoteMessage(0, 0, 15, "Zone connect: %s", zone->GetLongName());
zone->GetTimeSync();
} else {
this->SetZone(0);
zone->GetTimeSync();
}
else {
this->SetZoneData(0);
}
pack = new ServerPacket(ServerOP_LSZoneBoot,sizeof(ZoneBoot_Struct));
@ -174,7 +187,7 @@ void WorldServer::Process() {
break;
}
case ServerOP_ChannelMessage: {
if (!ZoneLoaded)
if (!is_zone_loaded)
break;
ServerChannelMessage_Struct* scm = (ServerChannelMessage_Struct*) pack->pBuffer;
if (scm->deliverto[0] == 0) {
@ -207,7 +220,7 @@ void WorldServer::Process() {
}
case ServerOP_VoiceMacro: {
if (!ZoneLoaded)
if (!is_zone_loaded)
break;
ServerVoiceMacro_Struct* svm = (ServerVoiceMacro_Struct*) pack->pBuffer;
@ -264,7 +277,7 @@ void WorldServer::Process() {
case ServerOP_SpawnCondition: {
if(pack->size != sizeof(ServerSpawnCondition_Struct))
break;
if (!ZoneLoaded)
if (!is_zone_loaded)
break;
ServerSpawnCondition_Struct* ssc = (ServerSpawnCondition_Struct*) pack->pBuffer;
@ -274,7 +287,7 @@ void WorldServer::Process() {
case ServerOP_SpawnEvent: {
if(pack->size != sizeof(ServerSpawnEvent_Struct))
break;
if (!ZoneLoaded)
if (!is_zone_loaded)
break;
ServerSpawnEvent_Struct* sse = (ServerSpawnEvent_Struct*) pack->pBuffer;
@ -285,7 +298,7 @@ void WorldServer::Process() {
case ServerOP_AcceptWorldEntrance: {
if(pack->size != sizeof(WorldToZone_Struct))
break;
if (!ZoneLoaded)
if (!is_zone_loaded)
break;
WorldToZone_Struct* wtz = (WorldToZone_Struct*) pack->pBuffer;
@ -300,7 +313,7 @@ void WorldServer::Process() {
case ServerOP_ZoneToZoneRequest: {
if(pack->size != sizeof(ZoneToZone_Struct))
break;
if (!ZoneLoaded)
if (!is_zone_loaded)
break;
ZoneToZone_Struct* ztz = (ZoneToZone_Struct*) pack->pBuffer;
@ -376,7 +389,7 @@ void WorldServer::Process() {
break;
}
case ServerOP_WhoAllReply:{
if(!ZoneLoaded)
if(!is_zone_loaded)
break;
@ -403,7 +416,7 @@ void WorldServer::Process() {
break;
}
case ServerOP_EmoteMessage: {
if (!ZoneLoaded)
if (!is_zone_loaded)
break;
ServerEmoteMessage_Struct* sem = (ServerEmoteMessage_Struct*) pack->pBuffer;
if (sem->to[0] != 0) {
@ -461,8 +474,8 @@ void WorldServer::Process() {
break;
}
// Annouce the change to the world
if (!ZoneLoaded) {
SetZone(0);
if (!is_zone_loaded) {
SetZoneData(0);
}
else {
SendEmoteMessage(0, 0, 15, "Zone shutdown: %s", zone->GetLongName());
@ -479,8 +492,8 @@ void WorldServer::Process() {
break;
}
ServerZoneStateChange_struct* zst = (ServerZoneStateChange_struct *) pack->pBuffer;
if (ZoneLoaded) {
SetZone(zone->GetZoneID(), zone->GetInstanceID());
if (is_zone_loaded) {
SetZoneData(zone->GetZoneID(), zone->GetInstanceID());
if (zst->zoneid == zone->GetZoneID()) {
// This packet also doubles as "incoming client" notification, lets not shut down before they get here
zone->StartShutdownTimer(AUTHENTICATION_TIMEOUT * 1000);
@ -503,8 +516,8 @@ void WorldServer::Process() {
break;
}
ServerZoneIncomingClient_Struct* szic = (ServerZoneIncomingClient_Struct*) pack->pBuffer;
if (ZoneLoaded) {
SetZone(zone->GetZoneID(), zone->GetInstanceID());
if (is_zone_loaded) {
SetZoneData(zone->GetZoneID(), zone->GetInstanceID());
if (szic->zoneid == zone->GetZoneID()) {
zone->AddAuth(szic);
// This packet also doubles as "incoming client" notification, lets not shut down before they get here
@ -540,7 +553,7 @@ void WorldServer::Process() {
if (client != 0) {
if (skp->adminrank >= client->Admin()) {
client->WorldKick();
if (ZoneLoaded)
if (is_zone_loaded)
SendEmoteMessage(skp->adminname, 0, 0, "Remote Kick: %s booted in zone %s.", skp->name, zone->GetShortName());
else
SendEmoteMessage(skp->adminname, 0, 0, "Remote Kick: %s booted.", skp->name);
@ -556,7 +569,7 @@ void WorldServer::Process() {
if (client != 0) {
if (skp->admin >= client->Admin()) {
client->GMKill();
if (ZoneLoaded)
if (is_zone_loaded)
SendEmoteMessage(skp->gmname, 0, 0, "Remote Kill: %s killed in zone %s.", skp->target, zone->GetShortName());
else
SendEmoteMessage(skp->gmname, 0, 0, "Remote Kill: %s killed.", skp->target);
@ -594,7 +607,7 @@ void WorldServer::Process() {
std::cout << "Wrong size on ServerOP_GMGoto. Got: " << pack->size << ", Expected: " << sizeof(ServerGMGoto_Struct) << std::endl;
break;
}
if (!ZoneLoaded)
if (!is_zone_loaded)
break;
ServerGMGoto_Struct* gmg = (ServerGMGoto_Struct*) pack->pBuffer;
Client* client = entity_list.GetClientByName(gmg->gotoname);
@ -1733,6 +1746,10 @@ void WorldServer::Process() {
database.LoadLogSettings(Log.log_settings);
break;
}
case ServerOP_ReloadPerlExportSettings: {
parse->LoadPerlEventExportSettings(parse->perl_event_export_settings);
break;
}
case ServerOP_CameraShake:
{
if(zone)

View File

@ -37,7 +37,7 @@ public:
bool SendEmoteMessage(const char* to, uint32 to_guilddbid, uint32 type, const char* message, ...);
bool SendEmoteMessage(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message, ...);
bool SendVoiceMacro(Client* From, uint32 Type, char* Target, uint32 MacroNumber, uint32 GroupOrRaidID = 0);
void SetZone(uint32 iZoneID, uint32 iInstanceID = 0);
void SetZoneData(uint32 iZoneID, uint32 iInstanceID = 0);
uint32 SendGroupIdRequest();
bool RezzPlayer(EQApplicationPacket* rpack, uint32 rezzexp, uint32 dbid, uint16 opcode);
bool IsOOCMuted() const { return(oocmuted); }

View File

@ -74,7 +74,7 @@ extern Zone* zone;
Mutex MZoneShutdown;
volatile bool ZoneLoaded = false;
volatile bool is_zone_loaded = false;
Zone* zone = 0;
bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) {
@ -82,9 +82,9 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) {
if (iZoneID == 0 || zonename == 0)
return false;
if (zone != 0 || ZoneLoaded) {
if (zone != 0 || is_zone_loaded) {
std::cerr << "Error: Zone::Bootup call when zone already booted!" << std::endl;
worldserver.SetZone(0);
worldserver.SetZoneData(0);
return false;
}
@ -97,7 +97,7 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) {
if (!zone->Init(iStaticZone)) {
safe_delete(zone);
std::cerr << "Zone->Init failed" << std::endl;
worldserver.SetZone(0);
worldserver.SetZoneData(0);
return false;
}
zone->zonemap = Map::LoadMapFile(zone->map_name);
@ -131,9 +131,9 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) {
}
}
ZoneLoaded = true;
is_zone_loaded = true;
worldserver.SetZone(iZoneID, iInstanceID);
worldserver.SetZoneData(iZoneID, iInstanceID);
if(iInstanceID != 0)
{
ServerPacket *pack = new ServerPacket(ServerOP_AdventureZoneData, sizeof(uint16));
@ -660,12 +660,12 @@ void Zone::LoadMercSpells(){
}
bool Zone::IsLoaded() {
return ZoneLoaded;
return is_zone_loaded;
}
void Zone::Shutdown(bool quite)
{
if (!ZoneLoaded)
if (!is_zone_loaded)
return;
entity_list.StopMobAI();
@ -699,7 +699,7 @@ void Zone::Shutdown(bool quite)
zone->SetZoneHasCurrentTime(false);
if (!quite)
Log.Out(Logs::General, Logs::Normal, "Zone shutdown: going to sleep");
ZoneLoaded = false;
is_zone_loaded = false;
zone->ResetAuth();
safe_delete(zone);
@ -846,7 +846,7 @@ Zone::~Zone() {
safe_delete(watermap);
safe_delete(pathing);
if (worldserver.Connected()) {
worldserver.SetZone(0);
worldserver.SetZoneData(0);
}
safe_delete_array(short_name);
safe_delete_array(long_name);
@ -1445,6 +1445,29 @@ void Zone::ClearNPCTypeCache(int id) {
}
}
void Zone::RepopClose(const glm::vec4& client_position, uint32 repop_distance)
{
if (!Depop())
return;
LinkedListIterator<Spawn2*> iterator(spawn2_list);
iterator.Reset();
while (iterator.MoreElements()) {
iterator.RemoveCurrent();
}
quest_manager.ClearAllTimers();
if (!database.PopulateZoneSpawnListClose(zoneid, spawn2_list, GetInstanceVersion(), client_position, repop_distance))
Log.Out(Logs::General, Logs::None, "Error in Zone::Repop: database.PopulateZoneSpawnList failed");
initgrids_timer.Start();
mod_repop();
}
void Zone::Repop(uint32 delay) {
if(!Depop())

View File

@ -140,6 +140,7 @@ public:
bool Depop(bool StartSpawnTimer = false);
void Repop(uint32 delay = 0);
void RepopClose(const glm::vec4& client_position, uint32 repop_distance);
void ClearNPCTypeCache(int id);
void SpawnStatus(Mob* client);
void ShowEnabledSpawnStatus(Mob* client);

View File

@ -46,7 +46,7 @@ void ZoneDatabase::ZDBInitVars() {
ZoneDatabase::~ZoneDatabase() {
unsigned int x;
if (npc_spells_cache) {
for (x=0; x<=npc_spells_maxid; x++) {
for (x = 0; x <= npc_spells_maxid; x++) {
safe_delete_array(npc_spells_cache[x]);
}
safe_delete_array(npc_spells_cache);
@ -54,7 +54,7 @@ ZoneDatabase::~ZoneDatabase() {
safe_delete_array(npc_spells_loadtried);
if (npc_spellseffects_cache) {
for (x=0; x<=npc_spellseffects_maxid; x++) {
for (x = 0; x <= npc_spellseffects_maxid; x++) {
safe_delete_array(npc_spellseffects_cache[x]);
}
safe_delete_array(npc_spellseffects_cache);
@ -62,7 +62,7 @@ ZoneDatabase::~ZoneDatabase() {
safe_delete_array(npc_spellseffects_loadtried);
if (faction_array != nullptr) {
for (x=0; x <= max_faction; x++) {
for (x = 0; x <= max_faction; x++) {
if (faction_array[x] != 0)
safe_delete(faction_array[x]);
}

View File

@ -7,6 +7,7 @@
#include "../common/faction.h"
#include "../common/eqemu_logsys.h"
#include "aa_ability.h"
#include "event_codes.h"
class Client;
class Corpse;
@ -358,6 +359,7 @@ public:
bool LoadSpawnGroups(const char* zone_name, uint16 version, SpawnGroupList* spawn_group_list);
bool LoadSpawnGroupsByID(int spawngroupid, SpawnGroupList* spawn_group_list);
bool PopulateZoneSpawnList(uint32 zoneid, LinkedList<Spawn2*> &spawn2_list, int16 version, uint32 repopdelay = 0);
bool PopulateZoneSpawnListClose(uint32 zoneid, LinkedList<Spawn2*> &spawn2_list, int16 version, const glm::vec4& client_position, uint32 repop_distance);
Spawn2* LoadSpawn2(LinkedList<Spawn2*> &spawn2_list, uint32 spawn2id, uint32 timeleft);
bool CreateSpawn2(Client *c, uint32 spawngroup, const char* zone, const glm::vec4& position, uint32 respawn, uint32 variance, uint16 condition, int16 cond_value);
void UpdateRespawnTime(uint32 id, uint16 instance_id,uint32 timeleft);