Compare commits

...

35 Commits

Author SHA1 Message Date
Uleat a0073b4018 Metric prototype 2020-01-17 21:13:34 -05:00
Uleat daa9c04e89 Merge branch 'master' of https://github.com/EQEmu/Server 2020-01-16 20:49:12 -05:00
Uleat a9ef2474d4 Updated eqemu_server.pl to use the appveyor archive when setting up bots [skip ci] 2020-01-16 20:49:03 -05:00
Michael Cook (mackal) e1408ede6b Remove AdventureManager::Load since it doesn't do anything 2020-01-16 19:22:17 -05:00
Michael Cook (mackal) 4241fba7e2 Forgot 2 exceptions 2020-01-16 19:10:04 -05:00
Michael Cook (mackal) 139b6c34e5 Change things -Wcatch-value complains about to references 2020-01-16 19:03:36 -05:00
Michael Cook (mackal) baf4cc62eb Fix format truncation in RoF2 OP_Trader 2020-01-16 18:04:20 -05:00
Michael Cook (mackal) 14402c9c41 Fix unreachable switch statements in console_server_connection.cpp 2020-01-16 17:44:46 -05:00
Michael Cook (mackal) e4c4e5edb2 References shouldn't be null 2020-01-16 17:17:31 -05:00
Michael Cook (mackal) e6a14beb2e Remove another unnecessary this == null check 2020-01-16 17:06:11 -05:00
Michael Cook (mackal) 945ca1278c Remove some unnecessary this == null checks 2020-01-16 17:02:35 -05:00
Michael Cook (mackal) a307747c29 Nuke unused command_itemtest 2020-01-16 16:51:24 -05:00
Michael Cook (mackal) 099da513ff Remove some unused misc.cpp functions (encode/decode)
These were unused and throwing warnings, so throw them away!
2020-01-16 16:18:08 -05:00
Michael Cook (mackal) 607379110b Add some focus effects bots were missing 2020-01-16 16:00:38 -05:00
Michael Cook (mackal) 7ce88b30ad Remove Bot::BotfocusType
This was just a maintenance burden keeping it in sync with focusType
(and it wasn't!)
2020-01-16 15:47:25 -05:00
Michael Cook (mackal) 28b0526857 Change NPCType::deity to uint32 to match client data type
Fixes overflow warning in bot.cpp
Shouldn't need DeityAgnostic_LB anymore either
2020-01-16 15:16:21 -05:00
Michael Cook (mackal) d5067c4c3a Treat bots like PCs for pcnpc_only_flag 2020-01-15 19:30:47 -05:00
Uleat 79db824a3c Fix for bots update reporting errors on server start-up after newer update applied [skip ci] 2020-01-15 02:56:00 -05:00
Akkadius 331032f4f4 Push a scan when mobs first construct [skip ci] 2020-01-14 16:14:19 -06:00
Uleat 61790ef195 Wasn't quite dead... (Removed substring call from silent saylink parsing) 2020-01-13 19:01:42 -05:00
Uleat 9bdb70b2f0 Fatality! (Fix for event_say parse events not observing the correct parser for their situation) 2020-01-13 01:47:39 -05:00
Uleat c438819ed6 Fix for command redirect of '#bot' using EVENT_COMMAND invocation 2020-01-12 22:40:05 -05:00
Uleat 7a791dda3c Merge branch 'master' of https://github.com/EQEmu/Server 2020-01-12 21:11:51 -05:00
Uleat 6366a3fa38 Fix for silent saylinks and EVENT_COMMAND calls 2020-01-12 21:11:43 -05:00
Akkadius 306a08b9ac Unify / streamline scanning logic calls, do a manual scan on enter and cleanup logging 2020-01-12 19:37:53 -06:00
Uleat 467f8d7867 Merge branch 'master' of https://github.com/EQEmu/Server 2020-01-12 01:33:17 -05:00
Uleat 6c2100a650 Fix for perl EVENT_COMMAND not exporting single arguments 2020-01-12 01:32:51 -05:00
Akkadius 9dacd0bd7a Remove aa_timers from character tables [skip ci] 2020-01-11 18:19:27 -06:00
Akkadius 3c6cdd0905 Update character_table_list.txt for now until replaced [skip ci] 2020-01-11 18:02:01 -06:00
Akkadius d1fb74ff5f Fix bot table 2020-01-10 02:59:52 -06:00
Akkadius f81b9d8244 Update worlddb.cpp 2020-01-10 02:54:34 -06:00
Akkadius b9e87abb3c Implement Character Soft Deletes 2020-01-10 02:54:29 -06:00
Uleat 451b0180c9 Merge pull request #943 from EQEmu/script_commands
Reworked EVENT_COMMAND handling and addressed script commands not present during help use
2020-01-07 21:43:32 -05:00
Akkadius 77ae4f0c3f Update missing aliases for when log compilation flag is turned off [skip ci] 2020-01-07 16:09:14 -06:00
Uleat 852d951b65 Reworked EVENT_COMMAND handling and addressed script commands not present during help use 2020-01-06 15:41:05 -05:00
63 changed files with 930 additions and 6374 deletions
+3
View File
@@ -44,6 +44,7 @@ SET(common_sources
md5.cpp
memory_buffer.cpp
memory_mapped_file.cpp
metric_manager.cpp
misc.cpp
misc_functions.cpp
mutex.cpp
@@ -173,6 +174,8 @@ SET(common_headers
md5.h
memory_buffer.h
memory_mapped_file.h
metric_event.h
metric_manager.h
misc.h
misc_functions.h
mutex.h
+73 -50
View File
@@ -341,65 +341,88 @@ bool Database::ReserveName(uint32 account_id, char* name) {
return true;
}
/*
Delete the character with the name "name"
returns false on failure, true otherwise
*/
bool Database::DeleteCharacter(char *name) {
uint32 charid = 0;
if(!name || !strlen(name)) {
/**
* @param character_name
* @return
*/
bool Database::DeleteCharacter(char *character_name) {
uint32 character_id = 0;
if(!character_name || !strlen(character_name)) {
LogInfo("DeleteCharacter: request to delete without a name (empty char slot)");
return false;
}
LogInfo("Database::DeleteCharacter name : [{}]", name);
/* Get id from character_data before deleting record so we can clean up the rest of the tables */
std::string query = StringFormat("SELECT `id` from `character_data` WHERE `name` = '%s'", name);
auto results = QueryDatabase(query);
for (auto row = results.begin(); row != results.end(); ++row) { charid = atoi(row[0]); }
if (charid <= 0){
LogError("Database::DeleteCharacter :: Character ({}) not found, stopping delete...", name);
std::string query = StringFormat("SELECT `id` from `character_data` WHERE `name` = '%s'", character_name);
auto results = QueryDatabase(query);
for (auto row = results.begin(); row != results.end(); ++row) {
character_id = atoi(row[0]);
}
if (character_id <= 0) {
LogError("DeleteCharacter | Invalid Character ID [{}]", character_name);
return false;
}
query = StringFormat("DELETE FROM `quest_globals` WHERE `charid` = '%d'", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_activities` WHERE `charid` = '%d'", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_enabledtasks` WHERE `charid` = '%d'", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_tasks` WHERE `charid` = '%d'", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `completed_tasks` WHERE `charid` = '%d'", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `friends` WHERE `charid` = '%d'", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `mail` WHERE `charid` = '%d'", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `timers` WHERE `char_id` = '%d'", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `inventory` WHERE `charid` = '%d'", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `char_recipe_list` WHERE `char_id` = '%d'", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `adventure_stats` WHERE `player_id` ='%d'", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `zone_flags` WHERE `charID` = '%d'", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `titles` WHERE `char_id` = '%d'", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `player_titlesets` WHERE `char_id` = '%d'", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `keyring` WHERE `char_id` = '%d'", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `faction_values` WHERE `char_id` = '%d'", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `instance_list_player` WHERE `charid` = '%d'", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_data` WHERE `id` = '%d'", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_skills` WHERE `id` = %u", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_languages` WHERE `id` = %u", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_bind` WHERE `id` = %u", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_alternate_abilities` WHERE `id` = %u", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_currency` WHERE `id` = %u", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_data` WHERE `id` = %u", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_spells` WHERE `id` = %u", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_memmed_spells` WHERE `id` = %u", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_disciplines` WHERE `id` = %u", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_material` WHERE `id` = %u", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_tribute` WHERE `id` = %u", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_bandolier` WHERE `id` = %u", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_potionbelt` WHERE `id` = %u", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_inspect_messages` WHERE `id` = %u", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_leadership_abilities` WHERE `id` = %u", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_alt_currency` WHERE `char_id` = '%d'", charid); QueryDatabase(query);
std::string delete_type = "hard-deleted";
if (RuleB(Character, SoftDeletes)) {
delete_type = "soft-deleted";
std::string query = fmt::format(
SQL(
UPDATE
character_data
SET
deleted_at = NOW()
WHERE
id = '{}'
),
character_id
);
QueryDatabase(query);
return true;
}
LogInfo("DeleteCharacter | Character [{}] ({}) is being [{}]", character_name, character_id, delete_type);
query = StringFormat("DELETE FROM `quest_globals` WHERE `charid` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_activities` WHERE `charid` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_enabledtasks` WHERE `charid` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_tasks` WHERE `charid` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `completed_tasks` WHERE `charid` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `friends` WHERE `charid` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `mail` WHERE `charid` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `timers` WHERE `char_id` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `inventory` WHERE `charid` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `char_recipe_list` WHERE `char_id` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `adventure_stats` WHERE `player_id` ='%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `zone_flags` WHERE `charID` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `titles` WHERE `char_id` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `player_titlesets` WHERE `char_id` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `keyring` WHERE `char_id` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `faction_values` WHERE `char_id` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `instance_list_player` WHERE `charid` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_data` WHERE `id` = '%d'", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_skills` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_languages` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_bind` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_alternate_abilities` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_currency` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_data` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_spells` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_memmed_spells` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_disciplines` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_material` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_tribute` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_bandolier` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_potionbelt` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_inspect_messages` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_leadership_abilities` WHERE `id` = %u", character_id); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_alt_currency` WHERE `char_id` = '%d'", character_id); QueryDatabase(query);
#ifdef BOTS
query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d' AND GetMobTypeById(%i) = 'C'", charid); // note: only use of GetMobTypeById()
query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d' AND GetMobTypeById(%i) = 'C'", character_id); // note: only use of GetMobTypeById()
#else
query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d'", charid);
query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d'", character_id);
#endif
QueryDatabase(query);
+1 -1
View File
@@ -107,7 +107,7 @@ public:
bool AddToNameFilter(const char* name);
bool CreateCharacter(uint32 account_id, char* name, uint16 gender, uint16 race, uint16 class_, uint8 str, uint8 sta, uint8 cha, uint8 dex, uint8 int_, uint8 agi, uint8 wis, uint8 face);
bool DeleteCharacter(char* name);
bool DeleteCharacter(char* character_name);
bool MoveCharacterToZone(const char* charname, const char* zonename);
bool MoveCharacterToZone(const char* charname, const char* zonename,uint32 zoneid);
bool MoveCharacterToZone(uint32 iCharID, const char* iZonename);
-1
View File
@@ -33,7 +33,6 @@ namespace DatabaseSchema {
static std::vector<std::string> GetPlayerTables()
{
std::vector<std::string> tables = {
"aa_timers",
"account",
"account_ip",
"account_flags",
+1 -1
View File
@@ -165,7 +165,7 @@ class EQEmuConfig
fconfig >> _config->_root;
_config->parse_config();
}
catch (std::exception) {
catch (std::exception &) {
return false;
}
return true;
+36
View File
@@ -842,6 +842,42 @@
#define LogStatusDetail(message, ...) do {\
} while (0)
#define LogAIScanClose(message, ...) do {\
} while (0)
#define LogAIScanCloseDetail(message, ...) do {\
} while (0)
#define LogAIYellForHelp(message, ...) do {\
} while (0)
#define LogAIYellForHelpDetail(message, ...) do {\
} while (0)
#define LogAICastBeneficialClose(message, ...) do {\
} while (0)
#define LogAICastBeneficialCloseDetail(message, ...) do {\
} while (0)
#define LogAoeCast(message, ...) do {\
} while (0)
#define LogAoeCastDetail(message, ...) do {\
} while (0)
#define LogEntityManagement(message, ...) do {\
} while (0)
#define LogEntityManagementDetail(message, ...) do {\
} while (0)
#define LogFlee(message, ...) do {\
} while (0)
#define LogFleeDetail(message, ...) do {\
} while (0)
#define Log(debug_level, log_category, message, ...) do {\
} while (0)
+5 -5
View File
@@ -32,7 +32,7 @@ EQ::JsonConfigFile EQ::JsonConfigFile::Load(
try {
ifs >> ret.m_root;
}
catch (std::exception) {
catch (std::exception &) {
return ret;
}
@@ -81,7 +81,7 @@ std::string EQ::JsonConfigFile::GetVariableString(
return m_root[title][parameter].asString();
}
}
catch (std::exception) {
catch (std::exception &) {
return default_value;
}
@@ -105,7 +105,7 @@ int EQ::JsonConfigFile::GetVariableInt(
return m_root[title][parameter].asInt();
}
}
catch (std::exception) {
catch (std::exception &) {
return default_value;
}
@@ -129,7 +129,7 @@ bool EQ::JsonConfigFile::GetVariableBool(
return m_root[title][parameter].asBool();
}
}
catch (std::exception) {
catch (std::exception &) {
return default_value;
}
@@ -153,7 +153,7 @@ double EQ::JsonConfigFile::GetVariableDouble(
return m_root[title][parameter].asDouble();
}
}
catch (std::exception) {
catch (std::exception &) {
return default_value;
}
-6
View File
@@ -278,12 +278,6 @@ void LinkedListIterator<TYPE>::Replace(const TYPE& new_data)
template<class TYPE>
void LinkedListIterator<TYPE>::Reset()
{
if (!(&list))
{
current_element=0;
return;
}
if (dir == FORWARD)
{
current_element = list.first;
+65
View File
@@ -0,0 +1,65 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2020 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef METRIC_EVENT_H
#define METRIC_EVENT_H
#include "types.h"
namespace EQEmu
{
class MetricEvent {
public:
enum class EventType {
eventNone,
eventNpcStatsMonitor
};
MetricEvent() {
m_finalized = false;
m_expired = false;
m_event_id = 0;
}
virtual EventType GetEventType() const = 0;
virtual void Process() = 0;
virtual void Flush() = 0;
virtual void Finalize() { m_finalized = true; } // invoke MetricEvent::Finalize() inside of derived class function if not handled locally
bool IsFinalized() const { return m_finalized; }
virtual void Expire() { m_finalized = true; m_expired = true; } // invoke MetricEvent::Expire() inside of derived class function if not handled locally
bool IsExpired() const { return m_expired; }
void SetEventId(int value) { if (m_event_id == 0) { m_event_id = value; } }
int GetEventId() const { return m_event_id; }
private:
bool m_finalized;
bool m_expired;
int m_event_id;
};
} // EQEmu
#endif // METRIC_EVENT_H
+112
View File
@@ -0,0 +1,112 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2020 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "metric_manager.h"
#include "metric_event.h"
EQEmu::MetricManager::MetricManager() {
m_current_event_id = 0;
}
void EQEmu::MetricManager::Process() {
for (std::list<MetricEvent*>::iterator iter = m_event_list.begin(); iter != m_event_list.end(); ) {
if ((*iter)->IsExpired()) {
iter = m_event_list.erase(iter);
continue;
}
(*iter)->Process();
++iter;
}
}
int EQEmu::MetricManager::RegisterEvent(MetricEvent* event_object) {
if (event_object == nullptr) {
return 0;
}
event_object->SetEventId(get_next_event_id());
m_event_list.push_back(event_object);
return event_object->GetEventId();
}
void EQEmu::MetricManager::FlushAll() {
for (auto iter : m_event_list) {
iter->Flush();
}
}
void EQEmu::MetricManager::FlushById(int event_id) {
for (auto iter : m_event_list) {
if (iter->GetEventId() == event_id) {
iter->Flush();
break;
}
}
}
void EQEmu::MetricManager::FinalizeAll() {
for (auto iter : m_event_list) {
iter->Finalize();
}
}
void EQEmu::MetricManager::FinalizeById(int event_id) {
for (auto iter : m_event_list) {
if (iter->GetEventId() == event_id) {
iter->Finalize();
break;
}
}
}
void EQEmu::MetricManager::ExpireAll() {
for (auto iter : m_event_list) {
iter->Expire();
}
}
void EQEmu::MetricManager::ExpireById(int event_id) {
for (auto iter : m_event_list) {
if (iter->GetEventId() == event_id) {
iter->Expire();
break;
}
}
}
int EQEmu::MetricManager::get_next_event_id() {
return ++m_current_event_id;
}
+58
View File
@@ -0,0 +1,58 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2020 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef METRIC_MANAGER_H
#define METRIC_MANAGER_H
#include <list>
namespace EQEmu
{
class MetricEvent;
class MetricManager {
public:
MetricManager();
void Process();
int RegisterEvent(MetricEvent*);
void FlushAll();
void FlushById(int);
void FinalizeAll();
void FinalizeById(int);
void ExpireAll();
void ExpireById(int);
private:
int get_next_event_id();
int m_current_event_id;
std::list<MetricEvent*> m_event_list;
};
} // EQEmu
#endif // METRIC_MANAGER_H
-61
View File
@@ -19,9 +19,6 @@
#include "types.h"
#include <cstring>
#define ENC(c) (((c) & 0x3f) + ' ')
#define DEC(c) (((c) - ' ') & 0x3f)
std::map<int,std::string> DBFieldNames;
#ifndef WIN32
@@ -333,64 +330,6 @@ void LoadItemDBFieldNames() {
DBFieldNames[113]="unknown115"; // ? (end quote)
}
void encode_length(unsigned long length, char *out)
{
char buf[4];
memcpy(buf,&length,sizeof(unsigned long));
encode_chunk(buf,3,out);
}
unsigned long encode(char *in, unsigned long length, char *out)
{
unsigned long used=0,len=0;
while(used<length) {
encode_chunk(in+used,length-used,out+len);
used+=3;
len+=4;
}
*(out+len)=0;
return len;
}
unsigned long decode_length(char *in)
{
int length;
char buf[4];
decode_chunk(in,&buf[0]);
buf[3]=0;
memcpy(&length,buf,sizeof(unsigned long));
return length;
}
void decode(char *in, char *out)
{
char *ptr=in;
char *outptr=out;
while(*ptr) {
decode_chunk(ptr,outptr);
ptr+=4;
outptr+=3;
}
*outptr=0;
}
void encode_chunk(char *in, int len, char *out)
{
*out=ENC(in[0] >> 2);
*(out+1)=ENC((in[0] << 4)|(((len<2 ? 0 : in[1]) >> 4) & 0xF));
*(out+2)=ENC(((len<2 ? 0 : in[1]) << 2)|(((len<3 ? 0 : in[2]) >> 6) & 0x3));
*(out+3)=ENC((len<3 ? 0 : in[2]));
}
void decode_chunk(char *in, char *out)
{
*out = DEC(*in) << 2 | DEC(in[1]) >> 4;
*(out+1) = DEC(in[1]) << 4 | DEC(in[2]) >> 2;
*(out+2) = DEC(in[2]) << 6 | DEC(in[3]);
}
void dump_message_column(unsigned char *buffer, unsigned long length, std::string leader, FILE *to)
{
unsigned long i,j;
-7
View File
@@ -17,13 +17,6 @@ int Tokenize(std::string s, std::map<int,std::string> & tokens, char delim='|');
void LoadItemDBFieldNames();
void encode_length(unsigned long length, char *out);
unsigned long decode_length(char *in);
unsigned long encode(char *in, unsigned long length, char *out);
void decode(char *in, char *out);
void encode_chunk(char *in, int len, char *out);
void decode_chunk(char *in, char *out);
#ifndef WIN32
int print_stacktrace();
#endif
+8 -4
View File
@@ -116,17 +116,21 @@ bool EQ::Net::ConsoleServerConnection::SendChannelMessage(const ServerChannelMes
}
switch (scm->chan_num) {
if (RuleB(Chat, ServerWideAuction)) {
case 4: {
case 4: {
if (RuleB(Chat, ServerWideAuction)) {
QueueMessage(fmt::format("{0} auctions, '{1}'", scm->from, scm->message));
break;
} else { // I think we want default action in this case?
return false;
}
}
if (RuleB(Chat, ServerWideOOC)) {
case 5: {
case 5: {
if (RuleB(Chat, ServerWideOOC)) {
QueueMessage(fmt::format("{0} says ooc, '{1}'", scm->from, scm->message));
break;
} else { // I think we want default action in this case?
return false;
}
}
+1 -1
View File
@@ -399,7 +399,7 @@ void EQ::Net::DaybreakConnection::Process()
ProcessQueue();
}
catch (std::exception ex) {
catch (std::exception &ex) {
if (m_owner->m_on_error_message) {
m_owner->m_on_error_message(fmt::format("Error processing connection: {0}", ex.what()));
}
+5 -5
View File
@@ -61,7 +61,7 @@ EQ::Net::WebsocketServer::WebsocketServer(const std::string &addr, int port)
auto &connection = iter->second;
connection->GetWebsocketConnection()->ping("keepalive");
}
catch (std::exception) {
catch (std::exception &) {
iter->second->GetTCPConnection()->Disconnect();
}
@@ -157,7 +157,7 @@ void EQ::Net::WebsocketServer::DispatchEvent(WebsocketSubscriptionEvent evt, Jso
}
}
}
catch (std::exception) {
catch (std::exception &) {
}
}
@@ -190,7 +190,7 @@ Json::Value EQ::Net::WebsocketServer::Login(WebsocketServerConnection *connectio
return ret;
}
catch (std::exception) {
catch (std::exception &) {
throw WebsocketException("Unable to process login request");
}
}
@@ -212,7 +212,7 @@ Json::Value EQ::Net::WebsocketServer::Subscribe(WebsocketServerConnection *conne
catch (WebsocketException &ex) {
throw ex;
}
catch (std::exception) {
catch (std::exception &) {
throw WebsocketException("Unable to process unsubscribe request");
}
}
@@ -234,7 +234,7 @@ Json::Value EQ::Net::WebsocketServer::Unsubscribe(WebsocketServerConnection *con
catch (WebsocketException &ex) {
throw ex;
}
catch (std::exception) {
catch (std::exception &) {
throw WebsocketException("Unable to process unsubscribe request");
}
}
+2 -1
View File
@@ -37,6 +37,7 @@
#include <sstream>
#include <numeric>
#include <cassert>
#include <cinttypes>
namespace RoF2
@@ -3548,7 +3549,7 @@ namespace RoF2
{
eq->items[i].Unknown18 = 0;
if (i < 80) {
snprintf(eq->items[i].SerialNumber, sizeof(eq->items[i].SerialNumber), "%016d", emu->SerialNumber[i]);
snprintf(eq->items[i].SerialNumber, sizeof(eq->items[i].SerialNumber), "%016" PRId64, emu->SerialNumber[i]);
eq->ItemCost[i] = emu->ItemCost[i];
}
else {
-4
View File
@@ -190,10 +190,6 @@ bool PersistentTimer::Clear(Database *db) {
/* This function checks if the timer triggered */
bool PersistentTimer::Expired(Database *db, bool iReset) {
if (this == nullptr) {
LogError("Null timer during ->Check()!?\n");
return(true);
}
uint32 current_time = get_current_time();
if (current_time-start_time >= timer_time) {
if (enabled && iReset) {
+1
View File
@@ -158,6 +158,7 @@ RULE_BOOL(Character, AllowCrossClassTrainers, false, "")
RULE_BOOL(Character, PetsUseReagents, true, "Pets use reagent on spells")
RULE_BOOL(Character, DismountWater, true, "Dismount horses when entering water")
RULE_BOOL(Character, UseNoJunkFishing, false, "Disregards junk items when fishing")
RULE_BOOL(Character, SoftDeletes, true, "When characters are deleted in character select, they are only soft deleted")
RULE_CATEGORY_END()
RULE_CATEGORY(Mercs)
-3
View File
@@ -262,9 +262,6 @@ public:
}
ServerPacket* Copy() {
if (this == 0) {
return 0;
}
ServerPacket* ret = new ServerPacket(this->opcode, this->size);
if (this->size)
memcpy(ret->pBuffer, this->pBuffer, this->size);
+1 -1
View File
@@ -222,7 +222,7 @@ bool StringIsNumber(const std::string &s) {
auto r = stod(s);
return true;
}
catch (std::exception) {
catch (std::exception &) {
return false;
}
}
+1 -1
View File
@@ -34,7 +34,7 @@
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9145
#define CURRENT_BINARY_DATABASE_VERSION 9146
#ifdef BOTS
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9026
+2 -2
View File
@@ -813,7 +813,7 @@ sub fetch_utility_scripts {
sub setup_bots {
if ($OS eq "Windows") {
fetch_latest_windows_binaries_bots();
fetch_latest_windows_appveyor_bots();
}
if ($OS eq "Linux") {
build_linux_source("bots");
@@ -821,7 +821,7 @@ sub setup_bots {
bots_db_management();
run_database_check();
print "Bots should be setup, run your server and the #bot command should be available in-game\n";
print "Bots should be setup, run your server and the bot command should be available in-game (type '^help')\n";
}
sub show_menu_prompt {
File diff suppressed because it is too large Load Diff
+18 -2
View File
@@ -1,9 +1,15 @@
account
account_ip
account_flags
account_rewards
adventure_details
adventure_stats
buyer
char_recipe_list
character_auras
character_activities
character_alt_currency
character_alternate_abilities
character_auras
character_bandolier
character_bind
character_buffs
@@ -20,15 +26,22 @@ character_leadership_abilities
character_material
character_memmed_spells
character_pet_buffs
character_pet_info
character_pet_inventory
character_potionbelt
character_skills
character_spells
character_tasks
character_tribute
completed_tasks
data_buckets
faction_values
friends
guild_bank
guild_members
guild_ranks
guild_relations
guilds
instance_list_player
inventory
inventory_snapshots
@@ -36,6 +49,9 @@ keyring
mail
player_titlesets
quest_globals
sharedbank
timers
titles
zone_flags
trader
trader_audit
zone_flags"
+1
View File
@@ -399,6 +399,7 @@
9143|2019_09_16_account_table_changes.sql|SHOW COLUMNS FROM `account` LIKE 'ls_id'|empty|
9144|2019_11_09_logsys_description_update.sql|SELECT * FROM db_version WHERE version >= 9143|empty|
9145|2019_12_24_banned_ips_update.sql|SHOW TABLES LIKE 'Banned_IPs'|not_empty|
9146|2020_01_10_character_soft_deletes.sql|SHOW COLUMNS FROM `character_data` LIKE 'deleted_at'|empty|
# Upgrade conditions:
# This won't be needed after this system is implemented, but it is used database that are not
@@ -21,9 +21,9 @@
9020|2018_08_13_bots_inventory_update.sql|SELECT * FROM `inventory_versions` WHERE `version` = 2 and `bot_step` = 0|not_empty|
9021|2018_10_09_bots_owner_options.sql|SHOW TABLES LIKE 'bot_owner_options'|empty|
9022|2019_02_07_bots_stance_type_update.sql|SELECT * FROM `bot_spell_casting_chances` WHERE `spell_type_index` = '255' AND `class_id` = '255' AND `stance_index` = '0'|not_empty|
9023|2019_06_22_bots_owner_option_stats_update.sql|SHOW COLUMNS FROM `bot_owner_options` LIKE 'stats_update'|empty|
9023|2019_06_22_bots_owner_option_stats_update.sql|SELECT * FROM db_version WHERE bots_version >= 9023|empty|
9024|2019_06_27_bots_pet_get_lost.sql|SELECT `bot_command` FROM `bot_command_settings` WHERE `bot_command` LIKE 'petgetlost'|empty|
9025|2019_08_26_bots_owner_option_spawn_message.sql|SHOW COLUMNS FROM `bot_owner_options` LIKE 'spawn_message_enabled'|empty|
9025|2019_08_26_bots_owner_option_spawn_message.sql|SELECT * FROM db_version WHERE bots_version >= 9025|empty|
9026|2019_09_09_bots_owner_options_rework.sql|SHOW COLUMNS FROM `bot_owner_options` LIKE 'option_type'|empty|
# Upgrade conditions:
@@ -0,0 +1 @@
ALTER TABLE `character_data` ADD COLUMN `deleted_at` datetime NULL DEFAULT NULL;
-99
View File
@@ -2119,102 +2119,3 @@ void AdventureManager::Save()
}
}
void AdventureManager::Load()
{
//disabled for now
return;
char *data = nullptr;
FILE *f = fopen("adventure_state.dat", "r");
if(f)
{
fseek(f, 0, SEEK_END);
long length = ftell(f);
if(length > 0)
{
data = new char[length];
fseek(f, 0, SEEK_SET);
fread(data, length, 1, f);
}
fclose(f);
}
if(data)
{
char *ptr = data;
int number_of_adventures = *((int*)ptr);
ptr += sizeof(int);
for(int i = 0; i < number_of_adventures; ++i)
{
int count = *((int*)ptr);
ptr += sizeof(int);
int a_count = *((int*)ptr);
ptr += sizeof(int);
int template_id = *((int*)ptr);
ptr += sizeof(int);
int status = *((int*)ptr);
ptr += sizeof(int);
int instance_id = *((int*)ptr);
ptr += sizeof(int);
int rem_time = *((int*)ptr);
ptr += sizeof(int);
int num_players = *((int*)ptr);
ptr += sizeof(int);
AdventureTemplate *t = GetAdventureTemplate(template_id);
if(t)
{
auto adv =
new Adventure(t, count, a_count, (AdventureStatus)status, instance_id, rem_time);
for(int j = 0; j < num_players; ++j)
{
adv->AddPlayer((const char*)ptr, false);
ptr += strlen((const char*)ptr);
ptr += 1;
}
adventure_list.push_back(adv);
}
else
{
for(int j = 0; j < num_players; ++j)
{
ptr += strlen((const char*)ptr);
ptr += 1;
}
}
}
int number_of_finished = *((int*)ptr);
ptr += sizeof(int);
for(int k = 0; k < number_of_finished; ++k)
{
AdventureFinishEvent afe;
afe.win = *((bool*)ptr);
ptr += sizeof(bool);
afe.points = *((int*)ptr);
ptr += sizeof(int);
afe.theme = *((int*)ptr);
ptr += sizeof(int);
afe.name = (const char*)ptr;
ptr += strlen((const char*)ptr);
ptr += 1;
finished_list.push_back(afe);
}
safe_delete_array(data);
}
}
-1
View File
@@ -34,7 +34,6 @@ public:
void AddFinishedEvent(AdventureFinishEvent fe) { finished_list.push_back(fe); Save(); }
bool PopFinishedEvent(const char *name, AdventureFinishEvent &fe);
void Save();
void Load();
Adventure **GetFinishedAdventures(const char *player, int &count);
Adventure *GetActiveAdventure(const char *player);
-1
View File
@@ -396,7 +396,6 @@ int main(int argc, char** argv) {
LogInfo("Unable to load adventure templates");
}
adventure_manager.Load();
adventure_manager.LoadLeaderboardInfo();
LogInfo("Purging expired instances");
+6 -6
View File
@@ -24,7 +24,7 @@ void WebInterface::OnCall(uint16 opcode, EQ::Net::Packet &p)
std::stringstream ss(json_str);
ss >> root;
}
catch (std::exception) {
catch (std::exception &) {
SendError("Could not parse request");
return;
}
@@ -40,7 +40,7 @@ void WebInterface::OnCall(uint16 opcode, EQ::Net::Packet &p)
return;
}
}
catch (std::exception) {
catch (std::exception &) {
SendError("Invalid request: method not supplied");
return;
}
@@ -49,7 +49,7 @@ void WebInterface::OnCall(uint16 opcode, EQ::Net::Packet &p)
try {
params = root["params"];
}
catch (std::exception) {
catch (std::exception &) {
params = nullptr;
}
@@ -57,7 +57,7 @@ void WebInterface::OnCall(uint16 opcode, EQ::Net::Packet &p)
try {
id = root["id"].asString();
}
catch (std::exception) {
catch (std::exception &) {
id = "";
}
@@ -82,7 +82,7 @@ void WebInterface::Send(const Json::Value &value)
p.PutString(0, ss.str());
m_connection->Send(ServerOP_WebInterfaceCall, p);
}
catch (std::exception) {
catch (std::exception &) {
//Log error
}
}
@@ -116,7 +116,7 @@ void WebInterface::SendEvent(const Json::Value &value)
p.PutString(0, ss.str());
m_connection->Send(ServerOP_WebInterfaceEvent, p);
}
catch (std::exception) {
catch (std::exception &) {
//Log error
}
}
+194 -146
View File
@@ -31,23 +31,27 @@ extern std::vector<RaceClassAllocation> character_create_allocations;
extern std::vector<RaceClassCombos> character_create_race_class_combos;
// the current stuff is at the bottom of this function
void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **outApp, uint32 clientVersionBit)
/**
* @param account_id
* @param out_app
* @param client_version_bit
*/
void WorldDatabase::GetCharSelectInfo(uint32 account_id, EQApplicationPacket **out_app, uint32 client_version_bit)
{
/* Set Character Creation Limit */
EQEmu::versions::ClientVersion client_version = EQEmu::versions::ConvertClientVersionBitToClientVersion(clientVersionBit);
EQEmu::versions::ClientVersion
client_version = EQEmu::versions::ConvertClientVersionBitToClientVersion(client_version_bit);
size_t character_limit = EQEmu::constants::StaticLookup(client_version)->CharacterCreationLimit;
// Validate against absolute server max
if (character_limit > EQEmu::constants::CHARACTER_CREATION_LIMIT)
if (character_limit > EQEmu::constants::CHARACTER_CREATION_LIMIT) {
character_limit = EQEmu::constants::CHARACTER_CREATION_LIMIT;
}
// Force Titanium clients to use '8'
if (client_version == EQEmu::versions::ClientVersion::Titanium)
if (client_version == EQEmu::versions::ClientVersion::Titanium) {
character_limit = 8;
/* Get Character Info */
std::string cquery = StringFormat(
}
std::string character_list_query = StringFormat(
"SELECT "
"`id`, " // 0
"name, " // 1
@@ -71,237 +75,281 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou
"zone_id " // 19
"FROM "
"character_data "
"WHERE `account_id` = %i ORDER BY `name` LIMIT %u", accountID, character_limit);
auto results = database.QueryDatabase(cquery);
"WHERE `account_id` = %i AND deleted_at IS NULL ORDER BY `name` LIMIT %u",
account_id,
character_limit
);
auto results = database.QueryDatabase(character_list_query);
size_t character_count = results.RowCount();
if (character_count == 0) {
*outApp = new EQApplicationPacket(OP_SendCharInfo, sizeof(CharacterSelect_Struct));
CharacterSelect_Struct *cs = (CharacterSelect_Struct *)(*outApp)->pBuffer;
cs->CharCount = 0;
*out_app = new EQApplicationPacket(OP_SendCharInfo, sizeof(CharacterSelect_Struct));
CharacterSelect_Struct *cs = (CharacterSelect_Struct *) (*out_app)->pBuffer;
cs->CharCount = 0;
cs->TotalChars = character_limit;
return;
}
size_t packet_size = sizeof(CharacterSelect_Struct) + (sizeof(CharacterSelectEntry_Struct) * character_count);
*outApp = new EQApplicationPacket(OP_SendCharInfo, packet_size);
*out_app = new EQApplicationPacket(OP_SendCharInfo, packet_size);
unsigned char *buff_ptr = (*outApp)->pBuffer;
CharacterSelect_Struct *cs = (CharacterSelect_Struct *)buff_ptr;
unsigned char *buff_ptr = (*out_app)->pBuffer;
CharacterSelect_Struct *cs = (CharacterSelect_Struct *) buff_ptr;
cs->CharCount = character_count;
cs->CharCount = character_count;
cs->TotalChars = character_limit;
buff_ptr += sizeof(CharacterSelect_Struct);
for (auto row = results.begin(); row != results.end(); ++row) {
CharacterSelectEntry_Struct *cse = (CharacterSelectEntry_Struct *)buff_ptr;
PlayerProfile_Struct pp;
EQEmu::InventoryProfile inv;
CharacterSelectEntry_Struct *p_character_select_entry_struct = (CharacterSelectEntry_Struct *) buff_ptr;
PlayerProfile_Struct player_profile_struct;
EQEmu::InventoryProfile inventory_profile;
pp.SetPlayerProfileVersion(EQEmu::versions::ConvertClientVersionToMobVersion(client_version));
inv.SetInventoryVersion(client_version);
inv.SetGMInventory(true); // charsel can not interact with items..but, no harm in setting to full expansion support
player_profile_struct.SetPlayerProfileVersion(EQEmu::versions::ConvertClientVersionToMobVersion(client_version));
inventory_profile.SetInventoryVersion(client_version);
inventory_profile.SetGMInventory(true); // charsel can not interact with items..but, no harm in setting to full expansion support
uint32 character_id = (uint32)atoi(row[0]);
uint8 has_home = 0;
uint8 has_bind = 0;
uint32 character_id = (uint32) atoi(row[0]);
uint8 has_home = 0;
uint8 has_bind = 0;
memset(&pp, 0, sizeof(PlayerProfile_Struct));
/* Fill CharacterSelectEntry_Struct */
memset(cse->Name, 0, sizeof(cse->Name));
strcpy(cse->Name, row[1]);
cse->Class = (uint8)atoi(row[4]);
cse->Race = (uint32)atoi(row[3]);
cse->Level = (uint8)atoi(row[5]);
cse->ShroudClass = cse->Class;
cse->ShroudRace = cse->Race;
cse->Zone = (uint16)atoi(row[19]);
cse->Instance = 0;
cse->Gender = (uint8)atoi(row[2]);
cse->Face = (uint8)atoi(row[15]);
memset(&player_profile_struct, 0, sizeof(PlayerProfile_Struct));
for (uint32 matslot = 0; matslot < EQEmu::textures::materialCount; matslot++) { // Processed below
cse->Equip[matslot].Material = 0;
cse->Equip[matslot].Unknown1 = 0;
cse->Equip[matslot].EliteModel = 0;
cse->Equip[matslot].HerosForgeModel = 0;
cse->Equip[matslot].Unknown2 = 0;
cse->Equip[matslot].Color = 0;
}
memset(p_character_select_entry_struct->Name, 0, sizeof(p_character_select_entry_struct->Name));
strcpy(p_character_select_entry_struct->Name, row[1]);
p_character_select_entry_struct->Class = (uint8) atoi(row[4]);
p_character_select_entry_struct->Race = (uint32) atoi(row[3]);
p_character_select_entry_struct->Level = (uint8) atoi(row[5]);
p_character_select_entry_struct->ShroudClass = p_character_select_entry_struct->Class;
p_character_select_entry_struct->ShroudRace = p_character_select_entry_struct->Race;
p_character_select_entry_struct->Zone = (uint16) atoi(row[19]);
p_character_select_entry_struct->Instance = 0;
p_character_select_entry_struct->Gender = (uint8) atoi(row[2]);
p_character_select_entry_struct->Face = (uint8) atoi(row[15]);
cse->Unknown15 = 0xFF;
cse->Unknown19 = 0xFF;
cse->DrakkinTattoo = (uint32)atoi(row[17]);
cse->DrakkinDetails = (uint32)atoi(row[18]);
cse->Deity = (uint32)atoi(row[6]);
cse->PrimaryIDFile = 0; // Processed Below
cse->SecondaryIDFile = 0; // Processed Below
cse->HairColor = (uint8)atoi(row[9]);
cse->BeardColor = (uint8)atoi(row[10]);
cse->EyeColor1 = (uint8)atoi(row[11]);
cse->EyeColor2 = (uint8)atoi(row[12]);
cse->HairStyle = (uint8)atoi(row[13]);
cse->Beard = (uint8)atoi(row[14]);
cse->GoHome = 0; // Processed Below
cse->Tutorial = 0; // Processed Below
cse->DrakkinHeritage = (uint32)atoi(row[16]);
cse->Unknown1 = 0;
cse->Enabled = 1;
cse->LastLogin = (uint32)atoi(row[7]); // RoF2 value: 1212696584
cse->Unknown2 = 0;
/* Fill End */
for (uint32 material_slot = 0; material_slot < EQEmu::textures::materialCount; material_slot++) {
p_character_select_entry_struct->Equip[material_slot].Material = 0;
p_character_select_entry_struct->Equip[material_slot].Unknown1 = 0;
p_character_select_entry_struct->Equip[material_slot].EliteModel = 0;
p_character_select_entry_struct->Equip[material_slot].HerosForgeModel = 0;
p_character_select_entry_struct->Equip[material_slot].Unknown2 = 0;
p_character_select_entry_struct->Equip[material_slot].Color = 0;
}
p_character_select_entry_struct->Unknown15 = 0xFF;
p_character_select_entry_struct->Unknown19 = 0xFF;
p_character_select_entry_struct->DrakkinTattoo = (uint32) atoi(row[17]);
p_character_select_entry_struct->DrakkinDetails = (uint32) atoi(row[18]);
p_character_select_entry_struct->Deity = (uint32) atoi(row[6]);
p_character_select_entry_struct->PrimaryIDFile = 0; // Processed Below
p_character_select_entry_struct->SecondaryIDFile = 0; // Processed Below
p_character_select_entry_struct->HairColor = (uint8) atoi(row[9]);
p_character_select_entry_struct->BeardColor = (uint8) atoi(row[10]);
p_character_select_entry_struct->EyeColor1 = (uint8) atoi(row[11]);
p_character_select_entry_struct->EyeColor2 = (uint8) atoi(row[12]);
p_character_select_entry_struct->HairStyle = (uint8) atoi(row[13]);
p_character_select_entry_struct->Beard = (uint8) atoi(row[14]);
p_character_select_entry_struct->GoHome = 0; // Processed Below
p_character_select_entry_struct->Tutorial = 0; // Processed Below
p_character_select_entry_struct->DrakkinHeritage = (uint32) atoi(row[16]);
p_character_select_entry_struct->Unknown1 = 0;
p_character_select_entry_struct->Enabled = 1;
p_character_select_entry_struct->LastLogin = (uint32) atoi(row[7]); // RoF2 value: 1212696584
p_character_select_entry_struct->Unknown2 = 0;
if (RuleB(World, EnableReturnHomeButton)) {
int now = time(nullptr);
if ((now - atoi(row[7])) >= RuleI(World, MinOfflineTimeToReturnHome))
cse->GoHome = 1;
if ((now - atoi(row[7])) >= RuleI(World, MinOfflineTimeToReturnHome)) {
p_character_select_entry_struct->GoHome = 1;
}
}
if (RuleB(World, EnableTutorialButton) && (cse->Level <= RuleI(World, MaxLevelForTutorial))) {
cse->Tutorial = 1;
if (RuleB(World, EnableTutorialButton) && (p_character_select_entry_struct->Level <= RuleI(World, MaxLevelForTutorial))) {
p_character_select_entry_struct->Tutorial = 1;
}
/* Set Bind Point Data for any character that may possibly be missing it for any reason */
cquery = StringFormat("SELECT `zone_id`, `instance_id`, `x`, `y`, `z`, `heading`, `slot` FROM `character_bind` WHERE `id` = %i LIMIT 5", character_id);
auto results_bind = database.QueryDatabase(cquery);
auto bind_count = results_bind.RowCount();
for (auto row_b = results_bind.begin(); row_b != results_bind.end(); ++row_b) {
/**
* Bind
*/
character_list_query = StringFormat(
"SELECT `zone_id`, `instance_id`, `x`, `y`, `z`, `heading`, `slot` FROM `character_bind` WHERE `id` = %i LIMIT 5",
character_id
);
auto results_bind = database.QueryDatabase(character_list_query);
auto bind_count = results_bind.RowCount();
for (auto row_b = results_bind.begin(); row_b != results_bind.end(); ++row_b) {
if (row_b[6] && atoi(row_b[6]) == 4) {
has_home = 1;
// If our bind count is less than 5, we need to actually make use of this data so lets parse it
if (bind_count < 5) {
pp.binds[4].zoneId = atoi(row_b[0]);
pp.binds[4].instance_id = atoi(row_b[1]);
pp.binds[4].x = atof(row_b[2]);
pp.binds[4].y = atof(row_b[3]);
pp.binds[4].z = atof(row_b[4]);
pp.binds[4].heading = atof(row_b[5]);
player_profile_struct.binds[4].zoneId = atoi(row_b[0]);
player_profile_struct.binds[4].instance_id = atoi(row_b[1]);
player_profile_struct.binds[4].x = atof(row_b[2]);
player_profile_struct.binds[4].y = atof(row_b[3]);
player_profile_struct.binds[4].z = atof(row_b[4]);
player_profile_struct.binds[4].heading = atof(row_b[5]);
}
}
if (row_b[6] && atoi(row_b[6]) == 0){ has_bind = 1; }
if (row_b[6] && atoi(row_b[6]) == 0) { has_bind = 1; }
}
if (has_home == 0 || has_bind == 0) {
cquery = StringFormat("SELECT `zone_id`, `bind_id`, `x`, `y`, `z` FROM `start_zones` WHERE `player_class` = %i AND `player_deity` = %i AND `player_race` = %i",
cse->Class, cse->Deity, cse->Race);
auto results_bind = database.QueryDatabase(cquery);
for (auto row_d = results_bind.begin(); row_d != results_bind.end(); ++row_d) {
character_list_query = StringFormat(
"SELECT `zone_id`, `bind_id`, `x`, `y`, `z` FROM `start_zones` WHERE `player_class` = %i AND `player_deity` = %i AND `player_race` = %i",
p_character_select_entry_struct->Class,
p_character_select_entry_struct->Deity,
p_character_select_entry_struct->Race
);
auto results_bind = database.QueryDatabase(character_list_query);
for (auto row_d = results_bind.begin(); row_d != results_bind.end(); ++row_d) {
/* If a bind_id is specified, make them start there */
if (atoi(row_d[1]) != 0) {
pp.binds[4].zoneId = (uint32)atoi(row_d[1]);
GetSafePoints(pp.binds[4].zoneId, 0, &pp.binds[4].x, &pp.binds[4].y, &pp.binds[4].z);
player_profile_struct.binds[4].zoneId = (uint32) atoi(row_d[1]);
GetSafePoints(player_profile_struct.binds[4].zoneId, 0, &player_profile_struct.binds[4].x, &player_profile_struct.binds[4].y, &player_profile_struct.binds[4].z);
}
/* Otherwise, use the zone and coordinates given */
/* Otherwise, use the zone and coordinates given */
else {
pp.binds[4].zoneId = (uint32)atoi(row_d[0]);
player_profile_struct.binds[4].zoneId = (uint32) atoi(row_d[0]);
float x = atof(row_d[2]);
float y = atof(row_d[3]);
float z = atof(row_d[4]);
if (x == 0 && y == 0 && z == 0){ GetSafePoints(pp.binds[4].zoneId, 0, &x, &y, &z); }
pp.binds[4].x = x; pp.binds[4].y = y; pp.binds[4].z = z;
if (x == 0 && y == 0 && z == 0) { GetSafePoints(player_profile_struct.binds[4].zoneId, 0, &x, &y, &z); }
player_profile_struct.binds[4].x = x;
player_profile_struct.binds[4].y = y;
player_profile_struct.binds[4].z = z;
}
}
pp.binds[0] = pp.binds[4];
player_profile_struct.binds[0] = player_profile_struct.binds[4];
/* If no home bind set, set it */
if (has_home == 0) {
std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)"
std::string query = StringFormat(
"REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)"
" VALUES (%u, %u, %u, %f, %f, %f, %f, %i)",
character_id, pp.binds[4].zoneId, 0, pp.binds[4].x, pp.binds[4].y, pp.binds[4].z, pp.binds[4].heading, 4);
auto results_bset = QueryDatabase(query);
character_id,
player_profile_struct.binds[4].zoneId,
0,
player_profile_struct.binds[4].x,
player_profile_struct.binds[4].y,
player_profile_struct.binds[4].z,
player_profile_struct.binds[4].heading,
4
);
auto results_bset = QueryDatabase(query);
}
/* If no regular bind set, set it */
if (has_bind == 0) {
std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)"
std::string query = StringFormat(
"REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)"
" VALUES (%u, %u, %u, %f, %f, %f, %f, %i)",
character_id, pp.binds[0].zoneId, 0, pp.binds[0].x, pp.binds[0].y, pp.binds[0].z, pp.binds[0].heading, 0);
auto results_bset = QueryDatabase(query);
character_id,
player_profile_struct.binds[0].zoneId,
0,
player_profile_struct.binds[0].x,
player_profile_struct.binds[0].y,
player_profile_struct.binds[0].z,
player_profile_struct.binds[0].heading,
0
);
auto results_bset = QueryDatabase(query);
}
}
/* If our bind count is less than 5, then we have null data that needs to be filled in. */
if (bind_count < 5) {
// we know that home and main bind must be valid here, so we don't check those
// we also use home to fill in the null data like live does.
for (int i = 1; i < 4; i++) {
if (pp.binds[i].zoneId != 0) // we assume 0 is the only invalid one ...
for (int i = 1; i < 4; i++) {
if (player_profile_struct.binds[i].zoneId != 0) { // we assume 0 is the only invalid one ...
continue;
}
std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)"
std::string query = StringFormat(
"REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)"
" VALUES (%u, %u, %u, %f, %f, %f, %f, %i)",
character_id, pp.binds[4].zoneId, 0, pp.binds[4].x, pp.binds[4].y, pp.binds[4].z, pp.binds[4].heading, i);
auto results_bset = QueryDatabase(query);
character_id,
player_profile_struct.binds[4].zoneId,
0,
player_profile_struct.binds[4].x,
player_profile_struct.binds[4].y,
player_profile_struct.binds[4].z,
player_profile_struct.binds[4].heading,
i
);
auto results_bset = QueryDatabase(query);
}
}
/* Bind End */
/* Load Character Material Data for Char Select */
cquery = StringFormat("SELECT slot, red, green, blue, use_tint, color FROM `character_material` WHERE `id` = %u", character_id);
auto results_b = database.QueryDatabase(cquery); uint8 slot = 0;
for (auto row_b = results_b.begin(); row_b != results_b.end(); ++row_b) {
character_list_query = StringFormat(
"SELECT slot, red, green, blue, use_tint, color FROM `character_material` WHERE `id` = %u",
character_id
);
auto results_b = database.QueryDatabase(character_list_query);
uint8 slot = 0;
for (auto row_b = results_b.begin(); row_b != results_b.end(); ++row_b) {
slot = atoi(row_b[0]);
pp.item_tint.Slot[slot].Red = atoi(row_b[1]);
pp.item_tint.Slot[slot].Green = atoi(row_b[2]);
pp.item_tint.Slot[slot].Blue = atoi(row_b[3]);
pp.item_tint.Slot[slot].UseTint = atoi(row_b[4]);
player_profile_struct.item_tint.Slot[slot].Red = atoi(row_b[1]);
player_profile_struct.item_tint.Slot[slot].Green = atoi(row_b[2]);
player_profile_struct.item_tint.Slot[slot].Blue = atoi(row_b[3]);
player_profile_struct.item_tint.Slot[slot].UseTint = atoi(row_b[4]);
}
/* Character Material Data End */
/* Load Inventory */
// If we ensure that the material data is updated appropriately, we can do away with inventory loads
if (GetCharSelInventory(accountID, cse->Name, &inv)) {
const EQEmu::ItemData* item = nullptr;
const EQEmu::ItemInstance* inst = nullptr;
int16 invslot = 0;
if (GetCharSelInventory(account_id, p_character_select_entry_struct->Name, &inventory_profile)) {
const EQEmu::ItemData *item = nullptr;
const EQEmu::ItemInstance *inst = nullptr;
int16 inventory_slot = 0;
for (uint32 matslot = EQEmu::textures::textureBegin; matslot < EQEmu::textures::materialCount; matslot++) {
invslot = EQEmu::InventoryProfile::CalcSlotFromMaterial(matslot);
if (invslot == INVALID_INDEX) { continue; }
inst = inv.GetItem(invslot);
if (inst == nullptr) { continue; }
inventory_slot = EQEmu::InventoryProfile::CalcSlotFromMaterial(matslot);
if (inventory_slot == INVALID_INDEX) { continue; }
inst = inventory_profile.GetItem(inventory_slot);
if (inst == nullptr) {
continue;
}
item = inst->GetItem();
if (item == nullptr) { continue; }
if (item == nullptr) {
continue;
}
if (matslot > 6) {
uint32 idfile = 0;
uint32 item_id_file = 0;
// Weapon Models
if (inst->GetOrnamentationIDFile() != 0) {
idfile = inst->GetOrnamentationIDFile();
cse->Equip[matslot].Material = idfile;
item_id_file = inst->GetOrnamentationIDFile();
p_character_select_entry_struct->Equip[matslot].Material = item_id_file;
}
else {
if (strlen(item->IDFile) > 2) {
idfile = atoi(&item->IDFile[2]);
cse->Equip[matslot].Material = idfile;
item_id_file = atoi(&item->IDFile[2]);
p_character_select_entry_struct->Equip[matslot].Material = item_id_file;
}
}
if (matslot == EQEmu::textures::weaponPrimary) {
cse->PrimaryIDFile = idfile;
p_character_select_entry_struct->PrimaryIDFile = item_id_file;
}
else {
cse->SecondaryIDFile = idfile;
p_character_select_entry_struct->SecondaryIDFile = item_id_file;
}
}
else {
uint32 color = 0;
if (pp.item_tint.Slot[matslot].UseTint) {
color = pp.item_tint.Slot[matslot].Color;
if (player_profile_struct.item_tint.Slot[matslot].UseTint) {
color = player_profile_struct.item_tint.Slot[matslot].Color;
}
else {
color = inst->GetColor();
}
// Armor Materials/Models
cse->Equip[matslot].Material = item->Material;
cse->Equip[matslot].EliteModel = item->EliteMaterial;
cse->Equip[matslot].HerosForgeModel = inst->GetOrnamentHeroModel(matslot);
cse->Equip[matslot].Color = color;
p_character_select_entry_struct->Equip[matslot].Material = item->Material;
p_character_select_entry_struct->Equip[matslot].EliteModel = item->EliteMaterial;
p_character_select_entry_struct->Equip[matslot].HerosForgeModel = inst->GetOrnamentHeroModel(matslot);
p_character_select_entry_struct->Equip[matslot].Color = color;
}
}
}
else {
printf("Error loading inventory for %s\n", cse->Name);
printf("Error loading inventory for %s\n", p_character_select_entry_struct->Name);
}
/* Load Inventory End */
buff_ptr += sizeof(CharacterSelectEntry_Struct);
}
+1 -1
View File
@@ -30,7 +30,7 @@ struct CharacterSelect_Struct;
class WorldDatabase : public SharedDatabase {
public:
bool GetStartZone(PlayerProfile_Struct* in_pp, CharCreate_Struct* in_cc, bool isTitanium);
void GetCharSelectInfo(uint32 accountID, EQApplicationPacket **outApp, uint32 clientVersionBit);
void GetCharSelectInfo(uint32 account_id, EQApplicationPacket **out_app, uint32 client_version_bit);
int MoveCharacterToBind(int CharID, uint8 bindnum = 0);
void GetLauncherList(std::vector<std::string> &result);
+1
View File
@@ -82,6 +82,7 @@ SET(zone_sources
main.cpp
map.cpp
merc.cpp
metric_event_types.cpp
mob.cpp
mob_ai.cpp
mob_appearance.cpp
+87 -55
View File
@@ -5234,7 +5234,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b
return false;
}
int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16 spell_id)
int32 Bot::CalcBotAAFocus(focusType type, uint32 aa_ID, uint32 points, uint16 spell_id)
{
const SPDat_Spell_Struct &spell = spells[spell_id];
int32 value = 0;
@@ -5388,6 +5388,10 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16
if (type == focusImprovedDamage && base1 > value)
value = base1;
break;
case SE_ImprovedDamage2:
if (type == focusImprovedDamage2 && base1 > value)
value = base1;
break;
case SE_ImprovedHeal:
if (type == focusImprovedHeal && base1 > value)
value = base1;
@@ -5499,6 +5503,11 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16
value = base1;
break;
}
case SE_FcDamageAmt2: {
if(type == focusFcDamageAmt2)
value = base1;
break;
}
case SE_FcDamageAmtCrit: {
if(type == focusFcDamageAmtCrit)
value = base1;
@@ -5557,8 +5566,8 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16
return (value * lvlModifier / 100);
}
int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) {
if (IsBardSong(spell_id) && bottype != BotfocusFcBaseEffects)
int32 Bot::GetBotFocusEffect(focusType bottype, uint16 spell_id) {
if (IsBardSong(spell_id) && bottype != focusFcBaseEffects)
return 0;
int32 realTotal = 0;
@@ -5567,7 +5576,7 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) {
bool rand_effectiveness = false;
//Improved Healing, Damage & Mana Reduction are handled differently in that some are random percentages
//In these cases we need to find the most powerful effect, so that each piece of gear wont get its own chance
if((bottype == BotfocusManaCost || bottype == BotfocusImprovedHeal || bottype == BotfocusImprovedDamage) && RuleB(Spells, LiveLikeFocusEffects))
if(RuleB(Spells, LiveLikeFocusEffects) && (bottype == focusManaCost || bottype == focusImprovedHeal || bottype == focusImprovedDamage || bottype == focusImprovedDamage2 || bottype == focusResistRate))
rand_effectiveness = true;
//Check if item focus effect exists for the client.
@@ -5708,16 +5717,16 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) {
}
}
if(bottype == BotfocusReagentCost && IsSummonPetSpell(spell_id) && GetAA(aaElementalPact))
if(bottype == focusReagentCost && IsSummonPetSpell(spell_id) && GetAA(aaElementalPact))
return 100;
if(bottype == BotfocusReagentCost && (IsEffectInSpell(spell_id, SE_SummonItem) || IsSacrificeSpell(spell_id)))
if(bottype == focusReagentCost && (IsEffectInSpell(spell_id, SE_SummonItem) || IsSacrificeSpell(spell_id)))
return 0;
return (realTotal + realTotal2);
}
int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spell_id, bool best_focus) {
int32 Bot::CalcBotFocusEffect(focusType bottype, uint16 focus_id, uint16 spell_id, bool best_focus) {
if(!IsValidSpell(focus_id) || !IsValidSpell(spell_id))
return 0;
@@ -5847,7 +5856,21 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
return 0;
break;
case SE_ImprovedDamage:
if (bottype == BotfocusImprovedDamage) {
if (bottype == focusImprovedDamage) {
if(best_focus) {
if (focus_spell.base2[i] != 0)
value = focus_spell.base2[i];
else
value = focus_spell.base[i];
}
else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i])
value = focus_spell.base[i];
else
value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]);
}
break;
case SE_ImprovedDamage2:
if (bottype == focusImprovedDamage2) {
if(best_focus) {
if (focus_spell.base2[i] != 0)
value = focus_spell.base2[i];
@@ -5861,7 +5884,7 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
}
break;
case SE_ImprovedHeal:
if (bottype == BotfocusImprovedHeal) {
if (bottype == focusImprovedHeal) {
if(best_focus) {
if (focus_spell.base2[i] != 0)
value = focus_spell.base2[i];
@@ -5875,7 +5898,7 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
}
break;
case SE_ReduceManaCost:
if (bottype == BotfocusManaCost) {
if (bottype == focusManaCost) {
if(best_focus) {
if (focus_spell.base2[i] != 0)
value = focus_spell.base2[i];
@@ -5889,39 +5912,39 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
}
break;
case SE_IncreaseSpellHaste:
if (bottype == BotfocusSpellHaste && focus_spell.base[i] > value)
if (bottype == focusSpellHaste && focus_spell.base[i] > value)
value = focus_spell.base[i];
break;
case SE_IncreaseSpellDuration:
if (bottype == BotfocusSpellDuration && focus_spell.base[i] > value)
if (bottype == focusSpellDuration && focus_spell.base[i] > value)
value = focus_spell.base[i];
break;
case SE_SpellDurationIncByTic:
if (bottype == BotfocusSpellDurByTic && focus_spell.base[i] > value)
if (bottype == focusSpellDurByTic && focus_spell.base[i] > value)
value = focus_spell.base[i];
break;
case SE_SwarmPetDuration:
if (bottype == BotfocusSwarmPetDuration && focus_spell.base[i] > value)
if (bottype == focusSwarmPetDuration && focus_spell.base[i] > value)
value = focus_spell.base[i];
break;
case SE_IncreaseRange:
if (bottype == BotfocusRange && focus_spell.base[i] > value)
if (bottype == focusRange && focus_spell.base[i] > value)
value = focus_spell.base[i];
break;
case SE_ReduceReagentCost:
if (bottype == BotfocusReagentCost && focus_spell.base[i] > value)
if (bottype == focusReagentCost && focus_spell.base[i] > value)
value = focus_spell.base[i];
break;
case SE_PetPowerIncrease:
if (bottype == BotfocusPetPower && focus_spell.base[i] > value)
if (bottype == focusPetPower && focus_spell.base[i] > value)
value = focus_spell.base[i];
break;
case SE_SpellResistReduction:
if (bottype == BotfocusResistRate && focus_spell.base[i] > value)
if (bottype == focusResistRate && focus_spell.base[i] > value)
value = focus_spell.base[i];
break;
case SE_SpellHateMod:
if (bottype == BotfocusSpellHateMod) {
if (bottype == focusSpellHateMod) {
if(value != 0) {
if(value > 0) {
if(focus_spell.base[i] > value)
@@ -5936,12 +5959,12 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
}
break;
case SE_ReduceReuseTimer: {
if(bottype == BotfocusReduceRecastTime)
if(bottype == focusReduceRecastTime)
value = (focus_spell.base[i] / 1000);
break;
}
case SE_TriggerOnCast: {
if(bottype == BotfocusTriggerOnCast) {
if(bottype == focusTriggerOnCast) {
if(zone->random.Int(0, 100) <= focus_spell.base[i])
value = focus_spell.base2[i];
else
@@ -5950,24 +5973,24 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
break;
}
case SE_FcSpellVulnerability: {
if(bottype == BotfocusSpellVulnerability)
if(bottype == focusSpellVulnerability)
value = focus_spell.base[i];
break;
}
case SE_BlockNextSpellFocus: {
if(bottype == BotfocusBlockNextSpell) {
if(bottype == focusBlockNextSpell) {
if(zone->random.Int(1, 100) <= focus_spell.base[i])
value = 1;
}
break;
}
case SE_FcTwincast: {
if(bottype == BotfocusTwincast)
if(bottype == focusTwincast)
value = focus_spell.base[i];
break;
}
case SE_SympatheticProc: {
if(bottype == BotfocusSympatheticProc) {
if(bottype == focusSympatheticProc) {
float ProcChance = GetSympatheticProcChances(spell_id, focus_spell.base[i]);
if(zone->random.Real(0, 1) <= ProcChance)
value = focus_id;
@@ -5977,49 +6000,54 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
break;
}
case SE_FcDamageAmt: {
if(bottype == BotfocusFcDamageAmt)
if(bottype == focusFcDamageAmt)
value = focus_spell.base[i];
break;
}
case SE_FcDamageAmt2: {
if(bottype == focusFcDamageAmt2)
value = focus_spell.base[i];
break;
}
case SE_FcDamageAmtCrit: {
if(bottype == BotfocusFcDamageAmtCrit)
if(bottype == focusFcDamageAmtCrit)
value = focus_spell.base[i];
break;
}
case SE_FcHealAmtIncoming:
if(bottype == BotfocusFcHealAmtIncoming)
if(bottype == focusFcHealAmtIncoming)
value = focus_spell.base[i];
break;
case SE_FcHealPctCritIncoming:
if (bottype == BotfocusFcHealPctCritIncoming)
if (bottype == focusFcHealPctCritIncoming)
value = focus_spell.base[i];
break;
case SE_FcHealAmtCrit:
if(bottype == BotfocusFcHealAmtCrit)
if(bottype == focusFcHealAmtCrit)
value = focus_spell.base[i];
break;
case SE_FcHealAmt:
if(bottype == BotfocusFcHealAmt)
if(bottype == focusFcHealAmt)
value = focus_spell.base[i];
break;
case SE_FcHealPctIncoming:
if(bottype == BotfocusFcHealPctIncoming)
if(bottype == focusFcHealPctIncoming)
value = focus_spell.base[i];
break;
case SE_FcBaseEffects: {
if (bottype == BotfocusFcBaseEffects)
if (bottype == focusFcBaseEffects)
value = focus_spell.base[i];
break;
}
case SE_FcDamagePctCrit: {
if(bottype == BotfocusFcDamagePctCrit)
if(bottype == focusFcDamagePctCrit)
value = focus_spell.base[i];
break;
}
case SE_FcIncreaseNumHits: {
if(bottype == BotfocusIncreaseNumHits)
if(bottype == focusIncreaseNumHits)
value = focus_spell.base[i];
break;
@@ -6559,14 +6587,14 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
int32 Bot::CheckAggroAmount(uint16 spellid) {
int32 AggroAmount = Mob::CheckAggroAmount(spellid, nullptr);
int32 focusAggro = GetBotFocusEffect(BotfocusSpellHateMod, spellid);
int32 focusAggro = GetBotFocusEffect(focusSpellHateMod, spellid);
AggroAmount = (AggroAmount * (100 + focusAggro) / 100);
return AggroAmount;
}
int32 Bot::CheckHealAggroAmount(uint16 spellid, Mob *target, uint32 heal_possible) {
int32 AggroAmount = Mob::CheckHealAggroAmount(spellid, target, heal_possible);
int32 focusAggro = GetBotFocusEffect(BotfocusSpellHateMod, spellid);
int32 focusAggro = GetBotFocusEffect(focusSpellHateMod, spellid);
AggroAmount = (AggroAmount * (100 + focusAggro) / 100);
return AggroAmount;
}
@@ -6840,7 +6868,7 @@ int32 Bot::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
bool Critical = false;
int32 value_BaseEffect = 0;
value_BaseEffect = (value + (value*GetBotFocusEffect(BotfocusFcBaseEffects, spell_id) / 100));
value_BaseEffect = (value + (value*GetBotFocusEffect(focusFcBaseEffects, spell_id) / 100));
// Need to scale HT damage differently after level 40! It no longer scales by the constant value in the spell file. It scales differently, instead of 10 more damage per level, it does 30 more damage per level. So we multiply the level minus 40 times 20 if they are over level 40.
if ( (spell_id == SPELL_HARM_TOUCH || spell_id == SPELL_HARM_TOUCH2 || spell_id == SPELL_IMP_HARM_TOUCH ) && GetLevel() > 40)
value -= ((GetLevel() - 40) * 20);
@@ -6868,16 +6896,18 @@ int32 Bot::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
ratio += RuleI(Spells, WizCritRatio);
if (Critical) {
value = (value_BaseEffect * ratio / 100);
value += (value_BaseEffect * GetBotFocusEffect(BotfocusImprovedDamage, spell_id) / 100);
value += (int(value_BaseEffect * GetBotFocusEffect(BotfocusFcDamagePctCrit, spell_id) / 100) * ratio / 100);
value += (value_BaseEffect * GetBotFocusEffect(focusImprovedDamage, spell_id) / 100);
value += (value_BaseEffect * GetBotFocusEffect(focusImprovedDamage2, spell_id) / 100);
value += (int(value_BaseEffect * GetBotFocusEffect(focusFcDamagePctCrit, spell_id) / 100) * ratio / 100);
if (target) {
value += (int(value_BaseEffect * target->GetVulnerability(this, spell_id, 0) / 100) * ratio / 100);
value -= target->GetFcDamageAmtIncoming(this, spell_id);
}
value -= (GetBotFocusEffect(BotfocusFcDamageAmtCrit, spell_id) * ratio / 100);
value -= (GetBotFocusEffect(focusFcDamageAmtCrit, spell_id) * ratio / 100);
value -= GetBotFocusEffect(BotfocusFcDamageAmt, spell_id);
value -= GetBotFocusEffect(focusFcDamageAmt, spell_id);
value -= GetBotFocusEffect(focusFcDamageAmt2, spell_id);
if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5)
value += (GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value) * ratio / 100);
@@ -6889,15 +6919,17 @@ int32 Bot::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
}
value = value_BaseEffect;
value += (value_BaseEffect * GetBotFocusEffect(BotfocusImprovedDamage, spell_id) / 100);
value += (value_BaseEffect * GetBotFocusEffect(BotfocusFcDamagePctCrit, spell_id) / 100);
value += (value_BaseEffect * GetBotFocusEffect(focusImprovedDamage, spell_id) / 100);
value += (value_BaseEffect * GetBotFocusEffect(focusImprovedDamage2, spell_id) / 100);
value += (value_BaseEffect * GetBotFocusEffect(focusFcDamagePctCrit, spell_id) / 100);
if (target) {
value += (value_BaseEffect * target->GetVulnerability(this, spell_id, 0) / 100);
value -= target->GetFcDamageAmtIncoming(this, spell_id);
}
value -= GetBotFocusEffect(BotfocusFcDamageAmtCrit, spell_id);
value -= GetBotFocusEffect(BotfocusFcDamageAmt, spell_id);
value -= GetBotFocusEffect(focusFcDamageAmtCrit, spell_id);
value -= GetBotFocusEffect(focusFcDamageAmt, spell_id);
value -= GetBotFocusEffect(focusFcDamageAmt2, spell_id);
if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5)
value += GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value);
@@ -6912,9 +6944,9 @@ int32 Bot::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
int32 chance = 0;
int8 modifier = 1;
bool Critical = false;
value_BaseEffect = (value + (value*GetBotFocusEffect(BotfocusFcBaseEffects, spell_id) / 100));
value_BaseEffect = (value + (value*GetBotFocusEffect(focusFcBaseEffects, spell_id) / 100));
value = value_BaseEffect;
value += int(value_BaseEffect*GetBotFocusEffect(BotfocusImprovedHeal, spell_id) / 100);
value += int(value_BaseEffect*GetBotFocusEffect(focusImprovedHeal, spell_id) / 100);
if(spells[spell_id].buffduration < 1) {
chance += (itembonuses.CriticalHealChance + spellbonuses.CriticalHealChance + aabonuses.CriticalHealChance);
chance += target->GetFocusIncoming(focusFcHealPctCritIncoming, SE_FcHealPctCritIncoming, this, spell_id);
@@ -6927,8 +6959,8 @@ int32 Bot::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
}
value *= modifier;
value += (GetBotFocusEffect(BotfocusFcHealAmtCrit, spell_id) * modifier);
value += GetBotFocusEffect(BotfocusFcHealAmt, spell_id);
value += (GetBotFocusEffect(focusFcHealAmtCrit, spell_id) * modifier);
value += GetBotFocusEffect(focusFcHealAmt, spell_id);
value += target->GetFocusIncoming(focusFcHealAmtIncoming, SE_FcHealAmtIncoming, this, spell_id);
if(itembonuses.HealAmt && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5)
@@ -6953,7 +6985,7 @@ int32 Bot::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
int32 Bot::GetActSpellCasttime(uint16 spell_id, int32 casttime) {
int32 cast_reducer = 0;
cast_reducer += GetBotFocusEffect(BotfocusSpellHaste, spell_id);
cast_reducer += GetBotFocusEffect(focusSpellHaste, spell_id);
uint8 botlevel = GetLevel();
uint8 botclass = GetClass();
if (botlevel >= 51 && casttime >= 3000 && !BeneficialSpell(spell_id) && (botclass == SHADOWKNIGHT || botclass == RANGER || botclass == PALADIN || botclass == BEASTLORD ))
@@ -7088,7 +7120,7 @@ int32 Bot::GetActSpellCost(uint16 spell_id, int32 cost) {
}
}
int32 focus_redux = GetBotFocusEffect(BotfocusManaCost, spell_id);
int32 focus_redux = GetBotFocusEffect(focusManaCost, spell_id);
if(focus_redux > 0)
PercentManaReduction += zone->random.Real(1, (double)focus_redux);
@@ -7115,14 +7147,14 @@ int32 Bot::GetActSpellCost(uint16 spell_id, int32 cost) {
float Bot::GetActSpellRange(uint16 spell_id, float range) {
float extrange = 100;
extrange += GetBotFocusEffect(BotfocusRange, spell_id);
extrange += GetBotFocusEffect(focusRange, spell_id);
return ((range * extrange) / 100);
}
int32 Bot::GetActSpellDuration(uint16 spell_id, int32 duration) {
int increase = 100;
increase += GetBotFocusEffect(BotfocusSpellDuration, spell_id);
int tic_inc = 0; tic_inc = GetBotFocusEffect(BotfocusSpellDurByTic, spell_id);
increase += GetBotFocusEffect(focusSpellDuration, spell_id);
int tic_inc = 0; tic_inc = GetBotFocusEffect(focusSpellDurByTic, spell_id);
if(IsBeneficialSpell(spell_id)) {
switch (GetAA(aaSpellCastingReinforcement)) {
+3 -37
View File
@@ -99,40 +99,6 @@ class Bot : public NPC {
friend class Mob;
public:
// Class enums
enum BotfocusType { //focus types
BotfocusSpellHaste = 1,
BotfocusSpellDuration,
BotfocusRange,
BotfocusReagentCost,
BotfocusManaCost,
BotfocusImprovedHeal,
BotfocusImprovedDamage,
BotfocusImprovedDOT, //i dont know about this...
BotfocusFcDamagePctCrit,
BotfocusImprovedUndeadDamage,
BotfocusPetPower,
BotfocusResistRate,
BotfocusSpellHateMod,
BotfocusTriggerOnCast,
BotfocusSpellVulnerability,
BotfocusTwincast,
BotfocusSympatheticProc,
BotfocusFcDamageAmt,
BotfocusFcDamageAmtCrit,
BotfocusSpellDurByTic,
BotfocusSwarmPetDuration,
BotfocusReduceRecastTime,
BotfocusBlockNextSpell,
BotfocusFcHealPctIncoming,
BotfocusFcDamageAmtIncoming,
BotfocusFcHealAmtIncoming,
BotfocusFcBaseEffects,
BotfocusIncreaseNumHits,
BotfocusFcHealPctCritIncoming,
BotfocusFcHealAmt,
BotfocusFcHealAmtCrit,
};
enum BotTradeType { // types of trades a bot can do
BotTradeClientNormal,
BotTradeClientNoDropNoTrade
@@ -636,9 +602,9 @@ protected:
virtual void PetAIProcess();
virtual void BotMeditate(bool isSitting);
virtual bool CheckBotDoubleAttack(bool Triple = false);
virtual int32 GetBotFocusEffect(BotfocusType bottype, uint16 spell_id);
virtual int32 CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spell_id, bool best_focus=false);
virtual int32 CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16 spell_id);
virtual int32 GetBotFocusEffect(focusType bottype, uint16 spell_id);
virtual int32 CalcBotFocusEffect(focusType bottype, uint16 focus_id, uint16 spell_id, bool best_focus=false);
virtual int32 CalcBotAAFocus(focusType type, uint32 aa_ID, uint32 points, uint16 spell_id);
virtual void PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* client);
virtual bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0);
+6
View File
@@ -3414,6 +3414,12 @@ void bot_command_help(Client *c, const Seperator *sep)
c->Message(m_usage, "%c%s - %s", BOT_COMMAND_CHAR, command_iter.first.c_str(), command_iter.second->desc == nullptr ? "[no description]" : command_iter.second->desc);
++bot_commands_shown;
}
if (parse->PlayerHasQuestSub(EVENT_BOT_COMMAND)) {
int i = parse->EventPlayer(EVENT_BOT_COMMAND, c, sep->msg, 0);
if (i >= 1) {
bot_commands_shown += i;
}
}
c->Message(m_message, "%d bot command%s listed.", bot_commands_shown, bot_commands_shown != 1 ? "s" : "");
c->Message(m_note, "type %ccommand [help | usage] for more information", BOT_COMMAND_CHAR);
}
+26 -10
View File
@@ -1106,40 +1106,56 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
case ChatChannel_Say: { /* Say */
if(message[0] == COMMAND_CHAR) {
if(command_dispatch(this, message) == -2) {
if(parse->PlayerHasQuestSub(EVENT_COMMAND)) {
if (parse->PlayerHasQuestSub(EVENT_COMMAND)) {
int i = parse->EventPlayer(EVENT_COMMAND, this, message, 0);
if(i == 0 && !RuleB(Chat, SuppressCommandErrors)) {
if (i == 0 && !RuleB(Chat, SuppressCommandErrors)) {
Message(Chat::Red, "Command '%s' not recognized.", message);
}
} else {
if(!RuleB(Chat, SuppressCommandErrors))
}
else if (parse->PlayerHasQuestSub(EVENT_SAY)) {
int i = parse->EventPlayer(EVENT_SAY, this, message, 0);
if (i == 0 && !RuleB(Chat, SuppressCommandErrors)) {
Message(Chat::Red, "Command '%s' not recognized.", message);
}
}
else {
if (!RuleB(Chat, SuppressCommandErrors)) {
Message(Chat::Red, "Command '%s' not recognized.", message);
}
}
}
break;
}
if (EQEmu::ProfanityManager::IsCensorshipActive())
EQEmu::ProfanityManager::RedactMessage(message);
#ifdef BOTS
if (message[0] == BOT_COMMAND_CHAR) {
if (bot_command_dispatch(this, message) == -2) {
if (parse->PlayerHasQuestSub(EVENT_COMMAND)) {
int i = parse->EventPlayer(EVENT_COMMAND, this, message, 0);
if (parse->PlayerHasQuestSub(EVENT_BOT_COMMAND)) {
int i = parse->EventPlayer(EVENT_BOT_COMMAND, this, message, 0);
if (i == 0 && !RuleB(Chat, SuppressCommandErrors)) {
Message(Chat::Red, "Bot command '%s' not recognized.", message);
}
}
else if (parse->PlayerHasQuestSub(EVENT_SAY)) {
int i = parse->EventPlayer(EVENT_SAY, this, message, 0);
if (i == 0 && !RuleB(Chat, SuppressCommandErrors)) {
Message(Chat::Red, "Bot command '%s' not recognized.", message);
}
}
else {
if (!RuleB(Chat, SuppressCommandErrors))
if (!RuleB(Chat, SuppressCommandErrors)) {
Message(Chat::Red, "Bot command '%s' not recognized.", message);
}
}
}
break;
}
#endif
if (EQEmu::ProfanityManager::IsCensorshipActive()) {
EQEmu::ProfanityManager::RedactMessage(message);
}
Mob* sender = this;
if (GetPet() && GetTarget() == GetPet() && GetPet()->FindType(SE_VoiceGraft))
sender = GetPet();
+25 -2
View File
@@ -905,6 +905,8 @@ void Client::CompleteConnect()
entity_list.RefreshClientXTargets(this);
worldserver.RequestTellQueue(GetName());
entity_list.ScanCloseMobs(close_mobs, this);
}
// connecting opcode handlers
@@ -8286,7 +8288,18 @@ void Client::Handle_OP_ItemLinkClick(const EQApplicationPacket *app)
if (GetTarget() && GetTarget()->IsNPC()) {
if (silentsaylink) {
parse->EventNPC(EVENT_SAY, GetTarget()->CastToNPC(), this, response.c_str(), 0);
parse->EventPlayer(EVENT_SAY, this, response.c_str(), 0);
if (response[0] == '#' && parse->PlayerHasQuestSub(EVENT_COMMAND)) {
parse->EventPlayer(EVENT_COMMAND, this, response.c_str(), 0);
}
#ifdef BOTS
else if (response[0] == '^' && parse->PlayerHasQuestSub(EVENT_BOT_COMMAND)) {
parse->EventPlayer(EVENT_BOT_COMMAND, this, response.c_str(), 0);
}
#endif
else {
parse->EventPlayer(EVENT_SAY, this, response.c_str(), 0);
}
}
else {
Message(Chat::LightGray, "You say, '%s'", response.c_str());
@@ -8296,7 +8309,17 @@ void Client::Handle_OP_ItemLinkClick(const EQApplicationPacket *app)
}
else {
if (silentsaylink) {
parse->EventPlayer(EVENT_SAY, this, response.c_str(), 0);
if (response[0] == '#' && parse->PlayerHasQuestSub(EVENT_COMMAND)) {
parse->EventPlayer(EVENT_COMMAND, this, response.c_str(), 0);
}
#ifdef BOTS
else if (response[0] == '^' && parse->PlayerHasQuestSub(EVENT_BOT_COMMAND)) {
parse->EventPlayer(EVENT_BOT_COMMAND, this, response.c_str(), 0);
}
#endif
else {
parse->EventPlayer(EVENT_SAY, this, response.c_str(), 0);
}
}
else {
Message(Chat::LightGray, "You say, '%s'", response.c_str());
+1 -22
View File
@@ -256,28 +256,7 @@ bool Client::Process() {
* Used in aggro checks
*/
if (mob_close_scan_timer.Check()) {
close_mobs.clear();
float scan_range = RuleI(Range, MobCloseScanDistance) * RuleI(Range, MobCloseScanDistance);
auto &mob_list = entity_list.GetMobList();
for (auto itr : mob_list) {
Mob *mob = itr.second;
float distance = DistanceSquared(m_Position, mob->GetPosition());
if (mob->GetID() <= 0) {
continue;
}
if (mob->IsNPC() || mob->IsClient()) {
if (distance <= scan_range) {
close_mobs.insert(std::pair<uint16, Mob *>(mob->GetID(), mob));
}
else if ((mob->GetAggroRange() * mob->GetAggroRange()) > scan_range) {
close_mobs.insert(std::pair<uint16, Mob *>(mob->GetID(), mob));
}
}
}
entity_list.ScanCloseMobs(close_mobs, this);
}
bool may_use_attacks = false;
+8 -21
View File
@@ -783,6 +783,12 @@ void command_help(Client *c, const Seperator *sep)
commands_shown++;
c->Message(Chat::White, " %c%s %s", COMMAND_CHAR, cur->first.c_str(), cur->second->desc == nullptr?"":cur->second->desc);
}
if (parse->PlayerHasQuestSub(EVENT_COMMAND)) {
int i = parse->EventPlayer(EVENT_COMMAND, c, sep->msg, 0);
if (i >= 1) {
commands_shown += i;
}
}
c->Message(Chat::White, "%d command%s listed.", commands_shown, commands_shown!=1?"s":"");
}
@@ -2167,25 +2173,6 @@ void command_spoff(Client *c, const Seperator *sep)
safe_delete(outapp);
}
void command_itemtest(Client *c, const Seperator *sep)
{
char chBuffer[8192] = {0};
//Using this to determine new item layout
FILE* f = nullptr;
if (!(f = fopen("c:\\EQEMUcvs\\ItemDump.txt", "rb"))) {
c->Message(Chat::Red, "Error: Could not open c:\\EQEMUcvs\\ItemDump.txt");
return;
}
fread(chBuffer, sizeof(chBuffer), sizeof(char), f);
fclose(f);
auto outapp = new EQApplicationPacket(OP_ItemLinkResponse, strlen(chBuffer) + 5);
memcpy(&outapp->pBuffer[4], chBuffer, strlen(chBuffer));
c->QueuePacket(outapp);
safe_delete(outapp);
}
void command_gassign(Client *c, const Seperator *sep)
{
if (sep->IsNumber(1) && c->GetTarget() && c->GetTarget()->IsNPC() && c->GetTarget()->CastToNPC()->GetSpawnPointID() > 0) {
@@ -13264,8 +13251,8 @@ void command_bot(Client *c, const Seperator *sep)
}
if (bot_command_dispatch(c, bot_message.c_str()) == -2) {
if (parse->PlayerHasQuestSub(EVENT_COMMAND)) {
int i = parse->EventPlayer(EVENT_COMMAND, c, bot_message, 0);
if (parse->PlayerHasQuestSub(EVENT_BOT_COMMAND)) {
int i = parse->EventPlayer(EVENT_BOT_COMMAND, c, bot_message, 0);
if (i == 0 && !RuleB(Chat, SuppressCommandErrors)) {
c->Message(Chat::Red, "Bot command '%s' not recognized.", bot_message.c_str());
}
-1
View File
@@ -150,7 +150,6 @@ void command_ipc(Client *c, const Seperator *sep);
void command_iplookup(Client *c, const Seperator *sep);
void command_iteminfo(Client *c, const Seperator *sep);
void command_itemsearch(Client *c, const Seperator *sep);
void command_itemtest(Client *c, const Seperator *sep);
void command_kick(Client *c, const Seperator *sep);
void command_killallnpcs(Client *c, const Seperator *sep);
void command_kill(Client *c, const Seperator *sep);
+4 -2
View File
@@ -809,11 +809,13 @@ void EntityList::AESpell(
* 1 = PC
* 2 = NPC
*/
if (spells[spell_id].pcnpc_only_flag == 1 && !current_mob->IsClient() && !current_mob->IsMerc()) {
if (spells[spell_id].pcnpc_only_flag == 1 && !current_mob->IsClient() && !current_mob->IsMerc() &&
!current_mob->IsBot()) {
continue;
}
if (spells[spell_id].pcnpc_only_flag == 2 && (current_mob->IsClient() || current_mob->IsMerc())) {
if (spells[spell_id].pcnpc_only_flag == 2 &&
(current_mob->IsClient() || current_mob->IsMerc() || current_mob->IsBot())) {
continue;
}
+16 -3
View File
@@ -98,7 +98,7 @@ const char *QuestEventSubroutines[_LargestEventID] = {
"EVENT_DUEL_LOSE",
"EVENT_ENCOUNTER_LOAD",
"EVENT_ENCOUNTER_UNLOAD",
"EVENT_SAY",
"EVENT_COMMAND",
"EVENT_DROP_ITEM",
"EVENT_DESTROY_ITEM",
"EVENT_FEIGN_DEATH",
@@ -119,6 +119,7 @@ const char *QuestEventSubroutines[_LargestEventID] = {
"EVENT_DEATH_ZONE",
"EVENT_USE_SKILL",
"EVENT_COMBINE_VALIDATE",
"EVENT_BOT_COMMAND"
};
PerlembParser::PerlembParser() : perl(nullptr)
@@ -1542,9 +1543,12 @@ void PerlembParser::ExportEventVariables(
}
case EVENT_COMMAND: {
Seperator sep(data);
ExportVar(package_name.c_str(), "command", (sep.arg[0] + 1));
ExportVar(package_name.c_str(), "args", (sep.argnum >= 1 ? (&data[strlen(sep.arg[0]) + 1]) : "0"));
ExportVar(package_name.c_str(), "data", objid);
ExportVar(package_name.c_str(), "text", data);
ExportVar(package_name.c_str(), "data", "0");
ExportVar(package_name.c_str(), "langid", "0");
ExportVar(package_name.c_str(), "langid", extradata);
break;
}
@@ -1610,6 +1614,15 @@ void PerlembParser::ExportEventVariables(
ExportVar(package_name.c_str(), "tradeskill_id", tradeskill_id.c_str());
break;
}
case EVENT_BOT_COMMAND: {
Seperator sep(data);
ExportVar(package_name.c_str(), "bot_command", (sep.arg[0] + 1));
ExportVar(package_name.c_str(), "args", (sep.argnum >= 1 ? (&data[strlen(sep.arg[0]) + 1]) : "0"));
ExportVar(package_name.c_str(), "data", objid);
ExportVar(package_name.c_str(), "text", data);
ExportVar(package_name.c_str(), "langid", extradata);
break;
}
default: {
break;
+10 -3
View File
@@ -65,6 +65,8 @@ Entity::Entity()
id = 0;
initial_id = 0;
spawn_timestamp = time(nullptr);
m_metric_event = nullptr;
}
Entity::~Entity()
@@ -2654,7 +2656,12 @@ void EntityList::ScanCloseMobs(std::unordered_map<uint16, Mob *> &close_mobs, Mo
}
}
LogAIScanClose("Close List Size [{}] for mob [{}]", close_mobs.size(), scanning_mob->GetCleanName());
LogAIScanClose(
"[{}] Scanning Close List | list_size [{}] moving [{}]",
scanning_mob->GetCleanName(),
close_mobs.size(),
scanning_mob->IsMoving() ? "true" : "false"
);
}
bool EntityList::RemoveMerc(uint16 delete_id)
@@ -4955,10 +4962,10 @@ void EntityList::GetTargetsForConeArea(Mob *start, float min_radius, float radiu
continue;
}
// check PC/NPC only flag 1 = PCs, 2 = NPCs
if (pcnpc == 1 && !ptr->IsClient() && !ptr->IsMerc()) {
if (pcnpc == 1 && !ptr->IsClient() && !ptr->IsMerc() && !ptr->IsBot()) {
++it;
continue;
} else if (pcnpc == 2 && (ptr->IsClient() || ptr->IsMerc())) {
} else if (pcnpc == 2 && (ptr->IsClient() || ptr->IsMerc() || ptr->IsBot())) {
++it;
continue;
}
+6
View File
@@ -26,6 +26,7 @@
#include "../common/servertalk.h"
#include "../common/bodytypes.h"
#include "../common/eq_constants.h"
#include "../common/metric_event.h"
#include "position.h"
#include "zonedump.h"
@@ -121,6 +122,9 @@ public:
const Bot* CastToBot() const;
#endif
EQEmu::MetricEvent* GetMetricEvent() { return m_metric_event; }
bool SetMetricEvent(EQEmu::MetricEvent* metric_event) { if (!m_metric_event) { m_metric_event = metric_event; return true; } else { return false; } }
protected:
friend class EntityList;
inline virtual void SetID(uint16 set_id) {
@@ -135,6 +139,8 @@ private:
uint16 id;
uint16 initial_id;
time_t spawn_timestamp;
EQEmu::MetricEvent* m_metric_event;
};
class EntityList
+1
View File
@@ -87,6 +87,7 @@ typedef enum {
EVENT_DEATH_ZONE,
EVENT_USE_SKILL,
EVENT_COMBINE_VALIDATE,
EVENT_BOT_COMMAND,
_LargestEventID
} QuestEventID;
+7 -7
View File
@@ -1397,7 +1397,7 @@ void Lua_Client::QuestReward(Lua_Mob target, luabind::adl::object reward) {
if (luabind::type(cur) != LUA_TNIL) {
try {
copper = luabind::object_cast<uint32>(cur);
} catch (luabind::cast_failed) {
} catch (luabind::cast_failed &) {
}
}
@@ -1405,7 +1405,7 @@ void Lua_Client::QuestReward(Lua_Mob target, luabind::adl::object reward) {
if (luabind::type(cur) != LUA_TNIL) {
try {
silver = luabind::object_cast<uint32>(cur);
} catch (luabind::cast_failed) {
} catch (luabind::cast_failed &) {
}
}
@@ -1413,7 +1413,7 @@ void Lua_Client::QuestReward(Lua_Mob target, luabind::adl::object reward) {
if (luabind::type(cur) != LUA_TNIL) {
try {
gold = luabind::object_cast<uint32>(cur);
} catch (luabind::cast_failed) {
} catch (luabind::cast_failed &) {
}
}
@@ -1421,7 +1421,7 @@ void Lua_Client::QuestReward(Lua_Mob target, luabind::adl::object reward) {
if (luabind::type(cur) != LUA_TNIL) {
try {
platinum = luabind::object_cast<uint32>(cur);
} catch (luabind::cast_failed) {
} catch (luabind::cast_failed &) {
}
}
@@ -1429,7 +1429,7 @@ void Lua_Client::QuestReward(Lua_Mob target, luabind::adl::object reward) {
if (luabind::type(cur) != LUA_TNIL) {
try {
itemid = luabind::object_cast<uint32>(cur);
} catch (luabind::cast_failed) {
} catch (luabind::cast_failed &) {
}
}
@@ -1437,7 +1437,7 @@ void Lua_Client::QuestReward(Lua_Mob target, luabind::adl::object reward) {
if (luabind::type(cur) != LUA_TNIL) {
try {
exp = luabind::object_cast<uint32>(cur);
} catch (luabind::cast_failed) {
} catch (luabind::cast_failed &) {
}
}
@@ -1445,7 +1445,7 @@ void Lua_Client::QuestReward(Lua_Mob target, luabind::adl::object reward) {
if (luabind::type(cur) != LUA_TNIL) {
try {
faction = luabind::object_cast<bool>(cur);
} catch (luabind::cast_failed) {
} catch (luabind::cast_failed &) {
}
}
+19 -19
View File
@@ -571,7 +571,7 @@ void lua_task_selector(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
cur_value = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
} else {
count = i - 1;
@@ -601,7 +601,7 @@ void lua_enable_task(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
cur_value = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
} else {
count = i - 1;
@@ -628,7 +628,7 @@ void lua_disable_task(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
cur_value = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
} else {
count = i - 1;
@@ -1156,7 +1156,7 @@ void lua_add_spawn_point(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
spawn2_id = luabind::object_cast<uint32>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
return;
}
} else {
@@ -1167,7 +1167,7 @@ void lua_add_spawn_point(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
spawngroup_id = luabind::object_cast<uint32>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
return;
}
} else {
@@ -1178,7 +1178,7 @@ void lua_add_spawn_point(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
x = luabind::object_cast<float>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
return;
}
} else {
@@ -1189,7 +1189,7 @@ void lua_add_spawn_point(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
y = luabind::object_cast<float>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
return;
}
} else {
@@ -1200,7 +1200,7 @@ void lua_add_spawn_point(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
z = luabind::object_cast<float>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
return;
}
} else {
@@ -1211,7 +1211,7 @@ void lua_add_spawn_point(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
heading = luabind::object_cast<float>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
return;
}
} else {
@@ -1222,7 +1222,7 @@ void lua_add_spawn_point(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
respawn = luabind::object_cast<uint32>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
return;
}
} else {
@@ -1233,7 +1233,7 @@ void lua_add_spawn_point(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
variance = luabind::object_cast<uint32>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
return;
}
} else {
@@ -1244,7 +1244,7 @@ void lua_add_spawn_point(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
timeleft = luabind::object_cast<uint32>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1252,7 +1252,7 @@ void lua_add_spawn_point(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
grid = luabind::object_cast<uint32>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1260,7 +1260,7 @@ void lua_add_spawn_point(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
condition_id = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1268,7 +1268,7 @@ void lua_add_spawn_point(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
condition_min_value = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1276,7 +1276,7 @@ void lua_add_spawn_point(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
enabled = luabind::object_cast<bool>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1284,7 +1284,7 @@ void lua_add_spawn_point(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
animation = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1399,7 +1399,7 @@ void lua_update_zone_header(std::string type, std::string value) {
try { \
npc_type->name = luabind::object_cast<c_type>(cur); \
} \
catch(luabind::cast_failed) { \
catch(luabind::cast_failed &) { \
npc_type->size = default_value; \
} \
} \
@@ -1415,7 +1415,7 @@ void lua_update_zone_header(std::string type, std::string value) {
std::string tmp = luabind::object_cast<std::string>(cur); \
strncpy(npc_type->name, tmp.c_str(), str_length); \
} \
catch(luabind::cast_failed) { \
catch(luabind::cast_failed &) { \
strncpy(npc_type->name, default_value, str_length); \
} \
} \
+28 -28
View File
@@ -113,7 +113,7 @@ bool Lua_Mob::Attack(Lua_Mob other, int hand, bool from_riposte, bool is_striket
if(luabind::type(cur) != LUA_TNIL) {
try {
options.armor_pen_flat = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -121,7 +121,7 @@ bool Lua_Mob::Attack(Lua_Mob other, int hand, bool from_riposte, bool is_striket
if(luabind::type(cur) != LUA_TNIL) {
try {
options.crit_flat = luabind::object_cast<float>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -129,7 +129,7 @@ bool Lua_Mob::Attack(Lua_Mob other, int hand, bool from_riposte, bool is_striket
if(luabind::type(cur) != LUA_TNIL) {
try {
options.damage_flat = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -137,7 +137,7 @@ bool Lua_Mob::Attack(Lua_Mob other, int hand, bool from_riposte, bool is_striket
if(luabind::type(cur) != LUA_TNIL) {
try {
options.hate_flat = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -145,7 +145,7 @@ bool Lua_Mob::Attack(Lua_Mob other, int hand, bool from_riposte, bool is_striket
if(luabind::type(cur) != LUA_TNIL) {
try {
options.armor_pen_percent = luabind::object_cast<float>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -153,7 +153,7 @@ bool Lua_Mob::Attack(Lua_Mob other, int hand, bool from_riposte, bool is_striket
if(luabind::type(cur) != LUA_TNIL) {
try {
options.crit_percent = luabind::object_cast<float>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -161,7 +161,7 @@ bool Lua_Mob::Attack(Lua_Mob other, int hand, bool from_riposte, bool is_striket
if(luabind::type(cur) != LUA_TNIL) {
try {
options.damage_percent = luabind::object_cast<float>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -169,7 +169,7 @@ bool Lua_Mob::Attack(Lua_Mob other, int hand, bool from_riposte, bool is_striket
if(luabind::type(cur) != LUA_TNIL) {
try {
options.hate_percent = luabind::object_cast<float>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
}
@@ -785,7 +785,7 @@ void Lua_Mob::QuestSay(Lua_Client client, const char *message, luabind::adl::obj
if (luabind::type(cur) != LUA_TNIL) {
try {
journal_opts.speak_mode = static_cast<Journal::SpeakMode>(luabind::object_cast<int>(cur));
} catch (luabind::cast_failed) {
} catch (luabind::cast_failed &) {
}
}
@@ -793,7 +793,7 @@ void Lua_Mob::QuestSay(Lua_Client client, const char *message, luabind::adl::obj
if (luabind::type(cur) != LUA_TNIL) {
try {
journal_opts.journal_mode = static_cast<Journal::Mode>(luabind::object_cast<int>(cur));
} catch (luabind::cast_failed) {
} catch (luabind::cast_failed &) {
}
}
@@ -801,7 +801,7 @@ void Lua_Mob::QuestSay(Lua_Client client, const char *message, luabind::adl::obj
if (luabind::type(cur) != LUA_TNIL) {
try {
journal_opts.language = luabind::object_cast<int>(cur);
} catch (luabind::cast_failed) {
} catch (luabind::cast_failed &) {
}
}
@@ -809,7 +809,7 @@ void Lua_Mob::QuestSay(Lua_Client client, const char *message, luabind::adl::obj
if (luabind::type(cur) != LUA_TNIL) {
try {
journal_opts.message_type = luabind::object_cast<int>(cur);
} catch (luabind::cast_failed) {
} catch (luabind::cast_failed &) {
}
}
}
@@ -1568,7 +1568,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
race = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1576,7 +1576,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
gender = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1584,7 +1584,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
texture = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1592,7 +1592,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
helmtexture = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1600,7 +1600,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
haircolor = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1608,7 +1608,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
beardcolor = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1616,7 +1616,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
eyecolor1 = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1624,7 +1624,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
eyecolor2 = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1632,7 +1632,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
hairstyle = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1640,7 +1640,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
luclinface = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1648,7 +1648,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
beard = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1656,7 +1656,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
aa_title = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1664,7 +1664,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
drakkin_heritage = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1672,7 +1672,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
drakkin_tattoo = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1680,7 +1680,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
drakkin_details = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1688,7 +1688,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
size = luabind::object_cast<float>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
+3 -1
View File
@@ -124,7 +124,8 @@ const char *LuaEvents[_LargestEventID] = {
"event_spawn_zone",
"event_death_zone",
"event_use_skill",
"event_combine_validate"
"event_combine_validate",
"event_bot_command"
};
extern Zone *zone;
@@ -208,6 +209,7 @@ LuaParser::LuaParser() {
PlayerArgumentDispatch[EVENT_UNHANDLED_OPCODE] = handle_player_packet;
PlayerArgumentDispatch[EVENT_USE_SKILL] = handle_player_use_skill;
PlayerArgumentDispatch[EVENT_COMBINE_VALIDATE] = handle_player_combine_validate;
PlayerArgumentDispatch[EVENT_BOT_COMMAND] = handle_player_bot_command;
ItemArgumentDispatch[EVENT_ITEM_CLICK] = handle_item_click;
ItemArgumentDispatch[EVENT_ITEM_CLICK_CAST] = handle_item_click;
+19
View File
@@ -539,6 +539,25 @@ void handle_player_combine_validate(QuestInterface* parse, lua_State* L, Client*
lua_setfield(L, -2, "tradeskill_id");
}
void handle_player_bot_command(QuestInterface* parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<EQEmu::Any>* extra_pointers) {
Seperator sep(data.c_str(), ' ', 10, 100, true);
std::string bot_command(sep.arg[0] + 1);
lua_pushstring(L, bot_command.c_str());
lua_setfield(L, -2, "bot_command");
luabind::adl::object args = luabind::newtable(L);
int max_args = sep.GetMaxArgNum();
for (int i = 1; i < max_args; ++i) {
if (strlen(sep.arg[i]) > 0) {
args[i] = std::string(sep.arg[i]);
}
}
args.push(L);
lua_setfield(L, -2, "args");
}
//Item
void handle_item_click(QuestInterface *parse, lua_State* L, Client* client, EQEmu::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers) {
+2
View File
@@ -99,6 +99,8 @@ void handle_player_use_skill(QuestInterface *parse, lua_State* L, Client* client
std::vector<EQEmu::Any> *extra_pointers);
void handle_player_combine_validate(QuestInterface* parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<EQEmu::Any>* extra_pointers);
void handle_player_bot_command(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers);
//Item
void handle_item_click(QuestInterface *parse, lua_State* L, Client* client, EQEmu::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data,
+3
View File
@@ -42,6 +42,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../common/eqemu_exception.h"
#include "../common/spdat.h"
#include "../common/eqemu_logsys.h"
#include "../common/metric_manager.h"
#include "api_service.h"
#include "zone_config.h"
@@ -111,6 +112,7 @@ const SPDat_Spell_Struct* spells;
int32 SPDAT_RECORDS = -1;
const ZoneConfig *Config;
double frame_time = 0.0;
EQEmu::MetricManager metrics;
void Shutdown();
void UpdateWindowTitle(char* iNewTitle);
@@ -537,6 +539,7 @@ int main(int argc, char** argv) {
quest_manager.Process();
}
metrics.Process();
}
}
+35
View File
@@ -0,0 +1,35 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2020 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/metric_event.h"
#include "npc.h"
class NPC::EventNpcStatsMonitor : EQEmu::MetricEvent {
public:
virtual EventType GetEventType() const { return EventType::eventNpcStatsMonitor; }
virtual void Process() {}
virtual void Flush() {}
virtual void Finalize() { MetricEvent::Finalize(); }
virtual void Expire() { MetricEvent::Expire(); }
};
+2
View File
@@ -459,6 +459,8 @@ Mob::Mob(
#ifdef BOTS
m_manual_follow = false;
#endif
mob_scan_close.Trigger();
}
Mob::~Mob()
+1 -2
View File
@@ -624,8 +624,7 @@ public:
//AI
static uint32 GetLevelCon(uint8 mylevel, uint8 iOtherLevel);
inline uint32 GetLevelCon(uint8 iOtherLevel) const {
return this ? GetLevelCon(GetLevel(), iOtherLevel) : CON_GRAY; }
inline uint32 GetLevelCon(uint8 iOtherLevel) const { return GetLevelCon(GetLevel(), iOtherLevel); }
virtual void AddToHateList(Mob* other, uint32 hate = 0, int32 damage = 0, bool iYellForHelp = true,
bool bFrenzy = false, bool iBuffTic = false, uint16 spell_id = SPELL_UNKNOWN, bool pet_comand = false);
bool RemoveFromHateList(Mob* mob);
+13 -7
View File
@@ -448,6 +448,18 @@ uint32 NPC::GetRoamboxMinDelay() const
NPC::~NPC()
{
auto metric_event = GetMetricEvent();
if (metric_event) {
switch (metric_event->GetEventType()) {
case EQEmu::MetricEvent::EventType::eventNpcStatsMonitor:
metric_event->Finalize();
SetMetricEvent(nullptr);
default:
break;
}
}
AI_Stop();
if(proximity != nullptr) {
@@ -705,12 +717,6 @@ bool NPC::Process()
SpellProcess();
if (mob_scan_close.Check()) {
LogAIScanClose(
"is_moving [{}] npc [{}] timer [{}]",
moving ? "true" : "false",
GetCleanName(),
mob_scan_close.GetDuration()
);
entity_list.ScanCloseMobs(close_mobs, this);
@@ -3201,4 +3207,4 @@ void NPC::AIYellForHelp(Mob *sender, Mob *attacker)
}
}
}
}
+2
View File
@@ -103,6 +103,8 @@ namespace EQEmu
class NPC : public Mob
{
public:
class EventNpcStatsMonitor;
static NPC* SpawnNPC(const char* spawncommand, const glm::vec4& position, Client* client = nullptr);
static bool SpawnZoneController();
static int8 GetAILevel(bool iForceReRead = false);
+1 -1
View File
@@ -199,7 +199,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
}
#ifdef BOTS
else if (this->IsBot())
act_power = CastToBot()->GetBotFocusEffect(Bot::BotfocusPetPower, spell_id);
act_power = CastToBot()->GetBotFocusEffect(focusPetPower, spell_id);
#endif
}
else if (petpower > 0)
+2 -2
View File
@@ -3455,9 +3455,9 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r
// 1 = PCs, 2 = NPCs
if (spells[spell_id].pcnpc_only_flag && spells[spell_id].targettype != ST_AETargetHateList &&
spells[spell_id].targettype != ST_HateList) {
if (spells[spell_id].pcnpc_only_flag == 1 && !spelltar->IsClient() && !spelltar->IsMerc())
if (spells[spell_id].pcnpc_only_flag == 1 && !spelltar->IsClient() && !spelltar->IsMerc() && !spelltar->IsBot())
return false;
else if (spells[spell_id].pcnpc_only_flag == 2 && (spelltar->IsClient() || spelltar->IsMerc()))
else if (spells[spell_id].pcnpc_only_flag == 2 && (spelltar->IsClient() || spelltar->IsMerc() || spelltar->IsBot()))
return false;
}
+1 -1
View File
@@ -44,7 +44,7 @@ struct NPCType
uint16 race;
uint8 class_;
uint8 bodytype; // added for targettype support
uint8 deity; //not loaded from DB
uint32 deity; //not loaded from DB
uint8 level;
uint32 npc_id;
uint8 texture;