Merge remote-tracking branch 'remotes/origin/master' into web_interface

Conflicts:
	CMakeLists.txt
	common/logtypes.h
	common/shareddb.cpp
	world/net.cpp
	zone/client_logs.cpp
	zone/corpse.cpp
	zone/mob.cpp
	zone/net.cpp
This commit is contained in:
Akkadius
2015-02-02 23:11:31 -06:00
640 changed files with 45474 additions and 38161 deletions
+4 -4
View File
@@ -9,14 +9,13 @@ SET(zone_sources
bot.cpp
botspellsai.cpp
client.cpp
client_logs.cpp
client_mods.cpp
client_packet.cpp
client_process.cpp
command.cpp
corpse.cpp
doors.cpp
effects.cpp
effects.cpp
embparser.cpp
embparser_api.cpp
embperl.cpp
@@ -92,6 +91,7 @@ SET(zone_sources
perlpacket.cpp
petitions.cpp
pets.cpp
position.cpp
qglobals.cpp
queryserv.cpp
questmgr.cpp
@@ -112,13 +112,13 @@ SET(zone_sources
trading.cpp
trap.cpp
tribute.cpp
tune.cpp
water_map.cpp
water_map_v1.cpp
water_map_v2.cpp
waypoints.cpp
worldserver.cpp
zone.cpp
zone_logsys.cpp
zone_config.cpp
zonedb.cpp
zoning.cpp
@@ -131,7 +131,6 @@ SET(zone_headers
bot.h
bot_structs.h
client.h
client_logs.h
client_packet.h
command.h
common.h
@@ -184,6 +183,7 @@ SET(zone_headers
perlpacket.h
petitions.h
pets.h
position.h
qglobals.h
quest_interface.h
queryserv.h
+114 -125
View File
@@ -17,7 +17,8 @@ Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net)
*/
#include "../common/classes.h"
#include "../common/debug.h"
#include "../common/global_define.h"
#include "../common/eqemu_logsys.h"
#include "../common/eq_packet_structs.h"
#include "../common/races.h"
#include "../common/spdat.h"
@@ -268,10 +269,10 @@ void Client::ActivateAA(aaID activate){
}
// Check if AA is expendable
if (aas_send[activate - activate_val]->special_category == 7) {
// Add the AA cost to the extended profile to track overall total
m_epp.expended_aa += aas_send[activate]->cost;
SetAA(activate, 0);
SaveAA(); /* Save Character AA */
@@ -444,7 +445,7 @@ void Client::HandleAAAction(aaID activate) {
break;
default:
LogFile->write(EQEMuLog::Error, "Unknown AA nonspell action type %d", caa->action);
Log.Out(Logs::General, Logs::Error, "Unknown AA nonspell action type %d", caa->action);
return;
}
@@ -500,7 +501,7 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u
PetRecord record;
if(!database.GetPetEntry(spells[spell_id].teleport_zone, &record))
{
LogFile->write(EQEMuLog::Error, "Unknown swarm pet spell id: %d, check pets table", spell_id);
Log.Out(Logs::General, Logs::Error, "Unknown swarm pet spell id: %d, check pets table", spell_id);
Message(13, "Unable to find data for pet %s", spells[spell_id].teleport_zone);
return;
}
@@ -527,7 +528,7 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u
const NPCType *npc_type = database.GetNPCType(pet.npc_id);
if(npc_type == nullptr) {
//log write
LogFile->write(EQEMuLog::Error, "Unknown npc type for swarm pet spell id: %d", spell_id);
Log.Out(Logs::General, Logs::Error, "Unknown npc type for swarm pet spell id: %d", spell_id);
Message(0,"Unable to find pet!");
return;
}
@@ -546,12 +547,12 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u
if(summon_count > MAX_SWARM_PETS)
summon_count = MAX_SWARM_PETS;
static const float swarm_pet_x[MAX_SWARM_PETS] = { 5, -5, 5, -5,
10, -10, 10, -10,
8, -8, 8, -8 };
static const float swarm_pet_y[MAX_SWARM_PETS] = { 5, 5, -5, -5,
10, 10, -10, -10,
8, 8, -8, -8 };
static const glm::vec2 swarmPetLocations[MAX_SWARM_PETS] = {
glm::vec2(5, 5), glm::vec2(-5, 5), glm::vec2(5, -5), glm::vec2(-5, -5),
glm::vec2(10, 10), glm::vec2(-10, 10), glm::vec2(10, -10), glm::vec2(-10, -10),
glm::vec2(8, 8), glm::vec2(-8, 8), glm::vec2(8, -8), glm::vec2(-8, -8)
};
while(summon_count > 0) {
int pet_duration = pet.duration;
if(duration_override > 0)
@@ -568,8 +569,8 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u
NPC* npca = new NPC(
(npc_dup!=nullptr)?npc_dup:npc_type, //make sure we give the NPC the correct data pointer
0,
GetX()+swarm_pet_x[summon_count], GetY()+swarm_pet_y[summon_count],
GetZ(), GetHeading(), FlyMode3);
GetPosition() + glm::vec4(swarmPetLocations[summon_count], 0.0f, 0.0f),
FlyMode3);
if (followme)
npca->SetFollowID(GetID());
@@ -624,7 +625,7 @@ void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_overrid
const NPCType *npc_type = database.GetNPCType(typesid);
if(npc_type == nullptr) {
//log write
LogFile->write(EQEMuLog::Error, "Unknown npc type for swarm pet type id: %d", typesid);
Log.Out(Logs::General, Logs::Error, "Unknown npc type for swarm pet type id: %d", typesid);
Message(0,"Unable to find pet!");
return;
}
@@ -643,12 +644,11 @@ void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_overrid
if(summon_count > MAX_SWARM_PETS)
summon_count = MAX_SWARM_PETS;
static const float swarm_pet_x[MAX_SWARM_PETS] = { 5, -5, 5, -5,
10, -10, 10, -10,
8, -8, 8, -8 };
static const float swarm_pet_y[MAX_SWARM_PETS] = { 5, 5, -5, -5,
10, 10, -10, -10,
8, 8, -8, -8 };
static const glm::vec2 swarmPetLocations[MAX_SWARM_PETS] = {
glm::vec2(5, 5), glm::vec2(-5, 5), glm::vec2(5, -5), glm::vec2(-5, -5),
glm::vec2(10, 10), glm::vec2(-10, 10), glm::vec2(10, -10), glm::vec2(-10, -10),
glm::vec2(8, 8), glm::vec2(-8, 8), glm::vec2(8, -8), glm::vec2(-8, -8)
};;
while(summon_count > 0) {
int pet_duration = pet.duration;
@@ -666,8 +666,8 @@ void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_overrid
NPC* npca = new NPC(
(npc_dup!=nullptr)?npc_dup:npc_type, //make sure we give the NPC the correct data pointer
0,
GetX()+swarm_pet_x[summon_count], GetY()+swarm_pet_y[summon_count],
GetZ(), GetHeading(), FlyMode3);
GetPosition() + glm::vec4(swarmPetLocations[summon_count], 0.0f, 0.0f),
FlyMode3);
if (followme)
npca->SetFollowID(GetID());
@@ -853,7 +853,7 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration)
make_npc->d_melee_texture1 = 0;
make_npc->d_melee_texture2 = 0;
NPC* npca = new NPC(make_npc, 0, GetX(), GetY(), GetZ(), GetHeading(), FlyMode3);
NPC* npca = new NPC(make_npc, 0, GetPosition(), FlyMode3);
if(!npca->GetSwarmInfo()){
AA_SwarmPetInfo* nSI = new AA_SwarmPetInfo;
@@ -950,7 +950,7 @@ void Client::SendAAStats() {
void Client::BuyAA(AA_Action* action)
{
mlog(AA__MESSAGE, "Starting to buy AA %d", action->ability);
Log.Out(Logs::Detail, Logs::AA, "Starting to buy AA %d", action->ability);
//find the AA information from the database
SendAA_Struct* aa2 = zone->FindAA(action->ability);
@@ -962,7 +962,7 @@ void Client::BuyAA(AA_Action* action)
a = action->ability - i;
if(a <= 0)
break;
mlog(AA__MESSAGE, "Could not find AA %d, trying potential parent %d", action->ability, a);
Log.Out(Logs::Detail, Logs::AA, "Could not find AA %d, trying potential parent %d", action->ability, a);
aa2 = zone->FindAA(a);
if(aa2 != nullptr)
break;
@@ -979,7 +979,7 @@ void Client::BuyAA(AA_Action* action)
uint32 cur_level = GetAA(aa2->id);
if((aa2->id + cur_level) != action->ability) { //got invalid AA
mlog(AA__ERROR, "Unable to find or match AA %d (found %d + lvl %d)", action->ability, aa2->id, cur_level);
Log.Out(Logs::Detail, Logs::AA, "Unable to find or match AA %d (found %d + lvl %d)", action->ability, aa2->id, cur_level);
return;
}
@@ -1010,14 +1010,14 @@ void Client::BuyAA(AA_Action* action)
if (m_pp.aapoints >= real_cost && cur_level < aa2->max_level) {
SetAA(aa2->id, cur_level + 1);
mlog(AA__MESSAGE, "Set AA %d to level %d", aa2->id, cur_level + 1);
Log.Out(Logs::Detail, Logs::AA, "Set AA %d to level %d", aa2->id, cur_level + 1);
m_pp.aapoints -= real_cost;
/* Do Player Profile rank calculations and set player profile */
SaveAA();
/* Save to Database to avoid having to write the whole AA array to the profile, only write changes*/
// database.SaveCharacterAA(this->CharacterID(), aa2->id, (cur_level + 1));
// database.SaveCharacterAA(this->CharacterID(), aa2->id, (cur_level + 1));
if ((RuleB(AA, Stacking) && (GetClientVersionBit() >= 4) && (aa2->hotkey_sid == 4294967295u))
&& ((aa2->max_level == (cur_level + 1)) && aa2->sof_next_id)){
@@ -1038,7 +1038,7 @@ void Client::BuyAA(AA_Action* action)
if (cur_level < 1){
Message(15, "You have gained the ability \"%s\" at a cost of %d ability %s.", aa2->name, real_cost, (real_cost>1) ? "points" : "point");
/* QS: Player_Log_AA_Purchases */
/* QS: Player_Log_AA_Purchases */
if (RuleB(QueryServ, PlayerLogAAPurchases)){
std::string event_desc = StringFormat("Initial AA Purchase :: aa_name:%s aa_id:%i at cost:%i in zoneid:%i instid:%i", aa2->name, aa2->id, real_cost, this->GetZoneID(), this->GetInstanceID());
QServ->PlayerLogEvent(Player_Log_AA_Purchases, this->CharacterID(), event_desc);
@@ -1428,10 +1428,10 @@ SendAA_Struct* Zone::FindAA(uint32 id) {
}
void Zone::LoadAAs() {
LogFile->write(EQEMuLog::Status, "Loading AA information...");
Log.Out(Logs::General, Logs::Status, "Loading AA information...");
totalAAs = database.CountAAs();
if(totalAAs == 0) {
LogFile->write(EQEMuLog::Error, "Failed to load AAs!");
Log.Out(Logs::General, Logs::Error, "Failed to load AAs!");
aas = nullptr;
return;
}
@@ -1446,11 +1446,11 @@ void Zone::LoadAAs() {
}
//load AA Effects into aa_effects
LogFile->write(EQEMuLog::Status, "Loading AA Effects...");
Log.Out(Logs::General, Logs::Status, "Loading AA Effects...");
if (database.LoadAAEffects2())
LogFile->write(EQEMuLog::Status, "Loaded %d AA Effects.", aa_effects.size());
Log.Out(Logs::General, Logs::Status, "Loaded %d AA Effects.", aa_effects.size());
else
LogFile->write(EQEMuLog::Error, "Failed to load AA Effects!");
Log.Out(Logs::General, Logs::Error, "Failed to load AA Effects!");
}
bool ZoneDatabase::LoadAAEffects2() {
@@ -1459,26 +1459,24 @@ bool ZoneDatabase::LoadAAEffects2() {
const std::string query = "SELECT aaid, slot, effectid, base1, base2 FROM aa_effects ORDER BY aaid ASC, slot ASC";
auto results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::LoadAAEffects2 query: '%s': %s", query.c_str(), results.ErrorMessage().c_str());
return false;
}
if (!results.RowCount()) { //no results
LogFile->write(EQEMuLog::Error, "Error loading AA Effects, none found in the database.");
return false;
return false;
}
for(auto row = results.begin(); row != results.end(); ++row) {
int aaid = atoi(row[0]);
int slot = atoi(row[1]);
int effectid = atoi(row[2]);
int base1 = atoi(row[3]);
int base2 = atoi(row[4]);
aa_effects[aaid][slot].skill_id = effectid;
aa_effects[aaid][slot].base1 = base1;
aa_effects[aaid][slot].base2 = base2;
aa_effects[aaid][slot].slot = slot; //not really needed, but we'll populate it just in case
}
for(auto row = results.begin(); row != results.end(); ++row) {
int aaid = atoi(row[0]);
int slot = atoi(row[1]);
int effectid = atoi(row[2]);
int base1 = atoi(row[3]);
int base2 = atoi(row[4]);
aa_effects[aaid][slot].skill_id = effectid;
aa_effects[aaid][slot].base1 = base1;
aa_effects[aaid][slot].base2 = base2;
aa_effects[aaid][slot].slot = slot; //not really needed, but we'll populate it just in case
}
return true;
}
@@ -1797,34 +1795,33 @@ bool ZoneDatabase::LoadAAEffects() {
memset(AA_Actions, 0, sizeof(AA_Actions)); //I hope the compiler is smart about this size...
const std::string query = "SELECT aaid, rank, reuse_time, spell_id, target, "
"nonspell_action, nonspell_mana, nonspell_duration, "
"redux_aa, redux_rate, redux_aa2, redux_rate2 FROM aa_actions";
auto results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in LoadAAEffects query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
"nonspell_action, nonspell_mana, nonspell_duration, "
"redux_aa, redux_rate, redux_aa2, redux_rate2 FROM aa_actions";
auto results = QueryDatabase(query);
if (!results.Success()) {
return false;
}
}
for (auto row = results.begin(); row != results.end(); ++row) {
for (auto row = results.begin(); row != results.end(); ++row) {
int aaid = atoi(row[0]);
int rank = atoi(row[1]);
if(aaid < 0 || aaid >= aaHighestID || rank < 0 || rank >= MAX_AA_ACTION_RANKS)
continue;
AA_DBAction *caction = &AA_Actions[aaid][rank];
int aaid = atoi(row[0]);
int rank = atoi(row[1]);
if(aaid < 0 || aaid >= aaHighestID || rank < 0 || rank >= MAX_AA_ACTION_RANKS)
continue;
AA_DBAction *caction = &AA_Actions[aaid][rank];
caction->reuse_time = atoi(row[2]);
caction->spell_id = atoi(row[3]);
caction->target = (aaTargetType) atoi(row[4]);
caction->action = (aaNonspellAction) atoi(row[5]);
caction->mana_cost = atoi(row[6]);
caction->duration = atoi(row[7]);
caction->redux_aa = (aaID) atoi(row[8]);
caction->redux_rate = atoi(row[9]);
caction->redux_aa2 = (aaID) atoi(row[10]);
caction->redux_rate2 = atoi(row[11]);
caction->reuse_time = atoi(row[2]);
caction->spell_id = atoi(row[3]);
caction->target = (aaTargetType) atoi(row[4]);
caction->action = (aaNonspellAction) atoi(row[5]);
caction->mana_cost = atoi(row[6]);
caction->duration = atoi(row[7]);
caction->redux_aa = (aaID) atoi(row[8]);
caction->redux_rate = atoi(row[9]);
caction->redux_aa2 = (aaID) atoi(row[10]);
caction->redux_rate2 = atoi(row[11]);
}
}
return true;
}
@@ -1840,14 +1837,13 @@ uint8 ZoneDatabase::GetTotalAALevels(uint32 skill_id) {
std::string query = StringFormat("SELECT count(slot) FROM aa_effects WHERE aaid = %i", skill_id);
auto results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in GetTotalAALevels '%s: %s", query.c_str(), results.ErrorMessage().c_str());
return 0;
}
if (results.RowCount() != 1)
return 0;
if (results.RowCount() != 1)
return 0;
auto row = results.begin();
auto row = results.begin();
return atoi(row[0]);
}
@@ -1894,14 +1890,13 @@ uint32 ZoneDatabase::CountAAs(){
const std::string query = "SELECT count(title_sid) FROM altadv_vars";
auto results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::CountAAs query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
return 0;
}
if (results.RowCount() != 1)
return 0;
return 0;
auto row = results.begin();
auto row = results.begin();
return atoi(row[0]);;
}
@@ -1911,14 +1906,13 @@ uint32 ZoneDatabase::CountAAEffects() {
const std::string query = "SELECT count(id) FROM aa_effects";
auto results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::CountAALevels query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
return 0;
}
if (results.RowCount() != 1)
return 0;
return 0;
auto row = results.begin();
auto row = results.begin();
return atoi(row[0]);
}
@@ -1944,63 +1938,58 @@ void ZoneDatabase::LoadAAs(SendAA_Struct **load){
load[index]->seq = index+1;
}
} else {
LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::LoadAAs query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
}
AARequiredLevelAndCost.clear();
query = "SELECT skill_id, level, cost from aa_required_level_cost order by skill_id";
results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::LoadAAs query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
return;
}
AALevelCost_Struct aalcs;
for (auto row = results.begin(); row != results.end(); ++row) {
aalcs.Level = atoi(row[1]);
aalcs.Cost = atoi(row[2]);
AARequiredLevelAndCost[atoi(row[0])] = aalcs;
}
query = "SELECT skill_id, level, cost from aa_required_level_cost order by skill_id";
results = QueryDatabase(query);
if (!results.Success()) {
return;
}
AALevelCost_Struct aalcs;
for (auto row = results.begin(); row != results.end(); ++row) {
aalcs.Level = atoi(row[1]);
aalcs.Cost = atoi(row[2]);
AARequiredLevelAndCost[atoi(row[0])] = aalcs;
}
}
SendAA_Struct* ZoneDatabase::GetAASkillVars(uint32 skill_id)
{
std::string query = "SET @row = 0"; //initialize "row" variable in database for next query
auto results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in GetAASkillVars '%s': %s", query.c_str(), results.ErrorMessage().c_str());
return nullptr;
}
auto results = QueryDatabase(query);
if (!results.Success()) {
return nullptr;
}
query = StringFormat("SELECT a.cost, a.max_level, a.hotkey_sid, a.hotkey_sid2, a.title_sid, a.desc_sid, a.type, "
"COALESCE(" //So we can return 0 if it's null.
"(" // this is our derived table that has the row #
// that we can SELECT from, because the client is stupid.
"SELECT p.prereq_index_num "
"FROM (SELECT a2.skill_id, @row := @row + 1 AS prereq_index_num "
query = StringFormat("SELECT a.cost, a.max_level, a.hotkey_sid, a.hotkey_sid2, a.title_sid, a.desc_sid, a.type, "
"COALESCE(" //So we can return 0 if it's null.
"(" // this is our derived table that has the row #
// that we can SELECT from, because the client is stupid.
"SELECT p.prereq_index_num "
"FROM (SELECT a2.skill_id, @row := @row + 1 AS prereq_index_num "
"FROM altadv_vars a2) AS p "
"WHERE p.skill_id = a.prereq_skill), 0) "
"AS prereq_skill_index, a.prereq_minpoints, a.spell_type, a.spell_refresh, a.classes, "
"a.berserker, a.spellid, a.class_type, a.name, a.cost_inc, a.aa_expansion, a.special_category, "
"a.sof_type, a.sof_cost_inc, a.sof_max_level, a.sof_next_skill, "
"a.clientver, " // Client Version 0 = None, 1 = All, 2 = Titanium/6.2, 4 = SoF 5 = SOD 6 = UF
"a.account_time_required, a.sof_current_level, a.sof_next_id, a.level_inc "
"FROM altadv_vars a WHERE skill_id=%i", skill_id);
results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in GetAASkillVars '%s': %s", query.c_str(), results.ErrorMessage().c_str());
return nullptr;
}
"WHERE p.skill_id = a.prereq_skill), 0) "
"AS prereq_skill_index, a.prereq_minpoints, a.spell_type, a.spell_refresh, a.classes, "
"a.berserker, a.spellid, a.class_type, a.name, a.cost_inc, a.aa_expansion, a.special_category, "
"a.sof_type, a.sof_cost_inc, a.sof_max_level, a.sof_next_skill, "
"a.clientver, " // Client Version 0 = None, 1 = All, 2 = Titanium/6.2, 4 = SoF 5 = SOD 6 = UF
"a.account_time_required, a.sof_current_level, a.sof_next_id, a.level_inc "
"FROM altadv_vars a WHERE skill_id=%i", skill_id);
results = QueryDatabase(query);
if (!results.Success()) {
return nullptr;
}
if (results.RowCount() != 1)
return nullptr;
if (results.RowCount() != 1)
return nullptr;
int total_abilities = GetTotalAALevels(skill_id); //eventually we'll want to use zone->GetTotalAALevels(skill_id) since it should save queries to the DB
int total_abilities = GetTotalAALevels(skill_id); //eventually we'll want to use zone->GetTotalAALevels(skill_id) since it should save queries to the DB
int totalsize = total_abilities * sizeof(AA_Ability) + sizeof(SendAA_Struct);
SendAA_Struct* sendaa = nullptr;
uchar* buffer;
SendAA_Struct* sendaa = nullptr;
uchar* buffer;
buffer = new uchar[totalsize];
memset(buffer,0,totalsize);
@@ -2011,7 +2000,7 @@ SendAA_Struct* ZoneDatabase::GetAASkillVars(uint32 skill_id)
//ATOI IS NOT UNSIGNED LONG-SAFE!!!
sendaa->cost = atoul(row[0]);
sendaa->cost2 = sendaa->cost;
sendaa->cost2 = sendaa->cost;
sendaa->max_level = atoul(row[1]);
sendaa->hotkey_sid = atoul(row[2]);
sendaa->id = skill_id;
+35 -36
View File
@@ -16,7 +16,8 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "../common/global_define.h"
#include "../common/eqemu_logsys.h"
#include "../common/faction.h"
#include "../common/rulesys.h"
#include "../common/spdat.h"
@@ -88,7 +89,7 @@ void EntityList::DescribeAggro(Client *towho, NPC *from_who, float d, bool verbo
if (mob->IsClient()) //also ensures that mob != around
continue;
if (mob->DistNoRoot(*from_who) > d2)
if (DistanceSquared(mob->GetPosition(), from_who->GetPosition()) > d2)
continue;
if (engaged) {
@@ -150,7 +151,8 @@ void NPC::DescribeAggro(Client *towho, Mob *mob, bool verbose) {
return;
}
float dist2 = mob->DistNoRoot(*this);
float dist2 = DistanceSquared(mob->GetPosition(), m_Position);
float iAggroRange2 = iAggroRange*iAggroRange;
if( dist2 > iAggroRange2 ) {
towho->Message(0, "...%s is out of range. %.3f > %.3f ", mob->GetName(),
@@ -295,7 +297,7 @@ bool Mob::CheckWillAggro(Mob *mob) {
return(false);
}
float dist2 = mob->DistNoRoot(*this);
float dist2 = DistanceSquared(mob->GetPosition(), m_Position);
float iAggroRange2 = iAggroRange*iAggroRange;
if( dist2 > iAggroRange2 ) {
@@ -341,22 +343,18 @@ bool Mob::CheckWillAggro(Mob *mob) {
{
//FatherNiwtit: make sure we can see them. last since it is very expensive
if(CheckLosFN(mob)) {
// Aggro
#if EQDEBUG>=6
LogFile->write(EQEMuLog::Debug, "Check aggro for %s target %s.", GetName(), mob->GetName());
#endif
Log.Out(Logs::Detail, Logs::Aggro, "Check aggro for %s target %s.", GetName(), mob->GetName());
return( mod_will_aggro(mob, this) );
}
}
#if EQDEBUG >= 6
printf("Is In zone?:%d\n", mob->InZone());
printf("Dist^2: %f\n", dist2);
printf("Range^2: %f\n", iAggroRange2);
printf("Faction: %d\n", fv);
printf("Int: %d\n", GetINT());
printf("Con: %d\n", GetLevelCon(mob->GetLevel()));
#endif
Log.Out(Logs::Detail, Logs::Aggro, "Is In zone?:%d\n", mob->InZone());
Log.Out(Logs::Detail, Logs::Aggro, "Dist^2: %f\n", dist2);
Log.Out(Logs::Detail, Logs::Aggro, "Range^2: %f\n", iAggroRange2);
Log.Out(Logs::Detail, Logs::Aggro, "Faction: %d\n", fv);
Log.Out(Logs::Detail, Logs::Aggro, "Int: %d\n", GetINT());
Log.Out(Logs::Detail, Logs::Aggro, "Con: %d\n", GetLevelCon(mob->GetLevel()));
return(false);
}
@@ -413,7 +411,7 @@ int EntityList::GetHatedCount(Mob *attacker, Mob *exclude)
AggroRange *= AggroRange;
if (mob->DistNoRoot(*attacker) > AggroRange)
if (DistanceSquared(mob->GetPosition(), attacker->GetPosition()) > AggroRange)
continue;
Count++;
@@ -443,7 +441,7 @@ void EntityList::AIYellForHelp(Mob* sender, Mob* attacker) {
// && !mob->IsCorpse()
// && mob->IsAIControlled()
&& mob->GetPrimaryFaction() != 0
&& mob->DistNoRoot(*sender) <= r
&& DistanceSquared(mob->GetPosition(), sender->GetPosition()) <= r
&& !mob->IsEngaged()
&& ((!mob->IsPet()) || (mob->IsPet() && mob->GetOwner() && !mob->GetOwner()->IsClient()))
// If we're a pet we don't react to any calls for help if our owner is a client
@@ -469,8 +467,10 @@ void EntityList::AIYellForHelp(Mob* sender, Mob* attacker) {
//Father Nitwit: make sure we can see them.
if(mob->CheckLosFN(sender)) {
#if (EQDEBUG>=5)
LogFile->write(EQEMuLog::Debug, "AIYellForHelp(\"%s\",\"%s\") %s attacking %s Dist %f Z %f",
sender->GetName(), attacker->GetName(), mob->GetName(), attacker->GetName(), mob->DistNoRoot(*sender), fabs(sender->GetZ()+mob->GetZ()));
Log.Out(Logs::General, Logs::None, "AIYellForHelp(\"%s\",\"%s\") %s attacking %s Dist %f Z %f",
sender->GetName(), attacker->GetName(), mob->GetName(),
attacker->GetName(), DistanceSquared(mob->GetPosition(),
sender->GetPosition()), fabs(sender->GetZ()+mob->GetZ()));
#endif
mob->AddToHateList(attacker, 1, 0, false);
}
@@ -481,7 +481,7 @@ void EntityList::AIYellForHelp(Mob* sender, Mob* attacker) {
}
/*
solar: returns false if attack should not be allowed
returns false if attack should not be allowed
I try to list every type of conflict that's possible here, so it's easy
to see how the decision is made. Yea, it could be condensed and made
faster, but I'm doing it this way to make it readable and easy to modify
@@ -550,7 +550,7 @@ bool Mob::IsAttackAllowed(Mob *target, bool isSpellAttack)
}
}
// solar: the format here is a matrix of mob type vs mob type.
// the format here is a matrix of mob type vs mob type.
// redundant ones are omitted and the reverse is tried if it falls through.
// first figure out if we're pets. we always look at the master's flags.
@@ -696,12 +696,12 @@ type', in which case, the answer is yes.
}
while( reverse++ == 0 );
LogFile->write(EQEMuLog::Debug, "Mob::IsAttackAllowed: don't have a rule for this - %s vs %s\n", this->GetName(), target->GetName());
Log.Out(Logs::General, Logs::None, "Mob::IsAttackAllowed: don't have a rule for this - %s vs %s\n", this->GetName(), target->GetName());
return false;
}
// solar: this is to check if non detrimental things are allowed to be done
// this is to check if non detrimental things are allowed to be done
// to the target. clients cannot affect npcs and vice versa, and clients
// cannot affect other clients that are not of the same pvp flag as them.
// also goes for their pets
@@ -717,7 +717,7 @@ bool Mob::IsBeneficialAllowed(Mob *target)
if (target->GetAllowBeneficial())
return true;
// solar: see IsAttackAllowed for notes
// see IsAttackAllowed for notes
// first figure out if we're pets. we always look at the master's flags.
// no need to compare pets to anything
@@ -836,7 +836,7 @@ bool Mob::IsBeneficialAllowed(Mob *target)
}
while( reverse++ == 0 );
LogFile->write(EQEMuLog::Debug, "Mob::IsBeneficialAllowed: don't have a rule for this - %s to %s\n", this->GetName(), target->GetName());
Log.Out(Logs::General, Logs::None, "Mob::IsBeneficialAllowed: don't have a rule for this - %s to %s\n", this->GetName(), target->GetName());
return false;
}
@@ -877,7 +877,7 @@ bool Mob::CombatRange(Mob* other)
if (size_mod > 10000)
size_mod = size_mod / 7;
float _DistNoRoot = DistNoRoot(*other);
float _DistNoRoot = DistanceSquared(m_Position, other->GetPosition());
if (GetSpecialAbility(NPC_CHASE_DISTANCE)){
@@ -934,8 +934,8 @@ bool Mob::CheckLosFN(float posX, float posY, float posZ, float mobSize) {
#endif
}
Map::Vertex myloc;
Map::Vertex oloc;
glm::vec3 myloc;
glm::vec3 oloc;
#define LOS_DEFAULT_HEIGHT 6.0f
@@ -948,7 +948,7 @@ bool Mob::CheckLosFN(float posX, float posY, float posZ, float mobSize) {
oloc.z = posZ + (mobSize==0.0?LOS_DEFAULT_HEIGHT:mobSize)/2 * SEE_POSITION;
#if LOSDEBUG>=5
LogFile->write(EQEMuLog::Debug, "LOS from (%.2f, %.2f, %.2f) to (%.2f, %.2f, %.2f) sizes: (%.2f, %.2f)", myloc.x, myloc.y, myloc.z, oloc.x, oloc.y, oloc.z, GetSize(), mobSize);
Log.Out(Logs::General, Logs::None, "LOS from (%.2f, %.2f, %.2f) to (%.2f, %.2f, %.2f) sizes: (%.2f, %.2f)", myloc.x, myloc.y, myloc.z, oloc.x, oloc.y, oloc.z, GetSize(), mobSize);
#endif
return zone->zonemap->CheckLoS(myloc, oloc);
}
@@ -1233,7 +1233,7 @@ void Mob::ClearFeignMemory() {
AIfeignremember_timer->Disable();
}
bool Mob::PassCharismaCheck(Mob* caster, Mob* spellTarget, uint16 spell_id) {
bool Mob::PassCharismaCheck(Mob* caster, uint16 spell_id) {
/*
Charm formula is correct based on over 50 hours of personal live parsing - Kayen
@@ -1260,9 +1260,9 @@ bool Mob::PassCharismaCheck(Mob* caster, Mob* spellTarget, uint16 spell_id) {
return true;
if (RuleB(Spells, CharismaCharmDuration))
resist_check = ResistSpell(spells[spell_id].resisttype, spell_id, caster,0,0,true,true);
resist_check = ResistSpell(spells[spell_id].resisttype, spell_id, caster,false,0,true,true);
else
resist_check = ResistSpell(spells[spell_id].resisttype, spell_id, caster, 0,0, false, true);
resist_check = ResistSpell(spells[spell_id].resisttype, spell_id, caster, false,0, false, true);
//2: The mob makes a resistance check against the charm
if (resist_check == 100)
@@ -1286,8 +1286,7 @@ bool Mob::PassCharismaCheck(Mob* caster, Mob* spellTarget, uint16 spell_id) {
{
// Assume this is a harmony/pacify spell
// If 'Lull' spell resists, do a second resist check with a charisma modifier AND regular resist checks. If resists agian you gain aggro.
resist_check = ResistSpell(spells[spell_id].resisttype, spell_id, caster, true);
resist_check = ResistSpell(spells[spell_id].resisttype, spell_id, caster, false,0,true);
if (resist_check == 100)
return true;
}
+126 -129
View File
@@ -16,11 +16,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#if EQDEBUG >= 5
//#define ATTACK_DEBUG 20
#endif
#include "../common/debug.h"
#include "../common/global_define.h"
#include "../common/eq_constants.h"
#include "../common/eq_packet_structs.h"
#include "../common/rulesys.h"
@@ -61,9 +57,9 @@ bool Mob::AttackAnimation(SkillUseTypes &skillinuse, int Hand, const ItemInst* w
int type = 0;
if (weapon && weapon->IsType(ItemClassCommon)) {
const Item_Struct* item = weapon->GetItem();
#if EQDEBUG >= 11
LogFile->write(EQEMuLog::Debug, "Weapon skill:%i", item->ItemType);
#endif
Log.Out(Logs::Detail, Logs::Attack, "Weapon skill : %i", item->ItemType);
switch (item->ItemType)
{
case ItemType1HSlash: // 1H Slashing
@@ -192,10 +188,7 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c
if(attacker->IsNPC() && !attacker->IsPet())
chancetohit += RuleR(Combat, NPCBonusHitChance);
#if ATTACK_DEBUG>=11
LogFile->write(EQEMuLog::Debug, "CheckHitChance(%s) attacked by %s", defender->GetName(), attacker->GetName());
#endif
mlog(COMBAT__TOHIT,"CheckHitChance(%s) attacked by %s", defender->GetName(), attacker->GetName());
Log.Out(Logs::Detail, Logs::Attack, "CheckHitChance(%s) attacked by %s", defender->GetName(), attacker->GetName());
bool pvpmode = false;
if(IsClient() && other->IsClient())
@@ -216,7 +209,7 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c
//Calculate the level difference
mlog(COMBAT__TOHIT, "Chance to hit before level diff calc %.2f", chancetohit);
Log.Out(Logs::Detail, Logs::Attack, "Chance to hit before level diff calc %.2f", chancetohit);
double level_difference = attacker_level - defender_level;
double range = defender->GetLevel();
@@ -244,32 +237,32 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c
chancetohit += (RuleR(Combat,HitBonusPerLevel) * level_difference);
}
mlog(COMBAT__TOHIT, "Chance to hit after level diff calc %.2f", chancetohit);
Log.Out(Logs::Detail, Logs::Attack, "Chance to hit after level diff calc %.2f", chancetohit);
chancetohit -= ((float)defender->GetAGI() * RuleR(Combat, AgiHitFactor));
mlog(COMBAT__TOHIT, "Chance to hit after agil calc %.2f", chancetohit);
Log.Out(Logs::Detail, Logs::Attack, "Chance to hit after Agility calc %.2f", chancetohit);
if(attacker->IsClient())
{
chancetohit -= (RuleR(Combat,WeaponSkillFalloff) * (attacker->CastToClient()->MaxSkill(skillinuse) - attacker->GetSkill(skillinuse)));
mlog(COMBAT__TOHIT, "Chance to hit after weapon falloff calc (attack) %.2f", chancetohit);
Log.Out(Logs::Detail, Logs::Attack, "Chance to hit after agil calc %.2f", "Chance to hit after weapon falloff calc (attack) %.2f", chancetohit);
}
if(defender->IsClient())
{
chancetohit += (RuleR(Combat,WeaponSkillFalloff) * (defender->CastToClient()->MaxSkill(SkillDefense) - defender->GetSkill(SkillDefense)));
mlog(COMBAT__TOHIT, "Chance to hit after weapon falloff calc (defense) %.2f", chancetohit);
Log.Out(Logs::Detail, Logs::Attack, "Chance to hit after weapon falloff calc (defense) %.2f", chancetohit);
}
//I dont think this is 100% correct, but at least it does something...
if(attacker->spellbonuses.MeleeSkillCheckSkill == skillinuse || attacker->spellbonuses.MeleeSkillCheckSkill == 255) {
chancetohit += attacker->spellbonuses.MeleeSkillCheck;
mlog(COMBAT__TOHIT, "Applied spell melee skill bonus %d, yeilding %.2f", attacker->spellbonuses.MeleeSkillCheck, chancetohit);
Log.Out(Logs::Detail, Logs::Attack, "Applied spell melee skill bonus %d, yeilding %.2f", attacker->spellbonuses.MeleeSkillCheck, chancetohit);
}
if(attacker->itembonuses.MeleeSkillCheckSkill == skillinuse || attacker->itembonuses.MeleeSkillCheckSkill == 255) {
chancetohit += attacker->itembonuses.MeleeSkillCheck;
mlog(COMBAT__TOHIT, "Applied item melee skill bonus %d, yeilding %.2f", attacker->spellbonuses.MeleeSkillCheck, chancetohit);
Log.Out(Logs::Detail, Logs::Attack, "Applied item melee skill bonus %d, yeilding %.2f", attacker->spellbonuses.MeleeSkillCheck, chancetohit);
}
//Avoidance Bonuses on defender decreases baseline hit chance by percent.
@@ -316,7 +309,7 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c
//Calculate final chance to hit
chancetohit += ((chancetohit * (hitBonus - avoidanceBonus)) / 100.0f);
mlog(COMBAT__TOHIT, "Chance to hit %.2f after accuracy calc %.2f and avoidance calc %.2f", chancetohit, hitBonus, avoidanceBonus);
Log.Out(Logs::Detail, Logs::Attack, "Chance to hit %.2f after accuracy calc %.2f and avoidance calc %.2f", chancetohit, hitBonus, avoidanceBonus);
chancetohit = mod_hit_chance(chancetohit, skillinuse, attacker);
@@ -334,9 +327,9 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c
//I dont know the best way to handle a garunteed hit discipline being used
//agains a garunteed riposte (for example) discipline... for now, garunteed hit wins
#if EQDEBUG>=11
LogFile->write(EQEMuLog::Debug, "3 FINAL calculated chance to hit is: %5.2f", chancetohit);
#endif
Log.Out(Logs::Detail, Logs::Attack, "3 FINAL calculated chance to hit is: %5.2f", chancetohit);
//
// Did we hit?
@@ -344,14 +337,14 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c
float tohit_roll = zone->random.Real(0, 100);
mlog(COMBAT__TOHIT, "Final hit chance: %.2f%%. Hit roll %.2f", chancetohit, tohit_roll);
Log.Out(Logs::Detail, Logs::Attack, "Final hit chance: %.2f%%. Hit roll %.2f", chancetohit, tohit_roll);
return(tohit_roll <= chancetohit);
}
bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte)
{
/* solar: called when a mob is attacked, does the checks to see if it's a hit
/* called when a mob is attacked, does the checks to see if it's a hit
* and does other mitigation checks. 'this' is the mob being attacked.
*
* special return values:
@@ -378,7 +371,7 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte)
/////////////////////////////////////////////////////////
if (IsEnraged() && other->InFrontMob(this, other->GetX(), other->GetY())) {
damage = -3;
mlog(COMBAT__DAMAGE, "I am enraged, riposting frontal attack.");
Log.Out(Logs::Detail, Logs::Combat, "I am enraged, riposting frontal attack.");
}
/////////////////////////////////////////////////////////
@@ -525,7 +518,7 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte)
}
}
mlog(COMBAT__DAMAGE, "Final damage after all avoidances: %d", damage);
Log.Out(Logs::Detail, Logs::Combat, "Final damage after all avoidances: %d", damage);
if (damage < 0)
return true;
@@ -698,9 +691,9 @@ void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttac
damage -= (myac * zone->random.Int(0, acrandom) / 10000);
}
if (damage<1) damage=1;
mlog(COMBAT__DAMAGE, "AC Damage Reduction: fail chance %d%%. Failed. Reduction %.3f%%, random %d. Resulting damage %d.", acfail, acreduction, acrandom, damage);
Log.Out(Logs::Detail, Logs::Combat, "AC Damage Reduction: fail chance %d%%. Failed. Reduction %.3f%%, random %d. Resulting damage %d.", acfail, acreduction, acrandom, damage);
} else {
mlog(COMBAT__DAMAGE, "AC Damage Reduction: fail chance %d%%. Did not fail.", acfail);
Log.Out(Logs::Detail, Logs::Combat, "AC Damage Reduction: fail chance %d%%. Did not fail.", acfail);
}
}
@@ -1136,14 +1129,14 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
{
if (!other) {
SetTarget(nullptr);
LogFile->write(EQEMuLog::Error, "A null Mob object was passed to Client::Attack() for evaluation!");
Log.Out(Logs::General, Logs::Error, "A null Mob object was passed to Client::Attack() for evaluation!");
return false;
}
if(!GetTarget())
SetTarget(other);
mlog(COMBAT__ATTACKS, "Attacking %s with hand %d %s", other?other->GetName():"(nullptr)", Hand, bRiposte?"(this is a riposte)":"");
Log.Out(Logs::Detail, Logs::Combat, "Attacking %s with hand %d %s", other?other->GetName():"(nullptr)", Hand, bRiposte?"(this is a riposte)":"");
//SetAttackTimer();
if (
@@ -1153,12 +1146,12 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
|| (GetHP() < 0)
|| (!IsAttackAllowed(other))
) {
mlog(COMBAT__ATTACKS, "Attack canceled, invalid circumstances.");
Log.Out(Logs::Detail, Logs::Combat, "Attack canceled, invalid circumstances.");
return false; // Only bards can attack while casting
}
if(DivineAura() && !GetGM()) {//cant attack while invulnerable unless your a gm
mlog(COMBAT__ATTACKS, "Attack canceled, Divine Aura is in effect.");
Log.Out(Logs::Detail, Logs::Combat, "Attack canceled, Divine Aura is in effect.");
Message_StringID(MT_DefaultText, DIVINE_AURA_NO_ATK); //You can't attack while invulnerable!
return false;
}
@@ -1178,19 +1171,19 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
if(weapon != nullptr) {
if (!weapon->IsWeapon()) {
mlog(COMBAT__ATTACKS, "Attack canceled, Item %s (%d) is not a weapon.", weapon->GetItem()->Name, weapon->GetID());
Log.Out(Logs::Detail, Logs::Combat, "Attack canceled, Item %s (%d) is not a weapon.", weapon->GetItem()->Name, weapon->GetID());
return(false);
}
mlog(COMBAT__ATTACKS, "Attacking with weapon: %s (%d)", weapon->GetItem()->Name, weapon->GetID());
Log.Out(Logs::Detail, Logs::Combat, "Attacking with weapon: %s (%d)", weapon->GetItem()->Name, weapon->GetID());
} else {
mlog(COMBAT__ATTACKS, "Attacking without a weapon.");
Log.Out(Logs::Detail, Logs::Combat, "Attacking without a weapon.");
}
// calculate attack_skill and skillinuse depending on hand and weapon
// also send Packet to near clients
SkillUseTypes skillinuse;
AttackAnimation(skillinuse, Hand, weapon);
mlog(COMBAT__ATTACKS, "Attacking with %s in slot %d using skill %d", weapon?weapon->GetItem()->Name:"Fist", Hand, skillinuse);
Log.Out(Logs::Detail, Logs::Combat, "Attacking with %s in slot %d using skill %d", weapon?weapon->GetItem()->Name:"Fist", Hand, skillinuse);
/// Now figure out damage
int damage = 0;
@@ -1208,7 +1201,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
if(IsBerserk() && GetClass() == BERSERKER){
int bonus = 3 + GetLevel()/10; //unverified
weapon_damage = weapon_damage * (100+bonus) / 100;
mlog(COMBAT__DAMAGE, "Berserker damage bonus increases DMG to %d", weapon_damage);
Log.Out(Logs::Detail, Logs::Combat, "Berserker damage bonus increases DMG to %d", weapon_damage);
}
//try a finishing blow.. if successful end the attack
@@ -1276,7 +1269,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
damage = mod_client_damage(damage, skillinuse, Hand, weapon, other);
mlog(COMBAT__DAMAGE, "Damage calculated to %d (min %d, max %d, str %d, skill %d, DMG %d, lv %d)",
Log.Out(Logs::Detail, Logs::Combat, "Damage calculated to %d (min %d, max %d, str %d, skill %d, DMG %d, lv %d)",
damage, min_hit, max_hit, GetSTR(), GetSkill(skillinuse), weapon_damage, mylevel);
int hit_chance_bonus = 0;
@@ -1291,7 +1284,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
//check to see if we hit..
if(!other->CheckHitChance(this, skillinuse, Hand, hit_chance_bonus)) {
mlog(COMBAT__ATTACKS, "Attack missed. Damage set to 0.");
Log.Out(Logs::Detail, Logs::Combat, "Attack missed. Damage set to 0.");
damage = 0;
} else { //we hit, try to avoid it
other->AvoidDamage(this, damage);
@@ -1299,7 +1292,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
if(damage > 0)
CommonOutgoingHitSuccess(other, damage, skillinuse);
mlog(COMBAT__DAMAGE, "Final damage after all reductions: %d", damage);
Log.Out(Logs::Detail, Logs::Combat, "Final damage after all reductions: %d", damage);
}
//riposte
@@ -1386,7 +1379,7 @@ void Client::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes att
if(spell_id==0)
spell_id = SPELL_UNKNOWN;
// cut all PVP spell damage to 2/3 -solar
// cut all PVP spell damage to 2/3
// Blasting ourselfs is considered PvP
//Don't do PvP mitigation if the caster is damaging himself
if(other && other->IsClient() && (other != this) && damage > 0) {
@@ -1438,7 +1431,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
}
int exploss = 0;
mlog(COMBAT__HITS, "Fatal blow dealt by %s with %d damage, spell %d, skill %d", killerMob ? killerMob->GetName() : "Unknown", damage, spell, attack_skill);
Log.Out(Logs::Detail, Logs::Combat, "Fatal blow dealt by %s with %d damage, spell %d, skill %d", killerMob ? killerMob->GetName() : "Unknown", damage, spell, attack_skill);
/*
#1: Send death packet to everyone
@@ -1592,10 +1585,12 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
//this generates a lot of 'updates' to the client that the client does not need
BuffFadeNonPersistDeath();
if((GetClientVersionBit() & BIT_SoFAndLater) && RuleB(Character, RespawnFromHover))
UnmemSpellAll(true);
else
UnmemSpellAll(false);
if (RuleB(Character, UnmemSpellsOnDeath)) {
if((GetClientVersionBit() & BIT_SoFAndLater) && RuleB(Character, RespawnFromHover))
UnmemSpellAll(true);
else
UnmemSpellAll(false);
}
if((RuleB(Character, LeaveCorpses) && GetLevel() >= RuleI(Character, DeathItemLossLevel)) || RuleB(Character, LeaveNakedCorpses))
{
@@ -1700,7 +1695,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
if (!other) {
SetTarget(nullptr);
LogFile->write(EQEMuLog::Error, "A null Mob object was passed to NPC::Attack() for evaluation!");
Log.Out(Logs::General, Logs::Error, "A null Mob object was passed to NPC::Attack() for evaluation!");
return false;
}
@@ -1718,7 +1713,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
if (other->IsClient())
other->CastToClient()->RemoveXTarget(this, false);
RemoveFromHateList(other);
mlog(COMBAT__ATTACKS, "I am not allowed to attack %s", other->GetName());
Log.Out(Logs::Detail, Logs::Combat, "I am not allowed to attack %s", other->GetName());
}
return false;
}
@@ -1745,10 +1740,10 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
//We dont factor much from the weapon into the attack.
//Just the skill type so it doesn't look silly using punching animations and stuff while wielding weapons
if(weapon) {
mlog(COMBAT__ATTACKS, "Attacking with weapon: %s (%d) (too bad im not using it for much)", weapon->Name, weapon->ID);
Log.Out(Logs::Detail, Logs::Combat, "Attacking with weapon: %s (%d) (too bad im not using it for much)", weapon->Name, weapon->ID);
if(Hand == MainSecondary && weapon->ItemType == ItemTypeShield){
mlog(COMBAT__ATTACKS, "Attack with shield canceled.");
Log.Out(Logs::Detail, Logs::Combat, "Attack with shield canceled.");
return false;
}
@@ -1837,11 +1832,11 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
//check if we're hitting above our max or below it.
if((min_dmg+eleBane) != 0 && damage < (min_dmg+eleBane)) {
mlog(COMBAT__DAMAGE, "Damage (%d) is below min (%d). Setting to min.", damage, (min_dmg+eleBane));
Log.Out(Logs::Detail, Logs::Combat, "Damage (%d) is below min (%d). Setting to min.", damage, (min_dmg+eleBane));
damage = (min_dmg+eleBane);
}
if((max_dmg+eleBane) != 0 && damage > (max_dmg+eleBane)) {
mlog(COMBAT__DAMAGE, "Damage (%d) is above max (%d). Setting to max.", damage, (max_dmg+eleBane));
Log.Out(Logs::Detail, Logs::Combat, "Damage (%d) is above max (%d). Setting to max.", damage, (max_dmg+eleBane));
damage = (max_dmg+eleBane);
}
@@ -1854,7 +1849,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
}
if(other->IsClient() && other->CastToClient()->IsSitting()) {
mlog(COMBAT__DAMAGE, "Client %s is sitting. Hitting for max damage (%d).", other->GetName(), (max_dmg+eleBane));
Log.Out(Logs::Detail, Logs::Combat, "Client %s is sitting. Hitting for max damage (%d).", other->GetName(), (max_dmg+eleBane));
damage = (max_dmg+eleBane);
damage += (itembonuses.HeroicSTR / 10) + (damage * other->GetSkillDmgTaken(skillinuse) / 100) + GetSkillDmgAmt(skillinuse);
@@ -1865,7 +1860,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
hate += opts->hate_flat;
}
mlog(COMBAT__HITS, "Generating hate %d towards %s", hate, GetName());
Log.Out(Logs::Detail, Logs::Combat, "Generating hate %d towards %s", hate, GetName());
// now add done damage to the hate list
other->AddToHateList(this, hate);
@@ -1889,7 +1884,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
if(damage > 0) {
CommonOutgoingHitSuccess(other, damage, skillinuse);
}
mlog(COMBAT__HITS, "Generating hate %d towards %s", hate, GetName());
Log.Out(Logs::Detail, Logs::Combat, "Generating hate %d towards %s", hate, GetName());
// now add done damage to the hate list
if(damage > 0)
other->AddToHateList(this, hate);
@@ -1898,7 +1893,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
}
}
mlog(COMBAT__DAMAGE, "Final damage against %s: %d", other->GetName(), damage);
Log.Out(Logs::Detail, Logs::Combat, "Final damage against %s: %d", other->GetName(), damage);
if(other->IsClient() && IsPet() && GetOwner()->IsClient()) {
//pets do half damage to clients in pvp
@@ -1910,7 +1905,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
//cant riposte a riposte
if (bRiposte && damage == -3) {
mlog(COMBAT__DAMAGE, "Riposte of riposte canceled.");
Log.Out(Logs::Detail, Logs::Combat, "Riposte of riposte canceled.");
return false;
}
@@ -1962,7 +1957,7 @@ void NPC::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack
//handle EVENT_ATTACK. Resets after we have not been attacked for 12 seconds
if(attacked_timer.Check())
{
mlog(COMBAT__HITS, "Triggering EVENT_ATTACK due to attack by %s", other->GetName());
Log.Out(Logs::Detail, Logs::Combat, "Triggering EVENT_ATTACK due to attack by %s", other->GetName());
parse->EventNPC(EVENT_ATTACK, this, other, "", 0);
}
attacked_timer.Start(CombatEventTimer_expire);
@@ -1999,7 +1994,7 @@ void NPC::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack
}
bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack_skill) {
mlog(COMBAT__HITS, "Fatal blow dealt by %s with %d damage, spell %d, skill %d", killerMob->GetName(), damage, spell, attack_skill);
Log.Out(Logs::Detail, Logs::Combat, "Fatal blow dealt by %s with %d damage, spell %d, skill %d", killerMob->GetName(), damage, spell, attack_skill);
bool MadeCorpse = false;
uint16 OrigEntID = this->GetID();
@@ -2039,9 +2034,7 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
if (IsEngaged())
{
zone->DelAggroMob();
#if EQDEBUG >= 11
LogFile->write(EQEMuLog::Debug,"NPC::Death() Mobs currently Aggro %i", zone->MobsAggroCount());
#endif
Log.Out(Logs::Detail, Logs::Attack, "%s Mobs currently Aggro %i", __FUNCTION__, zone->MobsAggroCount());
}
SetHP(0);
SetPet(0);
@@ -2486,7 +2479,7 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b
}
if(IsNPC() && CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
if(!zone->watermap->InLiquid(other->GetX(), other->GetY(), other->GetZ())) {
if(!zone->watermap->InLiquid(glm::vec3(other->GetPosition()))) {
return;
}
}
@@ -2569,7 +2562,7 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b
}
}
// solar: this is called from Damage() when 'this' is attacked by 'other.
// this is called from Damage() when 'this' is attacked by 'other.
// 'this' is the one being attacked
// 'other' is the attacker
// a damage shield causes damage (or healing) to whoever attacks the wearer
@@ -2604,7 +2597,7 @@ void Mob::DamageShield(Mob* attacker, bool spell_ds) {
if(DS == 0 && rev_ds == 0)
return;
mlog(COMBAT__HITS, "Applying Damage Shield of value %d to %s", DS, attacker->GetName());
Log.Out(Logs::Detail, Logs::Combat, "Applying Damage Shield of value %d to %s", DS, attacker->GetName());
//invert DS... spells yield negative values for a true damage shield
if(DS < 0) {
@@ -2649,7 +2642,7 @@ void Mob::DamageShield(Mob* attacker, bool spell_ds) {
rev_ds_spell_id = spellbonuses.ReverseDamageShieldSpellID;
if(rev_ds < 0) {
mlog(COMBAT__HITS, "Applying Reverse Damage Shield of value %d to %s", rev_ds, attacker->GetName());
Log.Out(Logs::Detail, Logs::Combat, "Applying Reverse Damage Shield of value %d to %s", rev_ds, attacker->GetName());
attacker->Damage(this, -rev_ds, rev_ds_spell_id, SkillAbjuration/*hackish*/, false); //"this" (us) will get the hate, etc. not sure how this works on Live, but it'll works for now, and tanks will love us for this
//do we need to send a damage packet here also?
}
@@ -3161,7 +3154,7 @@ int32 Mob::ReduceDamage(int32 damage)
int damage_to_reduce = damage * spellbonuses.MeleeThresholdGuard[0] / 100;
if(damage_to_reduce >= buffs[slot].melee_rune)
{
mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MeleeThresholdGuard %d damage negated, %d"
Log.Out(Logs::Detail, Logs::Spells, "Mob::ReduceDamage SE_MeleeThresholdGuard %d damage negated, %d"
" damage remaining, fading buff.", damage_to_reduce, buffs[slot].melee_rune);
damage -= buffs[slot].melee_rune;
if(!TryFadeEffect(slot))
@@ -3169,7 +3162,7 @@ int32 Mob::ReduceDamage(int32 damage)
}
else
{
mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MeleeThresholdGuard %d damage negated, %d"
Log.Out(Logs::Detail, Logs::Spells, "Mob::ReduceDamage SE_MeleeThresholdGuard %d damage negated, %d"
" damage remaining.", damage_to_reduce, buffs[slot].melee_rune);
buffs[slot].melee_rune = (buffs[slot].melee_rune - damage_to_reduce);
damage -= damage_to_reduce;
@@ -3188,7 +3181,7 @@ int32 Mob::ReduceDamage(int32 damage)
if(spellbonuses.MitigateMeleeRune[3] && (damage_to_reduce >= buffs[slot].melee_rune))
{
mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d"
Log.Out(Logs::Detail, Logs::Spells, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d"
" damage remaining, fading buff.", damage_to_reduce, buffs[slot].melee_rune);
damage -= buffs[slot].melee_rune;
if(!TryFadeEffect(slot))
@@ -3196,7 +3189,7 @@ int32 Mob::ReduceDamage(int32 damage)
}
else
{
mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d"
Log.Out(Logs::Detail, Logs::Spells, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d"
" damage remaining.", damage_to_reduce, buffs[slot].melee_rune);
if (spellbonuses.MitigateMeleeRune[3])
@@ -3314,7 +3307,7 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
if(spellbonuses.MitigateSpellRune[3] && (damage_to_reduce >= buffs[slot].magic_rune))
{
mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateSpellDamage %d damage negated, %d"
Log.Out(Logs::Detail, Logs::Spells, "Mob::ReduceDamage SE_MitigateSpellDamage %d damage negated, %d"
" damage remaining, fading buff.", damage_to_reduce, buffs[slot].magic_rune);
damage -= buffs[slot].magic_rune;
if(!TryFadeEffect(slot))
@@ -3322,7 +3315,7 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
}
else
{
mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d"
Log.Out(Logs::Detail, Logs::Spells, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d"
" damage remaining.", damage_to_reduce, buffs[slot].magic_rune);
if (spellbonuses.MitigateSpellRune[3])
@@ -3363,7 +3356,7 @@ int32 Mob::ReduceAllDamage(int32 damage)
}
}
CheckNumHitsRemaining(NUMHIT_IncomingDamage);
CheckNumHitsRemaining(NumHit::IncomingDamage);
return(damage);
}
@@ -3461,11 +3454,11 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
// This method is called with skill_used=ABJURE for Damage Shield damage.
bool FromDamageShield = (skill_used == SkillAbjuration);
mlog(COMBAT__HITS, "Applying damage %d done by %s with skill %d and spell %d, avoidable? %s, is %sa buff tic in slot %d",
Log.Out(Logs::Detail, Logs::Combat, "Applying damage %d done by %s with skill %d and spell %d, avoidable? %s, is %sa buff tic in slot %d",
damage, attacker?attacker->GetName():"NOBODY", skill_used, spell_id, avoidable?"yes":"no", iBuffTic?"":"not ", buffslot);
if (GetInvul() || DivineAura()) {
mlog(COMBAT__DAMAGE, "Avoiding %d damage due to invulnerability.", damage);
Log.Out(Logs::Detail, Logs::Combat, "Avoiding %d damage due to invulnerability.", damage);
damage = -5;
}
@@ -3479,10 +3472,10 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
}
if (spell_id == SPELL_UNKNOWN && skill_used) {
CheckNumHitsRemaining(NUMHIT_IncomingHitAttempts);
CheckNumHitsRemaining(NumHit::IncomingHitAttempts);
if (attacker)
attacker->CheckNumHitsRemaining(NUMHIT_OutgoingHitAttempts);
attacker->CheckNumHitsRemaining(NumHit::OutgoingHitAttempts);
}
if(attacker){
@@ -3517,7 +3510,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
int healed = damage;
healed = attacker->GetActSpellHealing(spell_id, healed);
mlog(COMBAT__DAMAGE, "Applying lifetap heal of %d to %s", healed, attacker->GetName());
Log.Out(Logs::Detail, Logs::Combat, "Applying lifetap heal of %d to %s", healed, attacker->GetName());
attacker->HealDamage(healed);
//we used to do a message to the client, but its gone now.
@@ -3530,7 +3523,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
if (pet && !pet->IsFamiliar() && !pet->GetSpecialAbility(IMMUNE_AGGRO) && !pet->IsEngaged() && attacker && attacker != this && !attacker->IsCorpse())
{
if (!pet->IsHeld()) {
mlog(PETS__AGGRO, "Sending pet %s into battle due to attack.", pet->GetName());
Log.Out(Logs::Detail, Logs::Aggro, "Sending pet %s into battle due to attack.", pet->GetName());
pet->AddToHateList(attacker, 1);
pet->SetTarget(attacker);
Message_StringID(10, PET_ATTACKING, pet->GetCleanName(), attacker->GetCleanName());
@@ -3540,7 +3533,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
//see if any runes want to reduce this damage
if(spell_id == SPELL_UNKNOWN) {
damage = ReduceDamage(damage);
mlog(COMBAT__HITS, "Melee Damage reduced to %d", damage);
Log.Out(Logs::Detail, Logs::Combat, "Melee Damage reduced to %d", damage);
damage = ReduceAllDamage(damage);
TryTriggerThreshHold(damage, SE_TriggerMeleeThreshold, attacker);
} else {
@@ -3559,7 +3552,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
}
if (skill_used)
CheckNumHitsRemaining(NUMHIT_IncomingHitSuccess);
CheckNumHitsRemaining(NumHit::IncomingHitSuccess);
if(IsClient() && CastToClient()->sneaking){
CastToClient()->sneaking = false;
@@ -3597,7 +3590,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
//fade mez if we are mezzed
if (IsMezzed() && attacker) {
mlog(COMBAT__HITS, "Breaking mez due to attack.");
Log.Out(Logs::Detail, Logs::Combat, "Breaking mez due to attack.");
entity_list.MessageClose_StringID(this, true, 100, MT_WornOff,
HAS_BEEN_AWAKENED, GetCleanName(), attacker->GetCleanName());
BuffFadeByEffect(SE_Mez);
@@ -3640,7 +3633,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
int stun_resist = itembonuses.StunResist + spellbonuses.StunResist;
int frontal_stun_resist = itembonuses.FrontalStunResist + spellbonuses.FrontalStunResist;
mlog(COMBAT__HITS, "Stun passed, checking resists. Was %d chance.", stun_chance);
Log.Out(Logs::Detail, Logs::Combat, "Stun passed, checking resists. Was %d chance.", stun_chance);
if (IsClient()) {
stun_resist += aabonuses.StunResist;
frontal_stun_resist += aabonuses.FrontalStunResist;
@@ -3650,20 +3643,20 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
if (((GetBaseRace() == OGRE && IsClient()) ||
(frontal_stun_resist && zone->random.Roll(frontal_stun_resist))) &&
!attacker->BehindMob(this, attacker->GetX(), attacker->GetY())) {
mlog(COMBAT__HITS, "Frontal stun resisted. %d chance.", frontal_stun_resist);
Log.Out(Logs::Detail, Logs::Combat, "Frontal stun resisted. %d chance.", frontal_stun_resist);
} else {
// Normal stun resist check.
if (stun_resist && zone->random.Roll(stun_resist)) {
if (IsClient())
Message_StringID(MT_Stun, SHAKE_OFF_STUN);
mlog(COMBAT__HITS, "Stun Resisted. %d chance.", stun_resist);
Log.Out(Logs::Detail, Logs::Combat, "Stun Resisted. %d chance.", stun_resist);
} else {
mlog(COMBAT__HITS, "Stunned. %d resist chance.", stun_resist);
Log.Out(Logs::Detail, Logs::Combat, "Stunned. %d resist chance.", stun_resist);
Stun(zone->random.Int(0, 2) * 1000); // 0-2 seconds
}
}
} else {
mlog(COMBAT__HITS, "Stun failed. %d chance.", stun_chance);
Log.Out(Logs::Detail, Logs::Combat, "Stun failed. %d chance.", stun_chance);
}
}
@@ -3677,7 +3670,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
//increment chances of interrupting
if(IsCasting()) { //shouldnt interrupt on regular spell damage
attacked_count++;
mlog(COMBAT__HITS, "Melee attack while casting. Attack count %d", attacked_count);
Log.Out(Logs::Detail, Logs::Combat, "Melee attack while casting. Attack count %d", attacked_count);
}
}
@@ -3883,7 +3876,7 @@ float Mob::GetProcChances(float ProcBonus, uint16 hand)
ProcChance += ProcChance * ProcBonus / 100.0f;
}
mlog(COMBAT__PROCS, "Proc chance %.2f (%.2f from bonuses)", ProcChance, ProcBonus);
Log.Out(Logs::Detail, Logs::Combat, "Proc chance %.2f (%.2f from bonuses)", ProcChance, ProcBonus);
return ProcChance;
}
@@ -3902,7 +3895,7 @@ float Mob::GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 h
ProcBonus += static_cast<float>(myagi) * RuleR(Combat, DefProcPerMinAgiContrib) / 100.0f;
ProcChance = ProcChance + (ProcChance * ProcBonus);
mlog(COMBAT__PROCS, "Defensive Proc chance %.2f (%.2f from bonuses)", ProcChance, ProcBonus);
Log.Out(Logs::Detail, Logs::Combat, "Defensive Proc chance %.2f (%.2f from bonuses)", ProcChance, ProcBonus);
return ProcChance;
}
@@ -3911,7 +3904,7 @@ void Mob::TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand) {
if (!on) {
SetTarget(nullptr);
LogFile->write(EQEMuLog::Error, "A null Mob object was passed to Mob::TryDefensiveProc for evaluation!");
Log.Out(Logs::General, Logs::Error, "A null Mob object was passed to Mob::TryDefensiveProc for evaluation!");
return;
}
@@ -3932,7 +3925,8 @@ void Mob::TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand) {
float chance = ProcChance * (static_cast<float>(DefensiveProcs[i].chance)/100.0f);
if (zone->random.Roll(chance)) {
ExecWeaponProc(nullptr, DefensiveProcs[i].spellID, on);
CheckNumHitsRemaining(NUMHIT_DefensiveSpellProcs,0,DefensiveProcs[i].base_spellID);
CheckNumHitsRemaining(NumHit::DefensiveSpellProcs, 0,
DefensiveProcs[i].base_spellID);
}
}
}
@@ -3942,17 +3936,17 @@ void Mob::TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand) {
void Mob::TryWeaponProc(const ItemInst* weapon_g, Mob *on, uint16 hand) {
if(!on) {
SetTarget(nullptr);
LogFile->write(EQEMuLog::Error, "A null Mob object was passed to Mob::TryWeaponProc for evaluation!");
Log.Out(Logs::General, Logs::Error, "A null Mob object was passed to Mob::TryWeaponProc for evaluation!");
return;
}
if (!IsAttackAllowed(on)) {
mlog(COMBAT__PROCS, "Preventing procing off of unattackable things.");
Log.Out(Logs::Detail, Logs::Combat, "Preventing procing off of unattackable things.");
return;
}
if (DivineAura()) {
mlog(COMBAT__PROCS, "Procs canceled, Divine Aura is in effect.");
Log.Out(Logs::Detail, Logs::Combat, "Procs canceled, Divine Aura is in effect.");
return;
}
@@ -3999,7 +3993,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on
static_cast<float>(weapon->ProcRate)) / 100.0f;
if (zone->random.Roll(WPC)) { // 255 dex = 0.084 chance of proc. No idea what this number should be really.
if (weapon->Proc.Level > ourlevel) {
mlog(COMBAT__PROCS,
Log.Out(Logs::Detail, Logs::Combat,
"Tried to proc (%s), but our level (%d) is lower than required (%d)",
weapon->Name, ourlevel, weapon->Proc.Level);
if (IsPet()) {
@@ -4010,7 +4004,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on
Message_StringID(13, PROC_TOOLOW);
}
} else {
mlog(COMBAT__PROCS,
Log.Out(Logs::Detail, Logs::Combat,
"Attacking weapon (%s) successfully procing spell %d (%.2f percent chance)",
weapon->Name, weapon->Proc.Effect, WPC * 100);
ExecWeaponProc(inst, weapon->Proc.Effect, on);
@@ -4089,12 +4083,12 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on,
// Perma procs (AAs)
if (PermaProcs[i].spellID != SPELL_UNKNOWN) {
if (zone->random.Roll(PermaProcs[i].chance)) { // TODO: Do these get spell bonus?
mlog(COMBAT__PROCS,
Log.Out(Logs::Detail, Logs::Combat,
"Permanent proc %d procing spell %d (%d percent chance)",
i, PermaProcs[i].spellID, PermaProcs[i].chance);
ExecWeaponProc(nullptr, PermaProcs[i].spellID, on);
} else {
mlog(COMBAT__PROCS,
Log.Out(Logs::Detail, Logs::Combat,
"Permanent proc %d failed to proc %d (%d percent chance)",
i, PermaProcs[i].spellID, PermaProcs[i].chance);
}
@@ -4104,13 +4098,14 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on,
if (SpellProcs[i].spellID != SPELL_UNKNOWN) {
float chance = ProcChance * (static_cast<float>(SpellProcs[i].chance) / 100.0f);
if (zone->random.Roll(chance)) {
mlog(COMBAT__PROCS,
Log.Out(Logs::Detail, Logs::Combat,
"Spell proc %d procing spell %d (%.2f percent chance)",
i, SpellProcs[i].spellID, chance);
ExecWeaponProc(nullptr, SpellProcs[i].spellID, on);
CheckNumHitsRemaining(NUMHIT_OffensiveSpellProcs, 0, SpellProcs[i].base_spellID);
CheckNumHitsRemaining(NumHit::OffensiveSpellProcs, 0,
SpellProcs[i].base_spellID);
} else {
mlog(COMBAT__PROCS,
Log.Out(Logs::Detail, Logs::Combat,
"Spell proc %d failed to proc %d (%.2f percent chance)",
i, SpellProcs[i].spellID, chance);
}
@@ -4120,13 +4115,14 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on,
if (RangedProcs[i].spellID != SPELL_UNKNOWN) {
float chance = ProcChance * (static_cast<float>(RangedProcs[i].chance) / 100.0f);
if (zone->random.Roll(chance)) {
mlog(COMBAT__PROCS,
Log.Out(Logs::Detail, Logs::Combat,
"Ranged proc %d procing spell %d (%.2f percent chance)",
i, RangedProcs[i].spellID, chance);
ExecWeaponProc(nullptr, RangedProcs[i].spellID, on);
CheckNumHitsRemaining(NUMHIT_OffensiveSpellProcs, 0, RangedProcs[i].base_spellID);
CheckNumHitsRemaining(NumHit::OffensiveSpellProcs, 0,
RangedProcs[i].base_spellID);
} else {
mlog(COMBAT__PROCS,
Log.Out(Logs::Detail, Logs::Combat,
"Ranged proc %d failed to proc %d (%.2f percent chance)",
i, RangedProcs[i].spellID, chance);
}
@@ -4376,7 +4372,7 @@ bool Mob::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse)
}
void Mob::DoRiposte(Mob* defender) {
mlog(COMBAT__ATTACKS, "Preforming a riposte");
Log.Out(Logs::Detail, Logs::Combat, "Preforming a riposte");
if (!defender)
return;
@@ -4394,7 +4390,7 @@ void Mob::DoRiposte(Mob* defender) {
//Live AA - Double Riposte
if(DoubleRipChance && zone->random.Roll(DoubleRipChance)) {
mlog(COMBAT__ATTACKS, "Preforming a double riposed (%d percent chance)", DoubleRipChance);
Log.Out(Logs::Detail, Logs::Combat, "Preforming a double riposed (%d percent chance)", DoubleRipChance);
defender->Attack(this, MainPrimary, true);
if (HasDied()) return;
}
@@ -4405,7 +4401,7 @@ void Mob::DoRiposte(Mob* defender) {
DoubleRipChance = defender->aabonuses.GiveDoubleRiposte[1];
if(DoubleRipChance && zone->random.Roll(DoubleRipChance)) {
mlog(COMBAT__ATTACKS, "Preforming a return SPECIAL ATTACK (%d percent chance)", DoubleRipChance);
Log.Out(Logs::Detail, Logs::Combat, "Preforming a return SPECIAL ATTACK (%d percent chance)", DoubleRipChance);
if (defender->GetClass() == MONK)
defender->MonkSpecialAttack(this, defender->aabonuses.GiveDoubleRiposte[2]);
@@ -4422,7 +4418,7 @@ void Mob::ApplyMeleeDamageBonus(uint16 skill, int32 &damage){
int dmgbonusmod = 0;
dmgbonusmod += (100*(itembonuses.STR + spellbonuses.STR))/3;
dmgbonusmod += (100*(spellbonuses.ATK + itembonuses.ATK))/5;
mlog(COMBAT__DAMAGE, "Damage bonus: %d percent from ATK and STR bonuses.", (dmgbonusmod/100));
Log.Out(Logs::Detail, Logs::Combat, "Damage bonus: %d percent from ATK and STR bonuses.", (dmgbonusmod/100));
damage += (damage*dmgbonusmod/10000);
}
}
@@ -4491,7 +4487,7 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
if (!on) {
SetTarget(nullptr);
LogFile->write(EQEMuLog::Error, "A null Mob object was passed to Mob::TrySkillProc for evaluation!");
Log.Out(Logs::General, Logs::Error, "A null Mob object was passed to Mob::TrySkillProc for evaluation!");
return;
}
@@ -4541,7 +4537,8 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
float final_chance = chance * (ProcMod / 100.0f);
if (zone->random.Roll(final_chance)) {
ExecWeaponProc(nullptr, proc_spell_id, on);
CheckNumHitsRemaining(NUMHIT_OffensiveSpellProcs,0, base_spell_id);
CheckNumHitsRemaining(NumHit::OffensiveSpellProcs, 0,
base_spell_id);
CanProc = false;
break;
}
@@ -4716,13 +4713,13 @@ bool Mob::TryRootFadeByDamage(int buffslot, Mob* attacker) {
if (!TryFadeEffect(spellbonuses.Root[1])) {
BuffFadeBySlot(spellbonuses.Root[1]);
mlog(COMBAT__HITS, "Spell broke root! BreakChance percent chance");
Log.Out(Logs::Detail, Logs::Combat, "Spell broke root! BreakChance percent chance");
return true;
}
}
}
mlog(COMBAT__HITS, "Spell did not break root. BreakChance percent chance");
Log.Out(Logs::Detail, Logs::Combat, "Spell did not break root. BreakChance percent chance");
return false;
}
@@ -4787,26 +4784,26 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, int32 &damage, SkillUseTypes s
ApplyMeleeDamageBonus(skillInUse, damage);
damage += (damage * defender->GetSkillDmgTaken(skillInUse) / 100) + (GetSkillDmgAmt(skillInUse) + defender->GetFcDamageAmtIncoming(this, 0, true, skillInUse));
TryCriticalHit(defender, skillInUse, damage);
CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess);
CheckNumHitsRemaining(NumHit::OutgoingHitSuccess);
}
void Mob::CommonBreakInvisible()
{
//break invis when you attack
if(invisible) {
mlog(COMBAT__ATTACKS, "Removing invisibility due to melee attack.");
Log.Out(Logs::Detail, Logs::Combat, "Removing invisibility due to melee attack.");
BuffFadeByEffect(SE_Invisibility);
BuffFadeByEffect(SE_Invisibility2);
invisible = false;
}
if(invisible_undead) {
mlog(COMBAT__ATTACKS, "Removing invisibility vs. undead due to melee attack.");
Log.Out(Logs::Detail, Logs::Combat, "Removing invisibility vs. undead due to melee attack.");
BuffFadeByEffect(SE_InvisVsUndead);
BuffFadeByEffect(SE_InvisVsUndead2);
invisible_undead = false;
}
if(invisible_animals){
mlog(COMBAT__ATTACKS, "Removing invisibility vs. animals due to melee attack.");
Log.Out(Logs::Detail, Logs::Combat, "Removing invisibility vs. animals due to melee attack.");
BuffFadeByEffect(SE_InvisVsAnimals);
invisible_animals = false;
}
@@ -4835,20 +4832,20 @@ void Mob::CommonBreakInvisible()
/* Dev quotes:
* Old formula
* Final delay = (Original Delay / (haste mod *.01f)) + ((Hundred Hands / 100) * Original Delay)
* Final delay = (Original Delay / (haste mod *.01f)) + ((Hundred Hands / 100) * Original Delay)
* New formula
* Final delay = (Original Delay / (haste mod *.01f)) + ((Hundred Hands / 1000) * (Original Delay / (haste mod *.01f))
* Base Delay 20 25 30 37
* Haste 2.25 2.25 2.25 2.25
* HHE (old) -17 -17 -17 -17
* Final Delay 5.488888889 6.861111111 8.233333333 10.15444444
* Final delay = (Original Delay / (haste mod *.01f)) + ((Hundred Hands / 1000) * (Original Delay / (haste mod *.01f))
* Base Delay 20 25 30 37
* Haste 2.25 2.25 2.25 2.25
* HHE (old) -17 -17 -17 -17
* Final Delay 5.488888889 6.861111111 8.233333333 10.15444444
*
* Base Delay 20 25 30 37
* Haste 2.25 2.25 2.25 2.25
* HHE (new) -383 -383 -383 -383
* Final Delay 5.484444444 6.855555556 8.226666667 10.14622222
* Base Delay 20 25 30 37
* Haste 2.25 2.25 2.25 2.25
* HHE (new) -383 -383 -383 -383
* Final Delay 5.484444444 6.855555556 8.226666667 10.14622222
*
* Difference -0.004444444 -0.005555556 -0.006666667 -0.008222222
* Difference -0.004444444 -0.005555556 -0.006666667 -0.008222222
*
* These times are in 10th of a second
*/
+5 -18
View File
@@ -18,7 +18,7 @@
/*
solar: Beacon class, extends Mob. Used for AE rain spells to have a mob
Beacon class, extends Mob. Used for AE rain spells to have a mob
target to center around.
*/
@@ -35,7 +35,7 @@ class Zone;
#include "../common/races.h"
#include "beacon.h"
#include "entity.h"
#include "mob.h"
#include "mob.h"
#ifdef BOTS
@@ -48,12 +48,12 @@ class Zone;
extern EntityList entity_list;
extern Zone* zone;
// solar: if lifetime is 0 this is a permanent beacon.. not sure if that'll be
// if lifetime is 0 this is a permanent beacon.. not sure if that'll be
// useful for anything
Beacon::Beacon(Mob *at_mob, int lifetime)
:Mob
(
nullptr, nullptr, 0, 0, 0, INVISIBLE_MAN, 0, BT_NoTarget, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
nullptr, nullptr, 0, 0, 0, INVISIBLE_MAN, 0, BT_NoTarget, 0, 0, 0, 0, 0, at_mob->GetPosition(), 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
),
remove_timer(lifetime),
@@ -67,26 +67,13 @@ Beacon::Beacon(Mob *at_mob, int lifetime)
spell_iterations = 0;
caster_id = 0;
// copy location
x_pos = at_mob->GetX();
y_pos = at_mob->GetY();
z_pos = at_mob->GetZ();
heading = at_mob->GetHeading();
if(lifetime)
{
remove_timer.Start();
}
#ifdef SOLAR
entity_list.Message(0, 0, "Beacon being created at %0.2f %0.2f %0.2f heading %0.2f lifetime %d", GetX(), GetY(), GetZ(), GetHeading(), lifetime);
#endif
}
Beacon::~Beacon()
{
#ifdef SOLAR
entity_list.Message(0, 0, "Beacon %d being removed at %0.2f %0.2f %0.2f heading %0.2f", GetID(), GetX(), GetY(), GetZ(), GetHeading());
#endif
}
bool Beacon::Process()
+9 -13
View File
@@ -16,7 +16,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/classes.h"
#include "../common/debug.h"
#include "../common/global_define.h"
#include "../common/item.h"
#include "../common/rulesys.h"
#include "../common/skills.h"
@@ -77,9 +77,9 @@ void Client::CalcBonuses()
CalcSpellBonuses(&spellbonuses);
_log(AA__BONUSES, "Calculating AA Bonuses for %s.", this->GetCleanName());
Log.Out(Logs::Detail, Logs::AA, "Calculating AA Bonuses for %s.", this->GetCleanName());
CalcAABonuses(&aabonuses); //we're not quite ready for this
_log(AA__BONUSES, "Finished calculating AA Bonuses for %s.", this->GetCleanName());
Log.Out(Logs::Detail, Logs::AA, "Finished calculating AA Bonuses for %s.", this->GetCleanName());
RecalcWeight();
@@ -155,7 +155,7 @@ void Client::CalcItemBonuses(StatBonuses* newbon) {
}
//Power Source Slot
if (GetClientVersion() >= EQClientSoF)
if (GetClientVersion() >= ClientVersion::SoF)
{
const ItemInst* inst = m_inv[MainPowerSource];
if(inst)
@@ -538,11 +538,7 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAu
}
void Client::CalcEdibleBonuses(StatBonuses* newbon) {
//#if EQDEBUG >= 11
// std::cout<<"Client::CalcEdibleBonuses(StatBonuses* newbon)"<<std::endl;
//#endif
// Search player slots for skill=14(food) and skill=15(drink)
uint32 i;
uint32 i;
bool food = false;
bool drink = false;
@@ -638,7 +634,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
if (effect == SE_Blank || (effect == SE_CHA && base1 == 0) || effect == SE_StackingCommand_Block || effect == SE_StackingCommand_Overwrite)
continue;
_log(AA__BONUSES, "Applying Effect %d from AA %u in slot %d (base1: %d, base2: %d) on %s", effect, aaid, slot, base1, base2, this->GetCleanName());
Log.Out(Logs::Detail, Logs::AA, "Applying Effect %d from AA %u in slot %d (base1: %d, base2: %d) on %s", effect, aaid, slot, base1, base2, this->GetCleanName());
uint8 focus = IsFocusEffect(0, 0, true,effect);
if (focus)
@@ -2980,7 +2976,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
//Special custom cases for loading effects on to NPC from 'npc_spels_effects' table
if (IsAISpellEffect) {
//Non-Focused Effect to modify incomming spell damage by resist type.
//Non-Focused Effect to modify incoming spell damage by resist type.
case SE_FcSpellVulnerability:
ModVulnerability(base2, effect_value);
break;
@@ -3086,7 +3082,7 @@ void Client::CalcItemScale() {
changed = true;
//Power Source Slot
if (GetClientVersion() >= EQClientSoF)
if (GetClientVersion() >= ClientVersion::SoF)
{
if(CalcItemScale(MainPowerSource, MainPowerSource))
changed = true;
@@ -3180,7 +3176,7 @@ void Client::DoItemEnterZone() {
changed = true;
//Power Source Slot
if (GetClientVersion() >= EQClientSoF)
if (GetClientVersion() >= ClientVersion::SoF)
{
if(DoItemEnterZone(MainPowerSource, MainPowerSource))
changed = true;
+142 -132
View File
@@ -9,7 +9,7 @@
extern volatile bool ZoneLoaded;
// This constructor is used during the bot create command
Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, 0, 0, 0, 0, 0, 0, false), rest_timer(1) {
Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm::vec4(), 0, false), rest_timer(1) {
if(botOwner) {
this->SetBotOwner(botOwner);
this->_botOwnerCharacterID = botOwner->CharacterID();
@@ -96,10 +96,12 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, 0, 0, 0, 0,
}
strcpy(this->name, this->GetCleanName());
active_light = spell_light = equip_light = innate_light = NOT_USED;
}
// This constructor is used when the bot is loaded out of the database
Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double totalPlayTime, uint32 lastZoneId, NPCType npcTypeData) : NPC(&npcTypeData, 0, 0, 0, 0, 0, 0, false), rest_timer(1) {
Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double totalPlayTime, uint32 lastZoneId, NPCType npcTypeData) : NPC(&npcTypeData, nullptr, glm::vec4(), 0, false), rest_timer(1) {
this->_botOwnerCharacterID = botOwnerCharacterID;
if(this->_botOwnerCharacterID > 0) {
@@ -211,6 +213,8 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to
if(cur_mana > max_mana)
cur_mana = max_mana;
cur_end = max_end;
active_light = spell_light = equip_light = innate_light = NOT_USED;
}
Bot::~Bot() {
@@ -380,6 +384,8 @@ NPCType Bot::FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::str
BotNPCType.mana_regen = 1;
BotNPCType.maxlevel = botLevel;
BotNPCType.light = NOT_USED; // due to the way that bots are coded..this is sent post-spawn
return BotNPCType;
}
@@ -1225,7 +1231,7 @@ int32 Bot::acmod()
return (65 + ((agility-300) / 21));
}
#if EQDEBUG >= 11
LogFile->write(EQEMuLog::Error, "Error in Bot::acmod(): Agility: %i, Level: %i",agility,level);
Log.Out(Logs::General, Logs::Error, "Error in Bot::acmod(): Agility: %i, Level: %i",agility,level);
#endif
return 0;
}
@@ -1375,7 +1381,7 @@ int32 Bot::GenerateBaseHitPoints()
uint32 Post255;
uint32 NormalSTA = GetSTA();
if(GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= EQClientSoD && RuleB(Character, SoDClientUseSoDHPManaEnd))
if(GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd))
{
float SoDPost255;
@@ -1462,7 +1468,7 @@ void Bot::LoadAAs() {
auto results = database.QueryDatabase(query);
if(!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in Bot::LoadAAs()");
Log.Out(Logs::General, Logs::Error, "Error in Bot::LoadAAs()");
return;
}
@@ -1564,7 +1570,7 @@ void Bot::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
if (effect == SE_Blank || (effect == SE_CHA && base1 == 0) || effect == SE_StackingCommand_Block || effect == SE_StackingCommand_Overwrite)
continue;
_log(AA__BONUSES, "Applying Effect %d from AA %u in slot %d (base1: %d, base2: %d) on %s", effect, aaid, slot, base1, base2, this->GetCleanName());
Log.Out(Logs::Detail, Logs::AA, "Applying Effect %d from AA %u in slot %d (base1: %d, base2: %d) on %s", effect, aaid, slot, base1, base2, this->GetCleanName());
uint8 focus = IsFocusEffect(0, 0, true,effect);
if (focus)
@@ -2774,7 +2780,7 @@ void Bot::LoadStance() {
std::string query = StringFormat("SELECT StanceID FROM botstances WHERE BotID = %u;", GetBotID());
auto results = database.QueryDatabase(query);
if(!results.Success() || results.RowCount() == 0) {
LogFile->write(EQEMuLog::Error, "Error in Bot::LoadStance()");
Log.Out(Logs::General, Logs::Error, "Error in Bot::LoadStance()");
SetDefaultBotStance();
return;
}
@@ -2792,7 +2798,7 @@ void Bot::SaveStance() {
"VALUES(%u, %u);", GetBotID(), GetBotStance());
auto results = database.QueryDatabase(query);
if(!results.Success())
LogFile->write(EQEMuLog::Error, "Error in Bot::SaveStance()");
Log.Out(Logs::General, Logs::Error, "Error in Bot::SaveStance()");
}
@@ -2807,7 +2813,7 @@ void Bot::LoadTimers() {
GetBotID(), DisciplineReuseStart-1, DisciplineReuseStart-1, GetClass(), GetLevel());
auto results = database.QueryDatabase(query);
if(!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in Bot::LoadTimers()");
Log.Out(Logs::General, Logs::Error, "Error in Bot::LoadTimers()");
return;
}
@@ -2847,7 +2853,7 @@ void Bot::SaveTimers() {
}
if(hadError)
LogFile->write(EQEMuLog::Error, "Error in Bot::SaveTimers()");
Log.Out(Logs::General, Logs::Error, "Error in Bot::SaveTimers()");
}
@@ -2979,7 +2985,7 @@ void Bot::BotRangedAttack(Mob* other) {
//make sure the attack and ranged timers are up
//if the ranged timer is disabled, then they have no ranged weapon and shouldent be attacking anyhow
if((attack_timer.Enabled() && !attack_timer.Check(false)) || (ranged_timer.Enabled() && !ranged_timer.Check())) {
mlog(COMBAT__RANGED, "Bot Archery attack canceled. Timer not up. Attack %d, ranged %d", attack_timer.GetRemainingTime(), ranged_timer.GetRemainingTime());
Log.Out(Logs::Detail, Logs::Combat, "Bot Archery attack canceled. Timer not up. Attack %d, ranged %d", attack_timer.GetRemainingTime(), ranged_timer.GetRemainingTime());
Message(0, "Error: Timer not up. Attack %d, ranged %d", attack_timer.GetRemainingTime(), ranged_timer.GetRemainingTime());
return;
}
@@ -2997,7 +3003,7 @@ void Bot::BotRangedAttack(Mob* other) {
if(!RangeWeapon || !Ammo)
return;
mlog(COMBAT__RANGED, "Shooting %s with bow %s (%d) and arrow %s (%d)", other->GetCleanName(), RangeWeapon->Name, RangeWeapon->ID, Ammo->Name, Ammo->ID);
Log.Out(Logs::Detail, Logs::Combat, "Shooting %s with bow %s (%d) and arrow %s (%d)", other->GetCleanName(), RangeWeapon->Name, RangeWeapon->ID, Ammo->Name, Ammo->ID);
if(!IsAttackAllowed(other) ||
IsCasting() ||
@@ -3015,19 +3021,19 @@ void Bot::BotRangedAttack(Mob* other) {
//break invis when you attack
if(invisible) {
mlog(COMBAT__ATTACKS, "Removing invisibility due to melee attack.");
Log.Out(Logs::Detail, Logs::Combat, "Removing invisibility due to melee attack.");
BuffFadeByEffect(SE_Invisibility);
BuffFadeByEffect(SE_Invisibility2);
invisible = false;
}
if(invisible_undead) {
mlog(COMBAT__ATTACKS, "Removing invisibility vs. undead due to melee attack.");
Log.Out(Logs::Detail, Logs::Combat, "Removing invisibility vs. undead due to melee attack.");
BuffFadeByEffect(SE_InvisVsUndead);
BuffFadeByEffect(SE_InvisVsUndead2);
invisible_undead = false;
}
if(invisible_animals){
mlog(COMBAT__ATTACKS, "Removing invisibility vs. animals due to melee attack.");
Log.Out(Logs::Detail, Logs::Combat, "Removing invisibility vs. animals due to melee attack.");
BuffFadeByEffect(SE_InvisVsAnimals);
invisible_animals = false;
}
@@ -3184,7 +3190,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes
return;
if (damage > 0)
CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess);
CheckNumHitsRemaining(NumHit::OutgoingHitSuccess);
if((skillinuse == SkillDragonPunch) && GetAA(aaDragonPunch) && zone->random.Int(0, 99) < 25){
SpellFinished(904, other, 10, 0, -1, spells[904].ResistDiff);
@@ -3354,7 +3360,7 @@ void Bot::AI_Process() {
if(GetHasBeenSummoned()) {
if(IsBotCaster() || IsBotArcher()) {
if (AImovement_timer->Check()) {
if(!GetTarget() || (IsBotCaster() && !IsBotCasterCombatRange(GetTarget())) || (IsBotArcher() && IsArcheryRange(GetTarget())) || (DistNoRootNoZ(GetPreSummonX(), GetPreSummonY()) < 10)) {
if(!GetTarget() || (IsBotCaster() && !IsBotCasterCombatRange(GetTarget())) || (IsBotArcher() && IsArcheryRange(GetTarget())) || (DistanceSquaredNoZ(static_cast<glm::vec3>(m_Position), m_PreSummonLocation) < 10)) {
if(GetTarget())
FaceTarget(GetTarget());
SetHasBeenSummoned(false);
@@ -3362,9 +3368,9 @@ void Bot::AI_Process() {
else if(!IsRooted()) {
if(GetTarget() && GetTarget()->GetHateTop() && GetTarget()->GetHateTop() != this)
{
mlog(AI__WAYPOINTS, "Returning to location prior to being summoned.");
CalculateNewPosition2(GetPreSummonX(), GetPreSummonY(), GetPreSummonZ(), GetRunspeed());
SetHeading(CalculateHeadingToTarget(GetPreSummonX(), GetPreSummonY()));
Log.Out(Logs::Detail, Logs::AI, "Returning to location prior to being summoned.");
CalculateNewPosition2(m_PreSummonLocation.x, m_PreSummonLocation.y, m_PreSummonLocation.z, GetRunspeed());
SetHeading(CalculateHeadingToTarget(m_PreSummonLocation.x, m_PreSummonLocation.y));
return;
}
}
@@ -3505,7 +3511,7 @@ void Bot::AI_Process() {
if(IsBotCasterCombatRange(GetTarget()))
atCombatRange = true;
}
else if(DistNoRoot(*GetTarget()) <= meleeDistance) {
else if(DistanceSquared(m_Position, GetTarget()->GetPosition()) <= meleeDistance) {
atCombatRange = true;
}
@@ -3533,7 +3539,7 @@ void Bot::AI_Process() {
return;
}
}
else if(!IsMoving() && GetClass() != ROGUE && (DistNoRootNoZ(*GetTarget()) < GetTarget()->GetSize())) {
else if(!IsMoving() && GetClass() != ROGUE && (DistanceSquaredNoZ(m_Position, GetTarget()->GetPosition()) < GetTarget()->GetSize())) {
// If we are not a rogue trying to backstab, let's try to adjust our melee range so we don't appear to be bunched up
float newX = 0;
float newY = 0;
@@ -3689,7 +3695,7 @@ void Bot::AI_Process() {
if (AImovement_timer->Check()) {
if(!IsRooted()) {
mlog(AI__WAYPOINTS, "Pursuing %s while engaged.", GetTarget()->GetCleanName());
Log.Out(Logs::Detail, Logs::AI, "Pursuing %s while engaged.", GetTarget()->GetCleanName());
CalculateNewPosition2(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), GetRunspeed());
return;
}
@@ -3732,7 +3738,7 @@ void Bot::AI_Process() {
Mob* follow = entity_list.GetMob(GetFollowID());
if(follow) {
float dist = DistNoRoot(*follow);
float dist = DistanceSquared(m_Position, follow->GetPosition());
float speed = follow->GetRunspeed();
if(dist < GetFollowDistance() + 1000)
@@ -3865,7 +3871,7 @@ void Bot::PetAIProcess() {
return;
}
}
else if(botPet->DistNoRootNoZ(*botPet->GetTarget()) < botPet->GetTarget()->GetSize()) {
else if(DistanceSquaredNoZ(botPet->GetPosition(), botPet->GetTarget()->GetPosition()) < botPet->GetTarget()->GetSize()) {
// Let's try to adjust our melee range so we don't appear to be bunched up
bool isBehindMob = false;
bool moveBehindMob = false;
@@ -3972,7 +3978,7 @@ void Bot::PetAIProcess() {
{
botPet->SetRunAnimSpeed(0);
if(!botPet->IsRooted()) {
mlog(AI__WAYPOINTS, "Pursuing %s while engaged.", botPet->GetTarget()->GetCleanName());
Log.Out(Logs::Detail, Logs::AI, "Pursuing %s while engaged.", botPet->GetTarget()->GetCleanName());
botPet->CalculateNewPosition2(botPet->GetTarget()->GetX(), botPet->GetTarget()->GetY(), botPet->GetTarget()->GetZ(), botPet->GetOwner()->GetRunspeed());
return;
}
@@ -4003,7 +4009,7 @@ void Bot::PetAIProcess() {
switch(pStandingPetOrder) {
case SPO_Follow:
{
float dist = botPet->DistNoRoot(*botPet->GetTarget());
float dist = DistanceSquared(botPet->GetPosition(), botPet->GetTarget()->GetPosition());
botPet->SetRunAnimSpeed(0);
if(dist > 184) {
botPet->CalculateNewPosition2(botPet->GetTarget()->GetX(), botPet->GetTarget()->GetY(), botPet->GetTarget()->GetZ(), botPet->GetTarget()->GetRunspeed());
@@ -4105,9 +4111,9 @@ void Bot::Spawn(Client* botCharacterOwner, std::string* errorMessage) {
this->GetBotOwner()->CastToClient()->Message(13, "%s save failed!", this->GetCleanName());
// Spawn the bot at the bow owner's loc
this->x_pos = botCharacterOwner->GetX();
this->y_pos = botCharacterOwner->GetY();
this->z_pos = botCharacterOwner->GetZ();
this->m_Position.x = botCharacterOwner->GetX();
this->m_Position.y = botCharacterOwner->GetY();
this->m_Position.z = botCharacterOwner->GetZ();
// Make the bot look at the bot owner
FaceTarget(botCharacterOwner);
@@ -4115,6 +4121,9 @@ void Bot::Spawn(Client* botCharacterOwner, std::string* errorMessage) {
// Level the bot to the same level as the bot owner
//this->SetLevel(botCharacterOwner->GetLevel());
UpdateEquipLightValue();
UpdateActiveLightValue();
entity_list.AddBot(this, true, true);
// Load pet
@@ -4178,6 +4187,7 @@ void Bot::RemoveBotItemBySlot(uint32 slotID, std::string *errorMessage) {
*errorMessage = std::string(results.ErrorMessage());
m_inv.DeleteItem(slotID);
UpdateEquipLightValue();
}
// Retrieves all the inventory records from the database for this bot.
@@ -4211,7 +4221,7 @@ void Bot::GetBotItems(std::string* errorMessage, Inventory &inv) {
ItemInst* inst = database.CreateItem(item_id, charges, aug[0], aug[1], aug[2], aug[3], aug[4]);
if (!inst) {
LogFile->write(EQEMuLog::Error, "Warning: botid %i has an invalid item_id %i in inventory slot %i", this->GetBotID(), item_id, slot_id);
Log.Out(Logs::General, Logs::Error, "Warning: botid %i has an invalid item_id %i in inventory slot %i", this->GetBotID(), item_id, slot_id);
continue;
}
@@ -4235,10 +4245,11 @@ void Bot::GetBotItems(std::string* errorMessage, Inventory &inv) {
// Save ptr to item in inventory
if (put_slot_id == INVALID_INDEX)
LogFile->write(EQEMuLog::Error, "Warning: Invalid slot_id for item in inventory: botid=%i, item_id=%i, slot_id=%i",this->GetBotID(), item_id, slot_id);
Log.Out(Logs::General, Logs::Error, "Warning: Invalid slot_id for item in inventory: botid=%i, item_id=%i, slot_id=%i",this->GetBotID(), item_id, slot_id);
}
UpdateEquipLightValue();
}
// Returns the inventory record for this bot from the database for the specified equipment slot.
@@ -4364,6 +4375,9 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
ns->spawn.size = 0;
ns->spawn.NPC = 0; // 0=player,1=npc,2=pc corpse,3=npc corpse
UpdateActiveLightValue();
ns->spawn.light = active_light;
ns->spawn.helm = helmtexture; //0xFF;
ns->spawn.equip_chest2 = texture; //0xFF;
@@ -5073,6 +5087,10 @@ void Bot::BotAddEquipItem(int slot, uint32 id) {
equipment[slot] = id; // npc has more than just material slots. Valid material should mean valid inventory index
SendWearChange(materialFromSlot);
}
UpdateEquipLightValue();
if (UpdateActiveLightValue())
SendAppearancePacket(AT_Light, GetActiveLightValue());
}
}
@@ -5087,6 +5105,10 @@ void Bot::BotRemoveEquipItem(int slot) {
if(materialFromSlot == MaterialChest)
SendWearChange(MaterialArms);
}
UpdateEquipLightValue();
if (UpdateActiveLightValue())
SendAppearancePacket(AT_Light, GetActiveLightValue());
}
}
@@ -5959,7 +5981,7 @@ void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, SkillUseTypes attack_
//handle EVENT_ATTACK. Resets after we have not been attacked for 12 seconds
if(attacked_timer.Check()) {
mlog(COMBAT__HITS, "Triggering EVENT_ATTACK due to attack by %s", from->GetName());
Log.Out(Logs::Detail, Logs::Combat, "Triggering EVENT_ATTACK due to attack by %s", from->GetName());
parse->EventNPC(EVENT_ATTACK, this, from, "", 0);
}
@@ -5972,7 +5994,7 @@ void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, SkillUseTypes attack_
// if spell is lifetap add hp to the caster
if (spell_id != SPELL_UNKNOWN && IsLifetapSpell(spell_id)) {
int healed = GetActSpellHealing(spell_id, damage);
mlog(COMBAT__DAMAGE, "Applying lifetap heal of %d to %s", healed, GetCleanName());
Log.Out(Logs::Detail, Logs::Combat, "Applying lifetap heal of %d to %s", healed, GetCleanName());
HealDamage(healed);
entity_list.MessageClose(this, true, 300, MT_Spells, "%s beams a smile at %s", GetCleanName(), from->GetCleanName() );
}
@@ -6017,14 +6039,14 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b
{
if (!other) {
SetTarget(nullptr);
LogFile->write(EQEMuLog::Error, "A null Mob object was passed to Bot::Attack for evaluation!");
Log.Out(Logs::General, Logs::Error, "A null Mob object was passed to Bot::Attack for evaluation!");
return false;
}
if(!GetTarget() || GetTarget() != other)
SetTarget(other);
mlog(COMBAT__ATTACKS, "Attacking %s with hand %d %s", other?other->GetCleanName():"(nullptr)", Hand, FromRiposte?"(this is a riposte)":"");
Log.Out(Logs::Detail, Logs::Combat, "Attacking %s with hand %d %s", other?other->GetCleanName():"(nullptr)", Hand, FromRiposte?"(this is a riposte)":"");
if ((IsCasting() && (GetClass() != BARD) && !IsFromSpell) ||
other == nullptr ||
@@ -6036,13 +6058,13 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b
entity_list.MessageClose(this, 1, 200, 10, "%s says, '%s is not a legal target master.'", this->GetCleanName(), this->GetTarget()->GetCleanName());
if(other) {
RemoveFromHateList(other);
mlog(COMBAT__ATTACKS, "I am not allowed to attack %s", other->GetCleanName());
Log.Out(Logs::Detail, Logs::Combat, "I am not allowed to attack %s", other->GetCleanName());
}
return false;
}
if(DivineAura()) {//cant attack while invulnerable
mlog(COMBAT__ATTACKS, "Attack canceled, Divine Aura is in effect.");
Log.Out(Logs::Detail, Logs::Combat, "Attack canceled, Divine Aura is in effect.");
return false;
}
@@ -6068,19 +6090,19 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b
if(weapon != nullptr) {
if (!weapon->IsWeapon()) {
mlog(COMBAT__ATTACKS, "Attack canceled, Item %s (%d) is not a weapon.", weapon->GetItem()->Name, weapon->GetID());
Log.Out(Logs::Detail, Logs::Combat, "Attack canceled, Item %s (%d) is not a weapon.", weapon->GetItem()->Name, weapon->GetID());
return(false);
}
mlog(COMBAT__ATTACKS, "Attacking with weapon: %s (%d)", weapon->GetItem()->Name, weapon->GetID());
Log.Out(Logs::Detail, Logs::Combat, "Attacking with weapon: %s (%d)", weapon->GetItem()->Name, weapon->GetID());
} else {
mlog(COMBAT__ATTACKS, "Attacking without a weapon.");
Log.Out(Logs::Detail, Logs::Combat, "Attacking without a weapon.");
}
// calculate attack_skill and skillinuse depending on hand and weapon
// also send Packet to near clients
SkillUseTypes skillinuse;
AttackAnimation(skillinuse, Hand, weapon);
mlog(COMBAT__ATTACKS, "Attacking with %s in slot %d using skill %d", weapon?weapon->GetItem()->Name:"Fist", Hand, skillinuse);
Log.Out(Logs::Detail, Logs::Combat, "Attacking with %s in slot %d using skill %d", weapon?weapon->GetItem()->Name:"Fist", Hand, skillinuse);
/// Now figure out damage
int damage = 0;
@@ -6098,7 +6120,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b
if(berserk && (GetClass() == BERSERKER)){
int bonus = 3 + GetLevel()/10; //unverified
weapon_damage = weapon_damage * (100+bonus) / 100;
mlog(COMBAT__DAMAGE, "Berserker damage bonus increases DMG to %d", weapon_damage);
Log.Out(Logs::Detail, Logs::Combat, "Berserker damage bonus increases DMG to %d", weapon_damage);
}
//try a finishing blow.. if successful end the attack
@@ -6163,7 +6185,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b
else
damage = zone->random.Int(min_hit, max_hit);
mlog(COMBAT__DAMAGE, "Damage calculated to %d (min %d, max %d, str %d, skill %d, DMG %d, lv %d)",
Log.Out(Logs::Detail, Logs::Combat, "Damage calculated to %d (min %d, max %d, str %d, skill %d, DMG %d, lv %d)",
damage, min_hit, max_hit, GetSTR(), GetSkill(skillinuse), weapon_damage, GetLevel());
if(opts) {
@@ -6175,7 +6197,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b
//check to see if we hit..
if(!other->CheckHitChance(other, skillinuse, Hand)) {
mlog(COMBAT__ATTACKS, "Attack missed. Damage set to 0.");
Log.Out(Logs::Detail, Logs::Combat, "Attack missed. Damage set to 0.");
damage = 0;
other->AddToHateList(this, 0);
} else { //we hit, try to avoid it
@@ -6185,13 +6207,13 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b
ApplyMeleeDamageBonus(skillinuse, damage);
damage += (itembonuses.HeroicSTR / 10) + (damage * other->GetSkillDmgTaken(skillinuse) / 100) + GetSkillDmgAmt(skillinuse);
TryCriticalHit(other, skillinuse, damage, opts);
mlog(COMBAT__HITS, "Generating hate %d towards %s", hate, GetCleanName());
Log.Out(Logs::Detail, Logs::Combat, "Generating hate %d towards %s", hate, GetCleanName());
// now add done damage to the hate list
//other->AddToHateList(this, hate);
}
else
other->AddToHateList(this, 0);
mlog(COMBAT__DAMAGE, "Final damage after all reductions: %d", damage);
Log.Out(Logs::Detail, Logs::Combat, "Final damage after all reductions: %d", damage);
}
//riposte
@@ -6249,23 +6271,23 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b
MeleeLifeTap(damage);
if (damage > 0)
CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess);
CheckNumHitsRemaining(NumHit::OutgoingHitSuccess);
//break invis when you attack
if(invisible) {
mlog(COMBAT__ATTACKS, "Removing invisibility due to melee attack.");
Log.Out(Logs::Detail, Logs::Combat, "Removing invisibility due to melee attack.");
BuffFadeByEffect(SE_Invisibility);
BuffFadeByEffect(SE_Invisibility2);
invisible = false;
}
if(invisible_undead) {
mlog(COMBAT__ATTACKS, "Removing invisibility vs. undead due to melee attack.");
Log.Out(Logs::Detail, Logs::Combat, "Removing invisibility vs. undead due to melee attack.");
BuffFadeByEffect(SE_InvisVsUndead);
BuffFadeByEffect(SE_InvisVsUndead2);
invisible_undead = false;
}
if(invisible_animals){
mlog(COMBAT__ATTACKS, "Removing invisibility vs. animals due to melee attack.");
Log.Out(Logs::Detail, Logs::Combat, "Removing invisibility vs. animals due to melee attack.");
BuffFadeByEffect(SE_InvisVsAnimals);
invisible_animals = false;
}
@@ -7028,7 +7050,7 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
return 0;
break;
default:
LogFile->write(EQEMuLog::Normal, "CalcFocusEffect: unknown limit spelltype %d", focus_spell.base[i]);
Log.Out(Logs::General, Logs::Normal, "CalcFocusEffect: unknown limit spelltype %d", focus_spell.base[i]);
}
break;
@@ -7332,12 +7354,10 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
break;
}
#if EQDEBUG >= 6
//this spits up a lot of garbage when calculating spell focuses
//since they have all kinds of extra effects on them.
default:
LogFile->write(EQEMuLog::Normal, "CalcFocusEffect: unknown effectid %d", focus_spell.effectid[i]);
#endif
Log.Out(Logs::General, Logs::Spells, "CalcFocusEffect: unknown effectid %d", focus_spell.effectid[i]);
}
}
//Check for spell skill limits.
@@ -7380,13 +7400,13 @@ float Bot::GetProcChances(float ProcBonus, uint16 hand) {
ProcChance += ProcChance*ProcBonus / 100.0f;
}
mlog(COMBAT__PROCS, "Proc chance %.2f (%.2f from bonuses)", ProcChance, ProcBonus);
Log.Out(Logs::Detail, Logs::Combat, "Proc chance %.2f (%.2f from bonuses)", ProcChance, ProcBonus);
return ProcChance;
}
bool Bot::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte)
{
/* solar: called when a mob is attacked, does the checks to see if it's a hit
/* called when a mob is attacked, does the checks to see if it's a hit
* and does other mitigation checks. 'this' is the mob being attacked.
*
* special return values:
@@ -7416,7 +7436,7 @@ bool Bot::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte)
/////////////////////////////////////////////////////////
if (IsEnraged() && !other->BehindMob(this, other->GetX(), other->GetY())) {
damage = -3;
mlog(COMBAT__DAMAGE, "I am enraged, riposting frontal attack.");
Log.Out(Logs::Detail, Logs::Combat, "I am enraged, riposting frontal attack.");
}
/////////////////////////////////////////////////////////
@@ -7558,7 +7578,7 @@ bool Bot::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte)
}
}
mlog(COMBAT__DAMAGE, "Final damage after all avoidances: %d", damage);
Log.Out(Logs::Detail, Logs::Combat, "Final damage after all avoidances: %d", damage);
if (damage < 0)
return true;
@@ -7611,14 +7631,14 @@ bool Bot::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse)
uint16 levelreq = aabonuses.FinishingBlowLvl[0];
if(defender->GetLevel() <= levelreq && (chance >= zone->random.Int(0, 1000))){
mlog(COMBAT__ATTACKS, "Landed a finishing blow: levelreq at %d, other level %d", levelreq , defender->GetLevel());
Log.Out(Logs::Detail, Logs::Combat, "Landed a finishing blow: levelreq at %d, other level %d", levelreq , defender->GetLevel());
entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FINISHING_BLOW, GetName());
defender->Damage(this, damage, SPELL_UNKNOWN, skillinuse);
return true;
}
else
{
mlog(COMBAT__ATTACKS, "FAILED a finishing blow: levelreq at %d, other level %d", levelreq , defender->GetLevel());
Log.Out(Logs::Detail, Logs::Combat, "FAILED a finishing blow: levelreq at %d, other level %d", levelreq , defender->GetLevel());
return false;
}
}
@@ -7626,7 +7646,7 @@ bool Bot::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse)
}
void Bot::DoRiposte(Mob* defender) {
mlog(COMBAT__ATTACKS, "Preforming a riposte");
Log.Out(Logs::Detail, Logs::Combat, "Preforming a riposte");
if (!defender)
return;
@@ -7639,7 +7659,7 @@ void Bot::DoRiposte(Mob* defender) {
defender->GetItemBonuses().GiveDoubleRiposte[0];
if(DoubleRipChance && (DoubleRipChance >= zone->random.Int(0, 100))) {
mlog(COMBAT__ATTACKS, "Preforming a double riposte (%d percent chance)", DoubleRipChance);
Log.Out(Logs::Detail, Logs::Combat, "Preforming a double riposte (%d percent chance)", DoubleRipChance);
defender->Attack(this, MainPrimary, true);
}
@@ -7707,7 +7727,7 @@ void Bot::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage,
if (HasDied()) return;
if (max_damage > 0)
CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess);
CheckNumHitsRemaining(NumHit::OutgoingHitSuccess);
//[AA Dragon Punch] value[0] = 100 for 25%, chance value[1] = skill
if(aabonuses.SpecialAttackKBProc[0] && aabonuses.SpecialAttackKBProc[1] == skill){
@@ -7761,7 +7781,7 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) {
if (bIsBehind || bCanFrontalBS){ // Bot is behind other OR can do Frontal Backstab
// solar - chance to assassinate
// chance to assassinate
int chance = 10 + (GetDEX()/10) + (itembonuses.HeroicDEX/10); //18.5% chance at 85 dex 40% chance at 300 dex
if(
level >= 60 && // bot is 60 or higher
@@ -8209,7 +8229,7 @@ bool Bot::TryHeadShot(Mob* defender, SkillUseTypes skillInUse) {
float AttackerChance = 0.20f + ((float)(rangerLevel - 51) * 0.005f);
float DefenderChance = (float)zone->random.Real(0.00f, 1.00f);
if(AttackerChance > DefenderChance) {
mlog(COMBAT__ATTACKS, "Landed a headshot: Attacker chance was %f and Defender chance was %f.", AttackerChance, DefenderChance);
Log.Out(Logs::Detail, Logs::Combat, "Landed a headshot: Attacker chance was %f and Defender chance was %f.", AttackerChance, DefenderChance);
// WildcardX: At the time I wrote this, there wasnt a string id for something like HEADSHOT_BLOW
//entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FINISHING_BLOW, GetName());
entity_list.MessageClose(this, false, 200, MT_CritMelee, "%s has scored a leathal HEADSHOT!", GetName());
@@ -8217,7 +8237,7 @@ bool Bot::TryHeadShot(Mob* defender, SkillUseTypes skillInUse) {
Result = true;
}
else {
mlog(COMBAT__ATTACKS, "FAILED a headshot: Attacker chance was %f and Defender chance was %f.", AttackerChance, DefenderChance);
Log.Out(Logs::Detail, Logs::Combat, "FAILED a headshot: Attacker chance was %f and Defender chance was %f.", AttackerChance, DefenderChance);
}
}
}
@@ -8386,6 +8406,8 @@ void Bot::EquipBot(std::string* errorMessage) {
return;
}
}
UpdateEquipLightValue();
}
//// This method is meant to be called by zone or client methods to clean up objects when a client camps, goes LD, zones out or something like that.
@@ -8420,7 +8442,7 @@ void Bot::ProcessBotOwnerRefDelete(Mob* botOwner) {
std::list<Bot*> BotList = entity_list.GetBotsByBotOwnerCharacterID(botOwner->CastToClient()->CharacterID());
if(!BotList.empty()) {
for(std::list<Bot*>::iterator botListItr = BotList.begin(); botListItr != BotList.end(); botListItr++) {
for(std::list<Bot*>::iterator botListItr = BotList.begin(); botListItr != BotList.end(); ++botListItr) {
Bot* tempBot = *botListItr;
if(tempBot) {
@@ -8443,11 +8465,11 @@ void Bot::ProcessGuildInvite(Client* guildOfficer, Bot* botToGuild) {
return;
}
// mlog(GUILDS__ACTIONS, "Inviting %s (%d) into guild %s (%d)", botToGuild->GetName(), botToGuild->GetBotID(), guild_mgr.GetGuildName(client->GuildID()), client->GuildID());
// Log.Out(Logs::Detail, Logs::Guilds, "Inviting %s (%d) into guild %s (%d)", botToGuild->GetName(), botToGuild->GetBotID(), guild_mgr.GetGuildName(client->GuildID()), client->GuildID());
SetBotGuildMembership(botToGuild->GetBotID(), guildOfficer->GuildID(), GUILD_MEMBER);
//_log(GUILDS__REFRESH, "Sending char refresh for BOT %s from guild %d to world", botToGuild->GetName(), guildOfficer->GuildID();
//Log.LogDebugType(Logs::Detail, Logs::Guilds, "Sending char refresh for BOT %s from guild %d to world", botToGuild->GetName(), guildOfficer->GuildID();
ServerPacket* pack = new ServerPacket(ServerOP_GuildCharRefresh, sizeof(ServerGuildCharRefresh_Struct));
ServerGuildCharRefresh_Struct *s = (ServerGuildCharRefresh_Struct *) pack->pBuffer;
@@ -8550,7 +8572,7 @@ int32 Bot::CalcMaxMana() {
}
default:
{
LogFile->write(EQEMuLog::Debug, "Invalid Class '%c' in CalcMaxMana", GetCasterClass());
Log.Out(Logs::General, Logs::None, "Invalid Class '%c' in CalcMaxMana", GetCasterClass());
max_mana = 0;
break;
}
@@ -9076,9 +9098,9 @@ void Bot::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste
bool Bot::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int32 cast_time, int32 mana_cost, uint32* oSpellWillFinish, uint32 item_slot, int16 *resist_adjust) {
bool Result = false;
if(zone && !zone->IsSpellBlocked(spell_id, GetX(), GetY(), GetZ())) {
if(zone && !zone->IsSpellBlocked(spell_id, glm::vec3(GetPosition()))) {
mlog(SPELLS__CASTING, "CastSpell called for spell %s (%d) on entity %d, slot %d, time %d, mana %d, from item slot %d",
Log.Out(Logs::Detail, Logs::Spells, "CastSpell called for spell %s (%d) on entity %d, slot %d, time %d, mana %d, from item slot %d",
spells[spell_id].name, spell_id, target_id, slot, cast_time, mana_cost, (item_slot==0xFFFFFFFF)?999:item_slot);
if(casting_spell_id == spell_id)
@@ -9086,7 +9108,7 @@ bool Bot::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int32 cast_t
if(GetClass() != BARD) {
if(!IsValidSpell(spell_id) || casting_spell_id || delaytimer || spellend_timer.Enabled() || IsStunned() || IsFeared() || IsMezzed() || (IsSilenced() && !IsDiscipline(spell_id)) || (IsAmnesiad() && IsDiscipline(spell_id))) {
mlog(SPELLS__CASTING_ERR, "Spell casting canceled: not able to cast now. Valid? %d, casting %d, waiting? %d, spellend? %d, stunned? %d, feared? %d, mezed? %d, silenced? %d",
Log.Out(Logs::Detail, Logs::Spells, "Spell casting canceled: not able to cast now. Valid? %d, casting %d, waiting? %d, spellend? %d, stunned? %d, feared? %d, mezed? %d, silenced? %d",
IsValidSpell(spell_id), casting_spell_id, delaytimer, spellend_timer.Enabled(), IsStunned(), IsFeared(), IsMezzed(), IsSilenced() );
if(IsSilenced() && !IsDiscipline(spell_id))
Message_StringID(13, SILENCED_STRING);
@@ -9107,7 +9129,7 @@ bool Bot::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int32 cast_t
//cannot cast under deivne aura
if(DivineAura()) {
mlog(SPELLS__CASTING_ERR, "Spell casting canceled: cannot cast while Divine Aura is in effect.");
Log.Out(Logs::Detail, Logs::Spells, "Spell casting canceled: cannot cast while Divine Aura is in effect.");
InterruptSpell(173, 0x121, false);
return(false);
}
@@ -9121,7 +9143,7 @@ bool Bot::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int32 cast_t
InterruptSpell(fizzle_msg, 0x121, spell_id);
uint32 use_mana = ((spells[spell_id].mana) / 4);
mlog(SPELLS__CASTING_ERR, "Spell casting canceled: fizzled. %d mana has been consumed", use_mana);
Log.Out(Logs::Detail, Logs::Spells, "Spell casting canceled: fizzled. %d mana has been consumed", use_mana);
// fizzle 1/4 the mana away
SetMana(GetMana() - use_mana);
@@ -9129,7 +9151,7 @@ bool Bot::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int32 cast_t
}
if (HasActiveSong()) {
mlog(SPELLS__BARDS, "Casting a new spell/song while singing a song. Killing old song %d.", bardsong);
Log.Out(Logs::Detail, Logs::Spells, "Casting a new spell/song while singing a song. Killing old song %d.", bardsong);
//Note: this does NOT tell the client
//_StopSong();
bardsong = 0;
@@ -9258,7 +9280,7 @@ bool Bot::IsImmuneToSpell(uint16 spell_id, Mob *caster) {
if(caster->IsBot()) {
if(spells[spell_id].targettype == ST_Undead) {
if((GetBodyType() != BT_SummonedUndead) && (GetBodyType() != BT_Undead) && (GetBodyType() != BT_Vampire)) {
mlog(SPELLS__RESISTS, "Bot's target is not an undead.");
Log.Out(Logs::Detail, Logs::Spells, "Bot's target is not an undead.");
return true;
}
}
@@ -9268,13 +9290,13 @@ bool Bot::IsImmuneToSpell(uint16 spell_id, Mob *caster) {
&& (GetBodyType() != BT_Summoned2)
&& (GetBodyType() != BT_Summoned3)
) {
mlog(SPELLS__RESISTS, "Bot's target is not a summoned creature.");
Log.Out(Logs::Detail, Logs::Spells, "Bot's target is not a summoned creature.");
return true;
}
}
}
mlog(SPELLS__RESISTS, "No bot immunities to spell %d found.", spell_id);
Log.Out(Logs::Detail, Logs::Spells, "No bot immunities to spell %d found.", spell_id);
}
}
@@ -9332,7 +9354,7 @@ int32 Bot::GenerateBaseManaPoints()
{
case 'I':
WisInt = INT;
if(GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= EQClientSoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) {
if(GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) {
if(WisInt > 100) {
ConvertedWisInt = (((WisInt - 100) * 5 / 2) + 100);
if(WisInt > 201) {
@@ -9375,7 +9397,7 @@ int32 Bot::GenerateBaseManaPoints()
case 'W':
WisInt = WIS;
if(GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= EQClientSoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) {
if(GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) {
if(WisInt > 100) {
ConvertedWisInt = (((WisInt - 100) * 5 / 2) + 100);
if(WisInt > 201) {
@@ -9614,7 +9636,7 @@ int32 Bot::GetMaxStat() {
if (level < 61) {
base = 255;
}
else if (GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= EQClientSoF) {
else if (GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= ClientVersion::SoF) {
base = 255 + 5 * (level - 60);
}
else if (level < 71) {
@@ -10234,7 +10256,7 @@ int32 Bot::CalcBaseEndurance()
int32 sta_end = 0;
int Stats = 0;
if(GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= EQClientSoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) {
if(GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) {
int HeroicStats = 0;
Stats = ((GetSTR() + GetSTA() + GetDEX() + GetAGI()) / 4);
@@ -10387,7 +10409,7 @@ bool Bot::IsArcheryRange(Mob *target) {
range *= range;
float targetDistance = DistNoRootNoZ(*target);
float targetDistance = DistanceSquaredNoZ(m_Position, target->GetPosition());
float minRuleDistance = RuleI(Combat, MinRangedAttackDist) * RuleI(Combat, MinRangedAttackDist);
@@ -10411,7 +10433,7 @@ bool Bot::IsBotCasterCombatRange(Mob *target) {
// half the max so the bot doesn't always stop at max range to allow combat movement
range *= .5;
float targetDistance = DistNoRootNoZ(*target);
float targetDistance = DistanceSquaredNoZ(m_Position, target->GetPosition());
if(targetDistance > range)
result = false;
@@ -10663,12 +10685,12 @@ void Bot::BotGroupSummon(Group* group, Client* client) {
if(botMember->GetBotOwnerCharacterID() == client->CharacterID()) {
botMember->SetTarget(botMember->GetBotOwner());
botMember->WipeHateList();
botMember->Warp(botMember->GetBotOwner()->GetX(), botMember->GetBotOwner()->GetY(), botMember->GetBotOwner()->GetZ());
botMember->Warp(glm::vec3(botMember->GetBotOwner()->GetPosition()));
if(botMember->HasPet() && botMember->GetPet()) {
botMember->GetPet()->SetTarget(botMember);
botMember->GetPet()->WipeHateList();
botMember->GetPet()->Warp(botMember->GetBotOwner()->GetX(), botMember->GetBotOwner()->GetY(), botMember->GetBotOwner()->GetZ());
botMember->GetPet()->Warp(glm::vec3(botMember->GetBotOwner()->GetPosition()));
}
}
}
@@ -11677,7 +11699,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) {
else
{
b->SetTarget(c->CastToMob());
b->Warp(c->GetX(), c->GetY(), c->GetZ());
b->Warp(glm::vec3(c->GetPosition()));
}
}
}
@@ -11707,7 +11729,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) {
std::string item_link;
Client::TextLink linker;
linker.SetLinkType(linker.linkItemInst);
linker.SetClientVersion(c->GetClientVersion());
for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) {
if((i == MainSecondary) && is2Hweapon) {
@@ -15457,7 +15478,7 @@ bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, fl
// according to Rogean, Live NPCs will just cast through walls/floors, no problem..
//
// This check was put in to address an idle-mob CPU issue
_log(AI__ERROR, "Error: detrimental spells requested from AICheckCloseBeneficialSpells!!");
Log.Out(Logs::General, Logs::Error, "Error: detrimental spells requested from AICheckCloseBeneficialSpells!!");
return(false);
}
@@ -15742,47 +15763,38 @@ std::list<Bot*> EntityList::GetBotsByBotOwnerCharacterID(uint32 botOwnerCharacte
void EntityList::BotPickLock(Bot* rogue)
{
auto it = door_list.begin();
for (auto it = door_list.begin(); it != door_list.end(); ++it) {
Doors *cdoor = it->second;
if(cdoor && !cdoor->IsDoorOpen()) {
float zdiff = rogue->GetZ() - cdoor->GetZ();
if(zdiff < 0)
zdiff = 0 - zdiff;
float curdist = 0;
float tmp = rogue->GetX() - cdoor->GetX();
curdist += (tmp * tmp);
tmp = rogue->GetY() - cdoor->GetY();
curdist += (tmp * tmp);
if((zdiff < 10) && (curdist <= 130)) {
// All rogue items with lock pick bonuses are hands or primary
const ItemInst* item1 = rogue->GetBotItem(MainHands);
const ItemInst* item2 = rogue->GetBotItem(MainPrimary);
if(!cdoor || cdoor->IsDoorOpen())
continue;
float bonus1 = 0.0f;
float bonus2 = 0.0f;
float skill = rogue->GetSkill(SkillPickLock);
auto diff = rogue->GetPosition() - cdoor->GetPosition();
if(item1) { // Hand slot item
if(item1->GetItem()->SkillModType == SkillPickLock) {
bonus1 = skill * (((float)item1->GetItem()->SkillModValue) / 100.0f);
}
}
float curdist = diff.x * diff.x + diff.y * diff.y;
if(item2) { // Primary slot item
if(item2->GetItem()->SkillModType == SkillPickLock) {
bonus2 = skill * (((float)item2->GetItem()->SkillModValue) / 100.0f);
}
}
if((diff.z * diff.z >= 10) || (curdist > 130))
continue;
if((skill+bonus1+bonus2) >= cdoor->GetLockpick()) {
cdoor->ForceOpen(rogue);
}
else {
rogue->Say("I am not skilled enough for this lock.");
}
}
}
// All rogue items with lock pick bonuses are hands or primary
const ItemInst* item1 = rogue->GetBotItem(MainHands);
const ItemInst* item2 = rogue->GetBotItem(MainPrimary);
float bonus1 = 0.0f;
float bonus2 = 0.0f;
float skill = rogue->GetSkill(SkillPickLock);
if(item1) // Hand slot item
if(item1->GetItem()->SkillModType == SkillPickLock)
bonus1 = skill * (((float)item1->GetItem()->SkillModValue) / 100.0f);
if(item2) // Primary slot item
if(item2->GetItem()->SkillModType == SkillPickLock)
bonus2 = skill * (((float)item2->GetItem()->SkillModValue) / 100.0f);
if((skill+bonus1+bonus2) >= cdoor->GetLockpick())
cdoor->ForceOpen(rogue);
else
rogue->Say("I am not skilled enough for this lock.");
}
}
@@ -15820,7 +15832,7 @@ void EntityList::ShowSpawnWindow(Client* client, int Distance, bool NamedOnly) {
for (auto it = mob_list.begin(); it != mob_list.end(); ++it) {
curMob = it->second;
if (curMob && curMob->DistNoZ(*client)<=Distance) {
if (curMob && DistanceNoZ(curMob->GetPosition(), client->GetPosition()) <= Distance) {
if(curMob->IsTrackable()) {
Mob* cur_entity = curMob;
int Extras = (cur_entity->IsBot() || cur_entity->IsPet() || cur_entity->IsFamiliar() || cur_entity->IsClient());
@@ -16169,11 +16181,9 @@ bool Bot::HasOrMayGetAggro() {
void Bot::SetHasBeenSummoned(bool wasSummoned) {
_hasBeenSummoned = wasSummoned;
if(!wasSummoned) {
_preSummonX = 0;
_preSummonY = 0;
_preSummonZ = 0;
}
if(!wasSummoned)
m_PreSummonLocation = glm::vec3();
}
void Bot::SetDefaultBotStance() {
+5 -10
View File
@@ -12,7 +12,7 @@
#include "zonedb.h"
#include "string_ids.h"
#include "../common/misc_functions.h"
#include "../common/debug.h"
#include "../common/global_define.h"
#include "guild_mgr.h"
#include "worldserver.h"
@@ -332,6 +332,7 @@ public:
void EquipBot(std::string* errorMessage);
bool CheckLoreConflict(const Item_Struct* item);
uint32 GetEquipmentColor(uint8 material_slot) const;
virtual void UpdateEquipLightValue() { equip_light = m_inv.FindHighestLightValue(); }
// Static Class Methods
static void SaveBotGroup(Group* botGroup, std::string botGroupName, std::string* errorMessage);
@@ -448,9 +449,7 @@ public:
uint32 GetAA(uint32 aa_id);
void ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon);
bool GetHasBeenSummoned() { return _hasBeenSummoned; }
float GetPreSummonX() { return _preSummonX; }
float GetPreSummonY() { return _preSummonY; }
float GetPreSummonZ() { return _preSummonZ; }
const glm::vec3 GetPreSummonLocation() const { return m_PreSummonLocation; }
bool GetGroupMessagesOn() { return _groupMessagesOn; }
bool GetInHealRotation() { return _isInHealRotation; }
bool GetHealRotationActive() { return (GetInHealRotation() && _isHealRotationActive); }
@@ -535,9 +534,7 @@ public:
void SetSpellRecastTimer(int timer_index, int32 recast_delay);
void SetDisciplineRecastTimer(int timer_index, int32 recast_delay);
void SetHasBeenSummoned(bool s);
void SetPreSummonX(float x) { _preSummonX = x; }
void SetPreSummonY(float y) { _preSummonY = y; }
void SetPreSummonZ(float z) { _preSummonZ = z; }
void SetPreSummonLocation(const glm::vec3& location) { m_PreSummonLocation = location; }
void SetGroupMessagesOn(bool groupMessagesOn) { _groupMessagesOn = groupMessagesOn; }
void SetInHealRotation( bool inRotation ) { _isInHealRotation = inRotation; }
void SetHealRotationActive( bool isActive ) { _isHealRotationActive = isActive; }
@@ -604,9 +601,7 @@ private:
int32 end_regen;
uint32 timers[MaxTimer];
bool _hasBeenSummoned;
float _preSummonX;
float _preSummonY;
float _preSummonZ;
glm::vec3 m_PreSummonLocation;
uint8 _spellCastingChances[MaxStances][MaxSpellTypes];
bool _groupMessagesOn;
bool _isInHealRotation;
+4 -4
View File
@@ -898,7 +898,7 @@ bool Bot::AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgain
if (AIspells[i].type & SpellType_Escape) {
dist2 = 0;
} else
dist2 = DistNoRoot(*tar);
dist2 = DistanceSquared(m_Position, tar->GetPosition());
if (((((spells[AIspells[i].spellid].targettype==ST_GroupTeleport && AIspells[i].type==2)
|| spells[AIspells[i].spellid].targettype==ST_AECaster
@@ -950,7 +950,7 @@ bool Bot::AI_PursueCastCheck() {
AIautocastspell_timer->Disable(); //prevent the timer from going off AGAIN while we are casting.
mlog(AI__SPELLS, "Bot Engaged (pursuing) autocast check triggered. Trying to cast offensive spells.");
Log.Out(Logs::Detail, Logs::AI, "Bot Engaged (pursuing) autocast check triggered. Trying to cast offensive spells.");
if(!AICastSpell(GetTarget(), 100, SpellType_Snare)) {
if(!AICastSpell(GetTarget(), 100, SpellType_Lifetap)) {
@@ -1055,7 +1055,7 @@ bool Bot::AI_EngagedCastCheck() {
BotStanceType botStance = GetBotStance();
bool mayGetAggro = HasOrMayGetAggro();
mlog(AI__SPELLS, "Engaged autocast check triggered (BOTS). Trying to cast healing spells then maybe offensive spells.");
Log.Out(Logs::Detail, Logs::AI, "Engaged autocast check triggered (BOTS). Trying to cast healing spells then maybe offensive spells.");
if(botClass == CLERIC) {
if(!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) {
@@ -1755,7 +1755,7 @@ Mob* Bot::GetFirstIncomingMobToMez(Bot* botCaster, BotSpell botSpell) {
for(std::list<NPC*>::iterator itr = npc_list.begin(); itr != npc_list.end(); ++itr) {
NPC* npc = *itr;
if(npc->DistNoRootNoZ(*botCaster) <= botCaster->GetActSpellRange(botSpell.SpellId, spells[botSpell.SpellId].range)) {
if(DistanceSquaredNoZ(npc->GetPosition(), botCaster->GetPosition()) <= botCaster->GetActSpellRange(botSpell.SpellId, spells[botSpell.SpellId].range)) {
if(!npc->IsMezzed()) {
if(botCaster->HasGroup()) {
Group* g = botCaster->GetGroup();
+530 -521
View File
File diff suppressed because it is too large Load Diff
+35 -32
View File
@@ -64,6 +64,7 @@ struct Item_Struct;
#include <float.h>
#include <set>
#include <algorithm>
#include <memory>
#define CLIENT_TIMEOUT 90000
@@ -201,7 +202,7 @@ struct ClientReward
class ClientFactory {
public:
Client *MakeClient(EQStream* ieqs);
Client *MakeClient(std::shared_ptr<EQStream> ieqs);
};
class Client : public Mob
@@ -398,10 +399,10 @@ public:
inline const char* GetLastName() const { return lastname; }
inline float ProximityX() const { return(proximity_x); }
inline float ProximityY() const { return(proximity_y); }
inline float ProximityZ() const { return(proximity_z); }
inline void ClearAllProximities() { entity_list.ProcessMove(this, FLT_MAX, FLT_MAX, FLT_MAX); proximity_x = FLT_MAX; proximity_y = FLT_MAX; proximity_z = FLT_MAX; }
inline float ProximityX() const { return m_Proximity.x; }
inline float ProximityY() const { return m_Proximity.y; }
inline float ProximityZ() const { return m_Proximity.z; }
inline void ClearAllProximities() { entity_list.ProcessMove(this, glm::vec3(FLT_MAX, FLT_MAX, FLT_MAX)); m_Proximity = glm::vec3(FLT_MAX,FLT_MAX,FLT_MAX); }
/*
Begin client modifiers
@@ -428,6 +429,7 @@ public:
inline virtual int32 GetPR() const { return PR; }
inline virtual int32 GetCR() const { return CR; }
inline virtual int32 GetCorrup() const { return Corrup; }
inline virtual int32 GetPhR() const { return PhR; }
int32 GetMaxStat() const;
int32 GetMaxResist() const;
@@ -452,6 +454,7 @@ public:
inline uint8 GetBaseAGI() const { return m_pp.AGI; }
inline uint8 GetBaseWIS() const { return m_pp.WIS; }
inline uint8 GetBaseCorrup() const { return 15; } // Same for all
inline uint8 GetBasePhR() const { return 0; } // Guessing at 0 as base
inline virtual int32 GetHeroicSTR() const { return itembonuses.HeroicSTR; }
inline virtual int32 GetHeroicSTA() const { return itembonuses.HeroicSTA; }
@@ -466,6 +469,7 @@ public:
inline virtual int32 GetHeroicPR() const { return itembonuses.HeroicPR; }
inline virtual int32 GetHeroicCR() const { return itembonuses.HeroicCR; }
inline virtual int32 GetHeroicCorrup() const { return itembonuses.HeroicCorrup; }
inline virtual int32 GetHeroicPhR() const { return 0; } // Heroic PhR not implemented yet
// Mod2
inline virtual int32 GetShielding() const { return itembonuses.MeleeMitigation; }
inline virtual int32 GetSpellShield() const { return itembonuses.SpellShield; }
@@ -577,7 +581,7 @@ public:
void GoToBind(uint8 bindnum = 0);
void GoToSafeCoords(uint16 zone_id, uint16 instance_id);
void Gate();
void SetBindPoint(int to_zone = -1, int to_instance = 0, float new_x = 0.0f, float new_y = 0.0f, float new_z = 0.0f);
void SetBindPoint(int to_zone = -1, int to_instance = 0, const glm::vec3& location = glm::vec3());
void SetStartZone(uint32 zoneid, float x = 0.0f, float y =0.0f, float z = 0.0f);
uint32 GetStartZone(void);
void MovePC(const char* zonename, float x, float y, float z, float heading, uint8 ignorerestrictions = 0, ZoneMode zm = ZoneSolicited);
@@ -603,8 +607,9 @@ public:
int32 GetCharacterFactionLevel(int32 faction_id);
int32 GetModCharacterFactionLevel(int32 faction_id);
void MerchantRejectMessage(Mob *merchant, int primaryfaction);
void SendFactionMessage(int32 tmpvalue, int32 faction_id, int32 totalvalue, uint8 temp);
void SendFactionMessage(int32 tmpvalue, int32 faction_id, int32 faction_before_hit, int32 totalvalue, uint8 temp, int32 this_faction_min, int32 this_faction_max);
void UpdatePersonalFaction(int32 char_id, int32 npc_value, int32 faction_id, int32 *current_value, int32 temp, int32 this_faction_min, int32 this_faction_max);
void SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, uint8 char_race, uint8 char_deity);
void SetFactionLevel2(uint32 char_id, int32 faction_id, uint8 char_class, uint8 char_race, uint8 char_deity, int32 value, uint8 temp);
int32 GetRawItemAC();
@@ -725,6 +730,7 @@ public:
#endif
uint32 GetEquipment(uint8 material_slot) const; // returns item id
uint32 GetEquipmentColor(uint8 material_slot) const;
virtual void UpdateEquipLightValue() { equip_light = m_inv.FindHighestLightValue(); }
inline bool AutoSplitEnabled() { return m_pp.autosplit != 0; }
@@ -832,20 +838,19 @@ public:
void SetProxyItemID(uint32 proxyItemID) { m_ProxyItemID = proxyItemID; } // mainly for saylinks..but, not limited to
void SetProxyText(const char* proxyText) { m_ProxyText = proxyText; } // overrides standard text use
void SetTaskUse() { m_TaskUse = true; }
void SetClientVersion(EQClientVersion clientVersion) { m_ClientVersion = EQLimits::ValidateClientVersion(clientVersion); }
std::string GenerateLink();
bool LinkError() { return m_Error; }
const char* GetLink(); // contains full format: '/12x' '<LinkBody>' '<LinkText>' '/12x'
const char* GetLinkBody(); // contains format: '<LinkBody>'
const char* GetLinkText(); // contains format: '<LinkText>'
std::string GetLinkString();
std::string GetLinkBodyString();
std::string GetLinkTextString();
std::string GetLink() { return m_Link; } // contains full string format: '/12x' '<LinkBody>' '<LinkText>' '/12x'
std::string GetLinkBody() { return m_LinkBody; } // contains string format: '<LinkBody>'
std::string GetLinkText() { return m_LinkText; } // contains string format: '<LinkText>'
void Reset();
static bool DegenerateLinkBody(TextLinkBody_Struct& textLinkBodyStruct, const std::string& textLinkBody);
static bool GenerateLinkBody(std::string& textLinkBody, const TextLinkBody_Struct& textLinkBodyStruct);
private:
void generate_body();
void generate_text();
@@ -857,10 +862,10 @@ public:
uint32 m_ProxyItemID;
const char* m_ProxyText;
bool m_TaskUse;
TextLinkBody_Struct m_LinkBodyStruct;
std::string m_Link;
std::string m_LinkBody;
std::string m_LinkText;
EQClientVersion m_ClientVersion;
bool m_Error;
};
@@ -912,8 +917,6 @@ public:
void SendZoneFlagInfo(Client *to) const;
void LoadZoneFlags();
void ChangeSQLLog(const char *file);
void LogSQL(const char *fmt, ...);
bool CanFish();
void GoFish();
void ForageItem(bool guarantee = false);
@@ -1017,8 +1020,9 @@ public:
inline int ActiveTasksInSet(int TaskSet) { return (taskstate ? taskstate->ActiveTasksInSet(TaskSet) :0); }
inline int CompletedTasksInSet(int TaskSet) { return (taskstate ? taskstate->CompletedTasksInSet(TaskSet) :0); }
inline const EQClientVersion GetClientVersion() const { return ClientVersion; }
inline const ClientVersion GetClientVersion() const { return m_ClientVersion; }
inline const uint32 GetClientVersionBit() const { return ClientVersionBit; }
inline void SetClientVersion(ClientVersion in) { m_ClientVersion = in; }
/** Adventure Stuff **/
void SendAdventureError(const char *error);
@@ -1076,7 +1080,7 @@ public:
void DoItemEnterZone();
bool DoItemEnterZone(uint32 slot_x, uint32 slot_y); // behavior change: 'slot_y' is now [RANGE]_END and not [RANGE]_END + 1
void SummonAndRezzAllCorpses();
void SummonAllCorpses(float dest_x, float dest_y, float dest_z, float dest_heading);
void SummonAllCorpses(const glm::vec4& position);
void DepopAllCorpses();
void DepopPlayerCorpse(uint32 dbid);
void BuryPlayerCorpses();
@@ -1095,7 +1099,7 @@ public:
QGlobalCache *GetQGlobals() { return qGlobals; }
QGlobalCache *CreateQGlobals() { qGlobals = new QGlobalCache(); return qGlobals; }
void GuildBankAck();
void GuildBankDepositAck(bool Fail);
void GuildBankDepositAck(bool Fail, int8 action);
inline bool IsGuildBanker() { return GuildBanker; }
void ClearGuildBank();
void SendGroupCreatePacket();
@@ -1135,7 +1139,7 @@ public:
void HandleLFGuildResponse(ServerPacket *pack);
void SendLFGuildStatus();
void SendGuildLFGuildStatus();
inline bool XTargettingAvailable() const { return ((ClientVersionBit & BIT_UnderfootAndLater) && RuleB(Character, EnableXTargetting)); }
inline bool XTargettingAvailable() const { return ((ClientVersionBit & BIT_UFAndLater) && RuleB(Character, EnableXTargetting)); }
inline uint8 GetMaxXTargets() const { return MaxXTargets; }
void SetMaxXTargets(uint8 NewMax);
bool IsXTarget(const Mob *m) const;
@@ -1245,6 +1249,10 @@ public:
bool InterrogateInventory(Client* requester, bool log, bool silent, bool allowtrip, bool& error, bool autolog = true);
//Command #Tune functions
virtual int32 Tune_GetMeleeMitDmg(Mob* GM, Mob *attacker, int32 damage, int32 minhit, float mit_rating, float atk_rating);
int32 GetMeleeDamage(Mob* other, bool GetMinDamage = false);
protected:
friend class Mob;
void CalcItemBonuses(StatBonuses* newbon);
@@ -1261,11 +1269,10 @@ protected:
Mob* bind_sight_target;
Map::Vertex aa_los_me;
Map::Vertex aa_los_them;
glm::vec4 m_AutoAttackPosition;
glm::vec3 m_AutoAttackTargetLocation;
Mob *aa_los_them_mob;
bool los_status;
float aa_los_me_heading;
bool los_status_facing;
QGlobalCache *qGlobals;
@@ -1418,9 +1425,8 @@ private:
void DoZoneSuccess(ZoneChange_Struct *zc, uint16 zone_id, uint32 instance_id, float dest_x, float dest_y, float dest_z, float dest_h, int8 ignore_r);
void ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z, float heading, uint8 ignorerestrictions, ZoneMode zm);
void ProcessMovePC(uint32 zoneID, uint32 instance_id, float x, float y, float z, float heading, uint8 ignorerestrictions = 0, ZoneMode zm = ZoneSolicited);
float zonesummon_x;
float zonesummon_y;
float zonesummon_z;
glm::vec3 m_ZoneSummonLocation;
uint16 zonesummon_id;
uint8 zonesummon_ignorerestrictions;
ZoneMode zone_mode;
@@ -1459,10 +1465,7 @@ private:
Timer RespawnFromHoverTimer;
Timer merc_timer;
float proximity_x;
float proximity_y;
float proximity_z;
glm::vec3 m_Proximity;
void BulkSendInventoryItems();
@@ -1505,7 +1508,7 @@ private:
Timer *GlobalChatLimiterTimer; //60 seconds
uint32 AttemptedMessages;
EQClientVersion ClientVersion;
ClientVersion m_ClientVersion;
uint32 ClientVersionBit;
int XPRate;
-138
View File
@@ -1,138 +0,0 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2004 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/debug.h"
#include "../common/features.h"
#ifdef CLIENT_LOGS
#include "client_logs.h"
#include "client.h"
#include <stdarg.h>
ClientLogs client_logs;
char ClientLogs::_buffer[MAX_CLIENT_LOG_MESSAGE_LENGTH+1];
void ClientLogs::subscribe(EQEMuLog::LogIDs id, Client *c) {
if(id >= EQEMuLog::MaxLogID)
return;
if(c == nullptr)
return;
std::vector<Client *>::iterator cur,end;
cur = entries[id].begin();
end = entries[id].end();
for(; cur != end; ++cur) {
if(*cur == c) {
return;
}
}
entries[id].push_back(c);
}
void ClientLogs::unsubscribe(EQEMuLog::LogIDs id, Client *c) {
if(id >= EQEMuLog::MaxLogID)
return;
if(c == nullptr)
return;
std::vector<Client *>::iterator cur,end;
cur = entries[id].begin();
end = entries[id].end();
for(; cur != end; ++cur) {
if(*cur == c) {
entries[id].erase(cur);
return;
}
}
}
void ClientLogs::subscribeAll(Client *c) {
if(c == nullptr)
return;
int r;
for(r = EQEMuLog::Status; r < EQEMuLog::MaxLogID; r++) {
subscribe((EQEMuLog::LogIDs)r, c);
}
}
void ClientLogs::unsubscribeAll(Client *c) {
if(c == nullptr)
return;
int r;
for(r = EQEMuLog::Status; r < EQEMuLog::MaxLogID; r++) {
unsubscribe((EQEMuLog::LogIDs)r, c);
}
}
void ClientLogs::clear() {
int r;
for(r = EQEMuLog::Status; r < EQEMuLog::MaxLogID; r++) {
entries[r].clear();
}
}
void ClientLogs::msg(EQEMuLog::LogIDs id, const char *buf) {
if(id >= EQEMuLog::MaxLogID)
return;
std::vector<Client *>::iterator cur,end;
cur = entries[id].begin();
end = entries[id].end();
for(; cur != end; ++cur) {
if(!(*cur)->InZone())
continue;
(*cur)->Message(CLIENT_LOG_CHANNEL, buf);
}
}
void ClientLogs::EQEmuIO_buf(EQEMuLog::LogIDs id, const char *buf, uint8 size, uint32 count) {
if(size != 1)
return; //cannot print multibyte data
if(buf[0] == '\n' || buf[0] == '\r')
return; //skip new lines...
if(count > MAX_CLIENT_LOG_MESSAGE_LENGTH)
count = MAX_CLIENT_LOG_MESSAGE_LENGTH;
memcpy(_buffer, buf, count);
_buffer[count] = '\0';
client_logs.msg(id, _buffer);
}
void ClientLogs::EQEmuIO_fmt(EQEMuLog::LogIDs id, const char *fmt, va_list ap) {
if(fmt[0] == '\n' || fmt[0] == '\r')
return; //skip new lines...
vsnprintf(_buffer, MAX_CLIENT_LOG_MESSAGE_LENGTH, fmt, ap);
_buffer[MAX_CLIENT_LOG_MESSAGE_LENGTH] = '\0';
client_logs.msg(id, _buffer);
}
void ClientLogs::EQEmuIO_pva(EQEMuLog::LogIDs id, const char *prefix, const char *fmt, va_list ap) {
if(fmt[0] == '\n' || fmt[0] == '\r')
return; //skip new lines...
char *buf = _buffer;
int plen = snprintf(buf, MAX_CLIENT_LOG_MESSAGE_LENGTH, "%s", prefix);
buf += plen;
vsnprintf(buf, MAX_CLIENT_LOG_MESSAGE_LENGTH-plen, fmt, ap);
_buffer[MAX_CLIENT_LOG_MESSAGE_LENGTH] = '\0';
client_logs.msg(id, _buffer);
}
#endif //CLIENT_LOGS
-61
View File
@@ -1,61 +0,0 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2004 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 CLIENT_LOGS_H
#define CLIENT_LOGS_H
#include "../common/debug.h"
#include "../common/features.h"
#ifdef CLIENT_LOGS
#define CLIENT_LOG_CHANNEL MT_Chat10Echo
//trim messages to this length before sending to any clients
#define MAX_CLIENT_LOG_MESSAGE_LENGTH 512
#include <vector>
class Client;
class ClientLogs {
public:
static void EQEmuIO_buf(EQEMuLog::LogIDs id, const char *buf, uint8 size, uint32 count);
static void EQEmuIO_fmt(EQEMuLog::LogIDs id, const char *fmt, va_list ap);
static void EQEmuIO_pva(EQEMuLog::LogIDs id, const char *prefix, const char *fmt, va_list ap);
void subscribe(EQEMuLog::LogIDs id, Client *c);
void unsubscribe(EQEMuLog::LogIDs id, Client *c);
void subscribeAll(Client *c);
void unsubscribeAll(Client *c);
void clear(); //unsubscribes everybody
void msg(EQEMuLog::LogIDs id, const char *buf);
protected:
std::vector<Client *> entries[EQEMuLog::MaxLogID];
static char _buffer[MAX_CLIENT_LOG_MESSAGE_LENGTH+1];
};
extern ClientLogs client_logs;
#endif //CLIENT_LOGS
#endif
+1093 -937
View File
File diff suppressed because it is too large Load Diff
+582 -533
View File
File diff suppressed because it is too large Load Diff
+57 -67
View File
@@ -18,7 +18,9 @@
client_process.cpp:
Handles client login sequence and packets sent from client to zone
*/
#include "../common/debug.h"
#include "../common/eqemu_logsys.h"
#include "../common/global_define.h"
#include <iostream>
#include <stdio.h>
#include <zlib.h>
@@ -124,7 +126,7 @@ bool Client::Process() {
HandleRespawnFromHover(0);
}
if(IsTracking() && (GetClientVersion() >= EQClientSoD) && TrackingTimer.Check())
if(IsTracking() && (GetClientVersion() >= ClientVersion::SoD) && TrackingTimer.Check())
DoTracking();
if(hpupdate_timer.Check())
@@ -174,7 +176,7 @@ bool Client::Process() {
GetMerc()->Save();
GetMerc()->Depop();
}
Raid *myraid = entity_list.GetRaidByClient(this);
if (myraid)
{
@@ -231,10 +233,7 @@ bool Client::Process() {
if(GetMercInfo().MercTemplateID != 0 && GetMercInfo().IsSuspended)
{
if(p_timers.Expired(&database, pTimerMercSuspend, false))
{
CheckMercSuspendTimer();
}
CheckMercSuspendTimer();
}
if(IsAIControlled())
@@ -340,41 +339,31 @@ bool Client::Process() {
if(aa_los_them_mob)
{
if(auto_attack_target != aa_los_them_mob ||
aa_los_me.x != GetX() ||
aa_los_me.y != GetY() ||
aa_los_me.z != GetZ() ||
aa_los_them.x != aa_los_them_mob->GetX() ||
aa_los_them.y != aa_los_them_mob->GetY() ||
aa_los_them.z != aa_los_them_mob->GetZ())
m_AutoAttackPosition.x != GetX() ||
m_AutoAttackPosition.y != GetY() ||
m_AutoAttackPosition.z != GetZ() ||
m_AutoAttackTargetLocation.x != aa_los_them_mob->GetX() ||
m_AutoAttackTargetLocation.y != aa_los_them_mob->GetY() ||
m_AutoAttackTargetLocation.z != aa_los_them_mob->GetZ())
{
aa_los_them_mob = auto_attack_target;
aa_los_me.x = GetX();
aa_los_me.y = GetY();
aa_los_me.z = GetZ();
aa_los_them.x = aa_los_them_mob->GetX();
aa_los_them.y = aa_los_them_mob->GetY();
aa_los_them.z = aa_los_them_mob->GetZ();
m_AutoAttackPosition = GetPosition();
m_AutoAttackTargetLocation = glm::vec3(aa_los_them_mob->GetPosition());
los_status = CheckLosFN(auto_attack_target);
aa_los_me_heading = GetHeading();
los_status_facing = IsFacingMob(aa_los_them_mob);
}
// If only our heading changes, we can skip the CheckLosFN call
// but above we still need to update los_status_facing
if (aa_los_me_heading != GetHeading()) {
aa_los_me_heading = GetHeading();
if (m_AutoAttackPosition.w != GetHeading()) {
m_AutoAttackPosition.w = GetHeading();
los_status_facing = IsFacingMob(aa_los_them_mob);
}
}
else
{
aa_los_them_mob = auto_attack_target;
aa_los_me.x = GetX();
aa_los_me.y = GetY();
aa_los_me.z = GetZ();
aa_los_me_heading = GetHeading();
aa_los_them.x = aa_los_them_mob->GetX();
aa_los_them.y = aa_los_them_mob->GetY();
aa_los_them.z = aa_los_them_mob->GetZ();
m_AutoAttackPosition = GetPosition();
m_AutoAttackTargetLocation = glm::vec3(aa_los_them_mob->GetPosition());
los_status = CheckLosFN(auto_attack_target);
los_status_facing = IsFacingMob(aa_los_them_mob);
}
@@ -529,9 +518,7 @@ bool Client::Process() {
else
{
animation = 0;
delta_x = 0;
delta_y = 0;
delta_z = 0;
m_Delta = glm::vec4(0.0f, 0.0f, 0.0f, m_Delta.w);
SendPosUpdate(2);
}
}
@@ -668,7 +655,7 @@ bool Client::Process() {
if (client_state != CLIENT_LINKDEAD && !eqs->CheckState(ESTABLISHED)) {
OnDisconnect(true);
std::cout << "Client linkdead: " << name << std::endl;
Log.Out(Logs::General, Logs::Zone_Server, "Client linkdead: %s", name);
if (GetGM()) {
if (GetMerc())
@@ -785,32 +772,32 @@ void Client::OnDisconnect(bool hard_disconnect) {
if (MyRaid)
MyRaid->MemberZoned(this);
parse->EventPlayer(EVENT_DISCONNECT, this, "", 0);
parse->EventPlayer(EVENT_DISCONNECT, this, "", 0);
/* QS: PlayerLogConnectDisconnect */
if (RuleB(QueryServ, PlayerLogConnectDisconnect)){
std::string event_desc = StringFormat("Disconnect :: in zoneid:%i instid:%i", this->GetZoneID(), this->GetInstanceID());
QServ->PlayerLogEvent(Player_Log_Connect_State, this->CharacterID(), event_desc);
}
}
}
Mob *Other = trade->With();
Mob *Other = trade->With();
if(Other)
{
mlog(TRADING__CLIENT, "Client disconnected during a trade. Returning their items.");
Log.Out(Logs::Detail, Logs::Trading, "Client disconnected during a trade. Returning their items.");
FinishTrade(this);
if(Other->IsClient())
Other->CastToClient()->FinishTrade(Other);
/* Reset both sides of the trade */
trade->Reset();
trade->Reset();
Other->trade->Reset();
}
database.SetFirstLogon(CharacterID(), 0); //We change firstlogon status regardless of if a player logs out to zone or not, because we only want to trigger it on their first login from world.
/* Remove ourself from all proximities */
/* Remove ourself from all proximities */
ClearAllProximities();
EQApplicationPacket *outapp = new EQApplicationPacket(OP_LogoutReply);
@@ -834,7 +821,7 @@ void Client::BulkSendInventoryItems() {
if(inst) {
bool is_arrow = (inst->GetItem()->ItemType == ItemTypeArrow) ? true : false;
int16 free_slot_id = m_inv.FindFreeSlot(inst->IsType(ItemClassContainer), true, inst->GetItem()->Size, is_arrow);
mlog(INVENTORY__ERROR, "Incomplete Trade Transaction: Moving %s from slot %i to %i", inst->GetItem()->Name, slot_id, free_slot_id);
Log.Out(Logs::Detail, Logs::Inventory, "Incomplete Trade Transaction: Moving %s from slot %i to %i", inst->GetItem()->Name, slot_id, free_slot_id);
PutItemInInventory(free_slot_id, *inst, false);
database.SaveInventory(character_id, nullptr, slot_id);
safe_delete(inst);
@@ -883,7 +870,7 @@ void Client::BulkSendInventoryItems() {
}
// Power Source
if(GetClientVersion() >= EQClientSoF) {
if(GetClientVersion() >= ClientVersion::SoF) {
const ItemInst* inst = m_inv[MainPowerSource];
if(inst) {
std::string packet = inst->Serialize(MainPowerSource);
@@ -973,6 +960,9 @@ void Client::BulkSendInventoryItems()
void Client::BulkSendMerchantInventory(int merchant_id, int npcid) {
const Item_Struct* handyitem = nullptr;
uint32 numItemSlots = 80; //The max number of items passed in the transaction.
if (ClientVersionBit & BIT_RoFAndLater) { // RoF+ can send 200 items
numItemSlots = 200;
}
const Item_Struct *item;
std::list<MerchantList> merlist = zone->merchanttable[merchant_id];
std::list<MerchantList>::const_iterator itr;
@@ -1035,7 +1025,7 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) {
// Account for merchant lists with gaps.
if (ml.slot >= i) {
if (ml.slot > i)
LogFile->write(EQEMuLog::Debug, "(WARNING) Merchantlist contains gap at slot %d. Merchant: %d, NPC: %d", i, merchant_id, npcid);
Log.Out(Logs::General, Logs::None, "(WARNING) Merchantlist contains gap at slot %d. Merchant: %d, NPC: %d", i, merchant_id, npcid);
i = ml.slot + 1;
}
}
@@ -1127,7 +1117,7 @@ uint8 Client::WithCustomer(uint16 NewCustomer){
Client* c = entity_list.GetClientByID(CustomerID);
if(!c) {
_log(TRADING__CLIENT, "Previous customer has gone away.");
Log.Out(Logs::Detail, Logs::Trading, "Previous customer has gone away.");
CustomerID = NewCustomer;
return 1;
}
@@ -1139,7 +1129,7 @@ void Client::OPRezzAnswer(uint32 Action, uint32 SpellID, uint16 ZoneID, uint16 I
{
if(PendingRezzXP < 0) {
// pendingrezexp is set to -1 if we are not expecting an OP_RezzAnswer
_log(SPELLS__REZ, "Unexpected OP_RezzAnswer. Ignoring it.");
Log.Out(Logs::Detail, Logs::Spells, "Unexpected OP_RezzAnswer. Ignoring it.");
Message(13, "You have already been resurrected.\n");
return;
}
@@ -1149,7 +1139,7 @@ void Client::OPRezzAnswer(uint32 Action, uint32 SpellID, uint16 ZoneID, uint16 I
// Mark the corpse as rezzed in the database, just in case the corpse has buried, or the zone the
// corpse is in has shutdown since the rez spell was cast.
database.MarkCorpseAsRezzed(PendingRezzDBID);
_log(SPELLS__REZ, "Player %s got a %i Rezz, spellid %i in zone%i, instance id %i",
Log.Out(Logs::Detail, Logs::Spells, "Player %s got a %i Rezz, spellid %i in zone%i, instance id %i",
this->name, (uint16)spells[SpellID].base[0],
SpellID, ZoneID, InstanceID);
@@ -1199,7 +1189,7 @@ void Client::OPMemorizeSpell(const EQApplicationPacket* app)
{
if(app->size != sizeof(MemorizeSpell_Struct))
{
LogFile->write(EQEMuLog::Error,"Wrong size on OP_MemorizeSpell. Got: %i, Expected: %i", app->size, sizeof(MemorizeSpell_Struct));
Log.Out(Logs::General, Logs::Error, "Wrong size on OP_MemorizeSpell. Got: %i, Expected: %i", app->size, sizeof(MemorizeSpell_Struct));
DumpPacket(app);
return;
}
@@ -1555,7 +1545,7 @@ void Client::OPMoveCoin(const EQApplicationPacket* app)
if (from_bucket == &m_pp.platinum_shared)
amount_to_add = 0 - amount_to_take;
database.SetSharedPlatinum(AccountID(),amount_to_add);
database.SetSharedPlatinum(AccountID(),amount_to_add);
}
}
else{
@@ -1613,7 +1603,7 @@ void Client::OPGMTraining(const EQApplicationPacket *app)
return;
//you have to be somewhat close to a trainer to be properly using them
if(DistNoRoot(*pTrainer) > USE_NPC_RANGE2)
if(DistanceSquared(m_Position,pTrainer->GetPosition()) > USE_NPC_RANGE2)
return;
// if this for-loop acts up again (crashes linux), try enabling the before and after #pragmas
@@ -1661,7 +1651,7 @@ void Client::OPGMEndTraining(const EQApplicationPacket *app)
return;
//you have to be somewhat close to a trainer to be properly using them
if(DistNoRoot(*pTrainer) > USE_NPC_RANGE2)
if(DistanceSquared(m_Position, pTrainer->GetPosition()) > USE_NPC_RANGE2)
return;
// goodbye message
@@ -1690,7 +1680,7 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app)
return;
//you have to be somewhat close to a trainer to be properly using them
if(DistNoRoot(*pTrainer) > USE_NPC_RANGE2)
if(DistanceSquared(m_Position, pTrainer->GetPosition()) > USE_NPC_RANGE2)
return;
if (gmskill->skillbank == 0x01)
@@ -1721,12 +1711,12 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app)
SkillUseTypes skill = (SkillUseTypes) gmskill->skill_id;
if(!CanHaveSkill(skill)) {
mlog(CLIENT__ERROR, "Tried to train skill %d, which is not allowed.", skill);
Log.Out(Logs::Detail, Logs::Skills, "Tried to train skill %d, which is not allowed.", skill);
return;
}
if(MaxSkill(skill) == 0) {
mlog(CLIENT__ERROR, "Tried to train skill %d, but training is not allowed at this level.", skill);
Log.Out(Logs::Detail, Logs::Skills, "Tried to train skill %d, but training is not allowed at this level.", skill);
return;
}
@@ -1741,7 +1731,7 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app)
}
SetSkill(skill, t_level);
} else {
} else {
switch(skill) {
case SkillBrewing:
case SkillMakePoison:
@@ -1804,7 +1794,7 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app)
}
}
if(GetClientVersion() >= EQClientSoF) {
if(GetClientVersion() >= ClientVersion::SoF) {
// The following packet decreases the skill points left in the Training Window and
// produces the 'You have increased your skill / learned the basics of' message.
//
@@ -1943,7 +1933,7 @@ void Client::DoEnduranceUpkeep() {
int upkeep_sum = 0;
int cost_redux = spellbonuses.EnduranceReduction + itembonuses.EnduranceReduction + aabonuses.EnduranceReduction;
bool has_effect = false;
uint32 buffs_i;
uint32 buff_count = GetMaxTotalSlots();
@@ -2120,7 +2110,7 @@ void Client::HandleRespawnFromHover(uint32 Option)
{
if (PendingRezzXP < 0 || PendingRezzSpellID == 0)
{
_log(SPELLS__REZ, "Unexpected Rezz from hover request.");
Log.Out(Logs::Detail, Logs::Spells, "Unexpected Rezz from hover request.");
return;
}
SetHP(GetMaxHP() / 5);
@@ -2129,9 +2119,9 @@ void Client::HandleRespawnFromHover(uint32 Option)
if (corpse)
{
x_pos = corpse->GetX();
y_pos = corpse->GetY();
z_pos = corpse->GetZ();
m_Position.x = corpse->GetX();
m_Position.y = corpse->GetY();
m_Position.z = corpse->GetZ();
}
EQApplicationPacket* outapp = new EQApplicationPacket(OP_ZonePlayerToBind, sizeof(ZonePlayerToBind_Struct) + 10);
@@ -2153,10 +2143,10 @@ void Client::HandleRespawnFromHover(uint32 Option)
if (corpse && corpse->IsCorpse())
{
_log(SPELLS__REZ, "Hover Rez in zone %s for corpse %s",
Log.Out(Logs::Detail, Logs::Spells, "Hover Rez in zone %s for corpse %s",
zone->GetShortName(), PendingRezzCorpseName.c_str());
_log(SPELLS__REZ, "Found corpse. Marking corpse as rezzed.");
Log.Out(Logs::Detail, Logs::Spells, "Found corpse. Marking corpse as rezzed.");
corpse->IsRezzed(true);
corpse->CompleteResurrection();
@@ -2184,10 +2174,10 @@ void Client::HandleRespawnFromHover(uint32 Option)
SetMana(GetMaxMana());
SetEndurance(GetMaxEndurance());
x_pos = chosen->x;
y_pos = chosen->y;
z_pos = chosen->z;
heading = chosen->heading;
m_Position.x = chosen->x;
m_Position.y = chosen->y;
m_Position.z = chosen->z;
m_Position.w = chosen->heading;
ClearHover();
entity_list.RefreshClientXTargets(this);
@@ -2197,7 +2187,7 @@ void Client::HandleRespawnFromHover(uint32 Option)
//After they've respawned into the same zone, trigger EVENT_RESPAWN
parse->EventPlayer(EVENT_RESPAWN, this, static_cast<std::string>(itoa(Option)), is_rez ? 1 : 0);
//Pop Rez option from the respawn options list;
//Pop Rez option from the respawn options list;
//easiest way to make sure it stays at the end and
//doesn't disrupt adding/removing scripted options
respawn_options.pop_back();
@@ -2244,7 +2234,7 @@ void Client::ClearHover()
entity_list.QueueClients(this, outapp, false);
safe_delete(outapp);
if(IsClient() && CastToClient()->GetClientVersionBit() & BIT_UnderfootAndLater)
if(IsClient() && CastToClient()->GetClientVersionBit() & BIT_UFAndLater)
{
EQApplicationPacket *outapp = MakeBuffsPacket(false);
CastToClient()->FastQueuePacket(&outapp);
+2285 -2316
View File
File diff suppressed because it is too large Load Diff
+5 -6
View File
@@ -87,7 +87,6 @@ void command_chat(Client *c, const Seperator *sep);
void command_showpetspell(Client *c, const Seperator *sep);
void command_ipc(Client *c, const Seperator *sep);
void command_npcloot(Client *c, const Seperator *sep);
void command_log(Client *c, const Seperator *sep);
void command_gm(Client *c, const Seperator *sep);
void command_summon(Client *c, const Seperator *sep);
void command_zone(Client *c, const Seperator *sep);
@@ -259,9 +258,6 @@ void command_undye(Client *c, const Seperator *sep);
void command_undyeme(Client *c, const Seperator *sep);
void command_hp(Client *c, const Seperator *sep);
void command_ginfo(Client *c, const Seperator *sep);
void command_logs(Client *c, const Seperator *sep);
void command_nologs(Client *c, const Seperator *sep);
void command_logsql(Client *c, const Seperator *sep);
void command_qglobal(Client *c, const Seperator *sep);
void command_path(Client *c, const Seperator *sep);
void command_ginfo(Client *c, const Seperator *sep);
@@ -272,7 +268,6 @@ void command_aggrozone(Client *c, const Seperator *sep);
void command_reloadstatic(Client *c, const Seperator *sep);
void command_flags(Client *c, const Seperator *sep);
void command_flagedit(Client *c, const Seperator *sep);
void command_mlog(Client *c, const Seperator *sep);
void command_serverrules(Client *c, const Seperator *sep);
void command_acceptrules(Client *c, const Seperator *sep);
void command_guildcreate(Client *c, const Seperator *sep);
@@ -326,7 +321,11 @@ void command_npctype_cache(Client *c, const Seperator *sep);
void command_merchantopenshop(Client *c, const Seperator *sep);
void command_merchantcloseshop(Client *c, const Seperator *sep);
void command_shownumhits(Client *c, const Seperator *sep);
void command_tune(Client *c, const Seperator *sep);
void command_logtest(Client *c, const Seperator *sep);
void command_mysqltest(Client *c, const Seperator *sep);
void command_logs(Client *c, const Seperator *sep);
#ifdef EQPROFILE
void command_profiledump(Client *c, const Seperator *sep);
void command_profilereset(Client *c, const Seperator *sep);
+15 -17
View File
@@ -7,7 +7,7 @@
#define HIGHEST_RESIST 9 //Max resist type value
#define MAX_SPELL_PROJECTILE 10 //Max amount of spell projectiles that can be active by a single mob.
/* solar: macros for IsAttackAllowed, IsBeneficialAllowed */
/* macros for IsAttackAllowed, IsBeneficialAllowed */
#define _CLIENT(x) (x && x->IsClient() && !x->CastToClient()->IsBecomeNPC())
#define _NPC(x) (x && x->IsNPC() && !x->CastToMob()->GetOwnerID())
#define _BECOMENPC(x) (x && x->IsClient() && x->CastToClient()->IsBecomeNPC())
@@ -158,18 +158,18 @@ enum TradeState {
TradeCompleting
};
enum { //Numhits type
NUMHIT_IncomingHitAttempts = 1, //Attempted incoming melee attacks (hit or miss) on YOU.
NUMHIT_OutgoingHitAttempts = 2, //Attempted outgoing melee attacks (hit or miss) on YOUR TARGET.
NUMHIT_IncomingSpells = 3, //Incoming detrimental spells
NUMHIT_OutgoingSpells = 4, //Outgoing deterimental spells
NUMHIT_OutgoingHitSuccess = 5, //Successful outgoing melee attack HIT on YOUR TARGET.
NUMHIT_IncomingHitSuccess = 6, //Successful incoming melee attack HIT on YOU.
NUMHIT_MatchingSpells = 7, //Any casted spell matching/triggering a focus effect.
NUMHIT_IncomingDamage = 8, //Successful incoming spell or melee dmg attack on YOU
NUMHIT_ReflectSpell = 9, //Incoming Reflected spells.
NUMHIT_DefensiveSpellProcs = 10, //Defensive buff procs
NUMHIT_OffensiveSpellProcs = 11 //Offensive buff procs
enum class NumHit { // Numhits type
IncomingHitAttempts = 1, // Attempted incoming melee attacks (hit or miss) on YOU.
OutgoingHitAttempts = 2, // Attempted outgoing melee attacks (hit or miss) on YOUR TARGET.
IncomingSpells = 3, // Incoming detrimental spells
OutgoingSpells = 4, // Outgoing detrimental spells
OutgoingHitSuccess = 5, // Successful outgoing melee attack HIT on YOUR TARGET.
IncomingHitSuccess = 6, // Successful incoming melee attack HIT on YOU.
MatchingSpells = 7, // Any casted spell matching/triggering a focus effect.
IncomingDamage = 8, // Successful incoming spell or melee dmg attack on YOU
ReflectSpell = 9, // Incoming Reflected spells.
DefensiveSpellProcs = 10, // Defensive buff procs
OffensiveSpellProcs = 11 // Offensive buff procs
};
//this is our internal representation of the BUFF struct, can put whatever we want in it
@@ -560,10 +560,8 @@ public:
// Audit trade
void LogTrade();
// Debug only method
#if (EQDEBUG >= 9)
void DumpTrade();
#endif
void DumpTrade();
public:
// Object state
+227 -259
View File
@@ -28,7 +28,8 @@ Child of the Mob class.
#define strcasecmp _stricmp
#endif
#include "../common/debug.h"
#include "../common/global_define.h"
#include "../common/eqemu_logsys.h"
#include "../common/rulesys.h"
#include "../common/string_util.h"
@@ -71,13 +72,13 @@ void Corpse::SendLootReqErrorPacket(Client* client, uint8 response) {
safe_delete(outapp);
}
Corpse* Corpse::LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std::string in_charname, float in_x, float in_y, float in_z, float in_heading, std::string time_of_death, bool rezzed, bool was_at_graveyard){
Corpse* Corpse::LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std::string in_charname, const glm::vec4& position, std::string time_of_death, bool rezzed, bool was_at_graveyard) {
uint32 item_count = database.GetCharacterCorpseItemCount(in_dbid);
char *buffer = new char[sizeof(PlayerCorpse_Struct) + (item_count * sizeof(player_lootitem::ServerLootItem_Struct))];
PlayerCorpse_Struct *pcs = (PlayerCorpse_Struct*)buffer;
database.LoadCharacterCorpseData(in_dbid, pcs);
/* Load Items */
/* Load Items */
ItemList itemlist;
ServerLootItem_Struct* tmp = 0;
for (unsigned int i = 0; i < pcs->itemcount; i++) {
@@ -96,10 +97,7 @@ Corpse* Corpse::LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std:
pcs->silver, // uint32 in_silver
pcs->gold, // uint32 in_gold
pcs->plat, // uint32 in_plat
in_x, // float in_x
in_y, // float in_y
in_z, // float in_z
in_heading, // float in_heading
position,
pcs->size, // float in_size
pcs->gender, // uint8 in_gender
pcs->race, // uint16 in_race
@@ -111,9 +109,9 @@ Corpse* Corpse::LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std:
pcs->exp, // uint32 in_rezexp
was_at_graveyard // bool wasAtGraveyard
);
if (pcs->locked){
if (pcs->locked)
pc->Lock();
}
/* Load Item Tints */
pc->item_tint[0].color = pcs->item_tint[0].color;
@@ -124,7 +122,7 @@ Corpse* Corpse::LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std:
pc->item_tint[5].color = pcs->item_tint[5].color;
pc->item_tint[6].color = pcs->item_tint[6].color;
pc->item_tint[7].color = pcs->item_tint[7].color;
pc->item_tint[8].color = pcs->item_tint[8].color;
pc->item_tint[8].color = pcs->item_tint[8].color;
/* Load Physical Appearance */
pc->haircolor = pcs->haircolor;
@@ -140,63 +138,22 @@ Corpse* Corpse::LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std:
pc->IsRezzed(rezzed);
pc->become_npc = false;
pc->spell_light = pc->innate_light = NOT_USED;
pc->UpdateEquipLightValue();
//pc->UpdateActiveLightValue();
safe_delete_array(pcs);
return pc;
}
Corpse::Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NPCType** in_npctypedata, uint32 in_decaytime)
: Mob("Unnamed_Corpse", // const char* in_name,
"", // const char* in_lastname,
0, // int32 in_cur_hp,
0, // int32 in_max_hp,
in_npc->GetGender(), // uint8 in_gender,
in_npc->GetRace(), // uint16 in_race,
in_npc->GetClass(), // uint8 in_class,
BT_Humanoid, // bodyType in_bodytype,
in_npc->GetDeity(), // uint8 in_deity,
in_npc->GetLevel(), // uint8 in_level,
in_npc->GetNPCTypeID(), // uint32 in_npctype_id,
in_npc->GetSize(), // float in_size,
0, // float in_runspeed,
in_npc->GetHeading(), // float in_heading,
in_npc->GetX(), // float in_x_pos,
in_npc->GetY(), // float in_y_pos,
in_npc->GetZ(), // float in_z_pos,
0, // uint8 in_light,
in_npc->GetTexture(), // uint8 in_texture,
in_npc->GetHelmTexture(), // uint8 in_helmtexture,
0, // uint16 in_ac,
0, // uint16 in_atk,
0, // uint16 in_str,
0, // uint16 in_sta,
0, // uint16 in_dex,
0, // uint16 in_agi,
0, // uint16 in_int,
0, // uint16 in_wis,
0, // uint16 in_cha,
0, // uint8 in_haircolor,
0, // uint8 in_beardcolor,
0, // uint8 in_eyecolor1, // the eyecolors always seem to be the same, maybe left and right eye?
0, // uint8 in_eyecolor2,
0, // uint8 in_hairstyle,
0, // uint8 in_luclinface,
0, // uint8 in_beard,
0, // uint32 in_drakkin_heritage,
0, // uint32 in_drakkin_tattoo,
0, // uint32 in_drakkin_details,
0, // uint32 in_armor_tint[_MaterialCount],
0xff, // uint8 in_aa_title,
0, // uint8 in_see_invis, // see through invis/ivu
0, // uint8 in_see_invis_undead,
0, // uint8 in_see_hide,
0, // uint8 in_see_improved_hide,
0, // int32 in_hp_regen,
0, // int32 in_mana_regen,
0, // uint8 in_qglobal,
0, // uint8 in_maxlevel,
0 // uint32 in_scalerate
),
// vesuvias - appearence fix
: Mob("Unnamed_Corpse","",0,0,in_npc->GetGender(),in_npc->GetRace(),in_npc->GetClass(),BT_Humanoid,//bodytype added
in_npc->GetDeity(),in_npc->GetLevel(),in_npc->GetNPCTypeID(),in_npc->GetSize(),0,
in_npc->GetPosition(), in_npc->GetInnateLightValue(), in_npc->GetTexture(),in_npc->GetHelmTexture(),
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0xff,0,0,0,0,0,0,0,0,0),
corpse_decay_timer(in_decaytime),
corpse_rez_timer(0),
corpse_delay_timer(RuleI(NPC, CorpseUnlockTimer)),
@@ -225,7 +182,7 @@ Corpse::Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NP
player_corpse_depop = false;
strcpy(corpse_name, in_npc->GetName());
strcpy(name, in_npc->GetName());
for(int count = 0; count < 100; count++) {
if ((level >= npcCorpseDecayTimes[count].minlvl) && (level <= npcCorpseDecayTimes[count].maxlvl)) {
corpse_decay_timer.SetTimer(npcCorpseDecayTimes[count].seconds*1000);
@@ -236,6 +193,7 @@ Corpse::Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NP
corpse_decay_timer.SetTimer(RuleI(NPC,EmptyNPCCorpseDecayTimeMS)+1000);
}
if(in_npc->HasPrivateCorpse()) {
corpse_delay_timer.SetTimer(corpse_decay_timer.GetRemainingTime() + 1000);
}
@@ -244,6 +202,10 @@ Corpse::Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NP
allowed_looters[i] = 0;
}
this->rez_experience = 0;
UpdateEquipLightValue();
spell_light = NOT_USED;
UpdateActiveLightValue();
}
Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
@@ -260,11 +222,8 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
0, // uint32 in_npctype_id,
client->GetSize(), // float in_size,
0, // float in_runspeed,
client->GetHeading(), // float in_heading,
client->GetX(), // float in_x_pos,
client->GetY(), // float in_y_pos,
client->GetZ(), // float in_z_pos,
0, // uint8 in_light,
client->GetPosition(),
0, // uint8 in_light, - verified for client innate_light value
client->GetTexture(), // uint8 in_texture,
client->GetHelmTexture(), // uint8 in_helmtexture,
0, // uint16 in_ac,
@@ -297,15 +256,15 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
0, // uint8 in_qglobal,
0, // uint8 in_maxlevel,
0 // uint32 in_scalerate
),
),
corpse_decay_timer(RuleI(Character, CorpseDecayTimeMS)),
corpse_rez_timer(RuleI(Character, CorpseResTimeMS)),
corpse_delay_timer(RuleI(NPC, CorpseUnlockTimer)),
corpse_graveyard_timer(RuleI(Zone, GraveyardTimeMS)),
loot_cooldown_timer(10)
loot_cooldown_timer(10)
{
int i;
PlayerProfile_Struct *pp = &client->GetPP();
ItemInst *item;
@@ -335,7 +294,7 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
platinum = 0;
strcpy(corpse_name, pp->name);
strcpy(name, pp->name);
strcpy(name, pp->name);
/* become_npc was not being initialized which led to some pretty funky things with newly created corpses */
become_npc = false;
@@ -343,13 +302,13 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
SetPlayerKillItemID(0);
/* Check Rule to see if we can leave corpses */
if(!RuleB(Character, LeaveNakedCorpses) ||
RuleB(Character, LeaveCorpses) &&
if(!RuleB(Character, LeaveNakedCorpses) ||
RuleB(Character, LeaveCorpses) &&
GetLevel() >= RuleI(Character, DeathItemLossLevel)) {
// cash
// Let's not move the cash when 'RespawnFromHover = true' && 'client->GetClientVersion() < EQClientSoF' since the client doesn't.
// (change to first client that supports 'death hover' mode, if not SoF.)
if (!RuleB(Character, RespawnFromHover) || client->GetClientVersion() < EQClientSoF) {
if (!RuleB(Character, RespawnFromHover) || client->GetClientVersion() < ClientVersion::SoF) {
SetCash(pp->copper, pp->silver, pp->gold, pp->platinum);
pp->copper = 0;
pp->silver = 0;
@@ -360,48 +319,30 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
// get their tints
memcpy(item_tint, &client->GetPP().item_tint, sizeof(item_tint));
// solar: TODO soulbound items need not be added to corpse, but they need
// TODO soulbound items need not be added to corpse, but they need
// to go into the regular slots on the player, out of bags
// worn + inventory + cursor
std::list<uint32> removed_list;
bool cursor = false;
for(i = MAIN_BEGIN; i < EmuConstants::MAP_POSSESSIONS_SIZE; i++) {
if(i == MainAmmo && client->GetClientVersion() >= EQClientSoF) {
for(i = MAIN_BEGIN; i < EmuConstants::MAP_POSSESSIONS_SIZE; ++i) {
if(i == MainAmmo && client->GetClientVersion() >= ClientVersion::SoF) {
item = client->GetInv().GetItem(MainPowerSource);
if((item && (!client->IsBecomeNPC())) || (item && client->IsBecomeNPC() && !item->GetItem()->NoRent)) {
std::list<uint32> slot_list = MoveItemToCorpse(client, item, MainPowerSource);
removed_list.merge(slot_list);
if (item != nullptr) {
if (!client->IsBecomeNPC() || (client->IsBecomeNPC() && !item->GetItem()->NoRent))
MoveItemToCorpse(client, item, MainPowerSource, removed_list);
}
}
item = client->GetInv().GetItem(i);
if((item && (!client->IsBecomeNPC())) || (item && client->IsBecomeNPC() && !item->GetItem()->NoRent)) {
std::list<uint32> slot_list = MoveItemToCorpse(client, item, i);
removed_list.merge(slot_list);
}
}
if (item == nullptr) { continue; }
// cursor queue // (change to first client that supports 'death hover' mode, if not SoF.)
if (!RuleB(Character, RespawnFromHover) || client->GetClientVersion() < EQClientSoF) {
// bumped starting assignment to 8001 because any in-memory 'slot 8000' item was moved above as 'slot 30'
// this was mainly for client profile state reflection..should match db player inventory entries now.
iter_queue it;
for (it = client->GetInv().cursor_begin(), i = 8001; it != client->GetInv().cursor_end(); ++it, i++) {
item = *it;
if ((item && (!client->IsBecomeNPC())) || (item && client->IsBecomeNPC() && !item->GetItem()->NoRent)) {
std::list<uint32> slot_list = MoveItemToCorpse(client, item, i);
removed_list.merge(slot_list);
cursor = true;
}
}
if(!client->IsBecomeNPC() || (client->IsBecomeNPC() && !item->GetItem()->NoRent))
MoveItemToCorpse(client, item, i, removed_list);
}
database.TransactionBegin();
if (removed_list.size() != 0) {
// I have an untested process that avoids this snarl up when all possessions inventory is removed..but this isn't broke -U
if (!removed_list.empty()) {
std::stringstream ss("");
ss << "DELETE FROM inventory WHERE charid=" << client->CharacterID();
ss << " AND (";
@@ -421,111 +362,127 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
database.QueryDatabase(ss.str().c_str());
}
if (cursor) { // all cursor items should be on corpse (client < SoF or RespawnFromHover = false)
while (!client->GetInv().CursorEmpty())
client->DeleteItemInInventory(MainCursor, 0, false, false);
}
else { // only visible cursor made it to corpse (client >= Sof and RespawnFromHover = true)
std::list<ItemInst*>::const_iterator start = client->GetInv().cursor_begin();
std::list<ItemInst*>::const_iterator finish = client->GetInv().cursor_end();
database.SaveCursor(client->CharacterID(), start, finish);
}
auto start = client->GetInv().cursor_begin();
auto finish = client->GetInv().cursor_end();
database.SaveCursor(client->CharacterID(), start, finish);
client->CalcBonuses(); // will only affect offline profile viewing of dead characters..unneeded overhead
client->CalcBonuses();
client->Save();
IsRezzed(false);
Save();
database.TransactionCommit();
UpdateEquipLightValue();
spell_light = NOT_USED;
UpdateActiveLightValue();
return;
} //end "not leaving naked corpses"
UpdateEquipLightValue();
spell_light = NOT_USED;
UpdateActiveLightValue();
IsRezzed(false);
Save();
}
std::list<uint32> Corpse::MoveItemToCorpse(Client *client, ItemInst *item, int16 equipslot)
void Corpse::MoveItemToCorpse(Client *client, ItemInst *inst, int16 equipSlot, std::list<uint32> &removedList)
{
int bagindex;
int16 interior_slot;
ItemInst *interior_item;
std::list<uint32> returnlist;
AddItem(
inst->GetItem()->ID,
inst->GetCharges(),
equipSlot,
inst->GetAugmentItemID(0),
inst->GetAugmentItemID(1),
inst->GetAugmentItemID(2),
inst->GetAugmentItemID(3),
inst->GetAugmentItemID(4),
inst->GetAugmentItemID(5),
inst->IsAttuned()
);
removedList.push_back(equipSlot);
AddItem(item->GetItem()->ID, item->GetCharges(), equipslot, item->GetAugmentItemID(0), item->GetAugmentItemID(1), item->GetAugmentItemID(2), item->GetAugmentItemID(3), item->GetAugmentItemID(4), item->GetAugmentItemID(5), item->IsAttuned());
returnlist.push_back(equipslot);
while (true) {
if (!inst->IsType(ItemClassContainer)) { break; }
if (equipSlot < EmuConstants::GENERAL_BEGIN || equipSlot > MainCursor) { break; }
// Qualified bag slot iterations. processing bag slots that don't exist is probably not a good idea.
if (item->IsType(ItemClassContainer) && ((equipslot >= EmuConstants::GENERAL_BEGIN && equipslot <= MainCursor))) {
for (bagindex = SUB_BEGIN; bagindex <= EmuConstants::ITEM_CONTAINER_SIZE; bagindex++) {
// For empty bags in cursor queue, slot was previously being resolved as SLOT_INVALID (-1)
interior_slot = Inventory::CalcSlotId(equipslot, bagindex);
interior_item = client->GetInv().GetItem(interior_slot);
for (auto sub_index = SUB_BEGIN; sub_index < EmuConstants::ITEM_CONTAINER_SIZE; ++sub_index) {
int16 real_bag_slot = Inventory::CalcSlotId(equipSlot, sub_index);
auto bag_inst = client->GetInv().GetItem(real_bag_slot);
if (bag_inst == nullptr) { continue; }
if (interior_item) {
AddItem(interior_item->GetItem()->ID, interior_item->GetCharges(), interior_slot, interior_item->GetAugmentItemID(0), interior_item->GetAugmentItemID(1), interior_item->GetAugmentItemID(2), interior_item->GetAugmentItemID(3), interior_item->GetAugmentItemID(4), interior_item->GetAugmentItemID(5), item->IsAttuned());
returnlist.push_back(Inventory::CalcSlotId(equipslot, bagindex));
client->DeleteItemInInventory(interior_slot, 0, true, false);
}
AddItem(
bag_inst->GetItem()->ID,
bag_inst->GetCharges(),
real_bag_slot,
bag_inst->GetAugmentItemID(0),
bag_inst->GetAugmentItemID(1),
bag_inst->GetAugmentItemID(2),
bag_inst->GetAugmentItemID(3),
bag_inst->GetAugmentItemID(4),
bag_inst->GetAugmentItemID(5),
bag_inst->IsAttuned()
);
removedList.push_back(real_bag_slot);
client->DeleteItemInInventory(real_bag_slot, 0, true, false);
}
break;
}
client->DeleteItemInInventory(equipslot, 0, true, false);
return returnlist;
client->DeleteItemInInventory(equipSlot, 0, true, false);
}
/* Called from Database Load */
Corpse::Corpse(uint32 in_dbid, uint32 in_charid, const char* in_charname, ItemList* in_itemlist, uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_plat, float in_x, float in_y, float in_z, float in_heading, float in_size, uint8 in_gender, uint16 in_race, uint8 in_class, uint8 in_deity, uint8 in_level, uint8 in_texture, uint8 in_helmtexture,uint32 in_rezexp, bool wasAtGraveyard)
: Mob("Unnamed_Corpse", // const char* in_name,
"", // const char* in_lastname,
0, // int32 in_cur_hp,
0, // int32 in_max_hp,
in_gender, // uint8 in_gender,
in_race, // uint16 in_race,
in_class, // uint8 in_class,
BT_Humanoid, // bodyType in_bodytype,
in_deity, // uint8 in_deity,
in_level, // uint8 in_level,
0, // uint32 in_npctype_id,
in_size, // float in_size,
0, // float in_runspeed,
in_heading, // float in_heading,
in_x, // float in_x_pos,
in_y, // float in_y_pos,
in_z, // float in_z_pos,
0, // uint8 in_light,
in_texture, // uint8 in_texture,
in_helmtexture, // uint8 in_helmtexture,
0, // uint16 in_ac,
0, // uint16 in_atk,
0, // uint16 in_str,
0, // uint16 in_sta,
0, // uint16 in_dex,
0, // uint16 in_agi,
0, // uint16 in_int,
0, // uint16 in_wis,
0, // uint16 in_cha,
0, // uint8 in_haircolor,
0, // uint8 in_beardcolor,
0, // uint8 in_eyecolor1, // the eyecolors always seem to be the same, maybe left and right eye?
0, // uint8 in_eyecolor2,
0, // uint8 in_hairstyle,
0, // uint8 in_luclinface,
0, // uint8 in_beard,
0, // uint32 in_drakkin_heritage,
0, // uint32 in_drakkin_tattoo,
0, // uint32 in_drakkin_details,
0, // uint32 in_armor_tint[_MaterialCount],
0xff, // uint8 in_aa_title,
0, // uint8 in_see_invis, // see through invis/ivu
0, // uint8 in_see_invis_undead,
0, // uint8 in_see_hide,
0, // uint8 in_see_improved_hide,
0, // int32 in_hp_regen,
0, // int32 in_mana_regen,
0, // uint8 in_qglobal,
0, // uint8 in_maxlevel,
0), // uint32 in_scalerate
// To be called from LoadFromDBData
Corpse::Corpse(uint32 in_dbid, uint32 in_charid, const char* in_charname, ItemList* in_itemlist, uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_plat, const glm::vec4& position, float in_size, uint8 in_gender, uint16 in_race, uint8 in_class, uint8 in_deity, uint8 in_level, uint8 in_texture, uint8 in_helmtexture,uint32 in_rezexp, bool wasAtGraveyard)
: Mob("Unnamed_Corpse",
"",
0,
0,
in_gender,
in_race,
in_class,
BT_Humanoid,
in_deity,
in_level,
0,
in_size,
0,
position,
0, // verified for client innate_light value
in_texture,
in_helmtexture,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0xff,
0,
0,
0,
0,
0,
0,
0,
0,
0),
corpse_decay_timer(RuleI(Character, CorpseDecayTimeMS)),
corpse_rez_timer(RuleI(Character, CorpseResTimeMS)),
corpse_delay_timer(RuleI(NPC, CorpseUnlockTimer)),
@@ -535,9 +492,8 @@ Corpse::Corpse(uint32 in_dbid, uint32 in_charid, const char* in_charname, ItemLi
LoadPlayerCorpseDecayTime(in_dbid);
if (!zone->HasGraveyard() || wasAtGraveyard){
if (!zone->HasGraveyard() || wasAtGraveyard)
corpse_graveyard_timer.Disable();
}
memset(item_tint, 0, sizeof(item_tint));
@@ -565,6 +521,10 @@ Corpse::Corpse(uint32 in_dbid, uint32 in_charid, const char* in_charname, ItemLi
allowed_looters[i] = 0;
}
SetPlayerKillItemID(0);
UpdateEquipLightValue();
spell_light = NOT_USED;
UpdateActiveLightValue();
}
Corpse::~Corpse() {
@@ -640,18 +600,18 @@ bool Corpse::Save() {
ItemList::iterator cur, end;
cur = itemlist.begin();
end = itemlist.end();
for (; cur != end; ++cur) {
for (; cur != end; ++cur) {
ServerLootItem_Struct* item = *cur;
memcpy((char*)&dbpc->items[x++], (char*)item, sizeof(ServerLootItem_Struct));
}
/* Create New Corpse*/
if (corpse_db_id == 0) {
corpse_db_id = database.SaveCharacterCorpse(char_id, corpse_name, zone->GetZoneID(), zone->GetInstanceID(), dbpc, x_pos, y_pos, z_pos, heading);
corpse_db_id = database.SaveCharacterCorpse(char_id, corpse_name, zone->GetZoneID(), zone->GetInstanceID(), dbpc, m_Position);
}
/* Update Corpse Data */
else{
corpse_db_id = database.UpdateCharacterCorpse(corpse_db_id, char_id, corpse_name, zone->GetZoneID(), zone->GetInstanceID(), dbpc, x_pos, y_pos, z_pos, heading, IsRezzed());
corpse_db_id = database.UpdateCharacterCorpse(corpse_db_id, char_id, corpse_name, zone->GetZoneID(), zone->GetInstanceID(), dbpc, m_Position, IsRezzed());
}
safe_delete_array(dbpc);
@@ -661,16 +621,15 @@ bool Corpse::Save() {
void Corpse::Delete() {
if (IsPlayerCorpse() && corpse_db_id != 0)
database.DeleteCharacterCorpse(corpse_db_id);
database.DeleteCharacterCorpse(corpse_db_id);
corpse_db_id = 0;
player_corpse_depop = true;
}
void Corpse::Bury() {
if (IsPlayerCorpse() && corpse_db_id != 0){
if (IsPlayerCorpse() && corpse_db_id != 0)
database.BuryCharacterCorpse(corpse_db_id);
}
corpse_db_id = 0;
player_corpse_depop = true;
}
@@ -702,7 +661,7 @@ void Corpse::AddItem(uint32 itemnum, uint16 charges, int16 slot, uint32 aug1, ui
is_corpse_changed = true;
ServerLootItem_Struct* item = new ServerLootItem_Struct;
memset(item, 0, sizeof(ServerLootItem_Struct));
item->item_id = itemnum;
item->charges = charges;
@@ -715,6 +674,8 @@ void Corpse::AddItem(uint32 itemnum, uint16 charges, int16 slot, uint32 aug1, ui
item->aug_6=aug6;
item->attuned=attuned;
itemlist.push_back(item);
UpdateEquipLightValue();
}
ServerLootItem_Struct* Corpse::GetItem(uint16 lootslot, ServerLootItem_Struct** bag_item_data) {
@@ -776,25 +737,25 @@ void Corpse::RemoveItem(uint16 lootslot) {
}
}
void Corpse::RemoveItem(ServerLootItem_Struct* item_data){
uint8 material;
ItemList::iterator cur,end;
cur = itemlist.begin();
end = itemlist.end();
for(; cur != end; ++cur) {
ServerLootItem_Struct* sitem = *cur;
if (sitem == item_data) {
is_corpse_changed = true;
itemlist.erase(cur);
void Corpse::RemoveItem(ServerLootItem_Struct* item_data)
{
for (auto iter = itemlist.begin(); iter != itemlist.end(); ++iter) {
auto sitem = *iter;
if (sitem != item_data) { continue; }
material = Inventory::CalcMaterialFromSlot(sitem->equip_slot);
if(material != _MaterialInvalid)
SendWearChange(material);
is_corpse_changed = true;
itemlist.erase(iter);
safe_delete(sitem);
uint8 material = Inventory::CalcMaterialFromSlot(sitem->equip_slot); // autos to unsigned char
if (material != _MaterialInvalid)
SendWearChange(material);
return;
}
UpdateEquipLightValue();
if (UpdateActiveLightValue())
SendAppearancePacket(AT_Light, GetActiveLightValue());
safe_delete(sitem);
return;
}
}
@@ -818,18 +779,16 @@ bool Corpse::IsEmpty() const {
if (copper != 0 || silver != 0 || gold != 0 || platinum != 0)
return false;
return(itemlist.size() == 0);
return itemlist.empty();
}
bool Corpse::Process() {
if (player_corpse_depop){
if (player_corpse_depop)
return false;
}
if (corpse_delay_timer.Check()) {
for (int i = 0; i < MAX_LOOTERS; i++){
for (int i = 0; i < MAX_LOOTERS; i++)
allowed_looters[i] = 0;
}
corpse_delay_timer.Disable();
return true;
}
@@ -839,8 +798,7 @@ bool Corpse::Process() {
Save();
player_corpse_depop = true;
database.SendCharacterCorpseToGraveyard(corpse_db_id, zone->graveyard_zoneid(),
(zone->GetZoneID() == zone->graveyard_zoneid()) ? zone->GetInstanceID() : 0, zone->graveyard_x(),
zone->graveyard_y(), zone->graveyard_z(), zone->graveyard_heading());
(zone->GetZoneID() == zone->graveyard_zoneid()) ? zone->GetInstanceID() : 0, zone->GetGraveyardPoint());
corpse_graveyard_timer.Disable();
ServerPacket* pack = new ServerPacket(ServerOP_SpawnPlayerCorpse, sizeof(SpawnPlayerCorpse_Struct));
SpawnPlayerCorpse_Struct* spc = (SpawnPlayerCorpse_Struct*)pack->pBuffer;
@@ -848,7 +806,7 @@ bool Corpse::Process() {
spc->zone_id = zone->graveyard_zoneid();
worldserver.SendPacket(pack);
safe_delete(pack);
LogFile->write(EQEMuLog::Debug, "Moved %s player corpse to the designated graveyard in zone %s.", this->GetName(), database.GetZoneName(zone->graveyard_zoneid()));
Log.Out(Logs::General, Logs::None, "Moved %s player corpse to the designated graveyard in zone %s.", this->GetName(), database.GetZoneName(zone->graveyard_zoneid()));
corpse_db_id = 0;
}
@@ -878,10 +836,10 @@ bool Corpse::Process() {
Save();
player_corpse_depop = true;
corpse_db_id = 0;
LogFile->write(EQEMuLog::Debug, "Tagged %s player corpse has burried.", this->GetName());
Log.Out(Logs::General, Logs::None, "Tagged %s player corpse has burried.", this->GetName());
}
else {
LogFile->write(EQEMuLog::Error, "Unable to bury %s player corpse.", this->GetName());
Log.Out(Logs::General, Logs::Error, "Unable to bury %s player corpse.", this->GetName());
return true;
}
}
@@ -906,15 +864,11 @@ bool Corpse::CanPlayerLoot(int charid) {
looters++;
}
if (allowed_looters[i] == charid){
if (allowed_looters[i] == charid)
return true;
}
}
/* If we have no looters, obviously client can loot */
if (looters == 0){
return true;
}
return false;
return looters == 0;
}
void Corpse::AllowPlayerLoot(Mob *them, uint8 slot) {
@@ -947,21 +901,20 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
return;
}
if(being_looted_by == 0) {
being_looted_by = 0xFFFFFFFF;
}
if(being_looted_by == 0)
being_looted_by = 0xFFFFFFFF;
if(this->being_looted_by != 0xFFFFFFFF) {
// lets double check....
Entity* looter = entity_list.GetID(this->being_looted_by);
if(looter == 0) {
this->being_looted_by = 0xFFFFFFFF;
}
if(looter == 0)
this->being_looted_by = 0xFFFFFFFF;
}
uint8 Loot_Request_Type = 1;
bool loot_coin = false;
if(database.GetVariable("LootCoin", tmp, 9)) { loot_coin = (atoi(tmp) == 1); }
if(database.GetVariable("LootCoin", tmp, 9))
loot_coin = (atoi(tmp) == 1);
if (this->being_looted_by != 0xFFFFFFFF && this->being_looted_by != client->GetID()) {
SendLootReqErrorPacket(client, 0);
@@ -999,7 +952,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
d->unknown2 = 0xef;
/* Dont take the coin off if it's a gm peeking at the corpse */
if(Loot_Request_Type == 2 || (Loot_Request_Type >= 3 && loot_coin)) {
if(Loot_Request_Type == 2 || (Loot_Request_Type >= 3 && loot_coin)) {
if(!IsPlayerCorpse() && client->IsGrouped() && client->AutoSplitEnabled() && client->GetGroup()) {
d->copper = 0;
d->silver = 0;
@@ -1017,9 +970,10 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
}
RemoveCash();
Save();
Save();
}
auto timestamps = database.GetItemRecastTimestamps(client->CharacterID());
outapp->priority = 6;
client->QueuePacket(outapp);
safe_delete(outapp);
@@ -1028,6 +982,8 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
const Item_Struct* item = database.GetItem(pkitem);
ItemInst* inst = database.CreateItem(item, item->MaxCharges);
if(inst) {
if (item->RecastDelay)
inst->SetRecastTimestamp(timestamps.count(item->RecastType) ? timestamps.at(item->RecastType) : 0);
client->SendItemPacket(EmuConstants::CORPSE_BEGIN, inst, ItemPacketLoot);
safe_delete(inst);
}
@@ -1059,6 +1015,8 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
if(client && item) {
ItemInst* inst = database.CreateItem(item, item_data->charges, item_data->aug_1, item_data->aug_2, item_data->aug_3, item_data->aug_4, item_data->aug_5, item_data->aug_6, item_data->attuned);
if(inst) {
if (item->RecastDelay)
inst->SetRecastTimestamp(timestamps.count(item->RecastType) ? timestamps.at(item->RecastType) : 0);
// MainGeneral1 is the corpse inventory start offset for Ti(EMu) - CORPSE_END = MainGeneral1 + MainCursor
client->SendItemPacket(i + EmuConstants::CORPSE_BEGIN, inst, ItemPacketLoot);
safe_delete(inst);
@@ -1089,7 +1047,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
for(; cur != end; ++cur) {
ServerLootItem_Struct* item_data = *cur;
item = database.GetItem(item_data->item_id);
LogFile->write(EQEMuLog::Debug, "Corpse Looting: %s was not sent to client loot window (corpse_dbid: %i, charname: %s(%s))", item->Name, GetCorpseDBID(), client->GetName(), client->GetGM() ? "GM" : "Owner");
Log.Out(Logs::General, Logs::None, "Corpse Looting: %s was not sent to client loot window (corpse_dbid: %i, charname: %s(%s))", item->Name, GetCorpseDBID(), client->GetName(), client->GetGM() ? "GM" : "Owner");
client->Message(0, "Inaccessable Corpse Item: %s", item->Name);
}
}
@@ -1101,7 +1059,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
// This is required for the 'Loot All' feature to work for SoD clients. I expect it is to tell the client that the
// server has now sent all the items on the corpse.
if(client->GetClientVersion() >= EQClientSoD) { SendLootReqErrorPacket(client, 6); }
if(client->GetClientVersion() >= ClientVersion::SoD) { SendLootReqErrorPacket(client, 6); }
}
void Corpse::LootItem(Client* client, const EQApplicationPacket* app) {
@@ -1246,7 +1204,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) {
/* Delete needs to be before RemoveItem because its deletes the pointer for item_data/bag_item_data */
database.DeleteItemOffCharacterCorpse(this->corpse_db_id, item_data->equip_slot, item_data->item_id);
/* Delete Item Instance */
RemoveItem(item_data->lootslot);
RemoveItem(item_data->lootslot);
}
/* Remove Bag Contents */
@@ -1254,9 +1212,9 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) {
for (int i = SUB_BEGIN; i < EmuConstants::ITEM_CONTAINER_SIZE; i++) {
if (bag_item_data[i]) {
/* Delete needs to be before RemoveItem because its deletes the pointer for item_data/bag_item_data */
database.DeleteItemOffCharacterCorpse(this->corpse_db_id, bag_item_data[i]->equip_slot, bag_item_data[i]->item_id);
database.DeleteItemOffCharacterCorpse(this->corpse_db_id, bag_item_data[i]->equip_slot, bag_item_data[i]->item_id);
/* Delete Item Instance */
RemoveItem(bag_item_data[i]);
RemoveItem(bag_item_data[i]);
}
}
}
@@ -1265,23 +1223,16 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) {
SetPlayerKillItemID(0);
}
/* Send message with item link to groups and such */
Client::TextLink linker;
linker.SetLinkType(linker.linkItemInst);
linker.SetItemInst(inst);
linker.SetClientVersion(client->GetClientVersion());
/* Send message with item link to groups and such */
Client::TextLink linker;
linker.SetLinkType(linker.linkItemInst);
linker.SetItemInst(inst);
auto item_link = linker.GenerateLink();
client->Message_StringID(MT_LootMessages, LOOTED_MESSAGE, item_link.c_str());
if(!IsPlayerCorpse()) {
// When sending to multiple/unknown client types, we set for the highest client..
// ..which is processed when 'EQClientUnknown,' or default value, is selected.
// This should help with any current issues..or it may create more! O.o
linker.SetClientVersion(EQClientUnknown);
item_link = linker.GenerateLink();
if (!IsPlayerCorpse()) {
Group *g = client->GetGroup();
if(g != nullptr) {
g->GroupMessage_StringID(client, MT_LootMessages, OTHER_LOOTED_MESSAGE, client->GetName(), item_link.c_str());
@@ -1333,9 +1284,12 @@ void Corpse::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
ns->spawn.NPC = 3;
else
ns->spawn.NPC = 2;
UpdateActiveLightValue();
ns->spawn.light = active_light;
}
void Corpse::QueryLoot(Client* to) {
void Corpse::QueryLoot(Client* to) {
int x = 0, y = 0; // x = visible items, y = total items
to->Message(0, "Coin: %ip, %ig, %is, %ic", platinum, gold, silver, copper);
@@ -1395,7 +1349,7 @@ bool Corpse::Summon(Client* client, bool spell, bool CheckDistance) {
client->Message(13, "That corpse is locked by a GM.");
return false;
}
if (!CheckDistance || (DistNoRootNoZ(*client) <= dist2)) {
if (!CheckDistance || (DistanceSquaredNoZ(m_Position, client->GetPosition()) <= dist2)) {
GMMove(client->GetX(), client->GetY(), client->GetZ());
is_corpse_changed = true;
}
@@ -1410,7 +1364,7 @@ bool Corpse::Summon(Client* client, bool spell, bool CheckDistance) {
std::list<std::string>::iterator itr;
for(itr = client->consent_list.begin(); itr != client->consent_list.end(); ++itr) {
if(strcmp(this->GetOwnerName(), itr->c_str()) == 0) {
if (!CheckDistance || (DistNoRootNoZ(*client) <= dist2)) {
if (!CheckDistance || (DistanceSquaredNoZ(m_Position, client->GetPosition()) <= dist2)) {
GMMove(client->GetX(), client->GetY(), client->GetZ());
is_corpse_changed = true;
}
@@ -1479,6 +1433,20 @@ uint32 Corpse::GetEquipmentColor(uint8 material_slot) const {
return 0;
}
void Corpse::UpdateEquipLightValue()
{
equip_light = NOT_USED;
for (auto iter = itemlist.begin(); iter != itemlist.end(); ++iter) {
if (((*iter)->equip_slot < EmuConstants::EQUIPMENT_BEGIN || (*iter)->equip_slot > EmuConstants::GENERAL_END) && (*iter)->equip_slot != MainPowerSource) { continue; }
auto item = database.GetItem((*iter)->item_id);
if (item == nullptr) { continue; }
if (item->ItemType != ItemTypeMisc && item->ItemType != ItemTypeLight) { continue; }
if (item->Light & 0xF0) { continue; }
if (item->Light > equip_light) { equip_light = item->Light; }
}
}
void Corpse::AddLooter(Mob* who) {
for (int i = 0; i < MAX_LOOTERS; i++) {
if (allowed_looters[i] == 0) {
+17 -18
View File
@@ -37,22 +37,19 @@ class Corpse : public Mob {
public:
static void SendEndLootErrorPacket(Client* client);
static void SendLootReqErrorPacket(Client* client, uint8 response = 2);
static void SendLootReqErrorPacket(Client* client, uint8 response = 2);
Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NPCType** in_npctypedata, uint32 in_decaytime = 600000);
Corpse(Client* client, int32 in_rezexp);
Corpse(uint32 in_corpseid, uint32 in_charid, const char* in_charname, ItemList* in_itemlist, uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_plat, float in_x, float in_y, float in_z, float in_heading, float in_size, uint8 in_gender, uint16 in_race, uint8 in_class, uint8 in_deity, uint8 in_level, uint8 in_texture, uint8 in_helmtexture, uint32 in_rezexp, bool wasAtGraveyard = false);
~Corpse();
static Corpse* LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std::string in_charname, float in_x, float in_y, float in_z, float in_heading, std::string time_of_death, bool rezzed, bool was_at_graveyard);
Corpse(uint32 in_corpseid, uint32 in_charid, const char* in_charname, ItemList* in_itemlist, uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_plat, const glm::vec4& position, float in_size, uint8 in_gender, uint16 in_race, uint8 in_class, uint8 in_deity, uint8 in_level, uint8 in_texture, uint8 in_helmtexture, uint32 in_rezexp, bool wasAtGraveyard = false);
~Corpse();
static Corpse* LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std::string in_charname, const glm::vec4& position, std::string time_of_death, bool rezzed, bool was_at_graveyard);
/* Corpse: General */
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) { return true; }
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false) { return; }
virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false,
bool IsStrikethrough = true, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) {
return false;
}
virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = true, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) { return false; }
virtual bool HasRaid() { return false; }
virtual bool HasGroup() { return false; }
virtual Raid* GetRaid() { return 0; }
@@ -73,7 +70,7 @@ class Corpse : public Mob {
uint32 GetDecayTime() { if (!corpse_decay_timer.Enabled()) return 0xFFFFFFFF; else return corpse_decay_timer.GetRemainingTime(); }
uint32 GetRezTime() { if (!corpse_rez_timer.Enabled()) return 0; else return corpse_rez_timer.GetRemainingTime(); }
void SetDecayTimer(uint32 decay_time);
void Delete();
void Bury();
void CalcCorpseName();
@@ -81,9 +78,9 @@ class Corpse : public Mob {
/* Corpse: Items */
uint32 GetWornItem(int16 equipSlot) const;
ServerLootItem_Struct* GetItem(uint16 lootslot, ServerLootItem_Struct** bag_item_data = 0);
ServerLootItem_Struct* GetItem(uint16 lootslot, ServerLootItem_Struct** bag_item_data = 0);
void SetPlayerKillItemID(int32 pk_item_id) { player_kill_item = pk_item_id; }
int32 GetPlayerKillItem() { return player_kill_item; }
int32 GetPlayerKillItem() { return player_kill_item; }
void RemoveItem(uint16 lootslot);
void RemoveItem(ServerLootItem_Struct* item_data);
void AddItem(uint32 itemnum, uint16 charges, int16 slot = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, uint8 attuned = 0);
@@ -123,13 +120,15 @@ class Corpse : public Mob {
bool Summon(Client* client, bool spell, bool CheckDistance);
void Spawn();
char corpse_name[64];
char corpse_name[64];
uint32 GetEquipment(uint8 material_slot) const;
uint32 GetEquipmentColor(uint8 material_slot) const;
inline int GetRezExp() { return rez_experience; }
inline int GetRezExp() { return rez_experience; }
virtual void UpdateEquipLightValue();
protected:
std::list<uint32> MoveItemToCorpse(Client *client, ItemInst *item, int16 equipslot);
void MoveItemToCorpse(Client *client, ItemInst *inst, int16 equipSlot, std::list<uint32> &removedList);
private:
bool is_player_corpse; /* Determines if Player Corpse or not */
@@ -139,7 +138,7 @@ private:
uint32 corpse_db_id; /* Corpse Database ID (Player Corpse) */
uint32 char_id; /* Character ID */
ItemList itemlist; /* Internal Item list used for corpses */
uint32 copper;
uint32 copper;
uint32 silver;
uint32 gold;
uint32 platinum;
@@ -152,7 +151,7 @@ private:
int allowed_looters[MAX_LOOTERS]; /* People allowed to loot the corpse, character id */
Timer corpse_decay_timer; /* The amount of time in millseconds in which a corpse will take to decay (Depop/Poof) */
Timer corpse_rez_timer; /* The amount of time in millseconds in which a corpse can be rezzed */
Timer corpse_delay_timer;
Timer corpse_delay_timer;
Timer corpse_graveyard_timer;
Timer loot_cooldown_timer; /* Delay between loot actions on the corpse entity */
Color_Struct item_tint[9];
+32 -66
View File
@@ -16,7 +16,8 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "../common/global_define.h"
#include "../common/eqemu_logsys.h"
#include "../common/string_util.h"
#include "client.h"
@@ -39,17 +40,15 @@
extern EntityList entity_list;
extern WorldServer worldserver;
Doors::Doors(const Door* door)
: close_timer(5000)
Doors::Doors(const Door* door) :
close_timer(5000),
m_Position(door->pos_x, door->pos_y, door->pos_z, door->heading),
m_Destination(door->dest_x, door->dest_y, door->dest_z, door->dest_heading)
{
db_id = door->db_id;
door_id = door->door_id;
strn0cpy(zone_name,door->zone_name,32);
strn0cpy(door_name,door->door_name,32);
pos_x = door->pos_x;
pos_y = door->pos_y;
pos_z = door->pos_z;
heading = door->heading;
incline = door->incline;
opentype = door->opentype;
guild_id = door->guild_id;
@@ -66,28 +65,22 @@ Doors::Doors(const Door* door)
close_timer.Disable();
strn0cpy(dest_zone,door->dest_zone,32);
strn0cpy(dest_zone,door->dest_zone,16);
dest_instance_id = door->dest_instance_id;
dest_x = door->dest_x;
dest_y = door->dest_y;
dest_z = door->dest_z;
dest_heading = door->dest_heading;
is_ldon_door = door->is_ldon_door;
client_version_mask = door->client_version_mask;
}
Doors::Doors(const char *dmodel, float dx, float dy, float dz, float dheading, uint8 dopentype, uint16 dsize)
: close_timer(5000)
Doors::Doors(const char *dmodel, const glm::vec4& position, uint8 dopentype, uint16 dsize) :
close_timer(5000),
m_Position(position),
m_Destination(glm::vec4())
{
db_id = database.GetDoorsCountPlusOne(zone->GetShortName(), zone->GetInstanceVersion());
door_id = database.GetDoorsDBCountPlusOne(zone->GetShortName(), zone->GetInstanceVersion());
strn0cpy(zone_name,zone->GetShortName(),32);
strn0cpy(door_name,dmodel,32);
pos_x = dx;
pos_y = dy;
pos_z = dz;
heading = dheading;
incline = 0;
opentype = dopentype;
guild_id = 0;
@@ -106,10 +99,6 @@ Doors::Doors(const char *dmodel, float dx, float dy, float dz, float dheading, u
strn0cpy(dest_zone,"NONE",32);
dest_instance_id = 0;
dest_x = 0;
dest_y = 0;
dest_z = 0;
dest_heading = 0;
is_ldon_door = 0;
client_version_mask = 4294967295u;
@@ -144,9 +133,9 @@ bool Doors::Process()
void Doors::HandleClick(Client* sender, uint8 trigger)
{
//door debugging info dump
_log(DOORS__INFO, "%s clicked door %s (dbid %d, eqid %d) at (%.4f,%.4f,%.4f @%.4f)", sender->GetName(), door_name, db_id, door_id, pos_x, pos_y, pos_z, heading);
_log(DOORS__INFO, " incline %d, opentype %d, lockpick %d, key %d, nokeyring %d, trigger %d type %d, param %d", incline, opentype, lockpick, keyitem, nokeyring, trigger_door, trigger_type, door_param);
_log(DOORS__INFO, " size %d, invert %d, dest: %s (%.4f,%.4f,%.4f @%.4f)", size, invert_state, dest_zone, dest_x, dest_y, dest_z, dest_heading);
Log.Out(Logs::Detail, Logs::Doors, "%s clicked door %s (dbid %d, eqid %d) at %s", sender->GetName(), door_name, db_id, door_id, to_string(m_Position).c_str());
Log.Out(Logs::Detail, Logs::Doors, " incline %d, opentype %d, lockpick %d, key %d, nokeyring %d, trigger %d type %d, param %d", incline, opentype, lockpick, keyitem, nokeyring, trigger_door, trigger_type, door_param);
Log.Out(Logs::Detail, Logs::Doors, " size %d, invert %d, dest: %s %s", size, invert_state, dest_zone, to_string(m_Destination).c_str());
EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct));
MoveDoor_Struct* md = (MoveDoor_Struct*)outapp->pBuffer;
@@ -301,9 +290,7 @@ void Doors::HandleClick(Client* sender, uint8 trigger)
float modskill=sender->GetSkill(SkillPickLock);
sender->CheckIncreaseSkill(SkillPickLock, nullptr, 1);
#if EQDEBUG>=5
LogFile->write(EQEMuLog::Debug, "Client has lockpicks: skill=%f", modskill);
#endif
Log.Out(Logs::General, Logs::Skills, "Client has lockpicks: skill=%f", modskill);
if(GetLockpick() <= modskill)
{
@@ -422,7 +409,7 @@ void Doors::HandleClick(Client* sender, uint8 trigger)
{
sender->KeyRingAdd(playerkey);
}
sender->MovePC(zone->GetZoneID(), zone->GetInstanceID(), dest_x, dest_y, dest_z, dest_heading);
sender->MovePC(zone->GetZoneID(), zone->GetInstanceID(), m_Destination.x, m_Destination.y, m_Destination.z, m_Destination.w);
}
else if (( !IsDoorOpen() || opentype == 58 ) && (keyneeded && ((keyneeded == playerkey) || sender->GetGM())))
{
@@ -432,22 +419,22 @@ void Doors::HandleClick(Client* sender, uint8 trigger)
}
if(database.GetZoneID(dest_zone) == zone->GetZoneID())
{
sender->MovePC(zone->GetZoneID(), zone->GetInstanceID(), dest_x, dest_y, dest_z, dest_heading);
sender->MovePC(zone->GetZoneID(), zone->GetInstanceID(), m_Destination.x, m_Destination.y, m_Destination.z, m_Destination.w);
}
else
{
sender->MovePC(database.GetZoneID(dest_zone), dest_instance_id, dest_x, dest_y, dest_z, dest_heading);
sender->MovePC(database.GetZoneID(dest_zone), dest_instance_id, m_Destination.x, m_Destination.y, m_Destination.z, m_Destination.w);
}
}
if (( !IsDoorOpen() || opentype == 58 ) && (!keyneeded))
{
if(database.GetZoneID(dest_zone) == zone->GetZoneID())
{
sender->MovePC(zone->GetZoneID(), zone->GetInstanceID(), dest_x, dest_y, dest_z, dest_heading);
sender->MovePC(zone->GetZoneID(), zone->GetInstanceID(), m_Destination.x, m_Destination.y, m_Destination.z, m_Destination.w);
}
else
{
sender->MovePC(database.GetZoneID(dest_zone), dest_instance_id, dest_x, dest_y, dest_z, dest_heading);
sender->MovePC(database.GetZoneID(dest_zone), dest_instance_id, m_Destination.x, m_Destination.y, m_Destination.z, m_Destination.w);
}
}
}
@@ -559,15 +546,15 @@ void Doors::ToggleState(Mob *sender)
}
void Doors::DumpDoor(){
LogFile->write(EQEMuLog::Debug,
"db_id:%i door_id:%i zone_name:%s door_name:%s pos_x:%f pos_y:%f pos_z:%f heading:%f",
db_id, door_id, zone_name, door_name, pos_x, pos_y, pos_z, heading);
LogFile->write(EQEMuLog::Debug,
Log.Out(Logs::General, Logs::None,
"db_id:%i door_id:%i zone_name:%s door_name:%s %s",
db_id, door_id, zone_name, door_name, to_string(m_Position).c_str());
Log.Out(Logs::General, Logs::None,
"opentype:%i guild_id:%i lockpick:%i keyitem:%i nokeyring:%i trigger_door:%i trigger_type:%i door_param:%i open:%s",
opentype, guild_id, lockpick, keyitem, nokeyring, trigger_door, trigger_type, door_param, (isopen) ? "open":"closed");
LogFile->write(EQEMuLog::Debug,
"dest_zone:%s dest_x:%f dest_y:%f dest_z:%f dest_heading:%f",
dest_zone, dest_x, dest_y, dest_z, dest_heading);
Log.Out(Logs::General, Logs::None,
"dest_zone:%s destination:%s ",
dest_zone, to_string(m_Destination).c_str());
}
int32 ZoneDatabase::GetDoorsCount(uint32* oMaxID, const char *zone_name, int16 version) {
@@ -577,7 +564,6 @@ int32 ZoneDatabase::GetDoorsCount(uint32* oMaxID, const char *zone_name, int16 v
zone_name, version);
auto results = QueryDatabase(query);
if (!results.Success()) {
std::cerr << "Error in GetDoorsCount query '" << query << "' " << results.ErrorMessage() << std::endl;
return -1;
}
@@ -604,7 +590,6 @@ int32 ZoneDatabase::GetDoorsCountPlusOne(const char *zone_name, int16 version) {
"WHERE zone = '%s' AND version = %u", zone_name, version);
auto results = QueryDatabase(query);
if (!results.Success()) {
std::cerr << "Error in GetDoorsCountPlusOne query '" << query << "' " << results.ErrorMessage() << std::endl;
return -1;
}
@@ -628,7 +613,6 @@ int32 ZoneDatabase::GetDoorsDBCountPlusOne(const char *zone_name, int16 version)
zone_name, version);
auto results = QueryDatabase(query);
if (!results.Success()) {
std::cerr << "Error in GetDoorsCountPlusOne query '" << query << "' " << results.ErrorMessage() << std::endl;
return -1;
}
@@ -644,7 +628,7 @@ int32 ZoneDatabase::GetDoorsDBCountPlusOne(const char *zone_name, int16 version)
}
bool ZoneDatabase::LoadDoors(int32 iDoorCount, Door *into, const char *zone_name, int16 version) {
LogFile->write(EQEMuLog::Status, "Loading Doors from database...");
Log.Out(Logs::General, Logs::Status, "Loading Doors from database...");
// Door tmpDoor;
@@ -656,7 +640,6 @@ bool ZoneDatabase::LoadDoors(int32 iDoorCount, Door *into, const char *zone_name
"ORDER BY doorid asc", zone_name, version);
auto results = QueryDatabase(query);
if (!results.Success()){
std::cerr << "Error in DBLoadDoors query '" << query << "' " << results.ErrorMessage() << std::endl;
return false;
}
@@ -709,30 +692,13 @@ bool ZoneDatabase::LoadDoors(int32 iDoorCount, Door *into, const char *zone_name
void Doors::SetLocation(float x, float y, float z)
{
entity_list.DespawnAllDoors();
pos_x = x;
pos_y = y;
pos_z = z;
m_Position = glm::vec4(x, y, z, m_Position.w);
entity_list.RespawnAllDoors();
}
void Doors::SetX(float in) {
void Doors::SetPosition(const glm::vec4& position) {
entity_list.DespawnAllDoors();
pos_x = in;
entity_list.RespawnAllDoors();
}
void Doors::SetY(float in) {
entity_list.DespawnAllDoors();
pos_y = in;
entity_list.RespawnAllDoors();
}
void Doors::SetZ(float in) {
entity_list.DespawnAllDoors();
pos_z = in;
entity_list.RespawnAllDoors();
}
void Doors::SetHeading(float in) {
entity_list.DespawnAllDoors();
heading = in;
m_Position = position;
entity_list.RespawnAllDoors();
}
@@ -767,6 +733,6 @@ void Doors::CreateDatabaseEntry()
{
return;
}
database.InsertDoor(GetDoorDBID(), GetDoorID(), GetDoorName(), GetX(), GetY(), GetZ(), GetHeading(), GetOpenType(), GetGuildID(), GetLockpick(), GetKeyItem(), GetDoorParam(), GetInvertState(), GetIncline(), GetSize());
database.InsertDoor(GetDoorDBID(), GetDoorID(), GetDoorName(), m_Position, GetOpenType(), GetGuildID(), GetLockpick(), GetKeyItem(), GetDoorParam(), GetInvertState(), GetIncline(), GetSize());
}
+7 -22
View File
@@ -17,7 +17,7 @@ class Doors : public Entity
{
public:
Doors(const Door* door);
Doors(const char *dmodel, float dx, float dy, float dz, float dheading, uint8 dopentype = 58, uint16 dsize = 100);
Doors(const char *dmodel, const glm::vec4& position, uint8 dopentype = 58, uint16 dsize = 100);
~Doors();
bool IsDoor() const { return true; }
void HandleClick(Client* sender, uint8 trigger);
@@ -29,10 +29,7 @@ public:
char* GetDoorName() { return door_name; }
uint32 GetDoorParam() { return door_param; }
int GetInvertState() { return invert_state; }
float GetX() { return pos_x; }
float GetY() { return pos_y; }
float GetZ() { return pos_z; }
float GetHeading() { return heading; }
const glm::vec4& GetPosition() const{ return m_Position; }
int GetIncline() { return incline; }
bool triggered;
void SetOpenState(bool st) { isopen = st; }
@@ -54,10 +51,7 @@ public:
void SetEntityID(uint32 entity) { entity_id = entity; }
void DumpDoor();
float GetDestX() { return dest_x; }
float GetDestY() { return dest_y; }
float GetDestZ() { return dest_z; }
float GetDestHeading() { return dest_heading; }
const glm::vec4 GetDestination() const { return m_Destination; }
uint8 IsLDoNDoor() { return is_ldon_door; }
uint32 GetClientVersionMask() { return client_version_mask; }
@@ -67,14 +61,11 @@ public:
void ForceClose(Mob *sender, bool alt_mode=false);
void ToggleState(Mob *sender);
void SetX(float in);
void SetY(float in);
void SetZ(float in);
void SetHeading(float in);
void SetPosition(const glm::vec4& position);
void SetLocation(float x, float y, float z);
void SetIncline(int in);
void SetDoorName(const char* name);
void SetOpenType(uint8 in);
void SetLocation(float x, float y, float z);
void SetSize(uint16 size);
void CreateDatabaseEntry();
@@ -84,10 +75,7 @@ private:
uint8 door_id;
char zone_name[32];
char door_name[32];
float pos_x;
float pos_y;
float pos_z;
float heading;
glm::vec4 m_Position;
int incline;
uint8 opentype;
uint32 guild_id;
@@ -106,10 +94,7 @@ private:
char dest_zone[16];
int dest_instance_id;
float dest_x;
float dest_y;
float dest_z;
float dest_heading;
glm::vec4 m_Destination;
uint8 is_ldon_door;
uint32 client_version_mask;
+14 -12
View File
@@ -16,7 +16,8 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "../common/global_define.h"
#include "../common/eqemu_logsys.h"
#include "../common/spdat.h"
#include "client.h"
@@ -26,6 +27,7 @@
#include "string_ids.h"
#include "worldserver.h"
#include "zonedb.h"
#include "position.h"
float Mob::GetActSpellRange(uint16 spell_id, float range, bool IsBard)
{
@@ -460,7 +462,7 @@ bool Client::TrainDiscipline(uint32 itemid) {
const Item_Struct *item = database.GetItem(itemid);
if(item == nullptr) {
Message(13, "Unable to find the tome you turned in!");
LogFile->write(EQEMuLog::Error, "Unable to find turned in tome id %lu\n", (unsigned long)itemid);
Log.Out(Logs::General, Logs::Error, "Unable to find turned in tome id %lu\n", (unsigned long)itemid);
return(false);
}
@@ -673,7 +675,7 @@ void EntityList::AETaunt(Client* taunter, float range)
zdiff *= -1;
if (zdiff < 10
&& taunter->IsAttackAllowed(them)
&& taunter->DistNoRootNoZ(*them) <= range) {
&& DistanceSquaredNoZ(taunter->GetPosition(), them->GetPosition()) <= range) {
if (taunter->CheckLosFN(them)) {
taunter->Taunt(them, true);
}
@@ -682,7 +684,7 @@ void EntityList::AETaunt(Client* taunter, float range)
}
}
// solar: causes caster to hit every mob within dist range of center with
// causes caster to hit every mob within dist range of center with
// spell_id.
// NPC spells will only affect other NPCs with compatible faction
void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster, int16 resist_adjust)
@@ -720,10 +722,10 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_
continue;
if (spells[spell_id].targettype == ST_Ring) {
dist_targ = curmob->DistNoRoot(caster->GetTargetRingX(), caster->GetTargetRingY(), caster->GetTargetRingZ());
dist_targ = DistanceSquared(static_cast<glm::vec3>(curmob->GetPosition()), caster->GetTargetRingLocation());
}
else if (center) {
dist_targ = center->DistNoRoot(*curmob);
dist_targ = DistanceSquared(curmob->GetPosition(), center->GetPosition());
}
if (dist_targ > dist2) //make sure they are in range
@@ -747,9 +749,9 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_
if (bad) {
if (!caster->IsAttackAllowed(curmob, true))
continue;
if (center && !center->CheckLosFN(curmob))
if (center && !spells[spell_id].npc_no_los && !center->CheckLosFN(curmob))
continue;
if (!center && !caster->CheckLosFN(caster->GetTargetRingX(), caster->GetTargetRingY(), caster->GetTargetRingZ(), curmob->GetSize()))
if (!center && !spells[spell_id].npc_no_los && !caster->CheckLosFN(caster->GetTargetRingX(), caster->GetTargetRingY(), caster->GetTargetRingZ(), curmob->GetSize()))
continue;
} else { // check to stop casting beneficial ae buffs (to wit: bard songs) on enemies...
// This does not check faction for beneficial AE buffs..only agro and attackable.
@@ -795,7 +797,7 @@ void EntityList::MassGroupBuff(Mob *caster, Mob *center, uint16 spell_id, bool a
continue;
if (curmob == caster && !affect_caster) //watch for caster too
continue;
if (center->DistNoRoot(*curmob) > dist2) //make sure they are in range
if (DistanceSquared(center->GetPosition(), curmob->GetPosition()) > dist2) //make sure they are in range
continue;
//Only npcs mgb should hit are client pets...
@@ -818,7 +820,7 @@ void EntityList::MassGroupBuff(Mob *caster, Mob *center, uint16 spell_id, bool a
}
}
// solar: causes caster to hit every mob within dist range of center with
// causes caster to hit every mob within dist range of center with
// a bard pulse of spell_id.
// NPC spells will only affect other NPCs with compatible faction
void EntityList::AEBardPulse(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster)
@@ -837,7 +839,7 @@ void EntityList::AEBardPulse(Mob *caster, Mob *center, uint16 spell_id, bool aff
continue;
if (curmob == caster && !affect_caster) //watch for caster too
continue;
if (center->DistNoRoot(*curmob) > dist2) //make sure they are in range
if (DistanceSquared(center->GetPosition(), curmob->GetPosition()) > dist2) //make sure they are in range
continue;
if (isnpc && curmob->IsNPC()) { //check npc->npc casting
FACTION_VALUE f = curmob->GetReverseFactionCon(caster);
@@ -887,7 +889,7 @@ void EntityList::AEAttack(Mob *attacker, float dist, int Hand, int count, bool I
&& curmob != attacker //this is not needed unless NPCs can use this
&&(attacker->IsAttackAllowed(curmob))
&& curmob->GetRace() != 216 && curmob->GetRace() != 472 /* dont attack horses */
&& (curmob->DistNoRoot(*attacker) <= dist2)
&& (DistanceSquared(curmob->GetPosition(), attacker->GetPosition()) <= dist2)
) {
attacker->Attack(curmob, Hand, false, false, IsFromSpell);
hit++;
+11 -3
View File
@@ -18,7 +18,7 @@
#ifdef EMBPERL
#include "../common/debug.h"
#include "../common/global_define.h"
#include "../common/seperator.h"
#include "../common/misc_functions.h"
#include "../common/string_util.h"
@@ -65,6 +65,7 @@ const char *QuestEventSubroutines[_LargestEventID] = {
"EVENT_AGGRO_SAY",
"EVENT_PLAYER_PICKUP",
"EVENT_POPUPRESPONSE",
"EVENT_ENVIRONMENTAL_DAMAGE",
"EVENT_PROXIMITY_SAY",
"EVENT_CAST",
"EVENT_CAST_BEGIN",
@@ -140,7 +141,7 @@ void PerlembParser::ReloadQuests() {
perl = nullptr;
}
LogFile->write(EQEMuLog::Status, "Error re-initializing perlembed: %s", e.what());
Log.Out(Logs::General, Logs::Status, "Error re-initializing perlembed: %s", e.what());
throw e.what();
}
@@ -1143,7 +1144,7 @@ void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID
ItemInst *inst = EQEmu::any_cast<ItemInst*>(extra_pointers->at(i));
std::string var_name = "item";
var_name += std::to_string(static_cast<long long>(i + 1));
var_name += std::to_string(i + 1);
if(inst) {
ExportVar(package_name.c_str(), var_name.c_str(), inst->GetItem()->ID);
@@ -1290,6 +1291,13 @@ void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID
ExportVar(package_name.c_str(), "popupid", data);
break;
}
case EVENT_ENVIRONMENTAL_DAMAGE:{
Seperator sep(data);
ExportVar(package_name.c_str(), "env_damage", sep.arg[0]);
ExportVar(package_name.c_str(), "env_damage_type", sep.arg[1]);
ExportVar(package_name.c_str(), "env_final_damage", sep.arg[2]);
break;
}
case EVENT_PROXIMITY_SAY: {
ExportVar(package_name.c_str(), "data", objid);
+60 -40
View File
@@ -21,8 +21,9 @@
#ifdef EMBPERL
#ifdef EMBPERL_XS
#include "../common/debug.h"
#include "../common/global_define.h"
#include "../common/misc_functions.h"
#include "../common/eqemu_logsys.h"
#include "embparser.h"
#include "embxs.h"
@@ -32,7 +33,7 @@
#include "zone.h"
extern Zone* zone;
extern QueryServ* QServ;
extern QueryServ* QServ;
/*
@@ -219,11 +220,9 @@ XS(XS__spawn)
int npc_type = (int)SvIV(ST(0));
int grid = (int)SvIV(ST(1));
int unused = (int)SvIV(ST(2));
float x = (float)SvNV(ST(3));
float y = (float)SvNV(ST(4));
float z = (float)SvNV(ST(5));
auto position = glm::vec4((float)SvNV(ST(3)), (float)SvNV(ST(4)), (float)SvNV(ST(5)), 0.0f);
Mob *r = quest_manager.spawn2(npc_type, grid, unused, x, y, z, 0);
Mob *r = quest_manager.spawn2(npc_type, grid, unused, position);
RETVAL = (r != nullptr) ? r->GetID() : 0;
XSprePUSH; PUSHu((UV)RETVAL);
@@ -243,12 +242,9 @@ XS(XS__spawn2)
int npc_type = (int)SvIV(ST(0));
int grid = (int)SvIV(ST(1));
int unused = (int)SvIV(ST(2));
float x = (float)SvNV(ST(3));
float y = (float)SvNV(ST(4));
float z = (float)SvNV(ST(5));
float heading = (float)SvNV(ST(6));
auto position = glm::vec4((float)SvNV(ST(3)), (float)SvNV(ST(4)), (float)SvNV(ST(5)), (float)SvNV(ST(6)));
Mob *r = quest_manager.spawn2(npc_type, grid, unused, x, y, z, heading);
Mob *r = quest_manager.spawn2(npc_type, grid, unused, position);
RETVAL = (r != nullptr) ? r->GetID() : 0;
XSprePUSH; PUSHu((UV)RETVAL);
@@ -275,7 +271,7 @@ XS(XS__unique_spawn)
if(items == 7)
heading = (float)SvNV(ST(6));
Mob *r = quest_manager.unique_spawn(npc_type, grid, unused, x, y, z, heading);
Mob *r = quest_manager.unique_spawn(npc_type, grid, unused, glm::vec4(x, y, z, heading));
RETVAL = (r != nullptr) ? r->GetID() : 0;
XSprePUSH; PUSHu((UV)RETVAL);
@@ -1175,7 +1171,7 @@ XS(XS__createguild)
Perl_croak(aTHX_ "Usage: createguild(guild_name, leader)");
char * guild_name = (char *)SvPV_nolen(ST(0));
char * leader = (char *)SvPV_nolen(ST(1));
char * leader = (char *)SvPV_nolen(ST(1));
quest_manager.CreateGuild(guild_name, leader);
@@ -1322,11 +1318,9 @@ XS(XS__rebind)
Perl_croak(aTHX_ "Usage: rebind(zoneid, x, y, z)");
int zoneid = (int)SvIV(ST(0));
float x = (float)SvNV(ST(1));
float y = (float)SvNV(ST(2));
float z = (float)SvNV(ST(3));
auto location = glm::vec3((float)SvNV(ST(1)),(float)SvNV(ST(2)),(float)SvNV(ST(3)));
quest_manager.rebind(zoneid, x, y, z);
quest_manager.rebind(zoneid, location);
XSRETURN_EMPTY;
}
@@ -1395,7 +1389,7 @@ XS(XS__moveto)
else
saveguard = false;
quest_manager.moveto(x, y, z, h, saveguard);
quest_manager.moveto(glm::vec4(x, y, z, h), saveguard);
XSRETURN_EMPTY;
}
@@ -1750,12 +1744,9 @@ XS(XS__summonburriedplayercorpse)
bool RETVAL;
uint32 char_id = (int)SvIV(ST(0));
float dest_x = (float)SvIV(ST(1));
float dest_y = (float)SvIV(ST(2));
float dest_z = (float)SvIV(ST(3));
float dest_heading = (float)SvIV(ST(4));
auto position = glm::vec4((float)SvIV(ST(1)), (float)SvIV(ST(2)), (float)SvIV(ST(3)),(float)SvIV(ST(4)));
RETVAL = quest_manager.summonburriedplayercorpse(char_id, dest_x, dest_y, dest_z, dest_heading);
RETVAL = quest_manager.summonburriedplayercorpse(char_id, position);
ST(0) = boolSV(RETVAL);
sv_2mortal(ST(0));
@@ -1771,12 +1762,9 @@ XS(XS__summonallplayercorpses)
bool RETVAL;
uint32 char_id = (int)SvIV(ST(0));
float dest_x = (float)SvIV(ST(1));
float dest_y = (float)SvIV(ST(2));
float dest_z = (float)SvIV(ST(3));
float dest_heading = (float)SvIV(ST(4));
auto position = glm::vec4((float)SvIV(ST(1)),(float)SvIV(ST(2)),(float)SvIV(ST(3)),(float)SvIV(ST(4)));
RETVAL = quest_manager.summonallplayercorpses(char_id, dest_x, dest_y, dest_z, dest_heading);
RETVAL = quest_manager.summonallplayercorpses(char_id, position);
ST(0) = boolSV(RETVAL);
sv_2mortal(ST(0));
@@ -2673,10 +2661,10 @@ XS(XS__CreateGroundObject)
uint16 id = 0;
if(items == 5)
id = quest_manager.CreateGroundObject(itemid, x, y, z, heading);
id = quest_manager.CreateGroundObject(itemid, glm::vec4(x, y, z, heading));
else{
uint32 decay_time = (uint32)SvIV(ST(5));
id = quest_manager.CreateGroundObject(itemid, x, y, z, heading, decay_time);
id = quest_manager.CreateGroundObject(itemid, glm::vec4(x, y, z, heading), decay_time);
}
XSRETURN_IV(id);
@@ -2704,7 +2692,7 @@ XS(XS__CreateGroundObjectFromModel)
if (items > 6)
decay_time = (uint32)SvIV(ST(6));
id = quest_manager.CreateGroundObjectFromModel(modelname, x, y, z, heading, type, decay_time);
id = quest_manager.CreateGroundObjectFromModel(modelname, glm::vec4(x, y, z, heading), type, decay_time);
XSRETURN_IV(id);
}
@@ -2979,12 +2967,12 @@ XS(XS__MovePCInstance)
if (items == 4)
{
quest_manager.MovePCInstance(zoneid, instanceid, x, y, z, 0.0f);
quest_manager.MovePCInstance(zoneid, instanceid, glm::vec4(x, y, z, 0.0f));
}
else
{
float heading = (float)SvNV(ST(5));
quest_manager.MovePCInstance(zoneid, instanceid, x, y, z, heading);
quest_manager.MovePCInstance(zoneid, instanceid, glm::vec4(x, y, z, heading));
}
XSRETURN_EMPTY;
@@ -3294,7 +3282,7 @@ XS(XS__GetZoneID)
char *zone = (char *)SvPV_nolen(ST(0));
int32 id = quest_manager.GetZoneID(zone);
XSRETURN_IV(id);
}
@@ -3307,7 +3295,7 @@ XS(XS__GetZoneLongName)
dXSTARG;
char *zone = (char *)SvPV_nolen(ST(0));
Const_char* RETVAL = quest_manager.GetZoneLongName(zone);
sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG;
XSRETURN(1);
}
@@ -3437,7 +3425,7 @@ XS(XS__clear_npctype_cache)
int32 npctype_id = (int32)SvIV(ST(0));
quest_manager.ClearNPCTypeCache(npctype_id);
}
XSRETURN_EMPTY;
}
@@ -3460,11 +3448,11 @@ XS(XS__qs_player_event);
XS(XS__qs_player_event)
{
dXSARGS;
if (items != 2){
if (items != 2){
Perl_croak(aTHX_ "Usage: qs_player_event(char_id, event_desc)");
}
else{
int char_id = (int)SvIV(ST(0));
int char_id = (int)SvIV(ST(0));
std::string event_desc = (std::string)SvPV_nolen(ST(1));
QServ->PlayerLogEvent(Player_Log_Quest, char_id, event_desc);
}
@@ -3499,13 +3487,44 @@ XS(XS__crosszonesignalnpcbynpctypeid)
if (items == 2) {
uint32 npctype_id = (uint32)SvIV(ST(0));
uint32 data = (uint32)SvIV(ST(1));
uint32 data = (uint32)SvIV(ST(1));
quest_manager.CrossZoneSignalNPCByNPCTypeID(npctype_id, data);
}
XSRETURN_EMPTY;
}
XS(XS__debug);
XS(XS__debug)
{
dXSARGS;
if (items != 1 && items != 2){
Perl_croak(aTHX_ "Usage: debug(message, [debug_level])");
}
else{
std::string log_message = (std::string)SvPV_nolen(ST(0));
uint8 debug_level = 1;
if (items == 2)
debug_level = (uint8)SvIV(ST(1));
if (debug_level > Logs::Detail)
return;
if (debug_level == Logs::General){
Log.Out(Logs::General, Logs::QuestDebug, log_message);
}
else if (debug_level == Logs::Moderate){
Log.Out(Logs::Moderate, Logs::QuestDebug, log_message);
}
else if (debug_level == Logs::Detail){
Log.Out(Logs::Detail, Logs::QuestDebug, log_message);
}
}
XSRETURN_EMPTY;
}
/*
This is the callback perl will look for to setup the
quest package's XSUBs
@@ -3519,7 +3538,7 @@ EXTERN_C XS(boot_quest)
file[255] = '\0';
if(items != 1)
LogFile->write(EQEMuLog::Error, "boot_quest does not take any arguments.");
Log.Out(Logs::General, Logs::Error, "boot_quest does not take any arguments.");
char buf[128]; //shouldent have any function names longer than this.
@@ -3592,6 +3611,7 @@ EXTERN_C XS(boot_quest)
newXS(strcpy(buf, "crosszonesignalclientbycharid"), XS__crosszonesignalclientbycharid, file);
newXS(strcpy(buf, "crosszonesignalclientbyname"), XS__crosszonesignalclientbyname, file);
newXS(strcpy(buf, "crosszonesignalnpcbynpctypeid"), XS__crosszonesignalnpcbynpctypeid, file);
newXS(strcpy(buf, "debug"), XS__debug, file);
newXS(strcpy(buf, "delglobal"), XS__delglobal, file);
newXS(strcpy(buf, "depop"), XS__depop, file);
newXS(strcpy(buf, "depop_withtimer"), XS__depop_withtimer, file);
+7 -6
View File
@@ -10,7 +10,8 @@ Eglin
#ifdef EMBPERL
#include "../common/debug.h"
#include "../common/global_define.h"
#include "../common/eqemu_logsys.h"
#include <cstdio>
#include <cstdarg>
#include <vector>
@@ -139,12 +140,12 @@ void Embperl::DoInit() {
catch(const char *err)
{
//remember... lasterr() is no good if we crap out here, in construction
LogFile->write(EQEMuLog::Quest, "perl error: %s", err);
Log.Out(Logs::General, Logs::Quests, "perl error: %s", err);
throw "failed to install eval_file hook";
}
#ifdef EMBPERL_IO_CAPTURE
LogFile->write(EQEMuLog::Quest, "Tying perl output to eqemu logs");
Log.Out(Logs::General, Logs::Quests, "Tying perl output to eqemu logs");
//make a tieable class to capture IO and pass it into EQEMuLog
eval_pv(
"package EQEmuIO; "
@@ -169,14 +170,14 @@ void Embperl::DoInit() {
,FALSE
);
LogFile->write(EQEMuLog::Quest, "Loading perlemb plugins.");
Log.Out(Logs::General, Logs::Quests, "Loading perlemb plugins.");
try
{
eval_pv("main::eval_file('plugin', 'plugin.pl');", FALSE);
}
catch(const char *err)
{
LogFile->write(EQEMuLog::Quest, "Warning - plugin.pl: %s", err);
Log.Out(Logs::General, Logs::Quests, "Warning - plugin.pl: %s", err);
}
try
{
@@ -194,7 +195,7 @@ void Embperl::DoInit() {
}
catch(const char *err)
{
LogFile->write(EQEMuLog::Quest, "Perl warning: %s", err);
Log.Out(Logs::General, Logs::Quests, "Perl warning: %s", err);
}
#endif //EMBPERL_PLUGIN
in_use = false;
+8 -4
View File
@@ -17,7 +17,8 @@
*/
#ifdef EMBPERL
#include "../common/debug.h"
#include "../common/global_define.h"
#include "../common/eqemu_logsys.h"
#include "masterentity.h"
#include "command.h"
@@ -63,7 +64,7 @@ EXTERN_C XS(boot_qc)
file[255] = '\0';
if(items != 1)
LogFile->write(EQEMuLog::Error, "boot_qc does not take any arguments.");
Log.Out(Logs::General, Logs::Error, "boot_qc does not take any arguments.");
char buf[128]; //shouldent have any function names longer than this.
@@ -91,12 +92,15 @@ XS(XS_EQEmuIO_PRINT)
char *str = SvPV_nolen(ST(r));
char *cur = str;
/* Strip newlines from log message 'str' */
*std::remove(str, str + strlen(str), '\n') = '\0';
int i;
int pos = 0;
int len = 0;
for(i = 0; *cur != '\0'; i++, cur++) {
if(*cur == '\n') {
LogFile->writebuf(EQEMuLog::Quest, str + pos, 1, len);
Log.Out(Logs::General, Logs::Quests, str);
len = 0;
pos = i+1;
} else {
@@ -104,7 +108,7 @@ XS(XS_EQEmuIO_PRINT)
}
}
if(len > 0) {
LogFile->writebuf(EQEMuLog::Quest, str + pos, 1, len);
Log.Out(Logs::General, Logs::Quests, str);
}
}
+162 -237
View File
@@ -15,7 +15,7 @@
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/debug.h"
#include "../common/global_define.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
@@ -71,23 +71,22 @@ Entity::Entity()
Entity::~Entity()
{
}
Client *Entity::CastToClient()
{
if (this == 0x00) {
std::cout << "CastToClient error (nullptr)" << std::endl;
DebugBreak();
Log.Out(Logs::General, Logs::Error, "CastToClient error (nullptr)");
return 0;
}
#ifdef _EQDEBUG
if (!IsClient()) {
std::cout << "CastToClient error (not client?)" << std::endl;
DebugBreak();
Log.Out(Logs::General, Logs::Error, "CastToClient error (not client)");
return 0;
}
#endif
return static_cast<Client *>(this);
}
@@ -95,8 +94,7 @@ NPC *Entity::CastToNPC()
{
#ifdef _EQDEBUG
if (!IsNPC()) {
std::cout << "CastToNPC error" << std::endl;
DebugBreak();
Log.Out(Logs::General, Logs::Error, "CastToNPC error (Not NPC)");
return 0;
}
#endif
@@ -108,7 +106,6 @@ Mob *Entity::CastToMob()
#ifdef _EQDEBUG
if (!IsMob()) {
std::cout << "CastToMob error" << std::endl;
DebugBreak();
return 0;
}
#endif
@@ -120,7 +117,6 @@ Merc *Entity::CastToMerc()
#ifdef _EQDEBUG
if (!IsMerc()) {
std::cout << "CastToMerc error" << std::endl;
DebugBreak();
return 0;
}
#endif
@@ -132,7 +128,6 @@ Trap *Entity::CastToTrap()
{
#ifdef DEBUG
if (!IsTrap()) {
//std::cout << "CastToTrap error" << std::endl;
return 0;
}
#endif
@@ -144,7 +139,6 @@ Corpse *Entity::CastToCorpse()
#ifdef _EQDEBUG
if (!IsCorpse()) {
std::cout << "CastToCorpse error" << std::endl;
DebugBreak();
return 0;
}
#endif
@@ -156,7 +150,6 @@ Object *Entity::CastToObject()
#ifdef _EQDEBUG
if (!IsObject()) {
std::cout << "CastToObject error" << std::endl;
DebugBreak();
return 0;
}
#endif
@@ -167,7 +160,6 @@ Object *Entity::CastToObject()
#ifdef _EQDEBUG
if(!IsGroup()) {
std::cout << "CastToGroup error" << std::endl;
DebugBreak();
return 0;
}
#endif
@@ -188,13 +180,11 @@ const Client *Entity::CastToClient() const
{
if (this == 0x00) {
std::cout << "CastToClient error (nullptr)" << std::endl;
DebugBreak();
return 0;
}
#ifdef _EQDEBUG
if (!IsClient()) {
std::cout << "CastToClient error (not client?)" << std::endl;
DebugBreak();
return 0;
}
#endif
@@ -206,7 +196,6 @@ const NPC *Entity::CastToNPC() const
#ifdef _EQDEBUG
if (!IsNPC()) {
std::cout << "CastToNPC error" << std::endl;
DebugBreak();
return 0;
}
#endif
@@ -218,7 +207,6 @@ const Mob *Entity::CastToMob() const
#ifdef _EQDEBUG
if (!IsMob()) {
std::cout << "CastToMob error" << std::endl;
DebugBreak();
return 0;
}
#endif
@@ -230,7 +218,6 @@ const Merc *Entity::CastToMerc() const
#ifdef _EQDEBUG
if (!IsMerc()) {
std::cout << "CastToMerc error" << std::endl;
DebugBreak();
return 0;
}
#endif
@@ -241,7 +228,6 @@ const Trap *Entity::CastToTrap() const
{
#ifdef DEBUG
if (!IsTrap()) {
//std::cout << "CastToTrap error" << std::endl;
return 0;
}
#endif
@@ -253,7 +239,6 @@ const Corpse *Entity::CastToCorpse() const
#ifdef _EQDEBUG
if (!IsCorpse()) {
std::cout << "CastToCorpse error" << std::endl;
DebugBreak();
return 0;
}
#endif
@@ -265,7 +250,6 @@ const Object *Entity::CastToObject() const
#ifdef _EQDEBUG
if (!IsObject()) {
std::cout << "CastToObject error" << std::endl;
DebugBreak();
return 0;
}
#endif
@@ -288,7 +272,6 @@ Bot *Entity::CastToBot()
#ifdef _EQDEBUG
if (!IsBot()) {
std::cout << "CastToBot error" << std::endl;
DebugBreak();
return 0;
}
#endif
@@ -374,7 +357,7 @@ void EntityList::CheckGroupList (const char *fname, const int fline)
{
if (*it == nullptr)
{
LogFile->write(EQEMuLog::Error, "nullptr group, %s:%i", fname, fline);
Log.Out(Logs::General, Logs::Error, "nullptr group, %s:%i", fname, fline);
}
}
}
@@ -389,11 +372,8 @@ void EntityList::GroupProcess()
return;
}
auto it = group_list.begin();
while (it != group_list.end()) {
(*it)->Process();
++it;
}
for (auto &group : group_list)
group->Process();
#if EQDEBUG >= 5
CheckGroupList (__FILE__, __LINE__);
@@ -402,11 +382,8 @@ void EntityList::GroupProcess()
void EntityList::QueueToGroupsForNPCHealthAA(Mob *sender, const EQApplicationPacket *app)
{
auto it = group_list.begin();
while (it != group_list.end()) {
(*it)->QueueHPPacketsForNPCHealthAA(sender, app);
++it;
}
for (auto &group : group_list)
group->QueueHPPacketsForNPCHealthAA(sender, app);
}
void EntityList::RaidProcess()
@@ -419,11 +396,8 @@ void EntityList::RaidProcess()
return;
}
auto it = raid_list.begin();
while (it != raid_list.end()) {
(*it)->Process();
++it;
}
for (auto &raid : raid_list)
raid->Process();
}
void EntityList::DoorProcess()
@@ -496,14 +470,14 @@ void EntityList::MobProcess()
while (it != mob_list.end()) {
uint16 id = it->first;
Mob *mob = it->second;
size_t sz = mob_list.size();
bool p_val = mob->Process();
size_t a_sz = mob_list.size();
if(a_sz > sz) {
//increased size can potentially screw with iterators so reset it to current value
//if buckets are re-orderered we may skip a process here and there but since
//if buckets are re-orderered we may skip a process here and there but since
//process happens so often it shouldn't matter much
it = mob_list.find(id);
++it;
@@ -527,17 +501,17 @@ void EntityList::MobProcess()
#ifdef _WINDOWS
struct in_addr in;
in.s_addr = mob->CastToClient()->GetIP();
std::cout << "Dropping client: Process=false, ip=" << inet_ntoa(in) << ", port=" << mob->CastToClient()->GetPort() << std::endl;
Log.Out(Logs::General, Logs::Zone_Server, "Dropping client: Process=false, ip=%s port=%u", inet_ntoa(in), mob->CastToClient()->GetPort());
#endif
zone->StartShutdownTimer();
Group *g = GetGroupByMob(mob);
if(g) {
LogFile->write(EQEMuLog::Error, "About to delete a client still in a group.");
Log.Out(Logs::General, Logs::Error, "About to delete a client still in a group.");
g->DelMember(mob);
}
Raid *r = entity_list.GetRaidByClient(mob->CastToClient());
if(r) {
LogFile->write(EQEMuLog::Error, "About to delete a client still in a raid.");
Log.Out(Logs::General, Logs::Error, "About to delete a client still in a raid.");
r->MemberZoned(mob->CastToClient());
}
entity_list.RemoveClient(id);
@@ -569,7 +543,7 @@ void EntityList::AddGroup(Group *group)
uint32 gid = worldserver.NextGroupID();
if (gid == 0) {
LogFile->write(EQEMuLog::Error,
Log.Out(Logs::General, Logs::Error,
"Unable to get new group ID from world server. group is going to be broken.");
return;
}
@@ -598,7 +572,7 @@ void EntityList::AddRaid(Raid *raid)
uint32 gid = worldserver.NextGroupID();
if (gid == 0) {
LogFile->write(EQEMuLog::Error,
Log.Out(Logs::General, Logs::Error,
"Unable to get new group ID from world server. group is going to be broken.");
return;
}
@@ -665,7 +639,7 @@ void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue)
} else {
NewSpawn_Struct *ns = new NewSpawn_Struct;
memset(ns, 0, sizeof(NewSpawn_Struct));
npc->FillSpawnStruct(ns, 0); // Not working on player newspawns, so it's safe to use a ForWho of 0
npc->FillSpawnStruct(ns, nullptr); // Not working on player newspawns, so it's safe to use a ForWho of 0
AddToSpawnQueue(npc->GetID(), &ns);
safe_delete(ns);
}
@@ -872,10 +846,11 @@ bool EntityList::MakeDoorSpawnPacket(EQApplicationPacket *app, Client *client)
strlen(door->GetDoorName()) > 3) {
memset(&nd, 0, sizeof(nd));
memcpy(nd.name, door->GetDoorName(), 32);
nd.xPos = door->GetX();
nd.yPos = door->GetY();
nd.zPos = door->GetZ();
nd.heading = door->GetHeading();
auto position = door->GetPosition();
nd.xPos = position.x;
nd.yPos = position.y;
nd.zPos = position.z;
nd.heading = position.w;
nd.incline = door->GetIncline();
nd.size = door->GetSize();
nd.doorId = door->GetDoorID();
@@ -1144,7 +1119,7 @@ void EntityList::ChannelMessage(Mob *from, uint8 chan_num, uint8 language,
filter = FilterAuctions;
//
// Only say is limited in range
if (chan_num != 8 || client->Dist(*from) < 200)
if (chan_num != 8 || Distance(client->GetPosition(), from->GetPosition()) < 200)
if (filter == FilterNone || client->GetFilter(filter) != FilterHide)
client->ChannelMessageSend(from->GetName(), 0, chan_num, language, lang_skill, buffer);
++it;
@@ -1467,7 +1442,7 @@ void EntityList::QueueCloseClients(Mob *sender, const EQApplicationPacket *app,
|| (filter2 == FilterShowGroupOnly && (sender == ent ||
(ent->GetGroup() && ent->GetGroup()->IsGroupMember(sender))))
|| (filter2 == FilterShowSelfOnly && ent == sender))
&& (ent->DistNoRoot(*sender) <= dist2)) {
&& (DistanceSquared(ent->GetPosition(), sender->GetPosition()) <= dist2)) {
ent->QueuePacket(app, ackreq, Client::CLIENT_CONNECTED);
}
}
@@ -1577,16 +1552,14 @@ Client *EntityList::GetClientByWID(uint32 iWID)
return nullptr;
}
Client *EntityList::GetRandomClient(float x, float y, float z, float Distance, Client *ExcludeClient)
Client *EntityList::GetRandomClient(const glm::vec3& location, float Distance, Client *ExcludeClient)
{
std::vector<Client *> ClientsInRange;
auto it = client_list.begin();
while (it != client_list.end()) {
if ((it->second != ExcludeClient) && (it->second->DistNoRoot(x, y, z) <= Distance))
for (auto it = client_list.begin();it != client_list.end(); ++it)
if ((it->second != ExcludeClient) && (DistanceSquared(static_cast<glm::vec3>(it->second->GetPosition()), location) <= Distance))
ClientsInRange.push_back(it->second);
++it;
}
if (ClientsInRange.empty())
return nullptr;
@@ -1611,7 +1584,7 @@ Corpse *EntityList::GetCorpseByOwnerWithinRange(Client *client, Mob *center, int
auto it = corpse_list.begin();
while (it != corpse_list.end()) {
if (it->second->IsPlayerCorpse())
if (center->DistNoRootNoZ(*it->second) < range &&
if (DistanceSquaredNoZ(center->GetPosition(), it->second->GetPosition()) < range &&
strcasecmp(it->second->GetOwnerName(), client->GetName()) == 0)
return it->second;
++it;
@@ -1948,7 +1921,7 @@ void EntityList::MessageClose_StringID(Mob *sender, bool skipsender, float dist,
for (auto it = client_list.begin(); it != client_list.end(); ++it) {
c = it->second;
if(c && c->DistNoRoot(*sender) <= dist2 && (!skipsender || c != sender))
if(c && DistanceSquared(c->GetPosition(), sender->GetPosition()) <= dist2 && (!skipsender || c != sender))
c->Message_StringID(type, string_id, message1, message2, message3, message4, message5, message6, message7, message8, message9);
}
}
@@ -1964,7 +1937,7 @@ void EntityList::FilteredMessageClose_StringID(Mob *sender, bool skipsender,
for (auto it = client_list.begin(); it != client_list.end(); ++it) {
c = it->second;
if (c && c->DistNoRoot(*sender) <= dist2 && (!skipsender || c != sender))
if (c && DistanceSquared(c->GetPosition(), sender->GetPosition()) <= dist2 && (!skipsender || c != sender))
c->FilteredMessage_StringID(sender, type, filter, string_id,
message1, message2, message3, message4, message5,
message6, message7, message8, message9);
@@ -2012,7 +1985,7 @@ void EntityList::MessageClose(Mob* sender, bool skipsender, float dist, uint32 t
auto it = client_list.begin();
while (it != client_list.end()) {
if (it->second->DistNoRoot(*sender) <= dist2 && (!skipsender || it->second != sender))
if (DistanceSquared(it->second->GetPosition(), sender->GetPosition()) <= dist2 && (!skipsender || it->second != sender))
it->second->Message(type, buffer);
++it;
}
@@ -2050,8 +2023,9 @@ void EntityList::RemoveAllMercs()
void EntityList::RemoveAllGroups()
{
while (group_list.size()) {
safe_delete(group_list.front());
auto group = group_list.front();
group_list.pop_front();
delete group;
}
#if EQDEBUG >= 5
CheckGroupList (__FILE__, __LINE__);
@@ -2061,8 +2035,9 @@ void EntityList::RemoveAllGroups()
void EntityList::RemoveAllRaids()
{
while (raid_list.size()) {
safe_delete(raid_list.front());
auto raid = raid_list.front();
raid_list.pop_front();
delete raid;
}
}
@@ -2266,44 +2241,30 @@ bool EntityList::RemoveCorpse(uint16 delete_id)
bool EntityList::RemoveGroup(uint32 delete_id)
{
std::list<Group *>::iterator iterator;
iterator = group_list.begin();
while(iterator != group_list.end())
{
if((*iterator)->GetID() == delete_id) {
safe_delete(*iterator);
group_list.remove(*iterator);
auto it = std::find_if(group_list.begin(), group_list.end(),
[delete_id](const Group *a) { return a->GetID() == delete_id; });
if (it == group_list.end()) {
#if EQDEBUG >= 5
CheckGroupList (__FILE__, __LINE__);
CheckGroupList (__FILE__, __LINE__);
#endif
return true;
}
++iterator;
return false;
}
#if EQDEBUG >= 5
CheckGroupList (__FILE__, __LINE__);
#endif
return false;
auto group = *it;
group_list.erase(it);
delete group;
return true;
}
bool EntityList::RemoveRaid(uint32 delete_id)
{
std::list<Raid *>::iterator iterator;
iterator = raid_list.begin();
while(iterator != raid_list.end())
{
if((*iterator)->GetID() == delete_id) {
safe_delete(*iterator);
raid_list.remove(*iterator);
return true;
}
++iterator;
}
return false;
auto it = std::find_if(raid_list.begin(), raid_list.end(),
[delete_id](const Raid *a) { return a->GetID() == delete_id; });
if (it == raid_list.end())
return false;
auto raid = *it;
raid_list.erase(it);
delete raid;
return true;
}
void EntityList::Clear()
@@ -2510,7 +2471,7 @@ void EntityList::SendPositionUpdates(Client *client, uint32 cLastUpdate,
//bool Grouped = client->HasGroup() && mob->IsClient() && (client->GetGroup() == mob->CastToClient()->GetGroup());
//if (range == 0 || (iterator.GetData() == alwayssend) || Grouped || (mob->DistNoRootNoZ(*client) <= range)) {
if (range == 0 || (it->second == alwayssend) || mob->IsClient() || (mob->DistNoRoot(*client) <= range)) {
if (range == 0 || (it->second == alwayssend) || mob->IsClient() || (DistanceSquared(mob->GetPosition(), client->GetPosition()) <= range)) {
mob->MakeSpawnUpdate(ppu);
}
if(mob && mob->IsClient() && mob->GetID()>0) {
@@ -2558,7 +2519,7 @@ char *EntityList::MakeNameUnique(char *name)
return name;
}
}
LogFile->write(EQEMuLog::Error, "Fatal error in EntityList::MakeNameUnique: Unable to find unique name for '%s'", name);
Log.Out(Logs::General, Logs::Error, "Fatal error in EntityList::MakeNameUnique: Unable to find unique name for '%s'", name);
char tmp[64] = "!";
strn0cpy(&tmp[1], name, sizeof(tmp) - 1);
strcpy(name, tmp);
@@ -2669,8 +2630,8 @@ void EntityList::FindPathsToAllNPCs()
auto it = npc_list.begin();
while (it != npc_list.end()) {
Map::Vertex Node0 = zone->pathing->GetPathNodeCoordinates(0, false);
Map::Vertex Dest(it->second->GetX(), it->second->GetY(), it->second->GetZ());
glm::vec3 Node0 = zone->pathing->GetPathNodeCoordinates(0, false);
glm::vec3 Dest(it->second->GetX(), it->second->GetY(), it->second->GetZ());
std::deque<int> Route = zone->pathing->FindRoute(Node0, Dest);
if (Route.size() == 0)
printf("Unable to find a route to %s\n", it->second->GetName());
@@ -2992,7 +2953,7 @@ bool EntityList::MakeTrackPacket(Client *client)
it->second->IsInvisible(client))
continue;
MobDistance = it->second->DistNoZ(*client);
MobDistance = DistanceNoZ(it->second->GetPosition(), client->GetPosition());
if (MobDistance > distance)
continue;
@@ -3041,7 +3002,8 @@ void EntityList::MessageGroup(Mob *sender, bool skipclose, uint32 type, const ch
auto it = client_list.begin();
while (it != client_list.end()) {
if (it->second != sender && (it->second->Dist(*sender) <= dist2 || it->second->GetGroup() == sender->CastToClient()->GetGroup())) {
if (it->second != sender &&
(Distance(it->second->GetPosition(), sender->GetPosition()) <= dist2 || it->second->GetGroup() == sender->CastToClient()->GetGroup())) {
it->second->Message(type, buffer);
}
++it;
@@ -3114,54 +3076,42 @@ void EntityList::AddHealAggro(Mob *target, Mob *caster, uint16 thedam)
void EntityList::OpenDoorsNear(NPC *who)
{
auto it = door_list.begin();
while (it != door_list.end()) {
for (auto it = door_list.begin();it != door_list.end(); ++it) {
Doors *cdoor = it->second;
if (cdoor && !cdoor->IsDoorOpen()) {
float zdiff = who->GetZ() - cdoor->GetZ();
if (zdiff < 0)
zdiff = 0 - zdiff;
float curdist = 0;
float tmp = who->GetX() - cdoor->GetX();
curdist += tmp * tmp;
tmp = who->GetY() - cdoor->GetY();
curdist += tmp * tmp;
if (zdiff < 10 && curdist <= 100)
cdoor->NPCOpen(who);
}
++it;
if (!cdoor || cdoor->IsDoorOpen())
continue;
auto diff = who->GetPosition() - cdoor->GetPosition();
float curdist = diff.x * diff.x + diff.y * diff.y;
if (diff.z * diff.z < 10 && curdist <= 100)
cdoor->NPCOpen(who);
}
}
void EntityList::SendAlarm(Trap *trap, Mob *currenttarget, uint8 kos)
{
float val2 = trap->effectvalue * trap->effectvalue;
float preSquareDistance = trap->effectvalue * trap->effectvalue;
auto it = npc_list.begin();
while (it != npc_list.end()) {
for (auto it = npc_list.begin();it != npc_list.end(); ++it) {
NPC *cur = it->second;
float curdist = 0;
float tmp = cur->GetX() - trap->x;
curdist += tmp*tmp;
tmp = cur->GetY() - trap->y;
curdist += tmp*tmp;
tmp = cur->GetZ() - trap->z;
curdist += tmp*tmp;
if (!cur->GetOwner() &&
/*!cur->CastToMob()->dead && */
!cur->IsEngaged() &&
curdist <= val2 )
{
if (kos) {
uint8 factioncon = currenttarget->GetReverseFactionCon(cur);
if (factioncon == FACTION_THREATENLY || factioncon == FACTION_SCOWLS) {
cur->AddToHateList(currenttarget,1);
}
} else {
auto diff = glm::vec3(cur->GetPosition()) - trap->m_Position;
float curdist = diff.x * diff.x + diff.y * diff.y + diff.z * diff.z;
if (cur->GetOwner() || cur->IsEngaged() || curdist > preSquareDistance )
continue;
if (kos) {
uint8 factioncon = currenttarget->GetReverseFactionCon(cur);
if (factioncon == FACTION_THREATENLY || factioncon == FACTION_SCOWLS) {
cur->AddToHateList(currenttarget,1);
}
}
++it;
else
cur->AddToHateList(currenttarget,1);
}
}
@@ -3171,21 +3121,18 @@ void EntityList::AddProximity(NPC *proximity_for)
proximity_list.push_back(proximity_for);
proximity_for->proximity = new NPCProximity;
proximity_for->proximity = new NPCProximity; // deleted in NPC::~NPC
}
bool EntityList::RemoveProximity(uint16 delete_npc_id)
{
auto iter = proximity_list.begin();
auto it = std::find_if(proximity_list.begin(), proximity_list.end(),
[delete_npc_id](const NPC *a) { return a->GetID() == delete_npc_id; });
if (it == proximity_list.end())
return false;
while (iter != proximity_list.end()) {
if ((*iter)->GetID() == delete_npc_id) {
proximity_list.erase(iter);
return true;
}
++iter;
}
return false;
proximity_list.erase(it);
return true;
}
void EntityList::RemoveAllLocalities()
@@ -3201,7 +3148,7 @@ struct quest_proximity_event {
int area_type;
};
void EntityList::ProcessMove(Client *c, float x, float y, float z)
void EntityList::ProcessMove(Client *c, const glm::vec3& location)
{
float last_x = c->ProximityX();
float last_y = c->ProximityY();
@@ -3223,9 +3170,9 @@ void EntityList::ProcessMove(Client *c, float x, float y, float z)
last_z < l->min_z || last_z > l->max_z) {
old_in = false;
}
if (x < l->min_x || x > l->max_x ||
y < l->min_y || y > l->max_y ||
z < l->min_z || z > l->max_z) {
if (location.x < l->min_x || location.x > l->max_x ||
location.y < l->min_y || location.y > l->max_y ||
location.z < l->min_z || location.z > l->max_z) {
new_in = false;
}
@@ -3258,9 +3205,9 @@ void EntityList::ProcessMove(Client *c, float x, float y, float z)
old_in = false;
}
if (x < a.min_x || x > a.max_x ||
y < a.min_y || y > a.max_y ||
z < a.min_z || z > a.max_z ) {
if (location.x < a.min_x || location.x > a.max_x ||
location.y < a.min_y || location.y > a.max_y ||
location.z < a.min_z || location.z > a.max_z ) {
new_in = false;
}
@@ -3388,14 +3335,12 @@ void EntityList::AddArea(int id, int type, float min_x, float max_x, float min_y
void EntityList::RemoveArea(int id)
{
auto iter = area_list.begin();
while(iter != area_list.end()) {
if((*iter).id == id) {
area_list.erase(iter);
return;
}
++iter;
}
auto it = std::find_if(area_list.begin(), area_list.end(),
[id](const Area &a) { return a.id == id; });
if (it == area_list.end())
return;
area_list.erase(it);
}
void EntityList::ClearAreas()
@@ -3451,7 +3396,7 @@ void EntityList::ReloadAllClientsTaskState(int TaskID)
// If we have been passed a TaskID, only reload the client state if they have
// that Task active.
if ((!TaskID) || (TaskID && client->IsTaskActive(TaskID))) {
_log(TASKS__CLIENTLOAD, "Reloading Task State For Client %s", client->GetName());
Log.Out(Logs::General, Logs::Tasks, "[CLIENTLOAD] Reloading Task State For Client %s", client->GetName());
client->RemoveClientTaskState();
client->LoadClientTaskState();
taskmanager->SendActiveTasksToClient(client);
@@ -3592,35 +3537,6 @@ bool EntityList::LimitCheckName(const char *npc_name)
return true;
}
void EntityList::RadialSetLogging(Mob *around, bool enabled, bool clients,
bool non_clients, float range)
{
float range2 = range * range;
auto it = mob_list.begin();
while (it != mob_list.end()) {
Mob *mob = it->second;
++it;
if (mob->IsClient()) {
if (!clients)
continue;
} else {
if (!non_clients)
continue;
}
if (around->DistNoRoot(*mob) > range2)
continue;
if (enabled)
mob->EnableLogging();
else
mob->DisableLogging();
}
}
void EntityList::UpdateHoTT(Mob *target)
{
auto it = client_list.begin();
@@ -3665,7 +3581,7 @@ int16 EntityList::CountTempPets(Mob *owner)
}
++it;
}
owner->SetTempPetCount(count);
return count;
@@ -3695,9 +3611,9 @@ bool Entity::CheckCoordLosNoZLeaps(float cur_x, float cur_y, float cur_z,
if (zone->zonemap == nullptr)
return true;
Map::Vertex myloc;
Map::Vertex oloc;
Map::Vertex hit;
glm::vec3 myloc;
glm::vec3 oloc;
glm::vec3 hit;
myloc.x = cur_x;
myloc.y = cur_y;
@@ -3731,7 +3647,7 @@ void EntityList::QuestJournalledSayClose(Mob *sender, Client *QuestInitiator,
// Use the old method for all other nearby clients
for (auto it = client_list.begin(); it != client_list.end(); ++it) {
c = it->second;
if(c && (c != QuestInitiator) && c->DistNoRoot(*sender) <= dist2)
if(c && (c != QuestInitiator) && DistanceSquared(c->GetPosition(), sender->GetPosition()) <= dist2)
c->Message_StringID(10, GENERIC_SAY, mobname, message);
}
}
@@ -3856,51 +3772,54 @@ void EntityList::GroupMessage(uint32 gid, const char *from, const char *message)
}
}
uint16 EntityList::CreateGroundObject(uint32 itemid, float x, float y, float z,
float heading, uint32 decay_time)
uint16 EntityList::CreateGroundObject(uint32 itemid, const glm::vec4& position, uint32 decay_time)
{
const Item_Struct *is = database.GetItem(itemid);
if (is) {
ItemInst *i = new ItemInst(is, is->MaxCharges);
if (i) {
Object *object = new Object(i, x, y, z, heading,decay_time);
entity_list.AddObject(object, true);
if (!is)
return 0;
safe_delete(i);
if (object)
return object->GetID();
}
return 0; // fell through itemstruct
}
return 0; // fell through everything, this is bad/incomplete from perl
ItemInst *i = new ItemInst(is, is->MaxCharges);
if (!i)
return 0;
Object *object = new Object(i, position.x, position.y, position.z, position.w,decay_time);
entity_list.AddObject(object, true);
safe_delete(i);
if (!object)
return 0;
return object->GetID();
}
uint16 EntityList::CreateGroundObjectFromModel(const char *model, float x,
float y, float z, float heading, uint8 type, uint32 decay_time)
uint16 EntityList::CreateGroundObjectFromModel(const char *model, const glm::vec4& position, uint8 type, uint32 decay_time)
{
if (model) {
Object *object = new Object(model, x, y, z, heading, type);
entity_list.AddObject(object, true);
if (!model)
return 0;
if (object)
return object->GetID();
}
return 0; // fell through everything, this is bad/incomplete from perl
Object *object = new Object(model, position.x, position.y, position.z, position.w, type);
entity_list.AddObject(object, true);
if (!object)
return 0;
return object->GetID();
}
uint16 EntityList::CreateDoor(const char *model, float x, float y, float z,
float heading, uint8 opentype, uint16 size)
uint16 EntityList::CreateDoor(const char *model, const glm::vec4& position, uint8 opentype, uint16 size)
{
if (model) {
Doors *door = new Doors(model, x, y, z, heading, opentype, size);
RemoveAllDoors();
zone->LoadZoneDoors(zone->GetShortName(), zone->GetInstanceVersion());
entity_list.AddDoor(door);
entity_list.RespawnAllDoors();
if (!model)
return 0; // fell through everything, this is bad/incomplete from perl
Doors *door = new Doors(model, position, opentype, size);
RemoveAllDoors();
zone->LoadZoneDoors(zone->GetShortName(), zone->GetInstanceVersion());
entity_list.AddDoor(door);
entity_list.RespawnAllDoors();
if (door)
return door->GetEntityID();
if (door)
return door->GetEntityID();
}
return 0; // fell through everything, this is bad/incomplete from perl
}
@@ -3930,7 +3849,7 @@ Mob *EntityList::GetTargetForMez(Mob *caster)
continue;
}
if (caster->DistNoRoot(*d) > 22250) { //only pick targets within 150 range
if (DistanceSquared(caster->GetPosition(), d->GetPosition()) > 22250) { //only pick targets within 150 range
++it;
continue;
}
@@ -4440,7 +4359,7 @@ void EntityList::UpdateFindableNPCState(NPC *n, bool Remove)
auto it = client_list.begin();
while (it != client_list.end()) {
Client *c = it->second;
if (c && (c->GetClientVersion() >= EQClientSoD))
if (c && (c->GetClientVersion() >= ClientVersion::SoD))
c->QueuePacket(outapp);
++it;
@@ -4558,7 +4477,6 @@ void EntityList::AddLootToNPCS(uint32 item_id, uint32 count)
void EntityList::CameraEffect(uint32 duration, uint32 intensity)
{
EQApplicationPacket* outapp = new EQApplicationPacket(OP_CameraEffect, sizeof(Camera_Struct));
memset(outapp->pBuffer, 0, sizeof(outapp->pBuffer));
Camera_Struct* cs = (Camera_Struct*) outapp->pBuffer;
cs->duration = duration; // Duration in milliseconds
cs->intensity = ((intensity * 6710886) + 1023410176); // Intensity ranges from 1023410176 to 1090519040, so simplify it from 0 to 10.
@@ -4723,3 +4641,10 @@ Mob *EntityList::GetTargetForVirus(Mob *spreader, int range)
return TargetsInRange[zone->random.Int(0, TargetsInRange.size() - 1)];
}
void EntityList::StopMobAI()
{
for (auto &mob : mob_list) {
mob.second->AI_Stop();
mob.second->AI_ShutDown();
}
}
+9 -8
View File
@@ -27,6 +27,7 @@
#include "../common/bodytypes.h"
#include "../common/eq_constants.h"
#include "position.h"
#include "zonedump.h"
class Beacon;
@@ -57,7 +58,7 @@ class Bot;
class BotRaids;
#endif
extern EntityList entity_list;
extern EntityList entity_list;
class Entity
{
@@ -154,7 +155,7 @@ public:
Client *GetClientByCharID(uint32 iCharID);
Client *GetClientByWID(uint32 iWID);
Client *GetClient(uint32 ip, uint16 port);
Client *GetRandomClient(float x, float y, float z, float Distance, Client *ExcludeClient = nullptr);
Client *GetRandomClient(const glm::vec3& location, float Distance, Client *ExcludeClient = nullptr);
Group *GetGroupByMob(Mob* mob);
Group *GetGroupByClient(Client* client);
Group *GetGroupByID(uint32 id);
@@ -202,7 +203,7 @@ public:
void MobProcess();
void TrapProcess();
void BeaconProcess();
void ProcessMove(Client *c, float x, float y, float z);
void ProcessMove(Client *c, const glm::vec3& location);
void ProcessMove(NPC *n, float x, float y, float z);
void AddArea(int id, int type, float min_x, float max_x, float min_y, float max_y, float min_z, float max_z);
void RemoveArea(int id);
@@ -268,6 +269,8 @@ public:
Entity *GetEntityMob(const char *name);
Entity *GetEntityCorpse(const char *name);
void StopMobAI();
void DescribeAggro(Client *towho, NPC *from_who, float dist, bool verbose);
void Message(uint32 to_guilddbid, uint32 type, const char* message, ...);
@@ -318,8 +321,6 @@ public:
void MassGroupBuff(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster = true);
void AEBardPulse(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster = true);
void RadialSetLogging(Mob *around, bool enabled, bool clients, bool non_clients, float range = 0);
//trap stuff
Mob* GetTrapTrigger(Trap* trap);
void SendAlarm(Trap* trap, Mob* currenttarget, uint8 kos);
@@ -391,9 +392,9 @@ public:
void SaveAllClientsTaskState();
void ReloadAllClientsTaskState(int TaskID=0);
uint16 CreateGroundObject(uint32 itemid, float x, float y, float z, float heading, uint32 decay_time = 300000);
uint16 CreateGroundObjectFromModel(const char *model, float x, float y, float z, float heading, uint8 type = 0x00, uint32 decay_time = 0);
uint16 CreateDoor(const char *model, float x, float y, float z, float heading, uint8 type = 0, uint16 size = 100);
uint16 CreateGroundObject(uint32 itemid, const glm::vec4& position, uint32 decay_time = 300000);
uint16 CreateGroundObjectFromModel(const char *model, const glm::vec4& position, uint8 type = 0x00, uint32 decay_time = 0);
uint16 CreateDoor(const char *model, const glm::vec4& position, uint8 type = 0, uint16 size = 100);
void ZoneWho(Client *c, Who_All_Struct* Who);
void UnMarkNPC(uint16 ID);
+1
View File
@@ -33,6 +33,7 @@ typedef enum {
EVENT_AGGRO_SAY,
EVENT_PLAYER_PICKUP,
EVENT_POPUP_RESPONSE,
EVENT_ENVIRONMENTAL_DAMAGE,
EVENT_PROXIMITY_SAY,
EVENT_CAST,
EVENT_CAST_BEGIN,
+6 -7
View File
@@ -16,7 +16,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "../common/global_define.h"
#include "../common/features.h"
#include "../common/rulesys.h"
#include "../common/string_util.h"
@@ -240,7 +240,7 @@ void Client::AddEXP(uint32 in_add_exp, uint8 conlevel, bool resexp) {
}
void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
_log(CLIENT__EXP, "Attempting to Set Exp for %s (XP: %u, AAXP: %u, Rez: %s)", this->GetCleanName(), set_exp, set_aaxp, isrezzexp ? "true" : "false");
Log.Out(Logs::Detail, Logs::None, "Attempting to Set Exp for %s (XP: %u, AAXP: %u, Rez: %s)", this->GetCleanName(), set_exp, set_aaxp, isrezzexp ? "true" : "false");
//max_AAXP = GetEXPForLevel(52) - GetEXPForLevel(51); //GetEXPForLevel() doesn't depend on class/race, just level, so it shouldn't change between Clients
max_AAXP = RuleI(AA, ExpPerPoint); //this may be redundant since we're doing this in Client::FinishConnState2()
if (max_AAXP == 0 || GetEXPForLevel(GetLevel()) == 0xFFFFFFFF) {
@@ -308,7 +308,7 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
//figure out how many AA points we get from the exp were setting
m_pp.aapoints = set_aaxp / max_AAXP;
_log(CLIENT__EXP, "Calculating additional AA Points from AAXP for %s: %u / %u = %.1f points", this->GetCleanName(), set_aaxp, max_AAXP, (float)set_aaxp / (float)max_AAXP);
Log.Out(Logs::Detail, Logs::None, "Calculating additional AA Points from AAXP for %s: %u / %u = %.1f points", this->GetCleanName(), set_aaxp, max_AAXP, (float)set_aaxp / (float)max_AAXP);
//get remainder exp points, set in PP below
set_aaxp = set_aaxp - (max_AAXP * m_pp.aapoints);
@@ -430,7 +430,7 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
void Client::SetLevel(uint8 set_level, bool command)
{
if (GetEXPForLevel(set_level) == 0xFFFFFFFF) {
LogFile->write(EQEMuLog::Error,"Client::SetLevel() GetEXPForLevel(%i) = 0xFFFFFFFF", set_level);
Log.Out(Logs::General, Logs::Error, "Client::SetLevel() GetEXPForLevel(%i) = 0xFFFFFFFF", set_level);
return;
}
@@ -488,7 +488,7 @@ void Client::SetLevel(uint8 set_level, bool command)
safe_delete(outapp);
this->SendAppearancePacket(AT_WhoLevel, set_level); // who level change
LogFile->write(EQEMuLog::Normal,"Setting Level for %s to %i", GetName(), set_level);
Log.Out(Logs::General, Logs::Normal, "Setting Level for %s to %i", GetName(), set_level);
CalcBonuses();
@@ -506,8 +506,7 @@ void Client::SetLevel(uint8 set_level, bool command)
SetMana(CalcMaxMana());
UpdateWho();
if(GetMerc())
UpdateMercLevel();
UpdateMercLevel();
Save();
}
+6 -14
View File
@@ -152,26 +152,24 @@ void Mob::CalculateNewFearpoint()
{
int Node = zone->pathing->GetRandomPathNode();
Map::Vertex Loc = zone->pathing->GetPathNodeCoordinates(Node);
glm::vec3 Loc = zone->pathing->GetPathNodeCoordinates(Node);
++Loc.z;
Map::Vertex CurrentPosition(GetX(), GetY(), GetZ());
glm::vec3 CurrentPosition(GetX(), GetY(), GetZ());
std::deque<int> Route = zone->pathing->FindRoute(CurrentPosition, Loc);
if(Route.size() > 0)
{
fear_walkto_x = Loc.x;
fear_walkto_y = Loc.y;
fear_walkto_z = Loc.z;
m_FearWalkTarget = glm::vec3(Loc.x, Loc.y, Loc.z);
curfp = true;
mlog(PATHING__DEBUG, "Feared to node %i (%8.3f, %8.3f, %8.3f)", Node, Loc.x, Loc.y, Loc.z);
Log.Out(Logs::Detail, Logs::None, "Feared to node %i (%8.3f, %8.3f, %8.3f)", Node, Loc.x, Loc.y, Loc.z);
return;
}
mlog(PATHING__DEBUG, "No path found to selected node. Falling through to old fear point selection.");
Log.Out(Logs::Detail, Logs::None, "No path found to selected node. Falling through to old fear point selection.");
}
int loop = 0;
@@ -194,14 +192,8 @@ void Mob::CalculateNewFearpoint()
}
}
if (curfp)
{
fear_walkto_x = ranx;
fear_walkto_y = rany;
fear_walkto_z = ranz;
}
m_FearWalkTarget = glm::vec3(ranx, rany, ranz);
else //Break fear
{
BuffFadeByEffect(SE_Fear);
}
}
+19 -17
View File
@@ -16,7 +16,8 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "../common/global_define.h"
#include "../common/eqemu_logsys.h"
#include "../common/misc_functions.h"
#include "../common/rulesys.h"
#include "../common/string_util.h"
@@ -58,7 +59,6 @@ uint32 ZoneDatabase::GetZoneForage(uint32 ZoneID, uint8 skill) {
"LIMIT %i", ZoneID, skill, FORAGE_ITEM_LIMIT);
auto results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in Forage query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
return 0;
}
@@ -69,7 +69,7 @@ uint32 ZoneDatabase::GetZoneForage(uint32 ZoneID, uint8 skill) {
item[index] = atoi(row[0]);
chance[index] = atoi(row[1]) + chancepool;
LogFile->write(EQEMuLog::Error, "Possible Forage: %d with a %d chance", item[index], chance[index]);
Log.Out(Logs::General, Logs::Error, "Possible Forage: %d with a %d chance", item[index], chance[index]);
chancepool = chance[index];
}
@@ -114,7 +114,6 @@ uint32 ZoneDatabase::GetZoneFishing(uint32 ZoneID, uint8 skill, uint32 &npc_id,
ZoneID, skill);
auto results = QueryDatabase(query);
if (!results.Success()) {
std::cerr << "Error in Fishing query '" << query << "' " << results.ErrorMessage() << std::endl;
return 0;
}
@@ -174,7 +173,8 @@ bool Client::CanFish() {
}
if(zone->zonemap != nullptr && zone->watermap != nullptr && RuleB(Watermap, CheckForWaterWhenFishing)) {
float RodX, RodY, RodZ;
glm::vec3 rodPosition;
// Tweak Rod and LineLength if required
const float RodLength = RuleR(Watermap, FishingRodLength);
const float LineLength = RuleR(Watermap, FishingLineLength);
@@ -183,25 +183,25 @@ bool Client::CanFish() {
HeadingDegrees = (int) ((GetHeading()*360)/256);
HeadingDegrees = HeadingDegrees % 360;
RodX = x_pos + RodLength * sin(HeadingDegrees * M_PI/180.0f);
RodY = y_pos + RodLength * cos(HeadingDegrees * M_PI/180.0f);
rodPosition.x = m_Position.x + RodLength * sin(HeadingDegrees * M_PI/180.0f);
rodPosition.y = m_Position.y + RodLength * cos(HeadingDegrees * M_PI/180.0f);
// Do BestZ to find where the line hanging from the rod intersects the water (if it is water).
// and go 1 unit into the water.
Map::Vertex dest;
dest.x = RodX;
dest.y = RodY;
dest.z = z_pos+10;
glm::vec3 dest;
dest.x = rodPosition.x;
dest.y = rodPosition.y;
dest.z = m_Position.z+10;
RodZ = zone->zonemap->FindBestZ(dest, nullptr) + 4;
bool in_lava = zone->watermap->InLava(RodX, RodY, RodZ);
bool in_water = zone->watermap->InWater(RodX, RodY, RodZ) || zone->watermap->InVWater(RodX, RodY, RodZ);
rodPosition.z = zone->zonemap->FindBestZ(dest, nullptr) + 4;
bool in_lava = zone->watermap->InLava(rodPosition);
bool in_water = zone->watermap->InWater(rodPosition) || zone->watermap->InVWater(rodPosition);
//Message(0, "Rod is at %4.3f, %4.3f, %4.3f, InWater says %d, InLava says %d", RodX, RodY, RodZ, in_water, in_lava);
if (in_lava) {
Message_StringID(MT_Skills, FISHING_LAVA); //Trying to catch a fire elemental or something?
return false;
}
if((!in_water) || (z_pos-RodZ)>LineLength) { //Didn't hit the water OR the water is too far below us
if((!in_water) || (m_Position.z-rodPosition.z)>LineLength) { //Didn't hit the water OR the water is too far below us
Message_StringID(MT_Skills, FISHING_LAND); //Trying to catch land sharks perhaps?
return false;
}
@@ -272,7 +272,9 @@ void Client::GoFish()
if(npc_chance < zone->random.Int(0, 99)) {
const NPCType* tmp = database.GetNPCType(npc_id);
if(tmp != nullptr) {
NPC* npc = new NPC(tmp, nullptr, GetX()+3, GetY(), GetZ(), GetHeading(), FlyMode3);
auto positionNPC = GetPosition();
positionNPC.x = positionNPC.x + 3;
NPC* npc = new NPC(tmp, nullptr, positionNPC, FlyMode3);
npc->AddLootTable();
npc->AddToHateList(this, 1, 0, false); //no help yelling
@@ -388,7 +390,7 @@ void Client::ForageItem(bool guarantee) {
const Item_Struct* food_item = database.GetItem(foragedfood);
if(!food_item) {
LogFile->write(EQEMuLog::Error, "nullptr returned from database.GetItem in ClientForageItem");
Log.Out(Logs::General, Logs::Error, "nullptr returned from database.GetItem in ClientForageItem");
return;
}
+86 -103
View File
@@ -15,7 +15,8 @@
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/debug.h"
#include "../common/global_define.h"
#include "../common/eqemu_logsys.h"
#include "masterentity.h"
#include "npc_ai.h"
#include "../common/packet_functions.h"
@@ -26,23 +27,16 @@
extern EntityList entity_list;
extern WorldServer worldserver;
//
// Xorlac: This will need proper synchronization to make it work correctly.
// Also, should investigate client ack for packet to ensure proper synch.
//
/*
note about how groups work:
A group contains 2 list, a list of pointers to members and a
list of member names. All members of a group should have their
name in the membername array, wether they are in the zone or not.
name in the membername array, whether they are in the zone or not.
Only members in this zone will have non-null pointers in the
members array.
*/
//create a group which should allready exist in the database
//create a group which should already exist in the database
Group::Group(uint32 gid)
: GroupIDConsumer(gid)
{
@@ -112,8 +106,7 @@ Group::~Group()
}
}
//Cofruben:Split money used in OP_Split.
//Rewritten by Father Nitwit
//Split money used in OP_Split (/split and /autosplit).
void Group::SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client *splitter) {
//avoid unneeded work
if(copper == 0 && silver == 0 && gold == 0 && platinum == 0)
@@ -197,7 +190,7 @@ void Group::SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinu
for (i = 0; i < MAX_GROUP_MEMBERS; i++) {
if (members[i] != nullptr && members[i]->IsClient()) { // If Group Member is Client
Client *c = members[i]->CastToClient();
Client *c = members[i]->CastToClient();
//I could not get MoneyOnCorpse to work, so we use this
c->AddMoneyToPP(cpsplit, spsplit, gpsplit, ppsplit, true);
c->Message(2, msg.c_str());
@@ -239,7 +232,6 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte
if(owner)
{
CharacterID = owner->CastToClient()->CharacterID();
NewMemberName = newmember->GetName();
}
ismerc = true;
}
@@ -290,14 +282,7 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte
if (members[i] != nullptr && members[i] != newmember)
{
//fill in group join & send it
if(members[i]->IsMerc())
{
strcpy(gj->yourname, members[i]->GetName());
}
else
{
strcpy(gj->yourname, members[i]->GetCleanName());
}
strcpy(gj->yourname, members[i]->GetCleanName());
if(members[i]->IsClient())
{
members[i]->CastToClient()->QueuePacket(outapp);
@@ -344,7 +329,7 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte
Client* owner = newmember->CastToMerc()->GetMercOwner();
if(owner)
{
database.SetGroupID(newmember->GetName(), GetID(), owner->CharacterID(), true);
database.SetGroupID(NewMemberName, GetID(), owner->CharacterID(), true);
}
}
#ifdef BOTS
@@ -368,7 +353,6 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte
void Group::AddMember(const char *NewMemberName)
{
// This method should be called when both the new member and the group leader are in a different zone to this one.
//
for (uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i)
if(!strcasecmp(membername[i], NewMemberName))
{
@@ -395,9 +379,8 @@ void Group::QueuePacket(const EQApplicationPacket *app, bool ack_req)
members[i]->CastToClient()->QueuePacket(app, ack_req);
}
// solar: sends the rest of the group's hps to member. this is useful when
// someone first joins a group, but otherwise there shouldn't be a need to
// call it
// Sends the rest of the group's hps to member. this is useful when someone
// first joins a group, but otherwise there shouldn't be a need to call it
void Group::SendHPPacketsTo(Mob *member)
{
if(member && member->IsClient())
@@ -411,7 +394,7 @@ void Group::SendHPPacketsTo(Mob *member)
{
members[i]->CreateHPPacket(&hpapp);
member->CastToClient()->QueuePacket(&hpapp, false);
if(member->CastToClient()->GetClientVersion() >= EQClientSoD)
if(member->CastToClient()->GetClientVersion() >= ClientVersion::SoD)
{
outapp.SetOpcode(OP_MobManaUpdate);
MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp.pBuffer;
@@ -442,7 +425,7 @@ void Group::SendHPPacketsFrom(Mob *member)
if(members[i] && members[i] != member && members[i]->IsClient())
{
members[i]->CastToClient()->QueuePacket(&hp_app);
if(members[i]->CastToClient()->GetClientVersion() >= EQClientSoD)
if(members[i]->CastToClient()->GetClientVersion() >= ClientVersion::SoD)
{
outapp.SetOpcode(OP_MobManaUpdate);
MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp.pBuffer;
@@ -459,9 +442,11 @@ void Group::SendHPPacketsFrom(Mob *member)
}
//updates a group member's client pointer when they zone in
//if the group was in the zone allready
//if the group was in the zone already
bool Group::UpdatePlayer(Mob* update){
bool updateSuccess = false;
VerifyGroup();
uint32 i=0;
@@ -483,11 +468,12 @@ bool Group::UpdatePlayer(Mob* update){
for (i = 0; i < MAX_GROUP_MEMBERS; i++)
{
if (!strcasecmp(membername[i],update->GetName()))
if (!strcasecmp(membername[i],update->GetCleanName()))
{
members[i] = update;
members[i]->SetGrouped(true);
return true;
updateSuccess = true;
break;
}
}
@@ -495,7 +481,7 @@ bool Group::UpdatePlayer(Mob* update){
if (update->IsClient() && !mentoree && mentoree_name.length() && !mentoree_name.compare(update->GetName()))
mentoree = update->CastToClient();
return false;
return updateSuccess;
}
@@ -520,6 +506,7 @@ void Group::MemberZoned(Mob* removemob) {
}
#endif //BOTS
}
if(removemob->IsClient() && HasRole(removemob, RoleAssist))
SetGroupAssistTarget(0);
@@ -551,7 +538,7 @@ void Group::SendGroupJoinOOZ(Mob* NewMember) {
gj->gid = GetID();
gj->zoneid = zone->GetZoneID();
gj->instance_id = zone->GetInstanceID();
strcpy(gj->member_name, NewMember->GetName());
strcpy(gj->member_name, NewMember->GetCleanName());
worldserver.SendPacket(pack);
safe_delete(pack);
@@ -578,7 +565,7 @@ bool Group::DelMemberOOZ(const char *Name) {
if(GroupCount() < 3)
{
UnDelegateMarkNPC(NPCMarkerName.c_str());
if(GetLeader() && GetLeader()->IsClient() && GetLeader()->CastToClient()->GetClientVersion() < EQClientSoD) {
if(GetLeader() && GetLeader()->IsClient() && GetLeader()->CastToClient()->GetClientVersion() < ClientVersion::SoD) {
UnDelegateMainAssist(MainAssistName.c_str());
}
ClearAllNPCMarks();
@@ -592,7 +579,7 @@ bool Group::DelMemberOOZ(const char *Name) {
return false;
}
bool Group::DelMember(Mob* oldmember,bool ignoresender)
bool Group::DelMember(Mob* oldmember, bool ignoresender)
{
if (oldmember == nullptr)
{
@@ -651,7 +638,7 @@ bool Group::DelMember(Mob* oldmember,bool ignoresender)
gl->gid = GetID();
gl->zoneid = zone->GetZoneID();
gl->instance_id = zone->GetInstanceID();
strcpy(gl->member_name, oldmember->GetName());
strcpy(gl->member_name, oldmember->GetCleanName());
worldserver.SendPacket(pack);
safe_delete(pack);
@@ -689,6 +676,8 @@ bool Group::DelMember(Mob* oldmember,bool ignoresender)
if(oldmember->IsClient())
oldmember->CastToClient()->QueuePacket(outapp);
}
safe_delete(outapp);
if(oldmember->IsClient())
{
@@ -700,31 +689,29 @@ bool Group::DelMember(Mob* oldmember,bool ignoresender)
Client* owner = oldmember->CastToMerc()->GetMercOwner();
if(owner)
{
database.SetGroupID(oldmember->GetName(), 0, owner->CharacterID(), true);
database.SetGroupID(oldmember->GetCleanName(), 0, owner->CharacterID(), true);
}
}
oldmember->SetGrouped(false);
disbandcheck = true;
safe_delete(outapp);
if(HasRole(oldmember, RoleTank))
{
SetGroupTankTarget(0);
UnDelegateMainTank(oldmember->GetName());
UnDelegateMainTank(oldmember->GetCleanName());
}
if(HasRole(oldmember, RoleAssist))
{
SetGroupAssistTarget(0);
UnDelegateMainAssist(oldmember->GetName());
UnDelegateMainAssist(oldmember->GetCleanName());
}
if(HasRole(oldmember, RolePuller))
{
SetGroupPullerTarget(0);
UnDelegatePuller(oldmember->GetName());
UnDelegatePuller(oldmember->GetCleanName());
}
if (oldmember->GetName() == mentoree_name)
@@ -736,7 +723,7 @@ bool Group::DelMember(Mob* oldmember,bool ignoresender)
if(GroupCount() < 3)
{
UnDelegateMarkNPC(NPCMarkerName.c_str());
if(GetLeader() && GetLeader()->IsClient() && GetLeader()->CastToClient()->GetClientVersion() < EQClientSoD) {
if(GetLeader() && GetLeader()->IsClient() && GetLeader()->CastToClient()->GetClientVersion() < ClientVersion::SoD) {
UnDelegateMainAssist(MainAssistName.c_str());
}
ClearAllNPCMarks();
@@ -772,7 +759,7 @@ void Group::CastGroupSpell(Mob* caster, uint16 spell_id) {
}
else if(members[z] != nullptr)
{
distance = caster->DistNoRoot(*members[z]);
distance = DistanceSquared(caster->GetPosition(), members[z]->GetPosition());
if(distance <= range2 && distance >= min_range2) {
members[z]->CalcSpellPowerDistanceMod(spell_id, distance);
caster->SpellOnTarget(spell_id, members[z]);
@@ -781,7 +768,7 @@ void Group::CastGroupSpell(Mob* caster, uint16 spell_id) {
caster->SpellOnTarget(spell_id, members[z]->GetPet());
#endif
} else
_log(SPELLS__CASTING, "Group spell: %s is out of range %f at distance %f from %s", members[z]->GetName(), range, distance, caster->GetName());
Log.Out(Logs::Detail, Logs::Spells, "Group spell: %s is out of range %f at distance %f from %s", members[z]->GetName(), range, distance, caster->GetName());
}
}
@@ -812,7 +799,7 @@ void Group::GroupBardPulse(Mob* caster, uint16 spell_id) {
}
else if(members[z] != nullptr)
{
distance = caster->DistNoRoot(*members[z]);
distance = DistanceSquared(caster->GetPosition(), members[z]->GetPosition());
if(distance <= range2) {
members[z]->BardPulse(spell_id, caster);
#ifdef GROUP_BUFF_PETS
@@ -820,7 +807,7 @@ void Group::GroupBardPulse(Mob* caster, uint16 spell_id) {
members[z]->GetPet()->BardPulse(spell_id, caster);
#endif
} else
_log(SPELLS__BARDS, "Group bard pulse: %s is out of range %f at distance %f from %s", members[z]->GetName(), range, distance, caster->GetName());
Log.Out(Logs::Detail, Logs::Spells, "Group bard pulse: %s is out of range %f at distance %f from %s", members[z]->GetName(), range, distance, caster->GetName());
}
}
}
@@ -864,7 +851,7 @@ void Group::GroupMessage(Mob* sender, uint8 language, uint8 lang_skill, const ch
gcm->zoneid = zone->GetZoneID();
gcm->groupid = GetID();
gcm->instanceid = zone->GetInstanceID();
strcpy(gcm->from, sender->GetName());
strcpy(gcm->from, sender->GetCleanName());
strcpy(gcm->message, message);
worldserver.SendPacket(pack);
safe_delete(pack);
@@ -906,8 +893,8 @@ void Group::DisbandGroup() {
Leader = members[i]->CastToClient();
}
strcpy(gu->yourname, members[i]->GetName());
database.SetGroupID(members[i]->GetName(), 0, members[i]->CastToClient()->CharacterID(), false);
strcpy(gu->yourname, members[i]->GetCleanName());
database.SetGroupID(members[i]->GetCleanName(), 0, members[i]->CastToClient()->CharacterID(), false);
members[i]->CastToClient()->QueuePacket(outapp);
SendMarkedNPCsToMember(members[i]->CastToClient(), true);
}
@@ -917,7 +904,7 @@ void Group::DisbandGroup() {
Client* owner = members[i]->CastToMerc()->GetMercOwner();
if(owner)
{
database.SetGroupID(members[i]->GetName(), 0, owner->CharacterID(), true);
database.SetGroupID(members[i]->GetCleanName(), 0, owner->CharacterID(), true);
}
}
@@ -936,12 +923,13 @@ void Group::DisbandGroup() {
worldserver.SendPacket(pack);
safe_delete(pack);
entity_list.RemoveGroup(GetID());
if(GetID() != 0)
{
database.ClearGroup(GetID());
}
entity_list.RemoveGroup(GetID());
if(Leader && (Leader->IsLFP()))
{
Leader->UpdateLFP();
@@ -981,7 +969,7 @@ void Group::SendUpdate(uint32 type, Mob* member)
for (uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i)
if (members[i] != nullptr && members[i] != member)
strcpy(gu->membername[x++], members[i]->GetName());
strcpy(gu->membername[x++], members[i]->GetCleanName());
member->CastToClient()->QueuePacket(outapp);
@@ -998,24 +986,21 @@ void Group::SendLeadershipAAUpdate()
// aware of it until they are next in the same zone as the leader.
EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct));
GroupJoin_Struct* gu = (GroupJoin_Struct*)outapp->pBuffer;
gu->action = groupActAAUpdate;
uint32 i = 0;
gu->leader_aas = LeaderAbilities;
gu->NPCMarkerID = GetNPCMarkerID();
uint32 i = 0;
for (i = 0;i < MAX_GROUP_MEMBERS; ++i)
{
if(members[i] && members[i]->IsClient())
{
strcpy(gu->yourname, members[i]->GetName());
strcpy(gu->membername, members[i]->GetName());
members[i]->CastToClient()->QueuePacket(outapp);
}
}
safe_delete(outapp);
}
@@ -1037,8 +1022,8 @@ uint8 Group::GroupCount() {
uint32 Group::GetHighestLevel()
{
uint32 level = 1;
uint32 i;
uint32 level = 1;
uint32 i;
for (i = 0; i < MAX_GROUP_MEMBERS; i++)
{
if (members[i])
@@ -1049,10 +1034,11 @@ uint32 i;
}
return level;
}
uint32 Group::GetLowestLevel()
{
uint32 level = 255;
uint32 i;
uint32 level = 255;
uint32 i;
for (i = 0; i < MAX_GROUP_MEMBERS; i++)
{
if (members[i])
@@ -1083,7 +1069,7 @@ bool Group::LearnMembers() {
return false;
if (results.RowCount() == 0) {
LogFile->write(EQEMuLog::Error, "Error getting group members for group %lu: %s", (unsigned long)GetID(), results.ErrorMessage().c_str());
Log.Out(Logs::General, Logs::Error, "Error getting group members for group %lu: %s", (unsigned long)GetID(), results.ErrorMessage().c_str());
return false;
}
@@ -1112,18 +1098,16 @@ void Group::VerifyGroup() {
for (i = 0; i < MAX_GROUP_MEMBERS; i++) {
if (membername[i][0] == '\0') {
#if EQDEBUG >= 7
LogFile->write(EQEMuLog::Debug, "Group %lu: Verify %d: Empty.\n", (unsigned long)GetID(), i);
Log.Out(Logs::General, Logs::None, "Group %lu: Verify %d: Empty.\n", (unsigned long)GetID(), i);
#endif
members[i] = nullptr;
continue;
}
//it should be safe to use GetClientByName, but Group is trying
//to be generic, so we'll go for general Mob
Mob *them = entity_list.GetMob(membername[i]);
if(them == nullptr && members[i] != nullptr) { //they arnt here anymore....
if(them == nullptr && members[i] != nullptr) { //they aren't in zone
#if EQDEBUG >= 6
LogFile->write(EQEMuLog::Debug, "Member of group %lu named '%s' has disappeared!!", (unsigned long)GetID(), membername[i]);
Log.Out(Logs::General, Logs::None, "Member of group %lu named '%s' has disappeared!!", (unsigned long)GetID(), membername[i]);
#endif
membername[i][0] = '\0';
members[i] = nullptr;
@@ -1132,18 +1116,17 @@ LogFile->write(EQEMuLog::Debug, "Group %lu: Verify %d: Empty.\n", (unsigned long
if(them != nullptr && members[i] != them) { //our pointer is out of date... not so good.
#if EQDEBUG >= 5
LogFile->write(EQEMuLog::Debug, "Member of group %lu named '%s' had an out of date pointer!!", (unsigned long)GetID(), membername[i]);
Log.Out(Logs::General, Logs::None, "Member of group %lu named '%s' had an out of date pointer!!", (unsigned long)GetID(), membername[i]);
#endif
members[i] = them;
continue;
}
#if EQDEBUG >= 8
LogFile->write(EQEMuLog::Debug, "Member of group %lu named '%s' is valid.", (unsigned long)GetID(), membername[i]);
Log.Out(Logs::General, Logs::None, "Member of group %lu named '%s' is valid.", (unsigned long)GetID(), membername[i]);
#endif
}
}
void Group::GroupMessage_StringID(Mob* sender, uint32 type, uint32 string_id, const char* message,const char* message2,const char* message3,const char* message4,const char* message5,const char* message6,const char* message7,const char* message8,const char* message9, uint32 distance) {
uint32 i;
for (i = 0; i < MAX_GROUP_MEMBERS; i++) {
@@ -1152,13 +1135,14 @@ void Group::GroupMessage_StringID(Mob* sender, uint32 type, uint32 string_id, co
if(members[i] == sender)
continue;
if(!members[i]->IsClient())
continue;
members[i]->Message_StringID(type, string_id, message, message2, message3, message4, message5, message6, message7, message8, message9, 0);
}
}
void Client::LeaveGroup() {
Group *g = GetGroup();
@@ -1166,7 +1150,7 @@ void Client::LeaveGroup() {
{
int32 MemberCount = g->GroupCount();
// Account for both client and merc leaving the group
if (GetMerc() && GetMerc()->HasGroup() && GetMerc()->GetGroup() == g)
if (GetMerc() && g == GetMerc()->GetGroup())
{
MemberCount -= 1;
}
@@ -1178,7 +1162,7 @@ void Client::LeaveGroup() {
else
{
g->DelMember(this);
if (GetMerc() && GetMerc()->HasGroup() && GetMerc()->GetGroup() == g)
if (GetMerc() != nullptr && g == GetMerc()->GetGroup() )
{
GetMerc()->RemoveMercFromGroup(GetMerc(), GetMerc()->GetGroup());
}
@@ -1187,10 +1171,10 @@ void Client::LeaveGroup() {
else
{
//force things a little
database.SetGroupID(GetName(), 0, CharacterID(), false);
database.SetGroupID(GetCleanName(), 0, CharacterID(), false);
if (GetMerc())
{
database.SetGroupID(GetMerc()->GetName(), 0, CharacterID(), true);
database.SetGroupID(GetMerc()->GetCleanName(), 0, CharacterID(), true);
}
}
@@ -1214,7 +1198,7 @@ void Group::HealGroup(uint32 heal_amt, Mob* caster, float range)
for(; gi < MAX_GROUP_MEMBERS; gi++)
{
if(members[gi]){
distance = caster->DistNoRoot(*members[gi]);
distance = DistanceSquared(caster->GetPosition(), members[gi]->GetPosition());
if(distance <= range2){
numMem += 1;
}
@@ -1225,7 +1209,7 @@ void Group::HealGroup(uint32 heal_amt, Mob* caster, float range)
for(gi = 0; gi < MAX_GROUP_MEMBERS; gi++)
{
if(members[gi]){
distance = caster->DistNoRoot(*members[gi]);
distance = DistanceSquared(caster->GetPosition(), members[gi]->GetPosition());
if(distance <= range2){
members[gi]->HealDamage(heal_amt, caster);
members[gi]->SendHPUpdate();
@@ -1252,7 +1236,7 @@ void Group::BalanceHP(int32 penalty, float range, Mob* caster, int32 limit)
for(; gi < MAX_GROUP_MEMBERS; gi++)
{
if(members[gi]){
distance = caster->DistNoRoot(*members[gi]);
distance = DistanceSquared(caster->GetPosition(), members[gi]->GetPosition());
if(distance <= range2){
dmgtaken_tmp = members[gi]->GetMaxHP() - members[gi]->GetHP();
@@ -1270,7 +1254,7 @@ void Group::BalanceHP(int32 penalty, float range, Mob* caster, int32 limit)
for(gi = 0; gi < MAX_GROUP_MEMBERS; gi++)
{
if(members[gi]){
distance = caster->DistNoRoot(*members[gi]);
distance = DistanceSquared(caster->GetPosition(), members[gi]->GetPosition());
if(distance <= range2){
if((members[gi]->GetMaxHP() - dmgtaken) < 1){ //this way the ability will never kill someone
members[gi]->SetHP(1); //but it will come darn close
@@ -1301,7 +1285,7 @@ void Group::BalanceMana(int32 penalty, float range, Mob* caster, int32 limit)
for(; gi < MAX_GROUP_MEMBERS; gi++)
{
if(members[gi] && (members[gi]->GetMaxMana() > 0)){
distance = caster->DistNoRoot(*members[gi]);
distance = DistanceSquared(caster->GetPosition(), members[gi]->GetPosition());
if(distance <= range2){
manataken_tmp = members[gi]->GetMaxMana() - members[gi]->GetMana();
@@ -1323,7 +1307,7 @@ void Group::BalanceMana(int32 penalty, float range, Mob* caster, int32 limit)
for(gi = 0; gi < MAX_GROUP_MEMBERS; gi++)
{
if(members[gi]){
distance = caster->DistNoRoot(*members[gi]);
distance = DistanceSquared(caster->GetPosition(), members[gi]->GetPosition());
if(distance <= range2){
if((members[gi]->GetMaxMana() - manataken) < 1){
members[gi]->SetMana(1);
@@ -1363,7 +1347,7 @@ void Group::MarkNPC(Mob* Target, int Number)
// Send a packet to all group members in this zone causing the client to prefix the Target mob's name
// with the specified Number.
//
if(!Target || Target->IsClient())
if(!Target || Target->IsClient() || Target->IsMerc())
return;
if((Number < 1) || (Number > MAX_MARKED_NPCS))
@@ -1473,7 +1457,7 @@ void Group::DelegateMainTank(const char *NewMainTankName, uint8 toggle)
MainTankName.c_str(), GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to set group main tank: %s\n", results.ErrorMessage().c_str());
Log.Out(Logs::General, Logs::Error, "Unable to set group main tank: %s\n", results.ErrorMessage().c_str());
}
}
@@ -1519,7 +1503,7 @@ void Group::DelegateMainAssist(const char *NewMainAssistName, uint8 toggle)
MainAssistName.c_str(), GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to set group main assist: %s\n", results.ErrorMessage().c_str());
Log.Out(Logs::General, Logs::Error, "Unable to set group main assist: %s\n", results.ErrorMessage().c_str());
}
}
@@ -1566,7 +1550,7 @@ void Group::DelegatePuller(const char *NewPullerName, uint8 toggle)
PullerName.c_str(), GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to set group main puller: %s\n", results.ErrorMessage().c_str());
Log.Out(Logs::General, Logs::Error, "Unable to set group main puller: %s\n", results.ErrorMessage().c_str());
}
@@ -1584,7 +1568,7 @@ void Group::NotifyMainTank(Client *c, uint8 toggle)
if(!MainTankName.size())
return;
if(c->GetClientVersion() < EQClientSoD)
if(c->GetClientVersion() < ClientVersion::SoD)
{
if(toggle)
c->Message(0, "%s is now Main Tank.", MainTankName.c_str());
@@ -1624,7 +1608,7 @@ void Group::NotifyMainAssist(Client *c, uint8 toggle)
if(!MainAssistName.size())
return;
if(c->GetClientVersion() < EQClientSoD)
if(c->GetClientVersion() < ClientVersion::SoD)
{
EQApplicationPacket *outapp = new EQApplicationPacket(OP_DelegateAbility, sizeof(DelegateAbility_Struct));
@@ -1679,7 +1663,7 @@ void Group::NotifyPuller(Client *c, uint8 toggle)
if(!PullerName.size())
return;
if(c->GetClientVersion() < EQClientSoD)
if(c->GetClientVersion() < ClientVersion::SoD)
{
if(toggle)
c->Message(0, "%s is now Puller.", PullerName.c_str());
@@ -1717,7 +1701,7 @@ void Group::UnDelegateMainTank(const char *OldMainTankName, uint8 toggle)
std::string query = StringFormat("UPDATE group_leaders SET maintank = '' WHERE gid = %i LIMIT 1", GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to clear group main tank: %s\n", results.ErrorMessage().c_str());
Log.Out(Logs::General, Logs::Error, "Unable to clear group main tank: %s\n", results.ErrorMessage().c_str());
if(!toggle) {
for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) {
@@ -1766,7 +1750,7 @@ void Group::UnDelegateMainAssist(const char *OldMainAssistName, uint8 toggle)
std::string query = StringFormat("UPDATE group_leaders SET assist = '' WHERE gid = %i LIMIT 1", GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to clear group main assist: %s\n", results.ErrorMessage().c_str());
Log.Out(Logs::General, Logs::Error, "Unable to clear group main assist: %s\n", results.ErrorMessage().c_str());
if(!toggle)
{
@@ -1794,7 +1778,7 @@ void Group::UnDelegatePuller(const char *OldPullerName, uint8 toggle)
std::string query = StringFormat("UPDATE group_leaders SET puller = '' WHERE gid = %i LIMIT 1", GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to clear group main puller: %s\n", results.ErrorMessage().c_str());
Log.Out(Logs::General, Logs::Error, "Unable to clear group main puller: %s\n", results.ErrorMessage().c_str());
if(!toggle) {
for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) {
@@ -1877,7 +1861,7 @@ void Group::SetGroupMentor(int percent, char *name)
mentoree_name.c_str(), mentor_percent, GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to set group mentor: %s\n", results.ErrorMessage().c_str());
Log.Out(Logs::General, Logs::Error, "Unable to set group mentor: %s\n", results.ErrorMessage().c_str());
}
void Group::ClearGroupMentor()
@@ -1888,7 +1872,7 @@ void Group::ClearGroupMentor()
std::string query = StringFormat("UPDATE group_leaders SET mentoree = '', mentor_percent = 0 WHERE gid = %i LIMIT 1", GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to clear group mentor: %s\n", results.ErrorMessage().c_str());
Log.Out(Logs::General, Logs::Error, "Unable to clear group mentor: %s\n", results.ErrorMessage().c_str());
}
void Group::NotifyAssistTarget(Client *c)
@@ -1958,7 +1942,7 @@ void Group::DelegateMarkNPC(const char *NewNPCMarkerName)
NewNPCMarkerName, GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to set group mark npc: %s\n", results.ErrorMessage().c_str());
Log.Out(Logs::General, Logs::Error, "Unable to set group mark npc: %s\n", results.ErrorMessage().c_str());
}
void Group::NotifyMarkNPC(Client *c)
@@ -2039,7 +2023,7 @@ void Group::UnDelegateMarkNPC(const char *OldNPCMarkerName)
std::string query = StringFormat("UPDATE group_leaders SET marknpc = '' WHERE gid = %i LIMIT 1", GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to clear group marknpc: %s\n", results.ErrorMessage().c_str());
Log.Out(Logs::General, Logs::Error, "Unable to clear group marknpc: %s\n", results.ErrorMessage().c_str());
}
@@ -2056,7 +2040,7 @@ void Group::SaveGroupLeaderAA()
safe_delete_array(queryBuffer);
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to store LeadershipAA: %s\n", results.ErrorMessage().c_str());
Log.Out(Logs::General, Logs::Error, "Unable to store LeadershipAA: %s\n", results.ErrorMessage().c_str());
}
@@ -2166,7 +2150,6 @@ int8 Group::GetNumberNeedingHealedInGroup(int8 hpr, bool includePets) {
}
}
return needHealed;
}
@@ -2228,7 +2211,7 @@ void Group::ChangeLeader(Mob* newleader)
// this changes the current group leader, notifies other members, and updates leadship AA
// if the new leader is invalid, do nothing
if (!newleader)
if (!newleader || !newleader->IsClient())
return;
Mob* oldleader = GetLeader();
@@ -2246,7 +2229,7 @@ void Group::ChangeLeader(Mob* newleader)
for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) {
if (members[i] && members[i]->IsClient())
{
if(members[i]->CastToClient()->GetClientVersion() >= EQClientSoD)
if(members[i]->CastToClient()->GetClientVersion() >= ClientVersion::SoD)
members[i]->CastToClient()->SendGroupLeaderChangePacket(newleader->GetName());
members[i]->CastToClient()->QueuePacket(outapp);
+12 -18
View File
@@ -56,15 +56,14 @@ void Client::SendGuildMOTD(bool GetGuildMOTDReply) {
}
mlog(GUILDS__OUT_PACKETS, "Sending OP_GuildMOTD of length %d", outapp->size);
mpkt(GUILDS__OUT_PACKET_TRACE, outapp);
Log.Out(Logs::Detail, Logs::Guilds, "Sending OP_GuildMOTD of length %d", outapp->size);
FastQueuePacket(&outapp);
}
void Client::SendGuildURL()
{
if(GetClientVersion() < EQClientSoF)
if(GetClientVersion() < ClientVersion::SoF)
return;
if(IsInAGuild())
@@ -85,7 +84,7 @@ void Client::SendGuildURL()
void Client::SendGuildChannel()
{
if(GetClientVersion() < EQClientSoF)
if(GetClientVersion() < ClientVersion::SoF)
return;
if(IsInAGuild())
@@ -107,7 +106,7 @@ void Client::SendGuildChannel()
void Client::SendGuildRanks()
{
if(GetClientVersion() < EQClientRoF)
if(GetClientVersion() < ClientVersion::RoF)
return;
int permissions = 30 + 1; //Static number of permissions in all EQ clients as of May 2014
@@ -145,12 +144,12 @@ void Client::SendGuildSpawnAppearance() {
if (!IsInAGuild()) {
// clear guildtag
SendAppearancePacket(AT_GuildID, GUILD_NONE);
mlog(GUILDS__OUT_PACKETS, "Sending spawn appearance for no guild tag.");
Log.Out(Logs::Detail, Logs::Guilds, "Sending spawn appearance for no guild tag.");
} else {
uint8 rank = guild_mgr.GetDisplayedRank(GuildID(), GuildRank(), CharacterID());
mlog(GUILDS__OUT_PACKETS, "Sending spawn appearance for guild %d at rank %d", GuildID(), rank);
Log.Out(Logs::Detail, Logs::Guilds, "Sending spawn appearance for guild %d at rank %d", GuildID(), rank);
SendAppearancePacket(AT_GuildID, GuildID());
if(GetClientVersion() >= EQClientRoF)
if(GetClientVersion() >= ClientVersion::RoF)
{
switch (rank) {
case 0: { rank = 5; break; } // GUILD_MEMBER 0
@@ -172,12 +171,11 @@ void Client::SendGuildList() {
//ask the guild manager to build us a nice guild list packet
outapp->pBuffer = guild_mgr.MakeGuildList(/*GetName()*/"", outapp->size);
if(outapp->pBuffer == nullptr) {
mlog(GUILDS__ERROR, "Unable to make guild list!");
Log.Out(Logs::Detail, Logs::Guilds, "Unable to make guild list!");
return;
}
mlog(GUILDS__OUT_PACKETS, "Sending OP_ZoneGuildList of length %d", outapp->size);
// mpkt(GUILDS__OUT_PACKET_TRACE, outapp);
Log.Out(Logs::Detail, Logs::Guilds, "Sending OP_ZoneGuildList of length %d", outapp->size);
FastQueuePacket(&outapp);
}
@@ -194,8 +192,7 @@ void Client::SendGuildMembers() {
outapp->pBuffer = data;
data = nullptr;
mlog(GUILDS__OUT_PACKETS, "Sending OP_GuildMemberList of length %d", outapp->size);
mpkt(GUILDS__OUT_PACKET_TRACE, outapp);
Log.Out(Logs::Detail, Logs::Guilds, "Sending OP_GuildMemberList of length %d", outapp->size);
FastQueuePacket(&outapp);
@@ -226,7 +223,7 @@ void Client::RefreshGuildInfo()
CharGuildInfo info;
if(!guild_mgr.GetCharInfo(CharacterID(), info)) {
mlog(GUILDS__ERROR, "Unable to obtain guild char info for %s (%d)", GetName(), CharacterID());
Log.Out(Logs::Detail, Logs::Guilds, "Unable to obtain guild char info for %s (%d)", GetName(), CharacterID());
return;
}
@@ -338,8 +335,7 @@ void Client::SendGuildJoin(GuildJoin_Struct* gj){
outgj->rank = gj->rank;
outgj->zoneid = gj->zoneid;
mlog(GUILDS__OUT_PACKETS, "Sending OP_GuildManageAdd for join of length %d", outapp->size);
mpkt(GUILDS__OUT_PACKET_TRACE, outapp);
Log.Out(Logs::Detail, Logs::Guilds, "Sending OP_GuildManageAdd for join of length %d", outapp->size);
FastQueuePacket(&outapp);
@@ -413,7 +409,6 @@ bool ZoneDatabase::CheckGuildDoor(uint8 doorid, uint16 guild_id, const char* zon
doorid-128, zone);
auto results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in CheckGuildDoor query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
return false;
}
@@ -433,7 +428,6 @@ bool ZoneDatabase::SetGuildDoor(uint8 doorid,uint16 guild_id, const char* zone)
guild_id, doorid, zone);
auto results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in SetGuildDoor query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
return false;
}
+18 -25
View File
@@ -32,7 +32,7 @@ extern WorldServer worldserver;
extern volatile bool ZoneLoaded;
void ZoneGuildManager::SendGuildRefresh(uint32 guild_id, bool name, bool motd, bool rank, bool relation) {
_log(GUILDS__REFRESH, "Sending guild refresh for %d to world, changes: name=%d, motd=%d, rank=d, relation=%d", guild_id, name, motd, rank, relation);
Log.Out(Logs::Detail, Logs::Guilds, "Sending guild refresh for %d to world, changes: name=%d, motd=%d, rank=d, relation=%d", guild_id, name, motd, rank, relation);
ServerPacket* pack = new ServerPacket(ServerOP_RefreshGuild, sizeof(ServerGuildRefresh_Struct));
ServerGuildRefresh_Struct *s = (ServerGuildRefresh_Struct *) pack->pBuffer;
s->guild_id = guild_id;
@@ -46,7 +46,7 @@ void ZoneGuildManager::SendGuildRefresh(uint32 guild_id, bool name, bool motd, b
void ZoneGuildManager::SendCharRefresh(uint32 old_guild_id, uint32 guild_id, uint32 charid) {
if(guild_id == 0) {
_log(GUILDS__REFRESH, "Guild lookup for char %d when sending char refresh.", charid);
Log.Out(Logs::Detail, Logs::Guilds, "Guild lookup for char %d when sending char refresh.", charid);
CharGuildInfo gci;
if(!GetCharInfo(charid, gci)) {
@@ -56,7 +56,7 @@ void ZoneGuildManager::SendCharRefresh(uint32 old_guild_id, uint32 guild_id, uin
}
}
_log(GUILDS__REFRESH, "Sending char refresh for %d from guild %d to world", charid, guild_id);
Log.Out(Logs::Detail, Logs::Guilds, "Sending char refresh for %d from guild %d to world", charid, guild_id);
ServerPacket* pack = new ServerPacket(ServerOP_GuildCharRefresh, sizeof(ServerGuildCharRefresh_Struct));
ServerGuildCharRefresh_Struct *s = (ServerGuildCharRefresh_Struct *) pack->pBuffer;
@@ -89,7 +89,7 @@ void ZoneGuildManager::SendRankUpdate(uint32 CharID)
}
void ZoneGuildManager::SendGuildDelete(uint32 guild_id) {
_log(GUILDS__REFRESH, "Sending guild delete for guild %d to world", guild_id);
Log.Out(Logs::Detail, Logs::Guilds, "Sending guild delete for guild %d to world", guild_id);
ServerPacket* pack = new ServerPacket(ServerOP_DeleteGuild, sizeof(ServerGuildID_Struct));
ServerGuildID_Struct *s = (ServerGuildID_Struct *) pack->pBuffer;
s->guild_id = guild_id;
@@ -261,12 +261,12 @@ void ZoneGuildManager::ProcessWorldPacket(ServerPacket *pack) {
switch(pack->opcode) {
case ServerOP_RefreshGuild: {
if(pack->size != sizeof(ServerGuildRefresh_Struct)) {
_log(GUILDS__ERROR, "Received ServerOP_RefreshGuild of incorrect size %d, expected %d", pack->size, sizeof(ServerGuildRefresh_Struct));
Log.Out(Logs::General, Logs::Error, "Received ServerOP_RefreshGuild of incorrect size %d, expected %d", pack->size, sizeof(ServerGuildRefresh_Struct));
return;
}
ServerGuildRefresh_Struct *s = (ServerGuildRefresh_Struct *) pack->pBuffer;
_log(GUILDS__REFRESH, "Received guild refresh from world for %d, changes: name=%d, motd=%d, rank=%d, relation=%d", s->guild_id, s->name_change, s->motd_change, s->rank_change, s->relation_change);
Log.Out(Logs::Detail, Logs::Guilds, "Received guild refresh from world for %d, changes: name=%d, motd=%d, rank=%d, relation=%d", s->guild_id, s->name_change, s->motd_change, s->rank_change, s->relation_change);
//reload all the guild details from the database.
RefreshGuild(s->guild_id);
@@ -295,12 +295,12 @@ void ZoneGuildManager::ProcessWorldPacket(ServerPacket *pack) {
case ServerOP_GuildCharRefresh: {
if(pack->size != sizeof(ServerGuildCharRefresh_Struct)) {
_log(GUILDS__ERROR, "Received ServerOP_RefreshGuild of incorrect size %d, expected %d", pack->size, sizeof(ServerGuildCharRefresh_Struct));
Log.Out(Logs::General, Logs::Error, "Received ServerOP_RefreshGuild of incorrect size %d, expected %d", pack->size, sizeof(ServerGuildCharRefresh_Struct));
return;
}
ServerGuildCharRefresh_Struct *s = (ServerGuildCharRefresh_Struct *) pack->pBuffer;
_log(GUILDS__REFRESH, "Received guild member refresh from world for char %d from guild %d", s->char_id, s->guild_id);
Log.Out(Logs::Detail, Logs::Guilds, "Received guild member refresh from world for char %d from guild %d", s->char_id, s->guild_id);
Client *c = entity_list.GetClientByCharID(s->char_id);
@@ -322,7 +322,7 @@ void ZoneGuildManager::ProcessWorldPacket(ServerPacket *pack) {
else if(c != nullptr && s->guild_id != GUILD_NONE) {
//char is in zone, and has changed into a new guild, send MOTD.
c->SendGuildMOTD();
if(c->GetClientVersion() >= EQClientRoF)
if(c->GetClientVersion() >= ClientVersion::RoF)
{
c->SendGuildRanks();
}
@@ -338,7 +338,7 @@ void ZoneGuildManager::ProcessWorldPacket(ServerPacket *pack) {
{
if(pack->size != sizeof(ServerGuildRankUpdate_Struct))
{
_log(GUILDS__ERROR, "Received ServerOP_RankUpdate of incorrect size %d, expected %d",
Log.Out(Logs::General, Logs::Error, "Received ServerOP_RankUpdate of incorrect size %d, expected %d",
pack->size, sizeof(ServerGuildRankUpdate_Struct));
return;
@@ -364,12 +364,12 @@ void ZoneGuildManager::ProcessWorldPacket(ServerPacket *pack) {
case ServerOP_DeleteGuild: {
if(pack->size != sizeof(ServerGuildID_Struct)) {
_log(GUILDS__ERROR, "Received ServerOP_DeleteGuild of incorrect size %d, expected %d", pack->size, sizeof(ServerGuildID_Struct));
Log.Out(Logs::General, Logs::Error, "Received ServerOP_DeleteGuild of incorrect size %d, expected %d", pack->size, sizeof(ServerGuildID_Struct));
return;
}
ServerGuildID_Struct *s = (ServerGuildID_Struct *) pack->pBuffer;
_log(GUILDS__REFRESH, "Received guild delete from world for guild %d", s->guild_id);
Log.Out(Logs::Detail, Logs::Guilds, "Received guild delete from world for guild %d", s->guild_id);
//clear all the guild tags.
entity_list.RefreshAllGuildInfo(s->guild_id);
@@ -417,10 +417,10 @@ void ZoneGuildManager::ProcessWorldPacket(ServerPacket *pack) {
if (!c || !c->IsInAGuild())
{
_log(GUILDS__ERROR,"Invalid Client or not in guild. ID=%i", FromID);
Log.Out(Logs::Detail, Logs::Guilds,"Invalid Client or not in guild. ID=%i", FromID);
break;
}
_log(GUILDS__IN_PACKETS,"Processing ServerOP_OnlineGuildMembersResponse");
Log.Out(Logs::Detail, Logs::Guilds,"Processing ServerOP_OnlineGuildMembersResponse");
EQApplicationPacket *outapp = new EQApplicationPacket(OP_GuildMemberUpdate, sizeof(GuildMemberUpdate_Struct));
GuildMemberUpdate_Struct *gmus = (GuildMemberUpdate_Struct*)outapp->pBuffer;
char Name[64];
@@ -433,7 +433,7 @@ void ZoneGuildManager::ProcessWorldPacket(ServerPacket *pack) {
VARSTRUCT_DECODE_STRING(Name, Buffer);
strn0cpy(gmus->MemberName, Name, sizeof(gmus->MemberName));
gmus->ZoneID = VARSTRUCT_DECODE_TYPE(uint32, Buffer);
_log(GUILDS__OUT_PACKETS,"Sending OP_GuildMemberUpdate to %i. Name=%s ZoneID=%i",FromID,Name,gmus->ZoneID);
Log.Out(Logs::Detail, Logs::Guilds,"Sending OP_GuildMemberUpdate to %i. Name=%s ZoneID=%i",FromID,Name,gmus->ZoneID);
c->QueuePacket(outapp);
}
safe_delete(outapp);
@@ -603,7 +603,6 @@ bool GuildBankManager::Load(uint32 guildID)
"FROM `guild_bank` WHERE `guildid` = %i", guildID);
auto results = database.QueryDatabase(query);
if(!results.Success()) {
_log(GUILDS__BANK_ERROR, "Error Loading guild bank: %s, %s", query.c_str(), results.ErrorMessage().c_str());
return false;
}
@@ -684,7 +683,7 @@ void GuildBankManager::SendGuildBank(Client *c)
if(Iterator == Banks.end())
{
_log(GUILDS__BANK_ERROR, "Unable to find guild bank for guild ID %i", c->GuildID());
Log.Out(Logs::General, Logs::Error, "Unable to find guild bank for guild ID %i", c->GuildID());
return;
}
@@ -800,7 +799,7 @@ bool GuildBankManager::AddItem(uint32 GuildID, uint8 Area, uint32 ItemID, int32
if(Iterator == Banks.end())
{
_log(GUILDS__BANK_ERROR, "Unable to find guild bank for guild ID %i", GuildID);
Log.Out(Logs::General, Logs::Error, "Unable to find guild bank for guild ID %i", GuildID);
return false;
}
@@ -846,7 +845,7 @@ bool GuildBankManager::AddItem(uint32 GuildID, uint8 Area, uint32 ItemID, int32
if(Slot < 0)
{
_log(GUILDS__BANK_ERROR, "No space to add item to the guild bank.");
Log.Out(Logs::General, Logs::Error, "No space to add item to the guild bank.");
return false;
}
@@ -857,7 +856,6 @@ bool GuildBankManager::AddItem(uint32 GuildID, uint8 Area, uint32 ItemID, int32
GuildID, Area, Slot, ItemID, QtyOrCharges, Donator, Permissions, WhoFor);
auto results = database.QueryDatabase(query);
if(!results.Success()) {
_log(GUILDS__BANK_ERROR, "Insert Error: %s : %s", query.c_str(), results.ErrorMessage().c_str());
return false;
}
@@ -922,7 +920,6 @@ int GuildBankManager::Promote(uint32 guildID, int slotID)
"LIMIT 1", mainSlot, guildID, slotID);
auto results = database.QueryDatabase(query);
if (!results.Success()) {
_log(GUILDS__BANK_ERROR, "error promoting item: %s : %s", query.c_str(), results.ErrorMessage().c_str());
return -1;
}
@@ -974,7 +971,6 @@ void GuildBankManager::SetPermissions(uint32 guildID, uint16 slotID, uint32 perm
auto results = database.QueryDatabase(query);
if(!results.Success())
{
_log(GUILDS__BANK_ERROR, "error changing permissions: %s : %s", query.c_str(), results.ErrorMessage().c_str());
return;
}
@@ -1124,7 +1120,6 @@ bool GuildBankManager::DeleteItem(uint32 guildID, uint16 area, uint16 slotID, ui
guildID, area, slotID);
auto results = database.QueryDatabase(query);
if(!results.Success()) {
_log(GUILDS__BANK_ERROR, "Delete item failed. %s : %s", query.c_str(), results.ErrorMessage().c_str());
return false;
}
@@ -1136,7 +1131,6 @@ bool GuildBankManager::DeleteItem(uint32 guildID, uint16 area, uint16 slotID, ui
BankArea[slotID].Quantity - quantity, guildID, area, slotID);
auto results = database.QueryDatabase(query);
if(!results.Success()) {
_log(GUILDS__BANK_ERROR, "Update item failed. %s : %s", query.c_str(), results.ErrorMessage().c_str());
return false;
}
@@ -1299,7 +1293,6 @@ void GuildBankManager::UpdateItemQuantity(uint32 guildID, uint16 area, uint16 sl
quantity, guildID, area, slotID);
auto results = database.QueryDatabase(query);
if(!results.Success()) {
_log(GUILDS__BANK_ERROR, "Update item quantity failed. %s : %s", query.c_str(), results.ErrorMessage().c_str());
return;
}
+5 -4
View File
@@ -158,7 +158,7 @@ Mob* HateList::GetClosestEntOnHateList(Mob *hater) {
auto iterator = list.begin();
while (iterator != list.end()) {
this_distance = (*iterator)->entity_on_hatelist->DistNoRootNoZ(*hater);
this_distance = DistanceSquaredNoZ((*iterator)->entity_on_hatelist->GetPosition(), hater->GetPosition());
if ((*iterator)->entity_on_hatelist != nullptr && this_distance <= close_distance) {
close_distance = this_distance;
close_entity = (*iterator)->entity_on_hatelist;
@@ -308,8 +308,9 @@ Mob *HateList::GetEntWithMostHateOnList(Mob *center)
continue;
}
auto hateEntryPosition = glm::vec3(cur->entity_on_hatelist->GetX(), cur->entity_on_hatelist->GetY(), cur->entity_on_hatelist->GetZ());
if (center->IsNPC() && center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
if (!zone->watermap->InLiquid(cur->entity_on_hatelist->GetX(), cur->entity_on_hatelist->GetY(), cur->entity_on_hatelist->GetZ())) {
if (!zone->watermap->InLiquid(hateEntryPosition)) {
skipped_count++;
++iterator;
continue;
@@ -434,7 +435,7 @@ Mob *HateList::GetEntWithMostHateOnList(Mob *center)
{
struct_HateList *cur = (*iterator);
if (center->IsNPC() && center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
if (!zone->watermap->InLiquid(cur->entity_on_hatelist->GetX(), cur->entity_on_hatelist->GetY(), cur->entity_on_hatelist->GetZ())) {
if(!zone->watermap->InLiquid(glm::vec3(cur->entity_on_hatelist->GetPosition()))) {
skipped_count++;
++iterator;
continue;
@@ -591,7 +592,7 @@ void HateList::SpellCast(Mob *caster, uint32 spell_id, float range, Mob* ae_cent
struct_HateList *h = (*iterator);
if (range > 0)
{
dist_targ = center->DistNoRoot(*h->entity_on_hatelist);
dist_targ = DistanceSquared(center->GetPosition(), h->entity_on_hatelist->GetPosition());
if (dist_targ <= range && dist_targ >= min_range2)
{
id_list.push_back(h->entity_on_hatelist->GetID());
+7 -7
View File
@@ -16,7 +16,8 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "../common/global_define.h"
#include "../common/eqemu_logsys.h"
#include "../common/linked_list.h"
#include "../common/string_util.h"
@@ -28,8 +29,8 @@
std::map<uint16, const NPCType *> Horse::horse_types;
LinkedList<NPCType *> horses_auto_delete;
Horse::Horse(Client *_owner, uint16 spell_id, float x, float y, float z, float heading)
: NPC(GetHorseType(spell_id), nullptr, x, y, z, heading, FlyMode3)
Horse::Horse(Client *_owner, uint16 spell_id, const glm::vec4& position)
: NPC(GetHorseType(spell_id), nullptr, position, FlyMode3)
{
//give the horse its proper name.
strn0cpy(name, _owner->GetCleanName(), 55);
@@ -72,12 +73,11 @@ const NPCType *Horse::BuildHorseType(uint16 spell_id) {
std::string query = StringFormat("SELECT race, gender, texture, mountspeed FROM horses WHERE filename = '%s'", fileName);
auto results = database.QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in Mount query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
return nullptr;
}
if (results.RowCount() != 1) {
LogFile->write(EQEMuLog::Error, "No Database entry for mount: %s, check the horses table", fileName);
Log.Out(Logs::General, Logs::Error, "No Database entry for mount: %s, check the horses table", fileName);
return nullptr;
}
@@ -120,13 +120,13 @@ void Client::SummonHorse(uint16 spell_id) {
return;
}
if(!Horse::IsHorseSpell(spell_id)) {
LogFile->write(EQEMuLog::Error, "%s tried to summon an unknown horse, spell id %d", GetName(), spell_id);
Log.Out(Logs::General, Logs::Error, "%s tried to summon an unknown horse, spell id %d", GetName(), spell_id);
return;
}
// No Horse, lets get them one.
Horse* horse = new Horse(this, spell_id, GetX(), GetY(), GetZ(), GetHeading());
Horse* horse = new Horse(this, spell_id, GetPosition());
//we want to manage the spawn packet ourself.
//another reason is we dont want quests executing on it.
+1 -1
View File
@@ -29,7 +29,7 @@ struct NewSpawn_Struct;
class Horse : public NPC {
public:
Horse(Client *owner, uint16 spell_id, float x, float y, float z, float heading);
Horse(Client *owner, uint16 spell_id, const glm::vec4& position);
virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
+410 -403
View File
File diff suppressed because it is too large Load Diff
+12 -3
View File
@@ -16,7 +16,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "../common/global_define.h"
#include "../common/loottable.h"
#include "../common/misc_functions.h"
@@ -145,7 +145,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml
drop_chance = zone->random.Real(0.0, 100.0);
#if EQDEBUG>=11
LogFile->write(EQEMuLog::Debug, "Drop chance for npc: %s, this chance:%f, drop roll:%f", npc->GetName(), thischance, drop_chance);
Log.Out(Logs::General, Logs::None, "Drop chance for npc: %s, this chance:%f, drop roll:%f", npc->GetName(), thischance, drop_chance);
#endif
if (thischance == 100.0 || drop_chance < thischance)
{
@@ -174,6 +174,11 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml
}
}
} // We either ran out of items or reached our limit.
npc->UpdateEquipLightValue();
// no wearchange associated with this function..so, this should not be needed
//if (npc->UpdateActiveLightValue())
// npc->SendAppearancePacket(AT_Light, npc->GetActiveLightValue());
}
//if itemlist is null, just send wear changes
@@ -187,7 +192,7 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge
ServerLootItem_Struct* item = new ServerLootItem_Struct;
#if EQDEBUG>=11
LogFile->write(EQEMuLog::Debug, "Adding drop to npc: %s, Item: %i", GetName(), item2->ID);
Log.Out(Logs::General, Logs::None, "Adding drop to npc: %s, Item: %i", GetName(), item2->ID);
#endif
EQApplicationPacket* outapp = nullptr;
@@ -359,6 +364,10 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge
entity_list.QueueClients(this, outapp);
safe_delete(outapp);
}
UpdateEquipLightValue();
if (UpdateActiveLightValue())
SendAppearancePacket(AT_Light, GetActiveLightValue());
}
void NPC::AddItem(const Item_Struct* item, uint16 charges, bool equipitem) {
+7 -7
View File
@@ -242,17 +242,17 @@ void Lua_Client::SetBindPoint(int to_zone, int to_instance) {
void Lua_Client::SetBindPoint(int to_zone, int to_instance, float new_x) {
Lua_Safe_Call_Void();
self->SetBindPoint(to_zone, to_instance, new_x);
self->SetBindPoint(to_zone, to_instance, glm::vec3(new_x,0.0f,0.0f));
}
void Lua_Client::SetBindPoint(int to_zone, int to_instance, float new_x, float new_y) {
Lua_Safe_Call_Void();
self->SetBindPoint(to_zone, to_instance, new_x, new_y);
self->SetBindPoint(to_zone, to_instance, glm::vec3(new_x, new_y, 0.0f));
}
void Lua_Client::SetBindPoint(int to_zone, int to_instance, float new_x, float new_y, float new_z) {
Lua_Safe_Call_Void();
self->SetBindPoint(to_zone, to_instance, new_x, new_y, new_z);
self->SetBindPoint(to_zone, to_instance, glm::vec3(new_x, new_y, new_z));
}
float Lua_Client::GetBindX() {
@@ -700,13 +700,13 @@ void Lua_Client::SummonItem(uint32 item_id, int charges, uint32 aug1, uint32 aug
self->SummonItem(item_id, charges, aug1, aug2, aug3, aug4, aug5);
}
void Lua_Client::SummonItem(uint32 item_id, int charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5,
void Lua_Client::SummonItem(uint32 item_id, int charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5,
bool attuned) {
Lua_Safe_Call_Void();
self->SummonItem(item_id, charges, aug1, aug2, aug3, aug4, aug5, 0, attuned);
}
void Lua_Client::SummonItem(uint32 item_id, int charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5,
void Lua_Client::SummonItem(uint32 item_id, int charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5,
bool attuned, int to_slot) {
Lua_Safe_Call_Void();
self->SummonItem(item_id, charges, aug1, aug2, aug3, aug4, aug5, 0, attuned, to_slot);
@@ -834,7 +834,7 @@ void Lua_Client::SetAATitle(const char *title) {
int Lua_Client::GetClientVersion() {
Lua_Safe_Call_Int();
return self->GetClientVersion();
return static_cast<unsigned int>(self->GetClientVersion());
}
uint32 Lua_Client::GetClientVersionBit() {
@@ -1396,7 +1396,7 @@ luabind::scope lua_register_client() {
.def("SummonItem", (void(Lua_Client::*)(uint32,int,uint32,uint32,uint32,uint32))&Lua_Client::SummonItem)
.def("SummonItem", (void(Lua_Client::*)(uint32,int,uint32,uint32,uint32,uint32,uint32))&Lua_Client::SummonItem)
.def("SummonItem", (void(Lua_Client::*)(uint32,int,uint32,uint32,uint32,uint32,uint32,bool))&Lua_Client::SummonItem)
.def("SummonItem", (void(Lua_Client::*)(uint32,int,uint32,uint32,uint32,uint32,uint32,bool,int))&Lua_Client::SummonItem)
.def("SummonItem", (void(Lua_Client::*)(uint32,int,uint32,uint32,uint32,uint32,uint32,bool,int))&Lua_Client::SummonItem)
.def("SetStats", (void(Lua_Client::*)(int,int))&Lua_Client::SetStats)
.def("IncStats", (void(Lua_Client::*)(int,int))&Lua_Client::IncStats)
.def("DropItem", (void(Lua_Client::*)(int))&Lua_Client::DropItem)
+16 -8
View File
@@ -20,42 +20,50 @@ const char *Lua_Door::GetDoorName() {
float Lua_Door::GetX() {
Lua_Safe_Call_Real();
return self->GetX();
return self->GetPosition().x;
}
float Lua_Door::GetY() {
Lua_Safe_Call_Real();
return self->GetY();
return self->GetPosition().y;
}
float Lua_Door::GetZ() {
Lua_Safe_Call_Real();
return self->GetZ();
return self->GetPosition().z;
}
float Lua_Door::GetHeading() {
Lua_Safe_Call_Real();
return self->GetHeading();
return self->GetPosition().w;
}
void Lua_Door::SetX(float x) {
Lua_Safe_Call_Void();
self->SetX(x);
auto position = self->GetPosition();
position.x = x;
self->SetPosition(position);
}
void Lua_Door::SetY(float y) {
Lua_Safe_Call_Void();
self->SetY(y);
auto position = self->GetPosition();
position.y = y;
self->SetPosition(position);
}
void Lua_Door::SetZ(float z) {
Lua_Safe_Call_Void();
self->SetZ(z);
auto position = self->GetPosition();
position.z = z;
self->SetPosition(position);
}
void Lua_Door::SetHeading(float h) {
Lua_Safe_Call_Void();
self->SetHeading(h);
auto position = self->GetPosition();
position.w = h;
self->SetPosition(position);
}
void Lua_Door::SetLocation(float x, float y, float z) {
+2 -2
View File
@@ -298,12 +298,12 @@ void Lua_EntityList::MessageGroup(Lua_Mob who, bool skip_close, uint32 type, con
Lua_Client Lua_EntityList::GetRandomClient(float x, float y, float z, float dist) {
Lua_Safe_Call_Class(Lua_Client);
return self->GetRandomClient(x, y, z, dist);
return self->GetRandomClient(glm::vec3(x, y, z), dist);
}
Lua_Client Lua_EntityList::GetRandomClient(float x, float y, float z, float dist, Lua_Client exclude) {
Lua_Safe_Call_Class(Lua_Client);
return self->GetRandomClient(x, y, z, dist, exclude);
return self->GetRandomClient(glm::vec3(x, y, z), dist, exclude);
}
Lua_Mob_List Lua_EntityList::GetMobList() {
+46 -30
View File
@@ -17,6 +17,7 @@
#include "questmgr.h"
#include "qglobals.h"
#include "../common/timer.h"
#include "../common/eqemu_logsys.h"
struct Events { };
struct Factions { };
@@ -124,7 +125,7 @@ void register_event(std::string package_name, std::string name, int evt, luabind
e.encounter_name = name;
e.lua_reference = func;
e.event_id = static_cast<QuestEventID>(evt);
auto liter = lua_encounter_events_registered.find(package_name);
if(liter == lua_encounter_events_registered.end()) {
std::list<lua_registered_event> elist;
@@ -200,8 +201,8 @@ void unregister_player_event(int evt) {
void register_item_event(std::string name, int evt, int item_id, luabind::adl::object func) {
std::string package_name = "item_";
package_name += std::to_string(static_cast<long long>(item_id));
package_name += std::to_string(item_id);
if(luabind::type(func) == LUA_TFUNCTION) {
register_event(package_name, name, evt, func);
}
@@ -214,7 +215,7 @@ void register_item_event(int evt, int item_id, luabind::adl::object func) {
void unregister_item_event(std::string name, int evt, int item_id) {
std::string package_name = "item_";
package_name += std::to_string(static_cast<long long>(item_id));
package_name += std::to_string(item_id);
unregister_event(package_name, name, evt);
}
@@ -251,13 +252,13 @@ void unregister_spell_event(int evt, int spell_id) {
}
Lua_Mob lua_spawn2(int npc_type, int grid, int unused, double x, double y, double z, double heading) {
return Lua_Mob(quest_manager.spawn2(npc_type, grid, unused,
static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(heading)));
auto position = glm::vec4(x, y, z, heading);
return Lua_Mob(quest_manager.spawn2(npc_type, grid, unused, position));
}
Lua_Mob lua_unique_spawn(int npc_type, int grid, int unused, double x, double y, double z, double heading = 0.0) {
return Lua_Mob(quest_manager.unique_spawn(npc_type, grid, unused,
static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(heading)));
auto position = glm::vec4(x, y, z, heading);
return Lua_Mob(quest_manager.unique_spawn(npc_type, grid, unused, position));
}
Lua_Mob lua_spawn_from_spawn2(uint32 spawn2_id) {
@@ -421,15 +422,15 @@ void lua_pause(int duration) {
}
void lua_move_to(float x, float y, float z) {
quest_manager.moveto(x, y, z, 0, false);
quest_manager.moveto(glm::vec4(x, y, z, 0.0f), false);
}
void lua_move_to(float x, float y, float z, float h) {
quest_manager.moveto(x, y, z, h, false);
quest_manager.moveto(glm::vec4(x, y, z, h), false);
}
void lua_move_to(float x, float y, float z, float h, bool save_guard_spot) {
quest_manager.moveto(x, y, z, h, save_guard_spot);
quest_manager.moveto(glm::vec4(x, y, z, h), save_guard_spot);
}
void lua_path_resume() {
@@ -485,11 +486,11 @@ void lua_toggle_spawn_event(int event_id, bool enable, bool strict, bool reset)
}
void lua_summon_burried_player_corpse(uint32 char_id, float x, float y, float z, float h) {
quest_manager.summonburriedplayercorpse(char_id, x, y, z, h);
quest_manager.summonburriedplayercorpse(char_id, glm::vec4(x, y, z, h));
}
void lua_summon_all_player_corpses(uint32 char_id, float x, float y, float z, float h) {
quest_manager.summonallplayercorpses(char_id, x, y, z, h);
quest_manager.summonallplayercorpses(char_id, glm::vec4(x, y, z, h));
}
int lua_get_player_burried_corpse_count(uint32 char_id) {
@@ -685,23 +686,23 @@ int lua_get_level(int type) {
}
void lua_create_ground_object(uint32 item_id, float x, float y, float z, float h) {
quest_manager.CreateGroundObject(item_id, x, y, z, h);
quest_manager.CreateGroundObject(item_id, glm::vec4(x, y, z, h));
}
void lua_create_ground_object(uint32 item_id, float x, float y, float z, float h, uint32 decay_time) {
quest_manager.CreateGroundObject(item_id, x, y, z, h, decay_time);
quest_manager.CreateGroundObject(item_id, glm::vec4(x, y, z, h), decay_time);
}
void lua_create_ground_object_from_model(const char *model, float x, float y, float z, float h) {
quest_manager.CreateGroundObjectFromModel(model, x, y, z, h);
quest_manager.CreateGroundObjectFromModel(model, glm::vec4(x, y, z, h));
}
void lua_create_ground_object_from_model(const char *model, float x, float y, float z, float h, int type) {
quest_manager.CreateGroundObjectFromModel(model, x, y, z, h, type);
quest_manager.CreateGroundObjectFromModel(model, glm::vec4(x, y, z, h), type);
}
void lua_create_ground_object_from_model(const char *model, float x, float y, float z, float h, int type, uint32 decay_time) {
quest_manager.CreateGroundObjectFromModel(model, x, y, z, h, type, decay_time);
quest_manager.CreateGroundObjectFromModel(model, glm::vec4(x, y, z, h), type, decay_time);
}
void lua_create_door(const char *model, float x, float y, float z, float h, int open_type, int size) {
@@ -1036,7 +1037,7 @@ void lua_add_spawn_point(luabind::adl::object table) {
int condition_min_value = 0;
bool enabled = true;
int animation = 0;
auto cur = table["spawn2_id"];
if(luabind::type(cur) != LUA_TNIL) {
try {
@@ -1221,7 +1222,6 @@ std::string lua_get_encounter() {
return quest_manager.GetEncounter();
}
void lua_map_opcodes() {
MapOpcodes();
}
@@ -1249,6 +1249,17 @@ double lua_clock() {
return static_cast<double>(t) / 1000.0;
}
void lua_debug(std::string message) {
Log.Out(Logs::General, Logs::QuestDebug, message);
}
void lua_debug(std::string message, int level) {
if (level < Logs::General || level > Logs::Detail)
return;
Log.Out(static_cast<Logs::DebugLevel>(level), Logs::QuestDebug, message);
}
#define LuaCreateNPCParse(name, c_type, default_value) do { \
cur = table[#name]; \
if(luabind::type(cur) != LUA_TNIL) { \
@@ -1284,7 +1295,7 @@ void lua_create_npc(luabind::adl::object table, float x, float y, float z, float
if(luabind::type(table) != LUA_TTABLE) {
return;
}
NPCType* npc_type = new NPCType;
memset(npc_type, 0, sizeof(NPCType));
@@ -1356,7 +1367,7 @@ void lua_create_npc(luabind::adl::object table, float x, float y, float z, float
LuaCreateNPCParseString(special_abilities, 512, "");
LuaCreateNPCParse(d_melee_texture1, uint16, 0);
LuaCreateNPCParse(d_melee_texture2, uint16, 0);
LuaCreateNPCParseString(ammo_idfile, 32, "");
LuaCreateNPCParseString(ammo_idfile, 30, "");
LuaCreateNPCParse(prim_melee_type, uint8, 0);
LuaCreateNPCParse(sec_melee_type, uint8, 0);
LuaCreateNPCParse(ranged_type, uint8, 0);
@@ -1391,7 +1402,7 @@ void lua_create_npc(luabind::adl::object table, float x, float y, float z, float
LuaCreateNPCParse(raid_target, bool, false);
LuaCreateNPCParse(probability, uint8, 0);
NPC* npc = new NPC(npc_type, nullptr, x, y, z, heading, FlyMode3);
NPC* npc = new NPC(npc_type, nullptr, glm::vec4(x, y, z, heading), FlyMode3);
npc->GiveNPCTypeData(npc_type);
entity_list.AddNPC(npc);
}
@@ -1582,7 +1593,9 @@ luabind::scope lua_register_general() {
luabind::def("disable_recipe", &lua_disable_recipe),
luabind::def("clear_npctype_cache", &lua_clear_npctype_cache),
luabind::def("clock", &lua_clock),
luabind::def("create_npc", &lua_create_npc)
luabind::def("create_npc", &lua_create_npc),
luabind::def("debug", (void(*)(std::string))&lua_debug),
luabind::def("debug", (void(*)(std::string, int))&lua_debug)
];
}
@@ -1612,6 +1625,7 @@ luabind::scope lua_register_events() {
luabind::value("cast_on", static_cast<int>(EVENT_CAST_ON)),
luabind::value("task_accepted", static_cast<int>(EVENT_TASK_ACCEPTED)),
luabind::value("task_stage_complete", static_cast<int>(EVENT_TASK_STAGE_COMPLETE)),
luabind::value("environmental_damage", static_cast<int>(EVENT_ENVIRONMENTAL_DAMAGE)),
luabind::value("task_update", static_cast<int>(EVENT_TASK_UPDATE)),
luabind::value("task_complete", static_cast<int>(EVENT_TASK_COMPLETE)),
luabind::value("task_fail", static_cast<int>(EVENT_TASK_FAIL)),
@@ -1758,12 +1772,14 @@ luabind::scope lua_register_client_version() {
return luabind::class_<ClientVersions>("ClientVersion")
.enum_("constants")
[
luabind::value("Unknown", static_cast<int>(EQClientUnknown)),
luabind::value("Titanium", static_cast<int>(EQClientTitanium)),
luabind::value("SoF", static_cast<int>(EQClientSoF)),
luabind::value("SoD", static_cast<int>(EQClientSoD)),
luabind::value("Underfoot", static_cast<int>(EQClientUnderfoot)),
luabind::value("RoF", static_cast<int>(EQClientRoF))
luabind::value("Unknown", static_cast<int>(ClientVersion::Unknown)),
luabind::value("Titanium", static_cast<int>(ClientVersion::Titanium)),
luabind::value("SoF", static_cast<int>(ClientVersion::SoF)),
luabind::value("SoD", static_cast<int>(ClientVersion::SoD)),
luabind::value("Underfoot", static_cast<int>(ClientVersion::UF)), // deprecated
luabind::value("UF", static_cast<int>(ClientVersion::UF)),
luabind::value("RoF", static_cast<int>(ClientVersion::RoF)),
luabind::value("RoF2", static_cast<int>(ClientVersion::RoF2))
];
}
+22 -16
View File
@@ -576,6 +576,11 @@ int Lua_Mob::GetCorruption() {
return self->GetCorrup();
}
int Lua_Mob::GetPhR() {
Lua_Safe_Call_Int();
return self->GetPhR();
}
int Lua_Mob::GetMaxSTR() {
Lua_Safe_Call_Int();
return self->GetMaxSTR();
@@ -626,7 +631,7 @@ double Lua_Mob::ResistSpell(int resist_type, int spell_id, Lua_Mob caster, bool
return self->ResistSpell(resist_type, spell_id, caster, use_resist_override, resist_override);
}
double Lua_Mob::ResistSpell(int resist_type, int spell_id, Lua_Mob caster, bool use_resist_override, int resist_override,
double Lua_Mob::ResistSpell(int resist_type, int spell_id, Lua_Mob caster, bool use_resist_override, int resist_override,
bool charisma_check) {
Lua_Safe_Call_Real();
return self->ResistSpell(resist_type, spell_id, caster, use_resist_override, resist_override, charisma_check);
@@ -669,22 +674,22 @@ double Lua_Mob::GetHeading() {
double Lua_Mob::GetWaypointX() {
Lua_Safe_Call_Real();
return self->GetCWPX();
return self->GetCurrentWayPoint().x;
}
double Lua_Mob::GetWaypointY() {
Lua_Safe_Call_Real();
return self->GetCWPY();
return self->GetCurrentWayPoint().y;
}
double Lua_Mob::GetWaypointZ() {
Lua_Safe_Call_Real();
return self->GetCWPZ();
return self->GetCurrentWayPoint().z;
}
double Lua_Mob::GetWaypointH() {
Lua_Safe_Call_Real();
return self->GetCWPH();
return self->GetCurrentWayPoint().w;
}
double Lua_Mob::GetWaypointPause() {
@@ -772,19 +777,19 @@ bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot, int cast_time, in
return self->CastSpell(spell_id, target_id, slot, cast_time, mana_cost, nullptr, static_cast<uint32>(item_slot));
}
bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot, int cast_time, int mana_cost, int item_slot, int timer,
bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot, int cast_time, int mana_cost, int item_slot, int timer,
int timer_duration) {
Lua_Safe_Call_Bool();
return self->CastSpell(spell_id, target_id, slot, cast_time, mana_cost, nullptr, static_cast<uint32>(item_slot),
return self->CastSpell(spell_id, target_id, slot, cast_time, mana_cost, nullptr, static_cast<uint32>(item_slot),
static_cast<uint32>(timer), static_cast<uint32>(timer_duration));
}
bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot, int cast_time, int mana_cost, int item_slot, int timer,
bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot, int cast_time, int mana_cost, int item_slot, int timer,
int timer_duration, int resist_adjust) {
Lua_Safe_Call_Bool();
int16 res = resist_adjust;
return self->CastSpell(spell_id, target_id, slot, cast_time, mana_cost, nullptr, static_cast<uint32>(item_slot),
return self->CastSpell(spell_id, target_id, slot, cast_time, mana_cost, nullptr, static_cast<uint32>(item_slot),
static_cast<uint32>(timer), static_cast<uint32>(timer_duration), 0, &res);
}
@@ -836,7 +841,7 @@ Lua_Mob Lua_Mob::GetOwner() {
Lua_HateList Lua_Mob::GetHateList() {
Lua_Safe_Call_Class(Lua_HateList);
Lua_HateList ret;
auto h_list = self->GetHateList();
auto iter = h_list.begin();
while(iter != h_list.end()) {
@@ -1217,7 +1222,7 @@ bool Lua_Mob::EntityVariableExists(const char *name) {
void Lua_Mob::Signal(uint32 id) {
Lua_Safe_Call_Void();
if(self->IsClient()) {
self->CastToClient()->Signal(id);
} else if(self->IsNPC()) {
@@ -1250,7 +1255,7 @@ void Lua_Mob::DoSpecialAttackDamage(Lua_Mob other, int skill, int max_damage, in
self->DoSpecialAttackDamage(other, static_cast<SkillUseTypes>(skill), max_damage, min_damage, hate_override, reuse_time);
}
void Lua_Mob::DoSpecialAttackDamage(Lua_Mob other, int skill, int max_damage, int min_damage, int hate_override, int reuse_time,
void Lua_Mob::DoSpecialAttackDamage(Lua_Mob other, int skill, int max_damage, int min_damage, int hate_override, int reuse_time,
bool hit_chance) {
Lua_Safe_Call_Void();
self->DoSpecialAttackDamage(other, static_cast<SkillUseTypes>(skill), max_damage, min_damage, hate_override, reuse_time, hit_chance);
@@ -1281,7 +1286,7 @@ void Lua_Mob::DoThrowingAttackDmg(Lua_Mob other, Lua_ItemInst range_weapon, Lua_
self->DoThrowingAttackDmg(other, range_weapon, item, weapon_damage, chance_mod);
}
void Lua_Mob::DoThrowingAttackDmg(Lua_Mob other, Lua_ItemInst range_weapon, Lua_Item item, int weapon_damage, int chance_mod,
void Lua_Mob::DoThrowingAttackDmg(Lua_Mob other, Lua_ItemInst range_weapon, Lua_Item item, int weapon_damage, int chance_mod,
int focus) {
Lua_Safe_Call_Void();
self->DoThrowingAttackDmg(other, range_weapon, item, weapon_damage, chance_mod, focus);
@@ -1332,7 +1337,7 @@ void Lua_Mob::DoArcheryAttackDmg(Lua_Mob other, Lua_ItemInst range_weapon, Lua_I
self->DoArcheryAttackDmg(other, range_weapon, ammo, weapon_damage, chance_mod);
}
void Lua_Mob::DoArcheryAttackDmg(Lua_Mob other, Lua_ItemInst range_weapon, Lua_ItemInst ammo, int weapon_damage, int chance_mod,
void Lua_Mob::DoArcheryAttackDmg(Lua_Mob other, Lua_ItemInst range_weapon, Lua_ItemInst ammo, int weapon_damage, int chance_mod,
int focus) {
Lua_Safe_Call_Void();
self->DoArcheryAttackDmg(other, range_weapon, ammo, weapon_damage, chance_mod, focus);
@@ -1390,7 +1395,7 @@ void Lua_Mob::ProjectileAnimation(Lua_Mob to, int item_id, bool is_arrow, double
void Lua_Mob::ProjectileAnimation(Lua_Mob to, int item_id, bool is_arrow, double speed, double angle, double tilt, double arc) {
Lua_Safe_Call_Void();
self->ProjectileAnimation(to, item_id, is_arrow, static_cast<float>(speed), static_cast<float>(angle), static_cast<float>(tilt),
self->ProjectileAnimation(to, item_id, is_arrow, static_cast<float>(speed), static_cast<float>(angle), static_cast<float>(tilt),
static_cast<float>(arc));
}
@@ -1630,7 +1635,7 @@ void Lua_Mob::SendSpellEffect(uint32 effect_id, uint32 duration, uint32 finish_d
self->SendSpellEffect(effect_id, duration, finish_delay, zone_wide, unk020, perm_effect);
}
void Lua_Mob::SendSpellEffect(uint32 effect_id, uint32 duration, uint32 finish_delay, bool zone_wide, uint32 unk020, bool perm_effect,
void Lua_Mob::SendSpellEffect(uint32 effect_id, uint32 duration, uint32 finish_delay, bool zone_wide, uint32 unk020, bool perm_effect,
Lua_Client c) {
Lua_Safe_Call_Void();
self->SendSpellEffect(effect_id, duration, finish_delay, zone_wide, unk020, perm_effect, c);
@@ -1962,6 +1967,7 @@ luabind::scope lua_register_mob() {
.def("GetPR", &Lua_Mob::GetPR)
.def("GetCR", &Lua_Mob::GetCR)
.def("GetCorruption", &Lua_Mob::GetCorruption)
.def("GetPhR", &Lua_Mob::GetPhR)
.def("GetMaxSTR", &Lua_Mob::GetMaxSTR)
.def("GetMaxSTA", &Lua_Mob::GetMaxSTA)
.def("GetMaxDEX", &Lua_Mob::GetMaxDEX)
+1
View File
@@ -128,6 +128,7 @@ public:
int GetPR();
int GetCR();
int GetCorruption();
int GetPhR();
int GetMaxSTR();
int GetMaxSTA();
int GetMaxDEX();
+9 -8
View File
@@ -269,7 +269,8 @@ void Lua_NPC::PauseWandering(int pause_time) {
void Lua_NPC::MoveTo(float x, float y, float z, float h, bool save) {
Lua_Safe_Call_Void();
self->MoveTo(x, y, z, h, save);
auto position = glm::vec4(x, y, z, h);
self->MoveTo(position, save);
}
void Lua_NPC::NextGuardPosition() {
@@ -314,37 +315,37 @@ int Lua_NPC::GetSpawnPointID() {
float Lua_NPC::GetSpawnPointX() {
Lua_Safe_Call_Real();
return self->GetSpawnPointX();
return self->GetSpawnPoint().x;
}
float Lua_NPC::GetSpawnPointY() {
Lua_Safe_Call_Real();
return self->GetSpawnPointY();
return self->GetSpawnPoint().y;
}
float Lua_NPC::GetSpawnPointZ() {
Lua_Safe_Call_Real();
return self->GetSpawnPointZ();
return self->GetSpawnPoint().z;
}
float Lua_NPC::GetSpawnPointH() {
Lua_Safe_Call_Real();
return self->GetSpawnPointH();
return self->GetSpawnPoint().w;
}
float Lua_NPC::GetGuardPointX() {
Lua_Safe_Call_Real();
return self->GetGuardPointX();
return self->GetGuardPoint().x;
}
float Lua_NPC::GetGuardPointY() {
Lua_Safe_Call_Real();
return self->GetGuardPointY();
return self->GetGuardPoint().y;
}
float Lua_NPC::GetGuardPointZ() {
Lua_Safe_Call_Real();
return self->GetGuardPointZ();
return self->GetGuardPoint().z;
}
void Lua_NPC::SetPrimSkill(int skill_id) {
+19 -17
View File
@@ -67,6 +67,7 @@ const char *LuaEvents[_LargestEventID] = {
"event_aggro_say",
"event_player_pickup",
"event_popup_response",
"event_environmental_damage",
"event_proximity_say",
"event_cast",
"event_cast_begin",
@@ -164,6 +165,7 @@ LuaParser::LuaParser() {
NPCArgumentDispatch[EVENT_LEAVE_AREA] = handle_npc_area;
PlayerArgumentDispatch[EVENT_SAY] = handle_player_say;
PlayerArgumentDispatch[EVENT_ENVIRONMENTAL_DAMAGE] = handle_player_environmental_damage;
PlayerArgumentDispatch[EVENT_DEATH] = handle_player_death;
PlayerArgumentDispatch[EVENT_DEATH_COMPLETE] = handle_player_death;
PlayerArgumentDispatch[EVENT_TIMER] = handle_player_timer;
@@ -235,7 +237,7 @@ int LuaParser::EventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data,
return 0;
}
std::string package_name = "npc_" + std::to_string(static_cast<long long>(npc->GetNPCTypeID()));
std::string package_name = "npc_" + std::to_string(npc->GetNPCTypeID());
return _EventNPC(package_name, evt, npc, init, data, extra_data, extra_pointers);
}
@@ -425,7 +427,7 @@ int LuaParser::EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *
}
std::string package_name = "item_";
package_name += std::to_string(static_cast<long long>(item->GetID()));
package_name += std::to_string(item->GetID());
return _EventItem(package_name, evt, client, item, mob, data, extra_data, extra_pointers);
}
@@ -499,12 +501,12 @@ int LuaParser::EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spe
return 0;
}
std::string package_name = "spell_" + std::to_string(static_cast<long long>(spell_id));
std::string package_name = "spell_" + std::to_string(spell_id);
if(!SpellHasQuestSub(spell_id, evt)) {
return 0;
}
return _EventSpell(package_name, evt, npc, client, spell_id, extra_data, extra_pointers);
}
@@ -646,7 +648,7 @@ bool LuaParser::HasQuestSub(uint32 npc_id, QuestEventID evt) {
return false;
}
std::string package_name = "npc_" + std::to_string(static_cast<long long>(npc_id));
std::string package_name = "npc_" + std::to_string(npc_id);
const char *subname = LuaEvents[evt];
return HasFunction(subname, package_name);
@@ -688,7 +690,7 @@ bool LuaParser::SpellHasQuestSub(uint32 spell_id, QuestEventID evt) {
return false;
}
std::string package_name = "spell_" + std::to_string(static_cast<long long>(spell_id));
std::string package_name = "spell_" + std::to_string(spell_id);
const char *subname = LuaEvents[evt];
return HasFunction(subname, package_name);
@@ -704,7 +706,7 @@ bool LuaParser::ItemHasQuestSub(ItemInst *itm, QuestEventID evt) {
}
std::string package_name = "item_";
package_name += std::to_string(static_cast<long long>(itm->GetID()));
package_name += std::to_string(itm->GetID());
const char *subname = LuaEvents[evt];
return HasFunction(subname, package_name);
@@ -723,7 +725,7 @@ bool LuaParser::EncounterHasQuestSub(std::string encounter_name, QuestEventID ev
}
void LuaParser::LoadNPCScript(std::string filename, int npc_id) {
std::string package_name = "npc_" + std::to_string(static_cast<long long>(npc_id));
std::string package_name = "npc_" + std::to_string(npc_id);
LoadScript(filename, package_name);
}
@@ -744,13 +746,13 @@ void LuaParser::LoadItemScript(std::string filename, ItemInst *item) {
if (item == nullptr)
return;
std::string package_name = "item_";
package_name += std::to_string(static_cast<long long>(item->GetID()));
package_name += std::to_string(item->GetID());
LoadScript(filename, package_name);
}
void LuaParser::LoadSpellScript(std::string filename, uint32 spell_id) {
std::string package_name = "spell_" + std::to_string(static_cast<long long>(spell_id));
std::string package_name = "spell_" + std::to_string(spell_id);
LoadScript(filename, package_name);
}
@@ -1011,8 +1013,8 @@ int LuaParser::DispatchEventNPC(QuestEventID evt, NPC* npc, Mob *init, std::stri
if(!npc)
return 0;
std::string package_name = "npc_" + std::to_string(static_cast<long long>(npc->GetNPCTypeID()));
int ret = 0;
std::string package_name = "npc_" + std::to_string(npc->GetNPCTypeID());
int ret = 0;
auto iter = lua_encounter_events_registered.find(package_name);
if(iter != lua_encounter_events_registered.end()) {
@@ -1085,11 +1087,11 @@ int LuaParser::DispatchEventItem(QuestEventID evt, Client *client, ItemInst *ite
if(!item)
return 0;
std::string package_name = "item_";
package_name += std::to_string(static_cast<long long>(item->GetID()));
int ret = 0;
package_name += std::to_string(item->GetID());
int ret = 0;
auto iter = lua_encounter_events_registered.find(package_name);
if(iter != lua_encounter_events_registered.end()) {
auto riter = iter->second.begin();
@@ -1129,7 +1131,7 @@ int LuaParser::DispatchEventSpell(QuestEventID evt, NPC* npc, Client *client, ui
return 0;
}
std::string package_name = "spell_" + std::to_string(static_cast<long long>(spell_id));
std::string package_name = "spell_" + std::to_string(spell_id);
int ret = 0;
auto iter = lua_encounter_events_registered.find(package_name);
+14 -1
View File
@@ -56,7 +56,7 @@ void handle_npc_event_trade(QuestInterface *parse, lua_State* L, NPC* npc, Mob *
if(extra_pointers) {
size_t sz = extra_pointers->size();
for(size_t i = 0; i < sz; ++i) {
std::string prefix = "item" + std::to_string(static_cast<long long>(i + 1));
std::string prefix = "item" + std::to_string(i + 1);
ItemInst *inst = EQEmu::any_cast<ItemInst*>(extra_pointers->at(i));
Lua_ItemInst l_inst = inst;
@@ -246,6 +246,19 @@ void handle_player_say(QuestInterface *parse, lua_State* L, Client* client, std:
lua_setfield(L, -2, "language");
}
void handle_player_environmental_damage(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers){
Seperator sep(data.c_str());
lua_pushinteger(L, std::stoi(sep.arg[0]));
lua_setfield(L, -2, "env_damage");
lua_pushinteger(L, std::stoi(sep.arg[1]));
lua_setfield(L, -2, "env_damage_type");
lua_pushinteger(L, std::stoi(sep.arg[2]));
lua_setfield(L, -2, "env_final_damage");
}
void handle_player_death(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers) {
Seperator sep(data.c_str());
+2
View File
@@ -44,6 +44,8 @@ void handle_npc_null(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, s
//Player
void handle_player_say(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers);
void handle_player_environmental_damage(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers);
void handle_player_death(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers);
void handle_player_timer(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
+41 -41
View File
@@ -1,4 +1,4 @@
#include "../common/debug.h"
#include "../common/global_define.h"
#include "../common/misc_functions.h"
#include "map.h"
@@ -62,17 +62,17 @@ Map::~Map() {
}
}
float Map::FindBestZ(Vertex &start, Vertex *result) const {
float Map::FindBestZ(glm::vec3 &start, glm::vec3 *result) const {
if (!imp)
return false;
Vertex tmp;
glm::vec3 tmp;
if(!result)
result = &tmp;
start.z += RuleI(Map, FindBestZHeightAdjust);
Vertex from(start.x, start.y, start.z);
Vertex to(start.x, start.y, BEST_Z_INVALID);
glm::vec3 from(start.x, start.y, start.z);
glm::vec3 to(start.x, start.y, BEST_Z_INVALID);
float hit_distance;
bool hit = false;
@@ -93,19 +93,19 @@ float Map::FindBestZ(Vertex &start, Vertex *result) const {
return BEST_Z_INVALID;
}
bool Map::LineIntersectsZone(Vertex start, Vertex end, float step, Vertex *result) const {
bool Map::LineIntersectsZone(glm::vec3 start, glm::vec3 end, float step, glm::vec3 *result) const {
if(!imp)
return false;
return imp->rm->raycast((const RmReal*)&start, (const RmReal*)&end, (RmReal*)result, nullptr, nullptr);
}
bool Map::LineIntersectsZoneNoZLeaps(Vertex start, Vertex end, float step_mag, Vertex *result) const {
bool Map::LineIntersectsZoneNoZLeaps(glm::vec3 start, glm::vec3 end, float step_mag, glm::vec3 *result) const {
if (!imp)
return false;
float z = BEST_Z_INVALID;
Vertex step;
Vertex cur;
glm::vec3 step;
glm::vec3 cur;
cur.x = start.x;
cur.y = start.y;
cur.z = start.z;
@@ -139,11 +139,11 @@ bool Map::LineIntersectsZoneNoZLeaps(Vertex start, Vertex end, float step_mag, V
while(cur.x != end.x || cur.y != end.y || cur.z != end.z)
{
steps++;
Vertex me;
glm::vec3 me;
me.x = cur.x;
me.y = cur.y;
me.z = cur.z;
Vertex hit;
glm::vec3 hit;
float best_z = FindBestZ(me, &hit);
float diff = best_z - z;
@@ -184,7 +184,7 @@ bool Map::LineIntersectsZoneNoZLeaps(Vertex start, Vertex end, float step_mag, V
return false;
}
bool Map::CheckLoS(Vertex myloc, Vertex oloc) const {
bool Map::CheckLoS(glm::vec3 myloc, glm::vec3 oloc) const {
if(!imp)
return false;
@@ -250,22 +250,22 @@ bool Map::LoadV1(FILE *f) {
return false;
}
std::vector<Vertex> verts;
std::vector<glm::vec3> verts;
std::vector<uint32> indices;
for(uint32 i = 0; i < face_count; ++i) {
Vertex a;
Vertex b;
Vertex c;
glm::vec3 a;
glm::vec3 b;
glm::vec3 c;
float normals[4];
if(fread(&a, sizeof(Vertex), 1, f) != 1) {
if(fread(&a, sizeof(glm::vec3), 1, f) != 1) {
return false;
}
if(fread(&b, sizeof(Vertex), 1, f) != 1) {
if(fread(&b, sizeof(glm::vec3), 1, f) != 1) {
return false;
}
if(fread(&c, sizeof(Vertex), 1, f) != 1) {
if(fread(&c, sizeof(glm::vec3), 1, f) != 1) {
return false;
}
@@ -309,7 +309,7 @@ struct ModelEntry
uint32 v1, v2, v3;
uint8 vis;
};
std::vector<Map::Vertex> verts;
std::vector<glm::vec3> verts;
std::vector<Poly> polys;
};
@@ -376,7 +376,7 @@ bool Map::LoadV2(FILE *f) {
units_per_vertex = *(float*)buf;
buf += sizeof(float);
std::vector<Vertex> verts;
std::vector<glm::vec3> verts;
std::vector<uint32> indices;
for (uint32 i = 0; i < vert_count; ++i) {
@@ -393,7 +393,7 @@ bool Map::LoadV2(FILE *f) {
z = *(float*)buf;
buf += sizeof(float);
Vertex vert(x, y, z);
glm::vec3 vert(x, y, z);
verts.push_back(vert);
}
@@ -413,9 +413,9 @@ bool Map::LoadV2(FILE *f) {
buf += sizeof(uint32);
}
std::map<std::string, std::shared_ptr<ModelEntry>> models;
std::map<std::string, std::unique_ptr<ModelEntry>> models;
for (uint32 i = 0; i < model_count; ++i) {
std::shared_ptr<ModelEntry> me(new ModelEntry);
std::unique_ptr<ModelEntry> me(new ModelEntry);
std::string name = buf;
buf += name.length() + 1;
@@ -434,7 +434,7 @@ bool Map::LoadV2(FILE *f) {
float z = *(float*)buf;
buf += sizeof(float);
me->verts[j] = Vertex(x, y, z);
me->verts[j] = glm::vec3(x, y, z);
}
me->polys.resize(poly_count);
@@ -456,7 +456,7 @@ bool Map::LoadV2(FILE *f) {
me->polys[j] = p;
}
models[name] = me;
models[name] = std::move(me);
}
for (uint32 i = 0; i < plac_count; ++i) {
@@ -487,7 +487,7 @@ bool Map::LoadV2(FILE *f) {
if (models.count(name) == 0)
continue;
auto model = models[name];
auto &model = models[name];
auto &mod_polys = model->polys;
auto &mod_verts = model->verts;
for (uint32 j = 0; j < mod_polys.size(); ++j) {
@@ -596,7 +596,7 @@ bool Map::LoadV2(FILE *f) {
for (size_t k = 0; k < model->polys.size(); ++k) {
auto &poly = model->polys[k];
Vertex v1, v2, v3;
glm::vec3 v1, v2, v3;
v1 = model->verts[poly.v1];
v2 = model->verts[poly.v2];
@@ -618,7 +618,7 @@ bool Map::LoadV2(FILE *f) {
RotateVertex(v2, 0, y_rot * 3.14159f / 180.0f, 0);
RotateVertex(v3, 0, y_rot * 3.14159f / 180.0f, 0);
Vertex correction(p_x, p_y, p_z);
glm::vec3 correction(p_x, p_y, p_z);
RotateVertex(correction, x_rot * 3.14159f / 180.0f, 0, 0);
@@ -724,10 +724,10 @@ bool Map::LoadV2(FILE *f) {
float QuadVertex4Z = QuadVertex1Z;
uint32 current_vert = (uint32)verts.size() + 3;
verts.push_back(Vertex(QuadVertex1X, QuadVertex1Y, QuadVertex1Z));
verts.push_back(Vertex(QuadVertex2X, QuadVertex2Y, QuadVertex2Z));
verts.push_back(Vertex(QuadVertex3X, QuadVertex3Y, QuadVertex3Z));
verts.push_back(Vertex(QuadVertex4X, QuadVertex4Y, QuadVertex4Z));
verts.push_back(glm::vec3(QuadVertex1X, QuadVertex1Y, QuadVertex1Z));
verts.push_back(glm::vec3(QuadVertex2X, QuadVertex2Y, QuadVertex2Z));
verts.push_back(glm::vec3(QuadVertex3X, QuadVertex3Y, QuadVertex3Z));
verts.push_back(glm::vec3(QuadVertex4X, QuadVertex4Y, QuadVertex4Z));
indices.push_back(current_vert);
indices.push_back(current_vert - 2);
@@ -790,7 +790,7 @@ bool Map::LoadV2(FILE *f) {
}
else {
i1 = (uint32)verts.size();
verts.push_back(Vertex(QuadVertex1X, QuadVertex1Y, QuadVertex1Z));
verts.push_back(glm::vec3(QuadVertex1X, QuadVertex1Y, QuadVertex1Z));
cur_verts[std::make_tuple(QuadVertex1X, QuadVertex1Y, QuadVertex1Z)] = i1;
}
@@ -801,7 +801,7 @@ bool Map::LoadV2(FILE *f) {
}
else {
i2 = (uint32)verts.size();
verts.push_back(Vertex(QuadVertex2X, QuadVertex2Y, QuadVertex2Z));
verts.push_back(glm::vec3(QuadVertex2X, QuadVertex2Y, QuadVertex2Z));
cur_verts[std::make_tuple(QuadVertex2X, QuadVertex2Y, QuadVertex2Z)] = i2;
}
@@ -812,7 +812,7 @@ bool Map::LoadV2(FILE *f) {
}
else {
i3 = (uint32)verts.size();
verts.push_back(Vertex(QuadVertex3X, QuadVertex3Y, QuadVertex3Z));
verts.push_back(glm::vec3(QuadVertex3X, QuadVertex3Y, QuadVertex3Z));
cur_verts[std::make_tuple(QuadVertex3X, QuadVertex3Y, QuadVertex3Z)] = i3;
}
@@ -823,7 +823,7 @@ bool Map::LoadV2(FILE *f) {
}
else {
i4 = (uint32)verts.size();
verts.push_back(Vertex(QuadVertex4X, QuadVertex4Y, QuadVertex4Z));
verts.push_back(glm::vec3(QuadVertex4X, QuadVertex4Y, QuadVertex4Z));
cur_verts[std::make_tuple(QuadVertex4X, QuadVertex4Y, QuadVertex4Z)] = i4;
}
@@ -859,8 +859,8 @@ bool Map::LoadV2(FILE *f) {
return true;
}
void Map::RotateVertex(Vertex &v, float rx, float ry, float rz) {
Vertex nv = v;
void Map::RotateVertex(glm::vec3 &v, float rx, float ry, float rz) {
glm::vec3 nv = v;
nv.y = (cos(rx) * v.y) - (sin(rx) * v.z);
nv.z = (sin(rx) * v.y) + (cos(rx) * v.z);
@@ -878,13 +878,13 @@ void Map::RotateVertex(Vertex &v, float rx, float ry, float rz) {
v = nv;
}
void Map::ScaleVertex(Vertex &v, float sx, float sy, float sz) {
void Map::ScaleVertex(glm::vec3 &v, float sx, float sy, float sz) {
v.x = v.x * sx;
v.y = v.y * sy;
v.z = v.z * sz;
}
void Map::TranslateVertex(Vertex &v, float tx, float ty, float tz) {
void Map::TranslateVertex(glm::vec3 &v, float tx, float ty, float tz) {
v.x = v.x + tx;
v.y = v.y + ty;
v.z = v.z + tz;
+10 -26
View File
@@ -22,6 +22,7 @@
#ifndef ZONE_MAP_H
#define ZONE_MAP_H
#include "position.h"
#include <stdio.h>
#define BEST_Z_INVALID -99999
@@ -29,39 +30,22 @@
class Map
{
public:
#pragma pack(1)
struct Vertex
{
Vertex() : x(0.0f), y(0.0f), z(0.0f) { }
Vertex(float _x, float _y, float _z) : x(_x), y(_y), z(_z) { }
~Vertex() { }
bool operator==(const Vertex &v) const
{
return((v.x == x) && (v.y == y) && (v.z == z));
}
float x;
float y;
float z;
};
#pragma pack()
Map();
~Map();
float FindBestZ(Vertex &start, Vertex *result) const;
bool LineIntersectsZone(Vertex start, Vertex end, float step, Vertex *result) const;
bool LineIntersectsZoneNoZLeaps(Vertex start, Vertex end, float step_mag, Vertex *result) const;
bool CheckLoS(Vertex myloc, Vertex oloc) const;
float FindBestZ(glm::vec3 &start, glm::vec3 *result) const;
bool LineIntersectsZone(glm::vec3 start, glm::vec3 end, float step, glm::vec3 *result) const;
bool LineIntersectsZoneNoZLeaps(glm::vec3 start, glm::vec3 end, float step_mag, glm::vec3 *result) const;
bool CheckLoS(glm::vec3 myloc, glm::vec3 oloc) const;
bool Load(std::string filename);
static Map *LoadMapFile(std::string file);
private:
void RotateVertex(Vertex &v, float rx, float ry, float rz);
void ScaleVertex(Vertex &v, float sx, float sy, float sz);
void TranslateVertex(Vertex &v, float tx, float ty, float tz);
void RotateVertex(glm::vec3 &v, float rx, float ry, float rz);
void ScaleVertex(glm::vec3 &v, float sx, float sy, float sz);
void TranslateVertex(glm::vec3 &v, float tx, float ty, float tz);
bool LoadV1(FILE *f);
bool LoadV2(FILE *f);
struct impl;
impl *imp;
};
+2868 -2302
View File
File diff suppressed because it is too large Load Diff
+342 -213
View File
File diff suppressed because it is too large Load Diff
+4 -2
View File
@@ -13,7 +13,6 @@ struct MercTemplate;
struct NPCType;
struct NewSpawn_Struct;
#define MERC_DEBUG 0
#define MAXMERCS 1
#define TANK 1
#define HEALER 2
@@ -138,8 +137,9 @@ public:
virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
static Merc* LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id, bool updateFromDB = false);
void UpdateMercInfo(Client *c);
void UpdateMercStats(Client *c);
void UpdateMercStats(Client *c, bool setmax = false);
void UpdateMercAppearance();
virtual void UpdateEquipLightValue();
void AddItem(uint8 slot, uint32 item_id);
static const char *GetRandomName();
bool Spawn(Client *owner);
@@ -189,6 +189,7 @@ public:
bool TryHide();
// stat functions
virtual void ScaleStats(int scalepercent, bool setmax = false);
virtual void CalcBonuses();
int32 GetEndurance() const {return cur_end;} //This gets our current endurance
inline virtual int32 GetAC() const { return AC; }
@@ -347,6 +348,7 @@ private:
// Private "base stats" Members
int32 base_mana;
int32 base_end;
int32 _baseAC;
uint32 _baseSTR;
uint32 _baseSTA;
+114 -177
View File
@@ -49,11 +49,7 @@ Mob::Mob(const char* in_name,
uint32 in_npctype_id,
float in_size,
float in_runspeed,
float in_heading,
float in_x_pos,
float in_y_pos,
float in_z_pos,
const glm::vec4& position,
uint8 in_light,
uint8 in_texture,
uint8 in_helmtexture,
@@ -102,29 +98,21 @@ Mob::Mob(const char* in_name,
bardsong_timer(6000),
gravity_timer(1000),
viral_timer(0),
flee_timer(FLEE_CHECK_TIMER)
m_FearWalkTarget(-999999.0f,-999999.0f,-999999.0f),
m_TargetLocation(glm::vec3()),
m_TargetV(glm::vec3()),
flee_timer(FLEE_CHECK_TIMER),
m_Position(position)
{
targeted = 0;
tar_ndx=0;
tar_vector=0;
tar_vx=0;
tar_vy=0;
tar_vz=0;
tarx=0;
tary=0;
tarz=0;
fear_walkto_x = -999999;
fear_walkto_y = -999999;
fear_walkto_z = -999999;
curfp = false;
AI_Init();
SetMoving(false);
moved=false;
rewind_x = 0; //Stored x_pos for /rewind
rewind_y = 0; //Stored y_pos for /rewind
rewind_z = 0; //Stored z_pos for /rewind
m_RewindLocation = glm::vec3();
move_tic_count = 0;
_egnode = nullptr;
@@ -161,11 +149,9 @@ Mob::Mob(const char* in_name,
if (runspeed < 0 || runspeed > 20)
runspeed = 1.25f;
heading = in_heading;
x_pos = in_x_pos;
y_pos = in_y_pos;
z_pos = in_z_pos;
light = in_light;
active_light = innate_light = in_light;
spell_light = equip_light = NOT_USED;
texture = in_texture;
helmtexture = in_helmtexture;
haircolor = in_haircolor;
@@ -259,10 +245,7 @@ Mob::Mob(const char* in_name,
}
}
delta_heading = 0;
delta_x = 0;
delta_y = 0;
delta_z = 0;
m_Delta = glm::vec4();
animation = 0;
logging_enabled = false;
@@ -335,17 +318,12 @@ Mob::Mob(const char* in_name,
wandertype=0;
pausetype=0;
cur_wp = 0;
cur_wp_x = 0;
cur_wp_y = 0;
cur_wp_z = 0;
m_CurrentWayPoint = glm::vec4();
cur_wp_pause = 0;
patrol=0;
follow=0;
follow_dist = 100; // Default Distance for Follow
flee_mode = false;
fear_walkto_x = -999999;
fear_walkto_y = -999999;
fear_walkto_z = -999999;
curfp = false;
flee_timer.Start();
@@ -387,9 +365,7 @@ Mob::Mob(const char* in_name,
nimbus_effect3 = 0;
m_targetable = true;
targetring_x = 0.0f;
targetring_y = 0.0f;
targetring_z = 0.0f;
m_TargetRing = glm::vec3();
flymode = FlyMode3;
// Pathing
@@ -908,10 +884,10 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
strn0cpy(ns->spawn.lastName, lastname, sizeof(ns->spawn.lastName));
}
ns->spawn.heading = FloatToEQ19(heading);
ns->spawn.x = FloatToEQ19(x_pos);//((int32)x_pos)<<3;
ns->spawn.y = FloatToEQ19(y_pos);//((int32)y_pos)<<3;
ns->spawn.z = FloatToEQ19(z_pos);//((int32)z_pos)<<3;
ns->spawn.heading = FloatToEQ19(m_Position.w);
ns->spawn.x = FloatToEQ19(m_Position.x);//((int32)x_pos)<<3;
ns->spawn.y = FloatToEQ19(m_Position.y);//((int32)y_pos)<<3;
ns->spawn.z = FloatToEQ19(m_Position.z);//((int32)z_pos)<<3;
ns->spawn.spawnId = GetID();
ns->spawn.curHp = static_cast<uint8>(GetHPRatio());
ns->spawn.max_hp = 100; //this field needs a better name
@@ -924,7 +900,10 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
ns->spawn.deity = deity;
ns->spawn.animation = 0;
ns->spawn.findable = findable?1:0;
ns->spawn.light = light;
UpdateActiveLightValue();
ns->spawn.light = active_light;
ns->spawn.showhelm = (helmtexture && helmtexture != 0xFF) ? 1 : 0;
ns->spawn.invis = (invisible || hidden) ? 1 : 0; // TODO: load this before spawning players
@@ -966,13 +945,9 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
// 3 - Mobs in water do not sink. A value of 3 in this field appears to be the default setting for all mobs
// (in water or not) according to 6.2 era packet collects.
if(IsClient())
{
ns->spawn.flymode = FindType(SE_Levitate) ? 2 : 0;
}
else
{
ns->spawn.flymode = flymode;
}
ns->spawn.lastName[0] = '\0';
@@ -1240,13 +1215,13 @@ void Mob::SendPosUpdate(uint8 iSendToSelf) {
void Mob::MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct *spu){
memset(spu,0xff,sizeof(PlayerPositionUpdateServer_Struct));
spu->spawn_id = GetID();
spu->x_pos = FloatToEQ19(x_pos);
spu->y_pos = FloatToEQ19(y_pos);
spu->z_pos = FloatToEQ19(z_pos);
spu->x_pos = FloatToEQ19(m_Position.x);
spu->y_pos = FloatToEQ19(m_Position.y);
spu->z_pos = FloatToEQ19(m_Position.z);
spu->delta_x = NewFloatToEQ13(0);
spu->delta_y = NewFloatToEQ13(0);
spu->delta_z = NewFloatToEQ13(0);
spu->heading = FloatToEQ19(heading);
spu->heading = FloatToEQ19(m_Position.w);
spu->animation = 0;
spu->delta_heading = NewFloatToEQ13(0);
spu->padding0002 =0;
@@ -1271,13 +1246,13 @@ void Mob::MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct *spu){
// this is for SendPosUpdate()
void Mob::MakeSpawnUpdate(PlayerPositionUpdateServer_Struct* spu) {
spu->spawn_id = GetID();
spu->x_pos = FloatToEQ19(x_pos);
spu->y_pos = FloatToEQ19(y_pos);
spu->z_pos = FloatToEQ19(z_pos);
spu->delta_x = NewFloatToEQ13(delta_x);
spu->delta_y = NewFloatToEQ13(delta_y);
spu->delta_z = NewFloatToEQ13(delta_z);
spu->heading = FloatToEQ19(heading);
spu->x_pos = FloatToEQ19(m_Position.x);
spu->y_pos = FloatToEQ19(m_Position.y);
spu->z_pos = FloatToEQ19(m_Position.z);
spu->delta_x = NewFloatToEQ13(m_Delta.x);
spu->delta_y = NewFloatToEQ13(m_Delta.y);
spu->delta_z = NewFloatToEQ13(m_Delta.z);
spu->heading = FloatToEQ19(m_Position.w);
spu->padding0002 =0;
spu->padding0006 =7;
spu->padding0014 =0x7f;
@@ -1286,7 +1261,7 @@ void Mob::MakeSpawnUpdate(PlayerPositionUpdateServer_Struct* spu) {
spu->animation = animation;
else
spu->animation = pRunAnimSpeed;
spu->delta_heading = NewFloatToEQ13(static_cast<float>(delta_heading));
spu->delta_heading = NewFloatToEQ13(m_Delta.w);
}
void Mob::ShowStats(Client* client)
@@ -1308,7 +1283,7 @@ void Mob::ShowStats(Client* client)
client->Message(0, " Mana: %i Max Mana: %i", GetMana(), GetMaxMana());
client->Message(0, " Total ATK: %i Worn/Spell ATK (Cap %i): %i", GetATK(), RuleI(Character, ItemATKCap), GetATKBonus());
client->Message(0, " STR: %i STA: %i DEX: %i AGI: %i INT: %i WIS: %i CHA: %i", GetSTR(), GetSTA(), GetDEX(), GetAGI(), GetINT(), GetWIS(), GetCHA());
client->Message(0, " MR: %i PR: %i FR: %i CR: %i DR: %i Corruption: %i", GetMR(), GetPR(), GetFR(), GetCR(), GetDR(), GetCorrup());
client->Message(0, " MR: %i PR: %i FR: %i CR: %i DR: %i Corruption: %i PhR: %i", GetMR(), GetPR(), GetFR(), GetCR(), GetDR(), GetCorrup(), GetPhR());
client->Message(0, " Race: %i BaseRace: %i Texture: %i HelmTexture: %i Gender: %i BaseGender: %i", GetRace(), GetBaseRace(), GetTexture(), GetHelmTexture(), GetGender(), GetBaseGender());
if (client->Admin() >= 100)
client->Message(0, " EntityID: %i PetID: %i OwnerID: %i AIControlled: %i Targetted: %i", GetID(), GetPetID(), GetOwnerID(), IsAIControlled(), targeted);
@@ -1402,11 +1377,11 @@ void Mob::GMMove(float x, float y, float z, float heading, bool SendUpdate) {
entity_list.ProcessMove(CastToNPC(), x, y, z);
}
x_pos = x;
y_pos = y;
z_pos = z;
if (heading != 0.01)
this->heading = heading;
m_Position.x = x;
m_Position.y = y;
m_Position.z = z;
if (m_Position.w != 0.01)
this->m_Position.w = heading;
if(IsNPC())
CastToNPC()->SaveGuardSpot(true);
if(SendUpdate)
@@ -1570,7 +1545,6 @@ void Mob::SendIllusionPacket(uint16 in_race, uint8 in_gender, uint8 in_texture,
}
EQApplicationPacket* outapp = new EQApplicationPacket(OP_Illusion, sizeof(Illusion_Struct));
memset(outapp->pBuffer, 0, sizeof(outapp->pBuffer));
Illusion_Struct* is = (Illusion_Struct*) outapp->pBuffer;
is->spawnid = GetID();
strcpy(is->charname, GetCleanName());
@@ -1592,7 +1566,7 @@ void Mob::SendIllusionPacket(uint16 in_race, uint8 in_gender, uint8 in_texture,
entity_list.QueueClients(this, outapp);
safe_delete(outapp);
mlog(CLIENT__SPELLS, "Illusion: Race = %i, Gender = %i, Texture = %i, HelmTexture = %i, HairColor = %i, BeardColor = %i, EyeColor1 = %i, EyeColor2 = %i, HairStyle = %i, Face = %i, DrakkinHeritage = %i, DrakkinTattoo = %i, DrakkinDetails = %i, Size = %f",
Log.Out(Logs::Detail, Logs::Spells, "Illusion: Race = %i, Gender = %i, Texture = %i, HelmTexture = %i, HairColor = %i, BeardColor = %i, EyeColor1 = %i, EyeColor2 = %i, HairStyle = %i, Face = %i, DrakkinHeritage = %i, DrakkinTattoo = %i, DrakkinDetails = %i, Size = %f",
race, gender, texture, helmtexture, haircolor, beardcolor, eyecolor1, eyecolor2, hairstyle, luclinface, drakkin_heritage, drakkin_tattoo, drakkin_details, size);
}
@@ -1811,7 +1785,6 @@ bool Mob::IsPlayerRace(uint16 in_race) {
uint8 Mob::GetDefaultGender(uint16 in_race, uint8 in_gender) {
//std::cout << "Gender in: " << (int)in_gender << std::endl; // undefined cout [CODEBUG]
if (Mob::IsPlayerRace(in_race) || in_race == 15 || in_race == 50 || in_race == 57 || in_race == 70 || in_race == 98 || in_race == 118) {
if (in_gender >= 2) {
// Male default for PC Races
@@ -1936,7 +1909,6 @@ void Mob::SendTargetable(bool on, Client *specific_target) {
void Mob::QuestReward(Client *c, uint32 silver, uint32 gold, uint32 platinum) {
EQApplicationPacket* outapp = new EQApplicationPacket(OP_Sound, sizeof(QuestReward_Struct));
memset(outapp->pBuffer, 0, sizeof(outapp->pBuffer));
QuestReward_Struct* qr = (QuestReward_Struct*) outapp->pBuffer;
qr->from_mob = GetID(); // Entity ID for the from mob name
@@ -1956,7 +1928,6 @@ void Mob::CameraEffect(uint32 duration, uint32 intensity, Client *c, bool global
if(global == true)
{
ServerPacket* pack = new ServerPacket(ServerOP_CameraShake, sizeof(ServerCameraShake_Struct));
memset(pack->pBuffer, 0, sizeof(pack->pBuffer));
ServerCameraShake_Struct* scss = (ServerCameraShake_Struct*) pack->pBuffer;
scss->duration = duration;
scss->intensity = intensity;
@@ -1966,7 +1937,6 @@ void Mob::CameraEffect(uint32 duration, uint32 intensity, Client *c, bool global
}
EQApplicationPacket* outapp = new EQApplicationPacket(OP_CameraEffect, sizeof(Camera_Struct));
memset(outapp->pBuffer, 0, sizeof(outapp->pBuffer));
Camera_Struct* cs = (Camera_Struct*) outapp->pBuffer;
cs->duration = duration; // Duration in milliseconds
cs->intensity = ((intensity * 6710886) + 1023410176); // Intensity ranges from 1023410176 to 1090519040, so simplify it from 0 to 10.
@@ -1982,7 +1952,6 @@ void Mob::CameraEffect(uint32 duration, uint32 intensity, Client *c, bool global
void Mob::SendSpellEffect(uint32 effectid, uint32 duration, uint32 finish_delay, bool zone_wide, uint32 unk020, bool perm_effect, Client *c) {
EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpellEffect, sizeof(SpellEffect_Struct));
memset(outapp->pBuffer, 0, sizeof(outapp->pBuffer));
SpellEffect_Struct* se = (SpellEffect_Struct*) outapp->pBuffer;
se->EffectID = effectid; // ID of the Particle Effect
se->EntityID = GetID();
@@ -2034,7 +2003,6 @@ void Mob::TempName(const char *newname)
// Send the new name to all clients
EQApplicationPacket* outapp = new EQApplicationPacket(OP_MobRename, sizeof(MobRename_Struct));
memset(outapp->pBuffer, 0, sizeof(outapp->pBuffer));
MobRename_Struct* mr = (MobRename_Struct*) outapp->pBuffer;
strn0cpy(mr->old_name, old_name, 64);
strn0cpy(mr->old_name_again, old_name, 64);
@@ -2077,6 +2045,39 @@ void Mob::SetAppearance(EmuAppearance app, bool iIgnoreSelf) {
}
}
bool Mob::UpdateActiveLightValue()
{
/* This is old information...
0 - "None"
1 - "Candle"
2 - "Torch"
3 - "Tiny Glowing Skull"
4 - "Small Lantern"
5 - "Stein of Moggok"
6 - "Large Lantern"
7 - "Flameless Lantern"
8 - "Globe of Stars"
9 - "Light Globe"
10 - "Lightstone"
11 - "Greater Lightstone"
12 - "Fire Beatle Eye"
13 - "Coldlight"
14 - "Unknown"
15 - "Unknown"
*/
uint8 old_light = (active_light & 0x0F);
active_light = (innate_light & 0x0F);
if (equip_light > active_light) { active_light = equip_light; } // limiter in property handler
if (spell_light > active_light) { active_light = spell_light; } // limiter in property handler
if (active_light != old_light)
return true;
return false;
}
void Mob::ChangeSize(float in_size = 0, bool bNoRestriction) {
// Size Code
if (!bNoRestriction)
@@ -2319,59 +2320,7 @@ bool Mob::CanThisClassBlock(void) const
return(CastToClient()->HasSkill(SkillBlock));
}
}
float Mob::Dist(const Mob &other) const {
float xDiff = other.x_pos - x_pos;
float yDiff = other.y_pos - y_pos;
float zDiff = other.z_pos - z_pos;
return sqrtf( (xDiff * xDiff)
+ (yDiff * yDiff)
+ (zDiff * zDiff) );
}
float Mob::DistNoZ(const Mob &other) const {
float xDiff = other.x_pos - x_pos;
float yDiff = other.y_pos - y_pos;
return sqrtf( (xDiff * xDiff)
+ (yDiff * yDiff) );
}
float Mob::DistNoRoot(const Mob &other) const {
float xDiff = other.x_pos - x_pos;
float yDiff = other.y_pos - y_pos;
float zDiff = other.z_pos - z_pos;
return ( (xDiff * xDiff)
+ (yDiff * yDiff)
+ (zDiff * zDiff) );
}
float Mob::DistNoRoot(float x, float y, float z) const {
float xDiff = x - x_pos;
float yDiff = y - y_pos;
float zDiff = z - z_pos;
return ( (xDiff * xDiff)
+ (yDiff * yDiff)
+ (zDiff * zDiff) );
}
float Mob::DistNoRootNoZ(float x, float y) const {
float xDiff = x - x_pos;
float yDiff = y - y_pos;
return ( (xDiff * xDiff) + (yDiff * yDiff) );
}
float Mob::DistNoRootNoZ(const Mob &other) const {
float xDiff = other.x_pos - x_pos;
float yDiff = other.y_pos - y_pos;
return ( (xDiff * xDiff) + (yDiff * yDiff) );
}
/*
float Mob::GetReciprocalHeading(Mob* target) {
float Result = 0;
@@ -2388,7 +2337,7 @@ float Mob::GetReciprocalHeading(Mob* target) {
return Result;
}
*/
bool Mob::PlotPositionAroundTarget(Mob* target, float &x_dest, float &y_dest, float &z_dest, bool lookForAftArc) {
bool Result = false;
@@ -2396,7 +2345,7 @@ bool Mob::PlotPositionAroundTarget(Mob* target, float &x_dest, float &y_dest, fl
float look_heading = 0;
if(lookForAftArc)
look_heading = GetReciprocalHeading(target);
look_heading = GetReciprocalHeading(target->GetPosition());
else
look_heading = target->GetHeading();
@@ -2512,20 +2461,18 @@ bool Mob::HateSummon() {
entity_list.MessageClose(this, true, 500, MT_Say, "%s says,'You will not evade me, %s!' ", GetCleanName(), target->GetCleanName() );
if (target->IsClient()) {
target->CastToClient()->MovePC(zone->GetZoneID(), zone->GetInstanceID(), x_pos, y_pos, z_pos, target->GetHeading(), 0, SummonPC);
target->CastToClient()->MovePC(zone->GetZoneID(), zone->GetInstanceID(), m_Position.x, m_Position.y, m_Position.z, target->GetHeading(), 0, SummonPC);
}
else {
#ifdef BOTS
if(target && target->IsBot()) {
// set pre summoning info to return to (to get out of melee range for caster)
target->CastToBot()->SetHasBeenSummoned(true);
target->CastToBot()->SetPreSummonX(target->GetX());
target->CastToBot()->SetPreSummonY(target->GetY());
target->CastToBot()->SetPreSummonZ(target->GetZ());
target->CastToBot()->SetPreSummonLocation(glm::vec3(target->GetPosition()));
}
#endif //BOTS
target->GMMove(x_pos, y_pos, z_pos, target->GetHeading());
target->GMMove(m_Position.x, m_Position.y, m_Position.z, target->GetHeading());
}
return true;
@@ -2703,7 +2650,7 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const
int32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType);
const Item_Struct *item;
item = database.GetItem(GetEquipment(material_slot));
if (item != 0)
{
// For primary and secondary we need the model, not the material
@@ -2814,14 +2761,10 @@ uint32 Mob::GetEquipmentColor(uint8 material_slot) const
{
return armor_tint[material_slot];
}
else
{
item = database.GetItem(GetEquipment(material_slot));
if (item != 0)
{
return item->Color;
}
}
item = database.GetItem(GetEquipment(material_slot));
if (item != 0)
return item->Color;
return 0;
}
@@ -2865,7 +2808,7 @@ void Mob::Say(const char *format, ...)
}
//
// solar: this is like the above, but the first parameter is a string id
// this is like the above, but the first parameter is a string id
//
void Mob::Say_StringID(uint32 string_id, const char *message3, const char *message4, const char *message5, const char *message6, const char *message7, const char *message8, const char *message9)
{
@@ -2943,20 +2886,16 @@ void Mob::SetNextIncHPEvent( int inchpevent )
nextinchpevent = inchpevent;
}
//warp for quest function,from sandy
void Mob::Warp( float x, float y, float z )
void Mob::Warp(const glm::vec3& location)
{
if(IsNPC()) {
entity_list.ProcessMove(CastToNPC(), x, y, z);
}
if(IsNPC())
entity_list.ProcessMove(CastToNPC(), location.x, location.y, location.z);
x_pos = x;
y_pos = y;
z_pos = z;
m_Position = glm::vec4(location, m_Position.w);
Mob* target = GetTarget();
if (target) {
if (target)
FaceTarget( target );
}
SendPosition();
}
@@ -2994,7 +2933,6 @@ int16 Mob::GetResist(uint8 type) const
uint32 Mob::GetLevelHP(uint8 tlevel)
{
//std::cout<<"Tlevel: "<<(int)tlevel<<std::endl; // cout undefined [CODEBUG]
int multiplier = 0;
if (tlevel < 10)
{
@@ -3042,7 +2980,7 @@ int32 Mob::GetActSpellCasttime(uint16 spell_id, int32 casttime) {
}
casttime = (casttime*(100 - cast_reducer)/100);
return(casttime);
return casttime;
}
void Mob::ExecWeaponProc(const ItemInst *inst, uint16 spell_id, Mob *on) {
@@ -3059,7 +2997,7 @@ void Mob::ExecWeaponProc(const ItemInst *inst, uint16 spell_id, Mob *on) {
if(!IsValidSpell(spell_id)) { // Check for a valid spell otherwise it will crash through the function
if(IsClient()){
Message(0, "Invalid spell proc %u", spell_id);
mlog(CLIENT__SPELLS, "Player %s, Weapon Procced invalid spell %u", this->GetName(), spell_id);
Log.Out(Logs::Detail, Logs::Spells, "Player %s, Weapon Procced invalid spell %u", this->GetName(), spell_id);
}
return;
}
@@ -3077,7 +3015,8 @@ void Mob::ExecWeaponProc(const ItemInst *inst, uint16 spell_id, Mob *on) {
bool twinproc = false;
int32 twinproc_chance = 0;
twinproc_chance = GetFocusEffect(focusTwincast, spell_id);
if(IsClient())
twinproc_chance = CastToClient()->GetFocusEffect(focusTwincast, spell_id);
if(twinproc_chance && zone->random.Roll(twinproc_chance))
twinproc = true;
@@ -3168,11 +3107,11 @@ float Mob::FindGroundZ(float new_x, float new_y, float z_offset)
float ret = -999999;
if (zone->zonemap != nullptr)
{
Map::Vertex me;
glm::vec3 me;
me.x = new_x;
me.y = new_y;
me.z = z_pos+z_offset;
Map::Vertex hit;
me.z = m_Position.z + z_offset;
glm::vec3 hit;
float best_z = zone->zonemap->FindBestZ(me, &hit);
if (best_z != -999999)
{
@@ -3188,11 +3127,11 @@ float Mob::GetGroundZ(float new_x, float new_y, float z_offset)
float ret = -999999;
if (zone->zonemap != 0)
{
Map::Vertex me;
glm::vec3 me;
me.x = new_x;
me.y = new_y;
me.z = z_pos+z_offset;
Map::Vertex hit;
me.z = m_Position.z+z_offset;
glm::vec3 hit;
float best_z = zone->zonemap->FindBestZ(me, &hit);
if (best_z != -999999)
{
@@ -3241,8 +3180,8 @@ int Mob::GetSnaredAmount()
{
int val = CalcSpellEffectValue_formula(spells[buffs[i].spellid].formula[j], spells[buffs[i].spellid].base[j], spells[buffs[i].spellid].max[j], buffs[i].casterlevel, buffs[i].spellid);
//int effect = CalcSpellEffectValue(buffs[i].spellid, spells[buffs[i].spellid].effectid[j], buffs[i].casterlevel);
if (val < 0 && abs(val) > worst_snare)
worst_snare = abs(val);
if (val < 0 && std::abs(val) > worst_snare)
worst_snare = std::abs(val);
}
}
}
@@ -3286,11 +3225,8 @@ void Mob::TriggerDefensiveProcs(const ItemInst* weapon, Mob *on, uint16 hand, in
}
}
void Mob::SetDeltas(float dx, float dy, float dz, float dh) {
delta_x = dx;
delta_y = dy;
delta_z = dz;
delta_heading = static_cast<int>(dh);
void Mob::SetDelta(const glm::vec4& delta) {
m_Delta = delta;
}
void Mob::SetEntityVariable(const char *id, const char *m_var)
@@ -3399,7 +3335,7 @@ void Mob::TriggerOnCast(uint32 focus_spell, uint32 spell_id, bool aa_trigger)
if(IsValidSpell(trigger_spell_id) && GetTarget()){
SpellFinished(trigger_spell_id, GetTarget(),10, 0, -1, spells[trigger_spell_id].ResistDiff);
CheckNumHitsRemaining(NUMHIT_MatchingSpells,-1, focus_spell);
CheckNumHitsRemaining(NumHit::MatchingSpells, -1, focus_spell);
}
}
}
@@ -3631,7 +3567,7 @@ int32 Mob::GetVulnerability(Mob* caster, uint32 spell_id, uint32 ticsremaining)
value += tmp_focus;
if (tmp_buffslot >= 0)
CheckNumHitsRemaining(NUMHIT_MatchingSpells, tmp_buffslot);
CheckNumHitsRemaining(NumHit::MatchingSpells, tmp_buffslot);
}
return value;
}
@@ -3736,7 +3672,7 @@ void Mob::TrySympatheticProc(Mob *target, uint32 spell_id)
SpellFinished(focus_trigger, target, 10, 0, -1, spells[focus_trigger].ResistDiff);
}
CheckNumHitsRemaining(NUMHIT_MatchingSpells, -1, focus_spell);
CheckNumHitsRemaining(NumHit::MatchingSpells, -1, focus_spell);
}
}
@@ -4552,7 +4488,7 @@ void Mob::MeleeLifeTap(int32 damage) {
if(lifetap_amt && damage > 0){
lifetap_amt = damage * lifetap_amt / 100;
mlog(COMBAT__DAMAGE, "Melee lifetap healing for %d damage.", damage);
Log.Out(Logs::Detail, Logs::Combat, "Melee lifetap healing for %d damage.", damage);
if (lifetap_amt > 0)
HealDamage(lifetap_amt); //Heal self for modified damage amount.
@@ -4611,7 +4547,8 @@ void Mob::DoGravityEffect()
if(value > 0)
away = 1;
amount = fabs(value) / (100.0f); // to bring the values in line, arbitarily picked
amount = std::abs(value) /
(100.0f); // to bring the values in line, arbitarily picked
x_vector = cur_x - caster_x;
y_vector = cur_y - caster_y;
@@ -4630,7 +4567,7 @@ void Mob::DoGravityEffect()
}
}
if((fabs(my_x - cur_x) > 0.01) || (fabs(my_y - cur_y) > 0.01)) {
if ((std::abs(my_x - cur_x) > 0.01) || (std::abs(my_y - cur_y) > 0.01)) {
float new_ground = GetGroundZ(cur_x, cur_y);
// If we cant get LoS on our new spot then keep checking up to 5 units up.
if(!CheckLosFN(cur_x, cur_y, new_ground, GetSize())) {
@@ -5290,7 +5227,7 @@ bool Mob::IsFacingMob(Mob *other)
if (angle < 40.0 && heading > 472.0)
angle = heading;
if (fabs(angle - heading) <= 80.0)
if (std::abs(angle - heading) <= 80.0)
return true;
return false;
@@ -5304,8 +5241,8 @@ float Mob::HeadingAngleToMob(Mob *other)
float this_x = GetX();
float this_y = GetY();
float y_diff = fabs(this_y - mob_y);
float x_diff = fabs(this_x - mob_x);
float y_diff = std::abs(this_y - mob_y);
float x_diff = std::abs(this_x - mob_x);
if (y_diff < 0.0000009999999974752427)
y_diff = 0.0000009999999974752427;
+88 -99
View File
@@ -22,8 +22,10 @@
#include "entity.h"
#include "hate_list.h"
#include "pathing.h"
#include "position.h"
#include <set>
#include <vector>
#include <memory>
char* strn0cpy(char* dest, const char* source, uint32 size);
@@ -77,10 +79,7 @@ public:
uint32 in_npctype_id,
float in_size,
float in_runspeed,
float in_heading,
float in_x_pos,
float in_y_pos,
float in_z_pos,
const glm::vec4& position,
uint8 in_light,
uint8 in_texture,
uint8 in_helmtexture,
@@ -124,7 +123,7 @@ public:
//Attack
virtual void RogueBackstab(Mob* other, bool min_damage = false, int ReuseTime = 10);
virtual void RogueAssassinate(Mob* other); // solar
virtual void RogueAssassinate(Mob* other);
float MobAngle(Mob *other = 0, float ourx = 0.0f, float oury = 0.0f) const;
// greater than 90 is behind
inline bool BehindMob(Mob *other = 0, float ourx = 0.0f, float oury = 0.0f) const
@@ -183,7 +182,7 @@ public:
bool IsInvisible(Mob* other = 0) const;
void SetInvisible(uint8 state);
bool AttackAnimation(SkillUseTypes &skillinuse, int Hand, const ItemInst* weapon);
//Song
bool UseBardSpellLogic(uint16 spell_id = 0xffff, int slot = -1);
bool ApplyNextBardPulse(uint16 spell_id, Mob *spell_target, uint16 slot);
@@ -282,7 +281,7 @@ public:
int16 GetBuffSlotFromType(uint16 type);
uint16 GetSpellIDFromSlot(uint8 slot);
int CountDispellableBuffs();
void CheckNumHitsRemaining(uint8 type, int32 buff_slot=-1, uint16 spell_id=SPELL_UNKNOWN);
void CheckNumHitsRemaining(NumHit type, int32 buff_slot = -1, uint16 spell_id = SPELL_UNKNOWN);
bool HasNumhits() const { return has_numhits; }
inline void Numhits(bool val) { has_numhits = val; }
bool HasMGB() const { return has_MGB; }
@@ -296,9 +295,10 @@ public:
inline virtual uint32 GetNimbusEffect2() const { return nimbus_effect2; }
inline virtual uint32 GetNimbusEffect3() const { return nimbus_effect3; }
void RemoveNimbusEffect(int effectid);
inline float GetTargetRingX() const { return targetring_x; }
inline float GetTargetRingY() const { return targetring_y; }
inline float GetTargetRingZ() const { return targetring_z; }
inline const glm::vec3& GetTargetRingLocation() const { return m_TargetRing; }
inline float GetTargetRingX() const { return m_TargetRing.x; }
inline float GetTargetRingY() const { return m_TargetRing.y; }
inline float GetTargetRingZ() const { return m_TargetRing.z; }
inline bool HasEndurUpkeep() const { return endur_upkeep; }
inline void SetEndurUpkeep(bool val) { endur_upkeep = val; }
@@ -371,7 +371,7 @@ public:
inline virtual int32 GetPR() const { return PR + itembonuses.PR + spellbonuses.PR; }
inline virtual int32 GetCR() const { return CR + itembonuses.CR + spellbonuses.CR; }
inline virtual int32 GetCorrup() const { return Corrup + itembonuses.Corrup + spellbonuses.Corrup; }
inline virtual int32 GetPhR() const { return PhR; }
inline virtual int32 GetPhR() const { return PhR; } // PhR bonuses not implemented yet
inline StatBonuses GetItemBonuses() const { return itembonuses; }
inline StatBonuses GetSpellBonuses() const { return spellbonuses; }
inline StatBonuses GetAABonuses() const { return aabonuses; }
@@ -400,18 +400,19 @@ public:
((static_cast<float>(cur_mana) / max_mana) * 100); }
virtual int32 CalcMaxMana();
uint32 GetNPCTypeID() const { return npctype_id; }
inline const float GetX() const { return x_pos; }
inline const float GetY() const { return y_pos; }
inline const float GetZ() const { return z_pos; }
inline const float GetHeading() const { return heading; }
inline const glm::vec4& GetPosition() const { return m_Position; }
inline const float GetX() const { return m_Position.x; }
inline const float GetY() const { return m_Position.y; }
inline const float GetZ() const { return m_Position.z; }
inline const float GetHeading() const { return m_Position.w; }
inline const float GetSize() const { return size; }
inline const float GetBaseSize() const { return base_size; }
inline const float GetTarX() const { return tarx; }
inline const float GetTarY() const { return tary; }
inline const float GetTarZ() const { return tarz; }
inline const float GetTarVX() const { return tar_vx; }
inline const float GetTarVY() const { return tar_vy; }
inline const float GetTarVZ() const { return tar_vz; }
inline const float GetTarX() const { return m_TargetLocation.x; }
inline const float GetTarY() const { return m_TargetLocation.y; }
inline const float GetTarZ() const { return m_TargetLocation.z; }
inline const float GetTarVX() const { return m_TargetV.x; }
inline const float GetTarVY() const { return m_TargetV.y; }
inline const float GetTarVZ() const { return m_TargetV.z; }
inline const float GetTarVector() const { return tar_vector; }
inline const uint8 GetTarNDX() const { return tar_ndx; }
bool IsBoat() const;
@@ -426,9 +427,9 @@ public:
virtual inline int32 GetPrimaryFaction() const { return 0; }
//Movement
void Warp( float x, float y, float z );
void Warp(const glm::vec3& location);
inline bool IsMoving() const { return moving; }
virtual void SetMoving(bool move) { moving = move; delta_x = 0; delta_y = 0; delta_z = 0; delta_heading = 0; }
virtual void SetMoving(bool move) { moving = move; m_Delta = glm::vec4(); }
virtual void GoToBind(uint8 bindnum = 0) { }
virtual void Gate();
float GetWalkspeed() const { return(_GetMovementSpeed(-47)); }
@@ -438,15 +439,15 @@ public:
bool IsRunning() const { return m_is_running; }
void SetRunning(bool val) { m_is_running = val; }
virtual void GMMove(float x, float y, float z, float heading = 0.01, bool SendUpdate = true);
void SetDeltas(float delta_x, float delta_y, float delta_z, float delta_h);
void SetDelta(const glm::vec4& delta);
void SetTargetDestSteps(uint8 target_steps) { tar_ndx = target_steps; }
void SendPosUpdate(uint8 iSendToSelf = 0);
void MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct* spu);
void MakeSpawnUpdate(PlayerPositionUpdateServer_Struct* spu);
void SendPosition();
void SetFlyMode(uint8 flymode);
inline void Teleport(Map::Vertex NewPosition) { x_pos = NewPosition.x; y_pos = NewPosition.y;
z_pos = NewPosition.z; };
inline void Teleport(glm::vec3 NewPosition) { m_Position.x = NewPosition.x; m_Position.y = NewPosition.y;
m_Position.z = NewPosition.z; };
//AI
static uint32 GetLevelCon(uint8 mylevel, uint8 iOtherLevel);
@@ -467,8 +468,8 @@ public:
bool IsEngaged() { return(!hate_list.IsHateListEmpty()); }
bool HateSummon();
void FaceTarget(Mob* MobToFace = 0);
void SetHeading(float iHeading) { if(heading != iHeading) { pLastChange = Timer::GetCurrentTime();
heading = iHeading; } }
void SetHeading(float iHeading) { if(m_Position.w != iHeading) { pLastChange = Timer::GetCurrentTime();
m_Position.w = iHeading; } }
void WipeHateList();
void AddFeignMemory(Client* attacker);
void RemoveFromFeignMemory(Client* attacker);
@@ -511,13 +512,6 @@ public:
void ShowStats(Client* client);
void ShowBuffs(Client* client);
void ShowBuffList(Client* client);
float Dist(const Mob &) const;
float DistNoZ(const Mob &) const;
float DistNoRoot(const Mob &) const;
float DistNoRoot(float x, float y, float z) const;
float DistNoRootNoZ(float x, float y) const;
float DistNoRootNoZ(const Mob &) const;
static float GetReciprocalHeading(Mob* target);
bool PlotPositionAroundTarget(Mob* target, float &x_dest, float &y_dest, float &z_dest,
bool lookForAftArc = true);
@@ -535,12 +529,6 @@ public:
bool HasProcs() const;
bool IsCombatProc(uint16 spell_id);
//Logging
bool IsLoggingEnabled() const { return(logging_enabled); }
void EnableLogging() { logging_enabled = true; }
void DisableLogging() { logging_enabled = false; }
//More stuff to sort:
virtual bool IsRaidTarget() const { return false; };
virtual bool IsAttackAllowed(Mob *target, bool isSpellAttack = false);
@@ -575,10 +563,10 @@ public:
int16 CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, bool best_focus=false);
uint8 IsFocusEffect(uint16 spellid, int effect_index, bool AA=false,uint32 aa_effect=0);
void SendIllusionPacket(uint16 in_race, uint8 in_gender = 0xFF, uint8 in_texture = 0xFF, uint8 in_helmtexture = 0xFF,
uint8 in_haircolor = 0xFF, uint8 in_beardcolor = 0xFF, uint8 in_eyecolor1 = 0xFF, uint8 in_eyecolor2 = 0xFF,
uint8 in_hairstyle = 0xFF, uint8 in_luclinface = 0xFF, uint8 in_beard = 0xFF, uint8 in_aa_title = 0xFF,
uint32 in_drakkin_heritage = 0xFFFFFFFF, uint32 in_drakkin_tattoo = 0xFFFFFFFF,
void SendIllusionPacket(uint16 in_race, uint8 in_gender = 0xFF, uint8 in_texture = 0xFF, uint8 in_helmtexture = 0xFF,
uint8 in_haircolor = 0xFF, uint8 in_beardcolor = 0xFF, uint8 in_eyecolor1 = 0xFF, uint8 in_eyecolor2 = 0xFF,
uint8 in_hairstyle = 0xFF, uint8 in_luclinface = 0xFF, uint8 in_beard = 0xFF, uint8 in_aa_title = 0xFF,
uint32 in_drakkin_heritage = 0xFFFFFFFF, uint32 in_drakkin_tattoo = 0xFFFFFFFF,
uint32 in_drakkin_details = 0xFFFFFFFF, float in_size = -1.0f);
bool RandomizeFeatures(bool send_illusion = true, bool set_variables = true);
virtual void Stun(int duration);
@@ -590,7 +578,7 @@ public:
void WakeTheDead(uint16 spell_id, Mob *target, uint32 duration);
void Spin();
void Kill();
bool PassCharismaCheck(Mob* caster, Mob* spellTarget, uint16 spell_id);
bool PassCharismaCheck(Mob* caster, uint16 spell_id);
bool TryDeathSave();
bool TryDivineSave();
void DoBuffWearOffEffect(uint32 index);
@@ -627,7 +615,7 @@ public:
bool CanBlockSpell() const { return(spellbonuses.BlockNextSpell); }
bool DoHPToManaCovert(uint16 mana_cost = 0);
int32 ApplySpellEffectiveness(Mob* caster, int16 spell_id, int32 value, bool IsBard = false);
int8 GetDecayEffectValue(uint16 spell_id, uint16 spelleffect);
int8 GetDecayEffectValue(uint16 spell_id, uint16 spelleffect);
int32 GetExtraSpellAmt(uint16 spell_id, int32 extra_spell_amt, int32 base_spell_dmg);
void MeleeLifeTap(int32 damage);
bool PassCastRestriction(bool UseCastRestriction = true, int16 value = 0, bool IsDamage = true);
@@ -664,6 +652,15 @@ public:
bool IsDestructibleObject() { return destructibleobject; }
void SetDestructibleObject(bool in) { destructibleobject = in; }
inline uint8 GetInnateLightValue() { return innate_light; }
inline uint8 GetEquipLightValue() { return equip_light; }
inline uint8 GetSpellLightValue() { return spell_light; }
virtual void UpdateEquipLightValue() { equip_light = NOT_USED; }
inline void SetSpellLightValue(uint8 light_value) { spell_light = (light_value & 0x0F); }
inline uint8 GetActiveLightValue() { return active_light; }
bool UpdateActiveLightValue(); // returns true if change, false if no change
Mob* GetPet();
void SetPet(Mob* newpet);
virtual Mob* GetOwner();
@@ -688,9 +685,9 @@ public:
inline int16 GetTempPetCount() const { return count_TempPet; }
inline void SetTempPetCount(int16 i) { count_TempPet = i; }
bool HasPetAffinity() { if (aabonuses.GivePetGroupTarget || itembonuses.GivePetGroupTarget || spellbonuses.GivePetGroupTarget) return true; return false; }
inline bool IsPetOwnerClient() const { return pet_owner_client; }
inline bool IsPetOwnerClient() const { return pet_owner_client; }
inline void SetPetOwnerClient(bool value) { pet_owner_client = value; }
inline bool IsTempPet() const { return _IsTempPet; }
inline bool IsTempPet() const { return _IsTempPet; }
inline void SetTempPet(bool value) { _IsTempPet = value; }
inline const bodyType GetBodyType() const { return bodytype; }
@@ -821,10 +818,10 @@ public:
void SetDontCureMeBefore(uint32 time) { pDontCureMeBefore = time; }
// calculate interruption of spell via movement of mob
void SaveSpellLoc() {spell_x = x_pos; spell_y = y_pos; spell_z = z_pos; }
inline float GetSpellX() const {return spell_x;}
inline float GetSpellY() const {return spell_y;}
inline float GetSpellZ() const {return spell_z;}
void SaveSpellLoc() { m_SpellLocation = glm::vec3(m_Position); }
inline float GetSpellX() const {return m_SpellLocation.x;}
inline float GetSpellY() const {return m_SpellLocation.y;}
inline float GetSpellZ() const {return m_SpellLocation.z;}
inline bool IsGrouped() const { return isgrouped; }
void SetGrouped(bool v);
inline bool IsRaidGrouped() const { return israidgrouped; }
@@ -875,19 +872,16 @@ public:
Shielders_Struct shielder[MAX_SHIELDERS];
Trade* trade;
inline float GetCWPX() const { return(cur_wp_x); }
inline float GetCWPY() const { return(cur_wp_y); }
inline float GetCWPZ() const { return(cur_wp_z); }
inline float GetCWPH() const { return(cur_wp_heading); }
inline glm::vec4 GetCurrentWayPoint() const { return m_CurrentWayPoint; }
inline float GetCWPP() const { return(static_cast<float>(cur_wp_pause)); }
inline int GetCWP() const { return(cur_wp); }
void SetCurrentWP(uint16 waypoint) { cur_wp = waypoint; }
virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther) { return FACTION_INDIFFERENT; }
inline bool IsTrackable() const { return(trackable); }
Timer* GetAIThinkTimer() { return AIthink_timer; }
Timer* GetAIMovementTimer() { return AImovement_timer; }
Timer* GetAIThinkTimer() { return AIthink_timer.get(); }
Timer* GetAIMovementTimer() { return AImovement_timer.get(); }
Timer GetAttackTimer() { return attack_timer; }
Timer GetAttackDWTimer() { return attack_dw_timer; }
inline bool IsFindable() { return findable; }
@@ -930,6 +924,16 @@ public:
void mod_spell_cast(uint16 spell_id, Mob* spelltar, bool reflect, bool use_resist_adjust, int16 resist_adjust, bool isproc);
bool mod_will_aggro(Mob *attacker, Mob *on);
//Command #Tune functions
int32 Tune_MeleeMitigation(Mob* GM, Mob *attacker, int32 damage, int32 minhit, ExtraAttackOptions *opts = nullptr, int Msg =0, int ac_override=0, int atk_override=0, int add_ac=0, int add_atk = 0);
virtual int32 Tune_GetMeleeMitDmg(Mob* GM, Mob *attacker, int32 damage, int32 minhit, float mit_rating, float atk_rating);
uint32 Tune_GetMeanDamage(Mob* GM, Mob *attacker, int32 damage, int32 minhit, ExtraAttackOptions *opts = nullptr, int Msg = 0,int ac_override=0, int atk_override=0, int add_ac=0, int add_atk = 0);
void Tune_FindATKByPctMitigation(Mob* defender, Mob *attacker, float pct_mitigation, int interval = 50, int max_loop = 100, int ac_override=0,int Msg =0);
void Tune_FindACByPctMitigation(Mob* defender, Mob *attacker, float pct_mitigation, int interval = 50, int max_loop = 100, int atk_override=0,int Msg =0);
float Tune_CheckHitChance(Mob* defender, Mob* attacker, SkillUseTypes skillinuse, int Hand, int16 chance_mod, int Msg = 1,int acc_override=0, int avoid_override=0, int add_acc=0, int add_avoid = 0);
void Tune_FindAccuaryByHitChance(Mob* defender, Mob *attacker, float hit_chance, int interval, int max_loop, int avoid_override, int Msg = 0);
void Tune_FindAvoidanceByHitChance(Mob* defender, Mob *attacker, float hit_chance, int interval, int max_loop, int acc_override, int Msg = 0);
protected:
void CommonDamage(Mob* other, int32 &damage, const uint16 spell_id, const SkillUseTypes attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic);
static uint16 GetProcID(uint16 spell_id, uint8 effect_index);
@@ -1013,10 +1017,7 @@ protected:
uint8 level;
uint8 orig_level;
uint32 npctype_id;
float x_pos;
float y_pos;
float z_pos;
float heading;
glm::vec4 m_Position;
uint16 animation;
float base_size;
float size;
@@ -1049,7 +1050,7 @@ protected:
virtual int16 GetFocusEffect(focusType type, uint16 spell_id) { return 0; }
void CalculateNewFearpoint();
float FindGroundZ(float new_x, float new_y, float z_offset=0.0);
Map::Vertex UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &WaypointChange, bool &NodeReached);
glm::vec3 UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &WaypointChange, bool &NodeReached);
void PrintRoute();
virtual float GetSympatheticProcChances(uint16 spell_id, int16 ProcRateMod, int32 ItemProcRate = 0);
@@ -1065,19 +1066,18 @@ protected:
char clean_name[64];
char lastname[64];
int32 delta_heading;
float delta_x;
float delta_y;
float delta_z;
glm::vec4 m_Delta;
uint8 light;
uint8 innate_light; // defined by db field `npc_types`.`light` - where appropriate
uint8 equip_light; // highest value of equipped/carried light-producing items
uint8 spell_light; // set value of any light-producing spell (can be modded to mimic equip_light behavior)
uint8 active_light; // highest value of all light sources
float fixedZ;
EmuAppearance _appearance;
uint8 pRunAnimSpeed;
bool m_is_running;
Timer attack_timer;
Timer attack_dw_timer;
Timer ranged_timer;
@@ -1090,7 +1090,7 @@ protected:
//spell casting vars
Timer spellend_timer;
uint16 casting_spell_id;
float spell_x, spell_y, spell_z;
glm::vec3 m_SpellLocation;
int attacked_count;
bool delaytimer;
uint16 casting_spell_targetid;
@@ -1109,9 +1109,8 @@ protected:
bool ActiveProjectileATK;
tProjatk ProjectileAtk[MAX_SPELL_PROJECTILE];
float rewind_x;
float rewind_y;
float rewind_z;
glm::vec3 m_RewindLocation;
Timer rewind_timer;
// Currently 3 max nimbus particle effects at a time
@@ -1172,14 +1171,14 @@ protected:
uint32 maxLastFightingDelayMoving;
float pAggroRange;
float pAssistRange;
Timer* AIthink_timer;
Timer* AImovement_timer;
Timer* AItarget_check_timer;
std::unique_ptr<Timer> AIthink_timer;
std::unique_ptr<Timer> AImovement_timer;
std::unique_ptr<Timer> AItarget_check_timer;
bool movetimercompleted;
bool permarooted;
Timer* AIscanarea_timer;
Timer* AIwalking_timer;
Timer* AIfeignremember_timer;
std::unique_ptr<Timer> AIscanarea_timer;
std::unique_ptr<Timer> AIwalking_timer;
std::unique_ptr<Timer> AIfeignremember_timer;
uint32 pLastFightingDelayMoving;
HateList hate_list;
std::set<uint32> feign_memory_list;
@@ -1207,22 +1206,18 @@ protected:
int pausetype;
int cur_wp;
float cur_wp_x;
float cur_wp_y;
float cur_wp_z;
glm::vec4 m_CurrentWayPoint;
int cur_wp_pause;
float cur_wp_heading;
int patrol;
float fear_walkto_x;
float fear_walkto_y;
float fear_walkto_z;
glm::vec3 m_FearWalkTarget;
bool curfp;
// Pathing
//
Map::Vertex PathingDestination;
Map::Vertex PathingLastPosition;
glm::vec3 PathingDestination;
glm::vec3 PathingLastPosition;
int PathingLoopCount;
int PathingLastNodeVisited;
std::deque<int> Route;
@@ -1251,19 +1246,13 @@ protected:
bool pet_owner_client; //Flags regular and pets as belonging to a client
EGNode *_egnode; //the EG node we are in
float tarx;
float tary;
float tarz;
glm::vec3 m_TargetLocation;
uint8 tar_ndx;
float tar_vector;
float tar_vx;
float tar_vy;
float tar_vz;
glm::vec3 m_TargetV;
float test_vector;
float targetring_x;
float targetring_y;
float targetring_z;
glm::vec3 m_TargetRing;
uint32 m_spellHitsLeft[38]; // Used to track which spells will have their numhits incremented when spell finishes casting, 38 Buffslots
int flymode;
+118 -120
View File
@@ -16,7 +16,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "../common/global_define.h"
#include "../common/features.h"
#include "../common/rulesys.h"
#include "../common/string_util.h"
@@ -45,7 +45,6 @@ extern Zone *zone;
#else
#define MobAI_DEBUG_Spells -1
#endif
#define ABS(x) ((x)<0?-(x):(x))
//NOTE: do NOT pass in beneficial and detrimental spell types into the same call here!
bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
@@ -69,7 +68,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
dist2 = 0; //DistNoRoot(*this); //WTF was up with this...
}
else
dist2 = DistNoRoot(*tar);
dist2 = DistanceSquared(m_Position, tar->GetPosition());
bool checked_los = false; //we do not check LOS until we are absolutely sure we need to, and we only do it once.
@@ -357,7 +356,7 @@ bool EntityList::AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float
// according to Rogean, Live NPCs will just cast through walls/floors, no problem..
//
// This check was put in to address an idle-mob CPU issue
_log(AI__ERROR, "Error: detrimental spells requested from AICheckCloseBeneficialSpells!!");
Log.Out(Logs::General, Logs::Error, "Error: detrimental spells requested from AICheckCloseBeneficialSpells!!");
return(false);
}
@@ -403,7 +402,7 @@ bool EntityList::AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float
if (t1 > iRange
|| t2 > iRange
|| t3 > iRange
|| mob->DistNoRoot(*caster) > iRange2
|| DistanceSquared(mob->GetPosition(), caster->GetPosition()) > iRange2
//this call should seem backwards:
|| !mob->CheckLosFN(caster)
|| mob->GetReverseFactionCon(caster) >= FACTION_KINDLY
@@ -425,14 +424,15 @@ bool EntityList::AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float
return false;
}
void Mob::AI_Init() {
void Mob::AI_Init()
{
pAIControlled = false;
AIthink_timer = 0;
AIwalking_timer = 0;
AImovement_timer = 0;
AItarget_check_timer = 0;
AIfeignremember_timer = nullptr;
AIscanarea_timer = 0;
AIthink_timer.reset(nullptr);
AIwalking_timer.reset(nullptr);
AImovement_timer.reset(nullptr);
AItarget_check_timer.reset(nullptr);
AIfeignremember_timer.reset(nullptr);
AIscanarea_timer.reset(nullptr);
minLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMin);
maxLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMax);
@@ -444,10 +444,9 @@ void Mob::AI_Init() {
pDontCureMeBefore = 0;
}
void NPC::AI_Init() {
Mob::AI_Init();
AIautocastspell_timer = 0;
void NPC::AI_Init()
{
AIautocastspell_timer.reset(nullptr);
casting_spell_AIindex = static_cast<uint8>(AIspells.size());
roambox_max_x = 0;
@@ -461,8 +460,8 @@ void NPC::AI_Init() {
roambox_delay = 2500;
}
void Client::AI_Init() {
Mob::AI_Init();
void Client::AI_Init()
{
minLastFightingDelayMoving = CLIENT_LD_TIMEOUT;
maxLastFightingDelayMoving = CLIENT_LD_TIMEOUT;
}
@@ -477,13 +476,13 @@ void Mob::AI_Start(uint32 iMoveDelay) {
pLastFightingDelayMoving = 0;
pAIControlled = true;
AIthink_timer = new Timer(AIthink_duration);
AIthink_timer = std::unique_ptr<Timer>(new Timer(AIthink_duration));
AIthink_timer->Trigger();
AIwalking_timer = new Timer(0);
AImovement_timer = new Timer(AImovement_duration);
AItarget_check_timer = new Timer(AItarget_check_duration);
AIfeignremember_timer = new Timer(AIfeignremember_delay);
AIscanarea_timer = new Timer(AIscanarea_delay);
AIwalking_timer = std::unique_ptr<Timer>(new Timer(0));
AImovement_timer = std::unique_ptr<Timer>(new Timer(AImovement_duration));
AItarget_check_timer = std::unique_ptr<Timer>(new Timer(AItarget_check_duration));
AIfeignremember_timer = std::unique_ptr<Timer>(new Timer(AIfeignremember_delay));
AIscanarea_timer = std::unique_ptr<Timer>(new Timer(AIscanarea_delay));
#ifdef REVERSE_AGGRO
if(IsNPC() && !CastToNPC()->WillAggroNPCs())
AIscanarea_timer->Disable();
@@ -495,10 +494,7 @@ void Mob::AI_Start(uint32 iMoveDelay) {
pAssistRange = 70;
hate_list.WipeHateList();
delta_heading = 0;
delta_x = 0;
delta_y = 0;
delta_z = 0;
m_Delta = glm::vec4();
pRunAnimSpeed = 0;
pLastChange = Timer::GetCurrentTime();
}
@@ -522,10 +518,10 @@ void NPC::AI_Start(uint32 iMoveDelay) {
return;
if (AIspells.size() == 0) {
AIautocastspell_timer = new Timer(1000);
AIautocastspell_timer = std::unique_ptr<Timer>(new Timer(1000));
AIautocastspell_timer->Disable();
} else {
AIautocastspell_timer = new Timer(750);
AIautocastspell_timer = std::unique_ptr<Timer>(new Timer(750));
AIautocastspell_timer->Start(RandomTimer(0, 15000), false);
}
@@ -546,19 +542,19 @@ void Mob::AI_Stop() {
pAIControlled = false;
safe_delete(AIthink_timer);
safe_delete(AIwalking_timer);
safe_delete(AImovement_timer);
safe_delete(AItarget_check_timer);
safe_delete(AIscanarea_timer);
safe_delete(AIfeignremember_timer);
AIthink_timer.reset(nullptr);
AIwalking_timer.reset(nullptr);
AImovement_timer.reset(nullptr);
AItarget_check_timer.reset(nullptr);
AIscanarea_timer.reset(nullptr);
AIfeignremember_timer.reset(nullptr);
hate_list.WipeHateList();
}
void NPC::AI_Stop() {
Waypoints.clear();
safe_delete(AIautocastspell_timer);
AIautocastspell_timer.reset(nullptr);
}
void Client::AI_Stop() {
@@ -627,7 +623,7 @@ void Client::AI_SpellCast()
if(!targ)
return;
float dist = DistNoRootNoZ(*targ);
float dist = DistanceSquaredNoZ(m_Position, targ->GetPosition());
std::vector<uint32> valid_spells;
std::vector<uint32> slots;
@@ -789,17 +785,18 @@ void Client::AI_Process()
if(AImovement_timer->Check()) {
animation = GetRunspeed() * 21;
// Check if we have reached the last fear point
if((ABS(GetX()-fear_walkto_x) < 0.1) && (ABS(GetY()-fear_walkto_y) <0.1)) {
if ((std::abs(GetX() - m_FearWalkTarget.x) < 0.1) &&
(std::abs(GetY() - m_FearWalkTarget.y) < 0.1)) {
// Calculate a new point to run to
CalculateNewFearpoint();
}
if(!RuleB(Pathing, Fear) || !zone->pathing)
CalculateNewPosition2(fear_walkto_x, fear_walkto_y, fear_walkto_z, GetFearSpeed(), true);
CalculateNewPosition2(m_FearWalkTarget.x, m_FearWalkTarget.y, m_FearWalkTarget.z, GetFearSpeed(), true);
else
{
bool WaypointChanged, NodeReached;
Map::Vertex Goal = UpdatePath(fear_walkto_x, fear_walkto_y, fear_walkto_z,
glm::vec3 Goal = UpdatePath(m_FearWalkTarget.x, m_FearWalkTarget.y, m_FearWalkTarget.z,
GetFearSpeed(), WaypointChanged, NodeReached);
if(WaypointChanged)
@@ -955,7 +952,7 @@ void Client::AI_Process()
else
{
bool WaypointChanged, NodeReached;
Map::Vertex Goal = UpdatePath(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(),
glm::vec3 Goal = UpdatePath(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(),
GetRunspeed(), WaypointChanged, NodeReached);
if(WaypointChanged)
@@ -1002,7 +999,7 @@ void Client::AI_Process()
if(owner == nullptr)
return;
float dist = DistNoRoot(*owner);
float dist = DistanceSquared(m_Position, owner->GetPosition());
if (dist >= 100)
{
float speed = dist >= 225 ? GetRunspeed() : GetWalkspeed();
@@ -1057,17 +1054,18 @@ void Mob::AI_Process() {
} else {
if(AImovement_timer->Check()) {
// Check if we have reached the last fear point
if((ABS(GetX()-fear_walkto_x) < 0.1) && (ABS(GetY()-fear_walkto_y) <0.1)) {
if ((std::abs(GetX() - m_FearWalkTarget.x) < 0.1) &&
(std::abs(GetY() - m_FearWalkTarget.y) < 0.1)) {
// Calculate a new point to run to
CalculateNewFearpoint();
}
if(!RuleB(Pathing, Fear) || !zone->pathing)
CalculateNewPosition2(fear_walkto_x, fear_walkto_y, fear_walkto_z, GetFearSpeed(), true);
CalculateNewPosition2(m_FearWalkTarget.x, m_FearWalkTarget.y, m_FearWalkTarget.z, GetFearSpeed(), true);
else
{
bool WaypointChanged, NodeReached;
Map::Vertex Goal = UpdatePath(fear_walkto_x, fear_walkto_y, fear_walkto_z,
glm::vec3 Goal = UpdatePath(m_FearWalkTarget.x, m_FearWalkTarget.y, m_FearWalkTarget.z,
GetFearSpeed(), WaypointChanged, NodeReached);
if(WaypointChanged)
@@ -1129,19 +1127,20 @@ void Mob::AI_Process() {
if(DivineAura())
return;
auto npcSpawnPoint = CastToNPC()->GetSpawnPoint();
if(GetSpecialAbility(TETHER)) {
float tether_range = static_cast<float>(GetSpecialAbilityParam(TETHER, 0));
tether_range = tether_range > 0.0f ? tether_range * tether_range : pAggroRange * pAggroRange;
if(DistNoRootNoZ(CastToNPC()->GetSpawnPointX(), CastToNPC()->GetSpawnPointY()) > tether_range) {
GMMove(CastToNPC()->GetSpawnPointX(), CastToNPC()->GetSpawnPointY(), CastToNPC()->GetSpawnPointZ(), CastToNPC()->GetSpawnPointH());
if(DistanceSquaredNoZ(m_Position, npcSpawnPoint) > tether_range) {
GMMove(npcSpawnPoint.x, npcSpawnPoint.y, npcSpawnPoint.z, npcSpawnPoint.w);
}
} else if(GetSpecialAbility(LEASH)) {
float leash_range = static_cast<float>(GetSpecialAbilityParam(LEASH, 0));
leash_range = leash_range > 0.0f ? leash_range * leash_range : pAggroRange * pAggroRange;
if(DistNoRootNoZ(CastToNPC()->GetSpawnPointX(), CastToNPC()->GetSpawnPointY()) > leash_range) {
GMMove(CastToNPC()->GetSpawnPointX(), CastToNPC()->GetSpawnPointY(), CastToNPC()->GetSpawnPointZ(), CastToNPC()->GetSpawnPointH());
if(DistanceSquaredNoZ(m_Position, npcSpawnPoint) > leash_range) {
GMMove(npcSpawnPoint.x, npcSpawnPoint.y, npcSpawnPoint.z, npcSpawnPoint.w);
SetHP(GetMaxHP());
BuffFadeAll();
WipeHateList();
@@ -1375,7 +1374,8 @@ void Mob::AI_Process() {
//we cannot reach our target...
//underwater stuff only works with water maps in the zone!
if(IsNPC() && CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
if(!zone->watermap->InLiquid(target->GetX(), target->GetY(), target->GetZ())) {
auto targetPosition = glm::vec3(target->GetX(), target->GetY(), target->GetZ());
if(!zone->watermap->InLiquid(targetPosition)) {
Mob *tar = hate_list.GetEntWithMostHateOnList(this);
if(tar == target) {
WipeHateList();
@@ -1406,14 +1406,14 @@ void Mob::AI_Process() {
else if (AImovement_timer->Check())
{
if(!IsRooted()) {
mlog(AI__WAYPOINTS, "Pursuing %s while engaged.", target->GetName());
Log.Out(Logs::Detail, Logs::AI, "Pursuing %s while engaged.", target->GetName());
if(!RuleB(Pathing, Aggro) || !zone->pathing)
CalculateNewPosition2(target->GetX(), target->GetY(), target->GetZ(), GetRunspeed());
else
{
bool WaypointChanged, NodeReached;
Map::Vertex Goal = UpdatePath(target->GetX(), target->GetY(), target->GetZ(),
glm::vec3 Goal = UpdatePath(target->GetX(), target->GetY(), target->GetZ(),
GetRunspeed(), WaypointChanged, NodeReached);
if(WaypointChanged)
@@ -1495,7 +1495,7 @@ void Mob::AI_Process() {
//if(owner->IsClient())
// printf("Pet start pos: (%f, %f, %f)\n", GetX(), GetY(), GetZ());
float dist = DistNoRoot(*owner);
float dist = DistanceSquared(m_Position, owner->GetPosition());
if (dist >= 400)
{
float speed = GetWalkspeed();
@@ -1550,7 +1550,7 @@ void Mob::AI_Process() {
if (!follow) SetFollowID(0);
else
{
float dist2 = DistNoRoot(*follow);
float dist2 = DistanceSquared(m_Position, follow->GetPosition());
int followdist = GetFollowDistance();
if (dist2 >= followdist) // Default follow distance is 100
@@ -1641,7 +1641,7 @@ void NPC::AI_DoMovement() {
roambox_movingto_y = zone->random.Real(roambox_min_y+1,roambox_max_y-1);
}
mlog(AI__WAYPOINTS, "Roam Box: d=%.3f (%.3f->%.3f,%.3f->%.3f): Go To (%.3f,%.3f)",
Log.Out(Logs::Detail, Logs::AI, "Roam Box: d=%.3f (%.3f->%.3f,%.3f->%.3f): Go To (%.3f,%.3f)",
roambox_distance, roambox_min_x, roambox_max_x, roambox_min_y, roambox_max_y, roambox_movingto_x, roambox_movingto_y);
if (!CalculateNewPosition2(roambox_movingto_x, roambox_movingto_y, GetZ(), walksp, true))
{
@@ -1694,11 +1694,11 @@ void NPC::AI_DoMovement() {
else {
movetimercompleted=false;
mlog(QUESTS__PATHING, "We are departing waypoint %d.", cur_wp);
Log.Out(Logs::Detail, Logs::Pathing, "We are departing waypoint %d.", cur_wp);
//if we were under quest control (with no grid), we are done now..
if(cur_wp == -2) {
mlog(QUESTS__PATHING, "Non-grid quest mob has reached its quest ordered waypoint. Leaving pathing mode.");
Log.Out(Logs::Detail, Logs::Pathing, "Non-grid quest mob has reached its quest ordered waypoint. Leaving pathing mode.");
roamer = false;
cur_wp = 0;
}
@@ -1727,15 +1727,15 @@ void NPC::AI_DoMovement() {
} // endif (movetimercompleted==true)
else if (!(AIwalking_timer->Enabled()))
{ // currently moving
if (cur_wp_x == GetX() && cur_wp_y == GetY())
if (m_CurrentWayPoint.x == GetX() && m_CurrentWayPoint.y == GetY())
{ // are we there yet? then stop
mlog(AI__WAYPOINTS, "We have reached waypoint %d (%.3f,%.3f,%.3f) on grid %d", cur_wp, GetX(), GetY(), GetZ(), GetGrid());
Log.Out(Logs::Detail, Logs::AI, "We have reached waypoint %d (%.3f,%.3f,%.3f) on grid %d", cur_wp, GetX(), GetY(), GetZ(), GetGrid());
SetWaypointPause();
if(GetAppearance() != eaStanding)
SetAppearance(eaStanding, false);
SetMoving(false);
if (cur_wp_heading >= 0.0) {
SetHeading(cur_wp_heading);
if (m_CurrentWayPoint.w >= 0.0) {
SetHeading(m_CurrentWayPoint.w);
}
SendPosition();
@@ -1751,12 +1751,12 @@ void NPC::AI_DoMovement() {
else
{ // not at waypoint yet, so keep moving
if(!RuleB(Pathing, AggroReturnToGrid) || !zone->pathing || (DistractedFromGrid == 0))
CalculateNewPosition2(cur_wp_x, cur_wp_y, cur_wp_z, walksp, true);
CalculateNewPosition2(m_CurrentWayPoint.x, m_CurrentWayPoint.y, m_CurrentWayPoint.z, walksp, true);
else
{
bool WaypointChanged;
bool NodeReached;
Map::Vertex Goal = UpdatePath(cur_wp_x, cur_wp_y, cur_wp_z, walksp, WaypointChanged, NodeReached);
glm::vec3 Goal = UpdatePath(m_CurrentWayPoint.x, m_CurrentWayPoint.y, m_CurrentWayPoint.z, walksp, WaypointChanged, NodeReached);
if(WaypointChanged)
tar_ndx = 20;
@@ -1775,7 +1775,7 @@ void NPC::AI_DoMovement() {
if (movetimercompleted==true)
{ // time to pause has ended
SetGrid( 0 - GetGrid()); // revert to AI control
mlog(QUESTS__PATHING, "Quest pathing is finished. Resuming on grid %d", GetGrid());
Log.Out(Logs::Detail, Logs::Pathing, "Quest pathing is finished. Resuming on grid %d", GetGrid());
if(GetAppearance() != eaStanding)
SetAppearance(eaStanding, false);
@@ -1789,13 +1789,13 @@ void NPC::AI_DoMovement() {
{
bool CP2Moved;
if(!RuleB(Pathing, Guard) || !zone->pathing)
CP2Moved = CalculateNewPosition2(guard_x, guard_y, guard_z, walksp);
CP2Moved = CalculateNewPosition2(m_GuardPoint.x, m_GuardPoint.y, m_GuardPoint.z, walksp);
else
{
if(!((x_pos == guard_x) && (y_pos == guard_y) && (z_pos == guard_z)))
if(!((m_Position.x == m_GuardPoint.x) && (m_Position.y == m_GuardPoint.y) && (m_Position.z == m_GuardPoint.z)))
{
bool WaypointChanged, NodeReached;
Map::Vertex Goal = UpdatePath(guard_x, guard_y, guard_z, walksp, WaypointChanged, NodeReached);
glm::vec3 Goal = UpdatePath(m_GuardPoint.x, m_GuardPoint.y, m_GuardPoint.z, walksp, WaypointChanged, NodeReached);
if(WaypointChanged)
tar_ndx = 20;
@@ -1811,13 +1811,13 @@ void NPC::AI_DoMovement() {
if (!CP2Moved)
{
if(moved) {
mlog(AI__WAYPOINTS, "Reached guard point (%.3f,%.3f,%.3f)", guard_x, guard_y, guard_z);
Log.Out(Logs::Detail, Logs::AI, "Reached guard point (%.3f,%.3f,%.3f)", m_GuardPoint.x, m_GuardPoint.y, m_GuardPoint.z);
ClearFeignMemory();
moved=false;
SetMoving(false);
if (GetTarget() == nullptr || DistNoRoot(*GetTarget()) >= 5*5 )
if (GetTarget() == nullptr || DistanceSquared(m_Position, GetTarget()->GetPosition()) >= 5*5 )
{
SetHeading(guard_heading);
SetHeading(m_GuardPoint.w);
} else {
FaceTarget(GetTarget());
}
@@ -1954,7 +1954,7 @@ bool NPC::AI_EngagedCastCheck() {
if (AIautocastspell_timer->Check(false)) {
AIautocastspell_timer->Disable(); //prevent the timer from going off AGAIN while we are casting.
mlog(AI__SPELLS, "Engaged autocast check triggered. Trying to cast healing spells then maybe offensive spells.");
Log.Out(Logs::Detail, Logs::AI, "Engaged autocast check triggered. Trying to cast healing spells then maybe offensive spells.");
// try casting a heal or gate
if (!AICastSpell(this, AISpellVar.engaged_beneficial_self_chance, SpellType_Heal | SpellType_Escape | SpellType_InCombatBuff)) {
@@ -1977,7 +1977,7 @@ bool NPC::AI_PursueCastCheck() {
if (AIautocastspell_timer->Check(false)) {
AIautocastspell_timer->Disable(); //prevent the timer from going off AGAIN while we are casting.
mlog(AI__SPELLS, "Engaged (pursuing) autocast check triggered. Trying to cast offensive spells.");
Log.Out(Logs::Detail, Logs::AI, "Engaged (pursuing) autocast check triggered. Trying to cast offensive spells.");
if(!AICastSpell(GetTarget(), AISpellVar.pursue_detrimental_chance, SpellType_Root | SpellType_Nuke | SpellType_Lifetap | SpellType_Snare | SpellType_DOT | SpellType_Dispel | SpellType_Mez | SpellType_Slow | SpellType_Debuff)) {
//no spell cast, try again soon.
AIautocastspell_timer->Start(RandomTimer(AISpellVar.pursue_no_sp_recast_min, AISpellVar.pursue_no_sp_recast_max), false);
@@ -2677,7 +2677,7 @@ DBnpcspells_Struct* ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID) {
npc_spells_cache = new DBnpcspells_Struct*[npc_spells_maxid+1];
npc_spells_loadtried = new bool[npc_spells_maxid+1];
for (uint32 i=0; i<=npc_spells_maxid; i++) {
npc_spells_cache[i] = 0;
npc_spells_cache[i] = nullptr;
npc_spells_loadtried[i] = false;
}
}
@@ -2700,7 +2700,6 @@ DBnpcspells_Struct* ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID) {
"idle_b_chance FROM npc_spells WHERE id=%d", iDBSpellsID);
auto results = QueryDatabase(query);
if (!results.Success()) {
std::cerr << "Error in AddNPCSpells query1 '" << query << "' " << results.ErrorMessage() << std::endl;
return nullptr;
}
@@ -2736,7 +2735,6 @@ DBnpcspells_Struct* ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID) {
if (!results.Success())
{
std::cerr << "Error in AddNPCSpells query1 '" << query << "' " << results.ErrorMessage() << std::endl;
return nullptr;
}
@@ -2793,7 +2791,6 @@ uint32 ZoneDatabase::GetMaxNPCSpellsID() {
std::string query = "SELECT max(id) from npc_spells";
auto results = QueryDatabase(query);
if (!results.Success()) {
std::cerr << "Error in GetMaxNPCSpellsID query '" << query << "' " << results.ErrorMessage() << std::endl;
return 0;
}
@@ -2808,16 +2805,17 @@ uint32 ZoneDatabase::GetMaxNPCSpellsID() {
return atoi(row[0]);
}
DBnpcspellseffects_Struct* ZoneDatabase::GetNPCSpellsEffects(uint32 iDBSpellsEffectsID) {
DBnpcspellseffects_Struct *ZoneDatabase::GetNPCSpellsEffects(uint32 iDBSpellsEffectsID)
{
if (iDBSpellsEffectsID == 0)
return nullptr;
if (!npc_spellseffects_cache) {
npc_spellseffects_maxid = GetMaxNPCSpellsEffectsID();
npc_spellseffects_cache = new DBnpcspellseffects_Struct*[npc_spellseffects_maxid+1];
npc_spellseffects_loadtried = new bool[npc_spellseffects_maxid+1];
for (uint32 i=0; i<=npc_spellseffects_maxid; i++) {
npc_spellseffects_cache[i] = 0;
npc_spellseffects_cache = new DBnpcspellseffects_Struct *[npc_spellseffects_maxid + 1];
npc_spellseffects_loadtried = new bool[npc_spellseffects_maxid + 1];
for (uint32 i = 0; i <= npc_spellseffects_maxid; i++) {
npc_spellseffects_cache[i] = nullptr;
npc_spellseffects_loadtried[i] = false;
}
}
@@ -2825,54 +2823,55 @@ DBnpcspellseffects_Struct* ZoneDatabase::GetNPCSpellsEffects(uint32 iDBSpellsEff
if (iDBSpellsEffectsID > npc_spellseffects_maxid)
return nullptr;
if (npc_spellseffects_cache[iDBSpellsEffectsID]) // it's in the cache, easy =)
if (npc_spellseffects_cache[iDBSpellsEffectsID]) // it's in the cache, easy =)
return npc_spellseffects_cache[iDBSpellsEffectsID];
if (npc_spellseffects_loadtried[iDBSpellsEffectsID])
return nullptr;
return nullptr;
npc_spellseffects_loadtried[iDBSpellsEffectsID] = true;
npc_spellseffects_loadtried[iDBSpellsEffectsID] = true;
std::string query = StringFormat("SELECT id, parent_list FROM npc_spells_effects WHERE id=%d", iDBSpellsEffectsID);
auto results = QueryDatabase(query);
if (!results.Success()) {
std::cerr << "Error in AddNPCSpells query1 '" << query << "' " << results.ErrorMessage() << std::endl;
return nullptr;
}
std::string query =
StringFormat("SELECT id, parent_list FROM npc_spells_effects WHERE id=%d", iDBSpellsEffectsID);
auto results = QueryDatabase(query);
if (!results.Success()) {
return nullptr;
}
if (results.RowCount() != 1)
return nullptr;
if (results.RowCount() != 1)
return nullptr;
auto row = results.begin();
uint32 tmpparent_list = atoi(row[1]);
auto row = results.begin();
uint32 tmpparent_list = atoi(row[1]);
query = StringFormat("SELECT spell_effect_id, minlevel, "
"maxlevel,se_base, se_limit, se_max "
"FROM npc_spells_effects_entries "
"WHERE npc_spells_effects_id = %d ORDER BY minlevel", iDBSpellsEffectsID);
results = QueryDatabase(query);
if (!results.Success())
return nullptr;
query = StringFormat("SELECT spell_effect_id, minlevel, "
"maxlevel,se_base, se_limit, se_max "
"FROM npc_spells_effects_entries "
"WHERE npc_spells_effects_id = %d ORDER BY minlevel",
iDBSpellsEffectsID);
results = QueryDatabase(query);
if (!results.Success())
return nullptr;
uint32 tmpSize = sizeof(DBnpcspellseffects_Struct) + (sizeof(DBnpcspellseffects_entries_Struct) * results.RowCount());
npc_spellseffects_cache[iDBSpellsEffectsID] = (DBnpcspellseffects_Struct*) new uchar[tmpSize];
memset(npc_spellseffects_cache[iDBSpellsEffectsID], 0, tmpSize);
npc_spellseffects_cache[iDBSpellsEffectsID]->parent_list = tmpparent_list;
npc_spellseffects_cache[iDBSpellsEffectsID]->numentries = results.RowCount();
uint32 tmpSize =
sizeof(DBnpcspellseffects_Struct) + (sizeof(DBnpcspellseffects_entries_Struct) * results.RowCount());
npc_spellseffects_cache[iDBSpellsEffectsID] = (DBnpcspellseffects_Struct *)new uchar[tmpSize];
memset(npc_spellseffects_cache[iDBSpellsEffectsID], 0, tmpSize);
npc_spellseffects_cache[iDBSpellsEffectsID]->parent_list = tmpparent_list;
npc_spellseffects_cache[iDBSpellsEffectsID]->numentries = results.RowCount();
int entryIndex = 0;
for (row = results.begin(); row != results.end(); ++row, ++entryIndex)
{
int spell_effect_id = atoi(row[0]);
npc_spellseffects_cache[iDBSpellsEffectsID]->entries[entryIndex].spelleffectid = spell_effect_id;
npc_spellseffects_cache[iDBSpellsEffectsID]->entries[entryIndex].minlevel = atoi(row[1]);
npc_spellseffects_cache[iDBSpellsEffectsID]->entries[entryIndex].maxlevel = atoi(row[2]);
npc_spellseffects_cache[iDBSpellsEffectsID]->entries[entryIndex].base = atoi(row[3]);
npc_spellseffects_cache[iDBSpellsEffectsID]->entries[entryIndex].limit = atoi(row[4]);
npc_spellseffects_cache[iDBSpellsEffectsID]->entries[entryIndex].max = atoi(row[5]);
}
int entryIndex = 0;
for (row = results.begin(); row != results.end(); ++row, ++entryIndex) {
int spell_effect_id = atoi(row[0]);
npc_spellseffects_cache[iDBSpellsEffectsID]->entries[entryIndex].spelleffectid = spell_effect_id;
npc_spellseffects_cache[iDBSpellsEffectsID]->entries[entryIndex].minlevel = atoi(row[1]);
npc_spellseffects_cache[iDBSpellsEffectsID]->entries[entryIndex].maxlevel = atoi(row[2]);
npc_spellseffects_cache[iDBSpellsEffectsID]->entries[entryIndex].base = atoi(row[3]);
npc_spellseffects_cache[iDBSpellsEffectsID]->entries[entryIndex].limit = atoi(row[4]);
npc_spellseffects_cache[iDBSpellsEffectsID]->entries[entryIndex].max = atoi(row[5]);
}
return npc_spellseffects_cache[iDBSpellsEffectsID];
return npc_spellseffects_cache[iDBSpellsEffectsID];
}
uint32 ZoneDatabase::GetMaxNPCSpellsEffectsID() {
@@ -2880,7 +2879,6 @@ uint32 ZoneDatabase::GetMaxNPCSpellsEffectsID() {
std::string query = "SELECT max(id) FROM npc_spells_effects";
auto results = QueryDatabase(query);
if (!results.Success()) {
std::cerr << "Error in GetMaxNPCSpellsEffectsID query '" << query << "' " << results.ErrorMessage() << std::endl;
return 0;
}
+83 -105
View File
@@ -17,8 +17,9 @@
*/
#define DONT_SHARED_OPCODES
#define PLATFORM_ZONE 1
#include "../common/debug.h"
#include "../common/global_define.h"
#include "../common/features.h"
#include "../common/queue.h"
#include "../common/timer.h"
@@ -27,7 +28,7 @@
#include "../common/eq_packet_structs.h"
#include "../common/mutex.h"
#include "../common/version.h"
#include "../common/eqemu_error.h"
#include "../common/packet_dump_file.h"
#include "../common/opcodemgr.h"
#include "../common/guilds.h"
@@ -42,6 +43,8 @@
#include "../common/memory_mapped_file.h"
#include "../common/eqemu_exception.h"
#include "../common/spdat.h"
#include "../common/eqemu_logsys.h"
#include "zone_config.h"
#include "masterentity.h"
@@ -57,7 +60,7 @@
#include "quest_parser_collection.h"
#include "embparser.h"
#include "lua_parser.h"
#include "client_logs.h"
#include "questmgr.h"
#include "remote_call.h"
#include "remote_call_subscribe.h"
@@ -70,6 +73,7 @@
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <ctime>
#ifdef _CRTDBG_MAP_ALLOC
#undef new
@@ -101,6 +105,7 @@ TitleManager title_manager;
QueryServ *QServ = 0;
TaskManager *taskmanager = 0;
QuestParserCollection *parse = 0;
EQEmuLogSys Log;
const SPDat_Spell_Struct* spells;
void LoadSpells(EQEmu::MemoryMappedFile **mmf);
@@ -111,6 +116,7 @@ extern void MapOpcodes();
int main(int argc, char** argv) {
RegisterExecutablePlatform(ExePlatformZone);
Log.LoadLogSettingsDefaults();
set_exception_handler();
register_remote_call_handlers();
@@ -144,144 +150,144 @@ int main(int argc, char** argv) {
worldserver.SetLauncherName("NONE");
}
_log(ZONE__INIT, "Loading server configuration..");
Log.Out(Logs::General, Logs::Zone_Server, "Loading server configuration..");
if (!ZoneConfig::LoadConfig()) {
_log(ZONE__INIT_ERR, "Loading server configuration failed.");
Log.Out(Logs::General, Logs::Error, "Loading server configuration failed.");
return 1;
}
const ZoneConfig *Config=ZoneConfig::get();
if(!load_log_settings(Config->LogSettingsFile.c_str()))
_log(ZONE__INIT, "Warning: Unable to read %s", Config->LogSettingsFile.c_str());
else
_log(ZONE__INIT, "Log settings loaded from %s", Config->LogSettingsFile.c_str());
const ZoneConfig *Config = ZoneConfig::get();
worldserver.SetPassword(Config->SharedKey.c_str());
_log(ZONE__INIT, "Connecting to MySQL...");
Log.Out(Logs::General, Logs::Zone_Server, "Connecting to MySQL...");
if (!database.Connect(
Config->DatabaseHost.c_str(),
Config->DatabaseUsername.c_str(),
Config->DatabasePassword.c_str(),
Config->DatabaseDB.c_str(),
Config->DatabasePort)) {
_log(ZONE__INIT_ERR, "Cannot continue without a database connection.");
Log.Out(Logs::General, Logs::Error, "Cannot continue without a database connection.");
return 1;
}
guild_mgr.SetDatabase(&database);
/* Register Log System and Settings */
Log.OnLogHookCallBackZone(&Zone::GMSayHookCallBackProcess);
database.LoadLogSettings(Log.log_settings);
Log.StartFileLogs();
/* Guilds */
guild_mgr.SetDatabase(&database);
GuildBanks = nullptr;
#ifdef _EQDEBUG
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif
_log(ZONE__INIT, "CURRENT_VERSION: %s", CURRENT_VERSION);
Log.Out(Logs::General, Logs::Zone_Server, "CURRENT_VERSION: %s", CURRENT_VERSION);
/*
* Setup nice signal handlers
*/
if (signal(SIGINT, CatchSignal) == SIG_ERR) {
_log(ZONE__INIT_ERR, "Could not set signal handler");
Log.Out(Logs::General, Logs::Error, "Could not set signal handler");
return 1;
}
if (signal(SIGTERM, CatchSignal) == SIG_ERR) {
_log(ZONE__INIT_ERR, "Could not set signal handler");
Log.Out(Logs::General, Logs::Error, "Could not set signal handler");
return 1;
}
#ifndef WIN32
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
_log(ZONE__INIT_ERR, "Could not set signal handler");
Log.Out(Logs::General, Logs::Error, "Could not set signal handler");
return 1;
}
#endif
const char *log_ini_file = "./log.ini";
if(!load_log_settings(log_ini_file))
_log(ZONE__INIT, "Warning: Unable to read %s", log_ini_file);
else
_log(ZONE__INIT, "Log settings loaded from %s", log_ini_file);
_log(ZONE__INIT, "Mapping Incoming Opcodes");
Log.Out(Logs::General, Logs::Zone_Server, "Mapping Incoming Opcodes");
MapOpcodes();
_log(ZONE__INIT, "Loading Variables");
Log.Out(Logs::General, Logs::Zone_Server, "Loading Variables");
database.LoadVariables();
_log(ZONE__INIT, "Loading zone names");
Log.Out(Logs::General, Logs::Zone_Server, "Loading zone names");
database.LoadZoneNames();
_log(ZONE__INIT, "Loading items");
Log.Out(Logs::General, Logs::Zone_Server, "Loading items");
if (!database.LoadItems()) {
_log(ZONE__INIT_ERR, "Loading items FAILED!");
_log(ZONE__INIT, "Failed. But ignoring error and going on...");
Log.Out(Logs::General, Logs::Error, "Loading items FAILED!");
Log.Out(Logs::General, Logs::Error, "Failed. But ignoring error and going on...");
}
_log(ZONE__INIT, "Loading npc faction lists");
Log.Out(Logs::General, Logs::Zone_Server, "Loading npc faction lists");
if (!database.LoadNPCFactionLists()) {
_log(ZONE__INIT_ERR, "Loading npcs faction lists FAILED!");
CheckEQEMuErrorAndPause();
Log.Out(Logs::General, Logs::Error, "Loading npcs faction lists FAILED!");
return 1;
}
_log(ZONE__INIT, "Loading loot tables");
Log.Out(Logs::General, Logs::Zone_Server, "Loading loot tables");
if (!database.LoadLoot()) {
_log(ZONE__INIT_ERR, "Loading loot FAILED!");
CheckEQEMuErrorAndPause();
Log.Out(Logs::General, Logs::Error, "Loading loot FAILED!");
return 1;
}
_log(ZONE__INIT, "Loading skill caps");
Log.Out(Logs::General, Logs::Zone_Server, "Loading skill caps");
if (!database.LoadSkillCaps()) {
_log(ZONE__INIT_ERR, "Loading skill caps FAILED!");
CheckEQEMuErrorAndPause();
Log.Out(Logs::General, Logs::Error, "Loading skill caps FAILED!");
return 1;
}
_log(ZONE__INIT, "Loading spells");
Log.Out(Logs::General, Logs::Zone_Server, "Loading spells");
EQEmu::MemoryMappedFile *mmf = nullptr;
LoadSpells(&mmf);
_log(ZONE__INIT, "Loading base data");
Log.Out(Logs::General, Logs::Zone_Server, "Loading base data");
if (!database.LoadBaseData()) {
_log(ZONE__INIT_ERR, "Loading base data FAILED!");
CheckEQEMuErrorAndPause();
Log.Out(Logs::General, Logs::Error, "Loading base data FAILED!");
return 1;
}
_log(ZONE__INIT, "Loading guilds");
Log.Out(Logs::General, Logs::Zone_Server, "Loading guilds");
guild_mgr.LoadGuilds();
_log(ZONE__INIT, "Loading factions");
Log.Out(Logs::General, Logs::Zone_Server, "Loading factions");
database.LoadFactionData();
_log(ZONE__INIT, "Loading titles");
Log.Out(Logs::General, Logs::Zone_Server, "Loading titles");
title_manager.LoadTitles();
_log(ZONE__INIT, "Loading AA effects");
Log.Out(Logs::General, Logs::Zone_Server, "Loading AA effects");
database.LoadAAEffects();
_log(ZONE__INIT, "Loading tributes");
Log.Out(Logs::General, Logs::Zone_Server, "Loading tributes");
database.LoadTributes();
_log(ZONE__INIT, "Loading corpse timers");
Log.Out(Logs::General, Logs::Zone_Server, "Loading corpse timers");
database.GetDecayTimes(npcCorpseDecayTimes);
_log(ZONE__INIT, "Loading commands");
Log.Out(Logs::General, Logs::Zone_Server, "Loading commands");
int retval=command_init();
if(retval<0)
_log(ZONE__INIT_ERR, "Command loading FAILED");
Log.Out(Logs::General, Logs::Error, "Command loading FAILED");
else
_log(ZONE__INIT, "%d commands loaded", retval);
Log.Out(Logs::General, Logs::Zone_Server, "%d commands loaded", retval);
//rules:
{
char tmp[64];
if (database.GetVariable("RuleSet", tmp, sizeof(tmp)-1)) {
_log(ZONE__INIT, "Loading rule set '%s'", tmp);
Log.Out(Logs::General, Logs::Zone_Server, "Loading rule set '%s'", tmp);
if(!RuleManager::Instance()->LoadRules(&database, tmp)) {
_log(ZONE__INIT_ERR, "Failed to load ruleset '%s', falling back to defaults.", tmp);
Log.Out(Logs::General, Logs::Error, "Failed to load ruleset '%s', falling back to defaults.", tmp);
}
} else {
if(!RuleManager::Instance()->LoadRules(&database, "default")) {
_log(ZONE__INIT, "No rule set configured, using default rules");
Log.Out(Logs::General, Logs::Zone_Server, "No rule set configured, using default rules");
} else {
_log(ZONE__INIT, "Loaded default rule set 'default'", tmp);
Log.Out(Logs::General, Logs::Zone_Server, "Loaded default rule set 'default'", tmp);
}
}
}
if(RuleB(TaskSystem, EnableTaskSystem)) {
_log(ZONE__INIT, "Loading Tasks");
Log.Out(Logs::General, Logs::Tasks, "[INIT] Loading Tasks");
taskmanager = new TaskManager;
taskmanager->LoadTasks();
}
@@ -298,17 +304,11 @@ int main(int argc, char** argv) {
#endif
//now we have our parser, load the quests
_log(ZONE__INIT, "Loading quests");
Log.Out(Logs::General, Logs::Zone_Server, "Loading quests");
parse->ReloadQuests();
#ifdef CLIENT_LOGS
LogFile->SetAllCallbacks(ClientLogs::EQEmuIO_buf);
LogFile->SetAllCallbacks(ClientLogs::EQEmuIO_fmt);
LogFile->SetAllCallbacks(ClientLogs::EQEmuIO_pva);
#endif
if (!worldserver.Connect()) {
_log(ZONE__INIT_ERR, "worldserver.Connect() FAILED!");
Log.Out(Logs::General, Logs::Error, "Worldserver Connection Failed :: worldserver.Connect()");
}
Timer InterserverTimer(INTERSERVER_TIMER); // does MySQL pings and auto-reconnect
@@ -320,9 +320,9 @@ int main(int argc, char** argv) {
#endif
#endif
if (!strlen(zone_name) || !strcmp(zone_name,".")) {
_log(ZONE__INIT, "Entering sleep mode");
Log.Out(Logs::General, Logs::Zone_Server, "Entering sleep mode");
} else if (!Zone::Bootup(database.GetZoneID(zone_name), 0, true)) { //todo: go above and fix this to allow cmd line instance
_log(ZONE__INIT_ERR, "Zone bootup FAILED!");
Log.Out(Logs::General, Logs::Error, "Zone Bootup failed :: Zone::Bootup");
zone = 0;
}
@@ -331,13 +331,13 @@ int main(int argc, char** argv) {
RegisterAllPatches(stream_identifier);
#ifndef WIN32
_log(COMMON__THREADS, "Main thread running with thread id %d", pthread_self());
Log.Out(Logs::Detail, Logs::None, "Main thread running with thread id %d", pthread_self());
#endif
Timer quest_timers(100);
UpdateWindowTitle();
bool worldwasconnected = worldserver.Connected();
EQStream* eqss;
std::shared_ptr<EQStream> eqss;
EQStreamInterface *eqsi;
uint8 IDLEZONEUPDATE = 200;
uint8 ZONEUPDATE = 10;
@@ -349,13 +349,12 @@ int main(int argc, char** argv) {
//Advance the timer to our current point in time
Timer::SetCurrentTime();
//process stuff from world
worldserver.Process();
if (!eqsf.IsOpen() && Config->ZonePort!=0) {
_log(ZONE__INIT, "Starting EQ Network server on port %d",Config->ZonePort);
Log.Out(Logs::General, Logs::Zone_Server, "Starting EQ Network server on port %d",Config->ZonePort);
if (!eqsf.Open(Config->ZonePort)) {
_log(ZONE__INIT_ERR, "Failed to open port %d",Config->ZonePort);
Log.Out(Logs::General, Logs::Error, "Failed to open port %d",Config->ZonePort);
ZoneConfig::SetZonePort(0);
worldserver.Disconnect();
worldwasconnected = false;
@@ -369,7 +368,7 @@ int main(int argc, char** argv) {
//structures and opcodes for that patch.
struct in_addr in;
in.s_addr = eqss->GetRemoteIP();
_log(WORLD__CLIENT, "New connection from %s:%d", inet_ntoa(in),ntohs(eqss->GetRemotePort()));
Log.Out(Logs::Detail, Logs::World_Server, "New connection from %s:%d", inet_ntoa(in),ntohs(eqss->GetRemotePort()));
stream_identifier.AddStream(eqss); //takes the stream
}
@@ -381,7 +380,7 @@ int main(int argc, char** argv) {
//now that we know what patch they are running, start up their client object
struct in_addr in;
in.s_addr = eqsi->GetRemoteIP();
_log(WORLD__CLIENT, "New client from %s:%d", inet_ntoa(in), ntohs(eqsi->GetRemotePort()));
Log.Out(Logs::Detail, Logs::World_Server, "New client from %s:%d", inet_ntoa(in), ntohs(eqsi->GetRemotePort()));
Client* client = new Client(eqsi);
entity_list.AddClient(client);
}
@@ -426,10 +425,8 @@ int main(int argc, char** argv) {
if(net.raid_timer.Enabled() && net.raid_timer.Check())
entity_list.RaidProcess();
entity_list.Process();
entity_list.MobProcess();
entity_list.Process();
entity_list.MobProcess();
entity_list.BeaconProcess();
if (zone) {
@@ -455,25 +452,6 @@ int main(int argc, char** argv) {
worldserver.AsyncConnect();
}
#if defined(_EQDEBUG) && defined(DEBUG_PC)
QueryPerformanceCounter(&tmp3);
mainloop_time += tmp3.QuadPart - tmp2.QuadPart;
if (!--tmp0) {
tmp0 = 200;
printf("Elapsed Tics : %9.0f (%1.4f sec)\n", (double)mainloop_time, ((double)mainloop_time/tmp.QuadPart));
printf("NPCAI Tics : %9.0f (%1.2f%%)\n", (double)npcai_time, ((double)npcai_time/mainloop_time)*100);
printf("FindSpell Tics: %9.0f (%1.2f%%)\n", (double)findspell_time, ((double)findspell_time/mainloop_time)*100);
printf("AtkAllowd Tics: %9.0f (%1.2f%%)\n", (double)IsAttackAllowed_time, ((double)IsAttackAllowed_time/mainloop_time)*100);
printf("ClientPro Tics: %9.0f (%1.2f%%)\n", (double)clientprocess_time, ((double)clientprocess_time/mainloop_time)*100);
printf("ClientAtk Tics: %9.0f (%1.2f%%)\n", (double)clientattack_time, ((double)clientattack_time/mainloop_time)*100);
mainloop_time = 0;
npcai_time = 0;
findspell_time = 0;
IsAttackAllowed_time = 0;
clientprocess_time = 0;
clientattack_time = 0;
}
#endif
#ifdef EQPROFILE
#ifdef PROFILE_DUMP_TIME
if(profile_dump_timer.Check()) {
@@ -481,7 +459,7 @@ int main(int argc, char** argv) {
}
#endif
#endif
} //end extra profiler block
} //end extra profiler block
Sleep(ZoneTimerResolution);
}
@@ -508,14 +486,14 @@ int main(int argc, char** argv) {
safe_delete(taskmanager);
command_deinit();
safe_delete(parse);
CheckEQEMuErrorAndPause();
_log(ZONE__INIT, "Proper zone shutdown complete.");
Log.Out(Logs::General, Logs::Zone_Server, "Proper zone shutdown complete.");
Log.CloseFileLogs();
return 0;
}
void CatchSignal(int sig_num) {
#ifdef _WINDOWS
_log(ZONE__INIT, "Recieved signal: %i", sig_num);
Log.Out(Logs::General, Logs::Zone_Server, "Recieved signal: %i", sig_num);
#endif
RunLoops = false;
}
@@ -524,9 +502,9 @@ void Shutdown()
{
Zone::Shutdown(true);
RunLoops = false;
worldserver.Disconnect();
// safe_delete(worldserver);
_log(ZONE__INIT, "Shutting down...");
worldserver.Disconnect();
Log.Out(Logs::General, Logs::Zone_Server, "Shutting down...");
Log.CloseFileLogs();
}
uint32 NetConnection::GetIP()
@@ -615,7 +593,7 @@ void LoadSpells(EQEmu::MemoryMappedFile **mmf) {
spells = reinterpret_cast<SPDat_Spell_Struct*>((*mmf)->Get());
mutex.Unlock();
} catch(std::exception &ex) {
LogFile->write(EQEMuLog::Error, "Error loading spells: %s", ex.what());
Log.Out(Logs::General, Logs::Error, "Error loading spells: %s", ex.what());
return;
}
+216 -249
View File
@@ -18,17 +18,17 @@
#include "../common/bodytypes.h"
#include "../common/classes.h"
#include "../common/debug.h"
#include "../common/global_define.h"
#include "../common/misc_functions.h"
#include "../common/rulesys.h"
#include "../common/seperator.h"
#include "../common/spdat.h"
#include "../common/string_util.h"
#include "../common/clientversions.h"
#include "../common/features.h"
#include "../common/item.h"
#include "../common/item_struct.h"
#include "../common/linked_list.h"
#include "../common/features.h"
#include "../common/item.h"
#include "../common/item_struct.h"
#include "../common/linked_list.h"
#include "../common/servertalk.h"
#include "aa.h"
@@ -56,7 +56,7 @@ extern Zone* zone;
extern volatile bool ZoneLoaded;
extern EntityList entity_list;
NPC::NPC(const NPCType* d, Spawn2* in_respawn, float x, float y, float z, float heading, int iflymode, bool IsCorpse)
NPC::NPC(const NPCType* d, Spawn2* in_respawn, const glm::vec4& position, int iflymode, bool IsCorpse)
: Mob(d->name,
d->lastname,
d->max_hp,
@@ -70,11 +70,8 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, float x, float y, float z, float
d->npc_id,
d->size,
d->runspeed,
heading,
x,
y,
z,
d->light,
position,
d->light, // innate_light
d->texture,
d->helmtexture,
d->AC,
@@ -115,7 +112,10 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, float x, float y, float z, float
qglobal_purge_timer(30000),
sendhpupdate_timer(1000),
enraged_timer(1000),
taunt_timer(TauntReuseTime * 1000)
taunt_timer(TauntReuseTime * 1000),
m_SpawnPoint(position),
m_GuardPoint(-1,-1,-1,0),
m_GuardPointSaved(0,0,0,0)
{
//What is the point of this, since the names get mangled..
Mob* mob = entity_list.GetMob(name);
@@ -205,14 +205,7 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, float x, float y, float z, float
MerchantType = d->merchanttype;
merchant_open = GetClass() == MERCHANT;
adventure_template_id = d->adventure_template;
org_x = x;
org_y = y;
org_z = z;
flymode = iflymode;
guard_x = -1; //just some value we might be able to recongize as "unset"
guard_y = -1;
guard_z = -1;
guard_heading = 0;
guard_anim = eaStanding;
roambox_distance = 0;
roambox_max_x = -2;
@@ -223,7 +216,6 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, float x, float y, float z, float
roambox_movingto_y = -2;
roambox_min_delay = 1000;
roambox_delay = 1000;
org_heading = heading;
p_depop = false;
loottable_id = d->loottable_id;
@@ -258,8 +250,8 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, float x, float y, float z, float
npc_aggro = d->npc_aggro;
if(!IsMerc())
AI_Start();
AI_Init();
AI_Start();
d_melee_texture1 = d->d_melee_texture1;
d_melee_texture2 = d->d_melee_texture2;
@@ -356,14 +348,13 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, float x, float y, float z, float
reface_timer = new Timer(15000);
reface_timer->Disable();
qGlobals = nullptr;
guard_x_saved = 0;
guard_y_saved = 0;
guard_z_saved = 0;
guard_heading_saved = 0;
SetEmoteID(d->emoteid);
InitializeBuffSlots();
CalcBonuses();
raid_target = d->raid_target;
active_light = d->light;
spell_light = equip_light = NOT_USED;
}
NPC::~NPC()
@@ -448,14 +439,19 @@ void NPC::RemoveItem(uint32 item_id, uint16 quantity, uint16 slot) {
ServerLootItem_Struct* item = *cur;
if (item->item_id == item_id && slot <= 0 && quantity <= 0) {
itemlist.erase(cur);
UpdateEquipLightValue();
if (UpdateActiveLightValue()) { SendAppearancePacket(AT_Light, GetActiveLightValue()); }
return;
}
else if (item->item_id == item_id && item->equip_slot == slot && quantity >= 1) {
//std::cout<<"NPC::RemoveItem"<<" equipSlot:"<<iterator.GetData()->equipSlot<<" quantity:"<< quantity<<std::endl; // iterator undefined [CODEBUG]
if (item->charges <= quantity)
if (item->charges <= quantity) {
itemlist.erase(cur);
else
UpdateEquipLightValue();
if (UpdateActiveLightValue()) { SendAppearancePacket(AT_Light, GetActiveLightValue()); }
}
else {
item->charges -= quantity;
}
return;
}
}
@@ -487,6 +483,9 @@ void NPC::CheckMinMaxLevel(Mob *them)
++cur;
}
UpdateEquipLightValue();
if (UpdateActiveLightValue())
SendAppearancePacket(AT_Light, GetActiveLightValue());
}
void NPC::ClearItemList() {
@@ -498,6 +497,10 @@ void NPC::ClearItemList() {
safe_delete(item);
}
itemlist.clear();
UpdateEquipLightValue();
if (UpdateActiveLightValue())
SendAppearancePacket(AT_Light, GetActiveLightValue());
}
void NPC::QueryLoot(Client* to)
@@ -508,14 +511,13 @@ void NPC::QueryLoot(Client* to)
for(ItemList::iterator cur = itemlist.begin(); cur != itemlist.end(); ++cur, ++x) {
const Item_Struct* item = database.GetItem((*cur)->item_id);
if (item == nullptr) {
LogFile->write(EQEMuLog::Error, "Database error, invalid item");
Log.Out(Logs::General, Logs::Error, "Database error, invalid item");
continue;
}
Client::TextLink linker;
linker.SetLinkType(linker.linkItemData);
linker.SetItemData(item);
linker.SetClientVersion(to->GetClientVersion());
auto item_link = linker.GenerateLink();
@@ -675,8 +677,8 @@ bool NPC::Process()
DoGravityEffect();
}
if(reface_timer->Check() && !IsEngaged() && (guard_x == GetX() && guard_y == GetY() && guard_z == GetZ())) {
SetHeading(guard_heading);
if(reface_timer->Check() && !IsEngaged() && (m_GuardPoint.x == GetX() && m_GuardPoint.y == GetY() && m_GuardPoint.z == GetZ())) {
SetHeading(m_GuardPoint.w);
SendPosition();
reface_timer->Disable();
}
@@ -716,6 +718,27 @@ uint32 NPC::CountLoot() {
return(itemlist.size());
}
void NPC::UpdateEquipLightValue()
{
equip_light = NOT_USED;
for (int index = MAIN_BEGIN; index < EmuConstants::EQUIPMENT_SIZE; ++index) {
if (equipment[index] == NOT_USED) { continue; }
auto item = database.GetItem(equipment[index]);
if (item == nullptr) { continue; }
if (item->Light & 0xF0) { continue; }
if (item->Light > equip_light) { equip_light = item->Light; }
}
for (auto iter = itemlist.begin(); iter != itemlist.end(); ++iter) {
auto item = database.GetItem((*iter)->item_id);
if (item == nullptr) { continue; }
if (item->ItemType != ItemTypeMisc && item->ItemType != ItemTypeLight) { continue; }
if (item->Light & 0xF0) { continue; }
if (item->Light > equip_light) { equip_light = item->Light; }
}
}
void NPC::Depop(bool StartSpawnTimer) {
uint16 emoteid = this->GetEmoteID();
if(emoteid != 0)
@@ -781,7 +804,7 @@ bool NPC::DatabaseCastAccepted(int spell_id) {
return false;
}
NPC* NPC::SpawnNPC(const char* spawncommand, float in_x, float in_y, float in_z, float in_heading, Client* client) {
NPC* NPC::SpawnNPC(const char* spawncommand, const glm::vec4& position, Client* client) {
if(spawncommand == 0 || spawncommand[0] == 0) {
return 0;
}
@@ -920,7 +943,7 @@ NPC* NPC::SpawnNPC(const char* spawncommand, float in_x, float in_y, float in_z,
npc_type->npc_id = 0;
npc_type->loottable_id = 0;
npc_type->texture = atoi(sep.arg[3]);
npc_type->light = 0;
npc_type->light = 0; // spawncommand needs update
npc_type->runspeed = 1.25;
npc_type->d_melee_texture1 = atoi(sep.arg[7]);
npc_type->d_melee_texture2 = atoi(sep.arg[8]);
@@ -940,7 +963,7 @@ NPC* NPC::SpawnNPC(const char* spawncommand, float in_x, float in_y, float in_z,
npc_type->prim_melee_type = 28;
npc_type->sec_melee_type = 28;
NPC* npc = new NPC(npc_type, 0, in_x, in_y, in_z, in_heading/8, FlyMode3);
NPC* npc = new NPC(npc_type, nullptr, position, FlyMode3);
npc->GiveNPCTypeData(npc_type);
entity_list.AddNPC(npc);
@@ -964,325 +987,267 @@ NPC* NPC::SpawnNPC(const char* spawncommand, float in_x, float in_y, float in_z,
}
}
uint32 ZoneDatabase::CreateNewNPCCommand(const char* zone, uint32 zone_version,Client *client, NPC* spawn, uint32 extra) {
uint32 ZoneDatabase::CreateNewNPCCommand(const char *zone, uint32 zone_version, Client *client, NPC *spawn,
uint32 extra)
{
uint32 npc_type_id = 0;
uint32 npc_type_id = 0;
if (extra && client && client->GetZoneID())
{
if (extra && client && client->GetZoneID()) {
// Set an npc_type ID within the standard range for the current zone if possible (zone_id * 1000)
int starting_npc_id = client->GetZoneID() * 1000;
std::string query = StringFormat("SELECT MAX(id) FROM npc_types WHERE id >= %i AND id < %i",
starting_npc_id, starting_npc_id + 1000);
auto results = QueryDatabase(query);
starting_npc_id, starting_npc_id + 1000);
auto results = QueryDatabase(query);
if (results.Success()) {
if (results.RowCount() != 0)
{
auto row = results.begin();
npc_type_id = atoi(row[0]) + 1;
// Prevent the npc_type id from exceeding the range for this zone
if (npc_type_id >= (starting_npc_id + 1000))
npc_type_id = 0;
}
else // No npc_type IDs set in this range yet
npc_type_id = starting_npc_id;
}
}
if (results.RowCount() != 0) {
auto row = results.begin();
npc_type_id = atoi(row[0]) + 1;
// Prevent the npc_type id from exceeding the range for this zone
if (npc_type_id >= (starting_npc_id + 1000))
npc_type_id = 0;
} else // No npc_type IDs set in this range yet
npc_type_id = starting_npc_id;
}
}
char tmpstr[64];
EntityList::RemoveNumbers(strn0cpy(tmpstr, spawn->GetName(), sizeof(tmpstr)));
std::string query;
if (npc_type_id)
{
query = StringFormat("INSERT INTO npc_types (id, name, level, race, class, hp, gender, "
"texture, helmtexture, size, loottable_id, merchant_id, face, "
"runspeed, prim_melee_type, sec_melee_type) "
"VALUES(%i, \"%s\" , %i, %i, %i, %i, %i, %i, %i, %f, %i, %i, %i, %f, %i, %i)",
npc_type_id, tmpstr, spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(),
spawn->GetMaxHP(), spawn->GetGender(), spawn->GetTexture(),
spawn->GetHelmTexture(), spawn->GetSize(), spawn->GetLoottableID(),
spawn->MerchantType, 0, spawn->GetRunspeed(), 28, 28);
auto results = QueryDatabase(query);
if (npc_type_id) {
query = StringFormat("INSERT INTO npc_types (id, name, level, race, class, hp, gender, "
"texture, helmtexture, size, loottable_id, merchant_id, face, "
"runspeed, prim_melee_type, sec_melee_type) "
"VALUES(%i, \"%s\" , %i, %i, %i, %i, %i, %i, %i, %f, %i, %i, %i, %f, %i, %i)",
npc_type_id, tmpstr, spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(),
spawn->GetMaxHP(), spawn->GetGender(), spawn->GetTexture(),
spawn->GetHelmTexture(), spawn->GetSize(), spawn->GetLoottableID(),
spawn->MerchantType, 0, spawn->GetRunspeed(), 28, 28);
auto results = QueryDatabase(query);
if (!results.Success()) {
return false;
}
npc_type_id = results.LastInsertedID();
} else {
query = StringFormat("INSERT INTO npc_types (name, level, race, class, hp, gender, "
"texture, helmtexture, size, loottable_id, merchant_id, face, "
"runspeed, prim_melee_type, sec_melee_type) "
"VALUES(\"%s\", %i, %i, %i, %i, %i, %i, %i, %f, %i, %i, %i, %f, %i, %i)",
tmpstr, spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(), spawn->GetMaxHP(),
spawn->GetGender(), spawn->GetTexture(), spawn->GetHelmTexture(), spawn->GetSize(),
spawn->GetLoottableID(), spawn->MerchantType, 0, spawn->GetRunspeed(), 28, 28);
auto results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "NPCSpawnDB Error: %s %s", query.c_str(), results.ErrorMessage().c_str());
return false;
}
npc_type_id = results.LastInsertedID();
}
else
{
query = StringFormat("INSERT INTO npc_types (name, level, race, class, hp, gender, "
"texture, helmtexture, size, loottable_id, merchant_id, face, "
"runspeed, prim_melee_type, sec_melee_type) "
"VALUES(\"%s\", %i, %i, %i, %i, %i, %i, %i, %f, %i, %i, %i, %f, %i, %i)",
tmpstr, spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(),
spawn->GetMaxHP(), spawn->GetGender(), spawn->GetTexture(),
spawn->GetHelmTexture(), spawn->GetSize(), spawn->GetLoottableID(),
spawn->MerchantType, 0, spawn->GetRunspeed(), 28, 28);
auto results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "NPCSpawnDB Error: %s %s", query.c_str(), results.ErrorMessage().c_str());
return false;
}
npc_type_id = results.LastInsertedID();
}
if(client)
client->LogSQL(query.c_str());
query = StringFormat("INSERT INTO spawngroup (id, name) VALUES(%i, '%s-%s')", 0, zone, spawn->GetName());
auto results = QueryDatabase(query);
auto results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "NPCSpawnDB Error: %s %s", query.c_str(), results.ErrorMessage().c_str());
return false;
}
uint32 spawngroupid = results.LastInsertedID();
uint32 spawngroupid = results.LastInsertedID();
if(client)
client->LogSQL(query.c_str());
query = StringFormat("INSERT INTO spawn2 (zone, version, x, y, z, respawntime, heading, spawngroupID) "
"VALUES('%s', %u, %f, %f, %f, %i, %f, %i)",
zone, zone_version, spawn->GetX(), spawn->GetY(), spawn->GetZ(), 1200,
spawn->GetHeading(), spawngroupid);
results = QueryDatabase(query);
query = StringFormat("INSERT INTO spawn2 (zone, version, x, y, z, respawntime, heading, spawngroupID) "
"VALUES('%s', %u, %f, %f, %f, %i, %f, %i)",
zone, zone_version, spawn->GetX(), spawn->GetY(), spawn->GetZ(), 1200, spawn->GetHeading(),
spawngroupid);
results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "NPCSpawnDB Error: %s %s", query.c_str(), results.ErrorMessage().c_str());
return false;
}
if(client)
client->LogSQL(query.c_str());
query = StringFormat("INSERT INTO spawnentry (spawngroupID, npcID, chance) VALUES(%i, %i, %i)",
spawngroupid, npc_type_id, 100);
results = QueryDatabase(query);
query = StringFormat("INSERT INTO spawnentry (spawngroupID, npcID, chance) VALUES(%i, %i, %i)", spawngroupid,
npc_type_id, 100);
results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "NPCSpawnDB Error: %s %s", query.c_str(), results.ErrorMessage().c_str());
return false;
}
if(client)
client->LogSQL(query.c_str());
return true;
}
uint32 ZoneDatabase::AddNewNPCSpawnGroupCommand(const char* zone, uint32 zone_version, Client *client, NPC* spawn, uint32 respawnTime) {
uint32 last_insert_id = 0;
uint32 ZoneDatabase::AddNewNPCSpawnGroupCommand(const char *zone, uint32 zone_version, Client *client, NPC *spawn,
uint32 respawnTime)
{
uint32 last_insert_id = 0;
std::string query = StringFormat("INSERT INTO spawngroup (name) VALUES('%s%s%i')",
zone, spawn->GetName(), Timer::GetCurrentTime());
auto results = QueryDatabase(query);
std::string query = StringFormat("INSERT INTO spawngroup (name) VALUES('%s%s%i')", zone, spawn->GetName(),
Timer::GetCurrentTime());
auto results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "CreateNewNPCSpawnGroupCommand Error: %s %s", query.c_str(), results.ErrorMessage().c_str());
return 0;
}
last_insert_id = results.LastInsertedID();
last_insert_id = results.LastInsertedID();
if(client)
client->LogSQL(query.c_str());
uint32 respawntime = 0;
uint32 spawnid = 0;
if (respawnTime)
respawntime = respawnTime;
else if (spawn->respawn2 && spawn->respawn2->RespawnTimer() != 0)
respawntime = spawn->respawn2->RespawnTimer();
else
respawntime = 1200;
uint32 respawntime = 0;
uint32 spawnid = 0;
if (respawnTime)
respawntime = respawnTime;
else if(spawn->respawn2 && spawn->respawn2->RespawnTimer() != 0)
respawntime = spawn->respawn2->RespawnTimer();
else
respawntime = 1200;
query = StringFormat("INSERT INTO spawn2 (zone, version, x, y, z, respawntime, heading, spawngroupID) "
"VALUES('%s', %u, %f, %f, %f, %i, %f, %i)",
zone, zone_version, spawn->GetX(), spawn->GetY(), spawn->GetZ(), respawntime,
spawn->GetHeading(), last_insert_id);
results = QueryDatabase(query);
if (!results.Success()) {
return 0;
}
spawnid = results.LastInsertedID();
query = StringFormat("INSERT INTO spawn2 (zone, version, x, y, z, respawntime, heading, spawngroupID) "
"VALUES('%s', %u, %f, %f, %f, %i, %f, %i)",
zone, zone_version, spawn->GetX(), spawn->GetY(), spawn->GetZ(), respawntime,
spawn->GetHeading(), last_insert_id);
results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "CreateNewNPCSpawnGroupCommand Error: %s %s", query.c_str(), results.ErrorMessage().c_str());
return 0;
}
spawnid = results.LastInsertedID();
query = StringFormat("INSERT INTO spawnentry (spawngroupID, npcID, chance) VALUES(%i, %i, %i)", last_insert_id,
spawn->GetNPCTypeID(), 100);
results = QueryDatabase(query);
if (!results.Success()) {
return 0;
}
if(client)
client->LogSQL(query.c_str());
query = StringFormat("INSERT INTO spawnentry (spawngroupID, npcID, chance) VALUES(%i, %i, %i)",
last_insert_id, spawn->GetNPCTypeID(), 100);
results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "CreateNewNPCSpawnGroupCommand Error: %s %s", query.c_str(), results.ErrorMessage().c_str());
return 0;
}
if(client)
client->LogSQL(query.c_str());
return spawnid;
return spawnid;
}
uint32 ZoneDatabase::UpdateNPCTypeAppearance(Client *client, NPC* spawn) {
std::string query = StringFormat("UPDATE npc_types SET name = \"%s\", level = %i, race = %i, class = %i, "
"hp = %i, gender = %i, texture = %i, helmtexture = %i, size = %i, "
"loottable_id = %i, merchant_id = %i, face = %i, WHERE id = %i",
spawn->GetName(), spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(),
spawn->GetMaxHP(), spawn->GetGender(), spawn->GetTexture(),
spawn->GetHelmTexture(), spawn->GetSize(), spawn->GetLoottableID(),
spawn->MerchantType, spawn->GetNPCTypeID());
auto results = QueryDatabase(query);
if (!results.Success() && client)
client->LogSQL(query.c_str());
return results.Success() == true? 1: 0;
uint32 ZoneDatabase::UpdateNPCTypeAppearance(Client *client, NPC *spawn)
{
std::string query =
StringFormat("UPDATE npc_types SET name = \"%s\", level = %i, race = %i, class = %i, "
"hp = %i, gender = %i, texture = %i, helmtexture = %i, size = %i, "
"loottable_id = %i, merchant_id = %i, face = %i, WHERE id = %i",
spawn->GetName(), spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(), spawn->GetMaxHP(),
spawn->GetGender(), spawn->GetTexture(), spawn->GetHelmTexture(), spawn->GetSize(),
spawn->GetLoottableID(), spawn->MerchantType, spawn->GetNPCTypeID());
auto results = QueryDatabase(query);
return results.Success() == true ? 1 : 0;
}
uint32 ZoneDatabase::DeleteSpawnLeaveInNPCTypeTable(const char* zone, Client *client, NPC* spawn) {
uint32 ZoneDatabase::DeleteSpawnLeaveInNPCTypeTable(const char *zone, Client *client, NPC *spawn)
{
uint32 id = 0;
uint32 spawngroupID = 0;
std::string query = StringFormat("SELECT id, spawngroupID FROM spawn2 WHERE "
"zone='%s' AND spawngroupID=%i", zone, spawn->GetSp2());
auto results = QueryDatabase(query);
if (!results.Success())
"zone='%s' AND spawngroupID=%i",
zone, spawn->GetSp2());
auto results = QueryDatabase(query);
if (!results.Success())
return 0;
if (results.RowCount() == 0)
return 0;
if (results.RowCount() == 0)
return 0;
auto row = results.begin();
if (row[0])
id = atoi(row[0]);
id = atoi(row[0]);
if (row[1])
spawngroupID = atoi(row[1]);
spawngroupID = atoi(row[1]);
query = StringFormat("DELETE FROM spawn2 WHERE id = '%i'", id);
results = QueryDatabase(query);
query = StringFormat("DELETE FROM spawn2 WHERE id = '%i'", id);
results = QueryDatabase(query);
if (!results.Success())
return 0;
if(client)
client->LogSQL(query.c_str());
query = StringFormat("DELETE FROM spawngroup WHERE id = '%i'", spawngroupID);
results = QueryDatabase(query);
query = StringFormat("DELETE FROM spawngroup WHERE id = '%i'", spawngroupID);
results = QueryDatabase(query);
if (!results.Success())
return 0;
if(client)
client->LogSQL(query.c_str());
query = StringFormat("DELETE FROM spawnentry WHERE spawngroupID = '%i'", spawngroupID);
results = QueryDatabase(query);
query = StringFormat("DELETE FROM spawnentry WHERE spawngroupID = '%i'", spawngroupID);
results = QueryDatabase(query);
if (!results.Success())
return 0;
if(client)
client->LogSQL(query.c_str());
return 1;
}
uint32 ZoneDatabase::DeleteSpawnRemoveFromNPCTypeTable(const char* zone, uint32 zone_version, Client *client, NPC* spawn) {
uint32 ZoneDatabase::DeleteSpawnRemoveFromNPCTypeTable(const char *zone, uint32 zone_version, Client *client,
NPC *spawn)
{
uint32 id = 0;
uint32 spawngroupID = 0;
std::string query = StringFormat("SELECT id, spawngroupID FROM spawn2 WHERE zone = '%s' "
"AND version = %u AND spawngroupID = %i",
zone, zone_version, spawn->GetSp2());
auto results = QueryDatabase(query);
if (!results.Success())
"AND version = %u AND spawngroupID = %i",
zone, zone_version, spawn->GetSp2());
auto results = QueryDatabase(query);
if (!results.Success())
return 0;
if (results.RowCount() == 0)
return 0;
if (results.RowCount() == 0)
return 0;
auto row = results.begin();
if (row[0])
id = atoi(row[0]);
id = atoi(row[0]);
if (row[1])
spawngroupID = atoi(row[1]);
spawngroupID = atoi(row[1]);
query = StringFormat("DELETE FROM spawn2 WHERE id = '%i'", id);
results = QueryDatabase(query);
if (!results.Success())
return 0;
if(client)
client->LogSQL(query.c_str());
query = StringFormat("DELETE FROM spawngroup WHERE id = '%i'", spawngroupID);
query = StringFormat("DELETE FROM spawn2 WHERE id = '%i'", id);
results = QueryDatabase(query);
if (!results.Success())
return 0;
if(client)
client->LogSQL(query.c_str());
query = StringFormat("DELETE FROM spawnentry WHERE spawngroupID = '%i'", spawngroupID);
query = StringFormat("DELETE FROM spawngroup WHERE id = '%i'", spawngroupID);
results = QueryDatabase(query);
if (!results.Success())
return 0;
if(client)
client->LogSQL(query.c_str());
query = StringFormat("DELETE FROM npc_types WHERE id = '%i'", spawn->GetNPCTypeID());
query = StringFormat("DELETE FROM spawnentry WHERE spawngroupID = '%i'", spawngroupID);
results = QueryDatabase(query);
if (!results.Success())
return 0;
if(client)
client->LogSQL(query.c_str());
query = StringFormat("DELETE FROM npc_types WHERE id = '%i'", spawn->GetNPCTypeID());
results = QueryDatabase(query);
if (!results.Success())
return 0;
return 1;
}
uint32 ZoneDatabase::AddSpawnFromSpawnGroup(const char* zone, uint32 zone_version, Client *client, NPC* spawn, uint32 spawnGroupID) {
uint32 ZoneDatabase::AddSpawnFromSpawnGroup(const char *zone, uint32 zone_version, Client *client, NPC *spawn,
uint32 spawnGroupID)
{
uint32 last_insert_id = 0;
std::string query = StringFormat("INSERT INTO spawn2 (zone, version, x, y, z, respawntime, heading, spawngroupID) "
"VALUES('%s', %u, %f, %f, %f, %i, %f, %i)",
zone, zone_version, client->GetX(), client->GetY(), client->GetZ(),
120, client->GetHeading(), spawnGroupID);
auto results = QueryDatabase(query);
if (!results.Success())
std::string query =
StringFormat("INSERT INTO spawn2 (zone, version, x, y, z, respawntime, heading, spawngroupID) "
"VALUES('%s', %u, %f, %f, %f, %i, %f, %i)",
zone, zone_version, client->GetX(), client->GetY(), client->GetZ(), 120, client->GetHeading(),
spawnGroupID);
auto results = QueryDatabase(query);
if (!results.Success())
return 0;
if(client)
client->LogSQL(query.c_str());
return 1;
return 1;
}
uint32 ZoneDatabase::AddNPCTypes(const char* zone, uint32 zone_version, Client *client, NPC* spawn, uint32 spawnGroupID) {
uint32 npc_type_id;
uint32 ZoneDatabase::AddNPCTypes(const char *zone, uint32 zone_version, Client *client, NPC *spawn, uint32 spawnGroupID)
{
uint32 npc_type_id;
char numberlessName[64];
EntityList::RemoveNumbers(strn0cpy(numberlessName, spawn->GetName(), sizeof(numberlessName)));
std::string query = StringFormat("INSERT INTO npc_types (name, level, race, class, hp, gender, "
"texture, helmtexture, size, loottable_id, merchant_id, face, "
"runspeed, prim_melee_type, sec_melee_type) "
"VALUES(\"%s\", %i, %i, %i, %i, %i, %i, %i, %f, %i, %i, %i, %f, %i, %i)",
numberlessName, spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(),
spawn->GetMaxHP(), spawn->GetGender(), spawn->GetTexture(),
spawn->GetHelmTexture(), spawn->GetSize(), spawn->GetLoottableID(),
spawn->MerchantType, 0, spawn->GetRunspeed(), 28, 28);
auto results = QueryDatabase(query);
std::string query =
StringFormat("INSERT INTO npc_types (name, level, race, class, hp, gender, "
"texture, helmtexture, size, loottable_id, merchant_id, face, "
"runspeed, prim_melee_type, sec_melee_type) "
"VALUES(\"%s\", %i, %i, %i, %i, %i, %i, %i, %f, %i, %i, %i, %f, %i, %i)",
numberlessName, spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(), spawn->GetMaxHP(),
spawn->GetGender(), spawn->GetTexture(), spawn->GetHelmTexture(), spawn->GetSize(),
spawn->GetLoottableID(), spawn->MerchantType, 0, spawn->GetRunspeed(), 28, 28);
auto results = QueryDatabase(query);
if (!results.Success())
return 0;
npc_type_id = results.LastInsertedID();
npc_type_id = results.LastInsertedID();
if(client)
client->LogSQL(query.c_str());
if(client)
client->Message(0, "%s npc_type ID %i created successfully!", numberlessName, npc_type_id);
if (client)
client->Message(0, "%s npc_type ID %i created successfully!", numberlessName, npc_type_id);
return 1;
}
@@ -1673,7 +1638,7 @@ void Mob::NPCSpecialAttacks(const char* parse, int permtag, bool reset, bool rem
{
if(database.SetSpecialAttkFlag(this->GetNPCTypeID(), orig_parse))
{
LogFile->write(EQEMuLog::Normal, "NPCTypeID: %i flagged to '%s' for Special Attacks.\n",this->GetNPCTypeID(),orig_parse);
Log.Out(Logs::General, Logs::Normal, "NPCTypeID: %i flagged to '%s' for Special Attacks.\n",this->GetNPCTypeID(),orig_parse);
}
}
}
@@ -1845,6 +1810,8 @@ void NPC::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
Mob::FillSpawnStruct(ns, ForWho);
PetOnSpawn(ns);
ns->spawn.is_npc = 1;
UpdateActiveLightValue();
ns->spawn.light = GetActiveLightValue();
}
void NPC::PetOnSpawn(NewSpawn_Struct* ns)
@@ -2434,7 +2401,7 @@ void NPC::DepopSwarmPets()
Mob* owner = entity_list.GetMobID(GetSwarmInfo()->owner_id);
if (owner)
owner->SetTempPetCount(owner->GetTempPetCount() - 1);
Depop();
return;
}
+23 -28
View File
@@ -64,10 +64,10 @@ struct AISpells_Struct {
};
struct AISpellsEffects_Struct {
uint16 spelleffectid;
int32 base;
int32 limit;
int32 max;
uint16 spelleffectid;
int32 base;
int32 limit;
int32 max;
};
struct AISpellsVar_Struct {
@@ -83,7 +83,7 @@ struct AISpellsVar_Struct {
uint32 idle_no_sp_recast_min;
uint32 idle_no_sp_recast_max;
uint8 idle_beneficial_chance;
};
};
class AA_SwarmPetInfo;
class Client;
@@ -95,10 +95,10 @@ struct Item_Struct;
class NPC : public Mob
{
public:
static NPC* SpawnNPC(const char* spawncommand, float in_x, float in_y, float in_z, float in_heading = 0, Client* client = 0);
static NPC* SpawnNPC(const char* spawncommand, const glm::vec4& position, Client* client = nullptr);
static int8 GetAILevel(bool iForceReRead = false);
NPC(const NPCType* data, Spawn2* respawn, float x, float y, float z, float heading, int iflymode, bool IsCorpse = false);
NPC(const NPCType* data, Spawn2* respawn, const glm::vec4& position, int iflymode, bool IsCorpse = false);
virtual ~NPC();
@@ -162,7 +162,7 @@ public:
FACTION_VALUE CheckNPCFactionAlly(int32 other_faction);
virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther);
void GoToBind(uint8 bindnum = 0) { GMMove(org_x, org_y, org_z, org_heading); }
void GoToBind(uint8 bindnum = 0) { GMMove(m_SpawnPoint.x, m_SpawnPoint.y, m_SpawnPoint.z, m_SpawnPoint.w); }
void Gate();
void GetPetState(SpellBuff_Struct *buffs, uint32 *items, char *name);
@@ -187,6 +187,7 @@ public:
void QueryLoot(Client* to);
uint32 CountLoot();
inline uint32 GetLoottableID() const { return loottable_id; }
virtual void UpdateEquipLightValue();
inline uint32 GetCopper() const { return copper; }
inline uint32 GetSilver() const { return silver; }
@@ -210,14 +211,8 @@ public:
uint32 GetSp2() const { return spawn_group; }
uint32 GetSpawnPointID() const;
float GetSpawnPointX() const { return org_x; }
float GetSpawnPointY() const { return org_y; }
float GetSpawnPointZ() const { return org_z; }
float GetSpawnPointH() const { return org_heading; }
float GetGuardPointX() const { return guard_x; }
float GetGuardPointY() const { return guard_y; }
float GetGuardPointZ() const { return guard_z; }
float GetGuardPointH() const { return guard_heading; }
glm::vec4 const GetSpawnPoint() const { return m_SpawnPoint; }
glm::vec4 const GetGuardPoint() const { return m_GuardPoint; }
EmuAppearance GetGuardPointAnim() const { return guard_anim; }
void SaveGuardPointAnim(EmuAppearance anim) { guard_anim = anim; }
@@ -254,7 +249,7 @@ public:
void SetNPCFactionID(int32 in) { npc_faction_id = in; database.GetFactionIdsForNPC(npc_faction_id, &faction_list, &primary_faction); }
float org_x, org_y, org_z, org_heading;
glm::vec4 m_SpawnPoint;
uint32 GetMaxDMG() const {return max_dmg;}
uint32 GetMinDMG() const {return min_dmg;}
@@ -266,6 +261,7 @@ public:
void SetPetSpellID(uint16 amt) {pet_spell_id = amt;}
uint32 GetMaxDamage(uint8 tlevel);
void SetTaunting(bool tog) {taunting = tog;}
bool IsTaunting() const { return taunting; }
void PickPocket(Client* thief);
void StartSwarmTimer(uint32 duration) { swarm_timer.Start(duration); }
void AddLootDrop(const Item_Struct*dbitem, ItemList* itemlistconst, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange = false);
@@ -287,15 +283,15 @@ public:
void StopWandering();
void ResumeWandering();
void PauseWandering(int pausetime);
void MoveTo(float mtx, float mty, float mtz, float mth, bool saveguardspot);
void GetClosestWaypoint(std::list<wplist> &wp_list, int count, float m_x, float m_y, float m_z);
void MoveTo(const glm::vec4& position, bool saveguardspot);
void GetClosestWaypoint(std::list<wplist> &wp_list, int count, const glm::vec3& location);
uint32 GetEquipment(uint8 material_slot) const; // returns item id
int32 GetEquipmentMaterial(uint8 material_slot) const;
void NextGuardPosition();
void SaveGuardSpot(bool iClearGuardSpot = false);
inline bool IsGuarding() const { return(guard_heading != 0); }
inline bool IsGuarding() const { return(m_GuardPoint.w != 0); }
void SaveGuardSpotCharm();
void RestoreGuardSpotCharm();
void AI_SetRoambox(float iDist, float iRoamDist, uint32 iDelay = 2500, uint32 iMinDelay = 2500);
@@ -386,7 +382,7 @@ public:
inline void SetHealScale(float amt) { healscale = amt; }
inline float GetHealScale() { return healscale; }
inline void SetSpellFocusDMG(int32 NewSpellFocusDMG) {SpellFocusDMG = NewSpellFocusDMG;}
inline int32 GetSpellFocusDMG() const { return SpellFocusDMG;}
@@ -407,7 +403,7 @@ public:
void SetHeroForgeModel(uint32 model) { herosforgemodel = model; }
bool IsRaidTarget() const { return raid_target; };
protected:
const NPCType* NPCTypedata;
@@ -440,7 +436,7 @@ protected:
uint32 npc_spells_id;
uint8 casting_spell_AIindex;
Timer* AIautocastspell_timer;
std::unique_ptr<Timer> AIautocastspell_timer;
uint32* pDontCastBefore_casting_spell;
std::vector<AISpells_Struct> AIspells;
bool HasAISpell;
@@ -448,8 +444,7 @@ protected:
virtual bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0);
AISpellsVar_Struct AISpellVar;
int16 GetFocusEffect(focusType type, uint16 spell_id);
uint32 npc_spells_effects_id;
std::vector<AISpellsEffects_Struct> AIspellsEffects;
bool HasAISpellEffects;
@@ -479,8 +474,8 @@ protected:
void _ClearWaypints();
int max_wp;
int save_wp;
float guard_x, guard_y, guard_z, guard_heading;
float guard_x_saved, guard_y_saved, guard_z_saved, guard_heading_saved;
glm::vec4 m_GuardPoint;
glm::vec4 m_GuardPointSaved;
EmuAppearance guard_anim;
float roambox_max_x;
float roambox_max_y;
@@ -518,7 +513,7 @@ protected:
//mercenary stuff
std::list<MercType> mercTypeList;
std::list<MercData> mercDataList;
bool raid_target;
uint8 probability;
+14 -11
View File
@@ -16,7 +16,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "../common/global_define.h"
#include "../common/string_util.h"
#include "client.h"
@@ -86,7 +86,6 @@ Object::Object(const ItemInst* inst, char* name,float max_x,float min_x,float ma
// Set as much struct data as we can
memset(&m_data, 0, sizeof(Object_Struct));
m_data.heading = heading;
//printf("Spawning object %s at %f,%f,%f\n",name,m_data.x,m_data.y,m_data.z);
m_data.z = z;
m_data.zone_id = zone->GetZoneID();
respawn_timer.Disable();
@@ -118,7 +117,7 @@ Object::Object(Client* client, const ItemInst* inst)
m_data.heading = client->GetHeading();
m_data.x = client->GetX();
m_data.y = client->GetY();
if (client->GetClientVersion() >= EQClientRoF2)
if (client->GetClientVersion() >= ClientVersion::RoF2)
{
// RoF2 places items at player's Z, which is 0.625 of their height.
m_data.z = client->GetZ() - (client->GetSize() * 0.625f);
@@ -336,7 +335,7 @@ const ItemInst* Object::GetItem(uint8 index) {
void Object::PutItem(uint8 index, const ItemInst* inst)
{
if (index > 9) {
LogFile->write(EQEMuLog::Error, "Object::PutItem: Invalid index specified (%i)", index);
Log.Out(Logs::General, Logs::Error, "Object::PutItem: Invalid index specified (%i)", index);
return;
}
@@ -468,16 +467,21 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object)
if (m_inst && sender) {
// if there is a lore conflict, delete the offending item from the server inventory
// the client updates itself and takes care of sending "duplicate lore item" messages
if(sender->CheckLoreConflict(m_inst->GetItem())) {
int16 loreslot = sender->GetInv().HasItem(m_inst->GetItem()->ID, 0, invWhereBank);
auto item = m_inst->GetItem();
if(sender->CheckLoreConflict(item)) {
int16 loreslot = sender->GetInv().HasItem(item->ID, 0, invWhereBank);
if (loreslot != INVALID_INDEX) // if the duplicate is in the bank, delete it.
sender->DeleteItemInInventory(loreslot);
else
cursordelete = true; // otherwise, we delete the new one
}
if (item->RecastDelay)
m_inst->SetRecastTimestamp(
database.GetItemRecastTimestamp(sender->CharacterID(), item->RecastType));
char buf[10];
snprintf(buf, 9, "%u", m_inst->GetItem()->ID);
snprintf(buf, 9, "%u", item->ID);
buf[9] = '\0';
std::vector<EQEmu::Any> args;
args.push_back(m_inst);
@@ -598,7 +602,7 @@ uint32 ZoneDatabase::AddObject(uint32 type, uint32 icon, const Object_Struct& ob
safe_delete_array(object_name);
auto results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Unable to insert object: %s", results.ErrorMessage().c_str());
Log.Out(Logs::General, Logs::Error, "Unable to insert object: %s", results.ErrorMessage().c_str());
return 0;
}
@@ -635,7 +639,7 @@ void ZoneDatabase::UpdateObject(uint32 id, uint32 type, uint32 icon, const Objec
safe_delete_array(object_name);
auto results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Unable to update object: %s", results.ErrorMessage().c_str());
Log.Out(Logs::General, Logs::Error, "Unable to update object: %s", results.ErrorMessage().c_str());
return;
}
@@ -654,7 +658,6 @@ Ground_Spawns* ZoneDatabase::LoadGroundSpawns(uint32 zone_id, int16 version, Gro
"LIMIT 50", zone_id, version);
auto results = QueryDatabase(query);
if (!results.Success()) {
std::cerr << "Error in LoadGroundSpawns query '" << query << "' " << results.ErrorMessage() << std::endl;
return gs;
}
@@ -680,7 +683,7 @@ void ZoneDatabase::DeleteObject(uint32 id)
std::string query = StringFormat("DELETE FROM object WHERE id = %i", id);
auto results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Unable to delete object: %s", results.ErrorMessage().c_str());
Log.Out(Logs::General, Logs::Error, "Unable to delete object: %s", results.ErrorMessage().c_str());
}
}
-8
View File
@@ -1589,22 +1589,18 @@ Message(0, "Disc packet id=%d, %x,%x,%x", disc_in->disc_id, disc_in->unknown3[0]
#endif
// Npc
if (caster->IsAttackAllowed(mob) && spells[spell_id].targettype != ST_AEBard) {
//printf("NPC Spell casted on %s\n", mob->GetName());
caster->SpellOnTarget(spell_id, mob);
}
else if (mob->IsAIControlled() && spells[spell_id].targettype == ST_AEBard) {
//printf("NPC mgb/aebard spell casted on %s\n", mob->GetName());
caster->SpellOnTarget(spell_id, mob);
}
else {
//printf("NPC AE, fall thru. spell_id:%i, Target type:%x\n", spell_id, spells[spell_id].targettype);
}
}
#ifdef IPC
else if(caster->IsNPC() && caster->CastToNPC()->IsInteractive()) {
// Interactive npc
if (caster->IsAttackAllowed(mob) && spells[spell_id].targettype != ST_AEBard && spells[spell_id].targettype != ST_GroupTeleport) {
//printf("IPC Spell casted on %s\n", mob->GetName());
caster->SpellOnTarget(spell_id, mob);
}
else if (!mob->IsAIControlled() && (spells[spell_id].targettype == ST_AEBard||group) && mob->CastToClient()->GetPVP() == caster->CastToClient()->GetPVP()) {
@@ -1612,18 +1608,15 @@ Message(0, "Disc packet id=%d, %x,%x,%x", disc_in->disc_id, disc_in->unknown3[0]
iterator.Advance();
continue;
}
//printf("IPC mgb/aebard spell casted on %s\n", mob->GetName());
caster->SpellOnTarget(spell_id, mob);
}
else {
//printf("NPC AE, fall thru. spell_id:%i, Target type:%x\n", spell_id, spells[spell_id].targettype);
}
}
#endif
else if (caster->IsClient() && !(caster->CastToClient()->IsBecomeNPC())) {
// Client
if (caster->IsAttackAllowed(mob) && spells[spell_id].targettype != ST_AEBard){
//printf("Client Spell casted on %s\n", mob->GetName());
caster->SpellOnTarget(spell_id, mob);
}
else if(spells[spell_id].targettype == ST_GroupTeleport && mob->IsClient() && mob->isgrouped && caster->isgrouped && entity_list.GetGroupByMob(caster))
@@ -1805,7 +1798,6 @@ void ZoneDatabase::AddLootDropToNPC(uint32 lootdrop_id, ItemList* itemlist) {
}
else
{
//printf("Adding item2: %i",item->item_id);
//cout << "Adding item to Mob" << endl;
ServerLootItem_Struct* item = new ServerLootItem_Struct;
item->item_id = dbitem->ItemNumber;
+2 -2
View File
@@ -1,6 +1,6 @@
#include "oriented_bounding_box.h"
#include <gtc/matrix_transform.hpp>
#include <gtx/transform.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/transform.hpp>
glm::mat4 CreateRotateMatrix(float rx, float ry, float rz) {
glm::mat4 rot_x(1.0f);
+2 -1
View File
@@ -1,7 +1,8 @@
#ifndef EQEMU_ORIENTED_BOUNDNG_BOX_H
#define EQEMU_ORIENTED_BOUNDNG_BOX_H
#include <glm.hpp>
#include <glm/vec3.hpp>
#include <glm/mat4x4.hpp>
class OrientedBoundingBox
{
+155 -155
View File
@@ -1,4 +1,4 @@
#include "../common/debug.h"
#include "../common/global_define.h"
#include "client.h"
#include "doors.h"
@@ -17,11 +17,10 @@
#endif
//#define PATHDEBUG
#define ABS(x) ((x)<0?-(x):(x))
extern Zone *zone;
float VertexDistance(Map::Vertex a, Map::Vertex b)
float VectorDistance(glm::vec3 a, glm::vec3 b)
{
float xdist = a.x - b.x;
float ydist = a.y - b.y;
@@ -29,7 +28,7 @@ float VertexDistance(Map::Vertex a, Map::Vertex b)
return sqrtf(xdist * xdist + ydist * ydist + zdist * zdist);
}
float VertexDistanceNoRoot(Map::Vertex a, Map::Vertex b)
float VectorDistanceNoRoot(glm::vec3 a, glm::vec3 b)
{
float xdist = a.x - b.x;
float ydist = a.y - b.y;
@@ -61,19 +60,19 @@ PathManager* PathManager::LoadPathFile(const char* ZoneName)
if(Ret->loadPaths(PathFile))
{
LogFile->write(EQEMuLog::Status, "Path File %s loaded.", ZonePathFileName);
Log.Out(Logs::General, Logs::Status, "Path File %s loaded.", ZonePathFileName);
}
else
{
LogFile->write(EQEMuLog::Error, "Path File %s failed to load.", ZonePathFileName);
Log.Out(Logs::General, Logs::Error, "Path File %s failed to load.", ZonePathFileName);
safe_delete(Ret);
}
fclose(PathFile);
}
else
{
LogFile->write(EQEMuLog::Error, "Path File %s not found.", ZonePathFileName);
Log.Out(Logs::General, Logs::Error, "Path File %s not found.", ZonePathFileName);
}
return Ret;
@@ -103,18 +102,18 @@ bool PathManager::loadPaths(FILE *PathFile)
if(strncmp(Magic, "EQEMUPATH", 9))
{
LogFile->write(EQEMuLog::Error, "Bad Magic String in .path file.");
Log.Out(Logs::General, Logs::Error, "Bad Magic String in .path file.");
return false;
}
fread(&Head, sizeof(Head), 1, PathFile);
LogFile->write(EQEMuLog::Status, "Path File Header: Version %ld, PathNodes %ld",
Log.Out(Logs::General, Logs::Status, "Path File Header: Version %ld, PathNodes %ld",
(long)Head.version, (long)Head.PathNodeCount);
if(Head.version != 2)
{
LogFile->write(EQEMuLog::Error, "Unsupported path file version.");
Log.Out(Logs::General, Logs::Error, "Unsupported path file version.");
return false;
}
@@ -138,7 +137,7 @@ bool PathManager::loadPaths(FILE *PathFile)
{
if(PathNodes[i].Neighbours[j].id > MaxNodeID)
{
LogFile->write(EQEMuLog::Error, "Path Node %i, Neighbour %i (%i) out of range.", i, j, PathNodes[i].Neighbours[j].id);
Log.Out(Logs::General, Logs::Error, "Path Node %i, Neighbour %i (%i) out of range.", i, j, PathNodes[i].Neighbours[j].id);
PathFileValid = false;
}
@@ -187,9 +186,9 @@ void PathManager::PrintPathing()
}
}
Map::Vertex PathManager::GetPathNodeCoordinates(int NodeNumber, bool BestZ)
glm::vec3 PathManager::GetPathNodeCoordinates(int NodeNumber, bool BestZ)
{
Map::Vertex Result;
glm::vec3 Result;
if(NodeNumber < Head.PathNodeCount)
{
@@ -206,10 +205,10 @@ Map::Vertex PathManager::GetPathNodeCoordinates(int NodeNumber, bool BestZ)
}
std::deque<int> PathManager::FindRoute(int startID, int endID)
{
_log(PATHING__DEBUG, "FindRoute from node %i to %i", startID, endID);
{
Log.Out(Logs::Detail, Logs::None, "FindRoute from node %i to %i", startID, endID);
memset(ClosedListFlag, 0, sizeof(int) * Head.PathNodeCount);
memset(ClosedListFlag, 0, sizeof(int) * Head.PathNodeCount);
std::deque<AStarNode> OpenList, ClosedList;
@@ -283,7 +282,7 @@ std::deque<int> PathManager::FindRoute(int startID, int endID)
AStarEntry.Teleport = PathNodes[CurrentNode.PathNodeID].Neighbours[i].Teleport;
// HCost is the estimated cost to get from this node to the end.
AStarEntry.HCost = VertexDistance(PathNodes[PathNodes[CurrentNode.PathNodeID].Neighbours[i].id].v,
AStarEntry.HCost = VectorDistance(PathNodes[PathNodes[CurrentNode.PathNodeID].Neighbours[i].id].v,
PathNodes[endID].v);
AStarEntry.GCost = CurrentNode.GCost + PathNodes[CurrentNode.PathNodeID].Neighbours[i].distance;
@@ -330,14 +329,14 @@ std::deque<int> PathManager::FindRoute(int startID, int endID)
}
}
_log(PATHING__DEBUG, "Unable to find a route.");
Log.Out(Logs::Detail, Logs::None, "Unable to find a route.");
return Route;
}
bool CheckLOSBetweenPoints(Map::Vertex start, Map::Vertex end) {
bool CheckLOSBetweenPoints(glm::vec3 start, glm::vec3 end) {
Map::Vertex hit;
glm::vec3 hit;
if((zone->zonemap) && (zone->zonemap->LineIntersectsZone(start, end, 1, &hit)))
return false;
@@ -350,9 +349,9 @@ auto path_compare = [](const PathNodeSortStruct& a, const PathNodeSortStruct& b)
return a.Distance < b.Distance;
};
std::deque<int> PathManager::FindRoute(Map::Vertex Start, Map::Vertex End)
std::deque<int> PathManager::FindRoute(glm::vec3 Start, glm::vec3 End)
{
_log(PATHING__DEBUG, "FindRoute(%8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f)", Start.x, Start.y, Start.z, End.x, End.y, End.z);
Log.Out(Logs::Detail, Logs::None, "FindRoute(%8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f)", Start.x, Start.y, Start.z, End.x, End.y, End.z);
std::deque<int> noderoute;
@@ -371,12 +370,11 @@ std::deque<int> PathManager::FindRoute(Map::Vertex Start, Map::Vertex End)
for(uint32 i = 0 ; i < Head.PathNodeCount; ++i)
{
if((ABS(Start.x - PathNodes[i].v.x) <= CandidateNodeRangeXY) &&
(ABS(Start.y - PathNodes[i].v.y) <= CandidateNodeRangeXY) &&
(ABS(Start.z - PathNodes[i].v.z) <= CandidateNodeRangeZ))
{
if ((std::abs(Start.x - PathNodes[i].v.x) <= CandidateNodeRangeXY) &&
(std::abs(Start.y - PathNodes[i].v.y) <= CandidateNodeRangeXY) &&
(std::abs(Start.z - PathNodes[i].v.z) <= CandidateNodeRangeZ)) {
TempNode.id = i;
TempNode.Distance = VertexDistanceNoRoot(Start, PathNodes[i].v);
TempNode.Distance = VectorDistanceNoRoot(Start, PathNodes[i].v);
SortedByDistance.push_back(TempNode);
}
@@ -386,7 +384,7 @@ std::deque<int> PathManager::FindRoute(Map::Vertex Start, Map::Vertex End)
for(auto Iterator = SortedByDistance.begin(); Iterator != SortedByDistance.end(); ++Iterator)
{
_log(PATHING__DEBUG, "Checking Reachability of Node %i from Start Position.", PathNodes[(*Iterator).id].id);
Log.Out(Logs::Detail, Logs::None, "Checking Reachability of Node %i from Start Position.", PathNodes[(*Iterator).id].id);
if(!zone->zonemap->LineIntersectsZone(Start, PathNodes[(*Iterator).id].v, 1.0f, nullptr))
{
@@ -396,11 +394,11 @@ std::deque<int> PathManager::FindRoute(Map::Vertex Start, Map::Vertex End)
}
if(ClosestPathNodeToStart <0 ) {
_log(PATHING__DEBUG, "No LOS to any starting Path Node within range.");
Log.Out(Logs::Detail, Logs::None, "No LOS to any starting Path Node within range.");
return noderoute;
}
_log(PATHING__DEBUG, "Closest Path Node To Start: %2d", ClosestPathNodeToStart);
Log.Out(Logs::Detail, Logs::None, "Closest Path Node To Start: %2d", ClosestPathNodeToStart);
// Find the nearest PathNode the end point has LOS to
@@ -410,12 +408,11 @@ std::deque<int> PathManager::FindRoute(Map::Vertex Start, Map::Vertex End)
for(uint32 i = 0 ; i < Head.PathNodeCount; ++i)
{
if((ABS(End.x - PathNodes[i].v.x) <= CandidateNodeRangeXY) &&
(ABS(End.y - PathNodes[i].v.y) <= CandidateNodeRangeXY) &&
(ABS(End.z - PathNodes[i].v.z) <= CandidateNodeRangeZ))
{
if ((std::abs(End.x - PathNodes[i].v.x) <= CandidateNodeRangeXY) &&
(std::abs(End.y - PathNodes[i].v.y) <= CandidateNodeRangeXY) &&
(std::abs(End.z - PathNodes[i].v.z) <= CandidateNodeRangeZ)) {
TempNode.id = i;
TempNode.Distance = VertexDistanceNoRoot(End, PathNodes[i].v);
TempNode.Distance = VectorDistanceNoRoot(End, PathNodes[i].v);
SortedByDistance.push_back(TempNode);
}
}
@@ -424,8 +421,8 @@ std::deque<int> PathManager::FindRoute(Map::Vertex Start, Map::Vertex End)
for(auto Iterator = SortedByDistance.begin(); Iterator != SortedByDistance.end(); ++Iterator)
{
_log(PATHING__DEBUG, "Checking Reachability of Node %i from End Position.", PathNodes[(*Iterator).id].id);
_log(PATHING__DEBUG, " (%8.3f, %8.3f, %8.3f) to (%8.3f, %8.3f, %8.3f)",
Log.Out(Logs::Detail, Logs::None, "Checking Reachability of Node %i from End Position.", PathNodes[(*Iterator).id].id);
Log.Out(Logs::Detail, Logs::None, " (%8.3f, %8.3f, %8.3f) to (%8.3f, %8.3f, %8.3f)",
End.x, End.y, End.z,
PathNodes[(*Iterator).id].v.x, PathNodes[(*Iterator).id].v.y, PathNodes[(*Iterator).id].v.z);
@@ -437,11 +434,11 @@ std::deque<int> PathManager::FindRoute(Map::Vertex Start, Map::Vertex End)
}
if(ClosestPathNodeToEnd < 0) {
_log(PATHING__DEBUG, "No LOS to any end Path Node within range.");
Log.Out(Logs::Detail, Logs::None, "No LOS to any end Path Node within range.");
return noderoute;
}
_log(PATHING__DEBUG, "Closest Path Node To End: %2d", ClosestPathNodeToEnd);
Log.Out(Logs::Detail, Logs::None, "Closest Path Node To End: %2d", ClosestPathNodeToEnd);
if(ClosestPathNodeToStart == ClosestPathNodeToEnd)
{
@@ -587,8 +584,8 @@ void PathManager::SpawnPathNodes()
npc_type->CHA = 150;
npc_type->findable = 1;
NPC* npc = new NPC(npc_type, 0, PathNodes[i].v.x, PathNodes[i].v.y, PathNodes[i].v.z, 0, FlyMode1);
auto position = glm::vec4(PathNodes[i].v.x, PathNodes[i].v.y, PathNodes[i].v.z, 0.0f);
NPC* npc = new NPC(npc_type, nullptr, position, FlyMode1);
npc->GiveNPCTypeData(npc_type);
entity_list.AddNPC(npc, true, true);
@@ -652,19 +649,19 @@ void PathManager::SimpleMeshTest()
fflush(stdout);
}
Map::Vertex Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &WaypointChanged, bool &NodeReached)
glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &WaypointChanged, bool &NodeReached)
{
WaypointChanged = false;
NodeReached = false;
Map::Vertex NodeLoc;
glm::vec3 NodeLoc;
Map::Vertex From(GetX(), GetY(), GetZ());
glm::vec3 From(GetX(), GetY(), GetZ());
Map::Vertex HeadPosition(From.x, From.y, From.z + (GetSize() < 6.0 ? 6 : GetSize()) * HEAD_POSITION);
glm::vec3 HeadPosition(From.x, From.y, From.z + (GetSize() < 6.0 ? 6 : GetSize()) * HEAD_POSITION);
Map::Vertex To(ToX, ToY, ToZ);
glm::vec3 To(ToX, ToY, ToZ);
bool SameDestination = (To == PathingDestination);
@@ -673,7 +670,7 @@ Map::Vertex Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &
if(To == From)
return To;
mlog(PATHING__DEBUG, "UpdatePath. From(%8.3f, %8.3f, %8.3f) To(%8.3f, %8.3f, %8.3f)", From.x, From.y, From.z, To.x, To.y, To.z);
Log.Out(Logs::Detail, Logs::None, "UpdatePath. From(%8.3f, %8.3f, %8.3f) To(%8.3f, %8.3f, %8.3f)", From.x, From.y, From.z, To.x, To.y, To.z);
if(From == PathingLastPosition)
{
@@ -681,7 +678,7 @@ Map::Vertex Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &
if((PathingLoopCount > 5) && !IsRooted())
{
mlog(PATHING__DEBUG, "appears to be stuck. Teleporting them to next position.", GetName());
Log.Out(Logs::Detail, Logs::None, "appears to be stuck. Teleporting them to next position.", GetName());
if(Route.size() == 0)
{
@@ -721,7 +718,7 @@ Map::Vertex Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &
// If we are already pathing, and the destination is the same as before ...
if(SameDestination)
{
mlog(PATHING__DEBUG, " Still pathing to the same destination.");
Log.Out(Logs::Detail, Logs::None, " Still pathing to the same destination.");
// Get the coordinates of the first path node we are going to.
NextNode = Route.front();
@@ -732,7 +729,7 @@ Map::Vertex Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &
// We have reached the path node.
if(NodeLoc == From)
{
mlog(PATHING__DEBUG, " Arrived at node %i", NextNode);
Log.Out(Logs::Detail, Logs::None, " Arrived at node %i", NextNode);
NodeReached = true;
@@ -746,37 +743,36 @@ Map::Vertex Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &
// target, and we may run past the target if we don't check LOS at this point.
int RouteSize = Route.size();
mlog(PATHING__DEBUG, "Route size is %i", RouteSize);
Log.Out(Logs::Detail, Logs::None, "Route size is %i", RouteSize);
if((RouteSize == 2)
|| ((PathingTraversedNodes >= RuleI(Pathing, MinNodesTraversedForLOSCheck))
&& (RouteSize <= RuleI(Pathing, MinNodesLeftForLOSCheck))
&& PathingLOSCheckTimer->Check()))
{
mlog(PATHING__DEBUG, " Checking distance to target.");
float Distance = VertexDistanceNoRoot(From, To);
Log.Out(Logs::Detail, Logs::None, " Checking distance to target.");
float Distance = VectorDistanceNoRoot(From, To);
mlog(PATHING__DEBUG, " Distance between From and To (NoRoot) is %8.3f", Distance);
Log.Out(Logs::Detail, Logs::None, " Distance between From and To (NoRoot) is %8.3f", Distance);
if((Distance <= RuleR(Pathing, MinDistanceForLOSCheckShort))
&& (ABS(From.z - To.z) <= RuleR(Pathing, ZDiffThreshold)))
{
if ((Distance <= RuleR(Pathing, MinDistanceForLOSCheckShort)) &&
(std::abs(From.z - To.z) <= RuleR(Pathing, ZDiffThreshold))) {
if(!zone->zonemap->LineIntersectsZone(HeadPosition, To, 1.0f, nullptr))
PathingLOSState = HaveLOS;
else
PathingLOSState = NoLOS;
mlog(PATHING__DEBUG, " LOS stats is %s", (PathingLOSState == HaveLOS) ? "HaveLOS" : "NoLOS");
Log.Out(Logs::Detail, Logs::None, "NoLOS");
if((PathingLOSState == HaveLOS) && zone->pathing->NoHazards(From, To))
{
mlog(PATHING__DEBUG, " No hazards. Running directly to target.");
Log.Out(Logs::Detail, Logs::None, " No hazards. Running directly to target.");
Route.clear();
return To;
}
else
{
mlog(PATHING__DEBUG, " Continuing on node path.");
Log.Out(Logs::Detail, Logs::None, " Continuing on node path.");
}
}
else
@@ -802,7 +798,7 @@ Map::Vertex Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &
if(Route.size() == 0)
{
mlog(PATHING__DEBUG, "Missing node after teleport.");
Log.Out(Logs::Detail, Logs::None, "Missing node after teleport.");
return To;
}
@@ -812,7 +808,7 @@ Map::Vertex Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &
Teleport(NodeLoc);
mlog(PATHING__DEBUG, " TELEPORTED to %8.3f, %8.3f, %8.3f\n", NodeLoc.x, NodeLoc.y, NodeLoc.z);
Log.Out(Logs::Detail, Logs::None, " TELEPORTED to %8.3f, %8.3f, %8.3f\n", NodeLoc.x, NodeLoc.y, NodeLoc.z);
Route.pop_front();
@@ -823,7 +819,7 @@ Map::Vertex Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &
}
zone->pathing->OpenDoors(PathingLastNodeVisited, NextNode, this);
mlog(PATHING__DEBUG, " Now moving to node %i", NextNode);
Log.Out(Logs::Detail, Logs::None, " Now moving to node %i", NextNode);
return zone->pathing->GetPathNodeCoordinates(NextNode);
}
@@ -831,7 +827,7 @@ Map::Vertex Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &
{
// we have run all the nodes, all that is left is the direct path from the last node
// to the destination
mlog(PATHING__DEBUG, " Reached end of node path, running direct to target.");
Log.Out(Logs::Detail, Logs::None, " Reached end of node path, running direct to target.");
return To;
}
@@ -845,31 +841,30 @@ Map::Vertex Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &
&& (RouteSize <= RuleI(Pathing, MinNodesLeftForLOSCheck))
&& PathingLOSCheckTimer->Check())
{
mlog(PATHING__DEBUG, " Checking distance to target.");
Log.Out(Logs::Detail, Logs::None, " Checking distance to target.");
float Distance = VertexDistanceNoRoot(From, To);
float Distance = VectorDistanceNoRoot(From, To);
mlog(PATHING__DEBUG, " Distance between From and To (NoRoot) is %8.3f", Distance);
Log.Out(Logs::Detail, Logs::None, " Distance between From and To (NoRoot) is %8.3f", Distance);
if((Distance <= RuleR(Pathing, MinDistanceForLOSCheckShort))
&& (ABS(From.z - To.z) <= RuleR(Pathing, ZDiffThreshold)))
{
if ((Distance <= RuleR(Pathing, MinDistanceForLOSCheckShort)) &&
(std::abs(From.z - To.z) <= RuleR(Pathing, ZDiffThreshold))) {
if(!zone->zonemap->LineIntersectsZone(HeadPosition, To, 1.0f, nullptr))
PathingLOSState = HaveLOS;
else
PathingLOSState = NoLOS;
mlog(PATHING__DEBUG, " LOS stats is %s", (PathingLOSState == HaveLOS) ? "HaveLOS" : "NoLOS");
Log.Out(Logs::Detail, Logs::None, "NoLOS");
if((PathingLOSState == HaveLOS) && zone->pathing->NoHazards(From, To))
{
mlog(PATHING__DEBUG, " No hazards. Running directly to target.");
Log.Out(Logs::Detail, Logs::None, " No hazards. Running directly to target.");
Route.clear();
return To;
}
else
{
mlog(PATHING__DEBUG, " Continuing on node path.");
Log.Out(Logs::Detail, Logs::None, " Continuing on node path.");
}
}
else
@@ -881,34 +876,33 @@ Map::Vertex Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &
{
// We get here if we were already pathing, but our destination has now changed.
//
mlog(PATHING__DEBUG, " Target has changed position.");
Log.Out(Logs::Detail, Logs::None, " Target has changed position.");
// Update our record of where we are going to.
PathingDestination = To;
// Check if we now have LOS etc to the new destination.
if(PathingLOSCheckTimer->Check())
{
float Distance = VertexDistanceNoRoot(From, To);
float Distance = VectorDistanceNoRoot(From, To);
if((Distance <= RuleR(Pathing, MinDistanceForLOSCheckShort))
&& (ABS(From.z - To.z) <= RuleR(Pathing, ZDiffThreshold)))
{
mlog(PATHING__DEBUG, " Checking for short LOS at distance %8.3f.", Distance);
if ((Distance <= RuleR(Pathing, MinDistanceForLOSCheckShort)) &&
(std::abs(From.z - To.z) <= RuleR(Pathing, ZDiffThreshold))) {
Log.Out(Logs::Detail, Logs::None, " Checking for short LOS at distance %8.3f.", Distance);
if(!zone->zonemap->LineIntersectsZone(HeadPosition, To, 1.0f, nullptr))
PathingLOSState = HaveLOS;
else
PathingLOSState = NoLOS;
mlog(PATHING__DEBUG, " LOS stats is %s", (PathingLOSState == HaveLOS) ? "HaveLOS" : "NoLOS");
Log.Out(Logs::Detail, Logs::None, "NoLOS");
if((PathingLOSState == HaveLOS) && zone->pathing->NoHazards(From, To))
{
mlog(PATHING__DEBUG, " No hazards. Running directly to target.");
Log.Out(Logs::Detail, Logs::None, " No hazards. Running directly to target.");
Route.clear();
return To;
}
else
{
mlog(PATHING__DEBUG, " Continuing on node path.");
Log.Out(Logs::Detail, Logs::None, " Continuing on node path.");
}
}
}
@@ -919,19 +913,19 @@ Map::Vertex Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &
{
if(!PathingRouteUpdateTimerShort->Check())
{
mlog(PATHING__DEBUG, "Short route update timer not yet expired.");
Log.Out(Logs::Detail, Logs::None, "Short route update timer not yet expired.");
return zone->pathing->GetPathNodeCoordinates(Route.front());
}
mlog(PATHING__DEBUG, "Short route update timer expired.");
Log.Out(Logs::Detail, Logs::None, "Short route update timer expired.");
}
else
{
if(!PathingRouteUpdateTimerLong->Check())
{
mlog(PATHING__DEBUG, "Long route update timer not yet expired.");
Log.Out(Logs::Detail, Logs::None, "Long route update timer not yet expired.");
return zone->pathing->GetPathNodeCoordinates(Route.front());
}
mlog(PATHING__DEBUG, "Long route update timer expired.");
Log.Out(Logs::Detail, Logs::None, "Long route update timer expired.");
}
// We are already pathing, destination changed, no LOS. Find the nearest node to our destination.
@@ -940,7 +934,7 @@ Map::Vertex Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &
// Destination unreachable via pathing, return direct route.
if(DestinationPathNode == -1)
{
mlog(PATHING__DEBUG, " Unable to find path node for new destination. Running straight to target.");
Log.Out(Logs::Detail, Logs::None, " Unable to find path node for new destination. Running straight to target.");
Route.clear();
return To;
}
@@ -948,7 +942,7 @@ Map::Vertex Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &
// one, we will carry on on our path.
if(DestinationPathNode == Route.back())
{
mlog(PATHING__DEBUG, " Same destination Node (%i). Continue with current path.", DestinationPathNode);
Log.Out(Logs::Detail, Logs::None, " Same destination Node (%i). Continue with current path.", DestinationPathNode);
NodeLoc = zone->pathing->GetPathNodeCoordinates(Route.front());
@@ -956,7 +950,7 @@ Map::Vertex Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &
// Check if we have reached a path node.
if(NodeLoc == From)
{
mlog(PATHING__DEBUG, " Arrived at node %i, moving to next one.\n", Route.front());
Log.Out(Logs::Detail, Logs::None, " Arrived at node %i, moving to next one.\n", Route.front());
NodeReached = true;
@@ -979,7 +973,7 @@ Map::Vertex Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &
if(Route.size() == 0)
{
mlog(PATHING__DEBUG, "Missing node after teleport.");
Log.Out(Logs::Detail, Logs::None, "Missing node after teleport.");
return To;
}
@@ -989,7 +983,7 @@ Map::Vertex Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &
Teleport(NodeLoc);
mlog(PATHING__DEBUG, " TELEPORTED to %8.3f, %8.3f, %8.3f\n", NodeLoc.x, NodeLoc.y, NodeLoc.z);
Log.Out(Logs::Detail, Logs::None, " TELEPORTED to %8.3f, %8.3f, %8.3f\n", NodeLoc.x, NodeLoc.y, NodeLoc.z);
Route.pop_front();
@@ -999,7 +993,7 @@ Map::Vertex Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &
NextNode = Route.front();
}
// Return the coords of our next path node on the route.
mlog(PATHING__DEBUG, " Now moving to node %i", NextNode);
Log.Out(Logs::Detail, Logs::None, " Now moving to node %i", NextNode);
zone->pathing->OpenDoors(PathingLastNodeVisited, NextNode, this);
@@ -1007,7 +1001,7 @@ Map::Vertex Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &
}
else
{
mlog(PATHING__DEBUG, " Reached end of path grid. Running direct to target.");
Log.Out(Logs::Detail, Logs::None, " Reached end of path grid. Running direct to target.");
return To;
}
}
@@ -1015,7 +1009,7 @@ Map::Vertex Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &
}
else
{
mlog(PATHING__DEBUG, " Target moved. End node is different. Clearing route.");
Log.Out(Logs::Detail, Logs::None, " Target moved. End node is different. Clearing route.");
Route.clear();
// We will now fall through to get a new route.
@@ -1025,11 +1019,11 @@ Map::Vertex Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &
}
mlog(PATHING__DEBUG, " Our route list is empty.");
Log.Out(Logs::Detail, Logs::None, " Our route list is empty.");
if((SameDestination) && !PathingLOSCheckTimer->Check())
{
mlog(PATHING__DEBUG, " Destination same as before, LOS check timer not reached. Returning To.");
Log.Out(Logs::Detail, Logs::None, " Destination same as before, LOS check timer not reached. Returning To.");
return To;
}
@@ -1039,27 +1033,26 @@ Map::Vertex Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &
WaypointChanged = true;
float Distance = VertexDistanceNoRoot(From, To);
float Distance = VectorDistanceNoRoot(From, To);
if((Distance <= RuleR(Pathing, MinDistanceForLOSCheckLong))
&& (ABS(From.z - To.z) <= RuleR(Pathing, ZDiffThreshold)))
{
mlog(PATHING__DEBUG, " Checking for long LOS at distance %8.3f.", Distance);
if ((Distance <= RuleR(Pathing, MinDistanceForLOSCheckLong)) &&
(std::abs(From.z - To.z) <= RuleR(Pathing, ZDiffThreshold))) {
Log.Out(Logs::Detail, Logs::None, " Checking for long LOS at distance %8.3f.", Distance);
if(!zone->zonemap->LineIntersectsZone(HeadPosition, To, 1.0f, nullptr))
PathingLOSState = HaveLOS;
else
PathingLOSState = NoLOS;
mlog(PATHING__DEBUG, " LOS stats is %s", (PathingLOSState == HaveLOS) ? "HaveLOS" : "NoLOS");
Log.Out(Logs::Detail, Logs::None, "NoLOS");
if((PathingLOSState == HaveLOS) && zone->pathing->NoHazards(From, To))
{
mlog(PATHING__DEBUG, "Target is reachable. Running directly there.");
Log.Out(Logs::Detail, Logs::None, "Target is reachable. Running directly there.");
return To;
}
}
mlog(PATHING__DEBUG, " Calculating new route to target.");
Log.Out(Logs::Detail, Logs::None, " Calculating new route to target.");
Route = zone->pathing->FindRoute(From, To);
@@ -1067,14 +1060,14 @@ Map::Vertex Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &
if(Route.size() == 0)
{
mlog(PATHING__DEBUG, " No route available, running direct.");
Log.Out(Logs::Detail, Logs::None, " No route available, running direct.");
return To;
}
if(SameDestination && (Route.front() == PathingLastNodeVisited))
{
mlog(PATHING__DEBUG, " Probable loop detected. Same destination and Route.front() == PathingLastNodeVisited.");
Log.Out(Logs::Detail, Logs::None, " Probable loop detected. Same destination and Route.front() == PathingLastNodeVisited.");
Route.clear();
@@ -1082,7 +1075,7 @@ Map::Vertex Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &
}
NodeLoc = zone->pathing->GetPathNodeCoordinates(Route.front());
mlog(PATHING__DEBUG, " New route determined, heading for node %i", Route.front());
Log.Out(Logs::Detail, Logs::None, " New route determined, heading for node %i", Route.front());
PathingLoopCount = 0;
@@ -1090,7 +1083,7 @@ Map::Vertex Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &
}
int PathManager::FindNearestPathNode(Map::Vertex Position)
int PathManager::FindNearestPathNode(glm::vec3 Position)
{
// Find the nearest PathNode we have LOS to.
@@ -1109,12 +1102,11 @@ int PathManager::FindNearestPathNode(Map::Vertex Position)
for(uint32 i = 0 ; i < Head.PathNodeCount; ++i)
{
if((ABS(Position.x - PathNodes[i].v.x) <= CandidateNodeRangeXY) &&
(ABS(Position.y - PathNodes[i].v.y) <= CandidateNodeRangeXY) &&
(ABS(Position.z - PathNodes[i].v.z) <= CandidateNodeRangeZ))
{
if ((std::abs(Position.x - PathNodes[i].v.x) <= CandidateNodeRangeXY) &&
(std::abs(Position.y - PathNodes[i].v.y) <= CandidateNodeRangeXY) &&
(std::abs(Position.z - PathNodes[i].v.z) <= CandidateNodeRangeZ)) {
TempNode.id = i;
TempNode.Distance = VertexDistanceNoRoot(Position, PathNodes[i].v);
TempNode.Distance = VectorDistanceNoRoot(Position, PathNodes[i].v);
SortedByDistance.push_back(TempNode);
}
@@ -1124,7 +1116,7 @@ int PathManager::FindNearestPathNode(Map::Vertex Position)
for(auto Iterator = SortedByDistance.begin(); Iterator != SortedByDistance.end(); ++Iterator)
{
_log(PATHING__DEBUG, "Checking Reachability of Node %i from Start Position.", PathNodes[(*Iterator).id].id);
Log.Out(Logs::Detail, Logs::None, "Checking Reachability of Node %i from Start Position.", PathNodes[(*Iterator).id].id);
if(!zone->zonemap->LineIntersectsZone(Position, PathNodes[(*Iterator).id].v, 1.0f, nullptr))
{
@@ -1134,40 +1126,39 @@ int PathManager::FindNearestPathNode(Map::Vertex Position)
}
if(ClosestPathNodeToStart <0 ) {
_log(PATHING__DEBUG, "No LOS to any starting Path Node within range.");
Log.Out(Logs::Detail, Logs::None, "No LOS to any starting Path Node within range.");
return -1;
}
return ClosestPathNodeToStart;
}
bool PathManager::NoHazards(Map::Vertex From, Map::Vertex To)
bool PathManager::NoHazards(glm::vec3 From, glm::vec3 To)
{
// Test the Z coordinate at the mid point.
//
Map::Vertex MidPoint((From.x + To.x) / 2, (From.y + To.y) / 2, From.z);
glm::vec3 MidPoint((From.x + To.x) / 2, (From.y + To.y) / 2, From.z);
float NewZ = zone->zonemap->FindBestZ(MidPoint, nullptr);
if(ABS(NewZ - From.z) > RuleR(Pathing, ZDiffThreshold))
{
_log(PATHING__DEBUG, " HAZARD DETECTED moving from %8.3f, %8.3f, %8.3f to %8.3f, %8.3f, %8.3f. Z Change is %8.3f",
if (std::abs(NewZ - From.z) > RuleR(Pathing, ZDiffThreshold)) {
Log.Out(Logs::Detail, Logs::None, " HAZARD DETECTED moving from %8.3f, %8.3f, %8.3f to %8.3f, %8.3f, %8.3f. Z Change is %8.3f",
From.x, From.y, From.z, MidPoint.x, MidPoint.y, MidPoint.z, NewZ - From.z);
return false;
}
else
{
_log(PATHING__DEBUG, "No HAZARD DETECTED moving from %8.3f, %8.3f, %8.3f to %8.3f, %8.3f, %8.3f. Z Change is %8.3f",
Log.Out(Logs::Detail, Logs::None, "No HAZARD DETECTED moving from %8.3f, %8.3f, %8.3f to %8.3f, %8.3f, %8.3f. Z Change is %8.3f",
From.x, From.y, From.z, MidPoint.x, MidPoint.y, MidPoint.z, NewZ - From.z);
}
return true;
}
bool PathManager::NoHazardsAccurate(Map::Vertex From, Map::Vertex To)
bool PathManager::NoHazardsAccurate(glm::vec3 From, glm::vec3 To)
{
float stepx, stepy, stepz, curx, cury, curz;
Map::Vertex cur = From;
glm::vec3 cur = From;
float last_z = From.z;
float step_size = 1.0;
@@ -1185,11 +1176,10 @@ bool PathManager::NoHazardsAccurate(Map::Vertex From, Map::Vertex To)
stepy = (stepy / factor)*step_size;
stepz = (stepz / factor)*step_size;
Map::Vertex TestPoint(curx, cury, curz);
glm::vec3 TestPoint(curx, cury, curz);
float NewZ = zone->zonemap->FindBestZ(TestPoint, nullptr);
if (ABS(NewZ - last_z) > 5.0f)
{
_log(PATHING__DEBUG, " HAZARD DETECTED moving from %8.3f, %8.3f, %8.3f to %8.3f, %8.3f, %8.3f. Best Z %8.3f, Z Change is %8.3f",
if (std::abs(NewZ - last_z) > 5.0f) {
Log.Out(Logs::Detail, Logs::None, " HAZARD DETECTED moving from %8.3f, %8.3f, %8.3f to %8.3f, %8.3f, %8.3f. Best Z %8.3f, Z Change is %8.3f",
From.x, From.y, From.z, TestPoint.x, TestPoint.y, TestPoint.z, NewZ, NewZ - From.z);
return false;
}
@@ -1197,16 +1187,18 @@ bool PathManager::NoHazardsAccurate(Map::Vertex From, Map::Vertex To)
if (zone->watermap)
{
if (zone->watermap->InLiquid(From.x, From.y, From.z) || zone->watermap->InLiquid(To.x, To.y, To.z))
auto from = glm::vec3(From.x, From.y, From.z);
auto to = glm::vec3(To.x, To.y, To.z);
if (zone->watermap->InLiquid(from) || zone->watermap->InLiquid(to))
{
break;
}
if (zone->watermap->InLiquid(TestPoint.x, TestPoint.y, NewZ))
auto testPointNewZ = glm::vec3(TestPoint.x, TestPoint.y, NewZ);
if (zone->watermap->InLiquid(testPointNewZ))
{
Map::Vertex TestPointWater(TestPoint.x, TestPoint.y, NewZ - 0.5f);
Map::Vertex TestPointWaterDest = TestPointWater;
Map::Vertex hit;
glm::vec3 TestPointWater(TestPoint.x, TestPoint.y, NewZ - 0.5f);
glm::vec3 TestPointWaterDest = TestPointWater;
glm::vec3 hit;
TestPointWaterDest.z -= 500;
float best_z2 = -999990;
if (zone->zonemap->LineIntersectsZone(TestPointWater, TestPointWaterDest, 1.0f, &hit))
@@ -1215,30 +1207,33 @@ bool PathManager::NoHazardsAccurate(Map::Vertex From, Map::Vertex To)
}
if (best_z2 == -999990)
{
_log(PATHING__DEBUG, " HAZARD DETECTED, really deep water/lava!");
Log.Out(Logs::Detail, Logs::None, " HAZARD DETECTED, really deep water/lava!");
return false;
}
else
{
if (ABS(NewZ - best_z2) > RuleR(Pathing, ZDiffThreshold))
{
_log(PATHING__DEBUG, " HAZARD DETECTED, water is fairly deep at %8.3f units deep", ABS(NewZ - best_z2));
if (std::abs(NewZ - best_z2) > RuleR(Pathing, ZDiffThreshold)) {
Log.Out(Logs::Detail, Logs::None,
" HAZARD DETECTED, water is fairly deep at %8.3f units deep",
std::abs(NewZ - best_z2));
return false;
}
else
{
_log(PATHING__DEBUG, " HAZARD NOT DETECTED, water is shallow at %8.3f units deep", ABS(NewZ - best_z2));
Log.Out(Logs::Detail, Logs::None,
" HAZARD NOT DETECTED, water is shallow at %8.3f units deep",
std::abs(NewZ - best_z2));
}
}
}
else
{
_log(PATHING__DEBUG, "Hazard point not in water or lava!");
Log.Out(Logs::Detail, Logs::None, "Hazard point not in water or lava!");
}
}
else
{
_log(PATHING__DEBUG, "No water map loaded for hazards!");
Log.Out(Logs::Detail, Logs::None, "No water map loaded for hazards!");
}
curx += stepx;
@@ -1249,9 +1244,12 @@ bool PathManager::NoHazardsAccurate(Map::Vertex From, Map::Vertex To)
cur.y = cury;
cur.z = curz;
if (ABS(curx - To.x) < step_size) cur.x = To.x;
if (ABS(cury - To.y) < step_size) cur.y = To.y;
if (ABS(curz - To.z) < step_size) cur.z = To.z;
if (std::abs(curx - To.x) < step_size)
cur.x = To.x;
if (std::abs(cury - To.y) < step_size)
cur.y = To.y;
if (std::abs(curz - To.z) < step_size)
cur.z = To.z;
} while (cur.x != To.x || cur.y != To.y || cur.z != To.z);
return true;
@@ -1290,7 +1288,7 @@ void PathManager::OpenDoors(int Node1, int Node2, Mob *ForWho)
if(d && !d->IsDoorOpen() )
{
_log(PATHING__DEBUG, "Opening door %i for %s", PathNodes[Node1].Neighbours[i].DoorID, ForWho->GetName());
Log.Out(Logs::Detail, Logs::None, "Opening door %i for %s", PathNodes[Node1].Neighbours[i].DoorID, ForWho->GetName());
d->ForceOpen(ForWho);
}
@@ -1574,7 +1572,8 @@ int32 PathManager::AddNode(float x, float y, float z, float best_z, int32 reques
npc_type->CHA = 150;
npc_type->findable = 1;
NPC* npc = new NPC(npc_type, 0, new_node.v.x, new_node.v.y, new_node.v.z, 0, FlyMode1);
auto position = glm::vec4(new_node.v.x, new_node.v.y, new_node.v.z, 0.0f);
NPC* npc = new NPC(npc_type, nullptr, position, FlyMode1);
npc->GiveNPCTypeData(npc_type);
entity_list.AddNPC(npc, true, true);
@@ -1634,7 +1633,8 @@ int32 PathManager::AddNode(float x, float y, float z, float best_z, int32 reques
npc_type->CHA = 150;
npc_type->findable = 1;
NPC* npc = new NPC(npc_type, 0, new_node.v.x, new_node.v.y, new_node.v.z, 0, FlyMode1);
auto position = glm::vec4(new_node.v.x, new_node.v.y, new_node.v.z, 0.0f);
NPC* npc = new NPC(npc_type, nullptr, position, FlyMode1);
npc->GiveNPCTypeData(npc_type);
entity_list.AddNPC(npc, true, true);
@@ -1793,7 +1793,7 @@ void PathManager::ConnectNodeToNode(int32 Node1, int32 Node2, int32 teleport, in
a->Neighbours[a_i].id = b->id;
a->Neighbours[a_i].DoorID = doorid;
a->Neighbours[a_i].Teleport = teleport;
a->Neighbours[a_i].distance = VertexDistance(a->v, b->v);
a->Neighbours[a_i].distance = VectorDistance(a->v, b->v);
break;
}
}
@@ -1808,7 +1808,7 @@ void PathManager::ConnectNodeToNode(int32 Node1, int32 Node2, int32 teleport, in
b->Neighbours[b_i].id = a->id;
b->Neighbours[b_i].DoorID = doorid;
b->Neighbours[b_i].Teleport = teleport;
b->Neighbours[b_i].distance = VertexDistance(a->v, b->v);
b->Neighbours[b_i].distance = VectorDistance(a->v, b->v);
break;
}
}
@@ -1878,7 +1878,7 @@ void PathManager::ConnectNode(int32 Node1, int32 Node2, int32 teleport, int32 do
a->Neighbours[a_i].id = b->id;
a->Neighbours[a_i].DoorID = doorid;
a->Neighbours[a_i].Teleport = teleport;
a->Neighbours[a_i].distance = VertexDistance(a->v, b->v);
a->Neighbours[a_i].distance = VectorDistance(a->v, b->v);
break;
}
}
@@ -1994,7 +1994,7 @@ void PathManager::MoveNode(Client *c)
if(zone->zonemap)
{
Map::Vertex loc(c->GetX(), c->GetY(), c->GetZ());
glm::vec3 loc(c->GetX(), c->GetY(), c->GetZ());
Node->bestz = zone->zonemap->FindBestZ(loc, nullptr);
}
else
@@ -2065,14 +2065,14 @@ bool PathManager::NodesConnected(PathNode *a, PathNode *b)
return false;
}
bool PathManager::CheckLosFN(Map::Vertex a, Map::Vertex b)
bool PathManager::CheckLosFN(glm::vec3 a, glm::vec3 b)
{
if(zone->zonemap)
{
Map::Vertex hit;
glm::vec3 hit;
Map::Vertex myloc;
Map::Vertex oloc;
glm::vec3 myloc;
glm::vec3 oloc;
myloc.x = a.x;
myloc.y = a.y;
@@ -2115,7 +2115,7 @@ void PathManager::ProcessNodesAndSave(std::string filename)
if(!NodesConnected(&PathNodes[x], &PathNodes[y]))
{
if(VertexDistance(PathNodes[x].v, PathNodes[y].v) <= 200)
if(VectorDistance(PathNodes[x].v, PathNodes[y].v) <= 200)
{
if(CheckLosFN(PathNodes[x].v, PathNodes[y].v))
{
+7 -7
View File
@@ -30,7 +30,7 @@ struct NeighbourNode {
struct PathNode {
uint16 id;
Map::Vertex v;
glm::vec3 v;
float bestz;
NeighbourNode Neighbours[PATHNODENEIGHBOURS];
};
@@ -60,17 +60,17 @@ public:
static PathManager *LoadPathFile(const char *ZoneName);
bool loadPaths(FILE *fp);
void PrintPathing();
std::deque<int> FindRoute(Map::Vertex Start, Map::Vertex End);
std::deque<int> FindRoute(glm::vec3 Start, glm::vec3 End);
std::deque<int> FindRoute(int startID, int endID);
Map::Vertex GetPathNodeCoordinates(int NodeNumber, bool BestZ = true);
bool CheckLosFN(Map::Vertex a, Map::Vertex b);
glm::vec3 GetPathNodeCoordinates(int NodeNumber, bool BestZ = true);
bool CheckLosFN(glm::vec3 a, glm::vec3 b);
void SpawnPathNodes();
void MeshTest();
void SimpleMeshTest();
int FindNearestPathNode(Map::Vertex Position);
bool NoHazards(Map::Vertex From, Map::Vertex To);
bool NoHazardsAccurate(Map::Vertex From, Map::Vertex To);
int FindNearestPathNode(glm::vec3 Position);
bool NoHazards(glm::vec3 From, glm::vec3 To);
bool NoHazardsAccurate(glm::vec3 From, glm::vec3 To);
void OpenDoors(int Node1, int Node2, Mob* ForWho);
PathNode* FindPathNodeByCoordinates(float x, float y, float z);
+18 -18
View File
@@ -27,7 +27,7 @@
#include "../common/features.h"
#ifdef EMBPERL_XS_CLASSES
#include "../common/debug.h"
#include "../common/global_define.h"
#include "embperl.h"
#ifdef seed
@@ -1072,7 +1072,7 @@ XS(XS_Client_SetBindPoint)
new_z = (float)SvNV(ST(5));
}
THIS->SetBindPoint(to_zone, to_instance, new_x, new_y, new_z);
THIS->SetBindPoint(to_zone, to_instance, glm::vec3(new_x, new_y, new_z));
}
XSRETURN_EMPTY;
}
@@ -1271,15 +1271,15 @@ XS(XS_Client_MovePC)
}
else {
if (THIS->IsMerc())
_log(CLIENT__ERROR, "Perl(XS_Client_MovePC) attempted to process a type Merc reference");
Log.Out(Logs::Detail, Logs::None, "[CLIENT] Perl(XS_Client_MovePC) attempted to process a type Merc reference");
else if (THIS->IsNPC())
_log(CLIENT__ERROR, "Perl(XS_Client_MovePC) attempted to process a type NPC reference");
Log.Out(Logs::Detail, Logs::None, "[CLIENT] Perl(XS_Client_MovePC) attempted to process a type NPC reference");
#ifdef BOTS
else if (THIS->IsBot())
_log(CLIENT__ERROR, "Perl(XS_Client_MovePC) attempted to process a type Bot reference");
#endif
Log.Out(Logs::Detail, Logs::None, "[CLIENT] Perl(XS_Client_MovePC) attempted to process a type Bot reference");
#endif
else
_log(CLIENT__ERROR, "Perl(XS_Client_MovePC) attempted to process an Unknown type reference");
Log.Out(Logs::Detail, Logs::None, "[CLIENT] Perl(XS_Client_MovePC) attempted to process an Unknown type reference");
Perl_croak(aTHX_ "THIS is not of type Client");
}
@@ -1317,17 +1317,17 @@ XS(XS_Client_MovePCInstance)
}
else {
if (THIS->IsMerc())
_log(CLIENT__ERROR, "Perl(XS_Client_MovePCInstance) attempted to process a type Merc reference");
Log.Out(Logs::Detail, Logs::None, "[CLIENT] Perl(XS_Client_MovePCInstance) attempted to process a type Merc reference");
else if (THIS->IsNPC())
_log(CLIENT__ERROR, "Perl(XS_Client_MovePCInstance) attempted to process a type NPC reference");
Log.Out(Logs::Detail, Logs::None, "[CLIENT] Perl(XS_Client_MovePCInstance) attempted to process a type NPC reference");
#ifdef BOTS
else if (THIS->IsBot())
_log(CLIENT__ERROR, "Perl(XS_Client_MovePCInstance) attempted to process a type Bot reference");
Log.Out(Logs::Detail, Logs::None, "[CLIENT] Perl(XS_Client_MovePCInstance) attempted to process a type Bot reference");
#endif
else
_log(CLIENT__ERROR, "Perl(XS_Client_MovePCInstance) attempted to process an Unknown type reference");
Log.Out(Logs::Detail, Logs::None, "[CLIENT] Perl(XS_Client_MovePCInstance) attempted to process an Unknown type reference");
Perl_croak(aTHX_ "THIS is not of type Client");
Perl_croak(aTHX_ "THIS is not of type Client");
Perl_croak(aTHX_ "THIS is not of type Client");
}
@@ -3899,7 +3899,7 @@ XS(XS_Client_GetClientVersion)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetClientVersion();
RETVAL = static_cast<unsigned int>(THIS->GetClientVersion());
XSprePUSH; PUSHu((UV)RETVAL);
}
XSRETURN(1);
@@ -5094,7 +5094,7 @@ XS(XS_Client_GetTaskActivityDoneCount)
Perl_croak(aTHX_ "Usage: Client::GetTaskActivityDoneCount(THIS, TaskID, ActivityID)");
{
Client * THIS;
int RETVAL;
int RETVAL;
int TaskID = (int)SvIV(ST(1));
int ActivityID = (int)SvIV(ST(2));
dXSTARG;
@@ -5108,7 +5108,7 @@ XS(XS_Client_GetTaskActivityDoneCount)
if (THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetTaskActivityDoneCountFromTaskID(TaskID, ActivityID);
XSprePUSH; PUSHi((IV)RETVAL);
}
@@ -5952,7 +5952,7 @@ XS(XS_Client_SilentMessage)
{
Client * THIS;
dXSTARG;
if (sv_derived_from(ST(0), "Client")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(Client *,tmp);
@@ -5963,7 +5963,7 @@ XS(XS_Client_SilentMessage)
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
if(THIS->GetTarget() != NULL){
if(THIS->GetTarget()->IsNPC()){
if (THIS->DistNoRootNoZ(*THIS->GetTarget()) <= 200) {
if (DistanceSquaredNoZ(THIS->GetPosition(), THIS->GetTarget()->GetPosition()) <= 200) {
if(THIS->GetTarget()->CastToNPC()->IsMoving() && !THIS->GetTarget()->CastToNPC()->IsOnHatelist(THIS->GetTarget()))
THIS->GetTarget()->CastToNPC()->PauseWandering(RuleI(NPC, SayPauseTimeInSec));
THIS->ChannelMessageReceived(8, 0, 100, SvPV_nolen(ST(1)));
@@ -6351,7 +6351,7 @@ XS(boot_Client)
newXSproto(strcpy(buf, "SendMarqueeMessage"), XS_Client_SendMarqueeMessage, file, "$$$$$$$");
newXSproto(strcpy(buf, "SendColoredText"), XS_Client_SendColoredText, file, "$$$");
newXSproto(strcpy(buf, "SendSpellAnim"), XS_Client_SendSpellAnim, file, "$$$");
XSRETURN_YES;
}
+20 -13
View File
@@ -27,7 +27,7 @@
#include "../common/features.h"
#ifdef EMBPERL_XS_CLASSES
#include "../common/debug.h"
#include "../common/global_define.h"
#include "embperl.h"
#ifdef seed
@@ -138,7 +138,7 @@ XS(XS_Doors_GetX)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetX();
RETVAL = THIS->GetPosition().x;
XSprePUSH; PUSHn((double)RETVAL);
}
XSRETURN(1);
@@ -164,7 +164,7 @@ XS(XS_Doors_GetY)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetY();
RETVAL = THIS->GetPosition().y;
XSprePUSH; PUSHn((double)RETVAL);
}
XSRETURN(1);
@@ -190,7 +190,7 @@ XS(XS_Doors_GetZ)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetZ();
RETVAL = THIS->GetPosition().z;
XSprePUSH; PUSHn((double)RETVAL);
}
XSRETURN(1);
@@ -216,7 +216,7 @@ XS(XS_Doors_GetHeading)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetHeading();
RETVAL = THIS->GetPosition().w;
XSprePUSH; PUSHn((double)RETVAL);
}
XSRETURN(1);
@@ -556,7 +556,7 @@ XS(XS_Doors_SetX)
Perl_croak(aTHX_ "Usage: Doors::SetX(THIS, XPos)");
{
Doors * THIS;
float pos = (float)SvNV(ST(1));
float x = (float)SvNV(ST(1));
if (sv_derived_from(ST(0), "Doors")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
@@ -566,8 +566,9 @@ XS(XS_Doors_SetX)
Perl_croak(aTHX_ "THIS is not of type Doors");
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
THIS->SetX(pos);
auto position = THIS->GetPosition();
position.x = x;
THIS->SetPosition(position);
}
XSRETURN_EMPTY;
}
@@ -580,7 +581,7 @@ XS(XS_Doors_SetY)
Perl_croak(aTHX_ "Usage: Doors::SetY(THIS, YPos)");
{
Doors * THIS;
float pos = (float)SvNV(ST(1));
float y = (float)SvNV(ST(1));
if (sv_derived_from(ST(0), "Doors")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
@@ -591,7 +592,9 @@ XS(XS_Doors_SetY)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
THIS->SetY(pos);
auto position = THIS->GetPosition();
position.y = y;
THIS->SetPosition(position);
}
XSRETURN_EMPTY;
}
@@ -604,7 +607,7 @@ XS(XS_Doors_SetZ)
Perl_croak(aTHX_ "Usage: Doors::SetZ(THIS, ZPos)");
{
Doors * THIS;
float pos = (float)SvNV(ST(1));
float z = (float)SvNV(ST(1));
if (sv_derived_from(ST(0), "Doors")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
@@ -615,7 +618,9 @@ XS(XS_Doors_SetZ)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
THIS->SetZ(pos);
auto position = THIS->GetPosition();
position.z = z;
THIS->SetPosition(position);
}
XSRETURN_EMPTY;
}
@@ -639,7 +644,9 @@ XS(XS_Doors_SetHeading)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
THIS->SetHeading(heading);
auto position = THIS->GetPosition();
position.w = heading;
THIS->SetPosition(position);
}
XSRETURN_EMPTY;
}
+2 -2
View File
@@ -27,7 +27,7 @@
#include "../common/features.h"
#ifdef EMBPERL_XS_CLASSES
#include "../common/debug.h"
#include "../common/global_define.h"
#include <list>
#include "embperl.h"
@@ -1875,7 +1875,7 @@ XS(XS_EntityList_GetRandomClient)
c = INT2PTR(Client *,tmp);
}
}
RETVAL = entity_list.GetRandomClient(x, y, z, d * d, c);
RETVAL = entity_list.GetRandomClient(glm::vec3(x, y, z), d * d, c);
ST(0) = sv_newmortal();
sv_setref_pv(ST(0), "Client", (void*)RETVAL);
}
+1 -1
View File
@@ -27,7 +27,7 @@
#include "../common/features.h"
#ifdef EMBPERL_XS_CLASSES
#include "../common/debug.h"
#include "../common/global_define.h"
#include "embperl.h"
#ifdef seed
+1 -1
View File
@@ -19,7 +19,7 @@
#include "../common/features.h"
#include "client.h"
#ifdef EMBPERL_XS_CLASSES
#include "../common/debug.h"
#include "../common/global_define.h"
#include "embperl.h"
#ifdef seed
+36 -12
View File
@@ -27,7 +27,7 @@
#include "../common/features.h"
#ifdef EMBPERL_XS_CLASSES
#include "../common/debug.h"
#include "../common/global_define.h"
#include "embperl.h"
#ifdef seed
@@ -1615,7 +1615,7 @@ XS(XS_Mob_TypesTempPet)
else
Perl_croak(aTHX_ "target is not of type Mob");
if (items < 7)
sticktarg = false;
else {
@@ -2933,6 +2933,32 @@ XS(XS_Mob_GetCorruption)
XSRETURN(1);
}
XS(XS_Mob_GetPhR); /* prototype to pass -Wmissing-prototypes */
XS(XS_Mob_GetPhR)
{
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: Mob::GetPhR(THIS)");
{
Mob * THIS;
int32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "Mob")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(Mob *, tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type Mob");
if (THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetPhR();
XSprePUSH; PUSHi((IV)RETVAL);
}
XSRETURN(1);
}
XS(XS_Mob_GetMaxSTR); /* prototype to pass -Wmissing-prototypes */
XS(XS_Mob_GetMaxSTR)
{
@@ -3525,7 +3551,7 @@ XS(XS_Mob_GetWaypointX)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetCWPX();
RETVAL = THIS->GetCurrentWayPoint().x;
XSprePUSH; PUSHn((double)RETVAL);
}
XSRETURN(1);
@@ -3551,7 +3577,7 @@ XS(XS_Mob_GetWaypointY)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetCWPY();
RETVAL = THIS->GetCurrentWayPoint().y;
XSprePUSH; PUSHn((double)RETVAL);
}
XSRETURN(1);
@@ -3577,7 +3603,7 @@ XS(XS_Mob_GetWaypointZ)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetCWPZ();
RETVAL = THIS->GetCurrentWayPoint().z;
XSprePUSH; PUSHn((double)RETVAL);
}
XSRETURN(1);
@@ -3603,7 +3629,7 @@ XS(XS_Mob_GetWaypointH)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetCWPH();
RETVAL = THIS->GetCurrentWayPoint().w;
XSprePUSH; PUSHn((double)RETVAL);
}
XSRETURN(1);
@@ -7636,10 +7662,7 @@ XS(XS_Mob_SetDeltas)
Perl_croak(aTHX_ "Usage: Mob::SetDeltas(THIS, delta_x, delta_y, delta_z, delta_h)");
{
Mob * THIS;
float delta_x = (float)SvNV(ST(1));
float delta_y = (float)SvNV(ST(2));
float delta_z = (float)SvNV(ST(3));
float delta_h = (float)SvNV(ST(4));
auto delta = glm::vec4((float)SvNV(ST(1)), (float)SvNV(ST(2)), (float)SvNV(ST(3)), (float)SvNV(ST(4)));
if (sv_derived_from(ST(0), "Mob")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
@@ -7650,7 +7673,7 @@ XS(XS_Mob_SetDeltas)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
THIS->SetDeltas(delta_x, delta_y, delta_z, delta_h);
THIS->SetDelta(delta);
}
XSRETURN_EMPTY;
}
@@ -8462,7 +8485,8 @@ XS(boot_Mob)
newXSproto(strcpy(buf, "GetDR"), XS_Mob_GetDR, file, "$");
newXSproto(strcpy(buf, "GetPR"), XS_Mob_GetPR, file, "$");
newXSproto(strcpy(buf, "GetCR"), XS_Mob_GetCR, file, "$");
newXSproto(strcpy(buf, "GetCorruption"), XS_Mob_GetCR, file, "$");
newXSproto(strcpy(buf, "GetCorruption"), XS_Mob_GetCorruption, file, "$");
newXSproto(strcpy(buf, "GetPhR"), XS_Mob_GetPhR, file, "$");
newXSproto(strcpy(buf, "GetMaxSTR"), XS_Mob_GetMaxSTR, file, "$");
newXSproto(strcpy(buf, "GetMaxSTA"), XS_Mob_GetMaxSTA, file, "$");
newXSproto(strcpy(buf, "GetMaxDEX"), XS_Mob_GetMaxDEX, file, "$");
+10 -9
View File
@@ -27,7 +27,7 @@
#include "../common/features.h"
#ifdef EMBPERL_XS_CLASSES
#include "../common/debug.h"
#include "../common/global_define.h"
#include "embperl.h"
#ifdef seed
@@ -1345,7 +1345,8 @@ XS(XS_NPC_MoveTo)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
THIS->MoveTo(mtx, mty, mtz, mth, saveguard);
auto position = glm::vec4(mtx, mty, mtz, mth);
THIS->MoveTo(position, saveguard);
}
XSRETURN_EMPTY;
}
@@ -1545,7 +1546,7 @@ XS(XS_NPC_GetSpawnPointX)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetSpawnPointX();
RETVAL = THIS->GetSpawnPoint().x;
XSprePUSH; PUSHn((double)RETVAL);
}
XSRETURN(1);
@@ -1572,7 +1573,7 @@ XS(XS_NPC_GetSpawnPointY)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetSpawnPointY();
RETVAL = THIS->GetSpawnPoint().y;
XSprePUSH; PUSHn((double)RETVAL);
}
XSRETURN(1);
@@ -1599,7 +1600,7 @@ XS(XS_NPC_GetSpawnPointZ)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetSpawnPointZ();
RETVAL = THIS->GetSpawnPoint().z;
XSprePUSH; PUSHn((double)RETVAL);
}
XSRETURN(1);
@@ -1626,7 +1627,7 @@ XS(XS_NPC_GetSpawnPointH)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetSpawnPointH();
RETVAL = THIS->GetSpawnPoint().w;
XSprePUSH; PUSHn((double)RETVAL);
}
XSRETURN(1);
@@ -1653,7 +1654,7 @@ XS(XS_NPC_GetGuardPointX)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetGuardPointX();
RETVAL = THIS->GetGuardPoint().x;
XSprePUSH; PUSHn((double)RETVAL);
}
XSRETURN(1);
@@ -1680,7 +1681,7 @@ XS(XS_NPC_GetGuardPointY)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetGuardPointY();
RETVAL = THIS->GetGuardPoint().y;
XSprePUSH; PUSHn((double)RETVAL);
}
XSRETURN(1);
@@ -1707,7 +1708,7 @@ XS(XS_NPC_GetGuardPointZ)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetGuardPointZ();
RETVAL = THIS->GetGuardPoint().z;
XSprePUSH; PUSHn((double)RETVAL);
}
XSRETURN(1);
+1 -1
View File
@@ -27,7 +27,7 @@
#include "../common/features.h"
#ifdef EMBPERL_XS_CLASSES
#include "../common/debug.h"
#include "../common/global_define.h"
#include "embperl.h"
#ifdef seed
+2 -1
View File
@@ -27,7 +27,8 @@
#include "../common/features.h"
#ifdef EMBPERL_XS_CLASSES
#include "../common/debug.h"
#include "../common/global_define.h"
#include "../common/types.h"
#include "embperl.h"
#ifdef seed
+1 -1
View File
@@ -27,7 +27,7 @@
#include "../common/features.h"
#ifdef EMBPERL_XS_CLASSES
#include "../common/debug.h"
#include "../common/global_define.h"
#include "embperl.h"
#ifdef seed
+1 -1
View File
@@ -19,7 +19,7 @@
#include "../common/features.h"
#include "client.h"
#ifdef EMBPERL_XS_CLASSES
#include "../common/debug.h"
#include "../common/global_define.h"
#include "embperl.h"
#ifdef seed
+1 -1
View File
@@ -27,7 +27,7 @@
#include "../common/features.h"
#ifdef EMBPERL_XS_CLASSES
#include "../common/debug.h"
#include "../common/global_define.h"
#include "embperl.h"
#ifdef seed
+1 -1
View File
@@ -15,7 +15,7 @@
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/debug.h"
#include "../common/global_define.h"
#include <stdlib.h>
#include "perlpacket.h"
#include "client.h"
+1
View File
@@ -21,6 +21,7 @@
#include <string>
#include <vector>
#include "../common/types.h"
#include "../common/emu_opcodes.h"
class Client;
+3 -10
View File
@@ -15,7 +15,8 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
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/debug.h"
#include "../common/global_define.h"
#include "../common/eqemu_logsys.h"
#include <string.h>
#ifdef _WINDOWS
#include <process.h>
@@ -211,9 +212,6 @@ void ZoneDatabase::DeletePetitionFromDB(Petition* wpet) {
std::string query = StringFormat("DELETE FROM petitions WHERE petid = %i", wpet->GetID());
auto results = QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Error in DeletePetitionFromDB query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
}
void ZoneDatabase::UpdatePetitionToDB(Petition* wpet) {
@@ -225,9 +223,6 @@ void ZoneDatabase::UpdatePetitionToDB(Petition* wpet) {
wpet->GetCheckouts(), wpet->GetUnavails(),
wpet->CheckedOut() ? 1: 0, wpet->GetID());
auto results = QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Error in UpdatePetitionToDB query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
}
void ZoneDatabase::InsertPetitionToDB(Petition* wpet)
@@ -253,12 +248,11 @@ void ZoneDatabase::InsertPetitionToDB(Petition* wpet)
safe_delete_array(petitiontext);
auto results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in InsertPetitionToDB query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
return;
}
#if EQDEBUG >= 5
LogFile->write(EQEMuLog::Debug, "New petition created");
Log.Out(Logs::General, Logs::None, "New petition created");
#endif
}
@@ -272,7 +266,6 @@ void ZoneDatabase::RefreshPetitionsFromDB()
"FROM petitions ORDER BY petid";
auto results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in RefreshPetitionsFromDB query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
return;
}
+68 -68
View File
@@ -16,7 +16,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "../common/global_define.h"
#include "../common/spdat.h"
#include "../common/string_util.h"
#include "../common/types.h"
@@ -243,7 +243,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
PetRecord record;
if(!database.GetPoweredPetEntry(pettype, act_power, &record)) {
Message(13, "Unable to find data for pet %s", pettype);
LogFile->write(EQEMuLog::Error, "Unable to find data for pet %s, check pets table.", pettype);
Log.Out(Logs::General, Logs::Error, "Unable to find data for pet %s, check pets table.", pettype);
return;
}
@@ -251,7 +251,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
const NPCType *base = database.GetNPCType(record.npc_type);
if(base == nullptr) {
Message(13, "Unable to load NPC data for pet %s", pettype);
LogFile->write(EQEMuLog::Error, "Unable to load NPC data for pet %s (NPC ID %d), check pets and npc_types tables.", pettype, record.npc_type);
Log.Out(Logs::General, Logs::Error, "Unable to load NPC data for pet %s (NPC ID %d), check pets and npc_types tables.", pettype, record.npc_type);
return;
}
@@ -361,28 +361,27 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
// get a random npc id from the spawngroups assigned to this zone
auto query = StringFormat("SELECT npcID "
"FROM (spawnentry INNER JOIN spawn2 ON spawn2.spawngroupID = spawnentry.spawngroupID) "
"INNER JOIN npc_types ON npc_types.id = spawnentry.npcID "
"WHERE spawn2.zone = '%s' AND npc_types.bodytype NOT IN (11, 33, 66, 67) "
"AND npc_types.race NOT IN (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 44, "
"55, 67, 71, 72, 73, 77, 78, 81, 90, 92, 93, 94, 106, 112, 114, 127, 128, "
"130, 139, 141, 183, 236, 237, 238, 239, 254, 266, 329, 330, 378, 379, "
"380, 381, 382, 383, 404, 522) "
"ORDER BY RAND() LIMIT 1", zone->GetShortName());
auto results = database.QueryDatabase(query);
"FROM (spawnentry INNER JOIN spawn2 ON spawn2.spawngroupID = spawnentry.spawngroupID) "
"INNER JOIN npc_types ON npc_types.id = spawnentry.npcID "
"WHERE spawn2.zone = '%s' AND npc_types.bodytype NOT IN (11, 33, 66, 67) "
"AND npc_types.race NOT IN (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 44, "
"55, 67, 71, 72, 73, 77, 78, 81, 90, 92, 93, 94, 106, 112, 114, 127, 128, "
"130, 139, 141, 183, 236, 237, 238, 239, 254, 266, 329, 330, 378, 379, "
"380, 381, 382, 383, 404, 522) "
"ORDER BY RAND() LIMIT 1", zone->GetShortName());
auto results = database.QueryDatabase(query);
if (!results.Success()) {
// if the database query failed
LogFile->write(EQEMuLog::Error, "Error querying database for monster summoning pet in zone %s (%s)", zone->GetShortName(), results.ErrorMessage().c_str());
return;
}
if (results.RowCount() != 0) {
auto row = results.begin();
monsterid = atoi(row[0]);
}
if (results.RowCount() != 0) {
auto row = results.begin();
monsterid = atoi(row[0]);
}
// since we don't have any monsters, just make it look like an earth pet for now
if (monsterid == 0)
monsterid = 567;
// since we don't have any monsters, just make it look like an earth pet for now
if (monsterid == 0)
monsterid = 567;
// give the summoned pet the attributes of the monster we found
const NPCType* monster = database.GetNPCType(monsterid);
@@ -395,7 +394,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
npc_type->helmtexture = monster->helmtexture;
npc_type->herosforgemodel = monster->herosforgemodel;
} else
LogFile->write(EQEMuLog::Error, "Error loading NPC data for monster summoning pet (NPC ID %d)", monsterid);
Log.Out(Logs::General, Logs::Error, "Error loading NPC data for monster summoning pet (NPC ID %d)", monsterid);
}
@@ -418,6 +417,8 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
}
}
npc->UpdateEquipLightValue();
// finally, override size if one was provided
if (in_size > 0.0f)
npc->size = in_size;
@@ -430,7 +431,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
into walls or objects (+10), this sometimes creates the "ghost" effect. I changed to +2 (as close as I
could get while it still looked good). I also noticed this can happen if an NPC is spawned on the same spot of another or in a related bad spot.*/
Pet::Pet(NPCType *type_data, Mob *owner, PetType type, uint16 spell_id, int16 power)
: NPC(type_data, 0, owner->GetX()+2, owner->GetY()+2, owner->GetZ(), owner->GetHeading(), FlyMode3)
: NPC(type_data, 0, owner->GetPosition() + glm::vec4(2.0f, 2.0f, 0.0f, 0.0f), FlyMode3)
{
GiveNPCTypeData(type_data);
typeofpet = type;
@@ -438,6 +439,8 @@ Pet::Pet(NPCType *type_data, Mob *owner, PetType type, uint16 spell_id, int16 po
SetOwnerID(owner->GetID());
SetPetSpellID(spell_id);
taunting = true;
// Class should use npc constructor to set light properties
}
bool ZoneDatabase::GetPetEntry(const char *pet_type, PetRecord *into) {
@@ -449,31 +452,31 @@ bool ZoneDatabase::GetPoweredPetEntry(const char *pet_type, int16 petpower, PetR
if (petpower <= 0)
query = StringFormat("SELECT npcID, temp, petpower, petcontrol, petnaming, monsterflag, equipmentset "
"FROM pets WHERE type='%s' AND petpower<=0", pet_type);
"FROM pets WHERE type='%s' AND petpower<=0", pet_type);
else
query = StringFormat("SELECT npcID, temp, petpower, petcontrol, petnaming, monsterflag, equipmentset "
"FROM pets WHERE type='%s' AND petpower<=%d ORDER BY petpower DESC LIMIT 1",
pet_type, petpower);
auto results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in GetPoweredPetEntry query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
return false;
}
"FROM pets WHERE type='%s' AND petpower<=%d ORDER BY petpower DESC LIMIT 1",
pet_type, petpower);
if (results.RowCount() != 1)
return false;
auto results = QueryDatabase(query);
if (!results.Success()) {
return false;
}
auto row = results.begin();
if (results.RowCount() != 1)
return false;
into->npc_type = atoi(row[0]);
into->temporary = atoi(row[1]);
into->petpower = atoi(row[2]);
into->petcontrol = atoi(row[3]);
into->petnaming = atoi(row[4]);
into->monsterflag = atoi(row[5]);
into->equipmentset = atoi(row[6]);
auto row = results.begin();
return true;
into->npc_type = atoi(row[0]);
into->temporary = atoi(row[1]);
into->petpower = atoi(row[2]);
into->petcontrol = atoi(row[3]);
into->petnaming = atoi(row[4]);
into->monsterflag = atoi(row[5]);
into->equipmentset = atoi(row[6]);
return true;
}
Mob* Mob::GetPet() {
@@ -653,41 +656,38 @@ bool ZoneDatabase::GetBasePetItems(int32 equipmentset, uint32 *items) {
// all of the result rows. Check if we have something in the slot
// already. If no, add the item id to the equipment array.
while (curset >= 0 && depth < 5) {
std::string query = StringFormat("SELECT nested_set FROM pets_equipmentset WHERE set_id = '%s'", curset);
std::string query = StringFormat("SELECT nested_set FROM pets_equipmentset WHERE set_id = '%s'", curset);
auto results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in GetBasePetItems query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
return false;
}
}
if (results.RowCount() != 1) {
// invalid set reference, it doesn't exist
LogFile->write(EQEMuLog::Error, "Error in GetBasePetItems equipment set '%d' does not exist", curset);
return false;
}
if (results.RowCount() != 1) {
// invalid set reference, it doesn't exist
Log.Out(Logs::General, Logs::Error, "Error in GetBasePetItems equipment set '%d' does not exist", curset);
return false;
}
auto row = results.begin();
nextset = atoi(row[0]);
auto row = results.begin();
nextset = atoi(row[0]);
query = StringFormat("SELECT slot, item_id FROM pets_equipmentset_entries WHERE set_id='%s'", curset);
results = QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Error in GetBasePetItems query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
else {
for (row = results.begin(); row != results.end(); ++row)
{
slot = atoi(row[0]);
query = StringFormat("SELECT slot, item_id FROM pets_equipmentset_entries WHERE set_id='%s'", curset);
results = QueryDatabase(query);
if (results.Success()) {
for (row = results.begin(); row != results.end(); ++row)
{
slot = atoi(row[0]);
if (slot >= EmuConstants::EQUIPMENT_SIZE)
continue;
if (slot >= EmuConstants::EQUIPMENT_SIZE)
continue;
if (items[slot] == 0)
items[slot] = atoi(row[1]);
}
}
if (items[slot] == 0)
items[slot] = atoi(row[1]);
}
}
curset = nextset;
depth++;
curset = nextset;
depth++;
}
return true;
+31 -20
View File
@@ -1,26 +1,37 @@
#ifndef PETS_H
#define PETS_H
#define PET_BACKOFF 1
#define PET_GETLOST 2
#define PET_HEALTHREPORT 4
#define PET_GUARDHERE 5
#define PET_GUARDME 6
#define PET_ATTACK 7
#define PET_FOLLOWME 8
#define PET_SITDOWN 9
#define PET_STANDUP 10
#define PET_TAUNT 11
#define PET_HOLD 12
#define PET_NOTAUNT 14
#define PET_LEADER 16
#define PET_SLUMBER 17
#define PET_NOCAST 18
#define PET_FOCUS 19
#define PET_FOCUS_ON 25
#define PET_FOCUS_OFF 26
#define PET_HOLD_ON 27
#define PET_HOLD_OFF 28
// Defines based on the RoF2 Client
#define PET_HEALTHREPORT 0 // 0x00 - /pet health or Pet Window
#define PET_LEADER 1 // 0x01 - /pet leader or Pet Window
#define PET_ATTACK 2 // 0x02 - /pet attack or Pet Window
#define PET_QATTACK 3 // 0x03 - /pet qattack or Pet Window
#define PET_FOLLOWME 4 // 0x04 - /pet follow or Pet Window
#define PET_GUARDHERE 5 // 0x05 - /pet guard or Pet Window
#define PET_SIT 6 // 0x06 - /pet sit or Pet Window
#define PET_SITDOWN 7 // 0x07 - /pet sit on
#define PET_STANDUP 8 // 0x08 - /pet sit off
#define PET_STOP 9 // 0x09 - /pet stop or Pet Window - Not implemented
#define PET_STOP_ON 10 // 0x0a - /pet stop on - Not implemented
#define PET_STOP_OFF 11 // 0x0b - /pet stop off - Not implemented
#define PET_TAUNT 12 // 0x0c - /pet taunt or Pet Window
#define PET_TAUNT_ON 13 // 0x0d - /pet taunt on
#define PET_TAUNT_OFF 14 // 0x0e - /pet taunt off
#define PET_HOLD 15 // 0x0f - /pet hold or Pet Window
#define PET_HOLD_ON 16 // 0x10 - /pet hold on
#define PET_HOLD_OFF 17 // 0x11 - /pet hold off
#define PET_SLUMBER 18 // 0x12 - What activates this? - define guessed
#define PET_SLUMBER_ON 19 // 0x13 - What activates this? - define guessed
#define PET_SLUMBER_OFF 20 // 0x14 - What activates this? - define guessed
#define PET_SPELLHOLD 21 // 0x15 - /pet no cast or /pet spellhold or Pet Window
#define PET_SPELLHOLD_ON 22 // 0x16 - /pet spellhold on
#define PET_SPELLHOLD_OFF 23 // 0x17 - /pet spellhold off
#define PET_FOCUS 24 // 0x18 - /pet focus or Pet Window
#define PET_FOCUS_ON 25 // 0x19 - /pet focus on
#define PET_FOCUS_OFF 26 // 0x1a - /pet focus off
#define PET_BACKOFF 28 // 0x1c - /pet back off
#define PET_GETLOST 29 // 0x1d - /pet get lost
#define PET_GUARDME 30 // 0x1e - Same as /pet follow, but different message in older clients - define not from client
class Mob;
struct NPCType;
+162
View File
@@ -0,0 +1,162 @@
#include "position.h"
#include <algorithm>
#include <string>
#include <cmath>
#include "../common/string_util.h"
std::string to_string(const glm::vec4 &position) {
return StringFormat("(%.3f, %.3f, %.3f, %.3f)", position.x,position.y,position.z,position.w);
}
std::string to_string(const glm::vec3 &position){
return StringFormat("(%.3f, %.3f, %.3f)", position.x,position.y,position.z);
}
std::string to_string(const glm::vec2 &position){
return StringFormat("(%.3f, %.3f)", position.x,position.y);
}
bool IsOrigin(const glm::vec2 &position) {
return glm::dot(position, position) == 0;
}
bool IsOrigin(const glm::vec3 &position) {
return glm::dot(position, position) == 0;
}
bool IsOrigin(const glm::vec4 &position) {
return IsOrigin(glm::vec3(position));
}
/**
* Produces the non square root'ed distance between the two points within the XY plane.
*/
float DistanceSquared(const glm::vec2& point1, const glm::vec2& point2) {
auto diff = point1 - point2;
return glm::dot(diff, diff);
}
/**
* Produces the distance between the two points on the XY plane.
*/
float Distance(const glm::vec2& point1, const glm::vec2& point2) {
return std::sqrt(DistanceSquared(point1, point2));
}
/**
* Produces the non square root'ed distance between the two points.
*/
float DistanceSquared(const glm::vec3& point1, const glm::vec3& point2) {
auto diff = point1 - point2;
return glm::dot(diff, diff);
}
/**
* Produces the non square root'ed distance between the two points.
*/
float DistanceSquared(const glm::vec4& point1, const glm::vec4& point2) {
return DistanceSquared(static_cast<glm::vec3>(point1), static_cast<glm::vec3>(point2));
}
/**
* Produces the distance between the two points.
*/
float Distance(const glm::vec3& point1, const glm::vec3& point2) {
return std::sqrt(DistanceSquared(point1, point2));
}
/**
* Produces the distance between the two points.
*/
float Distance(const glm::vec4& point1, const glm::vec4& point2) {
return Distance(static_cast<glm::vec3>(point1), static_cast<glm::vec3>(point2));
}
/**
* Produces the distance between the two points within the XY plane.
*/
float DistanceNoZ(const glm::vec3& point1, const glm::vec3& point2) {
return Distance(static_cast<glm::vec2>(point1),static_cast<glm::vec2>(point2));
}
/**
* Produces the distance between the two points within the XY plane.
*/
float DistanceNoZ(const glm::vec4& point1, const glm::vec4& point2) {
return Distance(static_cast<glm::vec2>(point1),static_cast<glm::vec2>(point2));
}
/**
* Produces the non square root'ed distance between the two points within the XY plane.
*/
float DistanceSquaredNoZ(const glm::vec3& point1, const glm::vec3& point2) {
return DistanceSquared(static_cast<glm::vec2>(point1),static_cast<glm::vec2>(point2));
}
/**
* Produces the non square root'ed distance between the two points within the XY plane.
*/
float DistanceSquaredNoZ(const glm::vec4& point1, const glm::vec4& point2) {
return DistanceSquared(static_cast<glm::vec2>(point1),static_cast<glm::vec2>(point2));
}
/**
* Determines if 'position' is within (inclusive) the axis aligned
* box (3 dimensional) formed from the points minimum and maximum.
*/
bool IsWithinAxisAlignedBox(const glm::vec3 &position, const glm::vec3 &minimum, const glm::vec3 &maximum) {
auto actualMinimum = glm::vec3(std::min(minimum.x, maximum.x), std::min(minimum.y, maximum.y),std::min(minimum.z, maximum.z));
auto actualMaximum = glm::vec3(std::max(minimum.x, maximum.x), std::max(minimum.y, maximum.y),std::max(minimum.z, maximum.z));
bool xcheck = position.x >= actualMinimum.x && position.x <= actualMaximum.x;
bool ycheck = position.y >= actualMinimum.y && position.y <= actualMaximum.y;
bool zcheck = position.z >= actualMinimum.z && position.z <= actualMaximum.z;
return xcheck && ycheck && zcheck;
}
/**
* Determines if 'position' is within (inclusive) the axis aligned
* box (2 dimensional) formed from the points minimum and maximum.
*/
bool IsWithinAxisAlignedBox(const glm::vec2 &position, const glm::vec2 &minimum, const glm::vec2 &maximum) {
auto actualMinimum = glm::vec2(std::min(minimum.x, maximum.x), std::min(minimum.y, maximum.y));
auto actualMaximum = glm::vec2(std::max(minimum.x, maximum.x), std::max(minimum.y, maximum.y));
bool xcheck = position.x >= actualMinimum.x && position.x <= actualMaximum.x;
bool ycheck = position.y >= actualMinimum.y && position.y <= actualMaximum.y;
return xcheck && ycheck;
}
/**
* Gives the heading directly 180 degrees from the
* current heading.
* Takes the EQfloat from the glm::vec4 and returns
* an EQFloat.
*/
float GetReciprocalHeading(const glm::vec4& point1) {
return GetReciprocalHeading(point1.w);
}
/**
* Gives the heading directly 180 degrees from the
* current heading.
* Takes an EQfloat and returns an EQFloat.
*/
float GetReciprocalHeading(const float heading)
{
float result = 0;
// Convert to radians
float h = (heading / 256.0f) * 6.283184f;
// Calculate the reciprocal heading in radians
result = h + 3.141592f;
// Convert back to eq heading from radians
result = (result / 6.283184f) * 256.0f;
return result;
}
+53
View File
@@ -0,0 +1,53 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
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 POSITION_H
#define POSITION_H
#include <string>
#include <glm/vec2.hpp>
#include <glm/vec3.hpp>
#include <glm/vec4.hpp>
#include <glm/geometric.hpp>
std::string to_string(const glm::vec4 &position);
std::string to_string(const glm::vec3 &position);
std::string to_string(const glm::vec2 &position);
bool IsWithinAxisAlignedBox(const glm::vec3 &position, const glm::vec3 &minimum, const glm::vec3 &maximum);
bool IsWithinAxisAlignedBox(const glm::vec2 &position, const glm::vec2 &minimum, const glm::vec2 &maximum);
bool IsOrigin(const glm::vec2 &position);
bool IsOrigin(const glm::vec3 &position);
bool IsOrigin(const glm::vec4 &position);
float DistanceSquared(const glm::vec2& point1, const glm::vec2& point2);
float Distance(const glm::vec2& point1, const glm::vec2& point2);
float DistanceSquared(const glm::vec3& point1, const glm::vec3& point2);
float Distance(const glm::vec3& point1, const glm::vec3& point2);
float DistanceNoZ(const glm::vec3& point1, const glm::vec3& point2);
float DistanceSquaredNoZ(const glm::vec3& point1, const glm::vec3& point2);
float DistanceSquared(const glm::vec4& point1, const glm::vec4& point2);
float Distance(const glm::vec4& point1, const glm::vec4& point2);
float DistanceNoZ(const glm::vec4& point1, const glm::vec4& point2);
float DistanceSquaredNoZ(const glm::vec4& point1, const glm::vec4& point2);
float GetReciprocalHeading(const glm::vec4& point1);
float GetReciprocalHeading(const float heading);
#endif
+1 -1
View File
@@ -16,7 +16,7 @@ Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net)
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "../common/global_define.h"
#include "../common/servertalk.h"
#include "../common/string_util.h"
#include "queryserv.h"
+5 -5
View File
@@ -16,7 +16,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "../common/global_define.h"
#include "../common/misc_functions.h"
#include "../common/features.h"
@@ -206,11 +206,11 @@ bool QuestParserCollection::ItemHasQuestSub(ItemInst *itm, QuestEventID evt) {
std::string item_script;
if(itm->GetItem()->ScriptFileID != 0) {
item_script = "script_";
item_script += std::to_string(static_cast<long long>(itm->GetItem()->ScriptFileID));
item_script += std::to_string(itm->GetItem()->ScriptFileID);
} else if(strlen(itm->GetItem()->CharmFile) > 0) {
item_script = itm->GetItem()->CharmFile;
} else {
item_script = std::to_string(static_cast<long long>(itm->GetID()));
item_script = std::to_string(itm->GetID());
}
uint32 item_id = itm->GetID();
@@ -358,11 +358,11 @@ int QuestParserCollection::EventItem(QuestEventID evt, Client *client, ItemInst
std::string item_script;
if(item->GetItem()->ScriptFileID != 0) {
item_script = "script_";
item_script += std::to_string(static_cast<long long>(item->GetItem()->ScriptFileID));
item_script += std::to_string(item->GetItem()->ScriptFileID);
} else if(strlen(item->GetItem()->CharmFile) > 0) {
item_script = item->GetItem()->CharmFile;
} else {
item_script = std::to_string(static_cast<long long>(item->GetID()));
item_script = std::to_string(item->GetID());
}
uint32 item_id = item->GetID();
+60 -70
View File
@@ -17,7 +17,7 @@
*/
#include "../common/classes.h"
#include "../common/debug.h"
#include "../common/global_define.h"
#include "../common/rulesys.h"
#include "../common/skills.h"
#include "../common/spdat.h"
@@ -154,7 +154,7 @@ void QuestManager::echo(int colour, const char *str) {
void QuestManager::say(const char *str) {
QuestManagerCurrentQuestVars();
if (!owner) {
LogFile->write(EQEMuLog::Quest, "QuestManager::say called with nullptr owner. Probably syntax error in quest file.");
Log.Out(Logs::General, Logs::Quests, "QuestManager::say called with nullptr owner. Probably syntax error in quest file.");
return;
}
else {
@@ -170,7 +170,7 @@ void QuestManager::say(const char *str) {
void QuestManager::say(const char *str, uint8 language) {
QuestManagerCurrentQuestVars();
if (!owner) {
LogFile->write(EQEMuLog::Quest, "QuestManager::say called with nullptr owner. Probably syntax error in quest file.");
Log.Out(Logs::General, Logs::Quests, "QuestManager::say called with nullptr owner. Probably syntax error in quest file.");
return;
}
else {
@@ -201,11 +201,11 @@ void QuestManager::write(const char *file, const char *str) {
fclose (pFile);
}
Mob* QuestManager::spawn2(int npc_type, int grid, int unused, float x, float y, float z, float heading) {
Mob* QuestManager::spawn2(int npc_type, int grid, int unused, const glm::vec4& position) {
const NPCType* tmp = 0;
if (tmp = database.GetNPCType(npc_type))
{
NPC* npc = new NPC(tmp, 0, x, y, z, heading, FlyMode3);
NPC* npc = new NPC(tmp, nullptr, position, FlyMode3);
npc->AddLootTable();
entity_list.AddNPC(npc,true,true);
if(grid > 0)
@@ -218,7 +218,7 @@ Mob* QuestManager::spawn2(int npc_type, int grid, int unused, float x, float y,
return nullptr;
}
Mob* QuestManager::unique_spawn(int npc_type, int grid, int unused, float x, float y, float z, float heading) {
Mob* QuestManager::unique_spawn(int npc_type, int grid, int unused, const glm::vec4& position) {
Mob *other = entity_list.GetMobByNpcTypeID(npc_type);
if(other != nullptr) {
return other;
@@ -227,7 +227,7 @@ Mob* QuestManager::unique_spawn(int npc_type, int grid, int unused, float x, flo
const NPCType* tmp = 0;
if (tmp = database.GetNPCType(npc_type))
{
NPC* npc = new NPC(tmp, 0, x, y, z, heading, FlyMode3);
NPC* npc = new NPC(tmp, nullptr, position, FlyMode3);
npc->AddLootTable();
entity_list.AddNPC(npc,true,true);
if(grid > 0)
@@ -300,8 +300,8 @@ Mob* QuestManager::spawn_from_spawn2(uint32 spawn2_id)
database.UpdateSpawn2Timeleft(spawn2_id, zone->GetInstanceID(), 0);
found_spawn->SetCurrentNPCID(npcid);
NPC* npc = new NPC(tmp, found_spawn, found_spawn->GetX(), found_spawn->GetY(), found_spawn->GetZ(),
found_spawn->GetHeading(), FlyMode3);
auto position = glm::vec4(found_spawn->GetX(), found_spawn->GetY(), found_spawn->GetZ(), found_spawn->GetHeading());
NPC* npc = new NPC(tmp, found_spawn, position, FlyMode3);
found_spawn->SetNPCPointer(npc);
npc->AddLootTable();
@@ -548,7 +548,7 @@ void QuestManager::stopalltimers(Mob *mob) {
void QuestManager::emote(const char *str) {
QuestManagerCurrentQuestVars();
if (!owner) {
LogFile->write(EQEMuLog::Quest, "QuestManager::emote called with nullptr owner. Probably syntax error in quest file.");
Log.Out(Logs::General, Logs::Quests, "QuestManager::emote called with nullptr owner. Probably syntax error in quest file.");
return;
}
else {
@@ -559,7 +559,7 @@ void QuestManager::emote(const char *str) {
void QuestManager::shout(const char *str) {
QuestManagerCurrentQuestVars();
if (!owner) {
LogFile->write(EQEMuLog::Quest, "QuestManager::shout called with nullptr owner. Probably syntax error in quest file.");
Log.Out(Logs::General, Logs::Quests, "QuestManager::shout called with nullptr owner. Probably syntax error in quest file.");
return;
}
else {
@@ -570,7 +570,7 @@ void QuestManager::shout(const char *str) {
void QuestManager::shout2(const char *str) {
QuestManagerCurrentQuestVars();
if (!owner) {
LogFile->write(EQEMuLog::Quest, "QuestManager::shout2 called with nullptr owner. Probably syntax error in quest file.");
Log.Out(Logs::General, Logs::Quests, "QuestManager::shout2 called with nullptr owner. Probably syntax error in quest file.");
return;
}
else {
@@ -589,7 +589,7 @@ void QuestManager::gmsay(const char *str, uint32 color, bool send_to_world, uint
void QuestManager::depop(int npc_type) {
QuestManagerCurrentQuestVars();
if (!owner || !owner->IsNPC()) {
LogFile->write(EQEMuLog::Quest, "QuestManager::depop called with nullptr owner or non-NPC owner. Probably syntax error in quest file.");
Log.Out(Logs::General, Logs::Quests, "QuestManager::depop called with nullptr owner or non-NPC owner. Probably syntax error in quest file.");
return;
}
else {
@@ -619,7 +619,7 @@ void QuestManager::depop(int npc_type) {
void QuestManager::depop_withtimer(int npc_type) {
QuestManagerCurrentQuestVars();
if (!owner || !owner->IsNPC()) {
LogFile->write(EQEMuLog::Quest, "QuestManager::depop_withtimer called with nullptr owner or non-NPC owner. Probably syntax error in quest file.");
Log.Out(Logs::General, Logs::Quests, "QuestManager::depop_withtimer called with nullptr owner or non-NPC owner. Probably syntax error in quest file.");
return;
}
else {
@@ -646,7 +646,7 @@ void QuestManager::depopall(int npc_type) {
entity_list.DepopAll(npc_type);
}
else {
LogFile->write(EQEMuLog::Quest, "QuestManager::depopall called with nullptr owner, non-NPC owner, or invalid NPC Type ID. Probably syntax error in quest file.");
Log.Out(Logs::General, Logs::Quests, "QuestManager::depopall called with nullptr owner, non-NPC owner, or invalid NPC Type ID. Probably syntax error in quest file.");
}
}
@@ -655,7 +655,7 @@ void QuestManager::depopzone(bool StartSpawnTimer) {
zone->Depop(StartSpawnTimer);
}
else {
LogFile->write(EQEMuLog::Quest, "QuestManager::depopzone called with nullptr zone. Probably syntax error in quest file.");
Log.Out(Logs::General, Logs::Quests, "QuestManager::depopzone called with nullptr zone. Probably syntax error in quest file.");
}
}
@@ -664,7 +664,7 @@ void QuestManager::repopzone() {
zone->Repop();
}
else {
LogFile->write(EQEMuLog::Quest, "QuestManager::repopzone called with nullptr zone. Probably syntax error in quest file.");
Log.Out(Logs::General, Logs::Quests, "QuestManager::repopzone called with nullptr zone. Probably syntax error in quest file.");
}
}
@@ -923,7 +923,7 @@ uint16 QuestManager::traindiscs(uint8 max_level, uint8 min_level) {
spells[curspell].skill != 52 &&
( !RuleB(Spells, UseCHAScribeHack) || spells[curspell].effectid[EFFECT_COUNT - 1] != 10 )
)
{
{
if(IsDiscipline(curspell)){
//we may want to come up with a function like Client::GetNextAvailableSpellBookSlot() to help speed this up a little
for(uint32 r = 0; r < MAX_PP_DISCIPLINES; r++) {
@@ -937,12 +937,12 @@ uint16 QuestManager::traindiscs(uint8 max_level, uint8 min_level) {
SpellGlobalCheckResult = initiator->SpellGlobalCheck(curspell, Char_ID);
if (SpellGlobalCheckResult) {
initiator->GetPP().disciplines.values[r] = curspell;
database.SaveCharacterDisc(Char_ID, r, curspell);
database.SaveCharacterDisc(Char_ID, r, curspell);
initiator->SendDisciplineUpdate();
initiator->Message(0, "You have learned a new discipline!");
count++; //success counter
}
break; //continue the 1st loop
break; //continue the 1st loop
}
else {
initiator->GetPP().disciplines.values[r] = curspell;
@@ -1234,7 +1234,6 @@ void QuestManager::itemlink(int item_id) {
Client::TextLink linker;
linker.SetLinkType(linker.linkItemData);
linker.SetItemData(item);
linker.SetClientVersion(initiator->GetClientVersion());
auto item_link = linker.GenerateLink();
@@ -1487,10 +1486,10 @@ void QuestManager::ding() {
}
void QuestManager::rebind(int zoneid, float x, float y, float z) {
void QuestManager::rebind(int zoneid, const glm::vec3& location) {
QuestManagerCurrentQuestVars();
if(initiator && initiator->IsClient()) {
initiator->SetBindPoint(zoneid, x, y, z);
initiator->SetBindPoint(zoneid, 0, location);
}
}
@@ -1518,12 +1517,12 @@ void QuestManager::pause(int duration) {
owner->CastToNPC()->PauseWandering(duration);
}
void QuestManager::moveto(float x, float y, float z, float h, bool saveguardspot) {
void QuestManager::moveto(const glm::vec4& position, bool saveguardspot) {
QuestManagerCurrentQuestVars();
if (!owner || !owner->IsNPC())
return;
owner->CastToNPC()->MoveTo(x, y, z, h, saveguardspot);
owner->CastToNPC()->MoveTo(position, saveguardspot);
}
void QuestManager::resume() {
@@ -1564,26 +1563,20 @@ void QuestManager::setnextinchpevent(int at) {
owner->SetNextIncHPEvent(at);
}
void QuestManager::respawn(int npc_type, int grid) {
void QuestManager::respawn(int npcTypeID, int grid) {
QuestManagerCurrentQuestVars();
if (!owner || !owner->IsNPC())
return;
float x,y,z,h;
x = owner->GetX();
y = owner->GetY();
z = owner->GetZ();
h = owner->GetHeading();
running_quest e = quests_running_.top();
e.depop_npc = true;
quests_running_.pop();
quests_running_.push(e);
const NPCType* tmp = 0;
if ((tmp = database.GetNPCType(npc_type)))
const NPCType* npcType = nullptr;
if ((npcType = database.GetNPCType(npcTypeID)))
{
owner = new NPC(tmp, 0, x, y, z, h, FlyMode3);
owner = new NPC(npcType, nullptr, owner->GetPosition(), FlyMode3);
owner->CastToNPC()->AddLootTable();
entity_list.AddNPC(owner->CastToNPC(),true,true);
if(grid > 0)
@@ -1653,7 +1646,7 @@ void QuestManager::showgrid(int grid) {
"ORDER BY `number`", grid, zone->GetZoneID());
auto results = database.QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Quest, "Error loading grid %d for showgrid(): %s", grid, results.ErrorMessage().c_str());
Log.Out(Logs::General, Logs::Quests, "Error loading grid %d for showgrid(): %s", grid, results.ErrorMessage().c_str());
return;
}
@@ -1705,27 +1698,28 @@ void QuestManager::sethp(int hpperc) {
owner->Damage(owner, newhp, SPELL_UNKNOWN, SkillHandtoHand, false, 0, false);
}
bool QuestManager::summonburriedplayercorpse(uint32 char_id, float dest_x, float dest_y, float dest_z, float dest_heading) {
bool QuestManager::summonburriedplayercorpse(uint32 char_id, const glm::vec4& position) {
bool Result = false;
if(char_id > 0) {
Corpse* PlayerCorpse = database.SummonBuriedCharacterCorpses(char_id, zone->GetZoneID(), zone->GetInstanceID(), dest_x, dest_y, dest_z, dest_heading);
if(PlayerCorpse) {
Result = true;
}
}
return Result;
if(char_id <= 0)
return false;
Corpse* PlayerCorpse = database.SummonBuriedCharacterCorpses(char_id, zone->GetZoneID(), zone->GetInstanceID(), position);
if(!PlayerCorpse)
return false;
return true;
}
bool QuestManager::summonallplayercorpses(uint32 char_id, float dest_x, float dest_y, float dest_z, float dest_heading) {
bool Result = false;
bool QuestManager::summonallplayercorpses(uint32 char_id, const glm::vec4& position) {
if(char_id > 0) {
Client* c = entity_list.GetClientByCharID(char_id);
c->SummonAllCorpses(dest_x, dest_y, dest_z, dest_heading);
Result = true;
}
return Result;
if(char_id <= 0)
return false;
Client* c = entity_list.GetClientByCharID(char_id);
c->SummonAllCorpses(position);
return true;
}
uint32 QuestManager::getplayerburriedcorpsecount(uint32 char_id) {
@@ -2075,7 +2069,7 @@ bool QuestManager::istaskenabled(int taskid) {
void QuestManager::tasksetselector(int tasksetid) {
QuestManagerCurrentQuestVars();
_log(TASKS__UPDATE, "TaskSetSelector called for task set %i", tasksetid);
Log.Out(Logs::General, Logs::Tasks, "[UPDATE] TaskSetSelector called for task set %i", tasksetid);
if(RuleB(TaskSystem, EnableTaskSystem) && initiator && owner && taskmanager)
initiator->TaskSetSelector(owner, tasksetid);
}
@@ -2313,17 +2307,17 @@ int QuestManager::getlevel(uint8 type)
return 0;
}
uint16 QuestManager::CreateGroundObject(uint32 itemid, float x, float y, float z, float heading, uint32 decay_time)
uint16 QuestManager::CreateGroundObject(uint32 itemid, const glm::vec4& position, uint32 decay_time)
{
uint16 entid = 0; //safety check
entid = entity_list.CreateGroundObject(itemid, x, y, z, heading, decay_time);
entid = entity_list.CreateGroundObject(itemid, position, decay_time);
return entid;
}
uint16 QuestManager::CreateGroundObjectFromModel(const char *model, float x, float y, float z, float heading, uint8 type, uint32 decay_time)
uint16 QuestManager::CreateGroundObjectFromModel(const char *model, const glm::vec4& position, uint8 type, uint32 decay_time)
{
uint16 entid = 0; //safety check
entid = entity_list.CreateGroundObjectFromModel(model, x, y, z, heading, type, decay_time);
entid = entity_list.CreateGroundObjectFromModel(model, position, type, decay_time);
return entid;
}
@@ -2474,8 +2468,6 @@ const char* QuestManager::varlink(char* perltext, int item_id) {
Client::TextLink linker;
linker.SetLinkType(linker.linkItemData);
linker.SetItemData(item);
if (initiator)
linker.SetClientVersion(initiator->GetClientVersion());
auto item_link = linker.GenerateLink();
strcpy(perltext, item_link.c_str()); // link length is currently ranged from 1 to 250 in TextLink::GenerateLink()
@@ -2590,12 +2582,12 @@ void QuestManager::RemoveAllFromInstance(uint16 instance_id)
}
}
void QuestManager::MovePCInstance(int zone_id, int instance_id, float x, float y, float z, float heading)
void QuestManager::MovePCInstance(int zone_id, int instance_id, const glm::vec4& position)
{
QuestManagerCurrentQuestVars();
if(initiator)
{
initiator->MovePC(zone_id, instance_id, x, y, z, heading);
initiator->MovePC(zone_id, instance_id, position.x, position.y, position.z, position.w);
}
}
@@ -2644,7 +2636,7 @@ const char* QuestManager::saylink(char* Phrase, bool silent, const char* LinkNam
std::string insert_query = StringFormat("INSERT INTO `saylink` (`phrase`) VALUES ('%s')", escaped_string);
results = database.QueryDatabase(insert_query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in saylink phrase queries", results.ErrorMessage().c_str());
Log.Out(Logs::General, Logs::Error, "Error in saylink phrase queries", results.ErrorMessage().c_str());
} else {
results = database.QueryDatabase(query);
if (results.Success()) {
@@ -2652,7 +2644,7 @@ const char* QuestManager::saylink(char* Phrase, bool silent, const char* LinkNam
for(auto row = results.begin(); row != results.end(); ++row)
sayid = atoi(row[0]);
} else {
LogFile->write(EQEMuLog::Error, "Error in saylink phrase queries", results.ErrorMessage().c_str());
Log.Out(Logs::General, Logs::Error, "Error in saylink phrase queries", results.ErrorMessage().c_str());
}
}
}
@@ -2668,8 +2660,6 @@ const char* QuestManager::saylink(char* Phrase, bool silent, const char* LinkNam
Client::TextLink linker;
linker.SetProxyItemID(sayid);
linker.SetProxyText(LinkName);
if (initiator)
linker.SetClientVersion(initiator->GetClientVersion());
auto say_link = linker.GenerateLink();
strcpy(Phrase, say_link.c_str()); // link length is currently ranged from 1 to 250 in TextLink::GenerateLink()
@@ -2814,7 +2804,7 @@ void QuestManager::voicetell(const char *str, int macronum, int racenum, int gen
safe_delete(outapp);
}
else
LogFile->write(EQEMuLog::Quest, "QuestManager::voicetell from %s. Client %s not found.", owner->GetName(), str);
Log.Out(Logs::General, Logs::Quests, "QuestManager::voicetell from %s. Client %s not found.", owner->GetName(), str);
}
}
@@ -2846,7 +2836,7 @@ void QuestManager::SendMail(const char *to, const char *from, const char *subjec
uint16 QuestManager::CreateDoor(const char* model, float x, float y, float z, float heading, uint8 opentype, uint16 size)
{
uint16 entid = 0; //safety check
entid = entity_list.CreateDoor(model, x, y, z, heading, opentype, size);
entid = entity_list.CreateDoor(model, glm::vec4(x, y, z, heading), opentype, size);
return entid;
}
@@ -2889,7 +2879,7 @@ void QuestManager::CrossZoneSignalPlayerByName(const char *CharName, uint32 data
CZSC->data = data;
worldserver.SendPacket(pack);
safe_delete(pack);
}
}
void QuestManager::CrossZoneMessagePlayerByName(uint32 Type, const char *CharName, const char *Message){
uint32 message_len = strlen(CharName) + 1;
@@ -2899,7 +2889,7 @@ void QuestManager::CrossZoneMessagePlayerByName(uint32 Type, const char *CharNam
CZSC->Type = Type;
strn0cpy(CZSC->CharName, CharName, 64);
strn0cpy(CZSC->Message, Message, 512);
worldserver.SendPacket(pack);
worldserver.SendPacket(pack);
safe_delete(pack);
}
@@ -2909,7 +2899,7 @@ void QuestManager::CrossZoneSetEntityVariableByNPCTypeID(uint32 npctype_id, cons
ServerPacket* pack = new ServerPacket(ServerOP_CZSetEntityVariableByNPCTypeID, sizeof(CZSetEntVarByNPCTypeID_Struct) + message_len + message_len2);
CZSetEntVarByNPCTypeID_Struct* CZSNBYNID = (CZSetEntVarByNPCTypeID_Struct*)pack->pBuffer;
CZSNBYNID->npctype_id = npctype_id;
strn0cpy(CZSNBYNID->id, id, 256);
strn0cpy(CZSNBYNID->id, id, 256);
strn0cpy(CZSNBYNID->m_var, m_var, 256);
worldserver.SendPacket(pack);
safe_delete(pack);
+10 -10
View File
@@ -57,8 +57,8 @@ public:
void me(const char *str);
void summonitem(uint32 itemid, int16 charges = -1);
void write(const char *file, const char *str);
Mob* spawn2(int npc_type, int grid, int unused, float x, float y, float z, float heading);
Mob* unique_spawn(int npc_type, int grid, int unused, float x, float y, float z, float heading = 0);
Mob* spawn2(int npc_type, int grid, int unused, const glm::vec4& position);
Mob* unique_spawn(int npc_type, int grid, int unused, const glm::vec4& position);
Mob* spawn_from_spawn2(uint32 spawn2_id);
void enable_spawn2(uint32 spawn2_id);
void disable_spawn2(uint32 spawn2_id);
@@ -132,11 +132,11 @@ public:
void targlobal(const char *varname, const char *value, const char *duration, int npcid, int charid, int zoneid);
void delglobal(const char *varname);
void ding();
void rebind(int zoneid, float x, float y, float z);
void rebind(int zoneid, const glm::vec3& location);
void start(int wp);
void stop();
void pause(int duration);
void moveto(float x, float y, float z, float h, bool saveguardspot);
void moveto(const glm::vec4& position, bool saveguardspot);
void resume();
void addldonpoints(int32 points, uint32 theme);
void addldonwin(int32 wins, uint32 theme);
@@ -157,8 +157,8 @@ public:
void set_zone_flag(int zone_id);
void clear_zone_flag(int zone_id);
void sethp(int hpperc);
bool summonburriedplayercorpse(uint32 char_id, float dest_x, float dest_y, float dest_z, float dest_heading);
bool summonallplayercorpses(uint32 char_id, float dest_x, float dest_y, float dest_z, float dest_heading);
bool summonburriedplayercorpse(uint32 char_id, const glm::vec4& position);
bool summonallplayercorpses(uint32 char_id, const glm::vec4& position);
uint32 getplayerburriedcorpsecount(uint32 char_id);
bool buryplayercorpse(uint32 char_id);
void forcedooropen(uint32 doorid, bool altmode);
@@ -208,8 +208,8 @@ public:
void enabletitle(int titleset);
bool checktitle(int titlecheck);
void removetitle(int titlecheck);
uint16 CreateGroundObject(uint32 itemid, float x, float y, float z, float heading, uint32 decay_time = 300000);
uint16 CreateGroundObjectFromModel(const char* model, float x, float y, float z, float heading, uint8 type = 0x00, uint32 decay_time = 0);
uint16 CreateGroundObject(uint32 itemid, const glm::vec4& position, uint32 decay_time = 300000);
uint16 CreateGroundObjectFromModel(const char* model, const glm::vec4& position, uint8 type = 0x00, uint32 decay_time = 0);
void ModifyNPCStat(const char *identifier, const char *newValue);
void UpdateSpawnTimer(uint32 id, uint32 newTime);
void MerchantSetItem(uint32 NPCid, uint32 itemid, uint32 quantity = 0);
@@ -224,7 +224,7 @@ public:
//void RemoveGroupFromInstance(uint16 instance_id); //potentially useful but not implmented at this time.
//void RemoveRaidFromInstance(uint16 instance_id); //potentially useful but not implmented at this time.
void RemoveAllFromInstance(uint16 instance_id);
void MovePCInstance(int zone_id, int instance_id, float x, float y, float z, float heading);
void MovePCInstance(int zone_id, int instance_id, const glm::vec4& position);
void FlagInstanceByGroupLeader(uint32 zone, int16 version);
void FlagInstanceByRaidLeader(uint32 zone, int16 version);
const char* varlink(char* perltext, int item_id);
@@ -241,7 +241,7 @@ public:
uint16 CreateDoor( const char* model, float x, float y, float z, float heading, uint8 opentype, uint16 size);
int32 GetZoneID(const char *zone);
const char *GetZoneLongName(const char *zone);
void CrossZoneSignalPlayerByCharID(int charid, uint32 data);
void CrossZoneSignalPlayerByCharID(int charid, uint32 data);
void CrossZoneSignalNPCByNPCTypeID(uint32 npctype_id, uint32 data);
void CrossZoneSignalPlayerByName(const char *CharName, uint32 data);
void CrossZoneSetEntityVariableByNPCTypeID(uint32 npctype_id, const char *id, const char *m_var);
+21 -21
View File
@@ -99,7 +99,7 @@ void Raid::AddMember(Client *c, uint32 group, bool rleader, bool groupleader, bo
auto results = database.QueryDatabase(query);
if(!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error inserting into raid members: %s", results.ErrorMessage().c_str());
Log.Out(Logs::General, Logs::Error, "Error inserting into raid members: %s", results.ErrorMessage().c_str());
}
LearnMembers();
@@ -233,12 +233,12 @@ void Raid::SetRaidLeader(const char *wasLead, const char *name)
std::string query = StringFormat("UPDATE raid_members SET israidleader = 0 WHERE name = '%s'", wasLead);
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Set Raid Leader error: %s\n", results.ErrorMessage().c_str());
Log.Out(Logs::General, Logs::Error, "Set Raid Leader error: %s\n", results.ErrorMessage().c_str());
query = StringFormat("UPDATE raid_members SET israidleader = 1 WHERE name = '%s'", name);
results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Set Raid Leader error: %s\n", results.ErrorMessage().c_str());
Log.Out(Logs::General, Logs::Error, "Set Raid Leader error: %s\n", results.ErrorMessage().c_str());
strn0cpy(leadername, name, 64);
@@ -271,7 +271,7 @@ void Raid::SaveGroupLeaderAA(uint32 gid)
safe_delete_array(queryBuffer);
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to store LeadershipAA: %s\n", results.ErrorMessage().c_str());
Log.Out(Logs::General, Logs::Error, "Unable to store LeadershipAA: %s\n", results.ErrorMessage().c_str());
}
void Raid::SaveRaidLeaderAA()
@@ -285,7 +285,7 @@ void Raid::SaveRaidLeaderAA()
safe_delete_array(queryBuffer);
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to store LeadershipAA: %s\n", results.ErrorMessage().c_str());
Log.Out(Logs::General, Logs::Error, "Unable to store LeadershipAA: %s\n", results.ErrorMessage().c_str());
}
void Raid::UpdateGroupAAs(uint32 gid)
@@ -489,7 +489,7 @@ void Raid::CastGroupSpell(Mob* caster, uint16 spellid, uint32 gid)
else if(members[x].member != nullptr)
{
if(members[x].GroupNumber == gid){
distance = caster->DistNoRoot(*members[x].member);
distance = DistanceSquared(caster->GetPosition(), members[x].member->GetPosition());
if(distance <= range2){
caster->SpellOnTarget(spellid, members[x].member);
#ifdef GROUP_BUFF_PETS
@@ -498,7 +498,7 @@ void Raid::CastGroupSpell(Mob* caster, uint16 spellid, uint32 gid)
#endif
}
else{
_log(SPELLS__CASTING, "Raid spell: %s is out of range %f at distance %f from %s", members[x].member->GetName(), range, distance, caster->GetName());
Log.Out(Logs::Detail, Logs::Spells, "Raid spell: %s is out of range %f at distance %f from %s", members[x].member->GetName(), range, distance, caster->GetName());
}
}
}
@@ -537,7 +537,7 @@ void Raid::HealGroup(uint32 heal_amt, Mob* caster, uint32 gid, float range)
if(members[gi].member){
if(members[gi].GroupNumber == gid)
{
distance = caster->DistNoRoot(*members[gi].member);
distance = DistanceSquared(caster->GetPosition(), members[gi].member->GetPosition());
if(distance <= range2){
numMem += 1;
}
@@ -551,7 +551,7 @@ void Raid::HealGroup(uint32 heal_amt, Mob* caster, uint32 gid, float range)
if(members[gi].member){
if(members[gi].GroupNumber == gid)
{
distance = caster->DistNoRoot(*members[gi].member);
distance = DistanceSquared(caster->GetPosition(), members[gi].member->GetPosition());
if(distance <= range2){
members[gi].member->SetHP(members[gi].member->GetHP() + heal_amt);
members[gi].member->SendHPUpdate();
@@ -581,7 +581,7 @@ void Raid::BalanceHP(int32 penalty, uint32 gid, float range, Mob* caster, int32
if(members[gi].member){
if(members[gi].GroupNumber == gid)
{
distance = caster->DistNoRoot(*members[gi].member);
distance = DistanceSquared(caster->GetPosition(), members[gi].member->GetPosition());
if(distance <= range2){
dmgtaken_tmp = members[gi].member->GetMaxHP() - members[gi].member->GetHP();
@@ -602,7 +602,7 @@ void Raid::BalanceHP(int32 penalty, uint32 gid, float range, Mob* caster, int32
if(members[gi].member){
if(members[gi].GroupNumber == gid)
{
distance = caster->DistNoRoot(*members[gi].member);
distance = DistanceSquared(caster->GetPosition(), members[gi].member->GetPosition());
if(distance <= range2){
if((members[gi].member->GetMaxHP() - dmgtaken) < 1){//this way the ability will never kill someone
members[gi].member->SetHP(1); //but it will come darn close
@@ -637,7 +637,7 @@ void Raid::BalanceMana(int32 penalty, uint32 gid, float range, Mob* caster, int3
if(members[gi].GroupNumber == gid)
{
if (members[gi].member->GetMaxMana() > 0) {
distance = caster->DistNoRoot(*members[gi].member);
distance = DistanceSquared(caster->GetPosition(), members[gi].member->GetPosition());
if(distance <= range2){
manataken_tmp = members[gi].member->GetMaxMana() - members[gi].member->GetMana();
@@ -660,7 +660,7 @@ void Raid::BalanceMana(int32 penalty, uint32 gid, float range, Mob* caster, int3
if(members[gi].member){
if(members[gi].GroupNumber == gid)
{
distance = caster->DistNoRoot(*members[gi].member);
distance = DistanceSquared(caster->GetPosition(), members[gi].member->GetPosition());
if(distance <= range2){
if((members[gi].member->GetMaxMana() - manataken) < 1){
members[gi].member->SetMana(1);
@@ -791,7 +791,7 @@ void Raid::GroupBardPulse(Mob* caster, uint16 spellid, uint32 gid){
else if(members[z].member != nullptr)
{
if(members[z].GroupNumber == gid){
distance = caster->DistNoRoot(*members[z].member);
distance = DistanceSquared(caster->GetPosition(), members[z].member->GetPosition());
if(distance <= range2) {
members[z].member->BardPulse(spellid, caster);
#ifdef GROUP_BUFF_PETS
@@ -799,7 +799,7 @@ void Raid::GroupBardPulse(Mob* caster, uint16 spellid, uint32 gid){
members[z].member->GetPet()->BardPulse(spellid, caster);
#endif
} else
_log(SPELLS__BARDS, "Group bard pulse: %s is out of range %f at distance %f from %s", members[z].member->GetName(), range, distance, caster->GetName());
Log.Out(Logs::Detail, Logs::Spells, "Group bard pulse: %s is out of range %f at distance %f from %s", members[z].member->GetName(), range, distance, caster->GetName());
}
}
}
@@ -1407,7 +1407,7 @@ void Raid::GetRaidDetails()
return;
if (results.RowCount() == 0) {
LogFile->write(EQEMuLog::Error, "Error getting raid details for raid %lu: %s", (unsigned long)GetID(), results.ErrorMessage().c_str());
Log.Out(Logs::General, Logs::Error, "Error getting raid details for raid %lu: %s", (unsigned long)GetID(), results.ErrorMessage().c_str());
return;
}
@@ -1439,7 +1439,7 @@ bool Raid::LearnMembers()
return false;
if(results.RowCount() == 0) {
LogFile->write(EQEMuLog::Error, "Error getting raid members for raid %lu: %s", (unsigned long)GetID(), results.ErrorMessage().c_str());
Log.Out(Logs::General, Logs::Error, "Error getting raid members for raid %lu: %s", (unsigned long)GetID(), results.ErrorMessage().c_str());
disbandCheck = true;
return false;
}
@@ -1529,7 +1529,7 @@ void Raid::SendHPPacketsTo(Client *c)
{
members[x].member->CreateHPPacket(&hpapp);
c->QueuePacket(&hpapp, false);
if(c->GetClientVersion() >= EQClientSoD)
if(c->GetClientVersion() >= ClientVersion::SoD)
{
outapp.SetOpcode(OP_MobManaUpdate);
MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp.pBuffer;
@@ -1565,7 +1565,7 @@ void Raid::SendHPPacketsFrom(Mob *m)
if(!m->IsClient() || ((members[x].member != m->CastToClient()) && (members[x].GroupNumber == gid)))
{
members[x].member->QueuePacket(&hpapp, false);
if(members[x].member->GetClientVersion() >= EQClientSoD)
if(members[x].member->GetClientVersion() >= ClientVersion::SoD)
{
outapp.SetOpcode(OP_MobManaUpdate);
MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp.pBuffer;
@@ -1643,7 +1643,7 @@ void Raid::SetGroupMentor(uint32 group_id, int percent, char *name)
name, percent, group_id, GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to set raid group mentor: %s\n", results.ErrorMessage().c_str());
Log.Out(Logs::General, Logs::Error, "Unable to set raid group mentor: %s\n", results.ErrorMessage().c_str());
}
void Raid::ClearGroupMentor(uint32 group_id)
@@ -1658,7 +1658,7 @@ void Raid::ClearGroupMentor(uint32 group_id)
group_id, GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to clear raid group mentor: %s\n", results.ErrorMessage().c_str());
Log.Out(Logs::General, Logs::Error, "Unable to clear raid group mentor: %s\n", results.ErrorMessage().c_str());
}
// there isn't a nice place to add this in another function, unlike groups
+72 -87
View File
@@ -16,7 +16,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "../common/global_define.h"
#include "../common/string_util.h"
#include "client.h"
@@ -153,13 +153,13 @@ bool Spawn2::Process() {
if (timer.Check()) {
timer.Disable();
_log(SPAWNS__MAIN, "Spawn2 %d: Timer has triggered", spawn2_id);
Log.Out(Logs::Detail, Logs::Spawns, "Spawn2 %d: Timer has triggered", spawn2_id);
//first check our spawn condition, if this isnt active
//then we reset the timer and try again next time.
if(condition_id != SC_AlwaysEnabled
&& !zone->spawn_conditions.Check(condition_id, condition_min_value)) {
_log(SPAWNS__CONDITIONS, "Spawn2 %d: spawning prevented by spawn condition %d", spawn2_id, condition_id);
Log.Out(Logs::Detail, Logs::Spawns, "Spawn2 %d: spawning prevented by spawn condition %d", spawn2_id, condition_id);
Reset();
return(true);
}
@@ -170,14 +170,14 @@ bool Spawn2::Process() {
}
if (sg == nullptr) {
_log(SPAWNS__MAIN, "Spawn2 %d: Unable to locate spawn group %d. Disabling.", spawn2_id, spawngroup_id_);
Log.Out(Logs::Detail, Logs::Spawns, "Spawn2 %d: Unable to locate spawn group %d. Disabling.", spawn2_id, spawngroup_id_);
return false;
}
//have the spawn group pick an NPC for us
uint32 npcid = sg->GetNPCType();
if (npcid == 0) {
_log(SPAWNS__MAIN, "Spawn2 %d: Spawn group %d did not yeild an NPC! not spawning.", spawn2_id, spawngroup_id_);
Log.Out(Logs::Detail, Logs::Spawns, "Spawn2 %d: Spawn group %d did not yeild an NPC! not spawning.", spawn2_id, spawngroup_id_);
Reset(); //try again later (why?)
return(true);
}
@@ -185,7 +185,7 @@ bool Spawn2::Process() {
//try to find our NPC type.
const NPCType* tmp = database.GetNPCType(npcid);
if (tmp == nullptr) {
_log(SPAWNS__MAIN, "Spawn2 %d: Spawn group %d yeilded an invalid NPC type %d", spawn2_id, spawngroup_id_, npcid);
Log.Out(Logs::Detail, Logs::Spawns, "Spawn2 %d: Spawn group %d yeilded an invalid NPC type %d", spawn2_id, spawngroup_id_, npcid);
Reset(); //try again later
return(true);
}
@@ -194,7 +194,7 @@ bool Spawn2::Process() {
{
if(!entity_list.LimitCheckName(tmp->name))
{
_log(SPAWNS__MAIN, "Spawn2 %d: Spawn group %d yeilded NPC type %d, which is unique and one already exists.", spawn2_id, spawngroup_id_, npcid);
Log.Out(Logs::Detail, Logs::Spawns, "Spawn2 %d: Spawn group %d yeilded NPC type %d, which is unique and one already exists.", spawn2_id, spawngroup_id_, npcid);
timer.Start(5000); //try again in five seconds.
return(true);
}
@@ -202,7 +202,7 @@ bool Spawn2::Process() {
if(tmp->spawn_limit > 0) {
if(!entity_list.LimitCheckType(npcid, tmp->spawn_limit)) {
_log(SPAWNS__MAIN, "Spawn2 %d: Spawn group %d yeilded NPC type %d, which is over its spawn limit (%d)", spawn2_id, spawngroup_id_, npcid, tmp->spawn_limit);
Log.Out(Logs::Detail, Logs::Spawns, "Spawn2 %d: Spawn group %d yeilded NPC type %d, which is over its spawn limit (%d)", spawn2_id, spawngroup_id_, npcid, tmp->spawn_limit);
timer.Start(5000); //try again in five seconds.
return(true);
}
@@ -218,7 +218,7 @@ bool Spawn2::Process() {
database.UpdateSpawn2Timeleft(spawn2_id, zone->GetInstanceID(), 0);
currentnpcid = npcid;
NPC* npc = new NPC(tmp, this, x, y, z, heading, FlyMode3);
NPC* npc = new NPC(tmp, this, glm::vec4(x, y, z, heading), FlyMode3);
npc->mod_prespawn(this);
@@ -233,10 +233,10 @@ bool Spawn2::Process() {
if(sg->roamdist && sg->roambox[0] && sg->roambox[1] && sg->roambox[2] && sg->roambox[3] && sg->delay && sg->min_delay)
npc->AI_SetRoambox(sg->roamdist,sg->roambox[0],sg->roambox[1],sg->roambox[2],sg->roambox[3],sg->delay,sg->min_delay);
if(zone->InstantGrids()) {
_log(SPAWNS__MAIN, "Spawn2 %d: Group %d spawned %s (%d) at (%.3f, %.3f, %.3f).", spawn2_id, spawngroup_id_, npc->GetName(), npcid, x, y, z);
Log.Out(Logs::Detail, Logs::Spawns, "Spawn2 %d: Group %d spawned %s (%d) at (%.3f, %.3f, %.3f).", spawn2_id, spawngroup_id_, npc->GetName(), npcid, x, y, z);
LoadGrid();
} else {
_log(SPAWNS__MAIN, "Spawn2 %d: Group %d spawned %s (%d) at (%.3f, %.3f, %.3f). Grid loading delayed.", spawn2_id, spawngroup_id_, tmp->name, npcid, x, y, z);
Log.Out(Logs::Detail, Logs::Spawns, "Spawn2 %d: Group %d spawned %s (%d) at (%.3f, %.3f, %.3f). Grid loading delayed.", spawn2_id, spawngroup_id_, tmp->name, npcid, x, y, z);
}
}
return true;
@@ -261,7 +261,7 @@ void Spawn2::LoadGrid() {
//dont set an NPC's grid until its loaded for them.
npcthis->SetGrid(grid_);
npcthis->AssignWaypoints(grid_);
_log(SPAWNS__MAIN, "Spawn2 %d: Loading grid %d for %s", spawn2_id, grid_, npcthis->GetName());
Log.Out(Logs::Detail, Logs::Spawns, "Spawn2 %d: Loading grid %d for %s", spawn2_id, grid_, npcthis->GetName());
}
@@ -272,21 +272,21 @@ void Spawn2::LoadGrid() {
void Spawn2::Reset() {
timer.Start(resetTimer());
npcthis = nullptr;
_log(SPAWNS__MAIN, "Spawn2 %d: Spawn reset, repop in %d ms", spawn2_id, timer.GetRemainingTime());
Log.Out(Logs::Detail, Logs::Spawns, "Spawn2 %d: Spawn reset, repop in %d ms", spawn2_id, timer.GetRemainingTime());
}
void Spawn2::Depop() {
timer.Disable();
_log(SPAWNS__MAIN, "Spawn2 %d: Spawn reset, repop disabled", spawn2_id);
Log.Out(Logs::Detail, Logs::Spawns, "Spawn2 %d: Spawn reset, repop disabled", spawn2_id);
npcthis = nullptr;
}
void Spawn2::Repop(uint32 delay) {
if (delay == 0) {
timer.Trigger();
_log(SPAWNS__MAIN, "Spawn2 %d: Spawn reset, repop immediately.", spawn2_id);
Log.Out(Logs::Detail, Logs::Spawns, "Spawn2 %d: Spawn reset, repop immediately.", spawn2_id);
} else {
_log(SPAWNS__MAIN, "Spawn2 %d: Spawn reset for repop, repop in %d ms", spawn2_id, delay);
Log.Out(Logs::Detail, Logs::Spawns, "Spawn2 %d: Spawn reset for repop, repop in %d ms", spawn2_id, delay);
timer.Start(delay);
}
npcthis = nullptr;
@@ -328,7 +328,7 @@ void Spawn2::ForceDespawn()
cur = despawnTimer(dtimer);
}
_log(SPAWNS__MAIN, "Spawn2 %d: Spawn group %d set despawn timer to %d ms.", spawn2_id, spawngroup_id_, cur);
Log.Out(Logs::Detail, Logs::Spawns, "Spawn2 %d: Spawn group %d set despawn timer to %d ms.", spawn2_id, spawngroup_id_, cur);
timer.Start(cur);
}
@@ -349,7 +349,7 @@ void Spawn2::DeathReset(bool realdeath)
if(spawn2_id)
{
database.UpdateSpawn2Timeleft(spawn2_id, zone->GetInstanceID(), (cur/1000));
_log(SPAWNS__MAIN, "Spawn2 %d: Spawn reset by death, repop in %d ms", spawn2_id, timer.GetRemainingTime());
Log.Out(Logs::Detail, Logs::Spawns, "Spawn2 %d: Spawn reset by death, repop in %d ms", spawn2_id, timer.GetRemainingTime());
//store it to database too
}
}
@@ -364,7 +364,6 @@ bool ZoneDatabase::PopulateZoneSpawnList(uint32 zoneid, LinkedList<Spawn2*> &spa
zone_name, version);
auto results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in PopulateZoneLists query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
return false;
}
@@ -392,12 +391,10 @@ Spawn2* ZoneDatabase::LoadSpawn2(LinkedList<Spawn2*> &spawn2_list, uint32 spawn2
"WHERE id = %i", spawn2id);
auto results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in LoadSpawn2 query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
return nullptr;
}
if (results.RowCount() != 1) {
LogFile->write(EQEMuLog::Error, "Error in LoadSpawn2 query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
return nullptr;
}
@@ -414,17 +411,16 @@ Spawn2* ZoneDatabase::LoadSpawn2(LinkedList<Spawn2*> &spawn2_list, uint32 spawn2
return newSpawn;
}
bool ZoneDatabase::CreateSpawn2(Client *client, uint32 spawngroup, const char* zone, float heading, float x, float y, float z, uint32 respawn, uint32 variance, uint16 condition, int16 cond_value)
bool ZoneDatabase::CreateSpawn2(Client *client, uint32 spawngroup, const char* zone, const glm::vec4& position, uint32 respawn, uint32 variance, uint16 condition, int16 cond_value)
{
std::string query = StringFormat("INSERT INTO spawn2 (spawngroupID, zone, x, y, z, heading, "
"respawntime, variance, _condition, cond_value) "
"VALUES (%i, '%s', %f, %f, %f, %f, %i, %i, %u, %i)",
spawngroup, zone, x, y, z, heading,
spawngroup, zone, position.x, position.y, position.z, position.w,
respawn, variance, condition, cond_value);
auto results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in CreateSpawn2 query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
return false;
}
@@ -432,7 +428,6 @@ bool ZoneDatabase::CreateSpawn2(Client *client, uint32 spawngroup, const char* z
return false;
if(client)
client->LogSQL(query.c_str());
return true;
}
@@ -466,12 +461,12 @@ void Spawn2::SpawnConditionChanged(const SpawnCondition &c, int16 old_value) {
if(GetSpawnCondition() != c.condition_id)
return;
_log(SPAWNS__CONDITIONS, "Spawn2 %d: Notified that our spawn condition %d has changed from %d to %d. Our min value is %d.", spawn2_id, c.condition_id, old_value, c.value, condition_min_value);
Log.Out(Logs::Detail, Logs::Spawns, "Spawn2 %d: Notified that our spawn condition %d has changed from %d to %d. Our min value is %d.", spawn2_id, c.condition_id, old_value, c.value, condition_min_value);
bool old_state = (old_value >= condition_min_value);
bool new_state = (c.value >= condition_min_value);
if(old_state == new_state) {
_log(SPAWNS__CONDITIONS, "Spawn2 %d: Our threshold for this condition was not crossed. Doing nothing.", spawn2_id);
Log.Out(Logs::Detail, Logs::Spawns, "Spawn2 %d: Our threshold for this condition was not crossed. Doing nothing.", spawn2_id);
return; //no change
}
@@ -479,50 +474,50 @@ void Spawn2::SpawnConditionChanged(const SpawnCondition &c, int16 old_value) {
switch(c.on_change) {
case SpawnCondition::DoNothing:
//that was easy.
_log(SPAWNS__CONDITIONS, "Spawn2 %d: Our condition is now %s. Taking no action on existing spawn.", spawn2_id, new_state?"enabled":"disabled");
Log.Out(Logs::Detail, Logs::Spawns, "Spawn2 %d: Our condition is now %s. Taking no action on existing spawn.", spawn2_id, new_state?"enabled":"disabled");
break;
case SpawnCondition::DoDepop:
_log(SPAWNS__CONDITIONS, "Spawn2 %d: Our condition is now %s. Depoping our mob.", spawn2_id, new_state?"enabled":"disabled");
Log.Out(Logs::Detail, Logs::Spawns, "Spawn2 %d: Our condition is now %s. Depoping our mob.", spawn2_id, new_state?"enabled":"disabled");
if(npcthis != nullptr)
npcthis->Depop(false); //remove the current mob
Reset(); //reset our spawn timer
break;
case SpawnCondition::DoRepop:
_log(SPAWNS__CONDITIONS, "Spawn2 %d: Our condition is now %s. Forcing a repop.", spawn2_id, new_state?"enabled":"disabled");
Log.Out(Logs::Detail, Logs::Spawns, "Spawn2 %d: Our condition is now %s. Forcing a repop.", spawn2_id, new_state?"enabled":"disabled");
if(npcthis != nullptr)
npcthis->Depop(false); //remove the current mob
Repop(); //repop
break;
case SpawnCondition::DoRepopIfReady:
_log(SPAWNS__CONDITIONS, "Spawn2 %d: Our condition is now %s. Forcing a repop if repsawn timer is expired.", spawn2_id, new_state?"enabled":"disabled");
Log.Out(Logs::Detail, Logs::Spawns, "Spawn2 %d: Our condition is now %s. Forcing a repop if repsawn timer is expired.", spawn2_id, new_state?"enabled":"disabled");
if(npcthis != nullptr) {
_log(SPAWNS__CONDITIONS, "Spawn2 %d: Our npcthis is currently not null. The zone thinks it is %s. Forcing a depop.", spawn2_id, npcthis->GetName());
Log.Out(Logs::Detail, Logs::Spawns, "Spawn2 %d: Our npcthis is currently not null. The zone thinks it is %s. Forcing a depop.", spawn2_id, npcthis->GetName());
npcthis->Depop(false); //remove the current mob
npcthis = nullptr;
}
if(new_state) { // only get repawn timer remaining when the SpawnCondition is enabled.
timer_remaining = database.GetSpawnTimeLeft(spawn2_id,zone->GetInstanceID());
_log(SPAWNS__CONDITIONS,"Spawn2 %d: Our condition is now %s. The respawn timer_remaining is %d. Forcing a repop if it is <= 0.", spawn2_id, new_state?"enabled":"disabled", timer_remaining);
Log.Out(Logs::Detail, Logs::Spawns,"Spawn2 %d: Our condition is now %s. The respawn timer_remaining is %d. Forcing a repop if it is <= 0.", spawn2_id, new_state?"enabled":"disabled", timer_remaining);
if(timer_remaining <= 0)
Repop();
} else {
_log(SPAWNS__CONDITIONS,"Spawn2 %d: Our condition is now %s. Not checking respawn timer.", spawn2_id, new_state?"enabled":"disabled");
Log.Out(Logs::Detail, Logs::Spawns,"Spawn2 %d: Our condition is now %s. Not checking respawn timer.", spawn2_id, new_state?"enabled":"disabled");
}
break;
default:
if(c.on_change < SpawnCondition::DoSignalMin) {
_log(SPAWNS__CONDITIONS, "Spawn2 %d: Our condition is now %s. Invalid on-change action %d.", spawn2_id, new_state?"enabled":"disabled", c.on_change);
Log.Out(Logs::Detail, Logs::Spawns, "Spawn2 %d: Our condition is now %s. Invalid on-change action %d.", spawn2_id, new_state?"enabled":"disabled", c.on_change);
return; //unknown onchange action
}
int signal_id = c.on_change - SpawnCondition::DoSignalMin;
_log(SPAWNS__CONDITIONS, "Spawn2 %d: Our condition is now %s. Signaling our mob with %d.", spawn2_id, new_state?"enabled":"disabled", signal_id);
Log.Out(Logs::Detail, Logs::Spawns, "Spawn2 %d: Our condition is now %s. Signaling our mob with %d.", spawn2_id, new_state?"enabled":"disabled", signal_id);
if(npcthis != nullptr)
npcthis->SignalNPC(signal_id);
}
}
void Zone::SpawnConditionChanged(const SpawnCondition &c, int16 old_value) {
_log(SPAWNS__CONDITIONS, "Zone notified that spawn condition %d has changed from %d to %d. Notifying all spawn points.", c.condition_id, old_value, c.value);
Log.Out(Logs::Detail, Logs::Spawns, "Zone notified that spawn condition %d has changed from %d to %d. Notifying all spawn points.", c.condition_id, old_value, c.value);
LinkedListIterator<Spawn2*> iterator(spawn2_list);
@@ -592,7 +587,7 @@ void SpawnConditionManager::Process() {
EQTime::AddMinutes(cevent.period, &cevent.next);
std::string t;
EQTime::ToString(&cevent.next, t);
_log(SPAWNS__CONDITIONS, "Event %d: Will trigger again in %d EQ minutes at %s.", cevent.id, cevent.period, t.c_str());
Log.Out(Logs::Detail, Logs::Spawns, "Event %d: Will trigger again in %d EQ minutes at %s.", cevent.id, cevent.period, t.c_str());
//save the next event time in the DB
UpdateDBEvent(cevent);
//find the next closest event timer.
@@ -611,7 +606,7 @@ void SpawnConditionManager::ExecEvent(SpawnEvent &event, bool send_update) {
std::map<uint16, SpawnCondition>::iterator condi;
condi = spawn_conditions.find(event.condition_id);
if(condi == spawn_conditions.end()) {
_log(SPAWNS__CONDITIONS, "Event %d: Unable to find condition %d to execute on.", event.id, event.condition_id);
Log.Out(Logs::Detail, Logs::Spawns, "Event %d: Unable to find condition %d to execute on.", event.id, event.condition_id);
return; //unable to find the spawn condition to operate on
}
@@ -619,7 +614,7 @@ void SpawnConditionManager::ExecEvent(SpawnEvent &event, bool send_update) {
zone->zone_time.getEQTimeOfDay(&tod);
if(event.strict && (event.next.hour != tod.hour || event.next.day != tod.day || event.next.month != tod.month || event.next.year != tod.year))
{
_log(SPAWNS__CONDITIONS, "Event %d: Unable to execute. Condition is strict, and event time has already passed.", event.id);
Log.Out(Logs::Detail, Logs::Spawns, "Event %d: Unable to execute. Condition is strict, and event time has already passed.", event.id);
return;
}
@@ -631,26 +626,26 @@ void SpawnConditionManager::ExecEvent(SpawnEvent &event, bool send_update) {
switch(event.action) {
case SpawnEvent::ActionSet:
new_value = event.argument;
_log(SPAWNS__CONDITIONS, "Event %d: Executing. Setting condition %d to %d.", event.id, event.condition_id, event.argument);
Log.Out(Logs::Detail, Logs::Spawns, "Event %d: Executing. Setting condition %d to %d.", event.id, event.condition_id, event.argument);
break;
case SpawnEvent::ActionAdd:
new_value += event.argument;
_log(SPAWNS__CONDITIONS, "Event %d: Executing. Adding %d to condition %d, yeilding %d.", event.id, event.argument, event.condition_id, new_value);
Log.Out(Logs::Detail, Logs::Spawns, "Event %d: Executing. Adding %d to condition %d, yeilding %d.", event.id, event.argument, event.condition_id, new_value);
break;
case SpawnEvent::ActionSubtract:
new_value -= event.argument;
_log(SPAWNS__CONDITIONS, "Event %d: Executing. Subtracting %d from condition %d, yeilding %d.", event.id, event.argument, event.condition_id, new_value);
Log.Out(Logs::Detail, Logs::Spawns, "Event %d: Executing. Subtracting %d from condition %d, yeilding %d.", event.id, event.argument, event.condition_id, new_value);
break;
case SpawnEvent::ActionMultiply:
new_value *= event.argument;
_log(SPAWNS__CONDITIONS, "Event %d: Executing. Multiplying condition %d by %d, yeilding %d.", event.id, event.condition_id, event.argument, new_value);
Log.Out(Logs::Detail, Logs::Spawns, "Event %d: Executing. Multiplying condition %d by %d, yeilding %d.", event.id, event.condition_id, event.argument, new_value);
break;
case SpawnEvent::ActionDivide:
new_value /= event.argument;
_log(SPAWNS__CONDITIONS, "Event %d: Executing. Dividing condition %d by %d, yeilding %d.", event.id, event.condition_id, event.argument, new_value);
Log.Out(Logs::Detail, Logs::Spawns, "Event %d: Executing. Dividing condition %d by %d, yeilding %d.", event.id, event.condition_id, event.argument, new_value);
break;
default:
_log(SPAWNS__CONDITIONS, "Event %d: Invalid event action type %d", event.id, event.action);
Log.Out(Logs::Detail, Logs::Spawns, "Event %d: Invalid event action type %d", event.id, event.action);
return;
}
@@ -672,10 +667,7 @@ void SpawnConditionManager::UpdateDBEvent(SpawnEvent &event) {
event.next.day, event.next.month,
event.next.year, event.enabled? 1: 0,
event.strict? 1: 0, event.id);
auto results = database.QueryDatabase(query);
if(!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to update spawn event '%s': %s\n", query.c_str(), results.ErrorMessage().c_str());
database.QueryDatabase(query);
}
void SpawnConditionManager::UpdateDBCondition(const char* zone_name, uint32 instance_id, uint16 cond_id, int16 value) {
@@ -684,10 +676,7 @@ void SpawnConditionManager::UpdateDBCondition(const char* zone_name, uint32 inst
"(id, value, zone, instance_id) "
"VALUES( %u, %u, '%s', %u)",
cond_id, value, zone_name, instance_id);
auto results = database.QueryDatabase(query);
if(!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to update spawn condition '%s': %s\n", query.c_str(), results.ErrorMessage().c_str());
database.QueryDatabase(query);
}
bool SpawnConditionManager::LoadDBEvent(uint32 event_id, SpawnEvent &event, std::string &zone_name) {
@@ -699,7 +688,6 @@ bool SpawnConditionManager::LoadDBEvent(uint32 event_id, SpawnEvent &event, std:
"FROM spawn_events WHERE id = %d", event_id);
auto results = database.QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in LoadDBEvent query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
return false;
}
@@ -727,7 +715,7 @@ bool SpawnConditionManager::LoadDBEvent(uint32 event_id, SpawnEvent &event, std:
std::string timeAsString;
EQTime::ToString(&event.next, timeAsString);
_log(SPAWNS__CONDITIONS, "(LoadDBEvent) Loaded %s spawn event %d on condition %d with period %d, action %d, argument %d, strict %d. Will trigger at %s", event.enabled? "enabled": "disabled", event.id, event.condition_id, event.period, event.action, event.argument, event.strict, timeAsString.c_str());
Log.Out(Logs::Detail, Logs::Spawns, "(LoadDBEvent) Loaded %s spawn event %d on condition %d with period %d, action %d, argument %d, strict %d. Will trigger at %s", event.enabled? "enabled": "disabled", event.id, event.condition_id, event.period, event.action, event.argument, event.strict, timeAsString.c_str());
return true;
}
@@ -742,7 +730,6 @@ bool SpawnConditionManager::LoadSpawnConditions(const char* zone_name, uint32 in
"WHERE zone = '%s'", zone_name);
auto results = database.QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in LoadSpawnConditions query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
return false;
}
@@ -755,7 +742,7 @@ bool SpawnConditionManager::LoadSpawnConditions(const char* zone_name, uint32 in
cond.on_change = (SpawnCondition::OnChange) atoi(row[1]);
spawn_conditions[cond.condition_id] = cond;
_log(SPAWNS__CONDITIONS, "Loaded spawn condition %d with value %d and on_change %d", cond.condition_id, cond.value, cond.on_change);
Log.Out(Logs::Detail, Logs::Spawns, "Loaded spawn condition %d with value %d and on_change %d", cond.condition_id, cond.value, cond.on_change);
}
//load values
@@ -764,7 +751,6 @@ bool SpawnConditionManager::LoadSpawnConditions(const char* zone_name, uint32 in
zone_name, instance_id);
results = database.QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in LoadSpawnConditions query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
spawn_conditions.clear();
return false;
}
@@ -782,7 +768,6 @@ bool SpawnConditionManager::LoadSpawnConditions(const char* zone_name, uint32 in
"FROM spawn_events WHERE zone = '%s'", zone_name);
results = database.QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in LoadSpawnConditions events query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
return false;
}
@@ -794,7 +779,7 @@ bool SpawnConditionManager::LoadSpawnConditions(const char* zone_name, uint32 in
event.period = atoi(row[2]);
if(event.period == 0) {
LogFile->write(EQEMuLog::Error, "Refusing to load spawn event #%d because it has a period of 0\n", event.id);
Log.Out(Logs::General, Logs::Error, "Refusing to load spawn event #%d because it has a period of 0\n", event.id);
continue;
}
@@ -811,7 +796,7 @@ bool SpawnConditionManager::LoadSpawnConditions(const char* zone_name, uint32 in
spawn_events.push_back(event);
_log(SPAWNS__CONDITIONS, "(LoadSpawnConditions) Loaded %s spawn event %d on condition %d with period %d, action %d, argument %d, strict %d", event.enabled? "enabled": "disabled", event.id, event.condition_id, event.period, event.action, event.argument, event.strict);
Log.Out(Logs::Detail, Logs::Spawns, "(LoadSpawnConditions) Loaded %s spawn event %d on condition %d with period %d, action %d, argument %d, strict %d", event.enabled? "enabled": "disabled", event.id, event.condition_id, event.period, event.action, event.argument, event.strict);
}
//now we need to catch up on events that happened while we were away
@@ -846,7 +831,7 @@ bool SpawnConditionManager::LoadSpawnConditions(const char* zone_name, uint32 in
//watch for special case of all 0s, which means to reset next to now
if(cevent.next.year == 0 && cevent.next.month == 0 && cevent.next.day == 0 && cevent.next.hour == 0 && cevent.next.minute == 0) {
_log(SPAWNS__CONDITIONS, "Initial next trigger time set for spawn event %d", cevent.id);
Log.Out(Logs::Detail, Logs::Spawns, "Initial next trigger time set for spawn event %d", cevent.id);
memcpy(&cevent.next, &tod, sizeof(cevent.next));
//add one period
EQTime::AddMinutes(cevent.period, &cevent.next);
@@ -857,7 +842,7 @@ bool SpawnConditionManager::LoadSpawnConditions(const char* zone_name, uint32 in
bool ran = false;
while(EQTime::IsTimeBefore(&tod, &cevent.next)) {
_log(SPAWNS__CONDITIONS, "Catch up triggering on event %d", cevent.id);
Log.Out(Logs::Detail, Logs::Spawns, "Catch up triggering on event %d", cevent.id);
//this event has been triggered.
//execute the event
if(!cevent.strict || StrictCheck)
@@ -900,9 +885,9 @@ void SpawnConditionManager::FindNearestEvent() {
}
}
if(next_id == -1)
_log(SPAWNS__CONDITIONS, "No spawn events enabled. Disabling next event.");
Log.Out(Logs::Detail, Logs::Spawns, "No spawn events enabled. Disabling next event.");
else
_log(SPAWNS__CONDITIONS, "Next event determined to be event %d", next_id);
Log.Out(Logs::Detail, Logs::Spawns, "Next event determined to be event %d", next_id);
}
void SpawnConditionManager::SetCondition(const char *zone_short, uint32 instance_id, uint16 condition_id, int16 new_value, bool world_update)
@@ -914,14 +899,14 @@ void SpawnConditionManager::SetCondition(const char *zone_short, uint32 instance
std::map<uint16, SpawnCondition>::iterator condi;
condi = spawn_conditions.find(condition_id);
if(condi == spawn_conditions.end()) {
_log(SPAWNS__CONDITIONS, "Condition update received from world for %d, but we do not have that conditon.", condition_id);
Log.Out(Logs::Detail, Logs::Spawns, "Condition update received from world for %d, but we do not have that conditon.", condition_id);
return; //unable to find the spawn condition
}
SpawnCondition &cond = condi->second;
if(cond.value == new_value) {
_log(SPAWNS__CONDITIONS, "Condition update received from world for %d with value %d, which is what we already have.", condition_id, new_value);
Log.Out(Logs::Detail, Logs::Spawns, "Condition update received from world for %d with value %d, which is what we already have.", condition_id, new_value);
return;
}
@@ -930,7 +915,7 @@ void SpawnConditionManager::SetCondition(const char *zone_short, uint32 instance
//set our local value
cond.value = new_value;
_log(SPAWNS__CONDITIONS, "Condition update received from world for %d with value %d", condition_id, new_value);
Log.Out(Logs::Detail, Logs::Spawns, "Condition update received from world for %d with value %d", condition_id, new_value);
//now we have to test each spawn point to see if it changed.
zone->SpawnConditionChanged(cond, old_value);
@@ -941,14 +926,14 @@ void SpawnConditionManager::SetCondition(const char *zone_short, uint32 instance
std::map<uint16, SpawnCondition>::iterator condi;
condi = spawn_conditions.find(condition_id);
if(condi == spawn_conditions.end()) {
_log(SPAWNS__CONDITIONS, "Local Condition update requested for %d, but we do not have that conditon.", condition_id);
Log.Out(Logs::Detail, Logs::Spawns, "Local Condition update requested for %d, but we do not have that conditon.", condition_id);
return; //unable to find the spawn condition
}
SpawnCondition &cond = condi->second;
if(cond.value == new_value) {
_log(SPAWNS__CONDITIONS, "Local Condition update requested for %d with value %d, which is what we already have.", condition_id, new_value);
Log.Out(Logs::Detail, Logs::Spawns, "Local Condition update requested for %d with value %d, which is what we already have.", condition_id, new_value);
return;
}
@@ -959,7 +944,7 @@ void SpawnConditionManager::SetCondition(const char *zone_short, uint32 instance
//save it in the DB too
UpdateDBCondition(zone_short, instance_id, condition_id, new_value);
_log(SPAWNS__CONDITIONS, "Local Condition update requested for %d with value %d", condition_id, new_value);
Log.Out(Logs::Detail, Logs::Spawns, "Local Condition update requested for %d with value %d", condition_id, new_value);
//now we have to test each spawn point to see if it changed.
zone->SpawnConditionChanged(cond, old_value);
@@ -969,7 +954,7 @@ void SpawnConditionManager::SetCondition(const char *zone_short, uint32 instance
//this is a remote spawn condition, update the DB and send
//an update packet to the zone if its up
_log(SPAWNS__CONDITIONS, "Remote spawn condition %d set to %d. Updating DB and notifying world.", condition_id, new_value);
Log.Out(Logs::Detail, Logs::Spawns, "Remote spawn condition %d set to %d. Updating DB and notifying world.", condition_id, new_value);
UpdateDBCondition(zone_short, instance_id, condition_id, new_value);
@@ -989,7 +974,7 @@ void SpawnConditionManager::SetCondition(const char *zone_short, uint32 instance
void SpawnConditionManager::ReloadEvent(uint32 event_id) {
std::string zone_short_name;
_log(SPAWNS__CONDITIONS, "Requested to reload event %d from the database.", event_id);
Log.Out(Logs::Detail, Logs::Spawns, "Requested to reload event %d from the database.", event_id);
//first look for the event in our local event list
std::vector<SpawnEvent>::iterator cur,end;
@@ -1002,7 +987,7 @@ void SpawnConditionManager::ReloadEvent(uint32 event_id) {
//load the event into the old event slot
if(!LoadDBEvent(event_id, cevent, zone_short_name)) {
//unable to find the event in the database...
_log(SPAWNS__CONDITIONS, "Failed to reload event %d from the database.", event_id);
Log.Out(Logs::Detail, Logs::Spawns, "Failed to reload event %d from the database.", event_id);
return;
}
//sync up our nearest event
@@ -1015,7 +1000,7 @@ void SpawnConditionManager::ReloadEvent(uint32 event_id) {
SpawnEvent e;
if(!LoadDBEvent(event_id, e, zone_short_name)) {
//unable to find the event in the database...
_log(SPAWNS__CONDITIONS, "Failed to reload event %d from the database.", event_id);
Log.Out(Logs::Detail, Logs::Spawns, "Failed to reload event %d from the database.", event_id);
return;
}
@@ -1032,7 +1017,7 @@ void SpawnConditionManager::ReloadEvent(uint32 event_id) {
void SpawnConditionManager::ToggleEvent(uint32 event_id, bool enabled, bool strict, bool reset_base) {
_log(SPAWNS__CONDITIONS, "Request to %s spawn event %d %sresetting trigger time", enabled?"enable":"disable", event_id, reset_base?"":"without ");
Log.Out(Logs::Detail, Logs::Spawns, "Request to %s spawn event %d %sresetting trigger time", enabled?"enable":"disable", event_id, reset_base?"":"without ");
//first look for the event in our local event list
std::vector<SpawnEvent>::iterator cur,end;
@@ -1047,13 +1032,13 @@ void SpawnConditionManager::ToggleEvent(uint32 event_id, bool enabled, bool stri
cevent.enabled = enabled;
cevent.strict = strict;
if(reset_base) {
_log(SPAWNS__CONDITIONS, "Spawn event %d located in this zone. State set. Trigger time reset (period %d).", event_id, cevent.period);
Log.Out(Logs::Detail, Logs::Spawns, "Spawn event %d located in this zone. State set. Trigger time reset (period %d).", event_id, cevent.period);
//start with the time now
zone->zone_time.getEQTimeOfDay(&cevent.next);
//advance the next time by our period
EQTime::AddMinutes(cevent.period, &cevent.next);
} else {
_log(SPAWNS__CONDITIONS, "Spawn event %d located in this zone. State changed.", event_id);
Log.Out(Logs::Detail, Logs::Spawns, "Spawn event %d located in this zone. State changed.", event_id);
}
//save the event in the DB
@@ -1062,7 +1047,7 @@ void SpawnConditionManager::ToggleEvent(uint32 event_id, bool enabled, bool stri
//sync up our nearest event
FindNearestEvent();
} else {
_log(SPAWNS__CONDITIONS, "Spawn event %d located in this zone but no change was needed.", event_id);
Log.Out(Logs::Detail, Logs::Spawns, "Spawn event %d located in this zone but no change was needed.", event_id);
}
//even if we dont change anything, we still found it
return;
@@ -1081,24 +1066,24 @@ void SpawnConditionManager::ToggleEvent(uint32 event_id, bool enabled, bool stri
SpawnEvent e;
std::string zone_short_name;
if(!LoadDBEvent(event_id, e, zone_short_name)) {
_log(SPAWNS__CONDITIONS, "Unable to find spawn event %d in the database.", event_id);
Log.Out(Logs::Detail, Logs::Spawns, "Unable to find spawn event %d in the database.", event_id);
//unable to find the event in the database...
return;
}
if(e.enabled == enabled && !reset_base) {
_log(SPAWNS__CONDITIONS, "Spawn event %d is not located in this zone but no change was needed.", event_id);
Log.Out(Logs::Detail, Logs::Spawns, "Spawn event %d is not located in this zone but no change was needed.", event_id);
return; //no changes.
}
e.enabled = enabled;
if(reset_base) {
_log(SPAWNS__CONDITIONS, "Spawn event %d is in zone %s. State set. Trigger time reset (period %d). Notifying world.", event_id, zone_short_name.c_str(), e.period);
Log.Out(Logs::Detail, Logs::Spawns, "Spawn event %d is in zone %s. State set. Trigger time reset (period %d). Notifying world.", event_id, zone_short_name.c_str(), e.period);
//start with the time now
zone->zone_time.getEQTimeOfDay(&e.next);
//advance the next time by our period
EQTime::AddMinutes(e.period, &e.next);
} else {
_log(SPAWNS__CONDITIONS, "Spawn event %d is in zone %s. State changed. Notifying world.", event_id, zone_short_name.c_str(), e.period);
Log.Out(Logs::Detail, Logs::Spawns, "Spawn event %d is in zone %s. State changed. Notifying world.", event_id, zone_short_name.c_str(), e.period);
}
//save the event in the DB
UpdateDBEvent(e);
@@ -1123,7 +1108,7 @@ int16 SpawnConditionManager::GetCondition(const char *zone_short, uint32 instanc
condi = spawn_conditions.find(condition_id);
if(condi == spawn_conditions.end())
{
_log(SPAWNS__CONDITIONS, "Unable to find local condition %d in Get request.", condition_id);
Log.Out(Logs::Detail, Logs::Spawns, "Unable to find local condition %d in Get request.", condition_id);
return(0); //unable to find the spawn condition
}
@@ -1138,12 +1123,12 @@ int16 SpawnConditionManager::GetCondition(const char *zone_short, uint32 instanc
zone_short, instance_id, condition_id);
auto results = database.QueryDatabase(query);
if (!results.Success()) {
_log(SPAWNS__CONDITIONS, "Unable to query remote condition %d from zone %s in Get request.", condition_id, zone_short);
Log.Out(Logs::Detail, Logs::Spawns, "Unable to query remote condition %d from zone %s in Get request.", condition_id, zone_short);
return 0; //dunno a better thing to do...
}
if (results.RowCount() == 0) {
_log(SPAWNS__CONDITIONS, "Unable to load remote condition %d from zone %s in Get request.", condition_id, zone_short);
Log.Out(Logs::Detail, Logs::Spawns, "Unable to load remote condition %d from zone %s in Get request.", condition_id, zone_short);
return 0; //dunno a better thing to do...
}
+5 -8
View File
@@ -16,7 +16,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "../common/global_define.h"
#include "../common/string_util.h"
#include "../common/types.h"
@@ -51,7 +51,7 @@ SpawnGroup::SpawnGroup( uint32 in_id, char* name, int in_group_spawn_limit, floa
uint32 SpawnGroup::GetNPCType() {
#if EQDEBUG >= 10
LogFile->write(EQEMuLog::Debug, "SpawnGroup[%08x]::GetNPCType()", (uint32) this);
Log.Out(Logs::General, Logs::None, "SpawnGroup[%08x]::GetNPCType()", (uint32) this);
#endif
int npcType = 0;
int totalchance = 0;
@@ -149,7 +149,6 @@ bool ZoneDatabase::LoadSpawnGroups(const char* zone_name, uint16 version, SpawnG
"AND spawn2.version = %u and zone = '%s'", version, zone_name);
auto results = QueryDatabase(query);
if (!results.Success()) {
_log(ZONE__SPAWNS, "Error2 in PopulateZoneLists query '%s' ", query.c_str());
return false;
}
@@ -168,7 +167,7 @@ bool ZoneDatabase::LoadSpawnGroups(const char* zone_name, uint16 version, SpawnG
"AND zone = '%s'", zone_name);
results = QueryDatabase(query);
if (!results.Success()) {
_log(ZONE__SPAWNS, "Error2 in PopulateZoneLists query '%'", query.c_str());
Log.Out(Logs::General, Logs::Error, "Error2 in PopulateZoneLists query '%'", query.c_str());
return false;
}
@@ -177,7 +176,6 @@ bool ZoneDatabase::LoadSpawnGroups(const char* zone_name, uint16 version, SpawnG
SpawnGroup *sg = spawn_group_list->GetSpawnGroup(atoi(row[0]));
if (!sg) {
_log(ZONE__SPAWNS, "Error in LoadSpawnGroups %s ", query.c_str());
continue;
}
@@ -197,7 +195,7 @@ bool ZoneDatabase::LoadSpawnGroupsByID(int spawngroupid, SpawnGroupList* spawn_g
"FROM spawngroup WHERE spawngroup.ID = '%i'", spawngroupid);
auto results = QueryDatabase(query);
if (!results.Success()) {
_log(ZONE__SPAWNS, "Error2 in PopulateZoneLists query %s", query.c_str());
Log.Out(Logs::General, Logs::Error, "Error2 in PopulateZoneLists query %s", query.c_str());
return false;
}
@@ -212,7 +210,7 @@ bool ZoneDatabase::LoadSpawnGroupsByID(int spawngroupid, SpawnGroupList* spawn_g
"ORDER BY chance", spawngroupid);
results = QueryDatabase(query);
if (!results.Success()) {
_log(ZONE__SPAWNS, "Error3 in PopulateZoneLists query '%s'", query.c_str());
Log.Out(Logs::General, Logs::Error, "Error3 in PopulateZoneLists query '%s'", query.c_str());
return false;
}
@@ -220,7 +218,6 @@ bool ZoneDatabase::LoadSpawnGroupsByID(int spawngroupid, SpawnGroupList* spawn_g
SpawnEntry* newSpawnEntry = new SpawnEntry( atoi(row[1]), atoi(row[2]), row[3]?atoi(row[3]):0);
SpawnGroup *sg = spawn_group_list->GetSpawnGroup(atoi(row[0]));
if (!sg) {
_log(ZONE__SPAWNS, "Error in SpawngroupID: %s ", row[0]);
continue;
}
+45 -39
View File
@@ -464,7 +464,7 @@ int Mob::MonkSpecialAttack(Mob* other, uint8 unchecked_type)
break;
}
default:
mlog(CLIENT__ERROR, "Invalid special attack type %d attempted", unchecked_type);
Log.Out(Logs::Detail, Logs::Attack, "Invalid special attack type %d attempted", unchecked_type);
return(1000); /* nice long delay for them, the caller depends on this! */
}
@@ -663,7 +663,7 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime)
DoAnim(animPiercing);
}
// solar - assassinate [Kayen: No longer used for regular assassinate 6-29-14]
// assassinate [No longer used for regular assassinate 6-29-14]
void Mob::RogueAssassinate(Mob* other)
{
//can you dodge, parry, etc.. an assassinate??
@@ -683,7 +683,7 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) {
//make sure the attack and ranged timers are up
//if the ranged timer is disabled, then they have no ranged weapon and shouldent be attacking anyhow
if(!CanDoubleAttack && ((attack_timer.Enabled() && !attack_timer.Check(false)) || (ranged_timer.Enabled() && !ranged_timer.Check()))) {
mlog(COMBAT__RANGED, "Throwing attack canceled. Timer not up. Attack %d, ranged %d", attack_timer.GetRemainingTime(), ranged_timer.GetRemainingTime());
Log.Out(Logs::Detail, Logs::Combat, "Throwing attack canceled. Timer not up. Attack %d, ranged %d", attack_timer.GetRemainingTime(), ranged_timer.GetRemainingTime());
// The server and client timers are not exact matches currently, so this would spam too often if enabled
//Message(0, "Error: Timer not up. Attack %d, ranged %d", attack_timer.GetRemainingTime(), ranged_timer.GetRemainingTime());
return;
@@ -695,12 +695,12 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) {
const ItemInst* Ammo = m_inv[MainAmmo];
if (!RangeWeapon || !RangeWeapon->IsType(ItemClassCommon)) {
mlog(COMBAT__RANGED, "Ranged attack canceled. Missing or invalid ranged weapon (%d) in slot %d", GetItemIDAt(MainRange), MainRange);
Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Missing or invalid ranged weapon (%d) in slot %d", GetItemIDAt(MainRange), MainRange);
Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have no bow!", GetItemIDAt(MainRange));
return;
}
if (!Ammo || !Ammo->IsType(ItemClassCommon)) {
mlog(COMBAT__RANGED, "Ranged attack canceled. Missing or invalid ammo item (%d) in slot %d", GetItemIDAt(MainAmmo), MainAmmo);
Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Missing or invalid ammo item (%d) in slot %d", GetItemIDAt(MainAmmo), MainAmmo);
Message(0, "Error: Ammo: GetItem(%i)==0, you have no ammo!", GetItemIDAt(MainAmmo));
return;
}
@@ -709,17 +709,17 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) {
const Item_Struct* AmmoItem = Ammo->GetItem();
if(RangeItem->ItemType != ItemTypeBow) {
mlog(COMBAT__RANGED, "Ranged attack canceled. Ranged item is not a bow. type %d.", RangeItem->ItemType);
Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Ranged item is not a bow. type %d.", RangeItem->ItemType);
Message(0, "Error: Rangeweapon: Item %d is not a bow.", RangeWeapon->GetID());
return;
}
if(AmmoItem->ItemType != ItemTypeArrow) {
mlog(COMBAT__RANGED, "Ranged attack canceled. Ammo item is not an arrow. type %d.", AmmoItem->ItemType);
Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Ammo item is not an arrow. type %d.", AmmoItem->ItemType);
Message(0, "Error: Ammo: type %d != %d, you have the wrong type of ammo!", AmmoItem->ItemType, ItemTypeArrow);
return;
}
mlog(COMBAT__RANGED, "Shooting %s with bow %s (%d) and arrow %s (%d)", other->GetName(), RangeItem->Name, RangeItem->ID, AmmoItem->Name, AmmoItem->ID);
Log.Out(Logs::Detail, Logs::Combat, "Shooting %s with bow %s (%d) and arrow %s (%d)", other->GetName(), RangeItem->Name, RangeItem->ID, AmmoItem->Name, AmmoItem->ID);
//look for ammo in inventory if we only have 1 left...
if(Ammo->GetCharges() == 1) {
@@ -746,7 +746,7 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) {
Ammo = baginst;
ammo_slot = m_inv.CalcSlotId(r, i);
found = true;
mlog(COMBAT__RANGED, "Using ammo from quiver stack at slot %d. %d in stack.", ammo_slot, Ammo->GetCharges());
Log.Out(Logs::Detail, Logs::Combat, "Using ammo from quiver stack at slot %d. %d in stack.", ammo_slot, Ammo->GetCharges());
break;
}
}
@@ -761,17 +761,17 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) {
if (aslot != INVALID_INDEX) {
ammo_slot = aslot;
Ammo = m_inv[aslot];
mlog(COMBAT__RANGED, "Using ammo from inventory stack at slot %d. %d in stack.", ammo_slot, Ammo->GetCharges());
Log.Out(Logs::Detail, Logs::Combat, "Using ammo from inventory stack at slot %d. %d in stack.", ammo_slot, Ammo->GetCharges());
}
}
}
float range = RangeItem->Range + AmmoItem->Range + GetRangeDistTargetSizeMod(GetTarget());
mlog(COMBAT__RANGED, "Calculated bow range to be %.1f", range);
Log.Out(Logs::Detail, Logs::Combat, "Calculated bow range to be %.1f", range);
range *= range;
float dist = DistNoRoot(*other);
float dist = DistanceSquared(m_Position, other->GetPosition());
if(dist > range) {
mlog(COMBAT__RANGED, "Ranged attack out of range... client should catch this. (%f > %f).\n", dist, range);
Log.Out(Logs::Detail, Logs::Combat, "Ranged attack out of range... client should catch this. (%f > %f).\n", dist, range);
Message_StringID(13,TARGET_OUT_OF_RANGE);//Client enforces range and sends the message, this is a backup just incase.
return;
}
@@ -799,9 +799,9 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) {
if (!ChanceAvoidConsume || (ChanceAvoidConsume < 100 && zone->random.Int(0,99) > ChanceAvoidConsume)){
DeleteItemInInventory(ammo_slot, 1, true);
mlog(COMBAT__RANGED, "Consumed one arrow from slot %d", ammo_slot);
Log.Out(Logs::Detail, Logs::Combat, "Consumed one arrow from slot %d", ammo_slot);
} else {
mlog(COMBAT__RANGED, "Endless Quiver prevented ammo consumption.");
Log.Out(Logs::Detail, Logs::Combat, "Endless Quiver prevented ammo consumption.");
}
CheckIncreaseSkill(SkillArchery, GetTarget(), -15);
@@ -857,7 +857,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
if (IsClient()){
_RangeWeapon = CastToClient()->m_inv[MainRange];
if (_RangeWeapon && !_RangeWeapon->GetItem() && _RangeWeapon->GetItem()->ID == range_id)
if (_RangeWeapon && _RangeWeapon->GetItem() && _RangeWeapon->GetItem()->ID == range_id)
RangeWeapon = _RangeWeapon;
_Ammo = CastToClient()->m_inv[AmmoSlot];
@@ -873,7 +873,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
SendItemAnimation(other, AmmoItem, SkillArchery);
if (ProjectileMiss || (!ProjectileImpact && !other->CheckHitChance(this, SkillArchery, MainPrimary, chance_mod))) {
mlog(COMBAT__RANGED, "Ranged attack missed %s.", other->GetName());
Log.Out(Logs::Detail, Logs::Combat, "Ranged attack missed %s.", other->GetName());
if (LaunchProjectile){
TryProjectileAttack(other, AmmoItem, SkillArchery, 0, RangeWeapon, Ammo, AmmoSlot, speed);
@@ -882,7 +882,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
else
other->Damage(this, 0, SPELL_UNKNOWN, SkillArchery);
} else {
mlog(COMBAT__RANGED, "Ranged attack hit %s.", other->GetName());
Log.Out(Logs::Detail, Logs::Combat, "Ranged attack hit %s.", other->GetName());
bool HeadShot = false;
uint32 HeadShot_Dmg = TryHeadShot(other, SkillArchery);
@@ -923,7 +923,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
MaxDmg += MaxDmg*bonusArcheryDamageModifier / 100;
mlog(COMBAT__RANGED, "Bow DMG %d, Arrow DMG %d, Max Damage %d.", WDmg, ADmg, MaxDmg);
Log.Out(Logs::Detail, Logs::Combat, "Bow DMG %d, Arrow DMG %d, Max Damage %d.", WDmg, ADmg, MaxDmg);
bool dobonus = false;
if(GetClass() == RANGER && GetLevel() > 50){
@@ -944,7 +944,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
hate *= 2;
MaxDmg = mod_archery_bonus_damage(MaxDmg, RangeWeapon);
mlog(COMBAT__RANGED, "Ranger. Double damage success roll, doubling damage to %d", MaxDmg);
Log.Out(Logs::Detail, Logs::Combat, "Ranger. Double damage success roll, doubling damage to %d", MaxDmg);
Message_StringID(MT_CritMelee, BOW_DOUBLE_DAMAGE);
}
}
@@ -996,10 +996,10 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
}
if (LaunchProjectile)
return;//Shouldn't reach this point, but just in case.
return;//Shouldn't reach this point durring initial launch phase, but just in case.
//Weapon Proc
if(!RangeWeapon && other && !other->HasDied())
if(RangeWeapon && other && !other->HasDied())
TryWeaponProc(RangeWeapon, other, MainRange);
//Ammo Proc
@@ -1101,8 +1101,14 @@ void Mob::ProjectileAttack()
if (target){
if (IsNPC())
CastToNPC()->DoRangedAttackDmg(target, false, ProjectileAtk[i].wpn_dmg,0, static_cast<SkillUseTypes>(ProjectileAtk[i].skill));
if (IsNPC()){
if (ProjectileAtk[i].skill == SkillConjuration){
if (IsValidSpell(ProjectileAtk[i].wpn_dmg))
SpellOnTarget(ProjectileAtk[i].wpn_dmg, target, false, true, spells[ProjectileAtk[i].wpn_dmg].ResistDiff, true);
}
else
CastToNPC()->DoRangedAttackDmg(target, false, ProjectileAtk[i].wpn_dmg,0, static_cast<SkillUseTypes>(ProjectileAtk[i].skill));
}
else
{
@@ -1186,7 +1192,7 @@ void NPC::RangedAttack(Mob* other)
//make sure the attack and ranged timers are up
//if the ranged timer is disabled, then they have no ranged weapon and shouldent be attacking anyhow
if((attack_timer.Enabled() && !attack_timer.Check(false)) || (ranged_timer.Enabled() && !ranged_timer.Check())){
mlog(COMBAT__RANGED, "Archery canceled. Timer not up. Attack %d, ranged %d", attack_timer.GetRemainingTime(), ranged_timer.GetRemainingTime());
Log.Out(Logs::Detail, Logs::Combat, "Archery canceled. Timer not up. Attack %d, ranged %d", attack_timer.GetRemainingTime(), ranged_timer.GetRemainingTime());
return;
}
@@ -1213,9 +1219,9 @@ void NPC::RangedAttack(Mob* other)
min_range = static_cast<float>(sa_min_range);
max_range *= max_range;
if(DistNoRoot(*other) > max_range)
if(DistanceSquared(m_Position, other->GetPosition()) > max_range)
return;
else if(DistNoRoot(*other) < (min_range * min_range))
else if(DistanceSquared(m_Position, other->GetPosition()) < (min_range * min_range))
return;
if(!other || !IsAttackAllowed(other) ||
@@ -1355,7 +1361,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51
//make sure the attack and ranged timers are up
//if the ranged timer is disabled, then they have no ranged weapon and shouldent be attacking anyhow
if((!CanDoubleAttack && (attack_timer.Enabled() && !attack_timer.Check(false)) || (ranged_timer.Enabled() && !ranged_timer.Check()))) {
mlog(COMBAT__RANGED, "Throwing attack canceled. Timer not up. Attack %d, ranged %d", attack_timer.GetRemainingTime(), ranged_timer.GetRemainingTime());
Log.Out(Logs::Detail, Logs::Combat, "Throwing attack canceled. Timer not up. Attack %d, ranged %d", attack_timer.GetRemainingTime(), ranged_timer.GetRemainingTime());
// The server and client timers are not exact matches currently, so this would spam too often if enabled
//Message(0, "Error: Timer not up. Attack %d, ranged %d", attack_timer.GetRemainingTime(), ranged_timer.GetRemainingTime());
return;
@@ -1365,19 +1371,19 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51
const ItemInst* RangeWeapon = m_inv[MainRange];
if (!RangeWeapon || !RangeWeapon->IsType(ItemClassCommon)) {
mlog(COMBAT__RANGED, "Ranged attack canceled. Missing or invalid ranged weapon (%d) in slot %d", GetItemIDAt(MainRange), MainRange);
Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Missing or invalid ranged weapon (%d) in slot %d", GetItemIDAt(MainRange), MainRange);
Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have nothing to throw!", GetItemIDAt(MainRange));
return;
}
const Item_Struct* item = RangeWeapon->GetItem();
if(item->ItemType != ItemTypeLargeThrowing && item->ItemType != ItemTypeSmallThrowing) {
mlog(COMBAT__RANGED, "Ranged attack canceled. Ranged item %d is not a throwing weapon. type %d.", item->ItemType);
Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Ranged item %d is not a throwing weapon. type %d.", item->ItemType);
Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have nothing useful to throw!", GetItemIDAt(MainRange));
return;
}
mlog(COMBAT__RANGED, "Throwing %s (%d) at %s", item->Name, item->ID, other->GetName());
Log.Out(Logs::Detail, Logs::Combat, "Throwing %s (%d) at %s", item->Name, item->ID, other->GetName());
if(RangeWeapon->GetCharges() == 1) {
//first check ammo
@@ -1386,7 +1392,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51
//more in the ammo slot, use it
RangeWeapon = AmmoItem;
ammo_slot = MainAmmo;
mlog(COMBAT__RANGED, "Using ammo from ammo slot, stack at slot %d. %d in stack.", ammo_slot, RangeWeapon->GetCharges());
Log.Out(Logs::Detail, Logs::Combat, "Using ammo from ammo slot, stack at slot %d. %d in stack.", ammo_slot, RangeWeapon->GetCharges());
} else {
//look through our inventory for more
int32 aslot = m_inv.HasItem(item->ID, 1, invWherePersonal);
@@ -1394,17 +1400,17 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51
//the item wont change, but the instance does, not that it matters
ammo_slot = aslot;
RangeWeapon = m_inv[aslot];
mlog(COMBAT__RANGED, "Using ammo from inventory slot, stack at slot %d. %d in stack.", ammo_slot, RangeWeapon->GetCharges());
Log.Out(Logs::Detail, Logs::Combat, "Using ammo from inventory slot, stack at slot %d. %d in stack.", ammo_slot, RangeWeapon->GetCharges());
}
}
}
float range = item->Range + GetRangeDistTargetSizeMod(other);
mlog(COMBAT__RANGED, "Calculated bow range to be %.1f", range);
Log.Out(Logs::Detail, Logs::Combat, "Calculated bow range to be %.1f", range);
range *= range;
float dist = DistNoRoot(*other);
float dist = DistanceSquared(m_Position, other->GetPosition());
if(dist > range) {
mlog(COMBAT__RANGED, "Throwing attack out of range... client should catch this. (%f > %f).\n", dist, range);
Log.Out(Logs::Detail, Logs::Combat, "Throwing attack out of range... client should catch this. (%f > %f).\n", dist, range);
Message_StringID(13,TARGET_OUT_OF_RANGE);//Client enforces range and sends the message, this is a backup just incase.
return;
}
@@ -1483,7 +1489,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
SendItemAnimation(other, AmmoItem, SkillThrowing);
if (ProjectileMiss || (!ProjectileImpact && !other->CheckHitChance(this, SkillThrowing, MainPrimary, chance_mod))){
mlog(COMBAT__RANGED, "Ranged attack missed %s.", other->GetName());
Log.Out(Logs::Detail, Logs::Combat, "Ranged attack missed %s.", other->GetName());
if (LaunchProjectile){
TryProjectileAttack(other, AmmoItem, SkillThrowing, 0, RangeWeapon, nullptr, AmmoSlot, speed);
return;
@@ -1491,7 +1497,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
else
other->Damage(this, 0, SPELL_UNKNOWN, SkillThrowing);
} else {
mlog(COMBAT__RANGED, "Throwing attack hit %s.", other->GetName());
Log.Out(Logs::Detail, Logs::Combat, "Throwing attack hit %s.", other->GetName());
int16 WDmg = 0;
@@ -1527,7 +1533,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, ASSASSINATES, GetName());
}
mlog(COMBAT__RANGED, "Item DMG %d. Max Damage %d. Hit for damage %d", WDmg, MaxDmg, TotalDmg);
Log.Out(Logs::Detail, Logs::Combat, "Item DMG %d. Max Damage %d. Hit for damage %d", WDmg, MaxDmg, TotalDmg);
if (!Assassinate_Dmg)
other->AvoidDamage(this, TotalDmg, false); //CanRiposte=false - Can not riposte throw attacks.
+49 -47
View File
@@ -16,9 +16,10 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/eqemu_logsys.h"
#include "../common/bodytypes.h"
#include "../common/classes.h"
#include "../common/debug.h"
#include "../common/global_define.h"
#include "../common/item.h"
#include "../common/rulesys.h"
#include "../common/skills.h"
@@ -133,7 +134,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
if (spells[spell_id].EndurUpkeep > 0)
SetEndurUpkeep(true);
if(IsClient() && CastToClient()->GetClientVersionBit() & BIT_UnderfootAndLater)
if(IsClient() && CastToClient()->GetClientVersionBit() & BIT_UFAndLater)
{
EQApplicationPacket *outapp = MakeBuffsPacket(false);
CastToClient()->FastQueuePacket(&outapp);
@@ -368,8 +369,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
snprintf(effect_desc, _EDLEN, "Current Mana: %+i", effect_value);
#endif
SetMana(GetMana() + effect_value);
caster->SetMana(caster->GetMana() + abs(effect_value));
caster->SetMana(caster->GetMana() + std::abs(effect_value));
if (effect_value < 0)
TryTriggerOnValueAmount(false, true);
#ifdef SPELL_EFFECT_SPAM
@@ -475,7 +476,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
if(!target_zone) {
#ifdef SPELL_EFFECT_SPAM
LogFile->write(EQEMuLog::Debug, "Succor/Evacuation Spell In Same Zone.");
Log.Out(Logs::General, Logs::None, "Succor/Evacuation Spell In Same Zone.");
#endif
if(IsClient())
CastToClient()->MovePC(zone->GetZoneID(), zone->GetInstanceID(), x, y, z, heading, 0, EvacToSafeCoords);
@@ -484,7 +485,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
}
else {
#ifdef SPELL_EFFECT_SPAM
LogFile->write(EQEMuLog::Debug, "Succor/Evacuation Spell To Another Zone.");
Log.Out(Logs::General, Logs::None, "Succor/Evacuation Spell To Another Zone.");
#endif
if(IsClient())
CastToClient()->MovePC(target_zone, x, y, z, heading);
@@ -710,7 +711,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
stun_resist += aabonuses.StunResist;
if (stun_resist <= 0 || zone->random.Int(0,99) >= stun_resist) {
mlog(COMBAT__HITS, "Stunned. We had %d percent resist chance.", stun_resist);
Log.Out(Logs::Detail, Logs::Combat, "Stunned. We had %d percent resist chance.", stun_resist);
if (caster->IsClient())
effect_value += effect_value*caster->GetFocusEffect(focusFcStunTimeMod, spell_id)/100;
@@ -720,7 +721,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
if (IsClient())
Message_StringID(MT_Stun, SHAKE_OFF_STUN);
mlog(COMBAT__HITS, "Stun Resisted. We had %d percent resist chance.", stun_resist);
Log.Out(Logs::Detail, Logs::Combat, "Stun Resisted. We had %d percent resist chance.", stun_resist);
}
}
break;
@@ -1648,7 +1649,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
if (IsCorpse() && CastToCorpse()->IsPlayerCorpse()) {
if(caster)
mlog(SPELLS__REZ, " corpse being rezzed using spell %i by %s",
Log.Out(Logs::Detail, Logs::Spells, " corpse being rezzed using spell %i by %s",
spell_id, caster->GetName());
CastToCorpse()->CastRezz(spell_id, caster);
@@ -1771,7 +1772,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
}
else {
Message_StringID(4, TARGET_NOT_FOUND);
LogFile->write(EQEMuLog::Error, "%s attempted to cast spell id %u with spell effect SE_SummonCorpse, but could not cast target into a Client object.", GetCleanName(), spell_id);
Log.Out(Logs::General, Logs::Error, "%s attempted to cast spell id %u with spell effect SE_SummonCorpse, but could not cast target into a Client object.", GetCleanName(), spell_id);
}
}
@@ -3064,7 +3065,7 @@ int Mob::CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level,
int mod = caster->GetInstrumentMod(spell_id);
mod = ApplySpellEffectiveness(caster, spell_id, mod, true);
effect_value = effect_value * mod / 10;
mlog(SPELLS__BARDS, "Effect value %d altered with bard modifier of %d to yeild %d", oval, mod, effect_value);
Log.Out(Logs::Detail, Logs::Spells, "Effect value %d altered with bard modifier of %d to yeild %d", oval, mod, effect_value);
}
effect_value = mod_effect_value(effect_value, spell_id, spells[spell_id].effectid[effect_id], caster);
@@ -3126,7 +3127,7 @@ snare has both of them negative, yet their range should work the same:
updownsign = 1;
}
mlog(SPELLS__EFFECT_VALUES, "CSEV: spell %d, formula %d, base %d, max %d, lvl %d. Up/Down %d",
Log.Out(Logs::Detail, Logs::Spells, "CSEV: spell %d, formula %d, base %d, max %d, lvl %d. Up/Down %d",
spell_id, formula, base, max, caster_level, updownsign);
switch(formula)
@@ -3210,7 +3211,7 @@ snare has both of them negative, yet their range should work the same:
break;
}
case 123: // added 2/6/04
result = zone->random.Int(ubase, abs(max));
result = zone->random.Int(ubase, std::abs(max));
break;
case 124: // check sign
@@ -3325,7 +3326,7 @@ snare has both of them negative, yet their range should work the same:
result = ubase * (caster_level * (formula - 2000) + 1);
}
else
LogFile->write(EQEMuLog::Debug, "Unknown spell effect value forumula %d", formula);
Log.Out(Logs::General, Logs::None, "Unknown spell effect value forumula %d", formula);
}
}
@@ -3350,7 +3351,7 @@ snare has both of them negative, yet their range should work the same:
if (base < 0 && result > 0)
result *= -1;
mlog(SPELLS__EFFECT_VALUES, "Result: %d (orig %d), cap %d %s", result, oresult, max, (base < 0 && result > 0)?"Inverted due to negative base":"");
Log.Out(Logs::Detail, Logs::Spells, "Result: %d (orig %d), cap %d %s", result, oresult, max, (base < 0 && result > 0)?"Inverted due to negative base":"");
return result;
}
@@ -3382,18 +3383,18 @@ void Mob::BuffProcess()
IsMezSpell(buffs[buffs_i].spellid) ||
IsBlindSpell(buffs[buffs_i].spellid))
{
mlog(SPELLS__BUFFS, "Buff %d in slot %d has expired. Fading.", buffs[buffs_i].spellid, buffs_i);
Log.Out(Logs::Detail, Logs::Spells, "Buff %d in slot %d has expired. Fading.", buffs[buffs_i].spellid, buffs_i);
BuffFadeBySlot(buffs_i);
}
}
else if (buffs[buffs_i].ticsremaining < 0)
{
mlog(SPELLS__BUFFS, "Buff %d in slot %d has expired. Fading.", buffs[buffs_i].spellid, buffs_i);
Log.Out(Logs::Detail, Logs::Spells, "Buff %d in slot %d has expired. Fading.", buffs[buffs_i].spellid, buffs_i);
BuffFadeBySlot(buffs_i);
}
else
{
mlog(SPELLS__BUFFS, "Buff %d in slot %d has %d tics remaining.", buffs[buffs_i].spellid, buffs_i, buffs[buffs_i].ticsremaining);
Log.Out(Logs::Detail, Logs::Spells, "Buff %d in slot %d has %d tics remaining.", buffs[buffs_i].spellid, buffs_i, buffs[buffs_i].ticsremaining);
}
}
else if(IsClient() && !(CastToClient()->GetClientVersionBit() & BIT_SoFAndLater))
@@ -3408,7 +3409,7 @@ void Mob::BuffProcess()
{
CastToClient()->SendBuffDurationPacket(buffs[buffs_i]);
// Hack to get UF to play nicer, RoF seems fine without it
if (CastToClient()->GetClientVersion() == EQClientUnderfoot && buffs[buffs_i].numhits > 0)
if (CastToClient()->GetClientVersion() == ClientVersion::UF && buffs[buffs_i].numhits > 0)
CastToClient()->SendBuffNumHitPacket(buffs[buffs_i], buffs_i);
buffs[buffs_i].UpdateClient = false;
}
@@ -3471,14 +3472,16 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste
{
effect_value = CalcSpellEffectValue(spell_id, i, caster_level, caster, ticsremaining);
//Handle client cast DOTs here.
if (caster && effect_value < 0 && IsDetrimentalSpell(spell_id)){
if (caster && effect_value < 0){
if (caster->IsClient()){
if (!caster->CastToClient()->GetFeigned())
if (IsDetrimentalSpell(spell_id)){
if (caster->IsClient()){
if (!caster->CastToClient()->GetFeigned())
AddToHateList(caster, -effect_value);
}
else if (!IsClient()) //Allow NPC's to generate hate if casted on other NPC's.
AddToHateList(caster, -effect_value);
}
else if (!IsClient()) //Allow NPC's to generate hate if casted on other NPC's.
AddToHateList(caster, -effect_value);
effect_value = caster->GetActDoTDamage(spell_id, effect_value, this);
@@ -3583,7 +3586,7 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste
}
case SE_Charm: {
if (!caster || !PassCharismaCheck(caster, this, spell_id)) {
if (!caster || !PassCharismaCheck(caster, spell_id)) {
BuffFadeByEffect(SE_Charm);
}
@@ -3758,7 +3761,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
if (IsClient() && !CastToClient()->IsDead())
CastToClient()->MakeBuffFadePacket(buffs[slot].spellid, slot);
mlog(SPELLS__BUFFS, "Fading buff %d from slot %d", buffs[slot].spellid, slot);
Log.Out(Logs::Detail, Logs::Spells, "Fading buff %d from slot %d", buffs[slot].spellid, slot);
if(spells[buffs[slot].spellid].viral_targets > 0) {
bool last_virus = true;
@@ -4172,7 +4175,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
safe_delete(outapp);
}
if(IsClient() && CastToClient()->GetClientVersionBit() & BIT_UnderfootAndLater)
if(IsClient() && CastToClient()->GetClientVersionBit() & BIT_UFAndLater)
{
EQApplicationPacket *outapp = MakeBuffsPacket(false);
CastToClient()->FastQueuePacket(&outapp);
@@ -4816,7 +4819,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
return 0;
break;
default:
LogFile->write(EQEMuLog::Normal, "CalcFocusEffect: unknown limit spelltype %d", focus_spell.base[i]);
Log.Out(Logs::General, Logs::Normal, "CalcFocusEffect: unknown limit spelltype %d", focus_spell.base[i]);
}
break;
@@ -5155,7 +5158,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
//this spits up a lot of garbage when calculating spell focuses
//since they have all kinds of extra effects on them.
default:
LogFile->write(EQEMuLog::Normal, "CalcFocusEffect: unknown effectid %d", focus_spell.effectid[i]);
Log.Out(Logs::General, Logs::Normal, "CalcFocusEffect: unknown effectid %d", focus_spell.effectid[i]);
#endif
}
@@ -5643,7 +5646,7 @@ int16 NPC::GetFocusEffect(focusType type, uint16 spell_id) {
return realTotal + realTotal2;
}
void Mob::CheckNumHitsRemaining(uint8 type, int32 buff_slot, uint16 spell_id)
void Mob::CheckNumHitsRemaining(NumHit type, int32 buff_slot, uint16 spell_id)
{
/*
Field 175 = numhits type
@@ -5670,7 +5673,7 @@ void Mob::CheckNumHitsRemaining(uint8 type, int32 buff_slot, uint16 spell_id)
if (IsValidSpell(spell_id)) {
for (int d = 0; d < buff_max; d++) {
if (buffs[d].spellid == spell_id && buffs[d].numhits > 0 &&
spells[buffs[d].spellid].numhitstype == type) {
spells[buffs[d].spellid].numhitstype == static_cast<int>(type)) {
if (--buffs[d].numhits == 0) {
CastOnNumHitFade(buffs[d].spellid);
if (!TryFadeEffect(d))
@@ -5680,7 +5683,7 @@ void Mob::CheckNumHitsRemaining(uint8 type, int32 buff_slot, uint16 spell_id)
}
}
}
} else if (type == NUMHIT_MatchingSpells) {
} else if (type == NumHit::MatchingSpells) {
if (buff_slot >= 0) {
if (--buffs[buff_slot].numhits == 0) {
CastOnNumHitFade(buffs[buff_slot].spellid);
@@ -5709,7 +5712,7 @@ void Mob::CheckNumHitsRemaining(uint8 type, int32 buff_slot, uint16 spell_id)
} else {
for (int d = 0; d < buff_max; d++) {
if (IsValidSpell(buffs[d].spellid) && buffs[d].numhits > 0 &&
spells[buffs[d].spellid].numhitstype == type) {
spells[buffs[d].spellid].numhitstype == static_cast<int>(type)) {
if (--buffs[d].numhits == 0) {
CastOnNumHitFade(buffs[d].spellid);
if (!TryFadeEffect(d))
@@ -5973,7 +5976,7 @@ int32 Mob::GetFcDamageAmtIncoming(Mob *caster, uint32 spell_id, bool use_skill,
}
if ((!limit_exists) || (limit_exists && skill_found)){
dmg += temp_dmg;
CheckNumHitsRemaining(NUMHIT_MatchingSpells,i);
CheckNumHitsRemaining(NumHit::MatchingSpells, i);
}
}
@@ -5981,7 +5984,7 @@ int32 Mob::GetFcDamageAmtIncoming(Mob *caster, uint32 spell_id, bool use_skill,
int32 focus = caster->CalcFocusEffect(focusFcDamageAmtIncoming, buffs[i].spellid, spell_id);
if(focus){
dmg += focus;
CheckNumHitsRemaining(NUMHIT_MatchingSpells,i);
CheckNumHitsRemaining(NumHit::MatchingSpells, i);
}
}
}
@@ -6033,7 +6036,7 @@ int32 Mob::GetFocusIncoming(focusType type, int effect, Mob *caster, uint32 spel
value = tmp_focus;
if (tmp_buffslot >= 0)
CheckNumHitsRemaining(NUMHIT_MatchingSpells, tmp_buffslot);
CheckNumHitsRemaining(NumHit::MatchingSpells, tmp_buffslot);
}
@@ -6568,33 +6571,32 @@ bool Mob::TrySpellProjectile(Mob* spell_target, uint16 spell_id, float speed){
DoAnim(anim, 0, true, IsClient() ? FilterPCSpells : FilterNPCSpells); //Override the default projectile animation.
return true;
}
}
void Mob::ResourceTap(int32 damage, uint16 spellid){
void Mob::ResourceTap(int32 damage, uint16 spellid)
{
//'this' = caster
if (!IsValidSpell(spellid))
return;
for (int i = 0; i <= EFFECT_COUNT; i++)
{
if (spells[spellid].effectid[i] == SE_ResourceTap){
damage += (damage * spells[spellid].base[i])/100;
for (int i = 0; i < EFFECT_COUNT; i++) {
if (spells[spellid].effectid[i] == SE_ResourceTap) {
damage += (damage * spells[spellid].base[i]) / 100;
if (spells[spellid].max[i] && (damage > spells[spellid].max[i]))
damage = spells[spellid].max[i];
if (spells[spellid].base2[i] == 0){ //HP Tap
if (spells[spellid].base2[i] == 0) { // HP Tap
if (damage > 0)
HealDamage(damage);
else
Damage(this, -damage,0, SkillEvocation,false);
Damage(this, -damage, 0, SkillEvocation, false);
}
if (spells[spellid].base2[i] == 1) //Mana Tap
if (spells[spellid].base2[i] == 1) // Mana Tap
SetMana(GetMana() + damage);
if (spells[spellid].base2[i] == 2 && IsClient()) //Endurance Tap
if (spells[spellid].base2[i] == 2 && IsClient()) // Endurance Tap
CastToClient()->SetEndurance(CastToClient()->GetEndurance() + damage);
}
}
+261 -239
View File
File diff suppressed because it is too large Load Diff
+132 -153
View File
File diff suppressed because it is too large Load Diff
+2 -9
View File
@@ -40,7 +40,6 @@ bool TitleManager::LoadTitles()
"`status`, `item_id`, `prefix`, `suffix`, `title_set` FROM titles";
auto results = database.QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Unable to load titles: %s : %s", query.c_str(), results.ErrorMessage().c_str());
return false;
}
@@ -263,7 +262,6 @@ void TitleManager::CreateNewPlayerTitle(Client *client, const char *title)
safe_delete_array(escTitle);
results = database.QueryDatabase(query);
if(!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error adding title: %s %s", query.c_str(), results.ErrorMessage().c_str());
return;
}
@@ -296,7 +294,6 @@ void TitleManager::CreateNewPlayerSuffix(Client *client, const char *suffix)
safe_delete_array(escSuffix);
results = database.QueryDatabase(query);
if(!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error adding title suffix: %s %s", query.c_str(), results.ErrorMessage().c_str());
return;
}
@@ -351,7 +348,7 @@ void Client::EnableTitle(int titleSet) {
CharacterID(), titleSet);
auto results = database.QueryDatabase(query);
if(!results.Success())
LogFile->write(EQEMuLog::Error, "Error in EnableTitle query for titleset %i and charid %i", titleSet, CharacterID());
Log.Out(Logs::General, Logs::Error, "Error in EnableTitle query for titleset %i and charid %i", titleSet, CharacterID());
}
@@ -362,7 +359,6 @@ bool Client::CheckTitle(int titleSet) {
titleSet, CharacterID());
auto results = database.QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in CheckTitle query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
return false;
}
@@ -380,9 +376,6 @@ void Client::RemoveTitle(int titleSet) {
std::string query = StringFormat("DELETE FROM player_titlesets "
"WHERE `title_set` = %i AND `char_id` = %i",
titleSet, CharacterID());
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Error in RemoveTitle query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
database.QueryDatabase(query);
}

Some files were not shown because too many files have changed in this diff Show More