mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-14 19:51:29 +00:00
Merge branch 'master' of https://github.com/EQEmu/Server into inv_possessions_rework
This commit is contained in:
commit
7c5b1e8fd2
23
.editorconfig
Normal file
23
.editorconfig
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# EditorConfig is awesome: http://EditorConfig.org
|
||||||
|
|
||||||
|
# top-most EditorConfig file
|
||||||
|
root = true
|
||||||
|
|
||||||
|
# Unix-style newlines with a newline ending every file
|
||||||
|
[*]
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
# Matches multiple files with brace expansion notation
|
||||||
|
# Set default charset
|
||||||
|
[*.{js,py}]
|
||||||
|
charset = utf-8
|
||||||
|
|
||||||
|
[*.cpp]
|
||||||
|
indent_style = tab
|
||||||
|
[*.h]
|
||||||
|
indent_style = tab
|
||||||
|
|
||||||
|
# Tab indentation (no size specified)
|
||||||
|
[Makefile]
|
||||||
|
indent_style = tab
|
||||||
@ -28,6 +28,9 @@
|
|||||||
#EQEMU_MAP_DIR
|
#EQEMU_MAP_DIR
|
||||||
|
|
||||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||||
|
IF(POLICY CMP0074)
|
||||||
|
cmake_policy(SET CMP0074 NEW)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
#FindMySQL is located here so lets make it so CMake can find it
|
#FindMySQL is located here so lets make it so CMake can find it
|
||||||
SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/" ${CMAKE_MODULE_PATH})
|
SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/" ${CMAKE_MODULE_PATH})
|
||||||
|
|||||||
@ -376,7 +376,11 @@ struct NewZone_Struct {
|
|||||||
/*0692*/ uint8 unknown692[8];
|
/*0692*/ uint8 unknown692[8];
|
||||||
/*0700*/ float fog_density;
|
/*0700*/ float fog_density;
|
||||||
/*0704*/ uint32 SuspendBuffs;
|
/*0704*/ uint32 SuspendBuffs;
|
||||||
/*0704*/
|
/*0708*/ uint32 FastRegenHP;
|
||||||
|
/*0712*/ uint32 FastRegenMana;
|
||||||
|
/*0716*/ uint32 FastRegenEndurance;
|
||||||
|
/*0720*/ uint32 NPCAggroMaxDist;
|
||||||
|
/*0724*/
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@ -90,6 +90,7 @@ enum LogCategory {
|
|||||||
FixZ,
|
FixZ,
|
||||||
Food,
|
Food,
|
||||||
Traps,
|
Traps,
|
||||||
|
NPCRoamBox,
|
||||||
MaxCategoryID /* Don't Remove this*/
|
MaxCategoryID /* Don't Remove this*/
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -144,7 +145,8 @@ static const char* LogCategoryName[LogCategory::MaxCategoryID] = {
|
|||||||
"HP Update",
|
"HP Update",
|
||||||
"FixZ",
|
"FixZ",
|
||||||
"Food",
|
"Food",
|
||||||
"Traps"
|
"Traps",
|
||||||
|
"NPC Roam Box"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -124,7 +124,7 @@ namespace EQEmu
|
|||||||
|
|
||||||
class OutBuffer : public std::stringstream {
|
class OutBuffer : public std::stringstream {
|
||||||
public:
|
public:
|
||||||
inline size_t size() { return tellp(); }
|
inline size_t size() { return static_cast<size_t>(tellp()); }
|
||||||
void overwrite(OutBuffer::pos_type position, const char *_Str, std::streamsize _Count);
|
void overwrite(OutBuffer::pos_type position, const char *_Str, std::streamsize _Count);
|
||||||
uchar* detach();
|
uchar* detach();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -73,7 +73,7 @@ uint32 SwapBits21And22(uint32 mask);
|
|||||||
uint32 Catch22(uint32 mask);
|
uint32 Catch22(uint32 mask);
|
||||||
|
|
||||||
// macro to catch fp errors (provided by noudness)
|
// macro to catch fp errors (provided by noudness)
|
||||||
#define FCMP(a,b) (fabs(a-b) < FLT_EPSILON)
|
#define FCMP(a,b) (std::abs(a-b) < FLT_EPSILON)
|
||||||
|
|
||||||
#define _ITOA_BUFLEN 25
|
#define _ITOA_BUFLEN 25
|
||||||
const char *itoa(int num); //not thread safe
|
const char *itoa(int num); //not thread safe
|
||||||
|
|||||||
@ -1823,6 +1823,9 @@ namespace RoF
|
|||||||
OUT(zone_id);
|
OUT(zone_id);
|
||||||
OUT(zone_instance);
|
OUT(zone_instance);
|
||||||
OUT(SuspendBuffs);
|
OUT(SuspendBuffs);
|
||||||
|
OUT(FastRegenHP);
|
||||||
|
OUT(FastRegenMana);
|
||||||
|
OUT(FastRegenEndurance);
|
||||||
|
|
||||||
eq->FogDensity = emu->fog_density;
|
eq->FogDensity = emu->fog_density;
|
||||||
|
|
||||||
@ -1839,9 +1842,6 @@ namespace RoF
|
|||||||
eq->unknown893 = 0;
|
eq->unknown893 = 0;
|
||||||
eq->fall_damage = 0; // 0 = Fall Damage on, 1 = Fall Damage off
|
eq->fall_damage = 0; // 0 = Fall Damage on, 1 = Fall Damage off
|
||||||
eq->unknown895 = 0;
|
eq->unknown895 = 0;
|
||||||
eq->unknown896 = 180;
|
|
||||||
eq->unknown900 = 180;
|
|
||||||
eq->unknown904 = 180;
|
|
||||||
eq->unknown908 = 2;
|
eq->unknown908 = 2;
|
||||||
eq->unknown912 = 2;
|
eq->unknown912 = 2;
|
||||||
eq->unknown932 = -1; // Set from PoK Example
|
eq->unknown932 = -1; // Set from PoK Example
|
||||||
@ -2807,7 +2807,7 @@ namespace RoF
|
|||||||
|
|
||||||
std::vector<int32> skill;
|
std::vector<int32> skill;
|
||||||
std::vector<int32> points;
|
std::vector<int32> points;
|
||||||
for(auto i = 0; i < emu->total_prereqs; ++i) {
|
for(auto i = 0u; i < emu->total_prereqs; ++i) {
|
||||||
skill.push_back(inapp->ReadUInt32());
|
skill.push_back(inapp->ReadUInt32());
|
||||||
points.push_back(inapp->ReadUInt32());
|
points.push_back(inapp->ReadUInt32());
|
||||||
}
|
}
|
||||||
@ -2861,7 +2861,7 @@ namespace RoF
|
|||||||
outapp->WriteUInt32(emu->total_effects);
|
outapp->WriteUInt32(emu->total_effects);
|
||||||
|
|
||||||
inapp->SetReadPosition(sizeof(AARankInfo_Struct));
|
inapp->SetReadPosition(sizeof(AARankInfo_Struct));
|
||||||
for(auto i = 0; i < emu->total_effects; ++i) {
|
for(auto i = 0u; i < emu->total_effects; ++i) {
|
||||||
outapp->WriteUInt32(inapp->ReadUInt32()); // skill_id
|
outapp->WriteUInt32(inapp->ReadUInt32()); // skill_id
|
||||||
outapp->WriteUInt32(inapp->ReadUInt32()); // base1
|
outapp->WriteUInt32(inapp->ReadUInt32()); // base1
|
||||||
outapp->WriteUInt32(inapp->ReadUInt32()); // base2
|
outapp->WriteUInt32(inapp->ReadUInt32()); // base2
|
||||||
@ -2917,7 +2917,7 @@ namespace RoF
|
|||||||
unsigned char *eq_ptr = __packet->pBuffer;
|
unsigned char *eq_ptr = __packet->pBuffer;
|
||||||
eq_ptr += sizeof(structs::CharacterSelect_Struct);
|
eq_ptr += sizeof(structs::CharacterSelect_Struct);
|
||||||
|
|
||||||
for (int counter = 0; counter < character_count; ++counter) {
|
for (auto counter = 0u; counter < character_count; ++counter) {
|
||||||
emu_cse = (CharacterSelectEntry_Struct *)emu_ptr;
|
emu_cse = (CharacterSelectEntry_Struct *)emu_ptr;
|
||||||
eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; // base address
|
eq_cse = (structs::CharacterSelectEntry_Struct *)eq_ptr; // base address
|
||||||
|
|
||||||
@ -3259,7 +3259,7 @@ namespace RoF
|
|||||||
InBuffer += title_size;
|
InBuffer += title_size;
|
||||||
|
|
||||||
TaskDescriptionData1_Struct *emu_tdd1 = (TaskDescriptionData1_Struct *)InBuffer;
|
TaskDescriptionData1_Struct *emu_tdd1 = (TaskDescriptionData1_Struct *)InBuffer;
|
||||||
emu_tdd1->StartTime = (time(nullptr) - emu_tdd1->StartTime); // RoF has elapsed time here rather than start time
|
emu_tdd1->StartTime = (static_cast<uint32>(time(nullptr)) - emu_tdd1->StartTime); // RoF has elapsed time here rather than start time
|
||||||
|
|
||||||
InBuffer += sizeof(TaskDescriptionData1_Struct);
|
InBuffer += sizeof(TaskDescriptionData1_Struct);
|
||||||
uint32 description_size = strlen(InBuffer) + 1;
|
uint32 description_size = strlen(InBuffer) + 1;
|
||||||
@ -3610,10 +3610,10 @@ namespace RoF
|
|||||||
|
|
||||||
// calculate size of names, note the packet DOES NOT have null termed c-strings
|
// calculate size of names, note the packet DOES NOT have null termed c-strings
|
||||||
std::vector<uint32> name_lengths;
|
std::vector<uint32> name_lengths;
|
||||||
for (int i = 0; i < count; ++i) {
|
for (auto i = 0u; i < count; ++i) {
|
||||||
InternalVeteranReward *ivr = (InternalVeteranReward *)__emu_buffer;
|
InternalVeteranReward *ivr = (InternalVeteranReward *)__emu_buffer;
|
||||||
|
|
||||||
for (int i = 0; i < ivr->claim_count; i++) {
|
for (auto i = 0u; i < ivr->claim_count; i++) {
|
||||||
uint32 length = strnlen(ivr->items[i].item_name, 63);
|
uint32 length = strnlen(ivr->items[i].item_name, 63);
|
||||||
if (length)
|
if (length)
|
||||||
name_lengths.push_back(length);
|
name_lengths.push_back(length);
|
||||||
@ -3633,7 +3633,7 @@ namespace RoF
|
|||||||
|
|
||||||
outapp->WriteUInt32(count);
|
outapp->WriteUInt32(count);
|
||||||
auto name_itr = name_lengths.begin();
|
auto name_itr = name_lengths.begin();
|
||||||
for (int i = 0; i < count; i++) {
|
for (auto i = 0u; i < count; i++) {
|
||||||
InternalVeteranReward *ivr = (InternalVeteranReward *)__emu_buffer;
|
InternalVeteranReward *ivr = (InternalVeteranReward *)__emu_buffer;
|
||||||
|
|
||||||
outapp->WriteUInt32(ivr->claim_id);
|
outapp->WriteUInt32(ivr->claim_id);
|
||||||
@ -3641,7 +3641,7 @@ namespace RoF
|
|||||||
outapp->WriteUInt32(ivr->claim_count);
|
outapp->WriteUInt32(ivr->claim_count);
|
||||||
outapp->WriteUInt8(1); // enabled
|
outapp->WriteUInt8(1); // enabled
|
||||||
|
|
||||||
for (int j = 0; j < ivr->claim_count; j++) {
|
for (auto j = 0u; j < ivr->claim_count; j++) {
|
||||||
assert(name_itr != name_lengths.end()); // the way it's written, it should never happen, so just assert
|
assert(name_itr != name_lengths.end()); // the way it's written, it should never happen, so just assert
|
||||||
outapp->WriteUInt32(*name_itr);
|
outapp->WriteUInt32(*name_itr);
|
||||||
outapp->WriteData(ivr->items[j].item_name, *name_itr);
|
outapp->WriteData(ivr->items[j].item_name, *name_itr);
|
||||||
@ -3869,7 +3869,7 @@ namespace RoF
|
|||||||
VARSTRUCT_ENCODE_STRING(Buffer, emu->name);
|
VARSTRUCT_ENCODE_STRING(Buffer, emu->name);
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->spawnId);
|
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->spawnId);
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->level);
|
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->level);
|
||||||
VARSTRUCT_ENCODE_TYPE(float, Buffer, SpawnSize - 0.7); // Eye Height?
|
VARSTRUCT_ENCODE_TYPE(float, Buffer, SpawnSize - 0.7f); // Eye Height?
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->NPC);
|
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->NPC);
|
||||||
|
|
||||||
structs::Spawn_Struct_Bitfields *Bitfields = (structs::Spawn_Struct_Bitfields*)Buffer;
|
structs::Spawn_Struct_Bitfields *Bitfields = (structs::Spawn_Struct_Bitfields*)Buffer;
|
||||||
|
|||||||
@ -1891,6 +1891,9 @@ namespace RoF2
|
|||||||
OUT(zone_id);
|
OUT(zone_id);
|
||||||
OUT(zone_instance);
|
OUT(zone_instance);
|
||||||
OUT(SuspendBuffs);
|
OUT(SuspendBuffs);
|
||||||
|
OUT(FastRegenHP);
|
||||||
|
OUT(FastRegenMana);
|
||||||
|
OUT(FastRegenEndurance);
|
||||||
|
|
||||||
eq->FogDensity = emu->fog_density;
|
eq->FogDensity = emu->fog_density;
|
||||||
|
|
||||||
@ -1914,9 +1917,6 @@ namespace RoF2
|
|||||||
eq->bNoFear = 0;
|
eq->bNoFear = 0;
|
||||||
eq->fall_damage = 0; // 0 = Fall Damage on, 1 = Fall Damage off
|
eq->fall_damage = 0; // 0 = Fall Damage on, 1 = Fall Damage off
|
||||||
eq->unknown895 = 0;
|
eq->unknown895 = 0;
|
||||||
eq->FastRegenHP = 180;
|
|
||||||
eq->FastRegenMana = 180;
|
|
||||||
eq->FastRegenEndurance = 180;
|
|
||||||
eq->CanPlaceCampsite = 2;
|
eq->CanPlaceCampsite = 2;
|
||||||
eq->CanPlaceGuildBanner = 2;
|
eq->CanPlaceGuildBanner = 2;
|
||||||
eq->FishingRelated = -1; // Set from PoK Example
|
eq->FishingRelated = -1; // Set from PoK Example
|
||||||
|
|||||||
@ -588,9 +588,9 @@ struct NewZone_Struct {
|
|||||||
/*0893*/ uint8 unknown893; // Seen 0 - 00
|
/*0893*/ uint8 unknown893; // Seen 0 - 00
|
||||||
/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off
|
/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off
|
||||||
/*0895*/ uint8 unknown895; // Seen 0 - 00
|
/*0895*/ uint8 unknown895; // Seen 0 - 00
|
||||||
/*0896*/ uint32 unknown896; // Seen 180
|
/*0896*/ uint32 FastRegenHP; // Seen 180
|
||||||
/*0900*/ uint32 unknown900; // Seen 180
|
/*0900*/ uint32 FastRegenMana; // Seen 180
|
||||||
/*0904*/ uint32 unknown904; // Seen 180
|
/*0904*/ uint32 FastRegenEndurance; // Seen 180
|
||||||
/*0908*/ uint32 unknown908; // Seen 2
|
/*0908*/ uint32 unknown908; // Seen 2
|
||||||
/*0912*/ uint32 unknown912; // Seen 2
|
/*0912*/ uint32 unknown912; // Seen 2
|
||||||
/*0916*/ float FogDensity; // Most zones have this set to 0.33 Blightfire had 0.16
|
/*0916*/ float FogDensity; // Most zones have this set to 0.33 Blightfire had 0.16
|
||||||
|
|||||||
@ -1350,6 +1350,10 @@ namespace SoD
|
|||||||
OUT(zone_id);
|
OUT(zone_id);
|
||||||
OUT(zone_instance);
|
OUT(zone_instance);
|
||||||
OUT(SuspendBuffs);
|
OUT(SuspendBuffs);
|
||||||
|
OUT(FastRegenHP);
|
||||||
|
OUT(FastRegenMana);
|
||||||
|
OUT(FastRegenEndurance);
|
||||||
|
|
||||||
/*fill in some unknowns with observed values, hopefully it will help */
|
/*fill in some unknowns with observed values, hopefully it will help */
|
||||||
eq->unknown800 = -1;
|
eq->unknown800 = -1;
|
||||||
eq->unknown844 = 600;
|
eq->unknown844 = 600;
|
||||||
@ -1363,9 +1367,6 @@ namespace SoD
|
|||||||
eq->unknown893 = 0;
|
eq->unknown893 = 0;
|
||||||
eq->fall_damage = 0; // 0 = Fall Damage on, 1 = Fall Damage off
|
eq->fall_damage = 0; // 0 = Fall Damage on, 1 = Fall Damage off
|
||||||
eq->unknown895 = 0;
|
eq->unknown895 = 0;
|
||||||
eq->unknown896 = 180;
|
|
||||||
eq->unknown900 = 180;
|
|
||||||
eq->unknown904 = 180;
|
|
||||||
eq->unknown908 = 2;
|
eq->unknown908 = 2;
|
||||||
eq->unknown912 = 2;
|
eq->unknown912 = 2;
|
||||||
eq->FogDensity = emu->fog_density;
|
eq->FogDensity = emu->fog_density;
|
||||||
|
|||||||
@ -456,9 +456,9 @@ struct NewZone_Struct {
|
|||||||
/*0893*/ uint8 unknown893; //seen 0 - 00
|
/*0893*/ uint8 unknown893; //seen 0 - 00
|
||||||
/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off
|
/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off
|
||||||
/*0895*/ uint8 unknown895; //seen 0 - 00
|
/*0895*/ uint8 unknown895; //seen 0 - 00
|
||||||
/*0896*/ uint32 unknown896; //seen 180
|
/*0896*/ uint32 FastRegenHP; //seen 180
|
||||||
/*0900*/ uint32 unknown900; //seen 180
|
/*0900*/ uint32 FastRegenMana; //seen 180
|
||||||
/*0904*/ uint32 unknown904; //seen 180
|
/*0904*/ uint32 FastRegenEndurance; //seen 180
|
||||||
/*0908*/ uint32 unknown908; //seen 2
|
/*0908*/ uint32 unknown908; //seen 2
|
||||||
/*0912*/ uint32 unknown912; //seen 2
|
/*0912*/ uint32 unknown912; //seen 2
|
||||||
/*0916*/ float FogDensity; //Of about 10 or so zones tested, all but one have this set to 0.33 Blightfire had 0.16
|
/*0916*/ float FogDensity; //Of about 10 or so zones tested, all but one have this set to 0.33 Blightfire had 0.16
|
||||||
|
|||||||
@ -1027,6 +1027,9 @@ namespace SoF
|
|||||||
OUT(zone_id);
|
OUT(zone_id);
|
||||||
OUT(zone_instance);
|
OUT(zone_instance);
|
||||||
OUT(SuspendBuffs);
|
OUT(SuspendBuffs);
|
||||||
|
OUT(FastRegenHP);
|
||||||
|
OUT(FastRegenMana);
|
||||||
|
OUT(FastRegenEndurance);
|
||||||
|
|
||||||
/*fill in some unknowns with observed values, hopefully it will help */
|
/*fill in some unknowns with observed values, hopefully it will help */
|
||||||
eq->unknown796 = -1;
|
eq->unknown796 = -1;
|
||||||
@ -1041,9 +1044,6 @@ namespace SoF
|
|||||||
eq->unknown889 = 0;
|
eq->unknown889 = 0;
|
||||||
eq->fall_damage = 0; // 0 = Fall Damage on, 1 = Fall Damage off
|
eq->fall_damage = 0; // 0 = Fall Damage on, 1 = Fall Damage off
|
||||||
eq->unknown891 = 0;
|
eq->unknown891 = 0;
|
||||||
eq->unknown892 = 180;
|
|
||||||
eq->unknown896 = 180;
|
|
||||||
eq->unknown900 = 180;
|
|
||||||
eq->unknown904 = 2;
|
eq->unknown904 = 2;
|
||||||
eq->unknown908 = 2;
|
eq->unknown908 = 2;
|
||||||
|
|
||||||
|
|||||||
@ -460,9 +460,9 @@ struct NewZone_Struct {
|
|||||||
/*0893*/ uint8 unknown889; //seen 0 - 00
|
/*0893*/ uint8 unknown889; //seen 0 - 00
|
||||||
/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off
|
/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off
|
||||||
/*0895*/ uint8 unknown891; //seen 0 - 00
|
/*0895*/ uint8 unknown891; //seen 0 - 00
|
||||||
/*0892*/ uint32 unknown892; //seen 180
|
/*0892*/ uint32 FastRegenHP; //seen 180
|
||||||
/*0896*/ uint32 unknown896; //seen 180
|
/*0896*/ uint32 FastRegenMana; //seen 180
|
||||||
/*0900*/ uint32 unknown900; //seen 180
|
/*0900*/ uint32 FastRegenEndurance; //seen 180
|
||||||
/*0904*/ uint32 unknown904; //seen 2
|
/*0904*/ uint32 unknown904; //seen 2
|
||||||
/*0908*/ uint32 unknown908; //seen 2
|
/*0908*/ uint32 unknown908; //seen 2
|
||||||
/*0912*/
|
/*0912*/
|
||||||
|
|||||||
@ -1574,6 +1574,9 @@ namespace UF
|
|||||||
OUT(zone_id);
|
OUT(zone_id);
|
||||||
OUT(zone_instance);
|
OUT(zone_instance);
|
||||||
OUT(SuspendBuffs);
|
OUT(SuspendBuffs);
|
||||||
|
OUT(FastRegenHP);
|
||||||
|
OUT(FastRegenMana);
|
||||||
|
OUT(FastRegenEndurance);
|
||||||
|
|
||||||
eq->FogDensity = emu->fog_density;
|
eq->FogDensity = emu->fog_density;
|
||||||
|
|
||||||
@ -1590,9 +1593,6 @@ namespace UF
|
|||||||
eq->unknown893 = 0;
|
eq->unknown893 = 0;
|
||||||
eq->fall_damage = 0; // 0 = Fall Damage on, 1 = Fall Damage off
|
eq->fall_damage = 0; // 0 = Fall Damage on, 1 = Fall Damage off
|
||||||
eq->unknown895 = 0;
|
eq->unknown895 = 0;
|
||||||
eq->unknown896 = 180;
|
|
||||||
eq->unknown900 = 180;
|
|
||||||
eq->unknown904 = 180;
|
|
||||||
eq->unknown908 = 2;
|
eq->unknown908 = 2;
|
||||||
eq->unknown912 = 2;
|
eq->unknown912 = 2;
|
||||||
|
|
||||||
|
|||||||
@ -456,9 +456,9 @@ struct NewZone_Struct {
|
|||||||
/*0893*/ uint8 unknown893; //seen 0 - 00
|
/*0893*/ uint8 unknown893; //seen 0 - 00
|
||||||
/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off
|
/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off
|
||||||
/*0895*/ uint8 unknown895; //seen 0 - 00
|
/*0895*/ uint8 unknown895; //seen 0 - 00
|
||||||
/*0896*/ uint32 unknown896; //seen 180
|
/*0896*/ uint32 FastRegenHP; //seen 180
|
||||||
/*0900*/ uint32 unknown900; //seen 180
|
/*0900*/ uint32 FastRegenMana; //seen 180
|
||||||
/*0904*/ uint32 unknown904; //seen 180
|
/*0904*/ uint32 FastRegenEndurance; //seen 180
|
||||||
/*0908*/ uint32 unknown908; //seen 2
|
/*0908*/ uint32 unknown908; //seen 2
|
||||||
/*0912*/ uint32 unknown912; //seen 2
|
/*0912*/ uint32 unknown912; //seen 2
|
||||||
/*0916*/ float FogDensity; //Of about 10 or so zones tested, all but one have this set to 0.33 Blightfire had 0.16
|
/*0916*/ float FogDensity; //Of about 10 or so zones tested, all but one have this set to 0.33 Blightfire had 0.16
|
||||||
|
|||||||
@ -94,9 +94,6 @@ RULE_INT(Character, SkillUpModifier, 100) //skill ups are at 100%
|
|||||||
RULE_BOOL(Character, SharedBankPlat, false) //off by default to prevent duping for now
|
RULE_BOOL(Character, SharedBankPlat, false) //off by default to prevent duping for now
|
||||||
RULE_BOOL(Character, BindAnywhere, false)
|
RULE_BOOL(Character, BindAnywhere, false)
|
||||||
RULE_BOOL(Character, RestRegenEnabled, true) // Enable OOC Regen
|
RULE_BOOL(Character, RestRegenEnabled, true) // Enable OOC Regen
|
||||||
RULE_INT(Character, RestRegenHP, 180) // seconds until full from 0. this is actually zone setable, but most or all zones are 180
|
|
||||||
RULE_INT(Character, RestRegenMana, 180) // seconds until full from 0. this is actually zone setable, but most or all zones are 180
|
|
||||||
RULE_INT(Character, RestRegenEnd, 180) // seconds until full from 0. this is actually zone setable, but most or all zones are 180
|
|
||||||
RULE_INT(Character, RestRegenTimeToActivate, 30) // Time in seconds for rest state regen to kick in.
|
RULE_INT(Character, RestRegenTimeToActivate, 30) // Time in seconds for rest state regen to kick in.
|
||||||
RULE_INT(Character, RestRegenRaidTimeToActivate, 300) // Time in seconds for rest state regen to kick in with a raid target.
|
RULE_INT(Character, RestRegenRaidTimeToActivate, 300) // Time in seconds for rest state regen to kick in with a raid target.
|
||||||
RULE_INT(Character, KillsPerGroupLeadershipAA, 250) // Number of dark blues or above per Group Leadership AA
|
RULE_INT(Character, KillsPerGroupLeadershipAA, 250) // Number of dark blues or above per Group Leadership AA
|
||||||
@ -419,6 +416,8 @@ RULE_BOOL(Combat, UseIntervalAC, true)
|
|||||||
RULE_INT(Combat, PetAttackMagicLevel, 30)
|
RULE_INT(Combat, PetAttackMagicLevel, 30)
|
||||||
RULE_BOOL(Combat, EnableFearPathing, true)
|
RULE_BOOL(Combat, EnableFearPathing, true)
|
||||||
RULE_REAL(Combat, FleeMultiplier, 2.0) // Determines how quickly a NPC will slow down while fleeing. Decrease multiplier to slow NPC down quicker.
|
RULE_REAL(Combat, FleeMultiplier, 2.0) // Determines how quickly a NPC will slow down while fleeing. Decrease multiplier to slow NPC down quicker.
|
||||||
|
RULE_BOOL(Combat, FleeGray, true) // If true FleeGrayHPRatio will be used.
|
||||||
|
RULE_INT(Combat, FleeGrayHPRatio, 50) //HP % when a Gray NPC begins to flee.
|
||||||
RULE_INT(Combat, FleeHPRatio, 25) //HP % when a NPC begins to flee.
|
RULE_INT(Combat, FleeHPRatio, 25) //HP % when a NPC begins to flee.
|
||||||
RULE_BOOL(Combat, FleeIfNotAlone, false) // If false, mobs won't flee if other mobs are in combat with it.
|
RULE_BOOL(Combat, FleeIfNotAlone, false) // If false, mobs won't flee if other mobs are in combat with it.
|
||||||
RULE_BOOL(Combat, AdjustProcPerMinute, true)
|
RULE_BOOL(Combat, AdjustProcPerMinute, true)
|
||||||
@ -532,6 +531,11 @@ RULE_INT(NPC, NPCToNPCAggroTimerMin, 500)
|
|||||||
RULE_INT(NPC, NPCToNPCAggroTimerMax, 6000)
|
RULE_INT(NPC, NPCToNPCAggroTimerMax, 6000)
|
||||||
RULE_BOOL(NPC, UseClassAsLastName, true) // Uses class archetype as LastName for npcs with none
|
RULE_BOOL(NPC, UseClassAsLastName, true) // Uses class archetype as LastName for npcs with none
|
||||||
RULE_BOOL(NPC, NewLevelScaling, true) // Better level scaling, use old if new formulas would break your server
|
RULE_BOOL(NPC, NewLevelScaling, true) // Better level scaling, use old if new formulas would break your server
|
||||||
|
RULE_INT(NPC, NPCGatePercent, 5) // % at which the NPC Will attempt to gate at.
|
||||||
|
RULE_BOOL(NPC, NPCGateNearBind, false) // Will NPC attempt to gate when near bind location?
|
||||||
|
RULE_INT(NPC, NPCGateDistanceBind, 75) // Distance from bind before NPC will attempt to gate
|
||||||
|
RULE_BOOL(NPC, NPCHealOnGate, true) // Will the NPC Heal on Gate.
|
||||||
|
RULE_REAL(NPC, NPCHealOnGateAmount, 25) // How much the npc will heal on gate if enabled.
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Aggro)
|
RULE_CATEGORY(Aggro)
|
||||||
@ -695,6 +699,7 @@ RULE_CATEGORY_END()
|
|||||||
RULE_CATEGORY(QueryServ)
|
RULE_CATEGORY(QueryServ)
|
||||||
RULE_BOOL(QueryServ, PlayerLogChat, false) // Logs Player Chat
|
RULE_BOOL(QueryServ, PlayerLogChat, false) // Logs Player Chat
|
||||||
RULE_BOOL(QueryServ, PlayerLogTrades, false) // Logs Player Trades
|
RULE_BOOL(QueryServ, PlayerLogTrades, false) // Logs Player Trades
|
||||||
|
RULE_BOOL(QueryServ, PlayerDropItems, false) // Logs Player dropping items
|
||||||
RULE_BOOL(QueryServ, PlayerLogHandins, false) // Logs Player Handins
|
RULE_BOOL(QueryServ, PlayerLogHandins, false) // Logs Player Handins
|
||||||
RULE_BOOL(QueryServ, PlayerLogNPCKills, false) // Logs Player NPC Kills
|
RULE_BOOL(QueryServ, PlayerLogNPCKills, false) // Logs Player NPC Kills
|
||||||
RULE_BOOL(QueryServ, PlayerLogDeletes, false) // Logs Player Deletes
|
RULE_BOOL(QueryServ, PlayerLogDeletes, false) // Logs Player Deletes
|
||||||
|
|||||||
@ -203,6 +203,7 @@
|
|||||||
#define ServerOP_CZSignalNPC 0x5017
|
#define ServerOP_CZSignalNPC 0x5017
|
||||||
#define ServerOP_CZSetEntityVariableByNPCTypeID 0x5018
|
#define ServerOP_CZSetEntityVariableByNPCTypeID 0x5018
|
||||||
#define ServerOP_WWMarquee 0x5019
|
#define ServerOP_WWMarquee 0x5019
|
||||||
|
#define ServerOP_QSPlayerDropItem 0x5020
|
||||||
|
|
||||||
/* Query Serv Generic Packet Flag/Type Enumeration */
|
/* Query Serv Generic Packet Flag/Type Enumeration */
|
||||||
enum { QSG_LFGuild = 0 };
|
enum { QSG_LFGuild = 0 };
|
||||||
@ -1140,6 +1141,27 @@ struct QSPlayerLogTrade_Struct {
|
|||||||
QSTradeItems_Struct items[0];
|
QSTradeItems_Struct items[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct QSDropItems_Struct {
|
||||||
|
uint32 item_id;
|
||||||
|
uint16 charges;
|
||||||
|
uint32 aug_1;
|
||||||
|
uint32 aug_2;
|
||||||
|
uint32 aug_3;
|
||||||
|
uint32 aug_4;
|
||||||
|
uint32 aug_5;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QSPlayerDropItem_Struct {
|
||||||
|
uint32 char_id;
|
||||||
|
bool pickup; // 0 drop, 1 pickup
|
||||||
|
uint32 zone_id;
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int z;
|
||||||
|
uint16 _detail_count;
|
||||||
|
QSDropItems_Struct items[0];
|
||||||
|
};
|
||||||
|
|
||||||
struct QSHandinItems_Struct {
|
struct QSHandinItems_Struct {
|
||||||
char action_type[7]; // handin, return or reward
|
char action_type[7]; // handin, return or reward
|
||||||
uint16 char_slot;
|
uint16 char_slot;
|
||||||
|
|||||||
@ -30,7 +30,7 @@
|
|||||||
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define CURRENT_BINARY_DATABASE_VERSION 9127
|
#define CURRENT_BINARY_DATABASE_VERSION 9129
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9020
|
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9020
|
||||||
#else
|
#else
|
||||||
|
|||||||
@ -123,6 +123,39 @@ void Database::AddSpeech(const char* from, const char* to, const char* message,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Database::LogPlayerDropItem(QSPlayerDropItem_Struct* QS) {
|
||||||
|
|
||||||
|
std::string query = StringFormat("INSERT INTO `qs_player_drop_record` SET `time` = NOW(), "
|
||||||
|
"`char_id` = '%i', `pickup` = '%i', "
|
||||||
|
"`zone_id` = '%i', `x` = '%i', `y` = '%i', `z` = '%i' ",
|
||||||
|
QS->char_id, QS->pickup, QS->zone_id, QS->x, QS->y, QS->z);
|
||||||
|
|
||||||
|
auto results = QueryDatabase(query);
|
||||||
|
if (!results.Success()) {
|
||||||
|
Log(Logs::Detail, Logs::QS_Server, "Failed Drop Record Insert: %s", results.ErrorMessage().c_str());
|
||||||
|
Log(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (QS->_detail_count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int lastIndex = results.LastInsertedID();
|
||||||
|
|
||||||
|
for (int i = 0; i < QS->_detail_count; i++) {
|
||||||
|
query = StringFormat("INSERT INTO `qs_player_drop_record_entries` SET `event_id` = '%i', "
|
||||||
|
"`item_id` = '%i', `charges` = '%i', `aug_1` = '%i', `aug_2` = '%i', "
|
||||||
|
"`aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'",
|
||||||
|
lastIndex, QS->items[i].item_id,
|
||||||
|
QS->items[i].charges, QS->items[i].aug_1, QS->items[i].aug_2,
|
||||||
|
QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5);
|
||||||
|
results = QueryDatabase(query);
|
||||||
|
if (!results.Success()) {
|
||||||
|
Log(Logs::Detail, Logs::QS_Server, "Failed Drop Record Entry Insert: %s", results.ErrorMessage().c_str());
|
||||||
|
Log(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Database::LogPlayerTrade(QSPlayerLogTrade_Struct* QS, uint32 detailCount) {
|
void Database::LogPlayerTrade(QSPlayerLogTrade_Struct* QS, uint32 detailCount) {
|
||||||
|
|
||||||
std::string query = StringFormat("INSERT INTO `qs_player_trade_record` SET `time` = NOW(), "
|
std::string query = StringFormat("INSERT INTO `qs_player_trade_record` SET `time` = NOW(), "
|
||||||
|
|||||||
@ -45,6 +45,7 @@ public:
|
|||||||
|
|
||||||
void AddSpeech(const char* from, const char* to, const char* message, uint16 minstatus, uint32 guilddbid, uint8 type);
|
void AddSpeech(const char* from, const char* to, const char* message, uint16 minstatus, uint32 guilddbid, uint8 type);
|
||||||
void LogPlayerTrade(QSPlayerLogTrade_Struct* QS, uint32 DetailCount);
|
void LogPlayerTrade(QSPlayerLogTrade_Struct* QS, uint32 DetailCount);
|
||||||
|
void LogPlayerDropItem(QSPlayerDropItem_Struct* QS);
|
||||||
void LogPlayerHandin(QSPlayerLogHandin_Struct* QS, uint32 DetailCount);
|
void LogPlayerHandin(QSPlayerLogHandin_Struct* QS, uint32 DetailCount);
|
||||||
void LogPlayerNPCKill(QSPlayerLogNPCKill_Struct* QS, uint32 Members);
|
void LogPlayerNPCKill(QSPlayerLogNPCKill_Struct* QS, uint32 Members);
|
||||||
void LogPlayerDelete(QSPlayerLogDelete_Struct* QS, uint32 Items);
|
void LogPlayerDelete(QSPlayerLogDelete_Struct* QS, uint32 Items);
|
||||||
|
|||||||
@ -98,6 +98,11 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
|||||||
database.LogPlayerTrade(QS, QS->_detail_count);
|
database.LogPlayerTrade(QS, QS->_detail_count);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ServerOP_QSPlayerDropItem: {
|
||||||
|
QSPlayerDropItem_Struct *QS = (QSPlayerDropItem_Struct *) p.Data();
|
||||||
|
database.LogPlayerDropItem(QS);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ServerOP_QSPlayerLogHandins: {
|
case ServerOP_QSPlayerLogHandins: {
|
||||||
QSPlayerLogHandin_Struct *QS = (QSPlayerLogHandin_Struct*)p.Data();
|
QSPlayerLogHandin_Struct *QS = (QSPlayerLogHandin_Struct*)p.Data();
|
||||||
database.LogPlayerHandin(QS, QS->_detail_count);
|
database.LogPlayerHandin(QS, QS->_detail_count);
|
||||||
|
|||||||
@ -40,7 +40,12 @@ if($Config{osname}=~/freebsd|linux/i){
|
|||||||
if($Config{osname}=~/Win|MS/i){
|
if($Config{osname}=~/Win|MS/i){
|
||||||
$OS = "Windows";
|
$OS = "Windows";
|
||||||
}
|
}
|
||||||
|
|
||||||
$has_internet_connection = check_internet_connection();
|
$has_internet_connection = check_internet_connection();
|
||||||
|
if(-e "skip_internet_connection_check.txt"){
|
||||||
|
$has_internet_connection = 1;
|
||||||
|
}
|
||||||
|
|
||||||
($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime();
|
($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime();
|
||||||
|
|
||||||
if(-e "eqemu_server_skip_update.txt"){
|
if(-e "eqemu_server_skip_update.txt"){
|
||||||
@ -826,6 +831,7 @@ sub show_menu_prompt {
|
|||||||
elsif($input eq "setup_bots"){ setup_bots(); $dc = 1; }
|
elsif($input eq "setup_bots"){ setup_bots(); $dc = 1; }
|
||||||
elsif($input eq "linux_login_server_setup"){ do_linux_login_server_setup(); $dc = 1; }
|
elsif($input eq "linux_login_server_setup"){ do_linux_login_server_setup(); $dc = 1; }
|
||||||
elsif($input eq "quest_heading_convert"){ quest_heading_convert(); $dc = 1; }
|
elsif($input eq "quest_heading_convert"){ quest_heading_convert(); $dc = 1; }
|
||||||
|
elsif($input eq "source_peq_db"){ fetch_peq_db_full(); $dc = 1; }
|
||||||
elsif($input eq "exit"){
|
elsif($input eq "exit"){
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,6 +54,8 @@ export apt_options="-y -qq" # Set autoconfirm and silent install
|
|||||||
|
|
||||||
################################################################
|
################################################################
|
||||||
|
|
||||||
|
if [ ! -f ./install_variables.txt ]; then
|
||||||
|
|
||||||
read -n1 -r -p "Press any key to continue..." key
|
read -n1 -r -p "Press any key to continue..." key
|
||||||
|
|
||||||
#::: Setting up user environment (eqemu)
|
#::: Setting up user environment (eqemu)
|
||||||
@ -84,6 +86,7 @@ read -p "Enter (Database) MySQL EQEmu Server password: " eqemu_db_password
|
|||||||
echo "mysql_eqemu_db_name:$eqemu_db_name" >> install_variables.txt
|
echo "mysql_eqemu_db_name:$eqemu_db_name" >> install_variables.txt
|
||||||
echo "mysql_eqemu_user:$eqemu_db_username" >> install_variables.txt
|
echo "mysql_eqemu_user:$eqemu_db_username" >> install_variables.txt
|
||||||
echo "mysql_eqemu_password:$eqemu_db_password" >> install_variables.txt
|
echo "mysql_eqemu_password:$eqemu_db_password" >> install_variables.txt
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ "$OS" == "Debian" ]]; then
|
if [[ "$OS" == "Debian" ]]; then
|
||||||
# Install pre-req packages
|
# Install pre-req packages
|
||||||
|
|||||||
@ -379,8 +379,10 @@
|
|||||||
9123|2018_07_07_data_buckets.sql|SHOW TABLES LIKE 'data_buckets'|empty|
|
9123|2018_07_07_data_buckets.sql|SHOW TABLES LIKE 'data_buckets'|empty|
|
||||||
9124|2018_07_09_tasks.sql|SHOW COLUMNS FROM `tasks` LIKE 'type'|empty|
|
9124|2018_07_09_tasks.sql|SHOW COLUMNS FROM `tasks` LIKE 'type'|empty|
|
||||||
9125|2018_07_20_task_emote.sql|SHOW COLUMNS FROM `tasks` LIKE 'completion_emote'|empty|
|
9125|2018_07_20_task_emote.sql|SHOW COLUMNS FROM `tasks` LIKE 'completion_emote'|empty|
|
||||||
9126|2018_08_13_inventory_version_update.sql|SHOW TABLES LIKE 'inventory_versions'|empty|
|
9126|2018_09_07_FastRegen.sql|SHOW COLUMNS FROM `zone` LIKE 'fast_regen_hp'|empty|
|
||||||
9127|2018_08_13_inventory_update.sql|SELECT * FROM `inventory_versions` WHERE `version` = 2 and `step` = 0|not_empty|
|
9127|2018_09_07_NPCMaxAggroDist.sql|SHOW COLUMNS FROM `zone` LIKE 'npc_max_aggro_dist'|empty|
|
||||||
|
9128|2018_08_13_inventory_version_update.sql|SHOW TABLES LIKE 'inventory_versions'|empty|
|
||||||
|
9129|2018_08_13_inventory_update.sql|SELECT * FROM `inventory_versions` WHERE `version` = 2 and `step` = 0|not_empty|
|
||||||
|
|
||||||
# Upgrade conditions:
|
# Upgrade conditions:
|
||||||
# This won't be needed after this system is implemented, but it is used database that are not
|
# This won't be needed after this system is implemented, but it is used database that are not
|
||||||
|
|||||||
3
utils/sql/git/required/2018_09_07_FastRegen.sql
Normal file
3
utils/sql/git/required/2018_09_07_FastRegen.sql
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
ALTER TABLE `zone` ADD `fast_regen_hp` INT NOT NULL DEFAULT '180';
|
||||||
|
ALTER TABLE `zone` ADD `fast_regen_mana` INT NOT NULL DEFAULT '180';
|
||||||
|
ALTER TABLE `zone` ADD `fast_regen_endurance` INT NOT NULL DEFAULT '180';
|
||||||
1
utils/sql/git/required/2018_09_07_NPCMaxAggroDist.sql
Normal file
1
utils/sql/git/required/2018_09_07_NPCMaxAggroDist.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE `zone` ADD `npc_max_aggro_dist` INT NOT NULL DEFAULT '600';
|
||||||
@ -1,11 +1,10 @@
|
|||||||
aa_ability
|
aa_ability
|
||||||
aa_actions
|
aa_actions
|
||||||
aa_effects
|
aa_effects
|
||||||
aa_required_level_cost
|
|
||||||
aa_ranks
|
|
||||||
aa_rank_effects
|
aa_rank_effects
|
||||||
aa_rank_prereqs
|
aa_rank_prereqs
|
||||||
task_activities
|
aa_ranks
|
||||||
|
aa_required_level_cost
|
||||||
adventure_template
|
adventure_template
|
||||||
adventure_template_entry
|
adventure_template_entry
|
||||||
adventure_template_entry_flavor
|
adventure_template_entry_flavor
|
||||||
@ -18,6 +17,7 @@ char_create_combinations
|
|||||||
char_create_point_allocations
|
char_create_point_allocations
|
||||||
class_skill
|
class_skill
|
||||||
damageshieldtypes
|
damageshieldtypes
|
||||||
|
data_buckets
|
||||||
doors
|
doors
|
||||||
faction_list
|
faction_list
|
||||||
faction_list_mod
|
faction_list_mod
|
||||||
@ -33,38 +33,39 @@ ground_spawns
|
|||||||
horses
|
horses
|
||||||
instance_list
|
instance_list
|
||||||
items
|
items
|
||||||
ldon_trap_templates
|
|
||||||
ldon_trap_entries
|
ldon_trap_entries
|
||||||
|
ldon_trap_templates
|
||||||
level_exp_mods
|
level_exp_mods
|
||||||
|
logsys_categories
|
||||||
lootdrop
|
lootdrop
|
||||||
lootdrop_entries
|
lootdrop_entries
|
||||||
loottable
|
loottable
|
||||||
loottable_entries
|
loottable_entries
|
||||||
merc_armorinfo
|
merc_armorinfo
|
||||||
merc_weaponinfo
|
merc_buffs
|
||||||
merc_stats
|
merc_inventory
|
||||||
merc_merchant_entries
|
merc_merchant_entries
|
||||||
merc_merchant_template_entries
|
merc_merchant_template_entries
|
||||||
merc_merchant_templates
|
merc_merchant_templates
|
||||||
merc_stance_entries
|
|
||||||
merc_templates
|
|
||||||
merc_npc_types
|
|
||||||
merc_name_types
|
merc_name_types
|
||||||
merc_subtypes
|
merc_npc_types
|
||||||
merc_types
|
|
||||||
merc_spell_list_entries
|
merc_spell_list_entries
|
||||||
merc_spell_lists
|
merc_spell_lists
|
||||||
merc_buffs
|
merc_stance_entries
|
||||||
mercs
|
merc_stats
|
||||||
merc_inventory
|
merc_subtypes
|
||||||
|
merc_templates
|
||||||
|
merc_types
|
||||||
|
merc_weaponinfo
|
||||||
merchantlist
|
merchantlist
|
||||||
|
mercs
|
||||||
npc_emotes
|
npc_emotes
|
||||||
npc_faction
|
npc_faction
|
||||||
npc_faction_entries
|
npc_faction_entries
|
||||||
npc_spells
|
npc_spells
|
||||||
npc_spells_entries
|
|
||||||
npc_spells_effects
|
npc_spells_effects
|
||||||
npc_spells_effects_entries
|
npc_spells_effects_entries
|
||||||
|
npc_spells_entries
|
||||||
npc_types
|
npc_types
|
||||||
npc_types_metadata
|
npc_types_metadata
|
||||||
npc_types_tint
|
npc_types_tint
|
||||||
@ -77,14 +78,15 @@ races
|
|||||||
saylink
|
saylink
|
||||||
skill_caps
|
skill_caps
|
||||||
spawn2
|
spawn2
|
||||||
spawn_conditions
|
|
||||||
spawn_condition_values
|
spawn_condition_values
|
||||||
|
spawn_conditions
|
||||||
spawn_events
|
spawn_events
|
||||||
spawnentry
|
spawnentry
|
||||||
spawngroup
|
spawngroup
|
||||||
spells_new
|
spells_new
|
||||||
start_zones
|
start_zones
|
||||||
starting_items
|
starting_items
|
||||||
|
task_activities
|
||||||
tasks
|
tasks
|
||||||
tasksets
|
tasksets
|
||||||
titles
|
titles
|
||||||
|
|||||||
@ -530,6 +530,28 @@ void ClientList::SendWhoAll(uint32 fromid,const char* to, int16 admin, Who_All_S
|
|||||||
//uint32 x = 0;
|
//uint32 x = 0;
|
||||||
int whomlen = 0;
|
int whomlen = 0;
|
||||||
if (whom) {
|
if (whom) {
|
||||||
|
// fixes for client converting some queries into a race query instead of zone
|
||||||
|
if (whom->wrace == 221) {
|
||||||
|
whom->wrace = 0xFFFF;
|
||||||
|
strcpy(whom->whom, "scarlet");
|
||||||
|
}
|
||||||
|
if (whom->wrace == 327) {
|
||||||
|
whom->wrace = 0xFFFF;
|
||||||
|
strcpy(whom->whom, "crystal");
|
||||||
|
}
|
||||||
|
if (whom->wrace == 103) {
|
||||||
|
whom->wrace = 0xFFFF;
|
||||||
|
strcpy(whom->whom, "kedge");
|
||||||
|
}
|
||||||
|
if (whom->wrace == 230) {
|
||||||
|
whom->wrace = 0xFFFF;
|
||||||
|
strcpy(whom->whom, "akheva");
|
||||||
|
}
|
||||||
|
if (whom->wrace == 229) {
|
||||||
|
whom->wrace = 0xFFFF;
|
||||||
|
strcpy(whom->whom, "netherbian");
|
||||||
|
}
|
||||||
|
|
||||||
whomlen = strlen(whom->whom);
|
whomlen = strlen(whom->whom);
|
||||||
if(whom->wrace == 0x001A) // 0x001A is the old Froglok race number and is sent by the client for /who all froglok
|
if(whom->wrace == 0x001A) // 0x001A is the old Froglok race number and is sent by the client for /who all froglok
|
||||||
whom->wrace = FROGLOK; // This is what EQEmu uses for the Froglok Race number.
|
whom->wrace = FROGLOK; // This is what EQEmu uses for the Froglok Race number.
|
||||||
|
|||||||
@ -1295,6 +1295,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
|||||||
case ServerOP_QSPlayerLogDeletes:
|
case ServerOP_QSPlayerLogDeletes:
|
||||||
case ServerOP_QSPlayerLogMoves:
|
case ServerOP_QSPlayerLogMoves:
|
||||||
case ServerOP_QSPlayerLogMerchantTransactions:
|
case ServerOP_QSPlayerLogMerchantTransactions:
|
||||||
|
case ServerOP_QSPlayerDropItem:
|
||||||
{
|
{
|
||||||
QSLink.SendPacket(pack);
|
QSLink.SendPacket(pack);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -107,16 +107,10 @@ void NPC::DescribeAggro(Client *towho, Mob *mob, bool verbose) {
|
|||||||
float iAggroRange = GetAggroRange();
|
float iAggroRange = GetAggroRange();
|
||||||
|
|
||||||
float t1, t2, t3;
|
float t1, t2, t3;
|
||||||
t1 = mob->GetX() - GetX();
|
t1 = std::abs(mob->GetX() - GetX());
|
||||||
t2 = mob->GetY() - GetY();
|
t2 = std::abs(mob->GetY() - GetY());
|
||||||
t3 = mob->GetZ() - GetZ();
|
t3 = std::abs(mob->GetZ() - GetZ());
|
||||||
//Cheap ABS()
|
|
||||||
if(t1 < 0)
|
|
||||||
t1 = 0 - t1;
|
|
||||||
if(t2 < 0)
|
|
||||||
t2 = 0 - t2;
|
|
||||||
if(t3 < 0)
|
|
||||||
t3 = 0 - t3;
|
|
||||||
if(( t1 > iAggroRange)
|
if(( t1 > iAggroRange)
|
||||||
|| ( t2 > iAggroRange)
|
|| ( t2 > iAggroRange)
|
||||||
|| ( t3 > iAggroRange) ) {
|
|| ( t3 > iAggroRange) ) {
|
||||||
@ -271,16 +265,10 @@ bool Mob::CheckWillAggro(Mob *mob) {
|
|||||||
// Image: I moved this up by itself above faction and distance checks because if one of these return true, theres no reason to go through the other information
|
// Image: I moved this up by itself above faction and distance checks because if one of these return true, theres no reason to go through the other information
|
||||||
|
|
||||||
float t1, t2, t3;
|
float t1, t2, t3;
|
||||||
t1 = mob->GetX() - GetX();
|
t1 = std::abs(mob->GetX() - GetX());
|
||||||
t2 = mob->GetY() - GetY();
|
t2 = std::abs(mob->GetY() - GetY());
|
||||||
t3 = mob->GetZ() - GetZ();
|
t3 = std::abs(mob->GetZ() - GetZ());
|
||||||
//Cheap ABS()
|
|
||||||
if(t1 < 0)
|
|
||||||
t1 = 0 - t1;
|
|
||||||
if(t2 < 0)
|
|
||||||
t2 = 0 - t2;
|
|
||||||
if(t3 < 0)
|
|
||||||
t3 = 0 - t3;
|
|
||||||
if(( t1 > iAggroRange)
|
if(( t1 > iAggroRange)
|
||||||
|| ( t2 > iAggroRange)
|
|| ( t2 > iAggroRange)
|
||||||
|| ( t3 > iAggroRange)
|
|| ( t3 > iAggroRange)
|
||||||
@ -424,7 +412,7 @@ Mob* EntityList::AICheckNPCtoNPCAggro(Mob* sender, float iAggroRange, float iAss
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int EntityList::GetHatedCount(Mob *attacker, Mob *exclude)
|
int EntityList::GetHatedCount(Mob *attacker, Mob *exclude, bool inc_gray_con)
|
||||||
{
|
{
|
||||||
// Return a list of how many non-feared, non-mezzed, non-green mobs, within aggro range, hate *attacker
|
// Return a list of how many non-feared, non-mezzed, non-green mobs, within aggro range, hate *attacker
|
||||||
if (!attacker)
|
if (!attacker)
|
||||||
@ -434,20 +422,25 @@ int EntityList::GetHatedCount(Mob *attacker, Mob *exclude)
|
|||||||
|
|
||||||
for (auto it = npc_list.begin(); it != npc_list.end(); ++it) {
|
for (auto it = npc_list.begin(); it != npc_list.end(); ++it) {
|
||||||
NPC *mob = it->second;
|
NPC *mob = it->second;
|
||||||
if (!mob || (mob == exclude))
|
if (!mob || (mob == exclude)) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!mob->IsEngaged())
|
if (!mob->IsEngaged()) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (mob->IsFeared() || mob->IsMezzed())
|
if (mob->IsFeared() || mob->IsMezzed()) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (attacker->GetLevelCon(mob->GetLevel()) == CON_GRAY)
|
if (!inc_gray_con && attacker->GetLevelCon(mob->GetLevel()) == CON_GRAY) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!mob->CheckAggro(attacker))
|
if (!mob->CheckAggro(attacker)) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
float AggroRange = mob->GetAggroRange();
|
float AggroRange = mob->GetAggroRange();
|
||||||
|
|
||||||
@ -455,14 +448,12 @@ int EntityList::GetHatedCount(Mob *attacker, Mob *exclude)
|
|||||||
|
|
||||||
AggroRange *= AggroRange;
|
AggroRange *= AggroRange;
|
||||||
|
|
||||||
if (DistanceSquared(mob->GetPosition(), attacker->GetPosition()) > AggroRange)
|
if (DistanceSquared(mob->GetPosition(), attacker->GetPosition()) > AggroRange) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
Count++;
|
Count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Count;
|
return Count;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityList::AIYellForHelp(Mob* sender, Mob* attacker) {
|
void EntityList::AIYellForHelp(Mob* sender, Mob* attacker) {
|
||||||
@ -523,7 +514,7 @@ void EntityList::AIYellForHelp(Mob* sender, Mob* attacker) {
|
|||||||
Log(Logs::General, Logs::None, "AIYellForHelp(\"%s\",\"%s\") %s attacking %s Dist %f Z %f",
|
Log(Logs::General, Logs::None, "AIYellForHelp(\"%s\",\"%s\") %s attacking %s Dist %f Z %f",
|
||||||
sender->GetName(), attacker->GetName(), mob->GetName(),
|
sender->GetName(), attacker->GetName(), mob->GetName(),
|
||||||
attacker->GetName(), DistanceSquared(mob->GetPosition(),
|
attacker->GetName(), DistanceSquared(mob->GetPosition(),
|
||||||
sender->GetPosition()), fabs(sender->GetZ()+mob->GetZ()));
|
sender->GetPosition()), std::abs(sender->GetZ()+mob->GetZ()));
|
||||||
#endif
|
#endif
|
||||||
mob->AddToHateList(attacker, 25, 0, false);
|
mob->AddToHateList(attacker, 25, 0, false);
|
||||||
sender->AddAssistCap();
|
sender->AddAssistCap();
|
||||||
|
|||||||
@ -5455,3 +5455,11 @@ void Mob::DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Mob::GetWasSpawnedInWater() const {
|
||||||
|
return spawned_in_water;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mob::SetSpawnedInWater(bool spawned_in_water) {
|
||||||
|
Mob::spawned_in_water = spawned_in_water;
|
||||||
|
}
|
||||||
|
|||||||
@ -7014,9 +7014,9 @@ void Bot::CalcRestState() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RestRegenHP = 6 * (GetMaxHP() / RuleI(Character, RestRegenHP));
|
RestRegenHP = 6 * (GetMaxHP() / zone->newzone_data.FastRegenHP);
|
||||||
RestRegenMana = 6 * (GetMaxMana() / RuleI(Character, RestRegenMana));
|
RestRegenMana = 6 * (GetMaxMana() / zone->newzone_data.FastRegenMana);
|
||||||
RestRegenEndurance = 6 * (GetMaxEndurance() / RuleI(Character, RestRegenEnd));
|
RestRegenEndurance = 6 * (GetMaxEndurance() / zone->newzone_data.FastRegenEndurance);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 Bot::LevelRegen() {
|
int32 Bot::LevelRegen() {
|
||||||
|
|||||||
@ -8081,9 +8081,9 @@ void Client::SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, ui
|
|||||||
{
|
{
|
||||||
//The ole switcheroo
|
//The ole switcheroo
|
||||||
if (npc_value[i] > 0)
|
if (npc_value[i] > 0)
|
||||||
npc_value[i] = -abs(npc_value[i]);
|
npc_value[i] = -std::abs(npc_value[i]);
|
||||||
else if (npc_value[i] < 0)
|
else if (npc_value[i] < 0)
|
||||||
npc_value[i] = abs(npc_value[i]);
|
npc_value[i] = std::abs(npc_value[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust the amount you can go up or down so the resulting range
|
// Adjust the amount you can go up or down so the resulting range
|
||||||
|
|||||||
@ -876,6 +876,7 @@ public:
|
|||||||
void SetStats(uint8 type,int16 set_val);
|
void SetStats(uint8 type,int16 set_val);
|
||||||
void IncStats(uint8 type,int16 increase_val);
|
void IncStats(uint8 type,int16 increase_val);
|
||||||
void DropItem(int16 slot_id, bool recurse = true);
|
void DropItem(int16 slot_id, bool recurse = true);
|
||||||
|
void DropItemQS(EQEmu::ItemInstance* inst, bool pickup);
|
||||||
|
|
||||||
int GetItemLinkHash(const EQEmu::ItemInstance* inst); // move to ItemData..or make use of the pre-calculated database field
|
int GetItemLinkHash(const EQEmu::ItemInstance* inst); // move to ItemData..or make use of the pre-calculated database field
|
||||||
|
|
||||||
|
|||||||
@ -290,9 +290,8 @@ int32 Client::CalcHPRegen(bool bCombat)
|
|||||||
// another check for IsClient && !(base + item_regen) && Cur_HP <= 0 do --base; do later
|
// another check for IsClient && !(base + item_regen) && Cur_HP <= 0 do --base; do later
|
||||||
|
|
||||||
if (!bCombat && CanFastRegen() && (IsSitting() || CanMedOnHorse())) {
|
if (!bCombat && CanFastRegen() && (IsSitting() || CanMedOnHorse())) {
|
||||||
auto fast_mod = RuleI(Character, RestRegenHP); // TODO: this is actually zone based
|
|
||||||
auto max_hp = GetMaxHP();
|
auto max_hp = GetMaxHP();
|
||||||
int fast_regen = 6 * (max_hp / fast_mod);
|
int fast_regen = 6 * (max_hp / zone->newzone_data.FastRegenHP);
|
||||||
if (base < fast_regen) // weird, but what the client is doing
|
if (base < fast_regen) // weird, but what the client is doing
|
||||||
base = fast_regen;
|
base = fast_regen;
|
||||||
}
|
}
|
||||||
@ -1296,9 +1295,8 @@ int32 Client::CalcManaRegen(bool bCombat)
|
|||||||
regen = regen * 100.0f * AreaManaRegen * 0.01f + 0.5f;
|
regen = regen * 100.0f * AreaManaRegen * 0.01f + 0.5f;
|
||||||
|
|
||||||
if (!bCombat && CanFastRegen() && (IsSitting() || CanMedOnHorse())) {
|
if (!bCombat && CanFastRegen() && (IsSitting() || CanMedOnHorse())) {
|
||||||
auto fast_mod = RuleI(Character, RestRegenMana); // TODO: this is actually zone based
|
|
||||||
auto max_mana = GetMaxMana();
|
auto max_mana = GetMaxMana();
|
||||||
int fast_regen = 6 * (max_mana / fast_mod);
|
int fast_regen = 6 * (max_mana / zone->newzone_data.FastRegenMana);
|
||||||
if (regen < fast_regen) // weird, but what the client is doing
|
if (regen < fast_regen) // weird, but what the client is doing
|
||||||
regen = fast_regen;
|
regen = fast_regen;
|
||||||
}
|
}
|
||||||
@ -2264,9 +2262,8 @@ int32 Client::CalcEnduranceRegen(bool bCombat)
|
|||||||
|
|
||||||
int regen = base;
|
int regen = base;
|
||||||
if (!bCombat && CanFastRegen() && (IsSitting() || CanMedOnHorse())) {
|
if (!bCombat && CanFastRegen() && (IsSitting() || CanMedOnHorse())) {
|
||||||
auto fast_mod = RuleI(Character, RestRegenEnd); // TODO: this is actually zone based
|
|
||||||
auto max_end = GetMaxEndurance();
|
auto max_end = GetMaxEndurance();
|
||||||
int fast_regen = 6 * (max_end / fast_mod);
|
int fast_regen = 6 * (max_end / zone->newzone_data.FastRegenEndurance);
|
||||||
if (aa_regen < fast_regen) // weird, but what the client is doing
|
if (aa_regen < fast_regen) // weird, but what the client is doing
|
||||||
aa_regen = fast_regen;
|
aa_regen = fast_regen;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2950,7 +2950,11 @@ void Client::Handle_OP_Assist(const EQApplicationPacket *app)
|
|||||||
Distance(m_Position, assistee->GetPosition()) <= TARGETING_RANGE)) {
|
Distance(m_Position, assistee->GetPosition()) <= TARGETING_RANGE)) {
|
||||||
SetAssistExemption(true);
|
SetAssistExemption(true);
|
||||||
eid->entity_id = new_target->GetID();
|
eid->entity_id = new_target->GetID();
|
||||||
|
} else {
|
||||||
|
eid->entity_id = 0;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
eid->entity_id = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -39,6 +39,7 @@
|
|||||||
#include "raids.h"
|
#include "raids.h"
|
||||||
#include "string_ids.h"
|
#include "string_ids.h"
|
||||||
#include "worldserver.h"
|
#include "worldserver.h"
|
||||||
|
#include "water_map.h"
|
||||||
|
|
||||||
#ifdef _WINDOWS
|
#ifdef _WINDOWS
|
||||||
#define snprintf _snprintf
|
#define snprintf _snprintf
|
||||||
@ -686,6 +687,15 @@ void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set whether NPC was spawned in or out of water
|
||||||
|
*/
|
||||||
|
if (zone->HasMap() && zone->HasWaterMap()) {
|
||||||
|
npc->SetSpawnedInWater(false);
|
||||||
|
if (zone->watermap->InLiquid(npc->GetPosition())) {
|
||||||
|
npc->SetSpawnedInWater(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityList::AddMerc(Merc *merc, bool SendSpawnPacket, bool dontqueue)
|
void EntityList::AddMerc(Merc *merc, bool SendSpawnPacket, bool dontqueue)
|
||||||
@ -3425,14 +3435,15 @@ void EntityList::ProcessMove(Client *c, const glm::vec3& location)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityList::ProcessMove(NPC *n, float x, float y, float z)
|
void EntityList::ProcessMove(NPC *n, float x, float y, float z) {
|
||||||
{
|
|
||||||
float last_x = n->GetX();
|
float last_x = n->GetX();
|
||||||
float last_y = n->GetY();
|
float last_y = n->GetY();
|
||||||
float last_z = n->GetZ();
|
float last_z = n->GetZ();
|
||||||
|
|
||||||
std::list<quest_proximity_event> events;
|
std::list<quest_proximity_event> events;
|
||||||
|
|
||||||
for (auto iter = area_list.begin(); iter != area_list.end(); ++iter) {
|
for (auto iter = area_list.begin(); iter != area_list.end(); ++iter) {
|
||||||
|
|
||||||
Area &a = (*iter);
|
Area &a = (*iter);
|
||||||
bool old_in = true;
|
bool old_in = true;
|
||||||
bool new_in = true;
|
bool new_in = true;
|
||||||
@ -3457,7 +3468,8 @@ void EntityList::ProcessMove(NPC *n, float x, float y, float z)
|
|||||||
evt.area_id = a.id;
|
evt.area_id = a.id;
|
||||||
evt.area_type = a.type;
|
evt.area_type = a.type;
|
||||||
events.push_back(evt);
|
events.push_back(evt);
|
||||||
} else if (!old_in && new_in) {
|
}
|
||||||
|
else if (!old_in && new_in) {
|
||||||
//were not in but now are
|
//were not in but now are
|
||||||
quest_proximity_event evt;
|
quest_proximity_event evt;
|
||||||
evt.event_id = EVENT_ENTER_AREA;
|
evt.event_id = EVENT_ENTER_AREA;
|
||||||
|
|||||||
@ -416,7 +416,7 @@ public:
|
|||||||
|
|
||||||
void CheckClientAggro(Client *around);
|
void CheckClientAggro(Client *around);
|
||||||
Mob* AICheckNPCtoNPCAggro(Mob* sender, float iAggroRange, float iAssistRange);
|
Mob* AICheckNPCtoNPCAggro(Mob* sender, float iAggroRange, float iAssistRange);
|
||||||
int GetHatedCount(Mob *attacker, Mob *exclude);
|
int GetHatedCount(Mob *attacker, Mob *exclude, bool inc_gray_con);
|
||||||
void AIYellForHelp(Mob* sender, Mob* attacker);
|
void AIYellForHelp(Mob* sender, Mob* attacker);
|
||||||
bool AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float iRange, uint32 iSpellTypes);
|
bool AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float iRange, uint32 iSpellTypes);
|
||||||
bool Merc_AICheckCloseBeneficialSpells(Merc* caster, uint8 iChance, float iRange, uint32 iSpellTypes);
|
bool Merc_AICheckCloseBeneficialSpells(Merc* caster, uint8 iChance, float iRange, uint32 iSpellTypes);
|
||||||
|
|||||||
@ -31,71 +31,91 @@ extern Zone* zone;
|
|||||||
|
|
||||||
//this is called whenever we are damaged to process possible fleeing
|
//this is called whenever we are damaged to process possible fleeing
|
||||||
void Mob::CheckFlee() {
|
void Mob::CheckFlee() {
|
||||||
//if were allready fleeing, dont need to check more...
|
|
||||||
if(flee_mode && currently_fleeing)
|
// if mob is dead why would you run?
|
||||||
|
if(GetHP() == 0) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if were already fleeing, don't need to check more...
|
||||||
|
if(flee_mode && currently_fleeing) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//dont bother if we are immune to fleeing
|
//dont bother if we are immune to fleeing
|
||||||
if(GetSpecialAbility(IMMUNE_FLEEING) || spellbonuses.ImmuneToFlee)
|
if(GetSpecialAbility(IMMUNE_FLEEING) || spellbonuses.ImmuneToFlee) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(!flee_timer.Check())
|
// Check if Flee Timer is cleared
|
||||||
return; //only do all this stuff every little while, since
|
if(!flee_timer.Check()) {
|
||||||
//its not essential that we start running RIGHT away
|
|
||||||
|
|
||||||
//see if were possibly hurt enough
|
|
||||||
float ratio = GetHPRatio();
|
|
||||||
float fleeratio = GetSpecialAbility(FLEE_PERCENT);
|
|
||||||
fleeratio = fleeratio > 0 ? fleeratio : RuleI(Combat, FleeHPRatio);
|
|
||||||
|
|
||||||
if(ratio >= fleeratio)
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//we might be hurt enough, check con now..
|
int hpratio = GetIntHPRatio();
|
||||||
|
int fleeratio = GetSpecialAbility(FLEE_PERCENT); // if a special flee_percent exists
|
||||||
Mob *hate_top = GetHateTop();
|
Mob *hate_top = GetHateTop();
|
||||||
|
|
||||||
|
// Sanity Check for race conditions
|
||||||
|
if(hate_top == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no special flee_percent check for Gray or Other con rates
|
||||||
|
if(GetLevelCon(hate_top->GetLevel(), GetLevel()) == CON_GRAY && fleeratio == 0 && RuleB(Combat, FleeGray)) {
|
||||||
|
fleeratio = RuleI(Combat, FleeGrayHPRatio);
|
||||||
|
} else if(fleeratio == 0) {
|
||||||
|
fleeratio = RuleI(Combat, FleeHPRatio );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mob does not have low enough health to flee
|
||||||
|
if(hpratio >= fleeratio) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanity Check this should never happen...
|
||||||
if(!hate_top) {
|
if(!hate_top) {
|
||||||
//this should never happen...
|
|
||||||
StartFleeing();
|
StartFleeing();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
float other_ratio = hate_top->GetHPRatio();
|
int other_ratio = hate_top->GetIntHPRatio();
|
||||||
|
// If the Client is nearing death the NPC will not flee and instead try to kill the client.
|
||||||
if(other_ratio < 20) {
|
if(other_ratio < 20) {
|
||||||
//our hate top is almost dead too... stay and fight
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//base our flee ratio on our con. this is how the
|
// Flee Chance checking based on con.
|
||||||
//attacker sees the mob, since this is all we can observe
|
|
||||||
uint32 con = GetLevelCon(hate_top->GetLevel(), GetLevel());
|
uint32 con = GetLevelCon(hate_top->GetLevel(), GetLevel());
|
||||||
float run_ratio;
|
int flee_chance;
|
||||||
switch(con) {
|
switch(con) {
|
||||||
//these values are not 100% researched
|
//these values are not 100% researched
|
||||||
case CON_GRAY:
|
case CON_GRAY:
|
||||||
run_ratio = fleeratio;
|
flee_chance = 100;
|
||||||
break;
|
break;
|
||||||
case CON_GREEN:
|
case CON_GREEN:
|
||||||
run_ratio = fleeratio * 9 / 10;
|
flee_chance = 90;
|
||||||
break;
|
break;
|
||||||
case CON_LIGHTBLUE:
|
case CON_LIGHTBLUE:
|
||||||
run_ratio = fleeratio * 9 / 10;
|
flee_chance = 90;
|
||||||
break;
|
break;
|
||||||
case CON_BLUE:
|
case CON_BLUE:
|
||||||
run_ratio = fleeratio * 8 / 10;
|
flee_chance = 80;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
run_ratio = fleeratio * 7 / 10;
|
flee_chance = 70;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(ratio < run_ratio)
|
|
||||||
{
|
// If we got here we are allowed to roll on flee chance if there is not other hated NPC's in the area.
|
||||||
if (RuleB(Combat, FleeIfNotAlone) ||
|
|
||||||
GetSpecialAbility(ALWAYS_FLEE) ||
|
if(RuleB(Combat, FleeIfNotAlone) || GetSpecialAbility(ALWAYS_FLEE) || zone->random.Roll(flee_chance) && entity_list.GetHatedCount(hate_top, this, true) == 0) {
|
||||||
(!RuleB(Combat, FleeIfNotAlone) && (entity_list.GetHatedCount(hate_top, this) == 0)))
|
currently_fleeing = true;
|
||||||
StartFleeing();
|
StartFleeing();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Mob::ProcessFlee()
|
void Mob::ProcessFlee()
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -107,11 +127,21 @@ void Mob::ProcessFlee()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//see if we are still dying, if so, do nothing
|
int hpratio = GetIntHPRatio();
|
||||||
float fleeratio = GetSpecialAbility(FLEE_PERCENT);
|
int fleeratio = GetSpecialAbility(FLEE_PERCENT); // if a special flee_percent exists
|
||||||
fleeratio = fleeratio > 0 ? fleeratio : RuleI(Combat, FleeHPRatio);
|
Mob *hate_top = GetHateTop();
|
||||||
if (GetHPRatio() < fleeratio)
|
|
||||||
|
// If no special flee_percent check for Gray or Other con rates
|
||||||
|
if(hate_top != nullptr && GetLevelCon(hate_top->GetLevel(), GetLevel()) == CON_GRAY && fleeratio == 0 && RuleB(Combat, FleeGray)) {
|
||||||
|
fleeratio = RuleI(Combat, FleeGrayHPRatio);
|
||||||
|
} else if(fleeratio == 0) {
|
||||||
|
fleeratio = RuleI(Combat, FleeHPRatio );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mob is still too low. Keep Running
|
||||||
|
if(hpratio < fleeratio) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//we are not dying anymore... see what we do next
|
//we are not dying anymore... see what we do next
|
||||||
|
|
||||||
@ -125,19 +155,21 @@ void Mob::ProcessFlee()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mob::CalculateNewFearpoint()
|
void Mob::CalculateNewFearpoint() {
|
||||||
{
|
if (RuleB(Pathing, Fear) && zone->pathing) {
|
||||||
if(RuleB(Pathing, Fear) && zone->pathing)
|
|
||||||
{
|
|
||||||
auto Node = zone->pathing->GetRandomLocation();
|
auto Node = zone->pathing->GetRandomLocation();
|
||||||
if (Node.x != 0.0f || Node.y != 0.0f || Node.z != 0.0f) {
|
if (Node.x != 0.0f || Node.y != 0.0f || Node.z != 0.0f) {
|
||||||
|
|
||||||
++Node.z;
|
++Node.z;
|
||||||
m_FearWalkTarget = Node;
|
m_FearWalkTarget = Node;
|
||||||
|
currently_fleeing = true;
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::None, "No path found to selected node. Falling through to old fear point selection.");
|
Log(Logs::Detail,
|
||||||
|
Logs::Pathing,
|
||||||
|
"No path found to selected node. Falling through to old fear point selection.");
|
||||||
}
|
}
|
||||||
|
|
||||||
int loop = 0;
|
int loop = 0;
|
||||||
@ -154,8 +186,7 @@ void Mob::CalculateNewFearpoint()
|
|||||||
if (ranz == BEST_Z_INVALID)
|
if (ranz == BEST_Z_INVALID)
|
||||||
continue;
|
continue;
|
||||||
float fdist = ranz - GetZ();
|
float fdist = ranz - GetZ();
|
||||||
if (fdist >= -12 && fdist <= 12 && CheckCoordLosNoZLeaps(GetX(),GetY(),GetZ(),ranx,rany,ranz))
|
if (fdist >= -12 && fdist <= 12 && CheckCoordLosNoZLeaps(GetX(), GetY(), GetZ(), ranx, rany, ranz)) {
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -575,12 +575,19 @@ int HateList::AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOption
|
|||||||
if (!target || !caster)
|
if (!target || !caster)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
// tank will be hit ONLY if they are the only target on the hate list
|
||||||
|
// if there is anyone else on the hate list, the tank will not be hit, even if those others aren't hit either
|
||||||
|
if (list.size() == 1) {
|
||||||
|
caster->ProcessAttackRounds(target, opts);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int hit_count = 0;
|
int hit_count = 0;
|
||||||
// This should prevent crashes if something dies (or mainly more than 1 thing goes away)
|
// This should prevent crashes if something dies (or mainly more than 1 thing goes away)
|
||||||
// This is a temp solution until the hate lists can be rewritten to not have that issue
|
// This is a temp solution until the hate lists can be rewritten to not have that issue
|
||||||
std::vector<uint16> id_list;
|
std::vector<uint16> id_list;
|
||||||
for (auto &h : list) {
|
for (auto &h : list) {
|
||||||
if (h->entity_on_hatelist && h->entity_on_hatelist != caster &&
|
if (h->entity_on_hatelist && h->entity_on_hatelist != caster && h->entity_on_hatelist != target &&
|
||||||
caster->CombatRange(h->entity_on_hatelist))
|
caster->CombatRange(h->entity_on_hatelist))
|
||||||
id_list.push_back(h->entity_on_hatelist->GetID());
|
id_list.push_back(h->entity_on_hatelist->GetID());
|
||||||
if (count != -1 && id_list.size() > count)
|
if (count != -1 && id_list.size() > count)
|
||||||
|
|||||||
@ -596,15 +596,15 @@ void Client::DropItem(int16 slot_id, bool recurse)
|
|||||||
if (LogSys.log_settings[Logs::Inventory].is_category_enabled) {
|
if (LogSys.log_settings[Logs::Inventory].is_category_enabled) {
|
||||||
Log(Logs::General, Logs::Inventory, "DropItem() Hack detected - full item parse:");
|
Log(Logs::General, Logs::Inventory, "DropItem() Hack detected - full item parse:");
|
||||||
Log(Logs::General, Logs::Inventory, "depth: 0, Item: '%s' (id: %u), IsDroppable: %s",
|
Log(Logs::General, Logs::Inventory, "depth: 0, Item: '%s' (id: %u), IsDroppable: %s",
|
||||||
(invalid_drop->GetItem() ? invalid_drop->GetItem()->Name : "null data"), invalid_drop->GetID(), invalid_drop->IsDroppable(false));
|
(invalid_drop->GetItem() ? invalid_drop->GetItem()->Name : "null data"), invalid_drop->GetID(), (invalid_drop->IsDroppable(false) ? "true" : "false"));
|
||||||
|
|
||||||
for (auto iter1 : *invalid_drop->GetContents()) { // depth 1
|
for (auto iter1 : *invalid_drop->GetContents()) { // depth 1
|
||||||
Log(Logs::General, Logs::Inventory, "-depth: 1, Item: '%s' (id: %u), IsDroppable: %s",
|
Log(Logs::General, Logs::Inventory, "-depth: 1, Item: '%s' (id: %u), IsDroppable: %s",
|
||||||
(iter1.second->GetItem() ? iter1.second->GetItem()->Name : "null data"), iter1.second->GetID(), iter1.second->IsDroppable(false));
|
(iter1.second->GetItem() ? iter1.second->GetItem()->Name : "null data"), iter1.second->GetID(), (iter1.second->IsDroppable(false) ? "true" : "false"));
|
||||||
|
|
||||||
for (auto iter2 : *iter1.second->GetContents()) { // depth 2
|
for (auto iter2 : *iter1.second->GetContents()) { // depth 2
|
||||||
Log(Logs::General, Logs::Inventory, "--depth: 2, Item: '%s' (id: %u), IsDroppable: %s",
|
Log(Logs::General, Logs::Inventory, "--depth: 2, Item: '%s' (id: %u), IsDroppable: %s",
|
||||||
(iter2.second->GetItem() ? iter2.second->GetItem()->Name : "null data"), iter2.second->GetID(), iter2.second->IsDroppable(false));
|
(iter2.second->GetItem() ? iter2.second->GetItem()->Name : "null data"), iter2.second->GetID(), (iter2.second->IsDroppable(false) ? "true" : "false"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -622,21 +622,21 @@ void Client::DropItem(int16 slot_id, bool recurse)
|
|||||||
if (LogSys.log_settings[Logs::Inventory].is_category_enabled) {
|
if (LogSys.log_settings[Logs::Inventory].is_category_enabled) {
|
||||||
Log(Logs::General, Logs::Inventory, "DropItem() Processing - full item parse:");
|
Log(Logs::General, Logs::Inventory, "DropItem() Processing - full item parse:");
|
||||||
Log(Logs::General, Logs::Inventory, "depth: 0, Item: '%s' (id: %u), IsDroppable: %s",
|
Log(Logs::General, Logs::Inventory, "depth: 0, Item: '%s' (id: %u), IsDroppable: %s",
|
||||||
(inst->GetItem() ? inst->GetItem()->Name : "null data"), inst->GetID(), inst->IsDroppable(false));
|
(inst->GetItem() ? inst->GetItem()->Name : "null data"), inst->GetID(), (inst->IsDroppable(false) ? "true" : "false"));
|
||||||
|
|
||||||
if (!inst->IsDroppable(false))
|
if (!inst->IsDroppable(false))
|
||||||
Log(Logs::General, Logs::Error, "Non-droppable item being processed for drop by '%s'", GetCleanName());
|
Log(Logs::General, Logs::Error, "Non-droppable item being processed for drop by '%s'", GetCleanName());
|
||||||
|
|
||||||
for (auto iter1 : *inst->GetContents()) { // depth 1
|
for (auto iter1 : *inst->GetContents()) { // depth 1
|
||||||
Log(Logs::General, Logs::Inventory, "-depth: 1, Item: '%s' (id: %u), IsDroppable: %s",
|
Log(Logs::General, Logs::Inventory, "-depth: 1, Item: '%s' (id: %u), IsDroppable: %s",
|
||||||
(iter1.second->GetItem() ? iter1.second->GetItem()->Name : "null data"), iter1.second->GetID(), iter1.second->IsDroppable(false));
|
(iter1.second->GetItem() ? iter1.second->GetItem()->Name : "null data"), iter1.second->GetID(), (iter1.second->IsDroppable(false) ? "true" : "false"));
|
||||||
|
|
||||||
if (!iter1.second->IsDroppable(false))
|
if (!iter1.second->IsDroppable(false))
|
||||||
Log(Logs::General, Logs::Error, "Non-droppable item being processed for drop by '%s'", GetCleanName());
|
Log(Logs::General, Logs::Error, "Non-droppable item being processed for drop by '%s'", GetCleanName());
|
||||||
|
|
||||||
for (auto iter2 : *iter1.second->GetContents()) { // depth 2
|
for (auto iter2 : *iter1.second->GetContents()) { // depth 2
|
||||||
Log(Logs::General, Logs::Inventory, "--depth: 2, Item: '%s' (id: %u), IsDroppable: %s",
|
Log(Logs::General, Logs::Inventory, "--depth: 2, Item: '%s' (id: %u), IsDroppable: %s",
|
||||||
(iter2.second->GetItem() ? iter2.second->GetItem()->Name : "null data"), iter2.second->GetID(), iter2.second->IsDroppable(false));
|
(iter2.second->GetItem() ? iter2.second->GetItem()->Name : "null data"), iter2.second->GetID(), (iter2.second->IsDroppable(false) ? "true" : "false"));
|
||||||
|
|
||||||
if (!iter2.second->IsDroppable(false))
|
if (!iter2.second->IsDroppable(false))
|
||||||
Log(Logs::General, Logs::Error, "Non-droppable item being processed for drop by '%s'", GetCleanName());
|
Log(Logs::General, Logs::Error, "Non-droppable item being processed for drop by '%s'", GetCleanName());
|
||||||
@ -674,10 +674,79 @@ void Client::DropItem(int16 slot_id, bool recurse)
|
|||||||
object->StartDecay();
|
object->StartDecay();
|
||||||
|
|
||||||
Log(Logs::General, Logs::Inventory, "Item drop handled ut assolet");
|
Log(Logs::General, Logs::Inventory, "Item drop handled ut assolet");
|
||||||
|
DropItemQS(inst, false);
|
||||||
|
|
||||||
safe_delete(inst);
|
safe_delete(inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::DropItemQS(EQEmu::ItemInstance* inst, bool pickup) {
|
||||||
|
if (RuleB(QueryServ, PlayerDropItems)) {
|
||||||
|
QSPlayerDropItem_Struct qs_audit;
|
||||||
|
std::list<void*> event_details;
|
||||||
|
memset(&qs_audit, 0, sizeof(QSPlayerDropItem_Struct));
|
||||||
|
|
||||||
|
qs_audit.char_id = this->character_id;
|
||||||
|
qs_audit.pickup = pickup;
|
||||||
|
qs_audit.zone_id = this->GetZoneID();
|
||||||
|
qs_audit.x = (int) this->GetX();
|
||||||
|
qs_audit.y = (int) this->GetY();
|
||||||
|
qs_audit.z = (int) this->GetZ();
|
||||||
|
|
||||||
|
if (inst) {
|
||||||
|
auto detail = new QSDropItems_Struct;
|
||||||
|
detail->item_id = inst->GetID();
|
||||||
|
detail->charges = inst->IsClassBag() ? 1 : inst->GetCharges();
|
||||||
|
detail->aug_1 = inst->GetAugmentItemID(1);
|
||||||
|
detail->aug_2 = inst->GetAugmentItemID(2);
|
||||||
|
detail->aug_3 = inst->GetAugmentItemID(3);
|
||||||
|
detail->aug_4 = inst->GetAugmentItemID(4);
|
||||||
|
detail->aug_5 = inst->GetAugmentItemID(5);
|
||||||
|
event_details.push_back(detail);
|
||||||
|
|
||||||
|
if (inst->IsClassBag()) {
|
||||||
|
for (uint8 sub_slot = EQEmu::invbag::SLOT_BEGIN; (sub_slot <= EQEmu::invbag::SLOT_END); ++sub_slot) { // this is to catch ALL items
|
||||||
|
const EQEmu::ItemInstance* bag_inst = inst->GetItem(sub_slot);
|
||||||
|
if (bag_inst) {
|
||||||
|
detail = new QSDropItems_Struct;
|
||||||
|
detail->item_id = bag_inst->GetID();
|
||||||
|
detail->charges = (!bag_inst->IsStackable() ? 1 : bag_inst->GetCharges());
|
||||||
|
detail->aug_1 = bag_inst->GetAugmentItemID(1);
|
||||||
|
detail->aug_2 = bag_inst->GetAugmentItemID(2);
|
||||||
|
detail->aug_3 = bag_inst->GetAugmentItemID(3);
|
||||||
|
detail->aug_4 = bag_inst->GetAugmentItemID(4);
|
||||||
|
detail->aug_5 = bag_inst->GetAugmentItemID(5);
|
||||||
|
event_details.push_back(detail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
qs_audit._detail_count = event_details.size();
|
||||||
|
|
||||||
|
auto qs_pack = new ServerPacket(
|
||||||
|
ServerOP_QSPlayerDropItem,
|
||||||
|
sizeof(QSPlayerDropItem_Struct) +
|
||||||
|
(sizeof(QSDropItems_Struct) * qs_audit._detail_count));
|
||||||
|
QSPlayerDropItem_Struct* qs_buf = (QSPlayerDropItem_Struct*) qs_pack->pBuffer;
|
||||||
|
|
||||||
|
memcpy(qs_buf, &qs_audit, sizeof(QSPlayerDropItem_Struct));
|
||||||
|
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
for (auto iter = event_details.begin(); iter != event_details.end(); ++iter, ++offset) {
|
||||||
|
QSDropItems_Struct* detail = reinterpret_cast<QSDropItems_Struct*>(*iter);
|
||||||
|
qs_buf->items[offset] = *detail;
|
||||||
|
safe_delete(detail);
|
||||||
|
}
|
||||||
|
|
||||||
|
event_details.clear();
|
||||||
|
|
||||||
|
if (worldserver.Connected())
|
||||||
|
worldserver.SendPacket(qs_pack);
|
||||||
|
|
||||||
|
safe_delete(qs_pack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Drop inst
|
// Drop inst
|
||||||
void Client::DropInst(const EQEmu::ItemInstance* inst)
|
void Client::DropInst(const EQEmu::ItemInstance* inst)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -32,12 +32,12 @@ int Lua_Raid::RaidCount() {
|
|||||||
return self->RaidCount();
|
return self->RaidCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 Lua_Raid::GetGroup(const char *c) {
|
int Lua_Raid::GetGroup(const char *c) {
|
||||||
Lua_Safe_Call_Int();
|
Lua_Safe_Call_Int();
|
||||||
return self->GetGroup(c);
|
return self->GetGroup(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 Lua_Raid::GetGroup(Lua_Client c) {
|
int Lua_Raid::GetGroup(Lua_Client c) {
|
||||||
Lua_Safe_Call_Int();
|
Lua_Safe_Call_Int();
|
||||||
return self->GetGroup(c);
|
return self->GetGroup(c);
|
||||||
}
|
}
|
||||||
@ -122,6 +122,16 @@ Lua_Client Lua_Raid::GetMember(int index) {
|
|||||||
return self->members[index].member;
|
return self->members[index].member;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Lua_Raid::GetGroupNumber(int index) {
|
||||||
|
Lua_Safe_Call_Int();
|
||||||
|
|
||||||
|
if(index >= 72 || index < 0 || self->members[index].GroupNumber == RAID_GROUPLESS) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self->members[index].GroupNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
luabind::scope lua_register_raid() {
|
luabind::scope lua_register_raid() {
|
||||||
return luabind::class_<Lua_Raid>("Raid")
|
return luabind::class_<Lua_Raid>("Raid")
|
||||||
@ -132,7 +142,8 @@ luabind::scope lua_register_raid() {
|
|||||||
.def("CastGroupSpell", (void(Lua_Raid::*)(Lua_Mob,int,uint32))&Lua_Raid::CastGroupSpell)
|
.def("CastGroupSpell", (void(Lua_Raid::*)(Lua_Mob,int,uint32))&Lua_Raid::CastGroupSpell)
|
||||||
.def("GroupCount", (int(Lua_Raid::*)(uint32))&Lua_Raid::GroupCount)
|
.def("GroupCount", (int(Lua_Raid::*)(uint32))&Lua_Raid::GroupCount)
|
||||||
.def("RaidCount", (int(Lua_Raid::*)(void))&Lua_Raid::RaidCount)
|
.def("RaidCount", (int(Lua_Raid::*)(void))&Lua_Raid::RaidCount)
|
||||||
.def("GetGroup", (uint32(Lua_Raid::*)(const char*))&Lua_Raid::GetGroup)
|
.def("GetGroup", (int(Lua_Raid::*)(const char*))&Lua_Raid::GetGroup)
|
||||||
|
.def("GetGroup", (int(Lua_Raid::*)(Lua_Client))&Lua_Raid::GetGroup)
|
||||||
.def("SplitExp", (void(Lua_Raid::*)(uint32,Lua_Mob))&Lua_Raid::SplitExp)
|
.def("SplitExp", (void(Lua_Raid::*)(uint32,Lua_Mob))&Lua_Raid::SplitExp)
|
||||||
.def("GetTotalRaidDamage", (uint32(Lua_Raid::*)(Lua_Mob))&Lua_Raid::GetTotalRaidDamage)
|
.def("GetTotalRaidDamage", (uint32(Lua_Raid::*)(Lua_Mob))&Lua_Raid::GetTotalRaidDamage)
|
||||||
.def("SplitMoney", (void(Lua_Raid::*)(uint32,uint32,uint32,uint32))&Lua_Raid::SplitMoney)
|
.def("SplitMoney", (void(Lua_Raid::*)(uint32,uint32,uint32,uint32))&Lua_Raid::SplitMoney)
|
||||||
@ -146,7 +157,8 @@ luabind::scope lua_register_raid() {
|
|||||||
.def("TeleportGroup", (int(Lua_Raid::*)(Lua_Mob,uint32,uint32,float,float,float,float,uint32))&Lua_Raid::TeleportGroup)
|
.def("TeleportGroup", (int(Lua_Raid::*)(Lua_Mob,uint32,uint32,float,float,float,float,uint32))&Lua_Raid::TeleportGroup)
|
||||||
.def("TeleportRaid", (int(Lua_Raid::*)(Lua_Mob,uint32,uint32,float,float,float,float))&Lua_Raid::TeleportRaid)
|
.def("TeleportRaid", (int(Lua_Raid::*)(Lua_Mob,uint32,uint32,float,float,float,float))&Lua_Raid::TeleportRaid)
|
||||||
.def("GetID", (int(Lua_Raid::*)(void))&Lua_Raid::GetID)
|
.def("GetID", (int(Lua_Raid::*)(void))&Lua_Raid::GetID)
|
||||||
.def("GetMember", (Lua_Client(Lua_Raid::*)(int))&Lua_Raid::GetMember);
|
.def("GetMember", (Lua_Client(Lua_Raid::*)(int))&Lua_Raid::GetMember)
|
||||||
|
.def("GetGroupNumber", (int(Lua_Raid::*)(int))&Lua_Raid::GetGroupNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -30,8 +30,8 @@ public:
|
|||||||
void CastGroupSpell(Lua_Mob caster, int spell_id, uint32 group_id);
|
void CastGroupSpell(Lua_Mob caster, int spell_id, uint32 group_id);
|
||||||
int GroupCount(uint32 group_id);
|
int GroupCount(uint32 group_id);
|
||||||
int RaidCount();
|
int RaidCount();
|
||||||
uint32 GetGroup(const char *c);
|
int GetGroup(const char *c);
|
||||||
uint32 GetGroup(Lua_Client c);
|
int GetGroup(Lua_Client c);
|
||||||
void SplitExp(uint32 exp, Lua_Mob other);
|
void SplitExp(uint32 exp, Lua_Mob other);
|
||||||
uint32 GetTotalRaidDamage(Lua_Mob other);
|
uint32 GetTotalRaidDamage(Lua_Mob other);
|
||||||
void SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum);
|
void SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum);
|
||||||
@ -47,6 +47,7 @@ public:
|
|||||||
void TeleportRaid(Lua_Mob sender, uint32 zone_id, uint32 instance_id, float x, float y, float z, float h);
|
void TeleportRaid(Lua_Mob sender, uint32 zone_id, uint32 instance_id, float x, float y, float z, float h);
|
||||||
int GetID();
|
int GetID();
|
||||||
Lua_Client GetMember(int index);
|
Lua_Client GetMember(int index);
|
||||||
|
int GetGroupNumber(int index);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -1168,11 +1168,11 @@ void Merc::CalcRestState() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RestRegenHP = 6 * (GetMaxHP() / RuleI(Character, RestRegenHP));
|
RestRegenHP = 6 * (GetMaxHP() / zone->newzone_data.FastRegenHP);
|
||||||
|
|
||||||
RestRegenMana = 6 * (GetMaxMana() / RuleI(Character, RestRegenMana));
|
RestRegenMana = 6 * (GetMaxMana() / zone->newzone_data.FastRegenMana);
|
||||||
|
|
||||||
RestRegenEndurance = 6 * (GetMaxEndurance() / RuleI(Character, RestRegenEnd));
|
RestRegenEndurance = 6 * (GetMaxEndurance() / zone->newzone_data.FastRegenEndurance);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Merc::HasSkill(EQEmu::skills::SkillType skill_id) const {
|
bool Merc::HasSkill(EQEmu::skills::SkillType skill_id) const {
|
||||||
@ -1408,7 +1408,7 @@ void Merc::AI_Process() {
|
|||||||
if(DivineAura())
|
if(DivineAura())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int hateCount = entity_list.GetHatedCount(this, nullptr);
|
int hateCount = entity_list.GetHatedCount(this, nullptr, false);
|
||||||
if(GetHatedCount() < hateCount) {
|
if(GetHatedCount() < hateCount) {
|
||||||
SetHatedCount(hateCount);
|
SetHatedCount(hateCount);
|
||||||
|
|
||||||
@ -1475,8 +1475,14 @@ void Merc::AI_Process() {
|
|||||||
if (RuleB(Mercs, MercsUsePathing) && zone->pathing) {
|
if (RuleB(Mercs, MercsUsePathing) && zone->pathing) {
|
||||||
bool WaypointChanged, NodeReached;
|
bool WaypointChanged, NodeReached;
|
||||||
|
|
||||||
glm::vec3 Goal = UpdatePath(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(),
|
glm::vec3 Goal = UpdatePath(
|
||||||
GetRunspeed(), WaypointChanged, NodeReached);
|
GetTarget()->GetX(),
|
||||||
|
GetTarget()->GetY(),
|
||||||
|
GetTarget()->GetZ(),
|
||||||
|
GetRunspeed(),
|
||||||
|
WaypointChanged,
|
||||||
|
NodeReached
|
||||||
|
);
|
||||||
|
|
||||||
if (WaypointChanged)
|
if (WaypointChanged)
|
||||||
tar_ndx = 20;
|
tar_ndx = 20;
|
||||||
|
|||||||
17
zone/mob.h
17
zone/mob.h
@ -981,15 +981,15 @@ public:
|
|||||||
|
|
||||||
inline bool CheckAggro(Mob* other) {return hate_list.IsEntOnHateList(other);}
|
inline bool CheckAggro(Mob* other) {return hate_list.IsEntOnHateList(other);}
|
||||||
float CalculateHeadingToTarget(float in_x, float in_y) { return HeadingAngleToMob(in_x, in_y); }
|
float CalculateHeadingToTarget(float in_x, float in_y) { return HeadingAngleToMob(in_x, in_y); }
|
||||||
virtual bool CalculateNewPosition(float x, float y, float z, int speed, bool checkZ = true, bool calcheading = true);
|
virtual bool CalculateNewPosition(float x, float y, float z, float speed, bool check_z = true, bool calculate_heading = true);
|
||||||
float CalculateDistance(float x, float y, float z);
|
float CalculateDistance(float x, float y, float z);
|
||||||
float GetGroundZ(float new_x, float new_y, float z_offset=0.0);
|
float GetGroundZ(float new_x, float new_y, float z_offset=0.0);
|
||||||
void SendTo(float new_x, float new_y, float new_z);
|
void SendTo(float new_x, float new_y, float new_z);
|
||||||
void SendToFixZ(float new_x, float new_y, float new_z);
|
void SendToFixZ(float new_x, float new_y, float new_z);
|
||||||
float GetZOffset() const;
|
float GetZOffset() const;
|
||||||
float GetDefaultRaceSize() const;
|
float GetDefaultRaceSize() const;
|
||||||
void FixZ(int32 z_find_offset = 5);
|
void FixZ(int32 z_find_offset = 5, bool fix_client_z = false);
|
||||||
float GetFixedZ(glm::vec3 position, int32 z_find_offset = 5);
|
float GetFixedZ(glm::vec3 destination, int32 z_find_offset = 5);
|
||||||
|
|
||||||
void NPCSpecialAttacks(const char* parse, int permtag, bool reset = true, bool remove = false);
|
void NPCSpecialAttacks(const char* parse, int permtag, bool reset = true, bool remove = false);
|
||||||
inline uint32 DontHealMeBefore() const { return pDontHealMeBefore; }
|
inline uint32 DontHealMeBefore() const { return pDontHealMeBefore; }
|
||||||
@ -1165,7 +1165,7 @@ protected:
|
|||||||
int _GetWalkSpeed() const;
|
int _GetWalkSpeed() const;
|
||||||
int _GetRunSpeed() const;
|
int _GetRunSpeed() const;
|
||||||
int _GetFearSpeed() const;
|
int _GetFearSpeed() const;
|
||||||
virtual bool MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, bool checkZ = true, bool calcHeading = true);
|
virtual bool MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, bool check_z = true, bool calculate_heading = true);
|
||||||
|
|
||||||
virtual bool AI_EngagedCastCheck() { return(false); }
|
virtual bool AI_EngagedCastCheck() { return(false); }
|
||||||
virtual bool AI_PursueCastCheck() { return(false); }
|
virtual bool AI_PursueCastCheck() { return(false); }
|
||||||
@ -1414,6 +1414,13 @@ protected:
|
|||||||
bool pseudo_rooted;
|
bool pseudo_rooted;
|
||||||
bool endur_upkeep;
|
bool endur_upkeep;
|
||||||
bool degenerating_effects; // true if we have a buff that needs to be recalced every tick
|
bool degenerating_effects; // true if we have a buff that needs to be recalced every tick
|
||||||
|
bool spawned_in_water;
|
||||||
|
public:
|
||||||
|
bool GetWasSpawnedInWater() const;
|
||||||
|
|
||||||
|
void SetSpawnedInWater(bool spawned_in_water);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
// Bind wound
|
// Bind wound
|
||||||
Timer bindwound_timer;
|
Timer bindwound_timer;
|
||||||
@ -1443,7 +1450,7 @@ protected:
|
|||||||
std::unique_ptr<Timer> AI_feign_remember_timer;
|
std::unique_ptr<Timer> AI_feign_remember_timer;
|
||||||
std::unique_ptr<Timer> AI_check_signal_timer;
|
std::unique_ptr<Timer> AI_check_signal_timer;
|
||||||
std::unique_ptr<Timer> AI_scan_door_open_timer;
|
std::unique_ptr<Timer> AI_scan_door_open_timer;
|
||||||
uint32 pLastFightingDelayMoving;
|
uint32 time_until_can_move;
|
||||||
HateList hate_list;
|
HateList hate_list;
|
||||||
std::set<uint32> feign_memory_list;
|
std::set<uint32> feign_memory_list;
|
||||||
// This is to keep track of mobs we cast faction mod spells on
|
// This is to keep track of mobs we cast faction mod spells on
|
||||||
|
|||||||
576
zone/mob_ai.cpp
576
zone/mob_ai.cpp
@ -30,6 +30,7 @@
|
|||||||
#include "string_ids.h"
|
#include "string_ids.h"
|
||||||
#include "water_map.h"
|
#include "water_map.h"
|
||||||
#include "fastmath.h"
|
#include "fastmath.h"
|
||||||
|
#include "../common/data_verification.h"
|
||||||
|
|
||||||
#include <glm/gtx/projection.hpp>
|
#include <glm/gtx/projection.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -199,12 +200,16 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes, bool bInnates
|
|||||||
case SpellType_Escape: {
|
case SpellType_Escape: {
|
||||||
// If min_hp !=0 then the spell list has specified
|
// If min_hp !=0 then the spell list has specified
|
||||||
// custom range and we're inside that range if we
|
// custom range and we're inside that range if we
|
||||||
// made it here. The hard coded <=5 is for unspecified.
|
// made it here.
|
||||||
if (AIspells[i].min_hp != 0 || GetHPRatio() <= 5)
|
if (AIspells[i].min_hp != 0 || GetHPRatio() <= (RuleI(NPC, NPCGatePercent))) {
|
||||||
{
|
auto npcSpawnPoint = CastToNPC()->GetSpawnPoint();
|
||||||
|
if (!RuleB(NPC, NPCGateNearBind) && DistanceNoZ(m_Position, npcSpawnPoint) < RuleI(NPC, NPCGateDistanceBind)) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
AIDoSpellCast(i, tar, mana_cost);
|
AIDoSpellCast(i, tar, mana_cost);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SpellType_Slow:
|
case SpellType_Slow:
|
||||||
@ -459,8 +464,9 @@ void NPC::AI_Init()
|
|||||||
roambox_min_x = 0;
|
roambox_min_x = 0;
|
||||||
roambox_min_y = 0;
|
roambox_min_y = 0;
|
||||||
roambox_distance = 0;
|
roambox_distance = 0;
|
||||||
roambox_movingto_x = 0;
|
roambox_destination_x = 0;
|
||||||
roambox_movingto_y = 0;
|
roambox_destination_y = 0;
|
||||||
|
roambox_destination_z = 0;
|
||||||
roambox_min_delay = 2500;
|
roambox_min_delay = 2500;
|
||||||
roambox_delay = 2500;
|
roambox_delay = 2500;
|
||||||
}
|
}
|
||||||
@ -476,9 +482,9 @@ void Mob::AI_Start(uint32 iMoveDelay) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (iMoveDelay)
|
if (iMoveDelay)
|
||||||
pLastFightingDelayMoving = Timer::GetCurrentTime() + iMoveDelay;
|
time_until_can_move = Timer::GetCurrentTime() + iMoveDelay;
|
||||||
else
|
else
|
||||||
pLastFightingDelayMoving = 0;
|
time_until_can_move = 0;
|
||||||
|
|
||||||
pAIControlled = true;
|
pAIControlled = true;
|
||||||
AI_think_timer = std::unique_ptr<Timer>(new Timer(AIthink_duration));
|
AI_think_timer = std::unique_ptr<Timer>(new Timer(AIthink_duration));
|
||||||
@ -777,20 +783,20 @@ void Client::AI_Process()
|
|||||||
if (RuleB(Combat, EnableFearPathing)) {
|
if (RuleB(Combat, EnableFearPathing)) {
|
||||||
if (currently_fleeing) {
|
if (currently_fleeing) {
|
||||||
|
|
||||||
if (fix_z_timer_engaged.Check())
|
if (fix_z_timer.Check())
|
||||||
this->FixZ();
|
this->FixZ(5, true);
|
||||||
|
|
||||||
if (IsRooted()) {
|
if (IsRooted()) {
|
||||||
//make sure everybody knows were not moving, for appearance sake
|
//make sure everybody knows were not moving, for appearance sake
|
||||||
if(IsMoving())
|
if (IsMoving()) {
|
||||||
{
|
|
||||||
if (GetTarget())
|
if (GetTarget())
|
||||||
SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()));
|
SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()));
|
||||||
SetCurrentSpeed(0);
|
SetCurrentSpeed(0);
|
||||||
}
|
}
|
||||||
//continue on to attack code, ensuring that we execute the engaged code
|
//continue on to attack code, ensuring that we execute the engaged code
|
||||||
engaged = true;
|
engaged = true;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
if (AI_movement_timer->Check()) {
|
if (AI_movement_timer->Check()) {
|
||||||
int speed = GetFearSpeed();
|
int speed = GetFearSpeed();
|
||||||
animation = speed;
|
animation = speed;
|
||||||
@ -802,16 +808,22 @@ void Client::AI_Process()
|
|||||||
// Calculate a new point to run to
|
// Calculate a new point to run to
|
||||||
CalculateNewFearpoint();
|
CalculateNewFearpoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!RuleB(Pathing, Fear) || !zone->pathing)
|
if (!RuleB(Pathing, Fear) || !zone->pathing)
|
||||||
CalculateNewPosition(m_FearWalkTarget.x, m_FearWalkTarget.y, m_FearWalkTarget.z, speed, true);
|
CalculateNewPosition(m_FearWalkTarget.x, m_FearWalkTarget.y, m_FearWalkTarget.z, speed, true);
|
||||||
else
|
else {
|
||||||
{
|
bool waypoint_changed, node_reached;
|
||||||
bool WaypointChanged, NodeReached;
|
|
||||||
|
|
||||||
glm::vec3 Goal = UpdatePath(m_FearWalkTarget.x, m_FearWalkTarget.y, m_FearWalkTarget.z,
|
glm::vec3 Goal = UpdatePath(
|
||||||
speed, WaypointChanged, NodeReached);
|
m_FearWalkTarget.x,
|
||||||
|
m_FearWalkTarget.y,
|
||||||
|
m_FearWalkTarget.z,
|
||||||
|
speed,
|
||||||
|
waypoint_changed,
|
||||||
|
node_reached
|
||||||
|
);
|
||||||
|
|
||||||
if(WaypointChanged)
|
if (waypoint_changed)
|
||||||
tar_ndx = 20;
|
tar_ndx = 20;
|
||||||
|
|
||||||
CalculateNewPosition(Goal.x, Goal.y, Goal.z, speed);
|
CalculateNewPosition(Goal.x, Goal.y, Goal.z, speed);
|
||||||
@ -1098,10 +1110,10 @@ void Mob::AI_Process() {
|
|||||||
//
|
//
|
||||||
if (RuleB(Combat, EnableFearPathing)) {
|
if (RuleB(Combat, EnableFearPathing)) {
|
||||||
if (currently_fleeing) {
|
if (currently_fleeing) {
|
||||||
if((IsRooted() || (IsBlind() && CombatRange(hate_list.GetClosestEntOnHateList(this)))) && !IsPetStop() && !IsPetRegroup()) {
|
if ((IsRooted() || (IsBlind() && CombatRange(hate_list.GetClosestEntOnHateList(this)))) && !IsPetStop() &&
|
||||||
|
!IsPetRegroup()) {
|
||||||
//make sure everybody knows were not moving, for appearance sake
|
//make sure everybody knows were not moving, for appearance sake
|
||||||
if(IsMoving())
|
if (IsMoving()) {
|
||||||
{
|
|
||||||
if (target)
|
if (target)
|
||||||
SetHeading(CalculateHeadingToTarget(target->GetX(), target->GetY()));
|
SetHeading(CalculateHeadingToTarget(target->GetX(), target->GetY()));
|
||||||
SetCurrentSpeed(0);
|
SetCurrentSpeed(0);
|
||||||
@ -1109,7 +1121,8 @@ void Mob::AI_Process() {
|
|||||||
}
|
}
|
||||||
//continue on to attack code, ensuring that we execute the engaged code
|
//continue on to attack code, ensuring that we execute the engaged code
|
||||||
engaged = true;
|
engaged = true;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
if (AI_movement_timer->Check()) {
|
if (AI_movement_timer->Check()) {
|
||||||
// Check if we have reached the last fear point
|
// Check if we have reached the last fear point
|
||||||
if ((std::abs(GetX() - m_FearWalkTarget.x) < 0.1) &&
|
if ((std::abs(GetX() - m_FearWalkTarget.x) < 0.1) &&
|
||||||
@ -1117,16 +1130,26 @@ void Mob::AI_Process() {
|
|||||||
// Calculate a new point to run to
|
// Calculate a new point to run to
|
||||||
CalculateNewFearpoint();
|
CalculateNewFearpoint();
|
||||||
}
|
}
|
||||||
if(!RuleB(Pathing, Fear) || !zone->pathing)
|
if (!RuleB(Pathing, Fear) || !zone->pathing) {
|
||||||
{
|
CalculateNewPosition(
|
||||||
CalculateNewPosition(m_FearWalkTarget.x, m_FearWalkTarget.y, m_FearWalkTarget.z, GetFearSpeed(), true);
|
m_FearWalkTarget.x,
|
||||||
|
m_FearWalkTarget.y,
|
||||||
|
m_FearWalkTarget.z,
|
||||||
|
GetFearSpeed(),
|
||||||
|
true
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
bool WaypointChanged, NodeReached;
|
bool WaypointChanged, NodeReached;
|
||||||
|
|
||||||
glm::vec3 Goal = UpdatePath(m_FearWalkTarget.x, m_FearWalkTarget.y, m_FearWalkTarget.z,
|
glm::vec3 Goal = UpdatePath(
|
||||||
GetFearSpeed(), WaypointChanged, NodeReached);
|
m_FearWalkTarget.x,
|
||||||
|
m_FearWalkTarget.y,
|
||||||
|
m_FearWalkTarget.z,
|
||||||
|
GetFearSpeed(),
|
||||||
|
WaypointChanged,
|
||||||
|
NodeReached
|
||||||
|
);
|
||||||
|
|
||||||
if (WaypointChanged)
|
if (WaypointChanged)
|
||||||
tar_ndx = 20;
|
tar_ndx = 20;
|
||||||
@ -1171,7 +1194,7 @@ void Mob::AI_Process() {
|
|||||||
// NPCs will forget people after 10 mins of not interacting with them or out of range
|
// NPCs will forget people after 10 mins of not interacting with them or out of range
|
||||||
// both of these maybe zone specific, hardcoded for now
|
// both of these maybe zone specific, hardcoded for now
|
||||||
if (hate_list_cleanup_timer.Check()) {
|
if (hate_list_cleanup_timer.Check()) {
|
||||||
hate_list.RemoveStaleEntries(600000, 600.0f);
|
hate_list.RemoveStaleEntries(600000, static_cast<float>(zone->newzone_data.NPCAggroMaxDist));
|
||||||
if (hate_list.IsHateListEmpty()) {
|
if (hate_list.IsHateListEmpty()) {
|
||||||
AI_Event_NoLongerEngaged();
|
AI_Event_NoLongerEngaged();
|
||||||
zone->DelAggroMob();
|
zone->DelAggroMob();
|
||||||
@ -1183,10 +1206,8 @@ void Mob::AI_Process() {
|
|||||||
// from above, so no extra blind checks needed
|
// from above, so no extra blind checks needed
|
||||||
if ((IsRooted() && !GetSpecialAbility(IGNORE_ROOT_AGGRO_RULES)) || IsBlind())
|
if ((IsRooted() && !GetSpecialAbility(IGNORE_ROOT_AGGRO_RULES)) || IsBlind())
|
||||||
SetTarget(hate_list.GetClosestEntOnHateList(this));
|
SetTarget(hate_list.GetClosestEntOnHateList(this));
|
||||||
else
|
else {
|
||||||
{
|
if (AI_target_check_timer->Check()) {
|
||||||
if (AI_target_check_timer->Check())
|
|
||||||
{
|
|
||||||
if (IsFocused()) {
|
if (IsFocused()) {
|
||||||
if (!target) {
|
if (!target) {
|
||||||
SetTarget(hate_list.GetEntWithMostHateOnList(this));
|
SetTarget(hate_list.GetEntWithMostHateOnList(this));
|
||||||
@ -1248,21 +1269,16 @@ void Mob::AI_Process() {
|
|||||||
|
|
||||||
bool is_combat_range = CombatRange(target);
|
bool is_combat_range = CombatRange(target);
|
||||||
|
|
||||||
if (is_combat_range)
|
if (is_combat_range) {
|
||||||
{
|
if (AI_movement_timer->Check()) {
|
||||||
if (AI_movement_timer->Check())
|
if (CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()) != m_Position.w) {
|
||||||
{
|
|
||||||
if (CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()) != m_Position.w)
|
|
||||||
{
|
|
||||||
SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()));
|
SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()));
|
||||||
SendPosition();
|
SendPosition();
|
||||||
}
|
}
|
||||||
SetCurrentSpeed(0);
|
SetCurrentSpeed(0);
|
||||||
}
|
}
|
||||||
if (IsMoving())
|
if (IsMoving()) {
|
||||||
{
|
if (CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()) != m_Position.w) {
|
||||||
if (CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()) != m_Position.w)
|
|
||||||
{
|
|
||||||
SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()));
|
SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()));
|
||||||
SendPosition();
|
SendPosition();
|
||||||
}
|
}
|
||||||
@ -1330,16 +1346,17 @@ void Mob::AI_Process() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((IsPet() || IsTempPet()) && IsPetOwnerClient()) {
|
if ((IsPet() || IsTempPet()) && IsPetOwnerClient()) {
|
||||||
if (spellbonuses.PC_Pet_Rampage[0] || itembonuses.PC_Pet_Rampage[0] || aabonuses.PC_Pet_Rampage[0]) {
|
if (spellbonuses.PC_Pet_Rampage[0] || itembonuses.PC_Pet_Rampage[0] ||
|
||||||
int chance = spellbonuses.PC_Pet_Rampage[0] + itembonuses.PC_Pet_Rampage[0] + aabonuses.PC_Pet_Rampage[0];
|
aabonuses.PC_Pet_Rampage[0]) {
|
||||||
|
int chance = spellbonuses.PC_Pet_Rampage[0] + itembonuses.PC_Pet_Rampage[0] +
|
||||||
|
aabonuses.PC_Pet_Rampage[0];
|
||||||
if (zone->random.Roll(chance)) {
|
if (zone->random.Roll(chance)) {
|
||||||
Rampage(nullptr);
|
Rampage(nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetSpecialAbility(SPECATK_RAMPAGE) && !specialed)
|
if (GetSpecialAbility(SPECATK_RAMPAGE) && !specialed) {
|
||||||
{
|
|
||||||
int rampage_chance = GetSpecialAbilityParam(SPECATK_RAMPAGE, 0);
|
int rampage_chance = GetSpecialAbilityParam(SPECATK_RAMPAGE, 0);
|
||||||
rampage_chance = rampage_chance > 0 ? rampage_chance : 20;
|
rampage_chance = rampage_chance > 0 ? rampage_chance : 20;
|
||||||
if (zone->random.Roll(rampage_chance)) {
|
if (zone->random.Roll(rampage_chance)) {
|
||||||
@ -1373,8 +1390,7 @@ void Mob::AI_Process() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetSpecialAbility(SPECATK_AREA_RAMPAGE) && !specialed)
|
if (GetSpecialAbility(SPECATK_AREA_RAMPAGE) && !specialed) {
|
||||||
{
|
|
||||||
int rampage_chance = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 0);
|
int rampage_chance = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 0);
|
||||||
rampage_chance = rampage_chance > 0 ? rampage_chance : 20;
|
rampage_chance = rampage_chance > 0 ? rampage_chance : 20;
|
||||||
if (zone->random.Roll(rampage_chance)) {
|
if (zone->random.Roll(rampage_chance)) {
|
||||||
@ -1434,7 +1450,7 @@ void Mob::AI_Process() {
|
|||||||
Heal();
|
Heal();
|
||||||
BuffFadeAll();
|
BuffFadeAll();
|
||||||
AI_walking_timer->Start(100);
|
AI_walking_timer->Start(100);
|
||||||
pLastFightingDelayMoving = Timer::GetCurrentTime();
|
time_until_can_move = Timer::GetCurrentTime();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (tar != nullptr) {
|
else if (tar != nullptr) {
|
||||||
@ -1445,8 +1461,7 @@ void Mob::AI_Process() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// See if we can summon the mob to us
|
// See if we can summon the mob to us
|
||||||
if (!HateSummon())
|
if (!HateSummon()) {
|
||||||
{
|
|
||||||
//could not summon them, check ranged...
|
//could not summon them, check ranged...
|
||||||
if (GetSpecialAbility(SPECATK_RANGED_ATK))
|
if (GetSpecialAbility(SPECATK_RANGED_ATK))
|
||||||
doranged = true;
|
doranged = true;
|
||||||
@ -1456,18 +1471,18 @@ void Mob::AI_Process() {
|
|||||||
if (AI_PursueCastCheck()) {
|
if (AI_PursueCastCheck()) {
|
||||||
//we did something, so do not process movement.
|
//we did something, so do not process movement.
|
||||||
}
|
}
|
||||||
else if (AI_movement_timer->Check() && target)
|
else if (AI_movement_timer->Check() && target) {
|
||||||
{
|
|
||||||
if (!IsRooted()) {
|
if (!IsRooted()) {
|
||||||
Log(Logs::Detail, Logs::AI, "Pursuing %s while engaged.", target->GetName());
|
Log(Logs::Detail, Logs::AI, "Pursuing %s while engaged.", target->GetName());
|
||||||
if (!RuleB(Pathing, Aggro) || !zone->pathing)
|
if (!RuleB(Pathing, Aggro) || !zone->pathing)
|
||||||
CalculateNewPosition(target->GetX(), target->GetY(), target->GetZ(), GetRunspeed());
|
CalculateNewPosition(target->GetX(), target->GetY(), target->GetZ(), GetRunspeed());
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
bool WaypointChanged, NodeReached;
|
bool WaypointChanged, NodeReached;
|
||||||
|
|
||||||
glm::vec3 Goal = UpdatePath(target->GetX(), target->GetY(), target->GetZ(),
|
glm::vec3 Goal = UpdatePath(
|
||||||
GetRunspeed(), WaypointChanged, NodeReached);
|
target->GetX(), target->GetY(), target->GetZ(),
|
||||||
|
GetRunspeed(), WaypointChanged, NodeReached
|
||||||
|
);
|
||||||
|
|
||||||
if (WaypointChanged)
|
if (WaypointChanged)
|
||||||
tar_ndx = 20;
|
tar_ndx = 20;
|
||||||
@ -1503,106 +1518,102 @@ void Mob::AI_Process() {
|
|||||||
if (remember_client == nullptr) {
|
if (remember_client == nullptr) {
|
||||||
//they are gone now...
|
//they are gone now...
|
||||||
RememberedCharID = feign_memory_list.erase(RememberedCharID);
|
RememberedCharID = feign_memory_list.erase(RememberedCharID);
|
||||||
} else if (!remember_client->GetFeigned()) {
|
}
|
||||||
|
else if (!remember_client->GetFeigned()) {
|
||||||
AddToHateList(remember_client->CastToMob(), 1);
|
AddToHateList(remember_client->CastToMob(), 1);
|
||||||
RememberedCharID = feign_memory_list.erase(RememberedCharID);
|
RememberedCharID = feign_memory_list.erase(RememberedCharID);
|
||||||
break;
|
break;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
//they are still feigned, carry on...
|
//they are still feigned, carry on...
|
||||||
++RememberedCharID;
|
++RememberedCharID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (AI_IdleCastCheck())
|
if (AI_IdleCastCheck()) {
|
||||||
{
|
|
||||||
//we processed a spell action, so do nothing else.
|
//we processed a spell action, so do nothing else.
|
||||||
}
|
}
|
||||||
else if (zone->CanDoCombat() && CastToNPC()->WillAggroNPCs() && AI_scan_area_timer->Check())
|
else if (zone->CanDoCombat() && CastToNPC()->WillAggroNPCs() && AI_scan_area_timer->Check()) {
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
* NPC to NPC aggro checking, npc needs npc_aggro flag
|
* NPC to NPC aggro checking, npc needs npc_aggro flag
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Mob *temp_target = entity_list.AICheckNPCtoNPCAggro(this, GetAggroRange(), GetAssistRange());
|
Mob *temp_target = entity_list.AICheckNPCtoNPCAggro(this, GetAggroRange(), GetAssistRange());
|
||||||
if (temp_target) {
|
if (temp_target) {
|
||||||
AddToHateList(temp_target);
|
AddToHateList(temp_target);
|
||||||
}
|
}
|
||||||
|
|
||||||
AI_scan_area_timer->Disable();
|
AI_scan_area_timer->Disable();
|
||||||
AI_scan_area_timer->Start(RandomTimer(RuleI(NPC, NPCToNPCAggroTimerMin), RuleI(NPC, NPCToNPCAggroTimerMax)), false);
|
AI_scan_area_timer->Start(
|
||||||
|
RandomTimer(RuleI(NPC, NPCToNPCAggroTimerMin), RuleI(NPC, NPCToNPCAggroTimerMax)),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (AI_movement_timer->Check() && !IsRooted())
|
else if (AI_movement_timer->Check() && !IsRooted()) {
|
||||||
{
|
if (IsPet()) {
|
||||||
if (IsPet())
|
|
||||||
{
|
|
||||||
// we're a pet, do as we're told
|
// we're a pet, do as we're told
|
||||||
switch (pStandingPetOrder)
|
switch (pStandingPetOrder) {
|
||||||
{
|
case SPO_Follow: {
|
||||||
case SPO_Follow:
|
|
||||||
{
|
|
||||||
|
|
||||||
Mob *owner = GetOwner();
|
Mob *owner = GetOwner();
|
||||||
if(owner == nullptr)
|
if (owner == nullptr) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
//if(owner->IsClient())
|
glm::vec4 pet_owner_position = owner->GetPosition();
|
||||||
// printf("Pet start pos: (%f, %f, %f)\n", GetX(), GetY(), GetZ());
|
float distance_to_owner = DistanceSquared(m_Position, pet_owner_position);
|
||||||
|
float z_distance = pet_owner_position.z - m_Position.z;
|
||||||
|
|
||||||
glm::vec4 ownerPos = owner->GetPosition();
|
if (distance_to_owner >= 400 || z_distance > 100) {
|
||||||
float dist = DistanceSquared(m_Position, ownerPos);
|
|
||||||
float distz = ownerPos.z - m_Position.z;
|
|
||||||
|
|
||||||
if (dist >= 400 || distz > 100)
|
int pet_speed = GetWalkspeed();
|
||||||
{
|
|
||||||
int speed = GetWalkspeed();
|
|
||||||
if (dist >= 1225) // 35
|
|
||||||
speed = GetRunspeed();
|
|
||||||
|
|
||||||
if (dist >= 202500 || distz > 100) // dist >= 450
|
/**
|
||||||
{
|
* Distance: >= 35 (Run if far away)
|
||||||
m_Position = ownerPos;
|
*/
|
||||||
|
if (distance_to_owner >= 1225) {
|
||||||
|
pet_speed = GetRunspeed();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Distance: >= 450 (Snap to owner)
|
||||||
|
*/
|
||||||
|
if (distance_to_owner >= 202500 || z_distance > 100) {
|
||||||
|
m_Position = pet_owner_position;
|
||||||
SendPositionUpdate();
|
SendPositionUpdate();
|
||||||
moved = true;
|
moved = true;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
CalculateNewPosition(owner->GetX(), owner->GetY(), owner->GetZ(), speed);
|
bool waypoint_changed, node_reached;
|
||||||
|
glm::vec3 Goal = UpdatePath(
|
||||||
|
owner->GetX(),
|
||||||
|
owner->GetY(),
|
||||||
|
owner->GetZ(),
|
||||||
|
pet_speed,
|
||||||
|
waypoint_changed,
|
||||||
|
node_reached
|
||||||
|
);
|
||||||
|
|
||||||
|
CalculateNewPosition(Goal.x, Goal.y, Goal.z, pet_speed, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
if (moved) {
|
||||||
if(moved)
|
|
||||||
{
|
|
||||||
this->FixZ();
|
this->FixZ();
|
||||||
SetCurrentSpeed(0);
|
SetCurrentSpeed(0);
|
||||||
moved = false;
|
moved = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
//fix up Z
|
|
||||||
float zdiff = GetZ() - owner->GetZ();
|
|
||||||
if(zdiff < 0)
|
|
||||||
zdiff = 0 - zdiff;
|
|
||||||
if(zdiff > 2.0f) {
|
|
||||||
SendTo(GetX(), GetY(), owner->GetZ());
|
|
||||||
SendPosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(owner->IsClient())
|
|
||||||
printf("Pet pos: (%f, %f, %f)\n", GetX(), GetY(), GetZ());
|
|
||||||
*/
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPO_Sit:
|
case SPO_Sit: {
|
||||||
{
|
|
||||||
SetAppearance(eaSitting, false);
|
SetAppearance(eaSitting, false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPO_Guard:
|
case SPO_Guard: {
|
||||||
{
|
|
||||||
//only NPCs can guard stuff. (forced by where the guard movement code is in the AI)
|
//only NPCs can guard stuff. (forced by where the guard movement code is in the AI)
|
||||||
if (IsNPC()) {
|
if (IsNPC()) {
|
||||||
CastToNPC()->NextGuardPosition();
|
CastToNPC()->NextGuardPosition();
|
||||||
@ -1610,28 +1621,45 @@ void Mob::AI_Process() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (IsPetRegroup())
|
if (IsPetRegroup()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* Entity has been assigned another entity to follow */
|
|
||||||
else if (GetFollowID())
|
|
||||||
{
|
|
||||||
Mob* follow = entity_list.GetMob(GetFollowID());
|
|
||||||
if (!follow) SetFollowID(0);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
float dist2 = DistanceSquared(m_Position, follow->GetPosition());
|
|
||||||
int followdist = GetFollowDistance();
|
|
||||||
|
|
||||||
if (dist2 >= followdist) // Default follow distance is 100
|
|
||||||
{
|
|
||||||
int speed = GetWalkspeed();
|
|
||||||
if (dist2 >= followdist + 150)
|
|
||||||
speed = GetRunspeed();
|
|
||||||
CalculateNewPosition(follow->GetX(), follow->GetY(), follow->GetZ(), speed);
|
|
||||||
}
|
}
|
||||||
else
|
/* Entity has been assigned another entity to follow */
|
||||||
{
|
else if (GetFollowID()) {
|
||||||
|
Mob *follow = entity_list.GetMob(static_cast<uint16>(GetFollowID()));
|
||||||
|
if (!follow) {
|
||||||
|
SetFollowID(0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
float distance = DistanceSquared(m_Position, follow->GetPosition());
|
||||||
|
int follow_distance = GetFollowDistance();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default follow distance is 100
|
||||||
|
*/
|
||||||
|
if (distance >= follow_distance) {
|
||||||
|
int speed = GetWalkspeed();
|
||||||
|
|
||||||
|
if (distance >= follow_distance + 150) {
|
||||||
|
speed = GetRunspeed();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool waypoint_changed, node_reached;
|
||||||
|
|
||||||
|
glm::vec3 Goal = UpdatePath(
|
||||||
|
follow->GetX(),
|
||||||
|
follow->GetY(),
|
||||||
|
follow->GetZ(),
|
||||||
|
speed,
|
||||||
|
waypoint_changed,
|
||||||
|
node_reached
|
||||||
|
);
|
||||||
|
|
||||||
|
CalculateNewPosition(Goal.x, Goal.y, Goal.z, speed, true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
moved = false;
|
moved = false;
|
||||||
SetCurrentSpeed(0);
|
SetCurrentSpeed(0);
|
||||||
}
|
}
|
||||||
@ -1640,20 +1668,21 @@ void Mob::AI_Process() {
|
|||||||
else //not a pet, and not following somebody...
|
else //not a pet, and not following somebody...
|
||||||
{
|
{
|
||||||
// dont move till a bit after you last fought
|
// dont move till a bit after you last fought
|
||||||
if (pLastFightingDelayMoving < Timer::GetCurrentTime())
|
if (time_until_can_move < Timer::GetCurrentTime()) {
|
||||||
{
|
if (this->IsClient()) {
|
||||||
if (this->IsClient())
|
|
||||||
{
|
/**
|
||||||
// LD timer expired, drop out of world
|
* LD timer expired, drop out of world
|
||||||
if (this->CastToClient()->IsLD())
|
*/
|
||||||
|
if (this->CastToClient()->IsLD()) {
|
||||||
this->CastToClient()->Disconnect();
|
this->CastToClient()->Disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(IsNPC())
|
if (IsNPC()) {
|
||||||
{
|
if (RuleB(NPC, SmartLastFightingDelayMoving) && !feign_memory_list.empty()) {
|
||||||
if(RuleB(NPC, SmartLastFightingDelayMoving) && !feign_memory_list.empty())
|
|
||||||
{
|
|
||||||
minLastFightingDelayMoving = 0;
|
minLastFightingDelayMoving = 0;
|
||||||
maxLastFightingDelayMoving = 0;
|
maxLastFightingDelayMoving = 0;
|
||||||
}
|
}
|
||||||
@ -1661,92 +1690,144 @@ void Mob::AI_Process() {
|
|||||||
CastToNPC()->AI_DoMovement();
|
CastToNPC()->AI_DoMovement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
} // else if (AImovement_timer->Check())
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Do Ranged attack here
|
//Do Ranged attack here
|
||||||
if(doranged)
|
if (doranged) {
|
||||||
{
|
|
||||||
RangedAttack(target);
|
RangedAttack(target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NPC::AI_DoMovement() {
|
void NPC::AI_DoMovement() {
|
||||||
float walksp = GetMovespeed();
|
|
||||||
if(walksp <= 0.0f)
|
|
||||||
return; //this is idle movement at walk speed, and we are unable to walk right now.
|
|
||||||
|
|
||||||
|
float move_speed = GetMovespeed();
|
||||||
|
|
||||||
|
if (move_speed <= 0.0f) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Roambox logic sets precedence
|
||||||
|
*/
|
||||||
if (roambox_distance > 0) {
|
if (roambox_distance > 0) {
|
||||||
if (
|
|
||||||
roambox_movingto_x > roambox_max_x
|
if (!IsMoving()) {
|
||||||
|| roambox_movingto_x < roambox_min_x
|
auto move_x = static_cast<float>(zone->random.Real(-roambox_distance, roambox_distance));
|
||||||
|| roambox_movingto_y > roambox_max_y
|
auto move_y = static_cast<float>(zone->random.Real(-roambox_distance, roambox_distance));
|
||||||
|| roambox_movingto_y < roambox_min_y
|
|
||||||
)
|
roambox_destination_x = EQEmu::Clamp((GetX() + move_x), roambox_min_x, roambox_max_x);
|
||||||
{
|
roambox_destination_y = EQEmu::Clamp((GetY() + move_y), roambox_min_y, roambox_max_y);
|
||||||
float movedist = roambox_distance*roambox_distance;
|
|
||||||
float movex = zone->random.Real(0, movedist);
|
/**
|
||||||
float movey = movedist - movex;
|
* If our roambox was configured with large distances, chances of hitting the min or max end of
|
||||||
movex = sqrtf(movex);
|
* the clamp is high, this causes NPC's to gather on the border of a box, to reduce clustering
|
||||||
movey = sqrtf(movey);
|
* either lower the roambox distance or the code will do a simple random between min - max when it
|
||||||
movex *= zone->random.Int(0, 1) ? 1 : -1;
|
* hits the min or max of the clamp
|
||||||
movey *= zone->random.Int(0, 1) ? 1 : -1;
|
*/
|
||||||
roambox_movingto_x = GetX() + movex;
|
if (roambox_destination_x == roambox_min_x || roambox_destination_x == roambox_max_x) {
|
||||||
roambox_movingto_y = GetY() + movey;
|
roambox_destination_x = static_cast<float>(zone->random.Real(roambox_min_x, roambox_max_x));
|
||||||
//Try to calculate new coord using distance.
|
|
||||||
if (roambox_movingto_x > roambox_max_x || roambox_movingto_x < roambox_min_x)
|
|
||||||
roambox_movingto_x -= movex * 2;
|
|
||||||
if (roambox_movingto_y > roambox_max_y || roambox_movingto_y < roambox_min_y)
|
|
||||||
roambox_movingto_y -= movey * 2;
|
|
||||||
//New coord is still invalid, ignore distance and just pick a new random coord.
|
|
||||||
//If we're here we may have a roambox where one side is shorter than the specified distance. Commons, Wkarana, etc.
|
|
||||||
if (roambox_movingto_x > roambox_max_x || roambox_movingto_x < roambox_min_x)
|
|
||||||
roambox_movingto_x = zone->random.Real(roambox_min_x+1,roambox_max_x-1);
|
|
||||||
if (roambox_movingto_y > roambox_max_y || roambox_movingto_y < roambox_min_y)
|
|
||||||
roambox_movingto_y = zone->random.Real(roambox_min_y+1,roambox_max_y-1);
|
|
||||||
Log(Logs::Detail, Logs::AI,
|
|
||||||
"Roam Box: d=%.3f (%.3f->%.3f,%.3f->%.3f): Go To (%.3f,%.3f)",
|
|
||||||
roambox_distance, roambox_min_x, roambox_max_x, roambox_min_y,
|
|
||||||
roambox_max_y, roambox_movingto_x, roambox_movingto_y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::AI, "Roam Box: d=%.3f (%.3f->%.3f,%.3f->%.3f): Go To (%.3f,%.3f)",
|
if (roambox_destination_y == roambox_min_y || roambox_destination_y == roambox_max_y) {
|
||||||
roambox_distance, roambox_min_x, roambox_max_x, roambox_min_y, roambox_max_y, roambox_movingto_x, roambox_movingto_y);
|
roambox_destination_y = static_cast<float>(zone->random.Real(roambox_min_y, roambox_max_y));
|
||||||
|
}
|
||||||
|
|
||||||
float new_z = this->FindGroundZ(m_Position.x, m_Position.y, 5) + GetZOffset();
|
/**
|
||||||
|
* If mob was not spawned in water, let's not randomly roam them into water
|
||||||
|
* if the roam box was sloppily configured
|
||||||
|
*/
|
||||||
|
if (!this->GetWasSpawnedInWater()) {
|
||||||
|
if (zone->HasMap() && zone->HasWaterMap()) {
|
||||||
|
auto position = glm::vec3(
|
||||||
|
roambox_destination_x,
|
||||||
|
roambox_destination_y,
|
||||||
|
(m_Position.z - 15)
|
||||||
|
);
|
||||||
|
|
||||||
if (!CalculateNewPosition(roambox_movingto_x, roambox_movingto_y, new_z, walksp, true))
|
/**
|
||||||
{
|
* If someone brought us into water when we naturally wouldn't path there, return to spawn
|
||||||
this->FixZ(); // FixZ on final arrival point.
|
*/
|
||||||
roambox_movingto_x = roambox_max_x + 1; // force update
|
if (zone->watermap->InLiquid(position) && zone->watermap->InLiquid(m_Position)) {
|
||||||
pLastFightingDelayMoving = Timer::GetCurrentTime() + RandomTimer(roambox_min_delay, roambox_delay);
|
roambox_destination_x = m_SpawnPoint.x;
|
||||||
|
roambox_destination_y = m_SpawnPoint.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zone->watermap->InLiquid(position)) {
|
||||||
|
Log(Logs::Detail,
|
||||||
|
Logs::NPCRoamBox, "%s | My destination is in water and I don't belong there!",
|
||||||
|
this->GetCleanName());
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 destination;
|
||||||
|
destination.x = roambox_destination_x;
|
||||||
|
destination.y = roambox_destination_y;
|
||||||
|
destination.z = m_Position.z;
|
||||||
|
roambox_destination_z = GetFixedZ(destination) + this->GetZOffset();
|
||||||
|
|
||||||
|
Log(Logs::Detail,
|
||||||
|
Logs::NPCRoamBox,
|
||||||
|
"Calculate | NPC: %s distance %.3f | min_x %.3f | max_x %.3f | final_x %.3f | min_y %.3f | max_y %.3f | final_y %.3f",
|
||||||
|
this->GetCleanName(),
|
||||||
|
roambox_distance,
|
||||||
|
roambox_min_x,
|
||||||
|
roambox_max_x,
|
||||||
|
roambox_destination_x,
|
||||||
|
roambox_min_y,
|
||||||
|
roambox_max_y,
|
||||||
|
roambox_destination_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool waypoint_changed, node_reached;
|
||||||
|
|
||||||
|
glm::vec3 Goal = UpdatePath(
|
||||||
|
roambox_destination_x,
|
||||||
|
roambox_destination_y,
|
||||||
|
roambox_destination_z,
|
||||||
|
move_speed,
|
||||||
|
waypoint_changed,
|
||||||
|
node_reached
|
||||||
|
);
|
||||||
|
|
||||||
|
CalculateNewPosition(Goal.x, Goal.y, Goal.z, move_speed, true);
|
||||||
|
|
||||||
|
if (m_Position.x == roambox_destination_x && m_Position.y == roambox_destination_y) {
|
||||||
|
time_until_can_move = Timer::GetCurrentTime() + RandomTimer(roambox_min_delay, roambox_delay);
|
||||||
SetMoving(false);
|
SetMoving(false);
|
||||||
SendPosition(); // makes mobs stop clientside
|
this->FixZ();
|
||||||
|
SendPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else if (roamer)
|
else if (roamer) {
|
||||||
{
|
if (AI_walking_timer->Check()) {
|
||||||
if (AI_walking_timer->Check())
|
|
||||||
{
|
|
||||||
movetimercompleted = true;
|
movetimercompleted = true;
|
||||||
AI_walking_timer->Disable();
|
AI_walking_timer->Disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int32 gridno = CastToNPC()->GetGrid();
|
int32 gridno = CastToNPC()->GetGrid();
|
||||||
|
|
||||||
if (gridno > 0 || cur_wp == -2) {
|
if (gridno > 0 || cur_wp == -2) {
|
||||||
if (movetimercompleted == true) { // time to pause at wp is over
|
if (movetimercompleted == true) { // time to pause at wp is over
|
||||||
AI_SetupNextWaypoint();
|
AI_SetupNextWaypoint();
|
||||||
} // endif (movetimercompleted==true)
|
} // endif (movetimercompleted==true)
|
||||||
else if (!(AI_walking_timer->Enabled()))
|
else if (!(AI_walking_timer->Enabled())) { // currently moving
|
||||||
{ // currently moving
|
|
||||||
bool doMove = true;
|
bool doMove = true;
|
||||||
if (m_CurrentWayPoint.x == GetX() && m_CurrentWayPoint.y == GetY())
|
if (m_CurrentWayPoint.x == GetX() && m_CurrentWayPoint.y == GetY()) { // are we there yet? then stop
|
||||||
{ // are we there yet? then stop
|
Log(Logs::Detail,
|
||||||
Log(Logs::Detail, Logs::AI, "We have reached waypoint %d (%.3f,%.3f,%.3f) on grid %d", cur_wp, GetX(), GetY(), GetZ(), GetGrid());
|
Logs::AI,
|
||||||
|
"We have reached waypoint %d (%.3f,%.3f,%.3f) on grid %d",
|
||||||
|
cur_wp,
|
||||||
|
GetX(),
|
||||||
|
GetY(),
|
||||||
|
GetZ(),
|
||||||
|
GetGrid());
|
||||||
|
|
||||||
SetWaypointPause();
|
SetWaypointPause();
|
||||||
SetAppearance(eaStanding, false);
|
SetAppearance(eaStanding, false);
|
||||||
@ -1776,32 +1857,41 @@ void NPC::AI_DoMovement() {
|
|||||||
if (cur_wp == 1)
|
if (cur_wp == 1)
|
||||||
ClearFeignMemory();
|
ClearFeignMemory();
|
||||||
}
|
}
|
||||||
if (doMove)
|
if (doMove) { // not at waypoint yet or at 0 pause WP, so keep moving
|
||||||
{ // not at waypoint yet or at 0 pause WP, so keep moving
|
|
||||||
if (!RuleB(Pathing, AggroReturnToGrid) || !zone->pathing || (DistractedFromGrid == 0))
|
if (!RuleB(Pathing, AggroReturnToGrid) || !zone->pathing || (DistractedFromGrid == 0))
|
||||||
CalculateNewPosition(m_CurrentWayPoint.x, m_CurrentWayPoint.y, m_CurrentWayPoint.z, walksp, true);
|
CalculateNewPosition(
|
||||||
else
|
m_CurrentWayPoint.x,
|
||||||
{
|
m_CurrentWayPoint.y,
|
||||||
|
m_CurrentWayPoint.z,
|
||||||
|
move_speed,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
else {
|
||||||
bool WaypointChanged;
|
bool WaypointChanged;
|
||||||
bool NodeReached;
|
bool NodeReached;
|
||||||
glm::vec3 Goal = UpdatePath(m_CurrentWayPoint.x, m_CurrentWayPoint.y, m_CurrentWayPoint.z, walksp, WaypointChanged, NodeReached);
|
glm::vec3 Goal = UpdatePath(
|
||||||
|
m_CurrentWayPoint.x,
|
||||||
|
m_CurrentWayPoint.y,
|
||||||
|
m_CurrentWayPoint.z,
|
||||||
|
move_speed,
|
||||||
|
WaypointChanged,
|
||||||
|
NodeReached
|
||||||
|
);
|
||||||
if (WaypointChanged)
|
if (WaypointChanged)
|
||||||
tar_ndx = 20;
|
tar_ndx = 20;
|
||||||
|
|
||||||
if (NodeReached)
|
if (NodeReached)
|
||||||
entity_list.OpenDoorsNear(CastToNPC());
|
entity_list.OpenDoorsNear(CastToNPC());
|
||||||
|
|
||||||
CalculateNewPosition(Goal.x, Goal.y, Goal.z, walksp, true);
|
CalculateNewPosition(Goal.x, Goal.y, Goal.z, move_speed, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // endif (gridno > 0)
|
} // endif (gridno > 0)
|
||||||
// handle new quest grid command processing
|
// handle new quest grid command processing
|
||||||
else if (gridno < 0)
|
else if (gridno < 0) { // this mob is under quest control
|
||||||
{ // this mob is under quest control
|
if (movetimercompleted == true) { // time to pause has ended
|
||||||
if (movetimercompleted==true)
|
|
||||||
{ // time to pause has ended
|
|
||||||
SetGrid(0 - GetGrid()); // revert to AI control
|
SetGrid(0 - GetGrid()); // revert to AI control
|
||||||
Log(Logs::Detail, Logs::Pathing, "Quest pathing is finished. Resuming on grid %d", GetGrid());
|
Log(Logs::Detail, Logs::Pathing, "Quest pathing is finished. Resuming on grid %d", GetGrid());
|
||||||
|
|
||||||
@ -1812,39 +1902,55 @@ void NPC::AI_DoMovement() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (IsGuarding())
|
else if (IsGuarding()) {
|
||||||
{
|
|
||||||
bool CP2Moved;
|
bool CP2Moved;
|
||||||
if(!RuleB(Pathing, Guard) || !zone->pathing)
|
if (!RuleB(Pathing, Guard) || !zone->pathing) {
|
||||||
CP2Moved = CalculateNewPosition(m_GuardPoint.x, m_GuardPoint.y, m_GuardPoint.z, walksp);
|
CP2Moved = CalculateNewPosition(m_GuardPoint.x, m_GuardPoint.y, m_GuardPoint.z, move_speed);
|
||||||
else
|
}
|
||||||
{
|
else {
|
||||||
if(!((m_Position.x == m_GuardPoint.x) && (m_Position.y == m_GuardPoint.y) && (m_Position.z == m_GuardPoint.z)))
|
if (!((m_Position.x == m_GuardPoint.x) && (m_Position.y == m_GuardPoint.y) &&
|
||||||
{
|
(m_Position.z == m_GuardPoint.z))) {
|
||||||
|
|
||||||
bool WaypointChanged, NodeReached;
|
bool WaypointChanged, NodeReached;
|
||||||
glm::vec3 Goal = UpdatePath(m_GuardPoint.x, m_GuardPoint.y, m_GuardPoint.z, walksp, WaypointChanged, NodeReached);
|
|
||||||
if(WaypointChanged)
|
glm::vec3 Goal = UpdatePath(
|
||||||
|
m_GuardPoint.x,
|
||||||
|
m_GuardPoint.y,
|
||||||
|
m_GuardPoint.z,
|
||||||
|
move_speed,
|
||||||
|
WaypointChanged,
|
||||||
|
NodeReached
|
||||||
|
);
|
||||||
|
if (WaypointChanged) {
|
||||||
tar_ndx = 20;
|
tar_ndx = 20;
|
||||||
|
}
|
||||||
|
|
||||||
if(NodeReached)
|
if (NodeReached) {
|
||||||
entity_list.OpenDoorsNear(CastToNPC());
|
entity_list.OpenDoorsNear(CastToNPC());
|
||||||
|
|
||||||
CP2Moved = CalculateNewPosition(Goal.x, Goal.y, Goal.z, walksp);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
CP2Moved = CalculateNewPosition(Goal.x, Goal.y, Goal.z, move_speed);
|
||||||
|
}
|
||||||
|
else {
|
||||||
CP2Moved = false;
|
CP2Moved = false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (!CP2Moved)
|
if (!CP2Moved) {
|
||||||
{
|
|
||||||
if (moved) {
|
if (moved) {
|
||||||
Log(Logs::Detail, Logs::AI, "Reached guard point (%.3f,%.3f,%.3f)", m_GuardPoint.x, m_GuardPoint.y, m_GuardPoint.z);
|
Log(Logs::Detail,
|
||||||
|
Logs::AI,
|
||||||
|
"Reached guard point (%.3f,%.3f,%.3f)",
|
||||||
|
m_GuardPoint.x,
|
||||||
|
m_GuardPoint.y,
|
||||||
|
m_GuardPoint.z);
|
||||||
|
|
||||||
ClearFeignMemory();
|
ClearFeignMemory();
|
||||||
moved = false;
|
moved = false;
|
||||||
if (GetTarget() == nullptr || DistanceSquared(m_Position, GetTarget()->GetPosition()) >= 5*5 )
|
if (GetTarget() == nullptr || DistanceSquared(m_Position, GetTarget()->GetPosition()) >= 5 * 5) {
|
||||||
{
|
|
||||||
SetHeading(m_GuardPoint.w);
|
SetHeading(m_GuardPoint.w);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
FaceTarget(GetTarget());
|
FaceTarget(GetTarget());
|
||||||
}
|
}
|
||||||
SetCurrentSpeed(0);
|
SetCurrentSpeed(0);
|
||||||
@ -1968,11 +2074,11 @@ void Mob::AI_Event_NoLongerEngaged() {
|
|||||||
if (!IsAIControlled())
|
if (!IsAIControlled())
|
||||||
return;
|
return;
|
||||||
this->AI_walking_timer->Start(RandomTimer(3000,20000));
|
this->AI_walking_timer->Start(RandomTimer(3000,20000));
|
||||||
pLastFightingDelayMoving = Timer::GetCurrentTime();
|
time_until_can_move = Timer::GetCurrentTime();
|
||||||
if (minLastFightingDelayMoving == maxLastFightingDelayMoving)
|
if (minLastFightingDelayMoving == maxLastFightingDelayMoving)
|
||||||
pLastFightingDelayMoving += minLastFightingDelayMoving;
|
time_until_can_move += minLastFightingDelayMoving;
|
||||||
else
|
else
|
||||||
pLastFightingDelayMoving += zone->random.Int(minLastFightingDelayMoving, maxLastFightingDelayMoving);
|
time_until_can_move += zone->random.Int(minLastFightingDelayMoving, maxLastFightingDelayMoving);
|
||||||
// So mobs don't keep running as a ghost until AIwalking_timer fires
|
// So mobs don't keep running as a ghost until AIwalking_timer fires
|
||||||
// if they were moving prior to losing all hate
|
// if they were moving prior to losing all hate
|
||||||
// except if we're a pet, then we might run into some issues with pets backing off when they should immediately be moving
|
// except if we're a pet, then we might run into some issues with pets backing off when they should immediately be moving
|
||||||
@ -2255,8 +2361,6 @@ void Mob::AreaRampage(ExtraAttackOptions *opts)
|
|||||||
m_specialattacks = eSpecialAttacks::AERampage;
|
m_specialattacks = eSpecialAttacks::AERampage;
|
||||||
index_hit = hate_list.AreaRampage(this, GetTarget(), rampage_targets, opts);
|
index_hit = hate_list.AreaRampage(this, GetTarget(), rampage_targets, opts);
|
||||||
|
|
||||||
if(index_hit == 0)
|
|
||||||
ProcessAttackRounds(GetTarget(), opts);
|
|
||||||
m_specialattacks = eSpecialAttacks::None;
|
m_specialattacks = eSpecialAttacks::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -242,8 +242,8 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, const glm::vec4& position, int if
|
|||||||
roambox_max_y = -2;
|
roambox_max_y = -2;
|
||||||
roambox_min_x = -2;
|
roambox_min_x = -2;
|
||||||
roambox_min_y = -2;
|
roambox_min_y = -2;
|
||||||
roambox_movingto_x = -2;
|
roambox_destination_x = -2;
|
||||||
roambox_movingto_y = -2;
|
roambox_destination_y = -2;
|
||||||
roambox_min_delay = 1000;
|
roambox_min_delay = 1000;
|
||||||
roambox_delay = 1000;
|
roambox_delay = 1000;
|
||||||
p_depop = false;
|
p_depop = false;
|
||||||
|
|||||||
17
zone/npc.h
17
zone/npc.h
@ -311,9 +311,17 @@ public:
|
|||||||
void SaveGuardSpot(bool iClearGuardSpot = false);
|
void SaveGuardSpot(bool iClearGuardSpot = false);
|
||||||
inline bool IsGuarding() const { return(m_GuardPoint.w != 0); }
|
inline bool IsGuarding() const { return(m_GuardPoint.w != 0); }
|
||||||
void SaveGuardSpotCharm();
|
void SaveGuardSpotCharm();
|
||||||
|
|
||||||
void RestoreGuardSpotCharm();
|
void RestoreGuardSpotCharm();
|
||||||
void AI_SetRoambox(float iDist, float iRoamDist, uint32 iDelay = 2500, uint32 iMinDelay = 2500);
|
|
||||||
void AI_SetRoambox(float iDist, float iMaxX, float iMinX, float iMaxY, float iMinY, uint32 iDelay = 2500, uint32 iMinDelay = 2500);
|
void AI_SetRoambox(
|
||||||
|
float max_distance,
|
||||||
|
float roam_distance_variance,
|
||||||
|
uint32 delay = 2500,
|
||||||
|
uint32 min_delay = 2500
|
||||||
|
);
|
||||||
|
|
||||||
|
void AI_SetRoambox(float distance, float max_x, float min_x, float max_y, float min_y, uint32 delay = 2500, uint32 min_delay = 2500);
|
||||||
|
|
||||||
//mercenary stuff
|
//mercenary stuff
|
||||||
void LoadMercTypes();
|
void LoadMercTypes();
|
||||||
@ -530,8 +538,9 @@ protected:
|
|||||||
float roambox_min_x;
|
float roambox_min_x;
|
||||||
float roambox_min_y;
|
float roambox_min_y;
|
||||||
float roambox_distance;
|
float roambox_distance;
|
||||||
float roambox_movingto_x;
|
float roambox_destination_x;
|
||||||
float roambox_movingto_y;
|
float roambox_destination_y;
|
||||||
|
float roambox_destination_z;
|
||||||
uint32 roambox_delay;
|
uint32 roambox_delay;
|
||||||
uint32 roambox_min_delay;
|
uint32 roambox_min_delay;
|
||||||
|
|
||||||
|
|||||||
@ -528,6 +528,8 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object)
|
|||||||
if(cursordelete) // delete the item if it's a duplicate lore. We have to do this because the client expects the item packet
|
if(cursordelete) // delete the item if it's a duplicate lore. We have to do this because the client expects the item packet
|
||||||
sender->DeleteItemInInventory(EQEmu::invslot::slotCursor);
|
sender->DeleteItemInInventory(EQEmu::invslot::slotCursor);
|
||||||
|
|
||||||
|
sender->DropItemQS(m_inst, true);
|
||||||
|
|
||||||
if(!m_ground_spawn)
|
if(!m_ground_spawn)
|
||||||
safe_delete(m_inst);
|
safe_delete(m_inst);
|
||||||
|
|
||||||
|
|||||||
124
zone/spawn2.cpp
124
zone/spawn2.cpp
@ -145,10 +145,11 @@ bool Spawn2::Process() {
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
//grab our spawn group
|
//grab our spawn group
|
||||||
SpawnGroup* sg = zone->spawn_group_list.GetSpawnGroup(spawngroup_id_);
|
SpawnGroup *spawn_group = zone->spawn_group_list.GetSpawnGroup(spawngroup_id_);
|
||||||
|
|
||||||
if(NPCPointerValid() && (sg->despawn == 0 || condition_id != 0))
|
if (NPCPointerValid() && (spawn_group->despawn == 0 || condition_id != 0)) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (timer.Check()) {
|
if (timer.Check()) {
|
||||||
timer.Disable();
|
timer.Disable();
|
||||||
@ -159,25 +160,39 @@ bool Spawn2::Process() {
|
|||||||
//then we reset the timer and try again next time.
|
//then we reset the timer and try again next time.
|
||||||
if (condition_id != SC_AlwaysEnabled
|
if (condition_id != SC_AlwaysEnabled
|
||||||
&& !zone->spawn_conditions.Check(condition_id, condition_min_value)) {
|
&& !zone->spawn_conditions.Check(condition_id, condition_min_value)) {
|
||||||
Log(Logs::Detail, Logs::Spawns, "Spawn2 %d: spawning prevented by spawn condition %d", spawn2_id, condition_id);
|
Log(Logs::Detail,
|
||||||
|
Logs::Spawns,
|
||||||
|
"Spawn2 %d: spawning prevented by spawn condition %d",
|
||||||
|
spawn2_id,
|
||||||
|
condition_id);
|
||||||
Reset();
|
Reset();
|
||||||
return (true);
|
return (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sg == nullptr) {
|
if (spawn_group == nullptr) {
|
||||||
database.LoadSpawnGroupsByID(spawngroup_id_, &zone->spawn_group_list);
|
database.LoadSpawnGroupsByID(spawngroup_id_, &zone->spawn_group_list);
|
||||||
sg = zone->spawn_group_list.GetSpawnGroup(spawngroup_id_);
|
spawn_group = zone->spawn_group_list.GetSpawnGroup(spawngroup_id_);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sg == nullptr) {
|
if (spawn_group == nullptr) {
|
||||||
Log(Logs::Detail, Logs::Spawns, "Spawn2 %d: Unable to locate spawn group %d. Disabling.", spawn2_id, spawngroup_id_);
|
Log(Logs::Detail,
|
||||||
|
Logs::Spawns,
|
||||||
|
"Spawn2 %d: Unable to locate spawn group %d. Disabling.",
|
||||||
|
spawn2_id,
|
||||||
|
spawngroup_id_);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//have the spawn group pick an NPC for us
|
//have the spawn group pick an NPC for us
|
||||||
uint32 npcid = sg->GetNPCType();
|
uint32 npcid = spawn_group->GetNPCType();
|
||||||
if (npcid == 0) {
|
if (npcid == 0) {
|
||||||
Log(Logs::Detail, Logs::Spawns, "Spawn2 %d: Spawn group %d did not yeild an NPC! not spawning.", spawn2_id, spawngroup_id_);
|
Log(Logs::Detail,
|
||||||
|
Logs::Spawns,
|
||||||
|
"Spawn2 %d: Spawn group %d did not yeild an NPC! not spawning.",
|
||||||
|
spawn2_id,
|
||||||
|
spawngroup_id_);
|
||||||
|
|
||||||
Reset(); //try again later (why?)
|
Reset(); //try again later (why?)
|
||||||
return (true);
|
return (true);
|
||||||
}
|
}
|
||||||
@ -185,16 +200,24 @@ bool Spawn2::Process() {
|
|||||||
//try to find our NPC type.
|
//try to find our NPC type.
|
||||||
const NPCType *tmp = database.LoadNPCTypesData(npcid);
|
const NPCType *tmp = database.LoadNPCTypesData(npcid);
|
||||||
if (tmp == nullptr) {
|
if (tmp == nullptr) {
|
||||||
Log(Logs::Detail, Logs::Spawns, "Spawn2 %d: Spawn group %d yeilded an invalid NPC type %d", spawn2_id, spawngroup_id_, npcid);
|
Log(Logs::Detail,
|
||||||
|
Logs::Spawns,
|
||||||
|
"Spawn2 %d: Spawn group %d yeilded an invalid NPC type %d",
|
||||||
|
spawn2_id,
|
||||||
|
spawngroup_id_,
|
||||||
|
npcid);
|
||||||
Reset(); //try again later
|
Reset(); //try again later
|
||||||
return (true);
|
return (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tmp->unique_spawn_by_name)
|
if (tmp->unique_spawn_by_name) {
|
||||||
{
|
if (!entity_list.LimitCheckName(tmp->name)) {
|
||||||
if(!entity_list.LimitCheckName(tmp->name))
|
Log(Logs::Detail,
|
||||||
{
|
Logs::Spawns,
|
||||||
Log(Logs::Detail, Logs::Spawns, "Spawn2 %d: Spawn group %d yeilded NPC type %d, which is unique and one already exists.", spawn2_id, spawngroup_id_, npcid);
|
"Spawn2 %d: Spawn group %d yeilded NPC type %d, which is unique and one already exists.",
|
||||||
|
spawn2_id,
|
||||||
|
spawngroup_id_,
|
||||||
|
npcid);
|
||||||
timer.Start(5000); //try again in five seconds.
|
timer.Start(5000); //try again in five seconds.
|
||||||
return (true);
|
return (true);
|
||||||
}
|
}
|
||||||
@ -202,30 +225,32 @@ bool Spawn2::Process() {
|
|||||||
|
|
||||||
if (tmp->spawn_limit > 0) {
|
if (tmp->spawn_limit > 0) {
|
||||||
if (!entity_list.LimitCheckType(npcid, tmp->spawn_limit)) {
|
if (!entity_list.LimitCheckType(npcid, tmp->spawn_limit)) {
|
||||||
Log(Logs::Detail, Logs::Spawns, "Spawn2 %d: Spawn group %d yeilded NPC type %d, which is over its spawn limit (%d)", spawn2_id, spawngroup_id_, npcid, tmp->spawn_limit);
|
Log(Logs::Detail,
|
||||||
|
Logs::Spawns,
|
||||||
|
"Spawn2 %d: Spawn group %d yeilded NPC type %d, which is over its spawn limit (%d)",
|
||||||
|
spawn2_id,
|
||||||
|
spawngroup_id_,
|
||||||
|
npcid,
|
||||||
|
tmp->spawn_limit);
|
||||||
timer.Start(5000); //try again in five seconds.
|
timer.Start(5000); //try again in five seconds.
|
||||||
return (true);
|
return (true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ignore_despawn = false;
|
bool ignore_despawn = false;
|
||||||
if (npcthis)
|
if (npcthis) {
|
||||||
{
|
|
||||||
ignore_despawn = npcthis->IgnoreDespawn();
|
ignore_despawn = npcthis->IgnoreDespawn();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ignore_despawn)
|
if (ignore_despawn) {
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sg->despawn != 0 && condition_id == 0 && !ignore_despawn)
|
if (spawn_group->despawn != 0 && condition_id == 0 && !ignore_despawn) {
|
||||||
{
|
|
||||||
zone->Despawn(spawn2_id);
|
zone->Despawn(spawn2_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsDespawned)
|
if (IsDespawned) {
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,23 +261,61 @@ bool Spawn2::Process() {
|
|||||||
|
|
||||||
npcthis = npc;
|
npcthis = npc;
|
||||||
npc->AddLootTable();
|
npc->AddLootTable();
|
||||||
if (npc->DropsGlobalLoot())
|
if (npc->DropsGlobalLoot()) {
|
||||||
npc->CheckGlobalLootTables();
|
npc->CheckGlobalLootTables();
|
||||||
|
}
|
||||||
npc->SetSp2(spawngroup_id_);
|
npc->SetSp2(spawngroup_id_);
|
||||||
npc->SaveGuardPointAnim(anim);
|
npc->SaveGuardPointAnim(anim);
|
||||||
npc->SetAppearance((EmuAppearance) anim);
|
npc->SetAppearance((EmuAppearance) anim);
|
||||||
entity_list.AddNPC(npc);
|
entity_list.AddNPC(npc);
|
||||||
//this limit add must be done after the AddNPC since we need the entity ID.
|
//this limit add must be done after the AddNPC since we need the entity ID.
|
||||||
entity_list.LimitAddNPC(npc);
|
entity_list.LimitAddNPC(npc);
|
||||||
if(sg->roamdist && sg->roambox[0] && sg->roambox[1] && sg->roambox[2] && sg->roambox[3] && sg->delay && sg->min_delay)
|
|
||||||
npc->AI_SetRoambox(sg->roamdist,sg->roambox[0],sg->roambox[1],sg->roambox[2],sg->roambox[3],sg->delay,sg->min_delay);
|
/**
|
||||||
|
* Roambox init
|
||||||
|
*/
|
||||||
|
if (spawn_group->roamdist && spawn_group->roambox[0] && spawn_group->roambox[1] && spawn_group->roambox[2] &&
|
||||||
|
spawn_group->roambox[3] && spawn_group->delay && spawn_group->min_delay) {
|
||||||
|
|
||||||
|
npc->AI_SetRoambox(
|
||||||
|
spawn_group->roamdist,
|
||||||
|
spawn_group->roambox[0],
|
||||||
|
spawn_group->roambox[1],
|
||||||
|
spawn_group->roambox[2],
|
||||||
|
spawn_group->roambox[3],
|
||||||
|
spawn_group->delay,
|
||||||
|
spawn_group->min_delay
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (zone->InstantGrids()) {
|
if (zone->InstantGrids()) {
|
||||||
Log(Logs::Detail, Logs::Spawns, "Spawn2 %d: Group %d spawned %s (%d) at (%.3f, %.3f, %.3f).", spawn2_id, spawngroup_id_, npc->GetName(), npcid, x, y, z);
|
Log(Logs::Detail,
|
||||||
|
Logs::Spawns,
|
||||||
|
"Spawn2 %d: Group %d spawned %s (%d) at (%.3f, %.3f, %.3f).",
|
||||||
|
spawn2_id,
|
||||||
|
spawngroup_id_,
|
||||||
|
npc->GetName(),
|
||||||
|
npcid,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
z);
|
||||||
|
|
||||||
LoadGrid();
|
LoadGrid();
|
||||||
} else {
|
}
|
||||||
Log(Logs::Detail, Logs::Spawns, "Spawn2 %d: Group %d spawned %s (%d) at (%.3f, %.3f, %.3f). Grid loading delayed.", spawn2_id, spawngroup_id_, tmp->name, npcid, x, y, z);
|
else {
|
||||||
|
Log(Logs::Detail,
|
||||||
|
Logs::Spawns,
|
||||||
|
"Spawn2 %d: Group %d spawned %s (%d) at (%.3f, %.3f, %.3f). Grid loading delayed.",
|
||||||
|
spawn2_id,
|
||||||
|
spawngroup_id_,
|
||||||
|
tmp->name,
|
||||||
|
npcid,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,7 +341,6 @@ void Spawn2::LoadGrid() {
|
|||||||
Log(Logs::Detail, Logs::Spawns, "Spawn2 %d: Loading grid %d for %s", spawn2_id, grid_, npcthis->GetName());
|
Log(Logs::Detail, Logs::Spawns, "Spawn2 %d: Loading grid %d for %s", spawn2_id, grid_, npcthis->GetName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
All three of these actions basically say that the mob which was
|
All three of these actions basically say that the mob which was
|
||||||
associated with this spawn point is no longer relavent.
|
associated with this spawn point is no longer relavent.
|
||||||
|
|||||||
@ -3928,6 +3928,12 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
|
|||||||
Mob* tempmob = GetOwner();
|
Mob* tempmob = GetOwner();
|
||||||
SetOwnerID(0);
|
SetOwnerID(0);
|
||||||
SetPetType(petNone);
|
SetPetType(petNone);
|
||||||
|
SetHeld(false);
|
||||||
|
SetGHeld(false);
|
||||||
|
SetNoCast(false);
|
||||||
|
SetFocused(false);
|
||||||
|
SetPetStop(false);
|
||||||
|
SetPetRegroup(false);
|
||||||
if(tempmob)
|
if(tempmob)
|
||||||
{
|
{
|
||||||
tempmob->SetPet(0);
|
tempmob->SetPet(0);
|
||||||
|
|||||||
@ -4247,6 +4247,7 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster)
|
|||||||
{
|
{
|
||||||
Log(Logs::Detail, Logs::Spells, "Our level (%d) is higher than the limit of this Mez spell (%d)", GetLevel(), spells[spell_id].max[effect_index]);
|
Log(Logs::Detail, Logs::Spells, "Our level (%d) is higher than the limit of this Mez spell (%d)", GetLevel(), spells[spell_id].max[effect_index]);
|
||||||
caster->Message_StringID(MT_Shout, CANNOT_MEZ_WITH_SPELL);
|
caster->Message_StringID(MT_Shout, CANNOT_MEZ_WITH_SPELL);
|
||||||
|
AddToHateList(caster, 1,0,true,false,false,spell_id);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4338,6 +4339,7 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster)
|
|||||||
{
|
{
|
||||||
Log(Logs::Detail, Logs::Spells, "Our level (%d) is higher than the limit of this Charm spell (%d)", GetLevel(), spells[spell_id].max[effect_index]);
|
Log(Logs::Detail, Logs::Spells, "Our level (%d) is higher than the limit of this Charm spell (%d)", GetLevel(), spells[spell_id].max[effect_index]);
|
||||||
caster->Message_StringID(MT_Shout, CANNOT_CHARM_YET);
|
caster->Message_StringID(MT_Shout, CANNOT_CHARM_YET);
|
||||||
|
AddToHateList(caster, 1,0,true,false,false,spell_id);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,7 +30,7 @@ bool WaterMapV2::InLava(const glm::vec3& location) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool WaterMapV2::InLiquid(const glm::vec3& location) const {
|
bool WaterMapV2::InLiquid(const glm::vec3& location) const {
|
||||||
return InWater(location) || InLava(location);
|
return InWater(location) || InLava(location) || InVWater(location);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WaterMapV2::InPvP(const glm::vec3& location) const {
|
bool WaterMapV2::InPvP(const glm::vec3& location) const {
|
||||||
|
|||||||
@ -42,19 +42,27 @@ struct wp_distance
|
|||||||
int index;
|
int index;
|
||||||
};
|
};
|
||||||
|
|
||||||
void NPC::AI_SetRoambox(float iDist, float iRoamDist, uint32 iDelay, uint32 iMinDelay) {
|
void NPC::AI_SetRoambox(float max_distance, float roam_distance_variance, uint32 delay, uint32 min_delay) {
|
||||||
AI_SetRoambox(iDist, GetX() + iRoamDist, GetX() - iRoamDist, GetY() + iRoamDist, GetY() - iRoamDist, iDelay, iMinDelay);
|
AI_SetRoambox(
|
||||||
|
max_distance,
|
||||||
|
GetX() + roam_distance_variance,
|
||||||
|
GetX() - roam_distance_variance,
|
||||||
|
GetY() + roam_distance_variance,
|
||||||
|
GetY() - roam_distance_variance,
|
||||||
|
delay,
|
||||||
|
min_delay
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NPC::AI_SetRoambox(float iDist, float iMaxX, float iMinX, float iMaxY, float iMinY, uint32 iDelay, uint32 iMinDelay) {
|
void NPC::AI_SetRoambox(float distance, float max_x, float min_x, float max_y, float min_y, uint32 delay, uint32 min_delay) {
|
||||||
roambox_distance = iDist;
|
roambox_distance = distance;
|
||||||
roambox_max_x = iMaxX;
|
roambox_max_x = max_x;
|
||||||
roambox_min_x = iMinX;
|
roambox_min_x = min_x;
|
||||||
roambox_max_y = iMaxY;
|
roambox_max_y = max_y;
|
||||||
roambox_min_y = iMinY;
|
roambox_min_y = min_y;
|
||||||
roambox_movingto_x = roambox_max_x + 1; // this will trigger a recalc
|
roambox_destination_x = roambox_max_x + 1; // this will trigger a recalc
|
||||||
roambox_delay = iDelay;
|
roambox_delay = delay;
|
||||||
roambox_min_delay = iMinDelay;
|
roambox_min_delay = min_delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NPC::DisplayWaypointInfo(Client *c) {
|
void NPC::DisplayWaypointInfo(Client *c) {
|
||||||
@ -199,7 +207,7 @@ void NPC::MoveTo(const glm::vec4& position, bool saveguardspot)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cur_wp_pause = 0;
|
cur_wp_pause = 0;
|
||||||
pLastFightingDelayMoving = 0;
|
time_until_can_move = 0;
|
||||||
if (AI_walking_timer->Enabled())
|
if (AI_walking_timer->Enabled())
|
||||||
AI_walking_timer->Start(100);
|
AI_walking_timer->Start(100);
|
||||||
}
|
}
|
||||||
@ -438,22 +446,16 @@ float Mob::CalculateDistance(float x, float y, float z) {
|
|||||||
return (float)sqrtf(((m_Position.x - x)*(m_Position.x - x)) + ((m_Position.y - y)*(m_Position.y - y)) + ((m_Position.z - z)*(m_Position.z - z)));
|
return (float)sqrtf(((m_Position.x - x)*(m_Position.x - x)) + ((m_Position.y - y)*(m_Position.y - y)) + ((m_Position.z - z)*(m_Position.z - z)));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, bool checkZ, bool calcHeading) {
|
bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, bool check_z, bool calculate_heading) {
|
||||||
if (GetID() == 0)
|
if (GetID() == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (speed <= 0)
|
if (speed <= 0) {
|
||||||
{
|
|
||||||
SetCurrentSpeed(0);
|
SetCurrentSpeed(0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((m_Position.x - x == 0) && (m_Position.y - y == 0)) { //spawn is at target coords
|
if ((m_Position.x - x == 0) && (m_Position.y - y == 0)) { //spawn is at target coords
|
||||||
if (m_Position.z - z != 0) {
|
|
||||||
m_Position.z = z;
|
|
||||||
Log(Logs::Detail, Logs::AI, "Calc Position2 (%.3f, %.3f, %.3f): Jumping pure Z.", x, y, z);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if ((std::abs(m_Position.x - x) < 0.1) && (std::abs(m_Position.y - y) < 0.1)) {
|
else if ((std::abs(m_Position.x - x) < 0.1) && (std::abs(m_Position.y - y) < 0.1)) {
|
||||||
@ -464,16 +466,17 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo
|
|||||||
m_Position.x = x;
|
m_Position.x = x;
|
||||||
m_Position.y = y;
|
m_Position.y = y;
|
||||||
m_Position.z = z;
|
m_Position.z = z;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool send_update = false;
|
|
||||||
int compare_steps = 20;
|
int compare_steps = 20;
|
||||||
if (tar_ndx < compare_steps && m_TargetLocation.x == x && m_TargetLocation.y == y) {
|
if (tar_ndx < compare_steps && m_TargetLocation.x == x && m_TargetLocation.y == y) {
|
||||||
|
|
||||||
float new_x = m_Position.x + m_TargetV.x * tar_vector;
|
float new_x = m_Position.x + m_TargetV.x * tar_vector;
|
||||||
float new_y = m_Position.y + m_TargetV.y * tar_vector;
|
float new_y = m_Position.y + m_TargetV.y * tar_vector;
|
||||||
float new_z = m_Position.z + m_TargetV.z * tar_vector;
|
float new_z = m_Position.z + m_TargetV.z * tar_vector;
|
||||||
|
|
||||||
if (IsNPC()) {
|
if (IsNPC()) {
|
||||||
entity_list.ProcessMove(CastToNPC(), new_x, new_y, new_z);
|
entity_list.ProcessMove(CastToNPC(), new_x, new_y, new_z);
|
||||||
}
|
}
|
||||||
@ -482,14 +485,14 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo
|
|||||||
m_Position.y = new_y;
|
m_Position.y = new_y;
|
||||||
m_Position.z = new_z;
|
m_Position.z = new_z;
|
||||||
|
|
||||||
if(checkZ && fix_z_timer.Check() &&
|
if (check_z && fix_z_timer.Check() && (!this->IsEngaged() || flee_mode || currently_fleeing)) {
|
||||||
(!this->IsEngaged() || flee_mode || currently_fleeing))
|
|
||||||
this->FixZ();
|
this->FixZ();
|
||||||
|
|
||||||
tar_ndx++;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tar_ndx++;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (tar_ndx > 50) {
|
if (tar_ndx > 50) {
|
||||||
tar_ndx--;
|
tar_ndx--;
|
||||||
@ -497,6 +500,7 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo
|
|||||||
else {
|
else {
|
||||||
tar_ndx = 0;
|
tar_ndx = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_TargetLocation = glm::vec3(x, y, z);
|
m_TargetLocation = glm::vec3(x, y, z);
|
||||||
|
|
||||||
float nx = this->m_Position.x;
|
float nx = this->m_Position.x;
|
||||||
@ -530,10 +534,8 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo
|
|||||||
|
|
||||||
// mob move fix
|
// mob move fix
|
||||||
|
|
||||||
if (numsteps<20)
|
if (numsteps < 20) {
|
||||||
{
|
if (numsteps > 1) {
|
||||||
if (numsteps>1)
|
|
||||||
{
|
|
||||||
tar_vector = 1.0f;
|
tar_vector = 1.0f;
|
||||||
m_TargetV.x = m_TargetV.x / (float) numsteps;
|
m_TargetV.x = m_TargetV.x / (float) numsteps;
|
||||||
m_TargetV.y = m_TargetV.y / (float) numsteps;
|
m_TargetV.y = m_TargetV.y / (float) numsteps;
|
||||||
@ -549,12 +551,12 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo
|
|||||||
m_Position.x = new_x;
|
m_Position.x = new_x;
|
||||||
m_Position.y = new_y;
|
m_Position.y = new_y;
|
||||||
m_Position.z = new_z;
|
m_Position.z = new_z;
|
||||||
if (calcHeading)
|
if (calculate_heading) {
|
||||||
m_Position.w = CalculateHeadingToTarget(x, y);
|
m_Position.w = CalculateHeadingToTarget(x, y);
|
||||||
|
}
|
||||||
tar_ndx = 20 - numsteps;
|
tar_ndx = 20 - numsteps;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
if (IsNPC()) {
|
if (IsNPC()) {
|
||||||
entity_list.ProcessMove(CastToNPC(), x, y, z);
|
entity_list.ProcessMove(CastToNPC(), x, y, z);
|
||||||
}
|
}
|
||||||
@ -581,6 +583,7 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo
|
|||||||
float new_x = m_Position.x + m_TargetV.x * tar_vector;
|
float new_x = m_Position.x + m_TargetV.x * tar_vector;
|
||||||
float new_y = m_Position.y + m_TargetV.y * tar_vector;
|
float new_y = m_Position.y + m_TargetV.y * tar_vector;
|
||||||
float new_z = m_Position.z + m_TargetV.z * tar_vector;
|
float new_z = m_Position.z + m_TargetV.z * tar_vector;
|
||||||
|
|
||||||
if (IsNPC()) {
|
if (IsNPC()) {
|
||||||
entity_list.ProcessMove(CastToNPC(), new_x, new_y, new_z);
|
entity_list.ProcessMove(CastToNPC(), new_x, new_y, new_z);
|
||||||
}
|
}
|
||||||
@ -588,11 +591,12 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo
|
|||||||
m_Position.x = new_x;
|
m_Position.x = new_x;
|
||||||
m_Position.y = new_y;
|
m_Position.y = new_y;
|
||||||
m_Position.z = new_z;
|
m_Position.z = new_z;
|
||||||
if (calcHeading)
|
if (calculate_heading) {
|
||||||
m_Position.w = CalculateHeadingToTarget(x, y);
|
m_Position.w = CalculateHeadingToTarget(x, y);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (checkZ && fix_z_timer.Check() && !this->IsEngaged())
|
if (check_z && fix_z_timer.Check() && !this->IsEngaged())
|
||||||
this->FixZ();
|
this->FixZ();
|
||||||
|
|
||||||
SetMoving(true);
|
SetMoving(true);
|
||||||
@ -600,13 +604,11 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo
|
|||||||
|
|
||||||
m_Delta = glm::vec4(m_Position.x - nx, m_Position.y - ny, m_Position.z - nz, 0.0f);
|
m_Delta = glm::vec4(m_Position.x - nx, m_Position.y - ny, m_Position.z - nz, 0.0f);
|
||||||
|
|
||||||
if (IsClient())
|
if (IsClient()) {
|
||||||
{
|
|
||||||
SendPositionUpdate(1);
|
SendPositionUpdate(1);
|
||||||
CastToClient()->ResetPositionTimer();
|
CastToClient()->ResetPositionTimer();
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
SendPositionUpdate();
|
SendPositionUpdate();
|
||||||
SetAppearance(eaStanding, false);
|
SetAppearance(eaStanding, false);
|
||||||
}
|
}
|
||||||
@ -615,8 +617,8 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mob::CalculateNewPosition(float x, float y, float z, int speed, bool checkZ, bool calcHeading) {
|
bool Mob::CalculateNewPosition(float x, float y, float z, float speed, bool check_z, bool calculate_heading) {
|
||||||
return MakeNewPositionAndSendUpdate(x, y, z, speed);
|
return MakeNewPositionAndSendUpdate(x, y, z, speed, check_z);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NPC::AssignWaypoints(int32 grid)
|
void NPC::AssignWaypoints(int32 grid)
|
||||||
@ -746,10 +748,11 @@ void Mob::SendToFixZ(float new_x, float new_y, float new_z) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float Mob::GetFixedZ(glm::vec3 dest, int32 z_find_offset) {
|
float Mob::GetFixedZ(glm::vec3 destination, int32 z_find_offset) {
|
||||||
BenchTimer timer;
|
BenchTimer timer;
|
||||||
timer.reset();
|
timer.reset();
|
||||||
float new_z = dest.z;
|
|
||||||
|
float new_z = destination.z;
|
||||||
|
|
||||||
if (zone->HasMap() && RuleB(Map, FixZWhenMoving)) {
|
if (zone->HasMap() && RuleB(Map, FixZWhenMoving)) {
|
||||||
|
|
||||||
@ -765,7 +768,7 @@ float Mob::GetFixedZ(glm::vec3 dest, int32 z_find_offset) {
|
|||||||
/*
|
/*
|
||||||
* Any more than 5 in the offset makes NPC's hop/snap to ceiling in small corridors
|
* Any more than 5 in the offset makes NPC's hop/snap to ceiling in small corridors
|
||||||
*/
|
*/
|
||||||
new_z = this->FindDestGroundZ(dest, z_find_offset);
|
new_z = this->FindDestGroundZ(destination, z_find_offset);
|
||||||
if (new_z != BEST_Z_INVALID) {
|
if (new_z != BEST_Z_INVALID) {
|
||||||
new_z += this->GetZOffset();
|
new_z += this->GetZOffset();
|
||||||
|
|
||||||
@ -776,31 +779,48 @@ float Mob::GetFixedZ(glm::vec3 dest, int32 z_find_offset) {
|
|||||||
|
|
||||||
auto duration = timer.elapsed();
|
auto duration = timer.elapsed();
|
||||||
|
|
||||||
Log(Logs::Moderate, Logs::FixZ,
|
Log(Logs::Moderate,
|
||||||
|
Logs::FixZ,
|
||||||
"Mob::GetFixedZ() (%s) returned %4.3f at %4.3f, %4.3f, %4.3f - Took %lf",
|
"Mob::GetFixedZ() (%s) returned %4.3f at %4.3f, %4.3f, %4.3f - Took %lf",
|
||||||
this->GetCleanName(), new_z, dest.x, dest.y, dest.z, duration);
|
this->GetCleanName(),
|
||||||
|
new_z,
|
||||||
|
destination.x,
|
||||||
|
destination.y,
|
||||||
|
destination.z,
|
||||||
|
duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new_z;
|
return new_z;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mob::FixZ(int32 z_find_offset /*= 5*/) {
|
void Mob::FixZ(int32 z_find_offset /*= 5*/, bool fix_client_z /*= false*/) {
|
||||||
glm::vec3 current_loc(m_Position);
|
glm::vec3 current_loc(m_Position);
|
||||||
|
|
||||||
|
if (IsClient() && !fix_client_z)
|
||||||
|
return;
|
||||||
|
|
||||||
float new_z = GetFixedZ(current_loc, z_find_offset);
|
float new_z = GetFixedZ(current_loc, z_find_offset);
|
||||||
|
|
||||||
if (!IsClient() && new_z != m_Position.z) {
|
if (new_z == m_Position.z)
|
||||||
|
return;
|
||||||
|
|
||||||
if ((new_z > -2000) && new_z != BEST_Z_INVALID) {
|
if ((new_z > -2000) && new_z != BEST_Z_INVALID) {
|
||||||
if (RuleB(Map, MobZVisualDebug))
|
if (RuleB(Map, MobZVisualDebug)) {
|
||||||
this->SendAppearanceEffect(78, 0, 0, 0, 0);
|
this->SendAppearanceEffect(78, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
m_Position.z = new_z;
|
m_Position.z = new_z;
|
||||||
} else {
|
|
||||||
if (RuleB(Map, MobZVisualDebug))
|
|
||||||
this->SendAppearanceEffect(103, 0, 0, 0, 0);
|
|
||||||
|
|
||||||
Log(Logs::General, Logs::FixZ, "%s is failing to find Z %f",
|
|
||||||
this->GetCleanName(), std::abs(m_Position.z - new_z));
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
if (RuleB(Map, MobZVisualDebug)) {
|
||||||
|
this->SendAppearanceEffect(103, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log(Logs::General,
|
||||||
|
Logs::FixZ,
|
||||||
|
"%s is failing to find Z %f",
|
||||||
|
this->GetCleanName(),
|
||||||
|
std::abs(m_Position.z - new_z));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -143,7 +143,11 @@ bool ZoneDatabase::GetZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct
|
|||||||
"snow_duration2, " // 53
|
"snow_duration2, " // 53
|
||||||
"snow_duration3, " // 54
|
"snow_duration3, " // 54
|
||||||
"snow_duration4, " // 55
|
"snow_duration4, " // 55
|
||||||
"gravity " // 56
|
"gravity, " // 56
|
||||||
|
"fast_regen_hp, " // 57
|
||||||
|
"fast_regen_mana, " // 58
|
||||||
|
"fast_regen_endurance, " // 59
|
||||||
|
"npc_max_aggro_dist " // 60
|
||||||
"FROM zone WHERE zoneidnumber = %i AND version = %i",
|
"FROM zone WHERE zoneidnumber = %i AND version = %i",
|
||||||
zoneid, instance_id);
|
zoneid, instance_id);
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
@ -188,6 +192,11 @@ bool ZoneDatabase::GetZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct
|
|||||||
Log(Logs::General, Logs::Debug, "Zone Gravity is %f", zone_data->gravity);
|
Log(Logs::General, Logs::Debug, "Zone Gravity is %f", zone_data->gravity);
|
||||||
allow_mercs = true;
|
allow_mercs = true;
|
||||||
|
|
||||||
|
zone_data->FastRegenHP = atoi(row[57]);
|
||||||
|
zone_data->FastRegenMana = atoi(row[58]);
|
||||||
|
zone_data->FastRegenEndurance = atoi(row[59]);
|
||||||
|
zone_data->NPCAggroMaxDist = atoi(row[60]);
|
||||||
|
|
||||||
int bindable = 0;
|
int bindable = 0;
|
||||||
bindable = atoi(row[31]);
|
bindable = atoi(row[31]);
|
||||||
|
|
||||||
|
|||||||
@ -717,6 +717,10 @@ void Client::GoToSafeCoords(uint16 zone_id, uint16 instance_id) {
|
|||||||
|
|
||||||
void Mob::Gate(uint8 bindnum) {
|
void Mob::Gate(uint8 bindnum) {
|
||||||
GoToBind(bindnum);
|
GoToBind(bindnum);
|
||||||
|
if (RuleB(NPC, NPCHealOnGate) && this->IsNPC() && this->GetHPRatio() <= RuleR(NPC, NPCHealOnGateAmount)) {
|
||||||
|
auto HealAmount = (RuleR(NPC, NPCHealOnGateAmount) / 100);
|
||||||
|
SetHP(int(this->GetMaxHP() * HealAmount));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::Gate(uint8 bindnum) {
|
void Client::Gate(uint8 bindnum) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user