mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 21:01:29 +00:00
Merge fix
This commit is contained in:
commit
1d1ee1ccbf
@ -1,6 +1,7 @@
|
||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||
-------------------------------------------------------
|
||||
== 4/1/2017 ==
|
||||
Akkadius: Cleaned up some of the NPC to NPC aggro code, only do aggro checks to other NPC's when the NPC is flagged for it
|
||||
Akkadius: [Performance] Reworked how all log calls are made in the source
|
||||
- Before we used Log.Out, we will now use a macro Log(
|
||||
- Before: Log.Out(Logs::General, Logs::Status, "Importing Spells...");
|
||||
|
||||
@ -49,7 +49,7 @@ namespace EQEmu
|
||||
};
|
||||
|
||||
enum DeityTypeBit : uint32 {
|
||||
bit_DeityAll = 0x00000000,
|
||||
bit_DeityNone = 0x00000000,
|
||||
bit_DeityAgnostic = 0x00000001,
|
||||
bit_DeityBertoxxulous = 0x00000002,
|
||||
bit_DeityBrellSirilis = 0x00000004,
|
||||
@ -66,7 +66,8 @@ namespace EQEmu
|
||||
bit_DeitySolusekRo = 0x00002000,
|
||||
bit_DeityTheTribunal = 0x00004000,
|
||||
bit_DeityTunare = 0x00008000,
|
||||
bit_DeityVeeshan = 0x00010000
|
||||
bit_DeityVeeshan = 0x00010000,
|
||||
bit_DeityAll = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
extern DeityTypeBit ConvertDeityTypeToDeityTypeBit(DeityType deity_type);
|
||||
|
||||
@ -105,6 +105,15 @@ void EQEmuLogSys::LoadLogSettingsDefaults()
|
||||
log_settings[Logs::Login_Server].log_to_console = Logs::General;
|
||||
log_settings[Logs::Headless_Client].log_to_console = Logs::General;
|
||||
|
||||
/* Set Category enabled status on defaults */
|
||||
log_settings[Logs::World_Server].is_category_enabled = 1;
|
||||
log_settings[Logs::Zone_Server].is_category_enabled = 1;
|
||||
log_settings[Logs::QS_Server].is_category_enabled = 1;
|
||||
log_settings[Logs::UCS_Server].is_category_enabled = 1;
|
||||
log_settings[Logs::Crash].is_category_enabled = 1;
|
||||
log_settings[Logs::MySQLError].is_category_enabled = 1;
|
||||
log_settings[Logs::Login_Server].is_category_enabled = 1;
|
||||
|
||||
/* Declare process file names for log writing
|
||||
If there is no process_file_name declared, no log file will be written, simply
|
||||
*/
|
||||
|
||||
@ -111,9 +111,6 @@ Zone extensions and features
|
||||
//path to where sql logs should be placed
|
||||
#define SQL_LOG_PATH "sql_logs/"
|
||||
|
||||
//New aggro system to reduce overhead.
|
||||
#define REVERSE_AGGRO
|
||||
|
||||
//The highest you can #setskill / #setallskill
|
||||
#define HIGHEST_CAN_SET_SKILL 400
|
||||
|
||||
|
||||
@ -241,48 +241,70 @@ EQEmu::ItemInstance* EQEmu::InventoryProfile::GetCursorItem()
|
||||
}
|
||||
|
||||
// Swap items in inventory
|
||||
bool EQEmu::InventoryProfile::SwapItem(int16 slot_a, int16 slot_b, uint16 race_id, uint8 class_id, uint16 deity_id, uint8 level)
|
||||
bool EQEmu::InventoryProfile::SwapItem(int16 slot_a, int16 slot_b, SwapItemFailState& fail_state, uint16 race_id, uint8 class_id, uint16 deity_id, uint8 level)
|
||||
{
|
||||
fail_state = swapInvalid;
|
||||
|
||||
// Temp holding areas for a and b
|
||||
ItemInstance* inst_a = GetItem(slot_a);
|
||||
ItemInstance* inst_b = GetItem(slot_b);
|
||||
|
||||
if (inst_a) {
|
||||
if (!inst_a->IsSlotAllowed(slot_b))
|
||||
if (!inst_a->IsSlotAllowed(slot_b)) {
|
||||
fail_state = swapNotAllowed;
|
||||
return false;
|
||||
|
||||
}
|
||||
if ((slot_b >= legacy::EQUIPMENT_BEGIN && slot_b <= legacy::EQUIPMENT_END) || slot_b == inventory::slotPowerSource) {
|
||||
auto item_a = inst_a->GetItem();
|
||||
if (!item_a)
|
||||
if (!item_a) {
|
||||
fail_state = swapNullData;
|
||||
return false;
|
||||
if (race_id && class_id && !item_a->IsEquipable(race_id, class_id))
|
||||
}
|
||||
if (race_id && class_id && !item_a->IsEquipable(race_id, class_id)) {
|
||||
fail_state = swapRaceClass;
|
||||
return false;
|
||||
if (deity_id && item_a->Deity && !(deity::ConvertDeityTypeToDeityTypeBit((deity::DeityType)deity_id) & item_a->Deity))
|
||||
}
|
||||
if (deity_id && item_a->Deity && !(deity::ConvertDeityTypeToDeityTypeBit((deity::DeityType)deity_id) & item_a->Deity)) {
|
||||
fail_state = swapDeity;
|
||||
return false;
|
||||
if (level && item_a->ReqLevel && level < item_a->ReqLevel)
|
||||
}
|
||||
if (level && item_a->ReqLevel && level < item_a->ReqLevel) {
|
||||
fail_state = swapLevel;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (inst_b) {
|
||||
if (!inst_b->IsSlotAllowed(slot_a))
|
||||
if (!inst_b->IsSlotAllowed(slot_a)) {
|
||||
fail_state = swapNotAllowed;
|
||||
return false;
|
||||
|
||||
}
|
||||
if ((slot_a >= legacy::EQUIPMENT_BEGIN && slot_a <= legacy::EQUIPMENT_END) || slot_a == inventory::slotPowerSource) {
|
||||
auto item_b = inst_b->GetItem();
|
||||
if (!item_b)
|
||||
if (!item_b) {
|
||||
fail_state = swapNullData;
|
||||
return false;
|
||||
if (race_id && class_id && !item_b->IsEquipable(race_id, class_id))
|
||||
}
|
||||
if (race_id && class_id && !item_b->IsEquipable(race_id, class_id)) {
|
||||
fail_state = swapRaceClass;
|
||||
return false;
|
||||
if (deity_id && item_b->Deity && !(deity::ConvertDeityTypeToDeityTypeBit((deity::DeityType)deity_id) & item_b->Deity))
|
||||
}
|
||||
if (deity_id && item_b->Deity && !(deity::ConvertDeityTypeToDeityTypeBit((deity::DeityType)deity_id) & item_b->Deity)) {
|
||||
fail_state = swapDeity;
|
||||
return false;
|
||||
if (level && item_b->ReqLevel && level < item_b->ReqLevel)
|
||||
}
|
||||
if (level && item_b->ReqLevel && level < item_b->ReqLevel) {
|
||||
fail_state = swapLevel;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_PutItem(slot_a, inst_b); // Copy b->a
|
||||
_PutItem(slot_b, inst_a); // Copy a->b
|
||||
_PutItem(slot_a, inst_b); // Assign b->a
|
||||
_PutItem(slot_b, inst_a); // Assign a->b
|
||||
|
||||
fail_state = swapPass;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -85,15 +85,22 @@ namespace EQEmu
|
||||
// Public Methods
|
||||
///////////////////////////////
|
||||
|
||||
InventoryProfile() { m_mob_version = versions::MobVersion::Unknown; m_mob_version_set = false; }
|
||||
InventoryProfile() {
|
||||
m_mob_version = versions::MobVersion::Unknown;
|
||||
m_mob_version_set = false;
|
||||
m_lookup = inventory::Lookup(versions::MobVersion::Unknown);
|
||||
}
|
||||
~InventoryProfile();
|
||||
|
||||
bool SetInventoryVersion(versions::MobVersion inventory_version) {
|
||||
if (!m_mob_version_set) {
|
||||
m_mob_version = versions::ValidateMobVersion(inventory_version);
|
||||
return (m_mob_version_set = true);
|
||||
m_lookup = inventory::Lookup(m_mob_version);
|
||||
m_mob_version_set = true;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
m_lookup = inventory::Lookup(versions::MobVersion::Unknown);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -127,7 +134,8 @@ namespace EQEmu
|
||||
ItemInstance* GetCursorItem();
|
||||
|
||||
// Swap items in inventory
|
||||
bool SwapItem(int16 slot_a, int16 slot_b, uint16 race_id = 0, uint8 class_id = 0, uint16 deity_id = 0, uint8 level = 0);
|
||||
enum SwapItemFailState : int8 { swapInvalid = -1, swapPass = 0, swapNotAllowed, swapNullData, swapRaceClass, swapDeity, swapLevel };
|
||||
bool SwapItem(int16 slot_a, int16 slot_b, SwapItemFailState& fail_state, uint16 race_id = 0, uint8 class_id = 0, uint16 deity_id = 0, uint8 level = 0);
|
||||
|
||||
// Remove item from inventory
|
||||
bool DeleteItem(int16 slot_id, uint8 quantity = 0);
|
||||
@ -224,6 +232,7 @@ namespace EQEmu
|
||||
// Active mob version
|
||||
versions::MobVersion m_mob_version;
|
||||
bool m_mob_version_set;
|
||||
const inventory::LookupEntry* m_lookup;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -22,7 +22,8 @@
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
enum { //values for pTimerType
|
||||
enum : int { //values for pTimerType
|
||||
pTimerNegativeItemReuse = -1, // these grow down basically, we will have item ID * -1 for the timer ID
|
||||
pTimerStartAdventureTimer = 1,
|
||||
pTimerSurnameChange = 2,
|
||||
pTimerFeignDeath = 3,
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
||||
*/
|
||||
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9107
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9110
|
||||
#ifdef BOTS
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9017
|
||||
#else
|
||||
|
||||
@ -44,6 +44,7 @@ int main()
|
||||
LogSys.LoadLogSettingsDefaults();
|
||||
|
||||
LogSys.log_settings[Logs::Error].log_to_console = Logs::General;
|
||||
LogSys.log_settings[Logs::Error].is_category_enabled = 1;
|
||||
|
||||
Log(Logs::General, Logs::Login_Server, "Logging System Init.");
|
||||
|
||||
|
||||
@ -361,6 +361,9 @@
|
||||
9105|2017_02_15_bot_spells_entries.sql|SELECT `id` FROM `npc_spells_entries` WHERE `npc_spells_id` >= 701 AND `npc_spells_id` <= 712|not_empty|
|
||||
9106|2017_02_26_npc_spells_update_for_bots.sql|SELECT * FROM `npc_spells` WHERE `id` = '701' AND `name` = 'Cleric Bot'|not_empty|
|
||||
9107|2017_03_09_inventory_version.sql|SHOW TABLES LIKE 'inventory_version'|empty|
|
||||
9108|2017_04_07_ignore_despawn.sql|SHOW COLUMNS FROM `npc_types` LIKE 'ignore_despawn'|empty|
|
||||
9109|2017_04_08_doors_disable_timer.sql|SHOW COLUMNS FROM `doors` LIKE 'disable_timer'|empty|
|
||||
9110|2017_04_10_graveyard.sql|show index from graveyard WHERE key_name = 'zone_id_nonunique'|empty|
|
||||
|
||||
# Upgrade conditions:
|
||||
# This won't be needed after this system is implemented, but it is used database that are not
|
||||
|
||||
1
utils/sql/git/required/2017_04_07_ignore_despawn.sql
Normal file
1
utils/sql/git/required/2017_04_07_ignore_despawn.sql
Normal file
@ -0,0 +1 @@
|
||||
alter table npc_types add column `ignore_despawn` tinyint(2) not null default 0;
|
||||
@ -0,0 +1 @@
|
||||
ALTER TABLE `doors` ADD COLUMN `disable_timer` TINYINT(2) NOT NULL DEFAULT '0' AFTER `triggertype`;
|
||||
2
utils/sql/git/required/2017_04_10_graveyard.sql
Normal file
2
utils/sql/git/required/2017_04_10_graveyard.sql
Normal file
@ -0,0 +1,2 @@
|
||||
alter table graveyard drop index zone_id;
|
||||
create index zone_id_nonunique on graveyard(zone_id);
|
||||
@ -162,6 +162,7 @@ SET(zone_headers
|
||||
lua_bit.h
|
||||
lua_client.h
|
||||
lua_corpse.h
|
||||
lua_door.h
|
||||
lua_encounter.h
|
||||
lua_entity.h
|
||||
lua_entity_list.h
|
||||
|
||||
@ -408,25 +408,19 @@ bool Mob::CheckWillAggro(Mob *mob) {
|
||||
return(false);
|
||||
}
|
||||
|
||||
Mob* EntityList::AICheckCloseAggro(Mob* sender, float iAggroRange, float iAssistRange) {
|
||||
Mob* EntityList::AICheckNPCtoNPCAggro(Mob* sender, float iAggroRange, float iAssistRange) {
|
||||
if (!sender || !sender->IsNPC())
|
||||
return(nullptr);
|
||||
|
||||
#ifdef REVERSE_AGGRO
|
||||
//with reverse aggro, npc->client is checked elsewhere, no need to check again
|
||||
auto it = npc_list.begin();
|
||||
while (it != npc_list.end()) {
|
||||
#else
|
||||
auto it = mob_list.begin();
|
||||
while (it != mob_list.end()) {
|
||||
#endif
|
||||
Mob *mob = it->second;
|
||||
|
||||
if (sender->CheckWillAggro(mob))
|
||||
return mob;
|
||||
++it;
|
||||
}
|
||||
//LogFile->write(EQEMuLog::Debug, "Check aggro for %s no target.", sender->GetName());
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@ -3974,16 +3974,9 @@ void Mob::TrySpellProc(const EQEmu::ItemInstance *inst, const EQEmu::ItemData *w
|
||||
float chance = ProcChance * (static_cast<float>(SpellProcs[i].chance) / 100.0f);
|
||||
if (zone->random.Roll(chance)) {
|
||||
Log(Logs::Detail, Logs::Combat,
|
||||
"Spell proc %d procing spell %d (%.2f percent chance)",
|
||||
i, SpellProcs[i].spellID, chance);
|
||||
auto outapp = new EQApplicationPacket(OP_BeginCast, sizeof(BeginCast_Struct));
|
||||
BeginCast_Struct* begincast = (BeginCast_Struct*)outapp->pBuffer;
|
||||
begincast->caster_id = GetID();
|
||||
begincast->spell_id = SpellProcs[i].spellID;
|
||||
begincast->cast_time = 0;
|
||||
outapp->priority = 3;
|
||||
entity_list.QueueCloseClients(this, outapp, false, RuleI(Range, SpellMessages), 0, true);
|
||||
safe_delete(outapp);
|
||||
"Spell proc %d procing spell %d (%.2f percent chance)",
|
||||
i, SpellProcs[i].spellID, chance);
|
||||
SendBeginCast(SpellProcs[i].spellID, 0);
|
||||
ExecWeaponProc(nullptr, SpellProcs[i].spellID, on, SpellProcs[i].level_override);
|
||||
CheckNumHitsRemaining(NumHit::OffensiveSpellProcs, 0,
|
||||
SpellProcs[i].base_spellID);
|
||||
|
||||
@ -134,9 +134,7 @@ Client::Client(EQStreamInterface* ieqs)
|
||||
endupkeep_timer(1000),
|
||||
forget_timer(0),
|
||||
autosave_timer(RuleI(Character, AutosaveIntervalS) * 1000),
|
||||
#ifdef REVERSE_AGGRO
|
||||
client_scan_npc_aggro_timer(RuleI(Aggro, ClientAggroCheckInterval) * 1000),
|
||||
#endif
|
||||
tribute_timer(Tribute_duration),
|
||||
proximity_timer(ClientProximity_interval),
|
||||
TaskPeriodic_Timer(RuleI(TaskSystem, PeriodicCheckTimer) * 1000),
|
||||
|
||||
@ -1460,9 +1460,7 @@ private:
|
||||
Timer endupkeep_timer;
|
||||
Timer forget_timer; // our 2 min everybody forgets you timer
|
||||
Timer autosave_timer;
|
||||
#ifdef REVERSE_AGGRO
|
||||
Timer client_scan_npc_aggro_timer;
|
||||
#endif
|
||||
Timer tribute_timer;
|
||||
|
||||
Timer proximity_timer;
|
||||
|
||||
@ -614,7 +614,6 @@ bool Client::Process() {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef REVERSE_AGGRO
|
||||
//At this point, we are still connected, everything important has taken
|
||||
//place, now check to see if anybody wants to aggro us.
|
||||
// only if client is not feigned
|
||||
@ -630,7 +629,6 @@ bool Client::Process() {
|
||||
}
|
||||
Log(Logs::General, Logs::Aggro, "Checking Reverse Aggro (client->npc) scanned_npcs (%i)", npc_scan_count);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (client_state != CLIENT_LINKDEAD && (client_state == CLIENT_ERROR || client_state == DISCONNECTED || client_state == CLIENT_KICKED || !eqs->CheckState(ESTABLISHED)))
|
||||
{
|
||||
|
||||
150
zone/doors.cpp
150
zone/doors.cpp
@ -70,6 +70,8 @@ m_Destination(door->dest_x, door->dest_y, door->dest_z, door->dest_heading)
|
||||
|
||||
is_ldon_door = door->is_ldon_door;
|
||||
client_version_mask = door->client_version_mask;
|
||||
|
||||
disable_timer = (door->disable_timer == 1 ? true : false);
|
||||
}
|
||||
|
||||
Doors::Doors(const char *dmodel, const glm::vec4& position, uint8 dopentype, uint16 dsize) :
|
||||
@ -102,6 +104,8 @@ m_Destination(glm::vec4())
|
||||
|
||||
is_ldon_door = 0;
|
||||
client_version_mask = 4294967295u;
|
||||
|
||||
disable_timer = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -135,7 +139,7 @@ void Doors::HandleClick(Client* sender, uint8 trigger)
|
||||
//door debugging info dump
|
||||
Log(Logs::Detail, Logs::Doors, "%s clicked door %s (dbid %d, eqid %d) at %s", sender->GetName(), door_name, db_id, door_id, to_string(m_Position).c_str());
|
||||
Log(Logs::Detail, Logs::Doors, " incline %d, opentype %d, lockpick %d, key %d, nokeyring %d, trigger %d type %d, param %d", incline, opentype, lockpick, keyitem, nokeyring, trigger_door, trigger_type, door_param);
|
||||
Log(Logs::Detail, Logs::Doors, " size %d, invert %d, dest: %s %s", size, invert_state, dest_zone, to_string(m_Destination).c_str());
|
||||
Log(Logs::Detail, Logs::Doors, " disable_timer '%s',size %d, invert %d, dest: %s %s", (disable_timer?"true":"false"), size, invert_state, dest_zone, to_string(m_Destination).c_str());
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct));
|
||||
MoveDoor_Struct* md = (MoveDoor_Struct*)outapp->pBuffer;
|
||||
@ -354,13 +358,15 @@ void Doors::HandleClick(Client* sender, uint8 trigger)
|
||||
entity_list.QueueClients(sender, outapp, false);
|
||||
if(!IsDoorOpen() || (opentype == 58))
|
||||
{
|
||||
close_timer.Start();
|
||||
if (!disable_timer)
|
||||
close_timer.Start();
|
||||
SetOpenState(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
close_timer.Disable();
|
||||
SetOpenState(false);
|
||||
if (!disable_timer)
|
||||
SetOpenState(false);
|
||||
}
|
||||
|
||||
//everything past this point assumes we opened the door
|
||||
@ -443,31 +449,34 @@ void Doors::HandleClick(Client* sender, uint8 trigger)
|
||||
|
||||
void Doors::NPCOpen(NPC* sender, bool alt_mode)
|
||||
{
|
||||
if(sender) {
|
||||
if(GetTriggerType() == 255 || GetTriggerDoorID() > 0 || GetLockpick() != 0 || GetKeyItem() != 0 || opentype == 59 || opentype == 58 || !sender->IsNPC()) { // this object isnt triggered or door is locked - NPCs should not open locked doors!
|
||||
if (sender) {
|
||||
if (GetTriggerType() == 255 || GetTriggerDoorID() > 0 || GetLockpick() != 0 || GetKeyItem() != 0 || opentype == 59 || opentype == 58 || !sender->IsNPC()) { // this object isnt triggered or door is locked - NPCs should not open locked doors!
|
||||
return;
|
||||
}
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct));
|
||||
MoveDoor_Struct* md=(MoveDoor_Struct*)outapp->pBuffer;
|
||||
MoveDoor_Struct* md = (MoveDoor_Struct*)outapp->pBuffer;
|
||||
md->doorid = door_id;
|
||||
md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR;
|
||||
entity_list.QueueCloseClients(sender,outapp,false,200);
|
||||
entity_list.QueueCloseClients(sender, outapp, false, 200);
|
||||
safe_delete(outapp);
|
||||
|
||||
if(!alt_mode) { // original function
|
||||
if(!isopen) {
|
||||
close_timer.Start();
|
||||
isopen=true;
|
||||
if (!alt_mode) { // original function
|
||||
if (!is_open) {
|
||||
if (!disable_timer)
|
||||
close_timer.Start();
|
||||
is_open = true;
|
||||
}
|
||||
else {
|
||||
close_timer.Disable();
|
||||
isopen=false;
|
||||
if (!disable_timer)
|
||||
is_open = false;
|
||||
}
|
||||
}
|
||||
else { // alternative function
|
||||
close_timer.Start();
|
||||
isopen=true;
|
||||
if (!disable_timer)
|
||||
close_timer.Start();
|
||||
is_open = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -475,49 +484,53 @@ void Doors::NPCOpen(NPC* sender, bool alt_mode)
|
||||
void Doors::ForceOpen(Mob *sender, bool alt_mode)
|
||||
{
|
||||
auto outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct));
|
||||
MoveDoor_Struct* md=(MoveDoor_Struct*)outapp->pBuffer;
|
||||
MoveDoor_Struct* md = (MoveDoor_Struct*)outapp->pBuffer;
|
||||
md->doorid = door_id;
|
||||
md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR;
|
||||
entity_list.QueueClients(sender,outapp,false);
|
||||
entity_list.QueueClients(sender, outapp, false);
|
||||
safe_delete(outapp);
|
||||
|
||||
if(!alt_mode) { // original function
|
||||
if(!isopen) {
|
||||
close_timer.Start();
|
||||
isopen=true;
|
||||
if (!alt_mode) { // original function
|
||||
if (!is_open) {
|
||||
if (!disable_timer)
|
||||
close_timer.Start();
|
||||
is_open = true;
|
||||
}
|
||||
else {
|
||||
close_timer.Disable();
|
||||
isopen=false;
|
||||
if (!disable_timer)
|
||||
is_open = false;
|
||||
}
|
||||
}
|
||||
else { // alternative function
|
||||
close_timer.Start();
|
||||
isopen=true;
|
||||
if (!disable_timer)
|
||||
close_timer.Start();
|
||||
is_open = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Doors::ForceClose(Mob *sender, bool alt_mode)
|
||||
{
|
||||
auto outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct));
|
||||
MoveDoor_Struct* md=(MoveDoor_Struct*)outapp->pBuffer;
|
||||
MoveDoor_Struct* md = (MoveDoor_Struct*)outapp->pBuffer;
|
||||
md->doorid = door_id;
|
||||
md->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR; // change from original (open to close)
|
||||
entity_list.QueueClients(sender,outapp,false);
|
||||
entity_list.QueueClients(sender, outapp, false);
|
||||
safe_delete(outapp);
|
||||
|
||||
if(!alt_mode) { // original function
|
||||
if(!isopen) {
|
||||
close_timer.Start();
|
||||
isopen=true;
|
||||
if (!alt_mode) { // original function
|
||||
if (!is_open) {
|
||||
if (!disable_timer)
|
||||
close_timer.Start();
|
||||
is_open = true;
|
||||
}
|
||||
else {
|
||||
close_timer.Disable();
|
||||
isopen=false;
|
||||
is_open = false;
|
||||
}
|
||||
}
|
||||
else { // alternative function
|
||||
if(isopen)
|
||||
if (is_open)
|
||||
close_timer.Trigger();
|
||||
}
|
||||
}
|
||||
@ -532,14 +545,14 @@ void Doors::ToggleState(Mob *sender)
|
||||
MoveDoor_Struct* md=(MoveDoor_Struct*)outapp->pBuffer;
|
||||
md->doorid = door_id;
|
||||
|
||||
if(!isopen) {
|
||||
if(!is_open) {
|
||||
md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR;
|
||||
isopen=true;
|
||||
is_open=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
md->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR;
|
||||
isopen=false;
|
||||
is_open=false;
|
||||
}
|
||||
|
||||
entity_list.QueueClients(sender,outapp,false);
|
||||
@ -552,7 +565,7 @@ void Doors::DumpDoor(){
|
||||
db_id, door_id, zone_name, door_name, to_string(m_Position).c_str());
|
||||
Log(Logs::General, Logs::None,
|
||||
"opentype:%i guild_id:%i lockpick:%i keyitem:%i nokeyring:%i trigger_door:%i trigger_type:%i door_param:%i open:%s",
|
||||
opentype, guild_id, lockpick, keyitem, nokeyring, trigger_door, trigger_type, door_param, (isopen) ? "open":"closed");
|
||||
opentype, guild_id, lockpick, keyitem, nokeyring, trigger_door, trigger_type, door_param, (is_open) ? "open":"closed");
|
||||
Log(Logs::General, Logs::None,
|
||||
"dest_zone:%s destination:%s ",
|
||||
dest_zone, to_string(m_Destination).c_str());
|
||||
@ -632,34 +645,32 @@ bool ZoneDatabase::LoadDoors(int32 iDoorCount, Door *into, const char *zone_name
|
||||
Log(Logs::General, Logs::Status, "Loading Doors from database...");
|
||||
|
||||
|
||||
// Door tmpDoor;
|
||||
std::string query = StringFormat("SELECT id, doorid, zone, name, pos_x, pos_y, pos_z, heading, "
|
||||
"opentype, guild, lockpick, keyitem, nokeyring, triggerdoor, triggertype, "
|
||||
"dest_zone, dest_instance, dest_x, dest_y, dest_z, dest_heading, "
|
||||
"door_param, invert_state, incline, size, is_ldon_door, client_version_mask "
|
||||
"FROM doors WHERE zone = '%s' AND (version = %u OR version = -1) "
|
||||
"ORDER BY doorid asc", zone_name, version);
|
||||
// Door tmpDoor;
|
||||
std::string query = StringFormat("SELECT id, doorid, zone, name, pos_x, pos_y, pos_z, heading, "
|
||||
"opentype, guild, lockpick, keyitem, nokeyring, triggerdoor, triggertype, "
|
||||
"dest_zone, dest_instance, dest_x, dest_y, dest_z, dest_heading, "
|
||||
"door_param, invert_state, incline, size, is_ldon_door, client_version_mask, disable_timer "
|
||||
"FROM doors WHERE zone = '%s' AND (version = %u OR version = -1) "
|
||||
"ORDER BY doorid asc", zone_name, version);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()){
|
||||
if (!results.Success()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int32 rowIndex = 0;
|
||||
for(auto row = results.begin(); row != results.end(); ++row, ++rowIndex) {
|
||||
if(rowIndex >= iDoorCount) {
|
||||
std::cerr << "Error, Door Count of " << iDoorCount << " exceeded." << std::endl;
|
||||
break;
|
||||
}
|
||||
int32 rowIndex = 0;
|
||||
for (auto row = results.begin(); row != results.end(); ++row, ++rowIndex) {
|
||||
if (rowIndex >= iDoorCount) {
|
||||
std::cerr << "Error, Door Count of " << iDoorCount << " exceeded." << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
memset(&into[rowIndex], 0, sizeof(Door));
|
||||
memset(&into[rowIndex], 0, sizeof(Door));
|
||||
|
||||
into[rowIndex].db_id = atoi(row[0]);
|
||||
into[rowIndex].door_id = atoi(row[1]);
|
||||
|
||||
Log(Logs::Detail, Logs::Doors, "Door Load: db id: %u, door_id %u", into[rowIndex].db_id, into[rowIndex].door_id);
|
||||
|
||||
strn0cpy(into[rowIndex].zone_name,row[2],32);
|
||||
strn0cpy(into[rowIndex].door_name,row[3],32);
|
||||
strn0cpy(into[rowIndex].zone_name, row[2], 32);
|
||||
strn0cpy(into[rowIndex].door_name, row[3], 32);
|
||||
|
||||
into[rowIndex].pos_x = (float)atof(row[4]);
|
||||
into[rowIndex].pos_y = (float)atof(row[5]);
|
||||
@ -676,17 +687,24 @@ bool ZoneDatabase::LoadDoors(int32 iDoorCount, Door *into, const char *zone_name
|
||||
strn0cpy(into[rowIndex].dest_zone, row[15], 32);
|
||||
|
||||
into[rowIndex].dest_instance_id = atoi(row[16]);
|
||||
into[rowIndex].dest_x = (float) atof(row[17]);
|
||||
into[rowIndex].dest_y = (float) atof(row[18]);
|
||||
into[rowIndex].dest_z = (float) atof(row[19]);
|
||||
into[rowIndex].dest_heading = (float) atof(row[20]);
|
||||
into[rowIndex].door_param=atoi(row[21]);
|
||||
into[rowIndex].invert_state=atoi(row[22]);
|
||||
into[rowIndex].incline=atoi(row[23]);
|
||||
into[rowIndex].size=atoi(row[24]);
|
||||
into[rowIndex].is_ldon_door=atoi(row[25]);
|
||||
into[rowIndex].dest_x = (float)atof(row[17]);
|
||||
into[rowIndex].dest_y = (float)atof(row[18]);
|
||||
into[rowIndex].dest_z = (float)atof(row[19]);
|
||||
into[rowIndex].dest_heading = (float)atof(row[20]);
|
||||
into[rowIndex].door_param = atoi(row[21]);
|
||||
into[rowIndex].invert_state = atoi(row[22]);
|
||||
into[rowIndex].incline = atoi(row[23]);
|
||||
into[rowIndex].size = atoi(row[24]);
|
||||
into[rowIndex].is_ldon_door = atoi(row[25]);
|
||||
into[rowIndex].client_version_mask = (uint32)strtoul(row[26], nullptr, 10);
|
||||
}
|
||||
into[rowIndex].disable_timer = atoi(row[27]);
|
||||
|
||||
Log(Logs::Detail, Logs::Doors, "Door Load: db id: %u, door_id %u disable_timer: %i",
|
||||
into[rowIndex].db_id,
|
||||
into[rowIndex].door_id,
|
||||
into[rowIndex].disable_timer
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -730,6 +748,10 @@ void Doors::SetSize(uint16 in) {
|
||||
entity_list.RespawnAllDoors();
|
||||
}
|
||||
|
||||
void Doors::SetDisableTimer(bool flag) {
|
||||
disable_timer = flag;
|
||||
}
|
||||
|
||||
void Doors::CreateDatabaseEntry()
|
||||
{
|
||||
if(database.GetDoorsDBCountPlusOne(zone->GetShortName(), zone->GetInstanceVersion()) - 1 >= 255)
|
||||
|
||||
11
zone/doors.h
11
zone/doors.h
@ -32,8 +32,8 @@ public:
|
||||
const glm::vec4& GetPosition() const{ return m_Position; }
|
||||
int GetIncline() { return incline; }
|
||||
bool triggered;
|
||||
void SetOpenState(bool st) { isopen = st; }
|
||||
bool IsDoorOpen() { return isopen; }
|
||||
void SetOpenState(bool st) { is_open = st; }
|
||||
bool IsDoorOpen() { return is_open; }
|
||||
|
||||
uint8 GetTriggerDoorID() { return trigger_door; }
|
||||
uint8 GetTriggerType() { return trigger_type; }
|
||||
@ -67,6 +67,10 @@ public:
|
||||
void SetDoorName(const char* name);
|
||||
void SetOpenType(uint8 in);
|
||||
void SetSize(uint16 size);
|
||||
|
||||
void SetDisableTimer(bool flag);
|
||||
bool GetDisableTimer() { return disable_timer; }
|
||||
|
||||
void CreateDatabaseEntry();
|
||||
|
||||
private:
|
||||
@ -88,7 +92,8 @@ private:
|
||||
uint16 size;
|
||||
int invert_state;
|
||||
uint32 entity_id;
|
||||
bool isopen;
|
||||
bool disable_timer;
|
||||
bool is_open;
|
||||
Timer close_timer;
|
||||
//Timer trigger_timer;
|
||||
|
||||
|
||||
@ -877,12 +877,12 @@ bool EntityList::MakeDoorSpawnPacket(EQApplicationPacket *app, Client *client)
|
||||
auto it = door_list.begin();
|
||||
while (it != door_list.end()) {
|
||||
if ((it->second->GetClientVersionMask() & mask_test) &&
|
||||
strlen(it->second->GetDoorName()) > 3)
|
||||
strlen(it->second->GetDoorName()) > 3)
|
||||
count++;
|
||||
++it;
|
||||
}
|
||||
|
||||
if(count == 0 || count > 500)
|
||||
if (count == 0 || count > 500)
|
||||
return false;
|
||||
|
||||
uint32 length = count * sizeof(Door_Struct);
|
||||
@ -890,31 +890,43 @@ bool EntityList::MakeDoorSpawnPacket(EQApplicationPacket *app, Client *client)
|
||||
memset(packet_buffer, 0, length);
|
||||
uchar *ptr = packet_buffer;
|
||||
Doors *door;
|
||||
Door_Struct nd;
|
||||
Door_Struct new_door;
|
||||
|
||||
it = door_list.begin();
|
||||
while (it != door_list.end()) {
|
||||
door = it->second;
|
||||
if (door && (door->GetClientVersionMask() & mask_test) &&
|
||||
strlen(door->GetDoorName()) > 3) {
|
||||
memset(&nd, 0, sizeof(nd));
|
||||
memcpy(nd.name, door->GetDoorName(), 32);
|
||||
strlen(door->GetDoorName()) > 3) {
|
||||
memset(&new_door, 0, sizeof(new_door));
|
||||
memcpy(new_door.name, door->GetDoorName(), 32);
|
||||
|
||||
auto position = door->GetPosition();
|
||||
nd.xPos = position.x;
|
||||
nd.yPos = position.y;
|
||||
nd.zPos = position.z;
|
||||
nd.heading = position.w;
|
||||
nd.incline = door->GetIncline();
|
||||
nd.size = door->GetSize();
|
||||
nd.doorId = door->GetDoorID();
|
||||
nd.opentype = door->GetOpenType();
|
||||
nd.state_at_spawn = door->GetInvertState() ? !door->IsDoorOpen() : door->IsDoorOpen();
|
||||
nd.invert_state = door->GetInvertState();
|
||||
nd.door_param = door->GetDoorParam();
|
||||
memcpy(ptr, &nd, sizeof(nd));
|
||||
ptr+=sizeof(nd);
|
||||
*(ptr-1)=0x01;
|
||||
*(ptr-3)=0x01;
|
||||
|
||||
new_door.xPos = position.x;
|
||||
new_door.yPos = position.y;
|
||||
new_door.zPos = position.z;
|
||||
new_door.heading = position.w;
|
||||
|
||||
new_door.incline = door->GetIncline();
|
||||
new_door.size = door->GetSize();
|
||||
new_door.doorId = door->GetDoorID();
|
||||
new_door.opentype = door->GetOpenType();
|
||||
|
||||
Log(Logs::General, Logs::Doors, "Door timer_disable: %s door_id: %u is_open: %s invert_state: %i",
|
||||
(door->GetDisableTimer() ? "true" : "false"),
|
||||
door->GetDoorID(),
|
||||
(door->IsDoorOpen() ? "true" : "false"),
|
||||
door->GetInvertState()
|
||||
);
|
||||
|
||||
new_door.state_at_spawn = (door->GetInvertState() ? !door->IsDoorOpen() : door->IsDoorOpen());
|
||||
new_door.invert_state = door->GetInvertState();
|
||||
|
||||
new_door.door_param = door->GetDoorParam();
|
||||
memcpy(ptr, &new_door, sizeof(new_door));
|
||||
ptr += sizeof(new_door);
|
||||
*(ptr - 1) = 0x01;
|
||||
*(ptr - 3) = 0x01;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
@ -412,7 +412,7 @@ public:
|
||||
bool LimitCheckName(const char* npc_name);
|
||||
|
||||
void CheckClientAggro(Client *around);
|
||||
Mob* AICheckCloseAggro(Mob* sender, float iAggroRange, float iAssistRange);
|
||||
Mob* AICheckNPCtoNPCAggro(Mob* sender, float iAggroRange, float iAssistRange);
|
||||
int GetHatedCount(Mob *attacker, Mob *exclude);
|
||||
void AIYellForHelp(Mob* sender, Mob* attacker);
|
||||
bool AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float iRange, uint32 iSpellTypes);
|
||||
|
||||
@ -1792,7 +1792,8 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
|
||||
// Nothing in destination slot: split stack into two
|
||||
if ((int16)move_in->number_in_stack >= src_inst->GetCharges()) {
|
||||
// Move entire stack
|
||||
if(!m_inv.SwapItem(src_slot_id, dst_slot_id)) { return false; }
|
||||
EQEmu::InventoryProfile::SwapItemFailState fail_state = EQEmu::InventoryProfile::swapInvalid;
|
||||
if (!m_inv.SwapItem(src_slot_id, dst_slot_id, fail_state)) { return false; }
|
||||
Log(Logs::Detail, Logs::Inventory, "Move entire stack from %d to %d with stack size %d. Dest empty.", src_slot_id, dst_slot_id, move_in->number_in_stack);
|
||||
}
|
||||
else {
|
||||
@ -1822,7 +1823,21 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
|
||||
}
|
||||
SetMaterial(dst_slot_id,src_inst->GetItem()->ID);
|
||||
}
|
||||
if(!m_inv.SwapItem(src_slot_id, dst_slot_id, GetRace(), GetClass(), GetDeity(), GetLevel())) { return false; }
|
||||
|
||||
EQEmu::InventoryProfile::SwapItemFailState fail_state = EQEmu::InventoryProfile::swapInvalid;
|
||||
if (!m_inv.SwapItem(src_slot_id, dst_slot_id, fail_state, GetBaseRace(), GetBaseClass(), GetDeity(), GetLevel())) {
|
||||
const char* fail_message = "The selected slot was invalid.";
|
||||
if (fail_state == EQEmu::InventoryProfile::swapRaceClass || fail_state == EQEmu::InventoryProfile::swapDeity)
|
||||
fail_message = "Your class, deity and/or race may not equip that item.";
|
||||
else if (fail_state == EQEmu::InventoryProfile::swapLevel)
|
||||
fail_message = "You are not sufficient level to use this item.";
|
||||
|
||||
if (fail_message)
|
||||
Message(CC_Red, "%s", fail_message);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Log(Logs::Detail, Logs::Inventory, "Moving entire item from slot %d to slot %d", src_slot_id, dst_slot_id);
|
||||
|
||||
if (src_slot_id <= EQEmu::legacy::EQUIPMENT_END || src_slot_id == EQEmu::inventory::slotPowerSource) {
|
||||
|
||||
@ -111,6 +111,16 @@ uint32 Lua_Door::GetOpenType() {
|
||||
return self->GetOpenType();
|
||||
}
|
||||
|
||||
void Lua_Door::SetDisableTimer(bool flag) {
|
||||
Lua_Safe_Call_Void();
|
||||
self->SetDisableTimer(flag);
|
||||
}
|
||||
|
||||
bool Lua_Door::GetDisableTimer() {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->GetDisableTimer();
|
||||
}
|
||||
|
||||
void Lua_Door::SetLockPick(uint32 pick) {
|
||||
Lua_Safe_Call_Void();
|
||||
self->SetLockpick(pick);
|
||||
@ -190,6 +200,8 @@ luabind::scope lua_register_door() {
|
||||
.def("GetIncline", (uint32(Lua_Door::*)(void))&Lua_Door::GetIncline)
|
||||
.def("SetOpenType", (void(Lua_Door::*)(uint32))&Lua_Door::SetOpenType)
|
||||
.def("GetOpenType", (uint32(Lua_Door::*)(void))&Lua_Door::GetOpenType)
|
||||
.def("SetDisableTimer", (void(Lua_Door::*)(bool))&Lua_Door::SetDisableTimer)
|
||||
.def("GetDisableTimer", (bool(Lua_Door::*)(void))&Lua_Door::GetDisableTimer)
|
||||
.def("SetLockPick", (void(Lua_Door::*)(uint32))&Lua_Door::SetLockPick)
|
||||
.def("GetLockPick", (uint32(Lua_Door::*)(void))&Lua_Door::GetLockPick)
|
||||
.def("SetKeyItem", (void(Lua_Door::*)(uint32))&Lua_Door::SetKeyItem)
|
||||
|
||||
@ -49,6 +49,8 @@ public:
|
||||
uint32 GetIncline();
|
||||
void SetOpenType(uint32 type);
|
||||
uint32 GetOpenType();
|
||||
void SetDisableTimer(bool flag);
|
||||
bool GetDisableTimer();
|
||||
void SetLockPick(uint32 pick);
|
||||
uint32 GetLockPick();
|
||||
void SetKeyItem(uint32 key);
|
||||
|
||||
@ -1680,7 +1680,7 @@ luabind::scope lua_register_events() {
|
||||
luabind::value("loot", static_cast<int>(EVENT_LOOT)),
|
||||
luabind::value("zone", static_cast<int>(EVENT_ZONE)),
|
||||
luabind::value("level_up", static_cast<int>(EVENT_LEVEL_UP)),
|
||||
luabind::value("killed_merit ", static_cast<int>(EVENT_KILLED_MERIT )),
|
||||
luabind::value("killed_merit", static_cast<int>(EVENT_KILLED_MERIT)),
|
||||
luabind::value("cast_on", static_cast<int>(EVENT_CAST_ON)),
|
||||
luabind::value("task_accepted", static_cast<int>(EVENT_TASK_ACCEPTED)),
|
||||
luabind::value("task_stage_complete", static_cast<int>(EVENT_TASK_STAGE_COMPLETE)),
|
||||
|
||||
@ -40,7 +40,8 @@ int Lua_Inventory::PushCursor(Lua_ItemInst item) {
|
||||
|
||||
bool Lua_Inventory::SwapItem(int slot_a, int slot_b) {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->SwapItem(slot_a, slot_b);
|
||||
EQEmu::InventoryProfile::SwapItemFailState fail_state = EQEmu::InventoryProfile::swapInvalid;
|
||||
return self->SwapItem(slot_a, slot_b, fail_state);
|
||||
}
|
||||
|
||||
bool Lua_Inventory::DeleteItem(int slot_id) {
|
||||
|
||||
@ -18,6 +18,11 @@ namespace luabind {
|
||||
|
||||
luabind::scope lua_register_inventory();
|
||||
|
||||
// This class should be deprecated due to the nature of inventory actions.
|
||||
// Direct manipulation of the inventory system bypasses the client management
|
||||
// of database calls and can lead to lost items, duplicated items and/or
|
||||
// desync'd inventories, if not handled correctly.
|
||||
|
||||
class Lua_Inventory : public Lua_Ptr<EQEmu::InventoryProfile>
|
||||
{
|
||||
typedef EQEmu::InventoryProfile NativeType;
|
||||
|
||||
@ -823,6 +823,11 @@ bool Lua_Mob::SpellFinished(int spell_id, Lua_Mob target, int slot, int mana_use
|
||||
return self->SpellFinished(spell_id, target, static_cast<EQEmu::CastingSlot>(slot), mana_used, inventory_slot, resist_adjust, proc);
|
||||
}
|
||||
|
||||
void Lua_Mob::SendBeginCast(int spell_id, int cast_time) {
|
||||
Lua_Safe_Call_Void();
|
||||
self->SendBeginCast(spell_id, cast_time);
|
||||
}
|
||||
|
||||
void Lua_Mob::SpellEffect(Lua_Mob caster, int spell_id, double partial) {
|
||||
Lua_Safe_Call_Void();
|
||||
self->SpellEffect(caster, spell_id, static_cast<float>(partial));
|
||||
@ -2128,6 +2133,7 @@ luabind::scope lua_register_mob() {
|
||||
.def("SpellFinished", (bool(Lua_Mob::*)(int,Lua_Mob,int,int,uint32))&Lua_Mob::SpellFinished)
|
||||
.def("SpellFinished", (bool(Lua_Mob::*)(int,Lua_Mob,int,int,uint32,int))&Lua_Mob::SpellFinished)
|
||||
.def("SpellFinished", (bool(Lua_Mob::*)(int,Lua_Mob,int,int,uint32,int,bool))&Lua_Mob::SpellFinished)
|
||||
.def("SendBeginCast", &Lua_Mob::SendBeginCast)
|
||||
.def("SpellEffect", &Lua_Mob::SpellEffect)
|
||||
.def("GetPet", &Lua_Mob::GetPet)
|
||||
.def("GetOwner", &Lua_Mob::GetOwner)
|
||||
|
||||
@ -181,6 +181,7 @@ public:
|
||||
bool SpellFinished(int spell_id, Lua_Mob target, int slot, int mana_used, uint32 inventory_slot);
|
||||
bool SpellFinished(int spell_id, Lua_Mob target, int slot, int mana_used, uint32 inventory_slot, int resist_adjust);
|
||||
bool SpellFinished(int spell_id, Lua_Mob target, int slot, int mana_used, uint32 inventory_slot, int resist_adjust, bool proc);
|
||||
void SendBeginCast(int spell_id, int cast_time);
|
||||
void SpellEffect(Lua_Mob caster, int spell_id, double partial);
|
||||
Lua_Mob GetPet();
|
||||
Lua_Mob GetOwner();
|
||||
|
||||
@ -279,6 +279,7 @@ public:
|
||||
uint32 inventory_slot = 0xFFFFFFFF, int16 resist_adjust = 0);
|
||||
bool SpellFinished(uint16 spell_id, Mob *target, EQEmu::CastingSlot slot = EQEmu::CastingSlot::Item, uint16 mana_used = 0,
|
||||
uint32 inventory_slot = 0xFFFFFFFF, int16 resist_adjust = 0, bool isproc = false, int level_override = -1);
|
||||
void SendBeginCast(uint16 spell_id, uint32 casttime);
|
||||
virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect = false,
|
||||
bool use_resist_adjust = false, int16 resist_adjust = 0, bool isproc = false, int level_override = -1);
|
||||
virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100, int level_override = -1);
|
||||
|
||||
@ -457,18 +457,18 @@ void Mob::AI_Start(uint32 iMoveDelay) {
|
||||
AI_movement_timer = std::unique_ptr<Timer>(new Timer(AImovement_duration));
|
||||
AI_target_check_timer = std::unique_ptr<Timer>(new Timer(AItarget_check_duration));
|
||||
AI_feign_remember_timer = std::unique_ptr<Timer>(new Timer(AIfeignremember_delay));
|
||||
AI_scan_area_timer = std::unique_ptr<Timer>(new Timer(RandomTimer(RuleI(NPC, NPCToNPCAggroTimerMin), RuleI(NPC, NPCToNPCAggroTimerMax))));
|
||||
|
||||
if(CastToNPC()->WillAggroNPCs())
|
||||
AI_scan_area_timer = std::unique_ptr<Timer>(new Timer(RandomTimer(RuleI(NPC, NPCToNPCAggroTimerMin), RuleI(NPC, NPCToNPCAggroTimerMax))));
|
||||
|
||||
AI_check_signal_timer = std::unique_ptr<Timer>(new Timer(AI_check_signal_timer_delay));
|
||||
|
||||
#ifdef REVERSE_AGGRO
|
||||
if(IsNPC() && !CastToNPC()->WillAggroNPCs())
|
||||
AI_scan_area_timer->Disable();
|
||||
#endif
|
||||
|
||||
if (GetAggroRange() == 0)
|
||||
pAggroRange = 70;
|
||||
if (GetAssistRange() == 0)
|
||||
pAssistRange = 70;
|
||||
|
||||
hate_list.WipeHateList();
|
||||
|
||||
m_Delta = glm::vec4();
|
||||
@ -1304,7 +1304,7 @@ void Mob::AI_Process() {
|
||||
if (m_PlayerState & static_cast<uint32>(PlayerState::Aggressive))
|
||||
SendRemovePlayerState(PlayerState::Aggressive);
|
||||
|
||||
if(!zone->CanDoCombat() && AI_feign_remember_timer->Check()) {
|
||||
if(zone->CanDoCombat() && AI_feign_remember_timer->Check()) {
|
||||
// 6/14/06
|
||||
// Improved Feign Death Memory
|
||||
// check to see if any of our previous feigned targets have gotten up.
|
||||
@ -1329,18 +1329,13 @@ void Mob::AI_Process() {
|
||||
{
|
||||
//we processed a spell action, so do nothing else.
|
||||
}
|
||||
else if (!zone->CanDoCombat() && AI_scan_area_timer->Check())
|
||||
else if (zone->CanDoCombat() && CastToNPC()->WillAggroNPCs() && AI_scan_area_timer->Check())
|
||||
{
|
||||
/*
|
||||
* This is where NPCs look around to see if they want to attack anybody.
|
||||
*
|
||||
* if REVERSE_AGGRO is enabled, then this timer is disabled unless they
|
||||
* have the npc_aggro flag on them, and aggro against clients is checked
|
||||
* by the clients.
|
||||
*
|
||||
* NPC to NPC aggro checking, npc needs npc_aggro flag
|
||||
*/
|
||||
|
||||
Mob* temp_target = entity_list.AICheckCloseAggro(this, GetAggroRange(), GetAssistRange());
|
||||
Mob* temp_target = entity_list.AICheckNPCtoNPCAggro(this, GetAggroRange(), GetAssistRange());
|
||||
if (temp_target){
|
||||
AddToHateList(temp_target);
|
||||
}
|
||||
@ -1415,6 +1410,7 @@ void Mob::AI_Process() {
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Entity has been assigned another entity to follow */
|
||||
else if (GetFollowID())
|
||||
{
|
||||
Mob* follow = entity_list.GetMob(GetFollowID());
|
||||
@ -1458,6 +1454,7 @@ void Mob::AI_Process() {
|
||||
minLastFightingDelayMoving = 0;
|
||||
maxLastFightingDelayMoving = 0;
|
||||
}
|
||||
/* All normal NPC pathing */
|
||||
CastToNPC()->AI_DoMovement();
|
||||
}
|
||||
}
|
||||
|
||||
@ -374,6 +374,7 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, const glm::vec4& position, int if
|
||||
InitializeBuffSlots();
|
||||
CalcBonuses();
|
||||
raid_target = d->raid_target;
|
||||
ignore_despawn = d->ignore_despawn;
|
||||
}
|
||||
|
||||
NPC::~NPC()
|
||||
|
||||
@ -417,6 +417,8 @@ public:
|
||||
bool IsRaidTarget() const { return raid_target; };
|
||||
void ResetHPUpdateTimer() { sendhpupdate_timer.Start(); }
|
||||
|
||||
bool IgnoreDespawn() { return ignore_despawn; }
|
||||
|
||||
protected:
|
||||
|
||||
const NPCType* NPCTypedata;
|
||||
@ -532,6 +534,7 @@ protected:
|
||||
|
||||
bool raid_target;
|
||||
uint8 probability;
|
||||
bool ignore_despawn; //NPCs with this set to 1 will ignore the despawn value in spawngroup
|
||||
|
||||
private:
|
||||
uint32 loottable_id;
|
||||
|
||||
@ -208,11 +208,26 @@ bool Spawn2::Process() {
|
||||
}
|
||||
}
|
||||
|
||||
if(sg->despawn != 0 && condition_id == 0)
|
||||
zone->Despawn(spawn2_id);
|
||||
|
||||
if(IsDespawned)
|
||||
bool ignore_despawn = false;
|
||||
if (npcthis)
|
||||
{
|
||||
ignore_despawn = npcthis->IgnoreDespawn();
|
||||
}
|
||||
|
||||
if (ignore_despawn)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sg->despawn != 0 && condition_id == 0 && !ignore_despawn)
|
||||
{
|
||||
zone->Despawn(spawn2_id);
|
||||
}
|
||||
|
||||
if (IsDespawned)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
currentnpcid = npcid;
|
||||
NPC* npc = new NPC(tmp, this, glm::vec4(x, y, z, heading), FlyMode3);
|
||||
@ -295,6 +310,9 @@ void Spawn2::ForceDespawn()
|
||||
|
||||
if(npcthis != nullptr)
|
||||
{
|
||||
if (npcthis->IgnoreDespawn())
|
||||
return;
|
||||
|
||||
if(!npcthis->IsEngaged())
|
||||
{
|
||||
if(sg->despawn == 3 || sg->despawn == 4)
|
||||
|
||||
@ -478,23 +478,8 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
|
||||
// now tell the people in the area -- we ALWAYS want to send this, even instant cast spells.
|
||||
// The only time this is skipped is for NPC innate procs and weapon procs. Procs from buffs
|
||||
// oddly still send this. Since those cases don't reach here, we don't need to check them
|
||||
if (slot != CastingSlot::Discipline) {
|
||||
auto outapp = new EQApplicationPacket(OP_BeginCast,sizeof(BeginCast_Struct));
|
||||
BeginCast_Struct* begincast = (BeginCast_Struct*)outapp->pBuffer;
|
||||
begincast->caster_id = GetID();
|
||||
begincast->spell_id = spell_id;
|
||||
begincast->cast_time = orgcasttime; // client calculates reduced time by itself
|
||||
outapp->priority = 3;
|
||||
entity_list.QueueCloseClients(
|
||||
this, /* Sender */
|
||||
outapp, /* Packet */
|
||||
false, /* Ignore Sender */
|
||||
RuleI(Range, BeginCast),
|
||||
0, /* Skip this Mob */
|
||||
true /* Packet ACK */
|
||||
); //IsClient() ? FILTER_PCSPELLS : FILTER_NPCSPELLS);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
if (slot != CastingSlot::Discipline)
|
||||
SendBeginCast(spell_id, orgcasttime);
|
||||
|
||||
// cast time is 0, just finish it right now and be done with it
|
||||
if(cast_time == 0) {
|
||||
@ -537,6 +522,29 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
|
||||
return(true);
|
||||
}
|
||||
|
||||
void Mob::SendBeginCast(uint16 spell_id, uint32 casttime)
|
||||
{
|
||||
auto outapp = new EQApplicationPacket(OP_BeginCast, sizeof(BeginCast_Struct));
|
||||
auto begincast = (BeginCast_Struct *)outapp->pBuffer;
|
||||
|
||||
begincast->caster_id = GetID();
|
||||
begincast->spell_id = spell_id;
|
||||
begincast->cast_time = casttime; // client calculates reduced time by itself
|
||||
|
||||
outapp->priority = 3;
|
||||
|
||||
entity_list.QueueCloseClients(
|
||||
this, /* Sender */
|
||||
outapp, /* Packet */
|
||||
false, /* Ignore Sender */
|
||||
RuleI(Range, BeginCast),
|
||||
0, /* Skip this Mob */
|
||||
true /* Packet ACK */
|
||||
); //IsClient() ? FILTER_PCSPELLS : FILTER_NPCSPELLS);
|
||||
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Some failures should be caught before the spell finishes casting
|
||||
* This is especially helpful to clients when they cast really long things
|
||||
@ -3782,11 +3790,13 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(reflect_chance) {
|
||||
Message_StringID(MT_Spells, SPELL_REFLECT, GetCleanName(), spelltar->GetCleanName());
|
||||
if (reflect_chance) {
|
||||
entity_list.MessageClose_StringID(this, false, RuleI(Range, SpellMessages), MT_Spells,
|
||||
SPELL_REFLECT, GetCleanName(), spelltar->GetCleanName());
|
||||
CheckNumHitsRemaining(NumHit::ReflectSpell);
|
||||
// caster actually appears to change
|
||||
// ex. During OMM fight you click your reflect mask and you get the recourse from the reflected spell
|
||||
// ex. During OMM fight you click your reflect mask and you get the recourse from the reflected
|
||||
// spell
|
||||
spelltar->SpellOnTarget(spell_id, this, true, use_resist_adjust, resist_adjust);
|
||||
safe_delete(action_packet);
|
||||
return false;
|
||||
|
||||
@ -1966,7 +1966,8 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load
|
||||
"npc_types.bracertexture, "
|
||||
"npc_types.handtexture, "
|
||||
"npc_types.legtexture, "
|
||||
"npc_types.feettexture "
|
||||
"npc_types.feettexture, "
|
||||
"npc_types.ignore_despawn "
|
||||
"FROM npc_types %s",
|
||||
where_condition.c_str()
|
||||
);
|
||||
@ -2141,6 +2142,7 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load
|
||||
temp_npctype_data->handtexture = atoi(row[94]);
|
||||
temp_npctype_data->legtexture = atoi(row[95]);
|
||||
temp_npctype_data->feettexture = atoi(row[96]);
|
||||
temp_npctype_data->ignore_despawn = atoi(row[97]) == 1 ? true : false;
|
||||
|
||||
// If NPC with duplicate NPC id already in table,
|
||||
// free item we attempted to add.
|
||||
@ -2987,16 +2989,16 @@ void ZoneDatabase::QGlobalPurge()
|
||||
database.QueryDatabase(query);
|
||||
}
|
||||
|
||||
void ZoneDatabase::InsertDoor(uint32 ddoordbid, uint16 ddoorid, const char* ddoor_name, const glm::vec4& position, uint8 dopentype, uint16 dguildid, uint32 dlockpick, uint32 dkeyitem, uint8 ddoor_param, uint8 dinvert, int dincline, uint16 dsize){
|
||||
void ZoneDatabase::InsertDoor(uint32 ddoordbid, uint16 ddoorid, const char* ddoor_name, const glm::vec4& position, uint8 dopentype, uint16 dguildid, uint32 dlockpick, uint32 dkeyitem, uint8 ddoor_param, uint8 dinvert, int dincline, uint16 dsize, bool ddisabletimer){
|
||||
|
||||
std::string query = StringFormat("REPLACE INTO doors (id, doorid, zone, version, name, "
|
||||
"pos_x, pos_y, pos_z, heading, opentype, guild, lockpick, "
|
||||
"keyitem, door_param, invert_state, incline, size) "
|
||||
"keyitem, disable_timer, door_param, invert_state, incline, size) "
|
||||
"VALUES('%i', '%i', '%s', '%i', '%s', '%f', '%f', "
|
||||
"'%f', '%f', '%i', '%i', '%i', '%i', '%i', '%i', '%i', '%i')",
|
||||
"'%f', '%f', '%i', '%i', '%i', '%i', '%i', '%i', '%i', '%i', '%i')",
|
||||
ddoordbid, ddoorid, zone->GetShortName(), zone->GetInstanceVersion(),
|
||||
ddoor_name, position.x, position.y, position.z, position.w,
|
||||
dopentype, dguildid, dlockpick, dkeyitem, ddoor_param, dinvert, dincline, dsize);
|
||||
dopentype, dguildid, dlockpick, dkeyitem, (ddisabletimer ? 1 : 0), ddoor_param, dinvert, dincline, dsize);
|
||||
QueryDatabase(query);
|
||||
}
|
||||
|
||||
|
||||
@ -454,7 +454,7 @@ public:
|
||||
int32 GetDoorsCount(uint32* oMaxID, const char *zone_name, int16 version);
|
||||
int32 GetDoorsCountPlusOne(const char *zone_name, int16 version);
|
||||
int32 GetDoorsDBCountPlusOne(const char *zone_name, int16 version);
|
||||
void InsertDoor(uint32 did, uint16 ddoorid, const char* ddoor_name, const glm::vec4& position, uint8 dopentype, uint16 dguildid, uint32 dlockpick, uint32 dkeyitem, uint8 ddoor_param, uint8 dinvert, int dincline, uint16 dsize);
|
||||
void InsertDoor(uint32 did, uint16 ddoorid, const char* ddoor_name, const glm::vec4& position, uint8 dopentype, uint16 dguildid, uint32 dlockpick, uint32 dkeyitem, uint8 ddoor_param, uint8 dinvert, int dincline, uint16 dsize, bool ddisabletimer = false);
|
||||
|
||||
/* Blocked Spells */
|
||||
int32 GetBlockedSpellsCount(uint32 zoneid);
|
||||
|
||||
@ -132,6 +132,7 @@ struct NPCType
|
||||
uint8 handtexture;
|
||||
uint8 legtexture;
|
||||
uint8 feettexture;
|
||||
bool ignore_despawn;
|
||||
};
|
||||
|
||||
namespace player_lootitem {
|
||||
@ -201,6 +202,7 @@ struct Door {
|
||||
uint8 nokeyring;
|
||||
uint8 trigger_door;
|
||||
uint8 trigger_type;
|
||||
uint8 disable_timer;
|
||||
uint32 door_param;
|
||||
int invert_state;
|
||||
uint16 size;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user