Merge and fix the loot update branch, ready for merge I think

This commit is contained in:
KimLS
2015-02-04 23:13:02 -08:00
738 changed files with 82418 additions and 58480 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
@@ -110,13 +110,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
@@ -129,7 +129,6 @@ SET(zone_headers
bot.h
bot_structs.h
client.h
client_logs.h
client_packet.h
command.h
common.h
@@ -182,6 +181,7 @@ SET(zone_headers
perlpacket.h
petitions.h
pets.h
position.h
qglobals.h
quest_interface.h
queryserv.h
+361 -250
View File
@@ -16,84 +16,34 @@ Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net)
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
// Test 1
#include <iostream>
#include "../common/debug.h"
#include "aa.h"
#include "mob.h"
#include "client.h"
#include "groups.h"
#include "raids.h"
#include "../common/spdat.h"
#include "object.h"
#include "doors.h"
#include "beacon.h"
#include "corpse.h"
#include "titles.h"
#include "../common/races.h"
#include "../common/classes.h"
#include "../common/global_define.h"
#include "../common/eqemu_logsys.h"
#include "../common/eq_packet_structs.h"
#include "../common/packet_dump.h"
#include "../common/races.h"
#include "../common/spdat.h"
#include "../common/string_util.h"
#include "../common/logsys.h"
#include "zonedb.h"
#include "string_ids.h"
#include "aa.h"
#include "client.h"
#include "corpse.h"
#include "groups.h"
#include "mob.h"
#include "queryserv.h"
#include "raids.h"
#include "string_ids.h"
#include "titles.h"
#include "zonedb.h"
extern QueryServ* QServ;
//static data arrays, really not big enough to warrant shared mem.
AA_DBAction AA_Actions[aaHighestID][MAX_AA_ACTION_RANKS]; //[aaid][rank]
std::map<uint32,SendAA_Struct*>aas_send;
std::map<uint32, std::map<uint32, AA_Ability> > aa_effects; //stores the effects from the aa_effects table in memory
std::map<uint32, AALevelCost_Struct> AARequiredLevelAndCost;
/*
Schema:
spell_id is spell to cast, SPELL_UNKNOWN == no spell
nonspell_action is action to preform on activation which is not a spell, 0=none
nonspell_mana is mana that the nonspell action consumes
nonspell_duration is a duration which may be used by the nonspell action
redux_aa is the aa which reduces the reuse timer of the skill
redux_rate is the multiplier of redux_aa, as a percentage of total rate (10 == 10% faster)
CREATE TABLE aa_actions (
aaid mediumint unsigned not null,
rank tinyint unsigned not null,
reuse_time mediumint unsigned not null,
spell_id mediumint unsigned not null,
target tinyint unsigned not null,
nonspell_action tinyint unsigned not null,
nonspell_mana mediumint unsigned not null,
nonspell_duration mediumint unsigned not null,
redux_aa mediumint unsigned not null,
redux_rate tinyint not null,
PRIMARY KEY(aaid, rank)
);
CREATE TABLE aa_swarmpets (
spell_id mediumint unsigned not null,
count tinyint unsigned not null,
npc_id int not null,
duration mediumint unsigned not null,
PRIMARY KEY(spell_id)
);
*/
/*
Credits for this function:
-FatherNitwit: Structure and mechanism
-Wiz: Initial set of AAs, original function contents
-Branks: Much updated info and a bunch of higher-numbered AAs
*/
int Client::GetAATimerID(aaID activate)
{
SendAA_Struct* aa2 = zone->FindAA(activate);
@@ -319,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 */
@@ -495,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;
}
@@ -542,10 +492,7 @@ void Client::HandleAAAction(aaID activate) {
}
}
//Originally written by Branks
//functionality rewritten by Father Nitwit
void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, uint32 duration_override) {
void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, uint32 duration_override, bool followme, bool sticktarg) {
//It might not be a bad idea to put these into the database, eventually..
@@ -554,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;
}
@@ -563,7 +510,7 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u
pet.count = 1;
pet.duration = 1;
for(int x = 0; x < 12; x++)
for(int x = 0; x < MAX_SWARM_PETS; x++)
{
if(spells[spell_id].effectid[x] == SE_TemporaryPets)
{
@@ -572,8 +519,7 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u
}
}
if(IsClient())
pet.duration += (CastToClient()->GetFocusEffect(focusSwarmPetDuration, spell_id) / 1000);
pet.duration += GetFocusEffect(focusSwarmPetDuration, spell_id) / 1000;
pet.npc_id = record.npc_type;
@@ -582,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;
}
@@ -601,13 +547,11 @@ 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 };
TempPets(true);
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;
@@ -625,10 +569,10 @@ 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((spell_id == 6882) || (spell_id == 6884))
if (followme)
npca->SetFollowID(GetID());
if(!npca->GetSwarmInfo()){
@@ -646,7 +590,10 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u
//give the pets somebody to "love"
if(targ != nullptr){
npca->AddToHateList(targ, 1000, 1000);
npca->GetSwarmInfo()->target = targ->GetID();
if (RuleB(Spells, SwarmPetTargetLock) || sticktarg)
npca->GetSwarmInfo()->target = targ->GetID();
else
npca->GetSwarmInfo()->target = 0;
}
//we allocated a new NPC type object, give the NPC ownership of that memory
@@ -660,9 +607,12 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u
//the target of these swarm pets will take offense to being cast on...
if(targ != nullptr)
targ->AddToHateList(this, 1, 0);
// The other pointers we make are handled elsewhere.
delete made_npc;
}
void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_override, uint32 duration_override, bool followme) {
void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_override, uint32 duration_override, bool followme, bool sticktarg) {
AA_SwarmPet pet;
pet.count = 1;
@@ -675,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;
}
@@ -694,13 +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 };
TempPets(true);
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;
@@ -718,8 +666,11 @@ 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());
if(!npca->GetSwarmInfo()){
AA_SwarmPetInfo* nSI = new AA_SwarmPetInfo;
@@ -736,7 +687,11 @@ void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_overrid
//give the pets somebody to "love"
if(targ != nullptr){
npca->AddToHateList(targ, 1000, 1000);
npca->GetSwarmInfo()->target = targ->GetID();
if (RuleB(Spells, SwarmPetTargetLock) || sticktarg)
npca->GetSwarmInfo()->target = targ->GetID();
else
npca->GetSwarmInfo()->target = 0;
}
//we allocated a new NPC type object, give the NPC ownership of that memory
@@ -746,6 +701,9 @@ void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_overrid
entity_list.AddNPC(npca, true, true);
summon_count--;
}
// The other pointers we make are handled elsewhere.
delete made_npc;
}
void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration)
@@ -892,12 +850,10 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration)
make_npc->loottable_id = 0;
make_npc->merchanttype = 0;
make_npc->d_meele_texture1 = 0;
make_npc->d_meele_texture2 = 0;
make_npc->d_melee_texture1 = 0;
make_npc->d_melee_texture2 = 0;
TempPets(true);
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;
@@ -942,7 +898,7 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration)
//turn on an AA effect
//duration == 0 means no time limit, used for one-shot deals, etc..
void Client::EnableAAEffect(aaEffectType type, uint32 duration) {
if(type > 32)
if(type > _maxaaEffectType)
return; //for now, special logic needed.
m_epp.aa_effects |= 1 << (type-1);
@@ -954,7 +910,7 @@ void Client::EnableAAEffect(aaEffectType type, uint32 duration) {
}
void Client::DisableAAEffect(aaEffectType type) {
if(type > 32)
if(type > _maxaaEffectType)
return; //for now, special logic needed.
uint32 bit = 1 << (type-1);
if(m_epp.aa_effects & bit) {
@@ -968,7 +924,7 @@ By default an AA effect is a one shot deal, unless
a duration timer is set.
*/
bool Client::CheckAAEffect(aaEffectType type) {
if(type > 32)
if(type > _maxaaEffectType)
return(false); //for now, special logic needed.
if(m_epp.aa_effects & (1 << (type-1))) { //is effect enabled?
//has our timer expired?
@@ -994,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);
@@ -1006,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;
@@ -1023,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;
}
@@ -1036,25 +992,32 @@ void Client::BuyAA(AA_Action* action)
}
uint32 real_cost;
uint8 req_level;
std::map<uint32, AALevelCost_Struct>::iterator RequiredLevel = AARequiredLevelAndCost.find(action->ability);
if(RequiredLevel != AARequiredLevelAndCost.end()) {
real_cost = RequiredLevel->second.Cost;
req_level = RequiredLevel->second.Level;
}
else
else {
real_cost = aa2->cost + (aa2->cost_inc * cur_level);
req_level = aa2->class_type + (aa2->level_inc * cur_level);
}
if (req_level > GetLevel())
return; //Cheater trying to Buy AA...
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)){
@@ -1075,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);
@@ -1465,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;
}
@@ -1483,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() {
@@ -1496,44 +1459,43 @@ 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;
}
void Client::ResetAA(){
RefundAA();
RefundAA();
uint32 i;
for(i=0;i<MAX_PP_AA_ARRAY;i++){
for (i=0; i < MAX_PP_AA_ARRAY; i++) {
aa[i]->AA = 0;
aa[i]->value = 0;
m_pp.aa_array[MAX_PP_AA_ARRAY].AA = 0;
m_pp.aa_array[MAX_PP_AA_ARRAY].value = 0;
m_pp.aa_array[MAX_PP_AA_ARRAY].value = 0;
}
std::map<uint32,uint8>::iterator itr;
for(itr=aa_points.begin();itr!=aa_points.end();++itr)
for(itr = aa_points.begin(); itr != aa_points.end(); ++itr)
aa_points[itr->first] = 0;
for(int i = 0; i < _maxLeaderAA; ++i)
for(int i = 0; i < _maxLeaderAA; ++i)
m_pp.leader_abilities.ranks[i] = 0;
m_pp.group_leadership_points = 0;
@@ -1542,14 +1504,62 @@ void Client::ResetAA(){
m_pp.raid_leadership_exp = 0;
database.DeleteCharacterAAs(this->CharacterID());
SaveAA();
SaveAA();
SendClearAA();
SendAAList();
SendAATable();
SendAAStats();
database.DeleteCharacterLeadershipAAs(this->CharacterID());
Kick();
// undefined for these clients
if (GetClientVersionBit() & BIT_TitaniumAndEarlier)
Kick();
}
void Client::SendClearAA()
{
EQApplicationPacket *outapp = new EQApplicationPacket(OP_ClearLeadershipAbilities, 0);
FastQueuePacket(&outapp);
outapp = new EQApplicationPacket(OP_ClearAA, 0);
FastQueuePacket(&outapp);
}
int Client::GroupLeadershipAAHealthEnhancement()
{
if (IsRaidGrouped()) {
int bonus = 0;
Raid *raid = GetRaid();
if (!raid)
return 0;
uint32 group_id = raid->GetGroup(this);
if (group_id < 12 && raid->GroupCount(group_id) >= 3) {
switch (raid->GetLeadershipAA(groupAAHealthEnhancement, group_id)) {
case 1:
bonus = 30;
break;
case 2:
bonus = 60;
break;
case 3:
bonus = 100;
break;
}
}
if (raid->RaidCount() >= 18) {
switch (raid->GetLeadershipAA(raidAAHealthEnhancement)) {
case 1:
bonus += 30;
break;
case 2:
bonus += 60;
break;
case 3:
bonus += 100;
break;
}
}
return bonus;
}
Group *g = GetGroup();
if(!g || (g->GroupCount() < 3))
@@ -1572,6 +1582,41 @@ int Client::GroupLeadershipAAHealthEnhancement()
int Client::GroupLeadershipAAManaEnhancement()
{
if (IsRaidGrouped()) {
int bonus = 0;
Raid *raid = GetRaid();
if (!raid)
return 0;
uint32 group_id = raid->GetGroup(this);
if (group_id < 12 && raid->GroupCount(group_id) >= 3) {
switch (raid->GetLeadershipAA(groupAAManaEnhancement, group_id)) {
case 1:
bonus = 30;
break;
case 2:
bonus = 60;
break;
case 3:
bonus = 100;
break;
}
}
if (raid->RaidCount() >= 18) {
switch (raid->GetLeadershipAA(raidAAManaEnhancement)) {
case 1:
bonus += 30;
break;
case 2:
bonus += 60;
break;
case 3:
bonus += 100;
break;
}
}
return bonus;
}
Group *g = GetGroup();
if(!g || (g->GroupCount() < 3))
@@ -1594,6 +1639,41 @@ int Client::GroupLeadershipAAManaEnhancement()
int Client::GroupLeadershipAAHealthRegeneration()
{
if (IsRaidGrouped()) {
int bonus = 0;
Raid *raid = GetRaid();
if (!raid)
return 0;
uint32 group_id = raid->GetGroup(this);
if (group_id < 12 && raid->GroupCount(group_id) >= 3) {
switch (raid->GetLeadershipAA(groupAAHealthRegeneration, group_id)) {
case 1:
bonus = 4;
break;
case 2:
bonus = 6;
break;
case 3:
bonus = 8;
break;
}
}
if (raid->RaidCount() >= 18) {
switch (raid->GetLeadershipAA(raidAAHealthRegeneration)) {
case 1:
bonus += 4;
break;
case 2:
bonus += 6;
break;
case 3:
bonus += 8;
break;
}
}
return bonus;
}
Group *g = GetGroup();
if(!g || (g->GroupCount() < 3))
@@ -1616,6 +1696,53 @@ int Client::GroupLeadershipAAHealthRegeneration()
int Client::GroupLeadershipAAOffenseEnhancement()
{
if (IsRaidGrouped()) {
int bonus = 0;
Raid *raid = GetRaid();
if (!raid)
return 0;
uint32 group_id = raid->GetGroup(this);
if (group_id < 12 && raid->GroupCount(group_id) >= 3) {
switch (raid->GetLeadershipAA(groupAAOffenseEnhancement, group_id)) {
case 1:
bonus = 10;
break;
case 2:
bonus = 19;
break;
case 3:
bonus = 28;
break;
case 4:
bonus = 34;
break;
case 5:
bonus = 40;
break;
}
}
if (raid->RaidCount() >= 18) {
switch (raid->GetLeadershipAA(raidAAOffenseEnhancement)) {
case 1:
bonus += 10;
break;
case 2:
bonus += 19;
break;
case 3:
bonus += 28;
break;
case 4:
bonus += 34;
break;
case 5:
bonus += 40;
break;
}
}
return bonus;
}
Group *g = GetGroup();
if(!g || (g->GroupCount() < 3))
@@ -1641,29 +1768,26 @@ int Client::GroupLeadershipAAOffenseEnhancement()
void Client::InspectBuffs(Client* Inspector, int Rank)
{
if(!Inspector || (Rank == 0)) return;
// At some point the removed the restriction of being a group member for this to work
// not sure when, but the way it's coded now, it wouldn't work with mobs.
if (!Inspector || Rank == 0)
return;
EQApplicationPacket *outapp = new EQApplicationPacket(OP_InspectBuffs, sizeof(InspectBuffs_Struct));
InspectBuffs_Struct *ib = (InspectBuffs_Struct *)outapp->pBuffer;
Inspector->Message_StringID(0, CURRENT_SPELL_EFFECTS, GetName());
uint32 buff_count = GetMaxTotalSlots();
for (uint32 i = 0; i < buff_count; ++i)
{
if (buffs[i].spellid != SPELL_UNKNOWN)
{
if(Rank == 1)
Inspector->Message(0, "%s", spells[buffs[i].spellid].name);
else
{
if (spells[buffs[i].spellid].buffdurationformula == DF_Permanent)
Inspector->Message(0, "%s (Permanent)", spells[buffs[i].spellid].name);
else {
char *TempString = nullptr;
MakeAnyLenString(&TempString, "%.1f", static_cast<float>(buffs[i].ticsremaining) / 10.0f);
Inspector->Message_StringID(0, BUFF_MINUTES_REMAINING, spells[buffs[i].spellid].name, TempString);
safe_delete_array(TempString);
}
}
}
uint32 packet_index = 0;
for (uint32 i = 0; i < buff_count; i++) {
if (buffs[i].spellid == SPELL_UNKNOWN)
continue;
ib->spell_id[packet_index] = buffs[i].spellid;
if (Rank > 1)
ib->tics_remaining[packet_index] = spells[buffs[i].spellid].buffdurationformula == DF_Permanent ? 0xFFFFFFFF : buffs[i].ticsremaining;
packet_index++;
}
Inspector->FastQueuePacket(&outapp);
}
//this really need to be renamed to LoadAAActions()
@@ -1671,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;
}
@@ -1714,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]);
}
@@ -1751,19 +1873,15 @@ void ZoneDatabase::FillAAEffects(SendAA_Struct* aa_struct){
if(!aa_struct)
return;
std::string query = StringFormat("SELECT effectid, base1, base2, slot from aa_effects where aaid=%i order by slot asc", aa_struct->id);
auto results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in Client::FillAAEffects query: '%s': %s", query.c_str(), results.ErrorMessage().c_str());
return;
}
int index = 0;
for (auto row = results.begin(); row != results.end(); ++row, ++index) {
aa_struct->abilities[index].skill_id=atoi(row[0]);
aa_struct->abilities[index].base1=atoi(row[1]);
aa_struct->abilities[index].base2=atoi(row[2]);
aa_struct->abilities[index].slot=atoi(row[3]);
auto it = aa_effects.find(aa_struct->id);
if (it != aa_effects.end()) {
for (uint32 slot = 0; slot < aa_struct->total_abilities; slot++) {
// aa_effects is a map of a map, so the slot reference does not start at 0
aa_struct->abilities[slot].skill_id = it->second[slot + 1].skill_id;
aa_struct->abilities[slot].base1 = it->second[slot + 1].base1;
aa_struct->abilities[slot].base2 = it->second[slot + 1].base2;
aa_struct->abilities[slot].slot = it->second[slot + 1].slot;
}
}
}
@@ -1772,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]);;
}
@@ -1789,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]);
}
@@ -1822,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);
@@ -1889,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;
+6 -2
View File
@@ -2,7 +2,9 @@
#ifndef AA_H
#define AA_H
#include "../common/eq_packet_structs.h"
struct AA_Ability;
struct SendAA_Struct;
#define MANA_BURN 664
@@ -50,7 +52,8 @@ typedef enum { //AA Effect IDs
aaEffectFrostArrows,
aaEffectWarcry,
aaEffectLeechTouch,
aaEffectProjectIllusion // unused - Handled via spell effect
aaEffectProjectIllusion, // unused - Handled via spell effect
_maxaaEffectType = 32
} aaEffectType;
@@ -2153,6 +2156,7 @@ enum { //values of AA_Action.action
};
class Timer;
class Mob;
class AA_SwarmPetInfo {
public:
AA_SwarmPetInfo();
+55 -54
View File
@@ -15,18 +15,23 @@
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 <stdlib.h>
#include <math.h>
#include "masterentity.h"
#include "../common/global_define.h"
#include "../common/eqemu_logsys.h"
#include "../common/faction.h"
#include "map.h"
#include "../common/spdat.h"
#include "../common/skills.h"
#include "../common/misc_functions.h"
#include "../common/rulesys.h"
#include "string_ids.h"
#include <iostream>
#include "../common/spdat.h"
#include "client.h"
#include "corpse.h"
#include "entity.h"
#include "mob.h"
#ifdef BOTS
#include "bot.h"
#endif
#include "map.h"
extern Zone* zone;
//#define LOSDEBUG 6
@@ -84,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) {
@@ -146,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(),
@@ -291,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 ) {
@@ -329,7 +335,7 @@ bool Mob::CheckWillAggro(Mob *mob) {
||
(
fv == FACTION_THREATENLY
&& MakeRandomInt(0,99) < THREATENLY_ARRGO_CHANCE - heroicCHA_mod
&& zone->random.Roll(THREATENLY_ARRGO_CHANCE - heroicCHA_mod)
)
)
)
@@ -337,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);
}
@@ -409,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++;
@@ -439,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
@@ -465,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);
}
@@ -477,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
@@ -546,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.
@@ -692,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
@@ -713,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
@@ -832,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;
}
@@ -873,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)){
@@ -881,7 +885,7 @@ bool Mob::CombatRange(Mob* other)
float max_dist = static_cast<float>(GetSpecialAbilityParam(NPC_CHASE_DISTANCE, 0));
float min_dist = static_cast<float>(GetSpecialAbilityParam(NPC_CHASE_DISTANCE, 1));
if (GetSpecialAbilityParam(NPC_CHASE_DISTANCE, 2));
if (GetSpecialAbilityParam(NPC_CHASE_DISTANCE, 2))
DoLoSCheck = false; //Ignore line of sight check
if (max_dist == 1)
@@ -930,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
@@ -944,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);
}
@@ -1124,8 +1128,7 @@ int32 Mob::CheckAggroAmount(uint16 spell_id, bool isproc)
int HateMod = RuleI(Aggro, SpellAggroMod);
if (IsClient())
HateMod += CastToClient()->GetFocusEffect(focusSpellHateMod, spell_id);
HateMod += GetFocusEffect(focusSpellHateMod, spell_id);
AggroAmount = (AggroAmount * HateMod) / 100;
@@ -1174,8 +1177,7 @@ int32 Mob::CheckHealAggroAmount(uint16 spell_id, uint32 heal_possible)
if (AggroAmount > 0) {
int HateMod = RuleI(Aggro, SpellAggroMod);
if (IsClient())
HateMod += CastToClient()->GetFocusEffect(focusSpellHateMod, spell_id);
HateMod += GetFocusEffect(focusSpellHateMod, spell_id);
//Live AA - Spell casting subtlety
HateMod += aabonuses.hatemod + spellbonuses.hatemod + itembonuses.hatemod;
@@ -1231,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
@@ -1254,13 +1256,13 @@ bool Mob::PassCharismaCheck(Mob* caster, Mob* spellTarget, uint16 spell_id) {
return true;
//1: The mob has a default 25% chance of being allowed a resistance check against the charm.
if (MakeRandomInt(0, 99) > RuleI(Spells, CharmBreakCheckChance))
if (zone->random.Int(0, 99) > RuleI(Spells, CharmBreakCheckChance))
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)
@@ -1273,7 +1275,7 @@ bool Mob::PassCharismaCheck(Mob* caster, Mob* spellTarget, uint16 spell_id) {
//3: At maxed ability, Total Domination has a 50% chance of preventing the charm break that otherwise would have occurred.
int16 TotalDominationBonus = caster->aabonuses.CharmBreakChance + caster->spellbonuses.CharmBreakChance + caster->itembonuses.CharmBreakChance;
if (MakeRandomInt(0, 99) < TotalDominationBonus)
if (zone->random.Int(0, 99) < TotalDominationBonus)
return true;
}
@@ -1284,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;
}
@@ -1296,7 +1297,7 @@ bool Mob::PassCharismaCheck(Mob* caster, Mob* spellTarget, uint16 spell_id) {
void Mob::RogueEvade(Mob *other)
{
int amount = other->GetHateAmount(this) - (GetLevel() * 13);
other->SetHate(this, std::max(1, amount));
other->SetHateAmountOnEnt(this, std::max(1, amount));
return;
}
+460 -452
View File
File diff suppressed because it is too large Load Diff
+16 -19
View File
@@ -18,12 +18,12 @@
/*
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.
*/
#include "../common/debug.h"
class Zone;
#ifdef _WINDOWS
#define snprintf _snprintf
@@ -32,18 +32,28 @@ target to center around.
#define strcasecmp _stricmp
#endif
#include "masterentity.h"
#include "../common/races.h"
#include "beacon.h"
#include "entity.h"
#include "mob.h"
#ifdef BOTS
#include "bot.h"
#endif
#include "../common/spdat.h"
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),
@@ -57,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()
+4 -1
View File
@@ -19,11 +19,14 @@
#ifndef BEACON_H
#define BEACON_H
#include "entity.h"
#include "mob.h"
#include "../common/types.h"
#include "../common/timer.h"
class Group;
class Raid;
struct ExtraAttackOptions;
class Beacon : public Mob
{
public:
+513 -490
View File
File diff suppressed because it is too large Load Diff
+424 -524
View File
File diff suppressed because it is too large Load Diff
+108 -113
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"
@@ -172,10 +172,10 @@ public:
virtual int GetMonkHandToHandDamage(void);
virtual bool TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse);
virtual void DoRiposte(Mob* defender);
inline virtual int16 GetATK() const { return ATK + itembonuses.ATK + spellbonuses.ATK + ((GetSTR() + GetSkill(SkillOffense)) * 9 / 10); }
inline virtual int16 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; }
uint16 GetTotalATK();
uint16 GetATKRating();
inline virtual int32 GetATK() const { return ATK + itembonuses.ATK + spellbonuses.ATK + ((GetSTR() + GetSkill(SkillOffense)) * 9 / 10); }
inline virtual int32 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; }
uint32 GetTotalATK();
uint32 GetATKRating();
uint16 GetPrimarySkillValue();
uint16 MaxSkill(SkillUseTypes skillid, uint16 class_, uint16 level) const;
inline uint16 MaxSkill(SkillUseTypes skillid) const { return MaxSkill(skillid, GetClass(), GetLevel()); }
@@ -208,7 +208,7 @@ public:
bool DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, uint16 slot, bool &stopLogic);
void SendBotArcheryWearChange(uint8 material_slot, uint32 material, uint32 color);
void Camp(bool databaseSave = true);
virtual void AddToHateList(Mob* other, int32 hate = 0, int32 damage = 0, bool iYellForHelp = true, bool bFrenzy = false, bool iBuffTic = false);
virtual void AddToHateList(Mob* other, uint32 hate = 0, int32 damage = 0, bool iYellForHelp = true, bool bFrenzy = false, bool iBuffTic = false);
virtual void SetTarget(Mob* mob);
virtual void Zone();
std::vector<AISpells_Struct> GetBotSpells() { return AIspells; }
@@ -238,35 +238,35 @@ public:
void ClearHealRotationLeader() { _healRotationLeader = 0; }
void ClearHealRotationMembers();
void ClearHealRotationTargets();
inline virtual int16 GetMaxStat();
inline virtual int16 GetMaxResist();
inline virtual int16 GetMaxSTR();
inline virtual int16 GetMaxSTA();
inline virtual int16 GetMaxDEX();
inline virtual int16 GetMaxAGI();
inline virtual int16 GetMaxINT();
inline virtual int16 GetMaxWIS();
inline virtual int16 GetMaxCHA();
inline virtual int16 GetMaxMR();
inline virtual int16 GetMaxPR();
inline virtual int16 GetMaxDR();
inline virtual int16 GetMaxCR();
inline virtual int16 GetMaxFR();
inline virtual int16 GetMaxCorrup();
int16 CalcATK();
int16 CalcSTR();
int16 CalcSTA();
int16 CalcDEX();
int16 CalcAGI();
int16 CalcINT();
int16 CalcWIS();
int16 CalcCHA();
int16 CalcMR();
int16 CalcFR();
int16 CalcDR();
int16 CalcPR();
int16 CalcCR();
int16 CalcCorrup();
inline virtual int32 GetMaxStat();
inline virtual int32 GetMaxResist();
inline virtual int32 GetMaxSTR();
inline virtual int32 GetMaxSTA();
inline virtual int32 GetMaxDEX();
inline virtual int32 GetMaxAGI();
inline virtual int32 GetMaxINT();
inline virtual int32 GetMaxWIS();
inline virtual int32 GetMaxCHA();
inline virtual int32 GetMaxMR();
inline virtual int32 GetMaxPR();
inline virtual int32 GetMaxDR();
inline virtual int32 GetMaxCR();
inline virtual int32 GetMaxFR();
inline virtual int32 GetMaxCorrup();
int32 CalcATK();
int32 CalcSTR();
int32 CalcSTA();
int32 CalcDEX();
int32 CalcAGI();
int32 CalcINT();
int32 CalcWIS();
int32 CalcCHA();
int32 CalcMR();
int32 CalcFR();
int32 CalcDR();
int32 CalcPR();
int32 CalcCR();
int32 CalcCorrup();
int32 CalcHPRegenCap();
int32 CalcManaRegenCap();
int32 LevelRegen();
@@ -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); }
@@ -465,57 +464,57 @@ public:
uint32 GetHealRotationNextHealTime() { return _healRotationNextHeal; }
uint32 GetHealRotationTimer () { return _healRotationTimer; }
bool GetBardUseOutOfCombatSongs() { return _bardUseOutOfCombatSongs;}
inline virtual int16 GetAC() const { return AC; }
inline virtual int16 GetSTR() const { return STR; }
inline virtual int16 GetSTA() const { return STA; }
inline virtual int16 GetDEX() const { return DEX; }
inline virtual int16 GetAGI() const { return AGI; }
inline virtual int16 GetINT() const { return INT; }
inline virtual int16 GetWIS() const { return WIS; }
inline virtual int16 GetCHA() const { return CHA; }
inline virtual int16 GetMR() const { return MR; }
inline virtual int16 GetFR() const { return FR; }
inline virtual int16 GetDR() const { return DR; }
inline virtual int16 GetPR() const { return PR; }
inline virtual int16 GetCR() const { return CR; }
inline virtual int16 GetCorrup() const { return Corrup; }
inline virtual int32 GetAC() const { return AC; }
inline virtual int32 GetSTR() const { return STR; }
inline virtual int32 GetSTA() const { return STA; }
inline virtual int32 GetDEX() const { return DEX; }
inline virtual int32 GetAGI() const { return AGI; }
inline virtual int32 GetINT() const { return INT; }
inline virtual int32 GetWIS() const { return WIS; }
inline virtual int32 GetCHA() const { return CHA; }
inline virtual int32 GetMR() const { return MR; }
inline virtual int32 GetFR() const { return FR; }
inline virtual int32 GetDR() const { return DR; }
inline virtual int32 GetPR() const { return PR; }
inline virtual int32 GetCR() const { return CR; }
inline virtual int32 GetCorrup() const { return Corrup; }
//Heroic
inline virtual int16 GetHeroicSTR() const { return itembonuses.HeroicSTR; }
inline virtual int16 GetHeroicSTA() const { return itembonuses.HeroicSTA; }
inline virtual int16 GetHeroicDEX() const { return itembonuses.HeroicDEX; }
inline virtual int16 GetHeroicAGI() const { return itembonuses.HeroicAGI; }
inline virtual int16 GetHeroicINT() const { return itembonuses.HeroicINT; }
inline virtual int16 GetHeroicWIS() const { return itembonuses.HeroicWIS; }
inline virtual int16 GetHeroicCHA() const { return itembonuses.HeroicCHA; }
inline virtual int16 GetHeroicMR() const { return itembonuses.HeroicMR; }
inline virtual int16 GetHeroicFR() const { return itembonuses.HeroicFR; }
inline virtual int16 GetHeroicDR() const { return itembonuses.HeroicDR; }
inline virtual int16 GetHeroicPR() const { return itembonuses.HeroicPR; }
inline virtual int16 GetHeroicCR() const { return itembonuses.HeroicCR; }
inline virtual int16 GetHeroicCorrup() const { return itembonuses.HeroicCorrup; }
inline virtual int32 GetHeroicSTR() const { return itembonuses.HeroicSTR; }
inline virtual int32 GetHeroicSTA() const { return itembonuses.HeroicSTA; }
inline virtual int32 GetHeroicDEX() const { return itembonuses.HeroicDEX; }
inline virtual int32 GetHeroicAGI() const { return itembonuses.HeroicAGI; }
inline virtual int32 GetHeroicINT() const { return itembonuses.HeroicINT; }
inline virtual int32 GetHeroicWIS() const { return itembonuses.HeroicWIS; }
inline virtual int32 GetHeroicCHA() const { return itembonuses.HeroicCHA; }
inline virtual int32 GetHeroicMR() const { return itembonuses.HeroicMR; }
inline virtual int32 GetHeroicFR() const { return itembonuses.HeroicFR; }
inline virtual int32 GetHeroicDR() const { return itembonuses.HeroicDR; }
inline virtual int32 GetHeroicPR() const { return itembonuses.HeroicPR; }
inline virtual int32 GetHeroicCR() const { return itembonuses.HeroicCR; }
inline virtual int32 GetHeroicCorrup() const { return itembonuses.HeroicCorrup; }
// Mod2
inline virtual int16 GetShielding() const { return itembonuses.MeleeMitigation; }
inline virtual int16 GetSpellShield() const { return itembonuses.SpellShield; }
inline virtual int16 GetDoTShield() const { return itembonuses.DoTShielding; }
inline virtual int16 GetStunResist() const { return itembonuses.StunResist; }
inline virtual int16 GetStrikeThrough() const { return itembonuses.StrikeThrough; }
inline virtual int16 GetAvoidance() const { return itembonuses.AvoidMeleeChance; }
inline virtual int16 GetAccuracy() const { return itembonuses.HitChance; }
inline virtual int16 GetCombatEffects() const { return itembonuses.ProcChance; }
inline virtual int16 GetDS() const { return itembonuses.DamageShield; }
inline virtual int32 GetShielding() const { return itembonuses.MeleeMitigation; }
inline virtual int32 GetSpellShield() const { return itembonuses.SpellShield; }
inline virtual int32 GetDoTShield() const { return itembonuses.DoTShielding; }
inline virtual int32 GetStunResist() const { return itembonuses.StunResist; }
inline virtual int32 GetStrikeThrough() const { return itembonuses.StrikeThrough; }
inline virtual int32 GetAvoidance() const { return itembonuses.AvoidMeleeChance; }
inline virtual int32 GetAccuracy() const { return itembonuses.HitChance; }
inline virtual int32 GetCombatEffects() const { return itembonuses.ProcChance; }
inline virtual int32 GetDS() const { return itembonuses.DamageShield; }
// Mod3
inline virtual int16 GetHealAmt() const { return itembonuses.HealAmt; }
inline virtual int16 GetSpellDmg() const { return itembonuses.SpellDmg; }
inline virtual int16 GetClair() const { return itembonuses.Clairvoyance; }
inline virtual int16 GetDSMit() const { return itembonuses.DSMitigation; }
inline virtual int32 GetHealAmt() const { return itembonuses.HealAmt; }
inline virtual int32 GetSpellDmg() const { return itembonuses.SpellDmg; }
inline virtual int32 GetClair() const { return itembonuses.Clairvoyance; }
inline virtual int32 GetDSMit() const { return itembonuses.DSMitigation; }
inline virtual int16 GetSingMod() const { return itembonuses.singingMod; }
inline virtual int16 GetBrassMod() const { return itembonuses.brassMod; }
inline virtual int16 GetPercMod() const { return itembonuses.percussionMod; }
inline virtual int16 GetStringMod() const { return itembonuses.stringedMod; }
inline virtual int16 GetWindMod() const { return itembonuses.windMod; }
inline virtual int32 GetSingMod() const { return itembonuses.singingMod; }
inline virtual int32 GetBrassMod() const { return itembonuses.brassMod; }
inline virtual int32 GetPercMod() const { return itembonuses.percussionMod; }
inline virtual int32 GetStringMod() const { return itembonuses.stringedMod; }
inline virtual int32 GetWindMod() const { return itembonuses.windMod; }
inline virtual int16 GetDelayDeath() const { return aabonuses.DelayDeath + spellbonuses.DelayDeath + itembonuses.DelayDeath; }
inline virtual int32 GetDelayDeath() const { return aabonuses.DelayDeath + spellbonuses.DelayDeath + itembonuses.DelayDeath; }
inline InspectMessage_Struct& GetInspectMessage() { return _botInspectMessage; }
inline const InspectMessage_Struct& GetInspectMessage() const { return _botInspectMessage; }
@@ -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; }
@@ -556,13 +553,13 @@ public:
protected:
virtual void PetAIProcess();
static NPCType FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender, float size, uint32 face, uint32 hairStyle, uint32 hairColor, uint32 eyeColor, uint32 eyeColor2, uint32 beardColor, uint32 beard, uint32 drakkinHeritage, uint32 drakkinTattoo, uint32 drakkinDetails, int32 hp, int32 mana, int16 mr, int16 cr, int16 dr, int16 fr, int16 pr, int16 corrup, int16 ac, uint16 str, uint16 sta, uint16 dex, uint16 agi, uint16 _int, uint16 wis, uint16 cha, uint16 attack);
static NPCType FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender, float size, uint32 face, uint32 hairStyle, uint32 hairColor, uint32 eyeColor, uint32 eyeColor2, uint32 beardColor, uint32 beard, uint32 drakkinHeritage, uint32 drakkinTattoo, uint32 drakkinDetails, int32 hp, int32 mana, int32 mr, int32 cr, int32 dr, int32 fr, int32 pr, int32 corrup, int32 ac, uint32 str, uint32 sta, uint32 dex, uint32 agi, uint32 _int, uint32 wis, uint32 cha, uint32 attack);
virtual void BotMeditate(bool isSitting);
virtual void BotRangedAttack(Mob* other);
virtual bool CheckBotDoubleAttack(bool Triple = false);
virtual int16 GetBotFocusEffect(BotfocusType bottype, uint16 spell_id);
virtual int16 CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spell_id, bool best_focus=false);
virtual int16 CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id);
virtual int32 GetBotFocusEffect(BotfocusType bottype, uint16 spell_id);
virtual int32 CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spell_id, bool best_focus=false);
virtual int32 CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id);
virtual void PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* client);
virtual bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0);
virtual float GetMaxMeleeRangeToTarget(Mob* target);
@@ -601,12 +598,10 @@ private:
int32 base_end;
int32 cur_end;
int32 max_end;
int16 end_regen;
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;
@@ -626,26 +621,26 @@ private:
bool _bardUseOutOfCombatSongs;
// Private "base stats" Members
int16 _baseMR;
int16 _baseCR;
int16 _baseDR;
int16 _baseFR;
int16 _basePR;
int16 _baseCorrup;
int _baseAC;
int16 _baseSTR;
int16 _baseSTA;
int16 _baseDEX;
int16 _baseAGI;
int16 _baseINT;
int16 _baseWIS;
int16 _baseCHA;
int16 _baseATK;
int32 _baseMR;
int32 _baseCR;
int32 _baseDR;
int32 _baseFR;
int32 _basePR;
int32 _baseCorrup;
int32 _baseAC;
int32 _baseSTR;
int32 _baseSTA;
int32 _baseDEX;
int32 _baseAGI;
int32 _baseINT;
int32 _baseWIS;
int32 _baseCHA;
int32 _baseATK;
uint16 _baseRace; // Necessary to preserve the race otherwise bots get their race updated in the db when they get an illusion.
uint8 _baseGender; // Bots gender. Necessary to preserve the original value otherwise it can be changed by illusions.
// Class Methods
int16 acmod();
int32 acmod();
void GenerateBaseStats();
void GenerateAppearance();
void GenerateArmorClass();
@@ -670,8 +665,8 @@ private:
void SavePetBuffs(SpellBuff_Struct* petBuffs, uint32 botPetSaveId);
void LoadPetItems(uint32* petItems, uint32 botPetSaveId);
void SavePetItems(uint32* petItems, uint32 botPetSaveId);
void LoadPetStats(std::string* petName, uint16* petMana, uint16* petHitPoints, uint32* botPetId, uint32 botPetSaveId);
uint32 SavePetStats(std::string petName, uint16 petMana, uint16 petHitPoints, uint32 botPetId);
void LoadPetStats(std::string* petName, uint32* petMana, uint32* petHitPoints, uint32* botPetId, uint32 botPetSaveId);
uint32 SavePetStats(std::string petName, uint32 petMana, uint32 petHitPoints, uint32 botPetId);
void LoadPet(); // Load and spawn bot pet if there is one
void SavePet(); // Save and depop bot pet if there is one
uint32 GetPetSaveId();
+8 -8
View File
@@ -13,7 +13,7 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
return false;
if (iChance < 100) {
if (MakeRandomInt(0, 100) > iChance){
if (zone->random.Int(0, 100) > iChance){
return false;
}
}
@@ -485,7 +485,7 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
if(botClass == PALADIN)
stunChance = 50;
if(!tar->GetSpecialAbility(UNSTUNABLE) && !tar->IsStunned() && (MakeRandomInt(1, 100) <= stunChance)) {
if(!tar->GetSpecialAbility(UNSTUNABLE) && !tar->IsStunned() && (zone->random.Int(1, 100) <= stunChance)) {
botSpell = GetBestBotSpellForStunByTargetType(this, ST_Target);
}
}
@@ -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();
@@ -1843,7 +1843,7 @@ std::string Bot::GetBotMagicianPetType(Bot* botCaster) {
result = std::string("SumEarth");
else if(botCaster->GetLevel() < 30) {
// Under level 30
int counter = MakeRandomInt(0, 3);
int counter = zone->random.Int(0, 3);
switch(counter) {
case 0:
@@ -1865,7 +1865,7 @@ std::string Bot::GetBotMagicianPetType(Bot* botCaster) {
}
else {
// Over level 30
int counter = MakeRandomInt(0, 4);
int counter = zone->random.Int(0, 4);
switch(counter) {
case 0:
+1014 -842
View File
File diff suppressed because it is too large Load Diff
+792 -746
View File
File diff suppressed because it is too large Load Diff
-140
View File
@@ -1,140 +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) {
printf("%s was already subscribed to %d\n", c->GetName(), id);
return;
}
}
printf("%s has been subscribed to %d\n", c->GetName(), id);
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
#include "../common/eq_packet_structs.h"
#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
+1136 -984
View File
File diff suppressed because it is too large Load Diff
+1131 -1060
View File
File diff suppressed because it is too large Load Diff
+3 -2
View File
@@ -1,4 +1,4 @@
// connecting opcode handlers
/* Connecting OpCode Handlers */
void Handle_Connect_0x3e33(const EQApplicationPacket *app);
void Handle_Connect_OP_ApproveZone(const EQApplicationPacket *app);
void Handle_Connect_OP_ClientError(const EQApplicationPacket *app);
@@ -20,7 +20,7 @@
void Handle_Connect_OP_WorldObjectsSent(const EQApplicationPacket *app);
void Handle_Connect_OP_ZoneComplete(const EQApplicationPacket *app);
void Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app);
// connected opcode handlers
/* Connected opcode handlers*/
void Handle_0x0193(const EQApplicationPacket *app);
void Handle_0x01e7(const EQApplicationPacket *app);
void Handle_OP_AAAction(const EQApplicationPacket *app);
@@ -138,6 +138,7 @@
void Handle_OP_GroupInvite(const EQApplicationPacket *app);
void Handle_OP_GroupInvite2(const EQApplicationPacket *app);
void Handle_OP_GroupMakeLeader(const EQApplicationPacket *app);
void Handle_OP_GroupMentor(const EQApplicationPacket *app);
void Handle_OP_GroupRoles(const EQApplicationPacket *app);
void Handle_OP_GroupUpdate(const EQApplicationPacket *app);
void Handle_OP_GuildBank(const EQApplicationPacket *app);
+186 -175
View File
@@ -18,15 +18,12 @@
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 <iomanip>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <zlib.h>
#include <assert.h>
#ifdef _WINDOWS
#include <windows.h>
@@ -41,29 +38,20 @@
#include <unistd.h>
#endif
#include "masterentity.h"
#include "zonedb.h"
#include "../common/packet_functions.h"
#include "../common/packet_dump.h"
#include "worldserver.h"
#include "../common/packet_dump_file.h"
#include "../common/string_util.h"
#include "../common/spdat.h"
#include "petitions.h"
#include "npc_ai.h"
#include "../common/skills.h"
#include "forage.h"
#include "zone.h"
#include "event_codes.h"
#include "../common/faction.h"
#include "../common/crc32.h"
#include "../common/rulesys.h"
#include "string_ids.h"
#include "map.h"
#include "../common/skills.h"
#include "../common/spdat.h"
#include "../common/string_util.h"
#include "event_codes.h"
#include "guild_mgr.h"
#include <string>
#include "quest_parser_collection.h"
#include "map.h"
#include "petitions.h"
#include "queryserv.h"
#include "quest_parser_collection.h"
#include "string_ids.h"
#include "worldserver.h"
#include "zone.h"
#include "zonedb.h"
extern QueryServ* QServ;
extern Zone* zone;
@@ -78,7 +66,8 @@ bool Client::Process() {
if(Connected() || IsLD())
{
// try to send all packets that weren't sent before
if(!IsLD() && zoneinpacket_timer.Check()){
if(!IsLD() && zoneinpacket_timer.Check())
{
SendAllPackets();
}
@@ -137,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())
@@ -145,10 +134,12 @@ bool Client::Process() {
if(mana_timer.Check())
SendManaUpdatePacket();
if(dead && dead_timer.Check()) {
database.MoveCharacterToZone(GetName(),database.GetZoneName(m_pp.binds[0].zoneId));
if(dead && dead_timer.Check()) {
database.MoveCharacterToZone(GetName(), database.GetZoneName(m_pp.binds[0].zoneId));
m_pp.zone_id = m_pp.binds[0].zoneId;
m_pp.zoneInstance = 0;
m_pp.zoneInstance = m_pp.binds[0].instance_id;
m_pp.x = m_pp.binds[0].x;
m_pp.y = m_pp.binds[0].y;
m_pp.z = m_pp.binds[0].z;
@@ -176,14 +167,16 @@ bool Client::Process() {
if(TaskPeriodic_Timer.Check() && taskstate)
taskstate->TaskPeriodicChecks(this);
if(linkdead_timer.Check()){
if(linkdead_timer.Check())
{
LeaveGroup();
Save();
if (GetMerc())
{
GetMerc()->Save();
GetMerc()->Depop();
}
LeaveGroup();
Raid *myraid = entity_list.GetRaidByClient(this);
if (myraid)
{
@@ -192,7 +185,8 @@ bool Client::Process() {
return false; //delete client
}
if (camp_timer.Check()) {
if (camp_timer.Check())
{
LeaveGroup();
Save();
if (GetMerc())
@@ -228,20 +222,18 @@ bool Client::Process() {
} else {
if(!ApplyNextBardPulse(bardsong, song_target, bardsong_slot))
InterruptSpell(SONG_ENDS_ABRUPTLY, 0x121, bardsong);
// SpellFinished(bardsong, bardsong_target, bardsong_slot, spells[bardsong].mana);
//SpellFinished(bardsong, bardsong_target, bardsong_slot, spells[bardsong].mana);
}
}
if(GetMerc())
{
UpdateMercTimer();
UpdateMercTimer();
}
if(GetMercInfo().MercTemplateID != 0 && GetMercInfo().IsSuspended)
{
if(p_timers.Expired(&database, pTimerMercSuspend, false)) {
CheckMercSuspendTimer();
}
CheckMercSuspendTimer();
}
if(IsAIControlled())
@@ -347,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);
}
@@ -443,7 +425,7 @@ bool Client::Process() {
if (auto_attack_target && flurrychance)
{
if(MakeRandomInt(0, 99) < flurrychance)
if(zone->random.Int(0, 99) < flurrychance)
{
Message_StringID(MT_NPCFlurry, YOU_FLURRY);
Attack(auto_attack_target, MainPrimary, false);
@@ -460,7 +442,7 @@ bool Client::Process() {
wpn->GetItem()->ItemType == ItemType2HBlunt ||
wpn->GetItem()->ItemType == ItemType2HPiercing )
{
if(MakeRandomInt(0, 99) < ExtraAttackChanceBonus)
if(zone->random.Int(0, 99) < ExtraAttackChanceBonus)
{
Attack(auto_attack_target, MainPrimary, false);
}
@@ -505,7 +487,7 @@ bool Client::Process() {
int16 DWBonus = spellbonuses.DualWieldChance + itembonuses.DualWieldChance;
DualWieldProbability += DualWieldProbability*float(DWBonus)/ 100.0f;
float random = MakeRandomFloat(0, 1);
float random = zone->random.Real(0, 1);
CheckIncreaseSkill(SkillDualWield, auto_attack_target, -10);
if (random < DualWieldProbability){ // Max 78% of DW
if(CheckAAEffect(aaEffectRampage)) {
@@ -536,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);
}
}
@@ -572,8 +552,7 @@ bool Client::Process() {
viral_timer_counter = 0;
}
if(projectile_timer.Check())
SpellProjectileEffect();
ProjectileAttack();
if(spellbonuses.GravityEffect == 1) {
if(gravity_timer.Check())
@@ -676,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())
@@ -715,16 +694,13 @@ bool Client::Process() {
}
#endif
if (client_state != CLIENT_LINKDEAD && (client_state == CLIENT_ERROR || client_state == DISCONNECTED || client_state == CLIENT_KICKED || !eqs->CheckState(ESTABLISHED))) {
if (client_state != CLIENT_LINKDEAD && (client_state == CLIENT_ERROR || client_state == DISCONNECTED || client_state == CLIENT_KICKED || !eqs->CheckState(ESTABLISHED)))
{
//client logged out or errored out
//ResetTrade();
if (client_state != CLIENT_KICKED) {
Save();
}
if (GetMerc())
{
GetMerc()->Depop();
}
client_state = CLIENT_LINKDEAD;
if (zoning || instalog || GetGM())
@@ -732,23 +708,32 @@ bool Client::Process() {
Group *mygroup = GetGroup();
if (mygroup)
{
if (!zoning) {
if (!zoning)
{
entity_list.MessageGroup(this, true, 15, "%s logged out.", GetName());
mygroup->DelMember(this);
} else {
LeaveGroup();
}
else
{
entity_list.MessageGroup(this, true, 15, "%s left the zone.", GetName());
mygroup->MemberZoned(this);
if (GetMerc() && GetMerc()->HasGroup())
{
GetMerc()->RemoveMercFromGroup(GetMerc(), GetMerc()->GetGroup());
}
}
}
Raid *myraid = entity_list.GetRaidByClient(this);
if (myraid)
{
if (!zoning) {
if (!zoning)
{
//entity_list.MessageGroup(this,true,15,"%s logged out.",GetName());
//mygroup->DelMember(this);
myraid->MemberZoned(this);
} else {
}
else
{
//entity_list.MessageGroup(this,true,15,"%s left the zone.",GetName());
myraid->MemberZoned(this);
}
@@ -774,38 +759,45 @@ bool Client::Process() {
/* Just a set of actions preformed all over in Client::Process */
void Client::OnDisconnect(bool hard_disconnect) {
if(hard_disconnect) {
LeaveGroup();
if(hard_disconnect)
{
LeaveGroup();
if (GetMerc())
{
GetMerc()->Save();
GetMerc()->Depop();
}
Raid *MyRaid = entity_list.GetRaidByClient(this);
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();
if(Other) {
mlog(TRADING__CLIENT, "Client disconnected during a trade. Returning their items.");
Mob *Other = trade->With();
if(Other)
{
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);
@@ -829,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);
@@ -878,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);
@@ -967,93 +959,99 @@ 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.
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;
Mob* merch = entity_list.GetMobByNpcTypeID(npcid);
if(merlist.size()==0){ //Attempt to load the data, it might have been missed if someone spawned the merchant after the zone was loaded
if (merlist.size() == 0) { //Attempt to load the data, it might have been missed if someone spawned the merchant after the zone was loaded
zone->LoadNewMerchantData(merchant_id);
merlist = zone->merchanttable[merchant_id];
if(merlist.size()==0)
if (merlist.size() == 0)
return;
}
std::list<TempMerchantList> tmp_merlist = zone->tmpmerchanttable[npcid];
std::list<TempMerchantList>::iterator tmp_itr;
uint32 i=1;
uint32 i = 1;
uint8 handychance = 0;
for (itr = merlist.begin(); itr != merlist.end() && i < numItemSlots; ++itr) {
for (itr = merlist.begin(); itr != merlist.end() && i <= numItemSlots; ++itr) {
MerchantList ml = *itr;
if (merch->CastToNPC()->GetMerchantProbability() > ml.probability)
continue;
if(GetLevel() < ml.level_required)
if (GetLevel() < ml.level_required)
continue;
if (!(ml.classes_required & (1 << (GetClass() - 1))))
continue;
int32 fac = merch ? merch->GetPrimaryFaction() : 0;
if(fac != 0 && GetModCharacterFactionLevel(fac) < ml.faction_required)
if (fac != 0 && GetModCharacterFactionLevel(fac) < ml.faction_required)
continue;
handychance = MakeRandomInt(0, merlist.size() + tmp_merlist.size() - 1 );
handychance = zone->random.Int(0, merlist.size() + tmp_merlist.size() - 1);
item = database.GetItem(ml.item);
if(item) {
if(handychance==0)
handyitem=item;
if (item) {
if (handychance == 0)
handyitem = item;
else
handychance--;
int charges=1;
if(item->ItemClass==ItemClassCommon)
charges=item->MaxCharges;
int charges = 1;
if (item->ItemClass == ItemClassCommon)
charges = item->MaxCharges;
ItemInst* inst = database.CreateItem(item, charges);
if (inst) {
if (RuleB(Merchant, UsePriceMod)){
inst->SetPrice((item->Price*(RuleR(Merchant, SellCostMod))*item->SellRate*Client::CalcPriceMod(merch,false)));
if (RuleB(Merchant, UsePriceMod)) {
inst->SetPrice((item->Price * (RuleR(Merchant, SellCostMod)) * item->SellRate * Client::CalcPriceMod(merch, false)));
}
else
inst->SetPrice((item->Price*(RuleR(Merchant, SellCostMod))*item->SellRate));
inst->SetPrice((item->Price * (RuleR(Merchant, SellCostMod)) * item->SellRate));
inst->SetMerchantSlot(ml.slot);
inst->SetMerchantCount(-1); //unlimited
if(charges > 0)
if (charges > 0)
inst->SetCharges(charges);
else
inst->SetCharges(1);
SendItemPacket(ml.slot-1, inst, ItemPacketMerchant);
SendItemPacket(ml.slot - 1, inst, ItemPacketMerchant);
safe_delete(inst);
}
}
// Account for merchant lists with gaps.
if(ml.slot >= i)
if (ml.slot >= i) {
if (ml.slot > i)
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;
}
}
std::list<TempMerchantList> origtmp_merlist = zone->tmpmerchanttable[npcid];
tmp_merlist.clear();
for(tmp_itr = origtmp_merlist.begin();tmp_itr != origtmp_merlist.end() && i<numItemSlots;++tmp_itr){
for (tmp_itr = origtmp_merlist.begin(); tmp_itr != origtmp_merlist.end() && i <= numItemSlots; ++tmp_itr) {
TempMerchantList ml = *tmp_itr;
item=database.GetItem(ml.item);
ml.slot=i;
item = database.GetItem(ml.item);
ml.slot = i;
if (item) {
if(handychance==0)
handyitem=item;
if (handychance == 0)
handyitem = item;
else
handychance--;
int charges=1;
int charges = 1;
//if(item->ItemClass==ItemClassCommon && (int16)ml.charges <= item->MaxCharges)
// charges=ml.charges;
//else
charges = item->MaxCharges;
ItemInst* inst = database.CreateItem(item, charges);
if (inst) {
if (RuleB(Merchant, UsePriceMod)){
inst->SetPrice((item->Price*(RuleR(Merchant, SellCostMod))*item->SellRate*Client::CalcPriceMod(merch,false)));
if (RuleB(Merchant, UsePriceMod)) {
inst->SetPrice((item->Price * (RuleR(Merchant, SellCostMod)) * item->SellRate * Client::CalcPriceMod(merch, false)));
}
else
inst->SetPrice((item->Price*(RuleR(Merchant, SellCostMod))*item->SellRate));
inst->SetPrice((item->Price * (RuleR(Merchant, SellCostMod)) * item->SellRate));
inst->SetMerchantSlot(ml.slot);
inst->SetMerchantCount(ml.charges);
if(charges > 0)
@@ -1069,32 +1067,32 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) {
}
//this resets the slot
zone->tmpmerchanttable[npcid] = tmp_merlist;
if(merch != nullptr && handyitem){
char handy_id[8]={0};
int greeting=MakeRandomInt(0, 4);
int greet_id=0;
switch(greeting){
if (merch != nullptr && handyitem) {
char handy_id[8] = { 0 };
int greeting = zone->random.Int(0, 4);
int greet_id = 0;
switch (greeting) {
case 1:
greet_id=MERCHANT_GREETING;
greet_id = MERCHANT_GREETING;
break;
case 2:
greet_id=MERCHANT_HANDY_ITEM1;
greet_id = MERCHANT_HANDY_ITEM1;
break;
case 3:
greet_id=MERCHANT_HANDY_ITEM2;
greet_id = MERCHANT_HANDY_ITEM2;
break;
case 4:
greet_id=MERCHANT_HANDY_ITEM3;
greet_id = MERCHANT_HANDY_ITEM3;
break;
default:
greet_id=MERCHANT_HANDY_ITEM4;
greet_id = MERCHANT_HANDY_ITEM4;
}
sprintf(handy_id,"%i",greet_id);
sprintf(handy_id, "%i", greet_id);
if(greet_id!=MERCHANT_GREETING)
Message_StringID(10,GENERIC_STRINGID_SAY,merch->GetCleanName(),handy_id,this->GetName(),handyitem->Name);
if (greet_id != MERCHANT_GREETING)
Message_StringID(10, GENERIC_STRINGID_SAY, merch->GetCleanName(), handy_id, this->GetName(), handyitem->Name);
else
Message_StringID(10,GENERIC_STRINGID_SAY,merch->GetCleanName(),handy_id,this->GetName());
Message_StringID(10, GENERIC_STRINGID_SAY, merch->GetCleanName(), handy_id, this->GetName());
merch->CastToNPC()->FaceTarget(this->CastToMob());
}
@@ -1119,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;
}
@@ -1131,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;
}
@@ -1141,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);
@@ -1191,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;
}
@@ -1547,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{
@@ -1605,19 +1603,22 @@ 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;
SkillUseTypes sk;
for (sk = Skill1HBlunt; sk <= HIGHEST_SKILL; sk = (SkillUseTypes)(sk+1)) {
// if this for-loop acts up again (crashes linux), try enabling the before and after #pragmas
//#pragma GCC push_options
//#pragma GCC optimize ("O0")
for (int sk = Skill1HBlunt; sk <= HIGHEST_SKILL; ++sk) {
if(sk == SkillTinkering && GetRace() != GNOME) {
gmtrain->skills[sk] = 0; //Non gnomes can't tinker!
} else {
gmtrain->skills[sk] = GetMaxSkillAfterSpecializationRules(sk, MaxSkill(sk, GetClass(), RuleI(Character, MaxLevel)));
gmtrain->skills[sk] = GetMaxSkillAfterSpecializationRules((SkillUseTypes)sk, MaxSkill((SkillUseTypes)sk, GetClass(), RuleI(Character, MaxLevel)));
//this is the highest level that the trainer can train you to, this is enforced clientside so we can't just
//Set it to 1 with CanHaveSkill or you wont be able to train past 1.
}
}
//#pragma GCC pop_options
uchar ending[]={0x34,0x87,0x8a,0x3F,0x01
,0xC9,0xC9,0xC9,0xC9,0xC9,0xC9,0xC9,0xC9,0xC9,0xC9,0xC9,0xC9,0xC9,0xC9,0xC9,0xC9
@@ -1629,7 +1630,7 @@ void Client::OPGMTraining(const EQApplicationPacket *app)
// welcome message
if (pTrainer && pTrainer->IsNPC())
{
pTrainer->Say_StringID(MakeRandomInt(1204, 1207), GetCleanName());
pTrainer->Say_StringID(zone->random.Int(1204, 1207), GetCleanName());
}
}
@@ -1650,13 +1651,13 @@ 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
if (pTrainer->IsNPC())
{
pTrainer->Say_StringID(MakeRandomInt(1208, 1211), GetCleanName());
pTrainer->Say_StringID(zone->random.Int(1208, 1211), GetCleanName());
}
}
@@ -1679,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)
@@ -1710,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;
}
@@ -1730,7 +1731,7 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app)
}
SetSkill(skill, t_level);
} else {
} else {
switch(skill) {
case SkillBrewing:
case SkillMakePoison:
@@ -1793,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.
//
@@ -1926,16 +1927,21 @@ void Client::DoEnduranceRegen()
}
void Client::DoEnduranceUpkeep() {
if (!HasEndurUpkeep())
return;
int upkeep_sum = 0;
int cost_redux = spellbonuses.EnduranceReduction + itembonuses.EnduranceReduction + aabonuses.EnduranceReduction;
int cost_redux = spellbonuses.EnduranceReduction + itembonuses.EnduranceReduction;
bool has_effect = false;
uint32 buffs_i;
uint32 buff_count = GetMaxTotalSlots();
for (buffs_i = 0; buffs_i < buff_count; buffs_i++) {
if (buffs[buffs_i].spellid != SPELL_UNKNOWN) {
int upkeep = spells[buffs[buffs_i].spellid].EndurUpkeep;
if(upkeep > 0) {
has_effect = true;
if(cost_redux > 0) {
if(upkeep <= cost_redux)
continue; //reduced to 0
@@ -1955,6 +1961,9 @@ void Client::DoEnduranceUpkeep() {
SetEndurance(GetEndurance() - upkeep_sum);
TryTriggerOnValueAmount(false, false, true);
}
if (!has_effect)
SetEndurUpkeep(false);
}
void Client::CalcRestState() {
@@ -2085,7 +2094,8 @@ void Client::HandleRespawnFromHover(uint32 Option)
BindStruct* b = &m_pp.binds[0];
default_to_bind = new RespawnOption;
default_to_bind->name = "Bind Location";
default_to_bind->zoneid = b->zoneId;
default_to_bind->zone_id = b->zoneId;
default_to_bind->instance_id = b->instance_id;
default_to_bind->x = b->x;
default_to_bind->y = b->y;
default_to_bind->z = b->z;
@@ -2094,13 +2104,13 @@ void Client::HandleRespawnFromHover(uint32 Option)
is_rez = false;
}
if (chosen->zoneid == zone->GetZoneID()) //If they should respawn in the current zone...
if (chosen->zone_id == zone->GetZoneID() && chosen->instance_id == zone->GetInstanceID()) //If they should respawn in the current zone...
{
if (is_rez)
{
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);
@@ -2109,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);
@@ -2133,13 +2143,13 @@ 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->Rezzed(true);
corpse->CompleteRezz();
corpse->IsRezzed(true);
corpse->CompleteResurrection();
}
}
else //Not rez
@@ -2150,6 +2160,7 @@ void Client::HandleRespawnFromHover(uint32 Option)
ZonePlayerToBind_Struct* gmg = (ZonePlayerToBind_Struct*) outapp->pBuffer;
gmg->bind_zone_id = zone->GetZoneID();
gmg->bind_instance_id = chosen->instance_id;
gmg->x = chosen->x;
gmg->y = chosen->y;
gmg->z = chosen->z;
@@ -2163,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);
@@ -2176,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();
@@ -2195,13 +2206,13 @@ void Client::HandleRespawnFromHover(uint32 Option)
if(r)
r->MemberZoned(this);
m_pp.zone_id = chosen->zoneid;
m_pp.zoneInstance = 0;
database.MoveCharacterToZone(this->CharacterID(), database.GetZoneName(chosen->zoneid));
m_pp.zone_id = chosen->zone_id;
m_pp.zoneInstance = chosen->instance_id;
database.MoveCharacterToZone(CharacterID(), database.GetZoneName(chosen->zone_id));
Save();
MovePC(chosen->zoneid,chosen->x,chosen->y,chosen->z,chosen->heading,1);
MovePC(chosen->zone_id, chosen->instance_id, chosen->x, chosen->y, chosen->z, chosen->heading, 1);
}
safe_delete(default_to_bind);
@@ -2223,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);
+3712 -4500
View File
File diff suppressed because it is too large Load Diff
+11 -9
View File
@@ -20,9 +20,10 @@
#ifndef COMMAND_H
#define COMMAND_H
#include "../common/seperator.h"
#include "../common/eq_stream.h"
#include "client.h"
class Client;
class Seperator;
#include "../common/types.h"
#define COMMAND_CHAR '#'
#define CMDALIASES 5
@@ -75,6 +76,7 @@ void command_serversidename(Client *c, const Seperator *sep);
void command_testspawnkill(Client *c, const Seperator *sep);
void command_testspawn(Client *c, const Seperator *sep);
void command_wc(Client *c, const Seperator *sep);
void command_heromodel(Client *c, const Seperator *sep);
void command_numauths(Client *c, const Seperator *sep);
void command_setanim(Client *c, const Seperator *sep);
void command_connectworldserver(Client *c, const Seperator *sep);
@@ -85,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);
@@ -152,6 +153,7 @@ void command_heal(Client *c, const Seperator *sep);
void command_appearance(Client *c, const Seperator *sep);
void command_nukeitem(Client *c, const Seperator *sep);
void command_peekinv(Client *c, const Seperator *sep);
void command_interrogateinv(Client *c, const Seperator *sep);
void command_findnpctype(Client *c, const Seperator *sep);
void command_findzone(Client *c, const Seperator *sep);
void command_viewnpctype(Client *c, const Seperator *sep);
@@ -256,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);
@@ -269,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);
@@ -323,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);
+207 -185
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())
@@ -19,6 +19,7 @@
#define USE_ITEM_SPELL_SLOT 10
#define POTION_BELT_SPELL_SLOT 11
#define TARGET_RING_SPELL_SLOT 12
#define DISCIPLINE_SPELL_SLOT 10
#define ABILITY_SPELL_SLOT 9
@@ -132,8 +133,10 @@ enum {
ALLOW_BENEFICIAL = 38,
DISABLE_MELEE = 39,
NPC_CHASE_DISTANCE = 40,
MAX_SPECIAL_ATTACK = 41
ALLOW_TO_TANK = 41,
IGNORE_ROOT_AGGRO_RULES = 42,
CASTING_RESIST_DIFF = 43,
MAX_SPECIAL_ATTACK = 44
};
typedef enum { //fear states
@@ -155,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
@@ -192,7 +195,7 @@ struct Buffs_Struct {
};
struct StatBonuses {
int16 AC;
int32 AC;
int32 HP;
int32 HPRegen;
int32 MaxHP;
@@ -200,47 +203,47 @@ struct StatBonuses {
int32 EnduranceRegen;
int32 Mana;
int32 Endurance;
int16 ATK;
int32 ATK;
//would it be worth it to create a Stat_Struct?
int16 STR;
int16 STRCapMod;
int16 HeroicSTR;
int16 STA;
int16 STACapMod;
int16 HeroicSTA;
int16 DEX;
int16 DEXCapMod;
int16 HeroicDEX;
int16 AGI;
int16 AGICapMod;
int16 HeroicAGI;
int16 INT;
int16 INTCapMod;
int16 HeroicINT;
int16 WIS;
int16 WISCapMod;
int16 HeroicWIS;
int16 CHA;
int16 CHACapMod;
int16 HeroicCHA;
int16 MR;
int16 MRCapMod;
int16 HeroicMR;
int16 FR;
int16 FRCapMod;
int16 HeroicFR;
int16 CR;
int16 CRCapMod;
int16 HeroicCR;
int16 PR;
int16 PRCapMod;
int16 HeroicPR;
int16 DR;
int16 DRCapMod;
int16 HeroicDR;
int16 Corrup;
int16 CorrupCapMod;
int16 HeroicCorrup;
int32 STR;
int32 STRCapMod;
int32 HeroicSTR;
int32 STA;
int32 STACapMod;
int32 HeroicSTA;
int32 DEX;
int32 DEXCapMod;
int32 HeroicDEX;
int32 AGI;
int32 AGICapMod;
int32 HeroicAGI;
int32 INT;
int32 INTCapMod;
int32 HeroicINT;
int32 WIS;
int32 WISCapMod;
int32 HeroicWIS;
int32 CHA;
int32 CHACapMod;
int32 HeroicCHA;
int32 MR;
int32 MRCapMod;
int32 HeroicMR;
int32 FR;
int32 FRCapMod;
int32 HeroicFR;
int32 CR;
int32 CRCapMod;
int32 HeroicCR;
int32 PR;
int32 PRCapMod;
int32 HeroicPR;
int32 DR;
int32 DRCapMod;
int32 HeroicDR;
int32 Corrup;
int32 CorrupCapMod;
int32 HeroicCorrup;
uint16 DamageShieldSpellID;
int DamageShield; // this is damage done to mobs that attack this
DmgShieldType DamageShieldType;
@@ -250,91 +253,91 @@ struct StatBonuses {
uint16 ReverseDamageShieldSpellID;
DmgShieldType ReverseDamageShieldType;
int movementspeed;
int16 haste;
int16 hastetype2;
int16 hastetype3;
int16 inhibitmelee;
int32 haste;
int32 hastetype2;
int32 hastetype3;
int32 inhibitmelee;
float AggroRange; // when calculate just replace original value with this
float AssistRange;
int16 skillmod[HIGHEST_SKILL+1];
int32 skillmod[HIGHEST_SKILL+1];
int effective_casting_level;
int reflect_chance; // chance to reflect incoming spell
uint16 singingMod;
uint16 Amplification; // stacks with singingMod
uint16 brassMod;
uint16 percussionMod;
uint16 windMod;
uint16 stringedMod;
uint16 songModCap;
uint32 singingMod;
uint32 Amplification; // stacks with singingMod
uint32 brassMod;
uint32 percussionMod;
uint32 windMod;
uint32 stringedMod;
uint32 songModCap;
int8 hatemod;
int32 EnduranceReduction;
int16 StrikeThrough; // PoP: Strike Through %
int16 MeleeMitigation; //i = Shielding
int16 MeleeMitigationEffect; //i = Spell Effect Melee Mitigation
int16 CriticalHitChance[HIGHEST_SKILL+2]; //i
int16 CriticalSpellChance; //i
int16 SpellCritDmgIncrease; //i
int16 SpellCritDmgIncNoStack; // increase
int16 DotCritDmgIncrease; //i
int16 CriticalHealChance; //i
int16 CriticalHealOverTime; //i
int16 CriticalDoTChance; //i
int16 CrippBlowChance; //
int16 AvoidMeleeChance; //AvoidMeleeChance/10 == % chance i = Avoidance (item mod)
int16 AvoidMeleeChanceEffect; //AvoidMeleeChance Spell Effect
int16 RiposteChance; //i
int16 DodgeChance; //i
int16 ParryChance; //i
int16 DualWieldChance; //i
int16 DoubleAttackChance; //i
int16 TripleAttackChance; //i
int16 DoubleRangedAttack; //i
int16 ResistSpellChance; //i
int16 ResistFearChance; //i
int32 StrikeThrough; // PoP: Strike Through %
int32 MeleeMitigation; //i = Shielding
int32 MeleeMitigationEffect; //i = Spell Effect Melee Mitigation
int32 CriticalHitChance[HIGHEST_SKILL+2]; //i
int32 CriticalSpellChance; //i
int32 SpellCritDmgIncrease; //i
int32 SpellCritDmgIncNoStack; // increase
int32 DotCritDmgIncrease; //i
int32 CriticalHealChance; //i
int32 CriticalHealOverTime; //i
int32 CriticalDoTChance; //i
int32 CrippBlowChance; //
int32 AvoidMeleeChance; //AvoidMeleeChance/10 == % chance i = Avoidance (item mod)
int32 AvoidMeleeChanceEffect; //AvoidMeleeChance Spell Effect
int32 RiposteChance; //i
int32 DodgeChance; //i
int32 ParryChance; //i
int32 DualWieldChance; //i
int32 DoubleAttackChance; //i
int32 TripleAttackChance; //i
int32 DoubleRangedAttack; //i
int32 ResistSpellChance; //i
int32 ResistFearChance; //i
bool Fearless; //i
bool IsFeared; //i
bool IsBlind; //i
int16 StunResist; //i
int16 MeleeSkillCheck; //i
int32 StunResist; //i
int32 MeleeSkillCheck; //i
uint8 MeleeSkillCheckSkill;
int16 HitChance; //HitChance/15 == % increase i = Accuracy (Item: Accuracy)
int16 HitChanceEffect[HIGHEST_SKILL+2]; //Spell effect Chance to Hit, straight percent increase
int16 DamageModifier[HIGHEST_SKILL+2]; //i
int16 DamageModifier2[HIGHEST_SKILL+2]; //i
int16 MinDamageModifier[HIGHEST_SKILL+2]; //i
int16 ProcChance; // ProcChance/10 == % increase i = CombatEffects
int16 ProcChanceSPA; // ProcChance from spell effects
int16 ExtraAttackChance;
int16 DoTShielding;
int16 DivineSaveChance[2]; // Second Chance (base1 = chance, base2 = spell on trigger)
uint16 DeathSave[4]; // Death Pact [0](value = 1 partial 2 = full) [1]=slot [2]=LvLimit [3]=HealAmt
int16 FlurryChance;
int16 Accuracy[HIGHEST_SKILL+2]; //Accuracy/15 == % increase [Spell Effect: Accuracy)
int16 HundredHands; //extra haste, stacks with all other haste i
int16 MeleeLifetap; //i
int16 Vampirism; //i
int16 HealRate; // Spell effect that influences effectiveness of heals
int32 HitChance; //HitChance/15 == % increase i = Accuracy (Item: Accuracy)
int32 HitChanceEffect[HIGHEST_SKILL+2]; //Spell effect Chance to Hit, straight percent increase
int32 DamageModifier[HIGHEST_SKILL+2]; //i
int32 DamageModifier2[HIGHEST_SKILL+2]; //i
int32 MinDamageModifier[HIGHEST_SKILL+2]; //i
int32 ProcChance; // ProcChance/10 == % increase i = CombatEffects
int32 ProcChanceSPA; // ProcChance from spell effects
int32 ExtraAttackChance;
int32 DoTShielding;
int32 DivineSaveChance[2]; // Second Chance (base1 = chance, base2 = spell on trigger)
uint32 DeathSave[4]; // Death Pact [0](value = 1 partial 2 = full) [1]=slot [2]=LvLimit [3]=HealAmt
int32 FlurryChance;
int32 Accuracy[HIGHEST_SKILL+2]; //Accuracy/15 == % increase [Spell Effect: Accuracy)
int32 HundredHands; //extra haste, stacks with all other haste i
int32 MeleeLifetap; //i
int32 Vampirism; //i
int32 HealRate; // Spell effect that influences effectiveness of heals
int32 MaxHPChange; // Spell Effect
int16 SkillDmgTaken[HIGHEST_SKILL+2]; // All Skills + -1
int32 HealAmt; // Item Effect
int32 SpellDmg; // Item Effect
int32 Clairvoyance; // Item Effect
int16 DSMitigation; // Item Effect
int16 DSMitigationOffHand; // Lowers damage shield from off hand attacks.
int32 DSMitigation; // Item Effect
int32 DSMitigationOffHand; // Lowers damage shield from off hand attacks.
uint32 SpellTriggers[MAX_SPELL_TRIGGER]; // Innate/Spell/Item Spells that trigger when you cast
uint32 SpellOnKill[MAX_SPELL_TRIGGER*3]; // Chance to proc after killing a mob
uint32 SpellOnDeath[MAX_SPELL_TRIGGER*2]; // Chance to have effect cast when you die
int16 CritDmgMob[HIGHEST_SKILL+2]; // All Skills + -1
int16 SkillReuseTime[HIGHEST_SKILL+1]; // Reduces skill timers
int16 SkillDamageAmount[HIGHEST_SKILL+2]; // All Skills + -1
int16 TwoHandBluntBlock; // chance to block when wielding two hand blunt weapon
uint16 ItemManaRegenCap; // Increases the amount of mana you have can over the cap(aa effect)
int16 GravityEffect; // Indictor of spell effect
int32 CritDmgMob[HIGHEST_SKILL+2]; // All Skills + -1
int32 SkillReuseTime[HIGHEST_SKILL+1]; // Reduces skill timers
int32 SkillDamageAmount[HIGHEST_SKILL+2]; // All Skills + -1
int32 TwoHandBluntBlock; // chance to block when wielding two hand blunt weapon
uint32 ItemManaRegenCap; // Increases the amount of mana you have can over the cap(aa effect)
int32 GravityEffect; // Indictor of spell effect
bool AntiGate; // spell effect that prevents gating
bool MagicWeapon; // spell effect that makes weapon magical
int16 IncreaseBlockChance; // overall block chance modifier
uint16 PersistantCasting; // chance to continue casting through a stun
int32 IncreaseBlockChance; // overall block chance modifier
uint32 PersistantCasting; // chance to continue casting through a stun
int XPRateMod; //i
int HPPercCap[2]; //Spell effect that limits you to being healed/regening beyond a % of your max
int ManaPercCap[2]; // ^^ 0 = % Cap 1 = Flat Amount Cap
@@ -342,64 +345,64 @@ struct StatBonuses {
bool BlockNextSpell; // Indicates whether the client can block a spell or not
//uint16 BlockSpellEffect[EFFECT_COUNT]; // Prevents spells with certain effects from landing on you *no longer used
bool ImmuneToFlee; // Bypass the fleeing flag
uint16 VoiceGraft; // Stores the ID of the mob with which to talk through
int16 SpellProcChance; // chance to proc from sympathetic spell effects
int16 CharmBreakChance; // chance to break charm
int16 SongRange; // increases range of beneficial bard songs
uint16 HPToManaConvert; // Uses HP to cast spells at specific conversion
uint16 FocusEffects[HIGHEST_FOCUS+1]; // Stores the focus effectid for each focustype you have.
uint32 VoiceGraft; // Stores the ID of the mob with which to talk through
int32 SpellProcChance; // chance to proc from sympathetic spell effects
int32 CharmBreakChance; // chance to break charm
int32 SongRange; // increases range of beneficial bard songs
uint32 HPToManaConvert; // Uses HP to cast spells at specific conversion
uint32 FocusEffects[HIGHEST_FOCUS+1]; // Stores the focus effectid for each focustype you have.
bool NegateEffects; // Check if you contain a buff with negate effect. (only spellbonuses)
int16 SkillDamageAmount2[HIGHEST_SKILL+2]; // Adds skill specific damage
uint16 NegateAttacks[3]; // 0 = bool HasEffect 1 = Buff Slot 2 = Max damage absorbed per hit
uint16 MitigateMeleeRune[4]; // 0 = Mitigation value 1 = Buff Slot 2 = Max mitigation per hit 3 = Rune Amt
uint16 MeleeThresholdGuard[3]; // 0 = Mitigation value 1 = Buff Slot 2 = Min damage to trigger.
uint16 SpellThresholdGuard[3]; // 0 = Mitigation value 1 = Buff Slot 2 = Min damage to trigger.
uint16 MitigateSpellRune[4]; // 0 = Mitigation value 1 = Buff Slot 2 = Max mitigation per spell 3 = Rune Amt
uint16 MitigateDotRune[4]; // 0 = Mitigation value 1 = Buff Slot 2 = Max mitigation per tick 3 = Rune Amt
int32 SkillDamageAmount2[HIGHEST_SKILL+2]; // Adds skill specific damage
uint32 NegateAttacks[3]; // 0 = bool HasEffect 1 = Buff Slot 2 = Max damage absorbed per hit
uint32 MitigateMeleeRune[4]; // 0 = Mitigation value 1 = Buff Slot 2 = Max mitigation per hit 3 = Rune Amt
uint32 MeleeThresholdGuard[3]; // 0 = Mitigation value 1 = Buff Slot 2 = Min damage to trigger.
uint32 SpellThresholdGuard[3]; // 0 = Mitigation value 1 = Buff Slot 2 = Min damage to trigger.
uint32 MitigateSpellRune[4]; // 0 = Mitigation value 1 = Buff Slot 2 = Max mitigation per spell 3 = Rune Amt
uint32 MitigateDotRune[4]; // 0 = Mitigation value 1 = Buff Slot 2 = Max mitigation per tick 3 = Rune Amt
bool TriggerMeleeThreshold; // Has Melee Threshhold
bool TriggerSpellThreshold; // Has Spell Threshhold
uint16 ManaAbsorbPercentDamage[2]; // 0 = Mitigation value 1 = Buff Slot
int16 ShieldBlock; // Chance to Shield Block
int16 BlockBehind; // Chance to Block Behind (with our without shield)
uint32 ManaAbsorbPercentDamage[2]; // 0 = Mitigation value 1 = Buff Slot
int32 ShieldBlock; // Chance to Shield Block
int32 BlockBehind; // Chance to Block Behind (with our without shield)
bool CriticalRegenDecay; // increase critical regen chance, decays based on spell level cast
bool CriticalHealDecay; // increase critical heal chance, decays based on spell level cast
bool CriticalDotDecay; // increase critical dot chance, decays based on spell level cast
bool DivineAura; // invulnerability
bool DistanceRemoval; // Check if Cancle if Moved effect is present
int16 ImprovedTaunt[3]; // 0 = Max Level 1 = Aggro modifier 2 = buffid
int32 ImprovedTaunt[3]; // 0 = Max Level 1 = Aggro modifier 2 = buffid
int8 Root[2]; // The lowest buff slot a root can be found. [0] = Bool if has root [1] = buff slot
int16 FrenziedDevastation; // base1= AArank(used) base2= chance increase spell criticals + all DD spells 2x mana.
uint16 AbsorbMagicAtt[2]; // 0 = magic rune value 1 = buff slot
uint16 MeleeRune[2]; // 0 = rune value 1 = buff slot
int32 FrenziedDevastation; // base1= AArank(used) base2= chance increase spell criticals + all DD spells 2x mana.
uint32 AbsorbMagicAtt[2]; // 0 = magic rune value 1 = buff slot
uint32 MeleeRune[2]; // 0 = rune value 1 = buff slot
bool NegateIfCombat; // Bool Drop buff if cast or melee
int8 Screech; // -1 = Will be blocked if another Screech is +(1)
int16 AlterNPCLevel; // amount of lvls +/-
int16 AStacker[2]; // For buff stack blocking 0=Exists 1=Effect_value
int16 BStacker[2]; // For buff stack blocking 0=Exists 1=Effect_value
int16 CStacker[2]; // For buff stack blocking 0=Exists 1=Effect_value
int16 DStacker[2]; // For buff stack blocking 0=Exists 1=Effect_value
int32 AlterNPCLevel; // amount of lvls +/-
int32 AStacker[2]; // For buff stack blocking 0=Exists 1=Effect_value
int32 BStacker[2]; // For buff stack blocking 0=Exists 1=Effect_value
int32 CStacker[2]; // For buff stack blocking 0=Exists 1=Effect_value
int32 DStacker[2]; // For buff stack blocking 0=Exists 1=Effect_value
bool BerserkSPA; // berserk effect
int16 Metabolism; // Food/drink consumption rates.
int32 Metabolism; // Food/drink consumption rates.
bool Sanctuary; // Sanctuary effect, lowers place on hate list until cast on others.
int16 FactionModPct; // Modifies amount of faction gained.
int16 MeleeVulnerability; // Weakness/mitigation to melee damage
int32 FactionModPct; // Modifies amount of faction gained.
int32 MeleeVulnerability; // Weakness/mitigation to melee damage
bool LimitToSkill[HIGHEST_SKILL+2]; // Determines if we need to search for a skill proc.
uint16 SkillProc[MAX_SKILL_PROCS]; // Max number of spells containing skill_procs.
uint16 SkillProcSuccess[MAX_SKILL_PROCS]; // Max number of spells containing skill_procs_success.
uint32 SkillProc[MAX_SKILL_PROCS]; // Max number of spells containing skill_procs.
uint32 SkillProcSuccess[MAX_SKILL_PROCS]; // Max number of spells containing skill_procs_success.
// AAs
int8 Packrat; //weight reduction for items, 1 point = 10%
uint8 BuffSlotIncrease; // Increases number of available buff slots
uint16 DelayDeath; // how far below 0 hp you can go
uint32 DelayDeath; // how far below 0 hp you can go
int8 BaseMovementSpeed; // Adjust base run speed, does not stack with other movement bonuses.
uint8 IncreaseRunSpeedCap; // Increase max run speed above cap.
int16 DoubleSpecialAttack; // Chance to to perform a double special attack (ie flying kick 2x)
int16 SpecialAttackKBProc[2]; // Chance to to do a knockback from special attacks. (0 = chance 1 = Skill)
int32 DoubleSpecialAttack; // Chance to to perform a double special attack (ie flying kick 2x)
int32 SpecialAttackKBProc[2]; // Chance to to do a knockback from special attacks. (0 = chance 1 = Skill)
uint8 FrontalStunResist; // Chance to resist a frontal stun
int16 BindWound; // Increase amount of HP by percent.
int16 MaxBindWound; // Increase max amount of HP you can bind wound.
int16 ChannelChanceSpells; // Modify chance to channel a spell.
int16 ChannelChanceItems; // Modify chance to channel a items.
int32 BindWound; // Increase amount of HP by percent.
int32 MaxBindWound; // Increase max amount of HP you can bind wound.
int32 ChannelChanceSpells; // Modify chance to channel a spell.
int32 ChannelChanceItems; // Modify chance to channel a items.
uint8 SeeInvis; // See Invs.
uint8 TripleBackstab; // Chance to triple backstab
bool FrontalBackstabMinDmg; // Allow frontal backstabs for min damage
@@ -407,36 +410,36 @@ struct StatBonuses {
uint8 ConsumeProjectile; // Chance to not consume arrow.
uint8 ForageAdditionalItems; // Chance to forage another item.
uint8 SalvageChance; // Chance to salvage a tradeskill components on fail.
uint16 ArcheryDamageModifier; // Increase Archery Damage by percent
uint32 ArcheryDamageModifier; // Increase Archery Damage by percent
bool SecondaryDmgInc; // Allow off hand weapon to recieve damage bonus.
uint16 GiveDoubleAttack; // Allow classes to double attack with a specified chance.
int16 SlayUndead[2]; // Allow classes to do extra damage verse undead.(base1 = rate, base2 = damage mod)
int16 PetCriticalHit; // Allow pets to critical hit with % value.
int16 PetAvoidance; // Pet avoidance chance.
int16 CombatStability; // Melee damage mitigation.
int16 DoubleRiposte; // Chance to double riposte
int16 GiveDoubleRiposte[3]; // 0=Regular Chance, 1=Skill Attack Chance, 2=Skill
uint16 RaiseSkillCap[2]; // Raise a specific skill cap (1 = value, 2=skill)
int16 Ambidexterity; // Increase chance to duel wield by adding bonus 'skill'.
int16 PetMaxHP; // Increase the max hp of your pet.
int16 PetFlurry; // Chance for pet to flurry.
uint32 GiveDoubleAttack; // Allow classes to double attack with a specified chance.
int32 SlayUndead[2]; // Allow classes to do extra damage verse undead.(base1 = rate, base2 = damage mod)
int32 PetCriticalHit; // Allow pets to critical hit with % value.
int32 PetAvoidance; // Pet avoidance chance.
int32 CombatStability; // Melee damage mitigation.
int32 DoubleRiposte; // Chance to double riposte
int32 GiveDoubleRiposte[3]; // 0=Regular Chance, 1=Skill Attack Chance, 2=Skill
uint32 RaiseSkillCap[2]; // Raise a specific skill cap (1 = value, 2=skill)
int32 Ambidexterity; // Increase chance to duel wield by adding bonus 'skill'.
int32 PetMaxHP; // Increase the max hp of your pet.
int32 PetFlurry; // Chance for pet to flurry.
uint8 MasteryofPast; // Can not fizzle spells below this level specified in value.
bool GivePetGroupTarget; // All pets to recieve group buffs. (Pet Affinity)
int16 RootBreakChance; // Chance root will break;
int16 UnfailingDivinity; // Improves chance that DI will fire + increase partial heal.
int16 ItemHPRegenCap; // Increase item regen cap.
int16 SEResist[MAX_RESISTABLE_EFFECTS*2]; // Resist chance by specific spell effects.
int16 OffhandRiposteFail; // chance for opponent to fail riposte with offhand attack.
int16 ItemATKCap; // Raise item attack cap
int32 RootBreakChance; // Chance root will break;
int32 UnfailingDivinity; // Improves chance that DI will fire + increase partial heal.
int32 ItemHPRegenCap; // Increase item regen cap.
int32 SEResist[MAX_RESISTABLE_EFFECTS*2]; // Resist chance by specific spell effects.
int32 OffhandRiposteFail; // chance for opponent to fail riposte with offhand attack.
int32 ItemATKCap; // Raise item attack cap
int32 FinishingBlow[2]; // Chance to do a finishing blow for specified damage amount.
uint16 FinishingBlowLvl[2]; // Sets max level an NPC can be affected by FB. (base1 = lv, base2= ???)
int16 ShieldEquipHateMod; // Hate mod when shield equiped.
int16 ShieldEquipDmgMod[2]; // Damage mod when shield equiped. 0 = damage modifier 1 = Unknown
uint32 FinishingBlowLvl[2]; // Sets max level an NPC can be affected by FB. (base1 = lv, base2= ???)
int32 ShieldEquipHateMod; // Hate mod when shield equiped.
int32 ShieldEquipDmgMod[2]; // Damage mod when shield equiped. 0 = damage modifier 1 = Unknown
bool TriggerOnValueAmount; // Triggers off various different conditions, bool to check if client has effect.
int8 StunBashChance; // chance to stun with bash.
int8 IncreaseChanceMemwipe; // increases chance to memory wipe
int8 CriticalMend; // chance critical monk mend
int16 ImprovedReclaimEnergy; // Modifies amount of mana returned from reclaim energy
int32 ImprovedReclaimEnergy; // Modifies amount of mana returned from reclaim energy
uint32 HeadShot[2]; // Headshot AA (Massive dmg vs humaniod w/ archery) 0= ? 1= Dmg
uint8 HSLevel; // Max Level Headshot will be effective at.
uint32 Assassinate[2]; // Assassinate AA (Massive dmg vs humaniod w/ assassinate) 0= ? 1= Dmg
@@ -457,6 +460,24 @@ struct Shielders_Struct {
uint16 shielder_bonus;
};
typedef struct
{
uint16 increment;
uint16 hit_increment;
uint16 target_id;
int32 wpn_dmg;
float origin_x;
float origin_y;
float origin_z;
float tlast_x;
float tlast_y;
uint32 ranged_id;
uint32 ammo_id;
int ammo_slot;
uint8 skill;
float speed_mod;
} tProjatk;
//eventually turn this into a typedef and
//make DoAnim take it instead of int, to enforce its use.
enum { //type arguments to DoAnim
@@ -484,7 +505,7 @@ typedef enum {
petOther,
petCharmed,
petNPCFollow,
petHatelist //remain active as long something is on the hatelist. Don't listen to any commands
petTargetLock //remain active as long something is on the hatelist. Don't listen to any commands
} PetType;
typedef enum {
@@ -494,6 +515,8 @@ typedef enum {
GroupSpell, // causes effect to caster + target's group
CAHateList, // causes effect to all people on caster's hate list within some range
DirectionalAE,
Beam,
TargetRing,
CastActUnknown
} CastAction_type;
@@ -537,10 +560,8 @@ public:
// Audit trade
void LogTrade();
// Debug only method
#if (EQDEBUG >= 9)
void DumpTrade();
#endif
void DumpTrade();
public:
// Object state
@@ -563,7 +584,7 @@ struct ExtraAttackOptions {
: damage_percent(1.0f), damage_flat(0),
armor_pen_percent(0.0f), armor_pen_flat(0),
crit_percent(1.0f), crit_flat(0.0f),
hate_percent(1.0f), hate_flat(0)
hate_percent(1.0f), hate_flat(0), hit_chance(0)
{ }
float damage_percent;
@@ -574,6 +595,7 @@ struct ExtraAttackOptions {
float crit_flat;
float hate_percent;
int hate_flat;
int hit_chance;
};
#endif
+651 -1273
View File
File diff suppressed because it is too large Load Diff
+95 -81
View File
@@ -22,126 +22,140 @@
#include "mob.h"
class Client;
class EQApplicationPacket;
class Group;
class ItemInst;
class NPC;
class Raid;
struct ExtraAttackOptions;
struct NPCType;
#define MAX_LOOTERS 72
class Corpse : public Mob
{
public:
class Corpse : public Mob {
public:
static void SendEndLootErrorPacket(Client* client);
static void SendLootReqErrorPacket(Client* client, uint8 response = 2);
static Corpse* LoadFromDBData(uint32 in_corpseid, uint32 in_charid, char* in_charname, uchar* in_data, uint32 in_datasize, float in_x, float in_y, float in_z, float in_heading, char* timeofdeath, bool rezzed = false, bool wasAtGraveyard = false);
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, 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(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);
//abstract virtual function implementations requird by base abstract class
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 HasRaid() { return false; }
virtual bool HasGroup() { return false; }
virtual Raid* GetRaid() { return 0; }
virtual Group* GetGroup() { return 0; }
/* 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 HasRaid() { return false; }
virtual bool HasGroup() { return false; }
virtual Raid* GetRaid() { return 0; }
virtual Group* GetGroup() { return 0; }
inline uint32 GetCorpseDBID() { return corpse_db_id; }
inline char* GetOwnerName() { return corpse_name; }
bool IsEmpty() const;
bool IsCorpse() const { return true; }
bool IsPlayerCorpse() const { return is_player_corpse; }
bool IsNPCCorpse() const { return !is_player_corpse; }
bool IsBecomeNPCCorpse() const { return become_npc; }
virtual void DepopNPCCorpse();
virtual void DepopPlayerCorpse();
bool Process();
bool Save();
uint32 GetCharID() { return char_id; }
uint32 SetCharID(uint32 iCharID) { if (IsPlayerCorpse()) { return (char_id = iCharID); } return 0xFFFFFFFF; };
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 LoadPlayerCorpseDecayTime(uint32 dbid);
void Delete();
void Bury();
void CalcCorpseName();
void LoadPlayerCorpseDecayTime(uint32 dbid);
bool IsCorpse() const { return true; }
bool IsPlayerCorpse() const { return p_PlayerCorpse; }
bool IsNPCCorpse() const { return !p_PlayerCorpse; }
bool IsBecomeNPCCorpse() const { return become_npc; }
bool Process();
bool Save();
uint32 GetCharID() { return charid; }
uint32 SetCharID(uint32 iCharID) { if (IsPlayerCorpse()) { return (charid=iCharID); } return 0xFFFFFFFF; };
uint32 GetDecayTime() { if (!corpse_decay_timer.Enabled()) return 0xFFFFFFFF; else return corpse_decay_timer.GetRemainingTime(); }
uint32 GetResTime() { if (!corpse_res_timer.Enabled()) return 0; else return corpse_res_timer.GetRemainingTime(); }
void CalcCorpseName();
inline void Lock() { pLocked = true; }
inline void UnLock() { pLocked = false; }
inline bool IsLocked() { return pLocked; }
inline void ResetLooter() { BeingLootedBy = 0xFFFFFFFF; }
inline bool IsBeingLooted() { return (BeingLootedBy != 0xFFFFFFFF); }
inline uint32 GetDBID() { return dbid; }
inline char* GetOwnerName() { return orgname;}
void SetDecayTimer(uint32 decaytime);
bool IsEmpty() const;
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 GetWornItem(int16 equipSlot) const;
ServerLootItem_Struct* GetItem(uint16 lootslot, ServerLootItem_Struct** bag_item_data = 0);
/* Corpse: Items */
uint32 GetWornItem(int16 equipSlot) const;
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; }
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);
/* Corpse: Coin */
void SetCash(uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_platinum);
void RemoveCash();
void QueryLoot(Client* to);
uint32 CountItems();
void Delete();
void Bury();
virtual void Depop();
virtual void DepopCorpse();
uint32 GetCopper() { return copper; }
uint32 GetSilver() { return silver; }
uint32 GetGold() { return gold; }
uint32 GetPlatinum() { return platinum; }
void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
void MakeLootRequestPackets(Client* client, const EQApplicationPacket* app);
/* Corpse: Resurrection */
bool IsRezzed() { return rez; }
void IsRezzed(bool in_rez) { rez = in_rez; }
void CastRezz(uint16 spellid, Mob* Caster);
void CompleteResurrection();
/* Corpse: Loot */
void QueryLoot(Client* to);
void LootItem(Client* client, const EQApplicationPacket* app);
void EndLoot(Client* client, const EQApplicationPacket* app);
bool Summon(Client* client, bool spell, bool CheckDistance);
void CastRezz(uint16 spellid, Mob* Caster);
void CompleteRezz();
void SetPKItem(int32 id) { pkitem = id; }
int32 GetPKItem() { return pkitem; }
bool CanMobLoot(int charid);
void AllowMobLoot(Mob *them, uint8 slot);
void AddLooter(Mob *who);
bool Rezzed() { return rez; }
void Rezzed(bool in_rez) { rez = in_rez; }
void Spawn();
void MakeLootRequestPackets(Client* client, const EQApplicationPacket* app);
void AllowPlayerLoot(Mob *them, uint8 slot);
void AddLooter(Mob *who);
uint32 CountItems();
bool CanPlayerLoot(int charid);
char orgname[64];
uint32 GetEquipment(uint8 material_slot) const; // returns item id
uint32 GetEquipmentColor(uint8 material_slot) const;
inline int GetRezzExp() { return rezzexp; }
inline void Lock() { is_locked = true; }
inline void UnLock() { is_locked = false; }
inline bool IsLocked() { return is_locked; }
inline void ResetLooter() { being_looted_by = 0xFFFFFFFF; }
inline bool IsBeingLooted() { return (being_looted_by != 0xFFFFFFFF); }
// these are a temporary work-around until corpse inventory is removed from the database blob
//static uint32 ServerToCorpseSlot(int16 server_slot); // encode
//static int16 CorpseToServerSlot(uint32 corpse_slot); // decode
/* Mob */
void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
bool Summon(Client* client, bool spell, bool CheckDistance);
void Spawn();
char corpse_name[64];
uint32 GetEquipment(uint8 material_slot) const;
uint32 GetEquipmentColor(uint8 material_slot) const;
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 p_PlayerCorpse; bool pIsChanged;
bool pLocked;
int32 pkitem;
uint32 dbid;
uint32 charid;
ItemList itemlist;
bool is_player_corpse; /* Determines if Player Corpse or not */
bool is_corpse_changed; /* Determines if corpse has changed or not */
bool is_locked; /* Determines if corpse is locked */
int32 player_kill_item; /* Determines if Player Kill Item */
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 silver;
uint32 gold;
uint32 platinum;
bool p_depop;
uint32 BeingLootedBy;
uint32 rezzexp;
bool player_corpse_depop; /* Sets up Corpse::Process to depop the player corpse */
uint32 being_looted_by; /* Determines what the corpse is being looted by internally for logic */
uint32 rez_experience; /* Amount of experience that the corpse would rez for */
bool rez;
bool can_rez;
bool can_corpse_be_rezzed; /* Bool declaring whether or not a corpse can be rezzed */
bool become_npc;
int looters[MAX_LOOTERS]; // People allowed to loot the corpse, character id
Timer corpse_decay_timer;
Timer corpse_res_timer;
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_graveyard_timer;
Timer loot_cooldown_timer;
Timer loot_cooldown_timer; /* Delay between loot actions on the corpse entity */
Color_Struct item_tint[9];
};
#endif
+46 -77
View File
@@ -15,18 +15,22 @@
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 <iostream>
#include <stdlib.h>
#include <string.h>
#include "masterentity.h"
#include "worldserver.h"
#include "string_ids.h"
#include "zonedb.h"
#include "../common/packet_functions.h"
#include "../common/packet_dump.h"
#include "../common/global_define.h"
#include "../common/eqemu_logsys.h"
#include "../common/string_util.h"
#include "client.h"
#include "doors.h"
#include "entity.h"
#include "guild_mgr.h"
#include "mob.h"
#include "string_ids.h"
#include "worldserver.h"
#include "zonedb.h"
#include <iostream>
#include <string.h>
#define OPEN_DOOR 0x02
#define CLOSE_DOOR 0x03
@@ -36,21 +40,19 @@
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;
lockpick = door->lockpick;
lockpick = door->lock_pick;
keyitem = door->keyitem;
nokeyring = door->nokeyring;
trigger_door = door->trigger_door;
@@ -63,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;
@@ -103,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;
@@ -141,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;
@@ -298,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)
{
@@ -419,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())))
{
@@ -429,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);
}
}
}
@@ -556,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) {
@@ -574,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;
}
@@ -601,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;
}
@@ -625,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;
}
@@ -641,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;
@@ -653,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;
}
@@ -678,7 +664,7 @@ bool ZoneDatabase::LoadDoors(int32 iDoorCount, Door *into, const char *zone_name
into[rowIndex].heading = (float)atof(row[7]);
into[rowIndex].opentype = atoi(row[8]);
into[rowIndex].guild_id = atoi(row[9]);
into[rowIndex].lockpick = atoi(row[10]);
into[rowIndex].lock_pick = atoi(row[10]);
into[rowIndex].keyitem = atoi(row[11]);
into[rowIndex].nokeyring = atoi(row[12]);
into[rowIndex].trigger_door = atoi(row[13]);
@@ -706,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();
}
@@ -764,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());
}
+15 -26
View File
@@ -1,19 +1,23 @@
#ifndef DOORS_H
#define DOORS_H
#include "../common/types.h"
#include "../common/linked_list.h"
#include "../common/timer.h"
#include "../common/emu_opcodes.h"
#include "../common/eq_packet_structs.h"
#include "entity.h"
#include "../common/linked_list.h"
#include "mob.h"
#include "zonedump.h"
class Client;
class Mob;
class NPC;
struct Door;
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);
@@ -25,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; }
@@ -50,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; }
@@ -63,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();
@@ -80,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;
@@ -102,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;
+160 -183
View File
@@ -15,22 +15,21 @@
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 "masterentity.h"
#include "../common/global_define.h"
#include "../common/eqemu_logsys.h"
#include "../common/spdat.h"
#include "client.h"
#include "entity.h"
#include "mob.h"
#include "string_ids.h"
#include "worldserver.h"
#include "zonedb.h"
#include "../common/spdat.h"
#include "../common/packet_dump.h"
#include "../common/packet_functions.h"
#include "petitions.h"
#include "../common/serverinfo.h"
#include "../common/zone_numbers.h"
#include "../common/moremath.h"
#include "../common/guilds.h"
#include "string_ids.h"
#include "npc_ai.h"
#include "position.h"
float Client::GetActSpellRange(uint16 spell_id, float range, bool IsBard)
float Mob::GetActSpellRange(uint16 spell_id, float range, bool IsBard)
{
float extrange = 100;
@@ -39,99 +38,58 @@ float Client::GetActSpellRange(uint16 spell_id, float range, bool IsBard)
return (range * extrange) / 100;
}
int32 NPC::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
//Quest scale all NPC spell damage via $npc->SetSpellFocusDMG(value)
//DoT Damage - Mob::DoBuffTic [spell_effects.cpp] / Direct Damage Mob::SpellEffect [spell_effects.cpp]
int32 dmg = value;
if (target) {
value += dmg*target->GetVulnerability(this, spell_id, 0)/100;
if (spells[spell_id].buffduration == 0)
value -= target->GetFcDamageAmtIncoming(this, spell_id);
else
value -= target->GetFcDamageAmtIncoming(this, spell_id)/spells[spell_id].buffduration;
}
value += dmg*GetSpellFocusDMG()/100;
if (AI_HasSpellsEffects()){
int16 chance = 0;
int ratio = 0;
if (spells[spell_id].buffduration == 0) {
chance += spellbonuses.CriticalSpellChance + spellbonuses.FrenziedDevastation;
if (chance && MakeRandomInt(1,100) <= chance){
ratio += spellbonuses.SpellCritDmgIncrease + spellbonuses.SpellCritDmgIncNoStack;
value += (value*ratio)/100;
entity_list.MessageClose_StringID(this, true, 100, MT_SpellCrits, OTHER_CRIT_BLAST, GetCleanName(), itoa(-value));
}
}
else {
chance += spellbonuses.CriticalDoTChance;
if (chance && MakeRandomInt(1,100) <= chance){
ratio += spellbonuses.DotCritDmgIncrease;
value += (value*ratio)/100;
}
}
}
return value;
}
int32 Client::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
if (spells[spell_id].targettype == ST_Self)
return value;
if (IsNPC())
value += value*CastToNPC()->GetSpellFocusDMG()/100;
bool Critical = false;
int32 value_BaseEffect = 0;
int chance = 0;
value_BaseEffect = value + (value*GetFocusEffect(focusFcBaseEffects, spell_id)/100);
// Need to scale HT damage differently after level 40! It no longer scales by the constant value in the spell file. It scales differently, instead of 10 more damage per level, it does 30 more damage per level. So we multiply the level minus 40 times 20 if they are over level 40.
if ( (spell_id == SPELL_HARM_TOUCH || spell_id == SPELL_HARM_TOUCH2 || spell_id == SPELL_IMP_HARM_TOUCH ) && GetLevel() > 40)
if ((spell_id == SPELL_HARM_TOUCH || spell_id == SPELL_HARM_TOUCH2 || spell_id == SPELL_IMP_HARM_TOUCH ) && GetLevel() > 40)
value -= (GetLevel() - 40) * 20;
//This adds the extra damage from the AA Unholy Touch, 450 per level to the AA Improved Harm TOuch.
if (spell_id == SPELL_IMP_HARM_TOUCH) //Improved Harm Touch
if (spell_id == SPELL_IMP_HARM_TOUCH && IsClient()) //Improved Harm Touch
value -= GetAA(aaUnholyTouch) * 450; //Unholy Touch
int chance = RuleI(Spells, BaseCritChance); //Wizard base critical chance is 2% (Does not scale with level)
chance = RuleI(Spells, BaseCritChance); //Wizard base critical chance is 2% (Does not scale with level)
chance += itembonuses.CriticalSpellChance + spellbonuses.CriticalSpellChance + aabonuses.CriticalSpellChance;
chance += itembonuses.FrenziedDevastation + spellbonuses.FrenziedDevastation + aabonuses.FrenziedDevastation;
if (chance > 0 || (GetClass() == WIZARD && GetLevel() >= RuleI(Spells, WizCritLevel))) {
//Crtical Hit Calculation pathway
if (chance > 0 || (IsClient() && GetClass() == WIZARD && GetLevel() >= RuleI(Spells, WizCritLevel))) {
int32 ratio = RuleI(Spells, BaseCritRatio); //Critical modifier is applied from spell effects only. Keep at 100 for live like criticals.
//Improved Harm Touch is a guaranteed crit if you have at least one level of SCF.
if (spell_id == SPELL_IMP_HARM_TOUCH && (GetAA(aaSpellCastingFury) > 0) && (GetAA(aaUnholyTouch) > 0))
if (spell_id == SPELL_IMP_HARM_TOUCH && IsClient() && (GetAA(aaSpellCastingFury) > 0) && (GetAA(aaUnholyTouch) > 0))
chance = 100;
if (MakeRandomInt(1,100) <= chance){
if (zone->random.Roll(chance)) {
Critical = true;
ratio += itembonuses.SpellCritDmgIncrease + spellbonuses.SpellCritDmgIncrease + aabonuses.SpellCritDmgIncrease;
ratio += itembonuses.SpellCritDmgIncNoStack + spellbonuses.SpellCritDmgIncNoStack + aabonuses.SpellCritDmgIncNoStack;
}
else if (GetClass() == WIZARD && (GetLevel() >= RuleI(Spells, WizCritLevel)) && (MakeRandomInt(1,100) <= RuleI(Spells, WizCritChance))) {
ratio += MakeRandomInt(20,70); //Wizard innate critical chance is calculated seperately from spell effect and is not a set ratio. (20-70 is parse confirmed)
Critical = true;
else if ((IsClient() && GetClass() == WIZARD) || (IsMerc() && GetClass() == CASTERDPS)) {
if ((GetLevel() >= RuleI(Spells, WizCritLevel)) && zone->random.Roll(RuleI(Spells, WizCritChance))){
//Wizard innate critical chance is calculated seperately from spell effect and is not a set ratio. (20-70 is parse confirmed)
ratio += zone->random.Int(20,70);
Critical = true;
}
}
ratio += RuleI(Spells, WizCritRatio); //Default is zero
if (IsClient() && GetClass() == WIZARD)
ratio += RuleI(Spells, WizCritRatio); //Default is zero
if (Critical){
value = value_BaseEffect*ratio/100;
@@ -152,14 +110,19 @@ int32 Client::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5)
value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value)*ratio/100;
else if (IsNPC() && CastToNPC()->GetSpellScale())
value = int(static_cast<float>(value) * CastToNPC()->GetSpellScale() / 100.0f);
entity_list.MessageClose_StringID(this, true, 100, MT_SpellCrits,
OTHER_CRIT_BLAST, GetName(), itoa(-value));
Message_StringID(MT_SpellCrits, YOU_CRIT_BLAST, itoa(-value));
if (IsClient())
Message_StringID(MT_SpellCrits, YOU_CRIT_BLAST, itoa(-value));
return value;
}
}
//Non Crtical Hit Calculation pathway
value = value_BaseEffect;
value += value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100;
@@ -178,14 +141,20 @@ int32 Client::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5)
value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value);
if (IsNPC() && CastToNPC()->GetSpellScale())
value = int(static_cast<float>(value) * CastToNPC()->GetSpellScale() / 100.0f);
return value;
}
int32 Client::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) {
int32 Mob::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) {
if (target == nullptr)
return value;
if (IsNPC())
value += value*CastToNPC()->GetSpellFocusDMG()/100;
int32 value_BaseEffect = 0;
int32 extra_dmg = 0;
int16 chance = 0;
@@ -193,22 +162,16 @@ int32 Client::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) {
if (spellbonuses.CriticalDotDecay)
chance += GetDecayEffectValue(spell_id, SE_CriticalDotDecay);
value_BaseEffect = value + (value*GetFocusEffect(focusFcBaseEffects, spell_id)/100);
if (chance > 0 && (MakeRandomInt(1, 100) <= chance)) {
if (chance > 0 && (zone->random.Roll(chance))) {
int32 ratio = 200;
ratio += itembonuses.DotCritDmgIncrease + spellbonuses.DotCritDmgIncrease + aabonuses.DotCritDmgIncrease;
value = value_BaseEffect*ratio/100;
value += int(value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100)*ratio/100;
value = value_BaseEffect*ratio/100;
value += int(value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100)*ratio/100;
value += int(value_BaseEffect*GetFocusEffect(focusFcDamagePctCrit, spell_id)/100)*ratio/100;
value += int(value_BaseEffect*target->GetVulnerability(this, spell_id, 0)/100)*ratio/100;
value += int(value_BaseEffect*target->GetVulnerability(this, spell_id, 0)/100)*ratio/100;
extra_dmg = target->GetFcDamageAmtIncoming(this, spell_id) +
int(GetFocusEffect(focusFcDamageAmtCrit, spell_id)*ratio/100) +
GetFocusEffect(focusFcDamageAmt, spell_id);
@@ -216,34 +179,32 @@ int32 Client::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) {
if (extra_dmg) {
int duration = CalcBuffDuration(this, this, spell_id);
if (duration > 0)
extra_dmg /= duration;
extra_dmg /= duration;
}
value -= extra_dmg;
}
else {
return value;
value = value_BaseEffect;
value += value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100;
value += value_BaseEffect*GetFocusEffect(focusFcDamagePctCrit, spell_id)/100;
value += value_BaseEffect*target->GetVulnerability(this, spell_id, 0)/100;
extra_dmg = target->GetFcDamageAmtIncoming(this, spell_id) +
GetFocusEffect(focusFcDamageAmtCrit, spell_id) +
GetFocusEffect(focusFcDamageAmt, spell_id);
if (extra_dmg) {
int duration = CalcBuffDuration(this, this, spell_id);
if (duration > 0)
extra_dmg /= duration;
}
value -= extra_dmg;
}
value = value_BaseEffect;
value += value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100;
value += value_BaseEffect*GetFocusEffect(focusFcDamagePctCrit, spell_id)/100;
value += value_BaseEffect*target->GetVulnerability(this, spell_id, 0)/100;
extra_dmg = target->GetFcDamageAmtIncoming(this, spell_id) +
GetFocusEffect(focusFcDamageAmtCrit, spell_id) +
GetFocusEffect(focusFcDamageAmt, spell_id);
if (extra_dmg) {
int duration = CalcBuffDuration(this, this, spell_id);
if (duration > 0)
extra_dmg /= duration;
}
value -= extra_dmg;
if (IsNPC() && CastToNPC()->GetSpellScale())
value = int(static_cast<float>(value) * CastToNPC()->GetSpellScale() / 100.0f);
return value;
}
@@ -260,7 +221,7 @@ int32 Mob::GetExtraSpellAmt(uint16 spell_id, int32 extra_spell_amt, int32 base_s
if (total_cast_time > 0 && total_cast_time <= 2500)
extra_spell_amt = extra_spell_amt*25/100;
else if (total_cast_time > 2500 && total_cast_time < 7000)
extra_spell_amt = extra_spell_amt*(0.167*((total_cast_time - 1000)/1000));
extra_spell_amt = extra_spell_amt*(167*((total_cast_time - 1000)/1000)) / 1000;
else
extra_spell_amt = extra_spell_amt * total_cast_time / 7000;
@@ -270,41 +231,14 @@ int32 Mob::GetExtraSpellAmt(uint16 spell_id, int32 extra_spell_amt, int32 base_s
return extra_spell_amt;
}
int32 NPC::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
//Scale all NPC spell healing via SetSpellFocusHeal(value)
value += value*GetSpellFocusHeal()/100;
if (target) {
value += target->GetFocusIncoming(focusFcHealAmtIncoming, SE_FcHealAmtIncoming, this, spell_id);
value += value*target->GetHealRate(spell_id, this)/100;
}
//Allow for critical heal chance if NPC is loading spell effect bonuses.
if (AI_HasSpellsEffects()){
if(spells[spell_id].buffduration < 1) {
if(spellbonuses.CriticalHealChance && (MakeRandomInt(0,99) < spellbonuses.CriticalHealChance)) {
value = value*2;
entity_list.MessageClose_StringID(this, true, 100, MT_SpellCrits, OTHER_CRIT_HEAL, GetCleanName(), itoa(value));
}
}
else if(spellbonuses.CriticalHealOverTime && (MakeRandomInt(0,99) < spellbonuses.CriticalHealOverTime)) {
value = value*2;
}
}
return value;
}
int32 Client::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
int32 Mob::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
if (target == nullptr)
target = this;
if (IsNPC())
value += value*CastToNPC()->GetSpellFocusHeal()/100;
int32 value_BaseEffect = 0;
int16 chance = 0;
int8 modifier = 1;
@@ -326,7 +260,7 @@ int32 Client::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
if (spellbonuses.CriticalHealDecay)
chance += GetDecayEffectValue(spell_id, SE_CriticalHealDecay);
if(chance && (MakeRandomInt(0,99) < chance)) {
if(chance && (zone->random.Roll(chance))) {
Critical = true;
modifier = 2; //At present time no critical heal amount modifier SPA exists.
}
@@ -341,10 +275,15 @@ int32 Client::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
value += value*target->GetHealRate(spell_id, this)/100;
if (IsNPC() && CastToNPC()->GetHealScale())
value = int(static_cast<float>(value) * CastToNPC()->GetHealScale() / 100.0f);
if (Critical) {
entity_list.MessageClose_StringID(this, true, 100, MT_SpellCrits,
OTHER_CRIT_HEAL, GetName(), itoa(value));
Message_StringID(MT_SpellCrits, YOU_CRIT_HEAL, itoa(value));
if (IsClient())
Message_StringID(MT_SpellCrits, YOU_CRIT_HEAL, itoa(value));
}
return value;
@@ -360,10 +299,13 @@ int32 Client::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
if (spellbonuses.CriticalRegenDecay)
chance += GetDecayEffectValue(spell_id, SE_CriticalRegenDecay);
if(chance && (MakeRandomInt(0,99) < chance))
return (value * 2);
if(chance && zone->random.Roll(chance))
value *= 2;
}
if (IsNPC() && CastToNPC()->GetHealScale())
value = int(static_cast<float>(value) * CastToNPC()->GetHealScale() / 100.0f);
return value;
}
@@ -374,12 +316,12 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost)
int16 FrenziedDevastation = itembonuses.FrenziedDevastation + spellbonuses.FrenziedDevastation + aabonuses.FrenziedDevastation;
if (FrenziedDevastation && IsPureNukeSpell(spell_id))
cost *= 2;
cost *= 2;
// Formula = Unknown exact, based off a random percent chance up to mana cost(after focuses) of the cast spell
if(this->itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5)
if(itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5)
{
int16 mana_back = this->itembonuses.Clairvoyance * MakeRandomInt(1, 100) / 100;
int16 mana_back = itembonuses.Clairvoyance * zone->random.Int(1, 100) / 100;
// Doesnt generate mana, so best case is a free spell
if(mana_back > cost)
mana_back = cost;
@@ -392,7 +334,7 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost)
// WildcardX
float PercentManaReduction = 0;
float SpecializeSkill = GetSpecializeSkillValue(spell_id);
int SuccessChance = MakeRandomInt(0, 100);
int SuccessChance = zone->random.Int(0, 100);
float bonus = 1.0;
switch(GetAA(aaSpellCastingMastery))
@@ -408,11 +350,11 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost)
break;
}
bonus += 0.05 * GetAA(aaAdvancedSpellCastingMastery);
bonus += 0.05f * GetAA(aaAdvancedSpellCastingMastery);
if(SuccessChance <= (SpecializeSkill * 0.3 * bonus))
{
PercentManaReduction = 1 + 0.05 * SpecializeSkill;
PercentManaReduction = 1 + 0.05f * SpecializeSkill;
switch(GetAA(aaSpellCastingMastery))
{
case 1:
@@ -444,14 +386,14 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost)
if(focus_redux > 0)
{
PercentManaReduction += MakeRandomFloat(1, (double)focus_redux);
PercentManaReduction += zone->random.Real(1, (double)focus_redux);
}
cost -= (cost * (PercentManaReduction / 100));
// Gift of Mana - reduces spell cost to 1 mana
if(focus_redux >= 100) {
uint32 buff_max = GetMaxTotalSlots();
int buff_max = GetMaxTotalSlots();
for (int buffSlot = 0; buffSlot < buff_max; buffSlot++) {
if (buffs[buffSlot].spellid == 0 || buffs[buffSlot].spellid >= SPDAT_RECORDS)
continue;
@@ -469,7 +411,7 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost)
return cost;
}
int32 Client::GetActSpellDuration(uint16 spell_id, int32 duration)
int32 Mob::GetActSpellDuration(uint16 spell_id, int32 duration)
{
if (spells[spell_id].not_extendable)
return duration;
@@ -481,7 +423,7 @@ int32 Client::GetActSpellDuration(uint16 spell_id, int32 duration)
// Only need this for clients, since the change was for bard songs, I assume we should keep non bard songs getting +1
// However if its bard or not and is mez, charm or fear, we need to add 1 so that client is in sync
if (!(IsShortDurationBuff(spell_id) && IsBardSong(spell_id)) ||
if (IsClient() && !(IsShortDurationBuff(spell_id) && IsBardSong(spell_id)) ||
IsFearSpell(spell_id) ||
IsCharmSpell(spell_id) ||
IsMezSpell(spell_id) ||
@@ -520,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);
}
@@ -682,20 +624,21 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) {
if(spell.recast_time > 0)
{
uint32 reduced_recast = spell.recast_time / 1000;
reduced_recast -= CastToClient()->GetFocusEffect(focusReduceRecastTime, spell_id);
if(reduced_recast < 0)
reduced_recast -= GetFocusEffect(focusReduceRecastTime, spell_id);
if(reduced_recast <= 0){
reduced_recast = 0;
CastSpell(spell_id, target, DISCIPLINE_SPELL_SLOT, -1, -1, 0, -1, (uint32)DiscTimer, reduced_recast);
if(spells[spell_id].EndurTimerIndex < MAX_DISCIPLINE_TIMERS)
{
EQApplicationPacket *outapp = new EQApplicationPacket(OP_DisciplineTimer, sizeof(DisciplineTimer_Struct));
DisciplineTimer_Struct *dts = (DisciplineTimer_Struct *)outapp->pBuffer;
dts->TimerID = spells[spell_id].EndurTimerIndex;
dts->Duration = reduced_recast;
QueuePacket(outapp);
safe_delete(outapp);
if (GetPTimers().Enabled((uint32)DiscTimer))
GetPTimers().Clear(&database, (uint32)DiscTimer);
}
if (reduced_recast > 0)
CastSpell(spell_id, target, DISCIPLINE_SPELL_SLOT, -1, -1, 0, -1, (uint32)DiscTimer, reduced_recast);
else{
CastSpell(spell_id, target, DISCIPLINE_SPELL_SLOT);
return true;
}
SendDisciplineTimer(spells[spell_id].EndurTimerIndex, reduced_recast);
}
else
{
@@ -704,6 +647,19 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) {
return(true);
}
void Client::SendDisciplineTimer(uint32 timer_id, uint32 duration)
{
if (timer_id < MAX_DISCIPLINE_TIMERS)
{
EQApplicationPacket *outapp = new EQApplicationPacket(OP_DisciplineTimer, sizeof(DisciplineTimer_Struct));
DisciplineTimer_Struct *dts = (DisciplineTimer_Struct *)outapp->pBuffer;
dts->TimerID = timer_id;
dts->Duration = duration;
QueuePacket(outapp);
safe_delete(outapp);
}
}
void EntityList::AETaunt(Client* taunter, float range)
{
if (range == 0)
@@ -719,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);
}
@@ -728,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)
@@ -742,7 +698,11 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_
bool bad = IsDetrimentalSpell(spell_id);
bool isnpc = caster->IsNPC();
const int MAX_TARGETS_ALLOWED = 4;
int MAX_TARGETS_ALLOWED = 4;
if (spells[spell_id].aemaxtargets)
MAX_TARGETS_ALLOWED = spells[spell_id].aemaxtargets;
int iCounter = 0;
for (auto it = mob_list.begin(); it != mob_list.end(); ++it) {
@@ -754,8 +714,20 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_
continue;
if (curmob == caster && !affect_caster) //watch for caster too
continue;
dist_targ = center->DistNoRoot(*curmob);
if (spells[spell_id].targettype == ST_TargetAENoPlayersPets && curmob->IsPetOwnerClient())
continue;
if (spells[spell_id].targettype == ST_AreaClientOnly && !curmob->IsClient())
continue;
if (spells[spell_id].targettype == ST_AreaNPCOnly && !curmob->IsNPC())
continue;
if (spells[spell_id].targettype == ST_Ring) {
dist_targ = DistanceSquared(static_cast<glm::vec3>(curmob->GetPosition()), caster->GetTargetRingLocation());
}
else if (center) {
dist_targ = DistanceSquared(curmob->GetPosition(), center->GetPosition());
}
if (dist_targ > dist2) //make sure they are in range
continue;
if (dist_targ < min_range2) //make sure they are in range
@@ -777,7 +749,9 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_
if (bad) {
if (!caster->IsAttackAllowed(curmob, true))
continue;
if (!center->CheckLosFN(curmob))
if (center && !spells[spell_id].npc_no_los && !center->CheckLosFN(curmob))
continue;
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.
@@ -797,10 +771,13 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_
caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust);
}
} else {
caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust);
if (spells[spell_id].aemaxtargets && iCounter < spells[spell_id].aemaxtargets)
caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust);
if (!spells[spell_id].aemaxtargets)
caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust);
}
if (!isnpc) //npcs are not target limited...
if (!isnpc || spells[spell_id].aemaxtargets) //npcs are not target limited (unless casting a spell with a target limit)...
iCounter++;
}
}
@@ -820,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...
@@ -843,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)
@@ -862,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);
@@ -912,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++;
+22 -4
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();
}
@@ -232,6 +233,7 @@ int PerlembParser::EventGlobalPlayer(QuestEventID evt, Client *client, std::stri
int PerlembParser::EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers) {
// needs pointer validation on 'item' argument
return EventCommon(evt, item->GetID(), nullptr, nullptr, item, client, extra_data, false, extra_pointers);
}
@@ -335,6 +337,9 @@ bool PerlembParser::ItemHasQuestSub(ItemInst *itm, QuestEventID evt) {
if(!perl)
return false;
if (itm == nullptr)
return false;
if(evt >= _LargestEventID)
return false;
@@ -449,6 +454,9 @@ void PerlembParser::LoadGlobalPlayerScript(std::string filename) {
}
void PerlembParser::LoadItemScript(std::string filename, ItemInst *item) {
if (item == nullptr)
return;
std::stringstream package_name;
package_name << "qst_item_" << item->GetID();
@@ -855,6 +863,7 @@ void PerlembParser::GetQuestPackageName(bool &isPlayerQuest, bool &isGlobalPlaye
}
}
else if(isItemQuest) {
// need a valid ItemInst pointer check here..unsure how to cancel this process -U
const Item_Struct* item = iteminst->GetItem();
package_name = "qst_item_";
package_name += itoa(item->ID);
@@ -1135,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);
@@ -1146,7 +1155,7 @@ void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID
temp_var_name = var_name;
temp_var_name += "_attuned";
ExportVar(package_name.c_str(), temp_var_name.c_str(), inst->IsInstNoDrop());
ExportVar(package_name.c_str(), temp_var_name.c_str(), inst->IsAttuned());
} else {
ExportVar(package_name.c_str(), var_name.c_str(), 0);
@@ -1282,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);
@@ -1292,6 +1308,7 @@ void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID
case EVENT_SCALE_CALC:
case EVENT_ITEM_ENTER_ZONE: {
// need a valid ItemInst pointer check here..unsure how to cancel this process -U
ExportVar(package_name.c_str(), "itemid", objid);
ExportVar(package_name.c_str(), "itemname", iteminst->GetItem()->Name);
break;
@@ -1299,6 +1316,7 @@ void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID
case EVENT_ITEM_CLICK_CAST:
case EVENT_ITEM_CLICK: {
// need a valid ItemInst pointer check here..unsure how to cancel this process -U
ExportVar(package_name.c_str(), "itemid", objid);
ExportVar(package_name.c_str(), "itemname", iteminst->GetItem()->Name);
ExportVar(package_name.c_str(), "slotid", extradata);
+342 -249
View File
@@ -21,17 +21,19 @@
#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 "questmgr.h"
#include "embxs.h"
#include "entity.h"
#include "zone.h"
#include "queryserv.h"
#include "questmgr.h"
#include "zone.h"
extern Zone* zone;
extern QueryServ* QServ;
extern QueryServ* QServ;
/*
@@ -218,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);
@@ -242,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);
@@ -274,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);
@@ -1174,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);
@@ -1321,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;
}
@@ -1394,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;
}
@@ -1521,7 +1516,7 @@ XS(XS__ChooseRandom)
if (items < 1)
Perl_croak(aTHX_ "Usage: ChooseRandom(... list ...)");
int index = MakeRandomInt(0, items-1);
int index = zone->random.Int(0, items-1);
SV *tmp = ST(0);
ST(0) = ST(index);
@@ -1749,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));
@@ -1770,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));
@@ -2278,18 +2267,22 @@ XS(XS__updatetaskactivity)
dXSARGS;
unsigned int task, activity;
int count = 1;
bool ignore_quest_update = false;
if(items == 2) {
task = (int)SvIV(ST(0));
activity = (int)SvIV(ST(1));
quest_manager.updatetaskactivity(task, activity, count);
quest_manager.updatetaskactivity(task, activity, count, false);
}
else if(items == 3) {
else if (items == 3 || items == 4) {
task = (int)SvIV(ST(0));
activity = (int)SvIV(ST(1));
count = (int)SvIV(ST(2));
quest_manager.updatetaskactivity(task, activity, count);
if (items == 4){
bool ignore_quest_update = (bool)SvTRUE(ST(3));
}
quest_manager.updatetaskactivity(task, activity, count, ignore_quest_update);
} else {
Perl_croak(aTHX_ "Usage: updatetaskactivity(task, activity [,count])");
Perl_croak(aTHX_ "Usage: updatetaskactivity(task, activity, [count], [ignore_quest_update])");
}
XSRETURN_EMPTY;
@@ -2668,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);
@@ -2699,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);
}
@@ -2859,14 +2852,54 @@ XS(XS__GetInstanceID) {
XSRETURN_UV(id);
}
XS(XS__GetCharactersInInstance);
XS(XS__GetCharactersInInstance) {
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: GetCharactersInInstance(instance_id)");
dXSTARG;
Const_char * RETVAL;
uint16 instance_id = (int)SvUV(ST(0));
std::list<uint32> charid_list;
std::string charid_string;
database.GetCharactersInInstance(instance_id, charid_list);
if (charid_list.size() > 0)
{
charid_string = itoa(charid_list.size());
charid_string += " player(s) in instance: ";
auto iter = charid_list.begin();
while (iter != charid_list.end())
{
char char_name[64];
database.GetCharName(*iter, char_name);
charid_string += char_name;
charid_string += "(";
charid_string += itoa(*iter);
charid_string += ")";
++iter;
if (iter != charid_list.end())
charid_string += ", ";
}
RETVAL = charid_string.c_str();
}
else
RETVAL = "No players in that instance.";
sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG;
XSRETURN(1);
}
XS(XS__AssignToInstance);
XS(XS__AssignToInstance) {
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: AssignToInstance(id)");
Perl_croak(aTHX_ "Usage: AssignToInstance(instance_id)");
uint16 id = (int)SvUV(ST(0));
quest_manager.AssignToInstance(id);
uint16 instance_id = (int)SvUV(ST(0));
quest_manager.AssignToInstance(instance_id);
XSRETURN_EMPTY;
}
@@ -2875,10 +2908,10 @@ XS(XS__AssignGroupToInstance);
XS(XS__AssignGroupToInstance) {
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: AssignGroupToInstance(id)");
Perl_croak(aTHX_ "Usage: AssignGroupToInstance(instance_id)");
uint16 id = (int)SvUV(ST(0));
quest_manager.AssignGroupToInstance(id);
uint16 instance_id = (int)SvUV(ST(0));
quest_manager.AssignGroupToInstance(instance_id);
XSRETURN_EMPTY;
}
@@ -2887,10 +2920,34 @@ XS(XS__AssignRaidToInstance);
XS(XS__AssignRaidToInstance) {
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: AssignRaidToInstance(id)");
Perl_croak(aTHX_ "Usage: AssignRaidToInstance(instance_id)");
uint16 id = (int)SvUV(ST(0));
quest_manager.AssignRaidToInstance(id);
uint16 instance_id = (int)SvUV(ST(0));
quest_manager.AssignRaidToInstance(instance_id);
XSRETURN_EMPTY;
}
XS(XS__RemoveFromInstance);
XS(XS__RemoveFromInstance) {
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: RemoveFromInstance(instance_id)");
uint16 instance_id = (int)SvUV(ST(0));
quest_manager.RemoveFromInstance(instance_id);
XSRETURN_EMPTY;
}
XS(XS__RemoveAllFromInstance);
XS(XS__RemoveAllFromInstance) {
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: RemoveAllFromInstance(instance_id)");
uint16 instance_id = (int)SvUV(ST(0));
quest_manager.RemoveAllFromInstance(instance_id);
XSRETURN_EMPTY;
}
@@ -2910,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;
@@ -3225,7 +3282,7 @@ XS(XS__GetZoneID)
char *zone = (char *)SvPV_nolen(ST(0));
int32 id = quest_manager.GetZoneID(zone);
XSRETURN_IV(id);
}
@@ -3238,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);
}
@@ -3368,7 +3425,7 @@ XS(XS__clear_npctype_cache)
int32 npctype_id = (int32)SvIV(ST(0));
quest_manager.ClearNPCTypeCache(npctype_id);
}
XSRETURN_EMPTY;
}
@@ -3391,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);
}
@@ -3430,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
@@ -3450,218 +3538,223 @@ 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.
//add the strcpy stuff to get rid of const warnings....
XS_VERSION_BOOTCHECK ;
newXS(strcpy(buf, "echo"), XS__echo, file);
newXS(strcpy(buf, "say"), XS__say, file);
newXS(strcpy(buf, "me"), XS__me, file);
newXS(strcpy(buf, "summonitem"), XS__summonitem, file);
newXS(strcpy(buf, "write"), XS__write, file);
newXS(strcpy(buf, "spawn"), XS__spawn, file);
newXS(strcpy(buf, "spawn2"), XS__spawn2, file);
newXS(strcpy(buf, "unique_spawn"), XS__unique_spawn, file);
newXS(strcpy(buf, "spawn_from_spawn2"), XS__spawn_from_spawn2, file);
newXS(strcpy(buf, "enable_spawn2"), XS__enable_spawn2, file);
newXS(strcpy(buf, "disable_spawn2"), XS__disable_spawn2, file);
newXS(strcpy(buf, "setstat"), XS__setstat, file);
newXS(strcpy(buf, "incstat"), XS__incstat, file);
newXS(strcpy(buf, "castspell"), XS__castspell, file);
newXS(strcpy(buf, "selfcast"), XS__selfcast, file);
#ifdef BOTS
newXS(strcpy(buf, "botquest"), XS__botquest, file);
newXS(strcpy(buf, "spawnbotcount"), XS__spawnbotcount, file);
newXS(strcpy(buf, "createbotcount"), XS__createbotcount, file);
newXS(strcpy(buf, "createBot"), XS__createBot, file);
#endif //BOTS
newXS(strcpy(buf, "AssignGroupToInstance"), XS__AssignGroupToInstance, file);
newXS(strcpy(buf, "AssignRaidToInstance"), XS__AssignRaidToInstance, file);
newXS(strcpy(buf, "AssignToInstance"), XS__AssignToInstance, file);
newXS(strcpy(buf, "ChooseRandom"), XS__ChooseRandom, file);
newXS(strcpy(buf, "CreateInstance"), XS__CreateInstance, file);
newXS(strcpy(buf, "DestroyInstance"), XS__DestroyInstance, file);
newXS(strcpy(buf, "FlagInstanceByGroupLeader"), XS__FlagInstanceByGroupLeader, file);
newXS(strcpy(buf, "FlagInstanceByRaidLeader"), XS__FlagInstanceByRaidLeader, file);
newXS(strcpy(buf, "FlyMode"), XS__FlyMode, file);
newXS(strcpy(buf, "GetCharactersInInstance"), XS__GetCharactersInInstance, file);
newXS(strcpy(buf, "GetInstanceID"), XS__GetInstanceID, file);
newXS(strcpy(buf, "GetSpellResistType"), XS__GetSpellResistType, file);
newXS(strcpy(buf, "GetSpellTargetType"), XS__GetSpellTargetType, file);
newXS(strcpy(buf, "GetTimeSeconds"), XS__GetTimeSeconds, file);
newXS(strcpy(buf, "GetZoneID"), XS__GetZoneID, file);
newXS(strcpy(buf, "GetZoneLongName"), XS__GetZoneLongName, file);
newXS(strcpy(buf, "IsBeneficialSpell"), XS__IsBeneficialSpell, file);
newXS(strcpy(buf, "IsEffectInSpell"), XS__IsEffectInSpell, file);
newXS(strcpy(buf, "IsRunning"), XS__IsRunning, file);
newXS(strcpy(buf, "LearnRecipe"), XS__LearnRecipe, file);
newXS(strcpy(buf, "MerchantCountItem"), XS__MerchantCountItem, file);
newXS(strcpy(buf, "MerchantSetItem"), XS__MerchantSetItem, file);
newXS(strcpy(buf, "MovePCInstance"), XS__MovePCInstance, file);
newXS(strcpy(buf, "RemoveAllFromInstance"), XS__RemoveAllFromInstance, file);
newXS(strcpy(buf, "RemoveFromInstance"), XS__RemoveFromInstance, file);
newXS(strcpy(buf, "SendMail"), XS__SendMail, file);
newXS(strcpy(buf, "SetRunning"), XS__SetRunning, file);
newXS(strcpy(buf, "activespeakactivity"), XS__activespeakactivity, file);
newXS(strcpy(buf, "activespeaktask"), XS__activespeaktask, file);
newXS(strcpy(buf, "activetasksinset"), XS__activetasksinset, file);
newXS(strcpy(buf, "addldonloss"), XS__addldonpoints, file);
newXS(strcpy(buf, "addldonpoints"), XS__addldonpoints, file);
newXS(strcpy(buf, "addldonwin"), XS__addldonpoints, file);
newXS(strcpy(buf, "addloot"), XS__addloot, file);
newXS(strcpy(buf, "zone"), XS__zone, file);
newXS(strcpy(buf, "settimer"), XS__settimer, file);
newXS(strcpy(buf, "settimerMS"), XS__settimerMS, file);
newXS(strcpy(buf, "stoptimer"), XS__stoptimer, file);
newXS(strcpy(buf, "stopalltimers"), XS__stopalltimers, file);
newXS(strcpy(buf, "emote"), XS__emote, file);
newXS(strcpy(buf, "shout"), XS__shout, file);
newXS(strcpy(buf, "shout2"), XS__shout2, file);
newXS(strcpy(buf, "gmsay"), XS__gmsay, file);
newXS(strcpy(buf, "depop"), XS__depop, file);
newXS(strcpy(buf, "depop_withtimer"), XS__depop_withtimer, file);
newXS(strcpy(buf, "settarget"), XS__settarget, file);
newXS(strcpy(buf, "follow"), XS__follow, file);
newXS(strcpy(buf, "sfollow"), XS__sfollow, file);
newXS(strcpy(buf, "changedeity"), XS__changedeity, file);
newXS(strcpy(buf, "exp"), XS__exp, file);
newXS(strcpy(buf, "level"), XS__level, file);
newXS(strcpy(buf, "traindisc"), XS__traindisc, file);
newXS(strcpy(buf, "isdisctome"), XS__isdisctome, file);
newXS(strcpy(buf, "safemove"), XS__safemove, file);
newXS(strcpy(buf, "rain"), XS__rain, file);
newXS(strcpy(buf, "snow"), XS__snow, file);
newXS(strcpy(buf, "surname"), XS__surname, file);
newXS(strcpy(buf, "permaclass"), XS__permaclass, file);
newXS(strcpy(buf, "permarace"), XS__permarace, file);
newXS(strcpy(buf, "permagender"), XS__permagender, file);
newXS(strcpy(buf, "scribespells"), XS__scribespells, file);
newXS(strcpy(buf, "traindiscs"), XS__traindiscs, file);
newXS(strcpy(buf, "unscribespells"), XS__unscribespells, file);
newXS(strcpy(buf, "untraindiscs"), XS__untraindiscs, file);
newXS(strcpy(buf, "givecash"), XS__givecash, file);
newXS(strcpy(buf, "pvp"), XS__pvp, file);
newXS(strcpy(buf, "movepc"), XS__movepc, file);
newXS(strcpy(buf, "gmmove"), XS__gmmove, file);
newXS(strcpy(buf, "movegrp"), XS__movegrp, file);
newXS(strcpy(buf, "doanim"), XS__doanim, file);
newXS(strcpy(buf, "addskill"), XS__addskill, file);
newXS(strcpy(buf, "setlanguage"), XS__setlanguage, file);
newXS(strcpy(buf, "setskill"), XS__setskill, file);
newXS(strcpy(buf, "setallskill"), XS__setallskill, file);
newXS(strcpy(buf, "assigntask"), XS__assigntask, file);
newXS(strcpy(buf, "attack"), XS__attack, file);
newXS(strcpy(buf, "attacknpc"), XS__attacknpc, file);
newXS(strcpy(buf, "attacknpctype"), XS__attacknpctype, file);
newXS(strcpy(buf, "save"), XS__save, file);
newXS(strcpy(buf, "faction"), XS__faction, file);
newXS(strcpy(buf, "setsky"), XS__setsky, file);
newXS(strcpy(buf, "setguild"), XS__setguild, file);
newXS(strcpy(buf, "createguild"), XS__createguild, file);
newXS(strcpy(buf, "settime"), XS__settime, file);
newXS(strcpy(buf, "itemlink"), XS__itemlink, file);
newXS(strcpy(buf, "signal"), XS__signal, file);
newXS(strcpy(buf, "signalwith"), XS__signalwith, file);
newXS(strcpy(buf, "setglobal"), XS__setglobal, file);
newXS(strcpy(buf, "targlobal"), XS__targlobal, file);
newXS(strcpy(buf, "delglobal"), XS__delglobal, file);
newXS(strcpy(buf, "ding"), XS__ding, file);
newXS(strcpy(buf, "rebind"), XS__rebind, file);
newXS(strcpy(buf, "start"), XS__start, file);
newXS(strcpy(buf, "stop"), XS__stop, file);
newXS(strcpy(buf, "pause"), XS__pause, file);
newXS(strcpy(buf, "moveto"), XS__moveto, file);
newXS(strcpy(buf, "resume"), XS__resume, file);
newXS(strcpy(buf, "addldonpoints"), XS__addldonpoints, file);
newXS(strcpy(buf, "addldonwin"), XS__addldonpoints, file);
newXS(strcpy(buf, "addldonloss"), XS__addldonpoints, file);
newXS(strcpy(buf, "setnexthpevent"), XS__setnexthpevent, file);
newXS(strcpy(buf, "setnextinchpevent"), XS__setnextinchpevent, file);
newXS(strcpy(buf, "sethp"), XS__sethp, file);
newXS(strcpy(buf, "respawn"), XS__respawn, file);
newXS(strcpy(buf, "getItemName"), XS_qc_getItemName, file);
newXS(strcpy(buf, "ChooseRandom"), XS__ChooseRandom, file);
newXS(strcpy(buf, "set_proximity"), XS__set_proximity, file);
newXS(strcpy(buf, "clear_proximity"), XS__clear_proximity, file);
newXS(strcpy(buf, "enable_proximity_say"), XS__enable_proximity_say, file);
newXS(strcpy(buf, "disable_proximity_say"), XS__disable_proximity_say, file);
newXS(strcpy(buf, "setanim"), XS__setanim, file);
newXS(strcpy(buf, "showgrid"), XS__showgrid, file);
newXS(strcpy(buf, "spawn_condition"), XS__spawn_condition, file);
newXS(strcpy(buf, "get_spawn_condition"), XS__get_spawn_condition, file);
newXS(strcpy(buf, "toggle_spawn_event"), XS__toggle_spawn_event, file);
newXS(strcpy(buf, "has_zone_flag"), XS__has_zone_flag, file);
newXS(strcpy(buf, "set_zone_flag"), XS__set_zone_flag, file);
newXS(strcpy(buf, "clear_zone_flag"), XS__clear_zone_flag, file);
newXS(strcpy(buf, "summonburriedplayercorpse"), XS__summonburriedplayercorpse, file);
newXS(strcpy(buf, "summonallplayercorpses"), XS__summonallplayercorpses, file);
newXS(strcpy(buf, "getplayerburriedcorpsecount"), XS__getplayerburriedcorpsecount, file);
newXS(strcpy(buf, "buryplayercorpse"), XS__buryplayercorpse, file);
newXS(strcpy(buf, "forcedooropen"), XS__forcedooropen, file);
newXS(strcpy(buf, "forcedoorclose"), XS__forcedoorclose, file);
newXS(strcpy(buf, "toggledoorstate"), XS__toggledoorstate, file);
newXS(strcpy(buf, "isdooropen"), XS__isdooropen, file);
newXS(strcpy(buf, "depopall"), XS__depopall, file);
newXS(strcpy(buf, "depopzone"), XS__depopzone, file);
newXS(strcpy(buf, "repopzone"), XS__repopzone, file);
newXS(strcpy(buf, "npcrace"), XS__npcrace, file);
newXS(strcpy(buf, "npcgender"), XS__npcgender, file);
newXS(strcpy(buf, "npcsize"), XS__npcsize, file);
newXS(strcpy(buf, "npctexture"), XS__npctexture, file);
newXS(strcpy(buf, "playerrace"), XS__playerrace, file);
newXS(strcpy(buf, "playergender"), XS__playergender, file);
newXS(strcpy(buf, "playersize"), XS__playersize, file);
newXS(strcpy(buf, "playertexture"), XS__playertexture, file);
newXS(strcpy(buf, "playerfeature"), XS__playerfeature, file);
newXS(strcpy(buf, "npcfeature"), XS__npcfeature, file);
#ifdef BOTS
newXS(strcpy(buf, "botquest"), XS__botquest, file);
newXS(strcpy(buf, "spawnbotcount"), XS__spawnbotcount, file);
newXS(strcpy(buf, "createbotcount"), XS__createbotcount, file);
newXS(strcpy(buf, "createBot"), XS__createBot, file);
#endif //BOTS
newXS(strcpy(buf, "taskselector"), XS__taskselector, file);
newXS(strcpy(buf, "tasksetselector"), XS__tasksetselector, file);
newXS(strcpy(buf, "enabletask"), XS__enabletask, file);
newXS(strcpy(buf, "disabletask"), XS__disabletask, file);
newXS(strcpy(buf, "istaskenabled"), XS__istaskenabled, file);
newXS(strcpy(buf, "istaskactive"), XS__istaskactive, file);
newXS(strcpy(buf, "istaskactivityactive"), XS__istaskactivityactive, file);
newXS(strcpy(buf, "gettaskactivitydonecount"), XS__gettaskactivitydonecount, file);
newXS(strcpy(buf, "updatetaskactivity"), XS__updatetaskactivity, file);
newXS(strcpy(buf, "resettaskactivity"), XS__resettaskactivity, file);
newXS(strcpy(buf, "taskexploredarea"), XS__taskexploredarea, file);
newXS(strcpy(buf, "assigntask"), XS__assigntask, file);
newXS(strcpy(buf, "failtask"), XS__failtask, file);
newXS(strcpy(buf, "tasktimeleft"), XS__tasktimeleft, file);
newXS(strcpy(buf, "istaskcompleted"), XS__istaskcompleted, file);
newXS(strcpy(buf, "enabledtaskcount"), XS__enabledtaskcount, file);
newXS(strcpy(buf, "firsttaskinset"), XS__firsttaskinset, file);
newXS(strcpy(buf, "lasttaskinset"), XS__lasttaskinset, file);
newXS(strcpy(buf, "nexttaskinset"), XS__nexttaskinset, file);
newXS(strcpy(buf, "activespeaktask"), XS__activespeaktask, file);
newXS(strcpy(buf, "activespeakactivity"), XS__activespeakactivity, file);
newXS(strcpy(buf, "activetasksinset"), XS__activetasksinset, file);
newXS(strcpy(buf, "completedtasksinset"), XS__completedtasksinset, file);
newXS(strcpy(buf, "istaskappropriate"), XS__istaskappropriate, file);
newXS(strcpy(buf, "popup"), XS__popup, file);
newXS(strcpy(buf, "castspell"), XS__castspell, file);
newXS(strcpy(buf, "changedeity"), XS__changedeity, file);
newXS(strcpy(buf, "checktitle"), XS__checktitle, file);
newXS(strcpy(buf, "clear_npctype_cache"), XS__clear_npctype_cache, file);
newXS(strcpy(buf, "clear_proximity"), XS__clear_proximity, file);
newXS(strcpy(buf, "clear_zone_flag"), XS__clear_zone_flag, file);
newXS(strcpy(buf, "clearspawntimers"), XS__clearspawntimers, file);
newXS(strcpy(buf, "ze"), XS__ze, file);
newXS(strcpy(buf, "we"), XS__we, file);
newXS(strcpy(buf, "getlevel"), XS__getlevel, file);
newXS(strcpy(buf, "collectitems"), XS__collectitems, file);
newXS(strcpy(buf, "completedtasksinset"), XS__completedtasksinset, file);
newXS(strcpy(buf, "createdoor"), XS__CreateDoor, file);
newXS(strcpy(buf, "creategroundobject"), XS__CreateGroundObject, file);
newXS(strcpy(buf, "creategroundobjectfrommodel"), XS__CreateGroundObjectFromModel, file);
newXS(strcpy(buf, "createdoor"), XS__CreateDoor, file);
newXS(strcpy(buf, "modifynpcstat"), XS__ModifyNPCStat, file);
newXS(strcpy(buf, "collectitems"), XS__collectitems, file);
newXS(strcpy(buf, "updatespawntimer"), XS__UpdateSpawnTimer, file);
newXS(strcpy(buf, "MerchantSetItem"), XS__MerchantSetItem, file);
newXS(strcpy(buf, "MerchantCountItem"), XS__MerchantCountItem, file);
newXS(strcpy(buf, "varlink"), XS__varlink, file);
newXS(strcpy(buf, "saylink"), XS__saylink, file);
newXS(strcpy(buf, "getguildnamebyid"), XS__getguildnamebyid, file);
newXS(strcpy(buf, "CreateInstance"), XS__CreateInstance, file);
newXS(strcpy(buf, "DestroyInstance"), XS__DestroyInstance, file);
newXS(strcpy(buf, "GetInstanceID"), XS__GetInstanceID, file);
newXS(strcpy(buf, "AssignToInstance"), XS__AssignToInstance, file);
newXS(strcpy(buf, "AssignGroupToInstance"), XS__AssignGroupToInstance, file);
newXS(strcpy(buf, "AssignRaidToInstance"), XS__AssignRaidToInstance, file);
newXS(strcpy(buf, "MovePCInstance"), XS__MovePCInstance, file);
newXS(strcpy(buf, "FlagInstanceByGroupLeader"), XS__FlagInstanceByGroupLeader, file);
newXS(strcpy(buf, "FlagInstanceByRaidLeader"), XS__FlagInstanceByRaidLeader, file);
newXS(strcpy(buf, "SetRunning"), XS__SetRunning, file);
newXS(strcpy(buf, "IsRunning"), XS__IsRunning, file);
newXS(strcpy(buf, "IsEffectInSpell"), XS__IsEffectInSpell, file);
newXS(strcpy(buf, "IsBeneficialSpell"), XS__IsBeneficialSpell, file);
newXS(strcpy(buf, "GetSpellResistType"), XS__GetSpellResistType, file);
newXS(strcpy(buf, "GetSpellTargetType"), XS__GetSpellTargetType, file);
newXS(strcpy(buf, "FlyMode"), XS__FlyMode, file);
newXS(strcpy(buf, "factionvalue"), XS_FactionValue, file);
newXS(strcpy(buf, "checktitle"), XS__checktitle, file);
newXS(strcpy(buf, "enabletitle"), XS__enabletitle, file);
newXS(strcpy(buf, "removetitle"), XS__removetitle, file);
newXS(strcpy(buf, "wearchange"), XS__wearchange, file);
newXS(strcpy(buf, "voicetell"), XS__voicetell, file);
newXS(strcpy(buf, "LearnRecipe"), XS__LearnRecipe, file);
newXS(strcpy(buf, "SendMail"), XS__SendMail, file);
newXS(strcpy(buf, "GetZoneID"), XS__GetZoneID, file);
newXS(strcpy(buf, "GetZoneLongName"), XS__GetZoneLongName, file);
newXS(strcpy(buf, "GetTimeSeconds"), XS__GetTimeSeconds, file);
newXS(strcpy(buf, "createguild"), XS__createguild, file);
newXS(strcpy(buf, "crosszonemessageplayerbyname"), XS__crosszonemessageplayerbyname, file);
newXS(strcpy(buf, "crosszonesetentityvariablebynpctypeid"), XS__crosszonesetentityvariablebynpctypeid, file);
newXS(strcpy(buf, "crosszonesignalclientbycharid"), XS__crosszonesignalclientbycharid, file);
newXS(strcpy(buf, "crosszonesignalclientbyname"), XS__crosszonesignalclientbyname, file);
newXS(strcpy(buf, "crosszonemessageplayerbyname"), XS__crosszonemessageplayerbyname, file);
newXS(strcpy(buf, "enablerecipe"), XS__enablerecipe, file);
newXS(strcpy(buf, "disablerecipe"), XS__disablerecipe, file);
newXS(strcpy(buf, "clear_npctype_cache"), XS__clear_npctype_cache, file);
newXS(strcpy(buf, "qs_send_query"), XS__qs_send_query, file);
newXS(strcpy(buf, "qs_player_event"), XS__qs_player_event, file);
newXS(strcpy(buf, "crosszonesetentityvariablebynpctypeid"), XS__crosszonesetentityvariablebynpctypeid, 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);
newXS(strcpy(buf, "depopall"), XS__depopall, file);
newXS(strcpy(buf, "depopzone"), XS__depopzone, file);
newXS(strcpy(buf, "ding"), XS__ding, file);
newXS(strcpy(buf, "disable_proximity_say"), XS__disable_proximity_say, file);
newXS(strcpy(buf, "disable_spawn2"), XS__disable_spawn2, file);
newXS(strcpy(buf, "disablerecipe"), XS__disablerecipe, file);
newXS(strcpy(buf, "disabletask"), XS__disabletask, file);
newXS(strcpy(buf, "doanim"), XS__doanim, file);
newXS(strcpy(buf, "echo"), XS__echo, file);
newXS(strcpy(buf, "emote"), XS__emote, file);
newXS(strcpy(buf, "enable_proximity_say"), XS__enable_proximity_say, file);
newXS(strcpy(buf, "enable_spawn2"), XS__enable_spawn2, file);
newXS(strcpy(buf, "enabledtaskcount"), XS__enabledtaskcount, file);
newXS(strcpy(buf, "enablerecipe"), XS__enablerecipe, file);
newXS(strcpy(buf, "enabletask"), XS__enabletask, file);
newXS(strcpy(buf, "enabletitle"), XS__enabletitle, file);
newXS(strcpy(buf, "exp"), XS__exp, file);
newXS(strcpy(buf, "faction"), XS__faction, file);
newXS(strcpy(buf, "factionvalue"), XS_FactionValue, file);
newXS(strcpy(buf, "failtask"), XS__failtask, file);
newXS(strcpy(buf, "firsttaskinset"), XS__firsttaskinset, file);
newXS(strcpy(buf, "follow"), XS__follow, file);
newXS(strcpy(buf, "forcedoorclose"), XS__forcedoorclose, file);
newXS(strcpy(buf, "forcedooropen"), XS__forcedooropen, file);
newXS(strcpy(buf, "getItemName"), XS_qc_getItemName, file);
newXS(strcpy(buf, "get_spawn_condition"), XS__get_spawn_condition, file);
newXS(strcpy(buf, "getguildnamebyid"), XS__getguildnamebyid, file);
newXS(strcpy(buf, "getlevel"), XS__getlevel, file);
newXS(strcpy(buf, "getplayerburriedcorpsecount"), XS__getplayerburriedcorpsecount, file);
newXS(strcpy(buf, "gettaskactivitydonecount"), XS__gettaskactivitydonecount, file);
newXS(strcpy(buf, "givecash"), XS__givecash, file);
newXS(strcpy(buf, "gmmove"), XS__gmmove, file);
newXS(strcpy(buf, "gmsay"), XS__gmsay, file);
newXS(strcpy(buf, "has_zone_flag"), XS__has_zone_flag, file);
newXS(strcpy(buf, "incstat"), XS__incstat, file);
newXS(strcpy(buf, "isdisctome"), XS__isdisctome, file);
newXS(strcpy(buf, "isdooropen"), XS__isdooropen, file);
newXS(strcpy(buf, "istaskactive"), XS__istaskactive, file);
newXS(strcpy(buf, "istaskactivityactive"), XS__istaskactivityactive, file);
newXS(strcpy(buf, "istaskappropriate"), XS__istaskappropriate, file);
newXS(strcpy(buf, "istaskcompleted"), XS__istaskcompleted, file);
newXS(strcpy(buf, "istaskenabled"), XS__istaskenabled, file);
newXS(strcpy(buf, "itemlink"), XS__itemlink, file);
newXS(strcpy(buf, "lasttaskinset"), XS__lasttaskinset, file);
newXS(strcpy(buf, "level"), XS__level, file);
newXS(strcpy(buf, "me"), XS__me, file);
newXS(strcpy(buf, "modifynpcstat"), XS__ModifyNPCStat, file);
newXS(strcpy(buf, "movegrp"), XS__movegrp, file);
newXS(strcpy(buf, "movepc"), XS__movepc, file);
newXS(strcpy(buf, "moveto"), XS__moveto, file);
newXS(strcpy(buf, "nexttaskinset"), XS__nexttaskinset, file);
newXS(strcpy(buf, "npcfeature"), XS__npcfeature, file);
newXS(strcpy(buf, "npcgender"), XS__npcgender, file);
newXS(strcpy(buf, "npcrace"), XS__npcrace, file);
newXS(strcpy(buf, "npcsize"), XS__npcsize, file);
newXS(strcpy(buf, "npctexture"), XS__npctexture, file);
newXS(strcpy(buf, "pause"), XS__pause, file);
newXS(strcpy(buf, "permaclass"), XS__permaclass, file);
newXS(strcpy(buf, "permagender"), XS__permagender, file);
newXS(strcpy(buf, "permarace"), XS__permarace, file);
newXS(strcpy(buf, "playerfeature"), XS__playerfeature, file);
newXS(strcpy(buf, "playergender"), XS__playergender, file);
newXS(strcpy(buf, "playerrace"), XS__playerrace, file);
newXS(strcpy(buf, "playersize"), XS__playersize, file);
newXS(strcpy(buf, "playertexture"), XS__playertexture, file);
newXS(strcpy(buf, "popup"), XS__popup, file);
newXS(strcpy(buf, "pvp"), XS__pvp, file);
newXS(strcpy(buf, "qs_player_event"), XS__qs_player_event, file);
newXS(strcpy(buf, "qs_send_query"), XS__qs_send_query, file);
newXS(strcpy(buf, "rain"), XS__rain, file);
newXS(strcpy(buf, "rebind"), XS__rebind, file);
newXS(strcpy(buf, "removetitle"), XS__removetitle, file);
newXS(strcpy(buf, "repopzone"), XS__repopzone, file);
newXS(strcpy(buf, "resettaskactivity"), XS__resettaskactivity, file);
newXS(strcpy(buf, "respawn"), XS__respawn, file);
newXS(strcpy(buf, "resume"), XS__resume, file);
newXS(strcpy(buf, "safemove"), XS__safemove, file);
newXS(strcpy(buf, "save"), XS__save, file);
newXS(strcpy(buf, "say"), XS__say, file);
newXS(strcpy(buf, "saylink"), XS__saylink, file);
newXS(strcpy(buf, "scribespells"), XS__scribespells, file);
newXS(strcpy(buf, "selfcast"), XS__selfcast, file);
newXS(strcpy(buf, "set_proximity"), XS__set_proximity, file);
newXS(strcpy(buf, "set_zone_flag"), XS__set_zone_flag, file);
newXS(strcpy(buf, "setallskill"), XS__setallskill, file);
newXS(strcpy(buf, "setanim"), XS__setanim, file);
newXS(strcpy(buf, "setglobal"), XS__setglobal, file);
newXS(strcpy(buf, "setguild"), XS__setguild, file);
newXS(strcpy(buf, "sethp"), XS__sethp, file);
newXS(strcpy(buf, "setlanguage"), XS__setlanguage, file);
newXS(strcpy(buf, "setnexthpevent"), XS__setnexthpevent, file);
newXS(strcpy(buf, "setnextinchpevent"), XS__setnextinchpevent, file);
newXS(strcpy(buf, "setskill"), XS__setskill, file);
newXS(strcpy(buf, "setsky"), XS__setsky, file);
newXS(strcpy(buf, "setstat"), XS__setstat, file);
newXS(strcpy(buf, "settarget"), XS__settarget, file);
newXS(strcpy(buf, "settime"), XS__settime, file);
newXS(strcpy(buf, "settimer"), XS__settimer, file);
newXS(strcpy(buf, "settimerMS"), XS__settimerMS, file);
newXS(strcpy(buf, "sfollow"), XS__sfollow, file);
newXS(strcpy(buf, "shout"), XS__shout, file);
newXS(strcpy(buf, "shout2"), XS__shout2, file);
newXS(strcpy(buf, "showgrid"), XS__showgrid, file);
newXS(strcpy(buf, "signal"), XS__signal, file);
newXS(strcpy(buf, "signalwith"), XS__signalwith, file);
newXS(strcpy(buf, "snow"), XS__snow, file);
newXS(strcpy(buf, "spawn"), XS__spawn, file);
newXS(strcpy(buf, "spawn2"), XS__spawn2, file);
newXS(strcpy(buf, "spawn_condition"), XS__spawn_condition, file);
newXS(strcpy(buf, "spawn_from_spawn2"), XS__spawn_from_spawn2, file);
newXS(strcpy(buf, "start"), XS__start, file);
newXS(strcpy(buf, "stop"), XS__stop, file);
newXS(strcpy(buf, "stopalltimers"), XS__stopalltimers, file);
newXS(strcpy(buf, "stoptimer"), XS__stoptimer, file);
newXS(strcpy(buf, "summonallplayercorpses"), XS__summonallplayercorpses, file);
newXS(strcpy(buf, "summonburriedplayercorpse"), XS__summonburriedplayercorpse, file);
newXS(strcpy(buf, "summonitem"), XS__summonitem, file);
newXS(strcpy(buf, "surname"), XS__surname, file);
newXS(strcpy(buf, "targlobal"), XS__targlobal, file);
newXS(strcpy(buf, "taskexploredarea"), XS__taskexploredarea, file);
newXS(strcpy(buf, "taskselector"), XS__taskselector, file);
newXS(strcpy(buf, "tasksetselector"), XS__tasksetselector, file);
newXS(strcpy(buf, "tasktimeleft"), XS__tasktimeleft, file);
newXS(strcpy(buf, "toggle_spawn_event"), XS__toggle_spawn_event, file);
newXS(strcpy(buf, "toggledoorstate"), XS__toggledoorstate, file);
newXS(strcpy(buf, "traindisc"), XS__traindisc, file);
newXS(strcpy(buf, "traindiscs"), XS__traindiscs, file);
newXS(strcpy(buf, "unique_spawn"), XS__unique_spawn, file);
newXS(strcpy(buf, "unscribespells"), XS__unscribespells, file);
newXS(strcpy(buf, "untraindiscs"), XS__untraindiscs, file);
newXS(strcpy(buf, "updatespawntimer"), XS__UpdateSpawnTimer, file);
newXS(strcpy(buf, "updatetaskactivity"), XS__updatetaskactivity, file);
newXS(strcpy(buf, "varlink"), XS__varlink, file);
newXS(strcpy(buf, "voicetell"), XS__voicetell, file);
newXS(strcpy(buf, "we"), XS__we, file);
newXS(strcpy(buf, "wearchange"), XS__wearchange, file);
newXS(strcpy(buf, "write"), XS__write, file);
newXS(strcpy(buf, "ze"), XS__ze, file);
newXS(strcpy(buf, "zone"), XS__zone, file);
XSRETURN_YES;
}
+9 -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;
@@ -210,6 +211,8 @@ Embperl::~Embperl()
" if(tied *STDERR) { untie(*STDERR); }"
,FALSE);
#endif
PL_perl_destruct_level = 1;
perl_destruct(my_perl);
perl_free(my_perl);
PERL_SYS_TERM();
my_perl = NULL;
+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);
}
}
+320 -347
View File
File diff suppressed because it is too large Load Diff
+35 -25
View File
@@ -17,6 +17,7 @@
*/
#ifndef ENTITY_H
#define ENTITY_H
#include <unordered_map>
#include <queue>
@@ -26,33 +27,38 @@
#include "../common/bodytypes.h"
#include "../common/eq_constants.h"
#include "zonedb.h"
#include "position.h"
#include "zonedump.h"
#include "qglobals.h"
class EQApplicationPacket;
class Client;
class Mob;
class NPC;
class Merc;
class Corpse;
class Beacon;
class Petition;
class Object;
class Group;
class Raid;
class Client;
class Corpse;
class Doors;
class Trap;
class EQApplicationPacket;
class Entity;
class EntityList;
class Group;
class Merc;
class Mob;
class NPC;
class Object;
class Petition;
class Raid;
class Spawn2;
class Trap;
struct GuildBankItemUpdate_Struct;
struct NewSpawn_Struct;
struct QGlobal;
struct UseAA_Struct;
struct Who_All_Struct;
#ifdef BOTS
class Bot;
class BotRaids;
#endif
extern EntityList entity_list;
extern EntityList entity_list;
class Entity
{
@@ -97,6 +103,7 @@ public:
const Beacon *CastToBeacon() const;
inline const uint16& GetID() const { return id; }
inline const time_t& GetSpawnTimeStamp() const { return spawn_timestamp; }
virtual const char* GetName() { return ""; }
bool CheckCoordLosNoZLeaps(float cur_x, float cur_y, float cur_z, float trg_x, float trg_y, float trg_z, float perwalk=1);
@@ -112,6 +119,7 @@ protected:
uint32 pDBAsyncWorkID;
private:
uint16 id;
time_t spawn_timestamp;
};
class EntityList
@@ -134,7 +142,7 @@ public:
Mob *GetMob(const char* name);
Mob *GetMobByNpcTypeID(uint32 get_id);
bool IsMobSpawnedByNpcTypeID(uint32 get_id);
Mob *GetTargetForVirus(Mob* spreader);
Mob *GetTargetForVirus(Mob* spreader, int range);
inline NPC *GetNPCByID(uint16 id)
{ return npc_list.count(id) ? npc_list.at(id) : nullptr; }
NPC *GetNPCByNPCTypeID(uint32 npc_id);
@@ -147,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);
@@ -195,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);
@@ -249,6 +257,8 @@ public:
void RemoveAllLocalities();
void RemoveAllRaids();
void DestroyTempPets(Mob *owner);
int16 CountTempPets(Mob *owner);
void AddTempPetsToHateList(Mob *owner, Mob* other, bool bFrenzy = false);
Entity *GetEntityMob(uint16 id);
Entity *GetEntityMerc(uint16 id);
Entity *GetEntityDoor(uint16 id);
@@ -259,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, ...);
@@ -297,7 +309,7 @@ public:
void QueueClientsGuild(Mob* sender, const EQApplicationPacket* app, bool ignore_sender = false, uint32 guildeqid = 0);
void QueueClientsGuildBankItemUpdate(const GuildBankItemUpdate_Struct *gbius, uint32 GuildID);
void QueueClientsByTarget(Mob* sender, const EQApplicationPacket* app, bool iSendToSender = true, Mob* SkipThisMob = 0, bool ackreq = true,
bool HoTT = true, uint32 ClientVersionBits = 0xFFFFFFFF);
bool HoTT = true, uint32 ClientVersionBits = 0xFFFFFFFF, bool inspect_buffs = false);
void QueueClientsByXTarget(Mob* sender, const EQApplicationPacket* app, bool iSendToSender = true);
void QueueToGroupsForNPCHealthAA(Mob* sender, const EQApplicationPacket* app);
@@ -309,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);
@@ -346,7 +356,7 @@ public:
void ClearAggro(Mob* targ);
void ClearFeignAggro(Mob* targ);
void ClearZoneFeignAggro(Client* targ);
void AggroZone(Mob* who, int hate = 0);
void AggroZone(Mob* who, uint32 hate = 0);
bool Fighting(Mob* targ);
void RemoveFromHateLists(Mob* mob, bool settoone = false);
@@ -382,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,
+70 -31
View File
@@ -15,14 +15,24 @@
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/features.h"
#include "masterentity.h"
#include "string_ids.h"
#include "../common/string_util.h"
#include "../common/rulesys.h"
#include "quest_parser_collection.h"
#include "../common/string_util.h"
#include "client.h"
#include "groups.h"
#include "mob.h"
#include "raids.h"
#include "queryserv.h"
#include "quest_parser_collection.h"
#include "string_ids.h"
#ifdef BOTS
#include "bot.h"
#endif
extern QueryServ* QServ;
@@ -133,30 +143,60 @@ void Client::AddEXP(uint32 in_add_exp, uint8 conlevel, bool resexp) {
}
}
if(IsLeadershipEXPOn() && ((conlevel == CON_BLUE) || (conlevel == CON_WHITE) || (conlevel == CON_YELLOW) || (conlevel == CON_RED))) {
if (IsLeadershipEXPOn() && (conlevel == CON_BLUE || conlevel == CON_WHITE || conlevel == CON_YELLOW || conlevel == CON_RED)) {
add_exp = static_cast<uint32>(static_cast<float>(add_exp) * 0.8f);
if(GetGroup())
{
if((m_pp.group_leadership_points < MaxBankedGroupLeadershipPoints(GetLevel()))
&& (RuleI(Character, KillsPerGroupLeadershipAA) > 0))
{
AddLeadershipEXP(GROUP_EXP_PER_POINT / RuleI(Character, KillsPerGroupLeadershipAA), 0);
Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_EXP);
}
else
if (GetGroup()) {
if (m_pp.group_leadership_points < MaxBankedGroupLeadershipPoints(GetLevel())
&& RuleI(Character, KillsPerGroupLeadershipAA) > 0) {
uint32 exp = GROUP_EXP_PER_POINT / RuleI(Character, KillsPerGroupLeadershipAA);
Client *mentoree = GetGroup()->GetMentoree();
if (GetGroup()->GetMentorPercent() && mentoree &&
mentoree->GetGroupPoints() < MaxBankedGroupLeadershipPoints(mentoree->GetLevel())) {
uint32 mentor_exp = exp * (GetGroup()->GetMentorPercent() / 100.0f);
exp -= mentor_exp;
mentoree->AddLeadershipEXP(mentor_exp, 0); // ends up rounded down
mentoree->Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_EXP);
}
if (exp > 0) { // possible if you mentor 100% to the other client
AddLeadershipEXP(exp, 0); // ends up rounded up if mentored, no idea how live actually does it
Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_EXP);
}
} else {
Message_StringID(MT_Leadership, MAX_GROUP_LEADERSHIP_POINTS);
}
else
{
if((m_pp.raid_leadership_points < MaxBankedRaidLeadershipPoints(GetLevel()))
&& (RuleI(Character, KillsPerRaidLeadershipAA) > 0))
{
AddLeadershipEXP(0, RAID_EXP_PER_POINT / RuleI(Character, KillsPerRaidLeadershipAA));
Message_StringID(MT_Leadership, GAIN_RAID_LEADERSHIP_EXP);
}
else
Message_StringID(MT_Leadership, MAX_RAID_LEADERSHIP_POINTS);
} else {
Raid *raid = GetRaid();
// Raid leaders CAN NOT gain group AA XP, other group leaders can though!
if (raid->IsLeader(this)) {
if (m_pp.raid_leadership_points < MaxBankedRaidLeadershipPoints(GetLevel())
&& RuleI(Character, KillsPerRaidLeadershipAA) > 0) {
AddLeadershipEXP(0, RAID_EXP_PER_POINT / RuleI(Character, KillsPerRaidLeadershipAA));
Message_StringID(MT_Leadership, GAIN_RAID_LEADERSHIP_EXP);
} else {
Message_StringID(MT_Leadership, MAX_RAID_LEADERSHIP_POINTS);
}
} else {
if (m_pp.group_leadership_points < MaxBankedGroupLeadershipPoints(GetLevel())
&& RuleI(Character, KillsPerGroupLeadershipAA) > 0) {
uint32 group_id = raid->GetGroup(this);
uint32 exp = GROUP_EXP_PER_POINT / RuleI(Character, KillsPerGroupLeadershipAA);
Client *mentoree = raid->GetMentoree(group_id);
if (raid->GetMentorPercent(group_id) && mentoree &&
mentoree->GetGroupPoints() < MaxBankedGroupLeadershipPoints(mentoree->GetLevel())) {
uint32 mentor_exp = exp * (raid->GetMentorPercent(group_id) / 100.0f);
exp -= mentor_exp;
mentoree->AddLeadershipEXP(mentor_exp, 0);
mentoree->Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_EXP);
}
if (exp > 0) {
AddLeadershipEXP(exp, 0);
Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_EXP);
}
} else {
Message_StringID(MT_Leadership, MAX_GROUP_LEADERSHIP_POINTS);
}
}
}
}
@@ -200,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) {
@@ -268,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);
@@ -390,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;
}
@@ -448,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();
@@ -466,8 +506,7 @@ void Client::SetLevel(uint8 set_level, bool command)
SetMana(CalcMaxMana());
UpdateWho();
if(GetMerc())
UpdateMercLevel();
UpdateMercLevel();
Save();
}
+12 -25
View File
@@ -16,17 +16,12 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <cstdlib>
#include "../common/rulesys.h"
#include "../common/misc_functions.h"
#include "map.h"
#include "zone.h"
#include "pathing.h"
#include "zone.h"
#ifdef _WINDOWS
#define snprintf _snprintf
#endif
@@ -157,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::list<int> Route = zone->pathing->FindRoute(CurrentPosition, Loc);
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;
@@ -186,8 +179,8 @@ void Mob::CalculateNewFearpoint()
{
int ran = 250 - (loop*2);
loop++;
ranx = GetX()+MakeRandomInt(0, ran-1)-MakeRandomInt(0, ran-1);
rany = GetY()+MakeRandomInt(0, ran-1)-MakeRandomInt(0, ran-1);
ranx = GetX()+zone->random.Int(0, ran-1)-zone->random.Int(0, ran-1);
rany = GetY()+zone->random.Int(0, ran-1)-zone->random.Int(0, ran-1);
ranz = FindGroundZ(ranx,rany);
if (ranz == -999999)
continue;
@@ -199,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);
}
}
+45 -85
View File
@@ -15,75 +15,34 @@
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 <iostream>
#include <stdlib.h>
#include <math.h>
#ifdef _WINDOWS
#define snprintf _snprintf
#endif
#include "forage.h"
#include "entity.h"
#include "masterentity.h"
#include "npc.h"
#include "water_map.h"
#include "titles.h"
#include "string_ids.h"
#include "../common/global_define.h"
#include "../common/eqemu_logsys.h"
#include "../common/misc_functions.h"
#include "../common/string_util.h"
#include "../common/rulesys.h"
#include "../common/string_util.h"
#include "entity.h"
#include "forage.h"
#include "npc.h"
#include "quest_parser_collection.h"
#include "string_ids.h"
#include "titles.h"
#include "water_map.h"
#include "zonedb.h"
#include <iostream>
#ifdef _WINDOWS
#define snprintf _snprintf
#endif
#include "quest_parser_collection.h"
struct NPCType;
//max number of items which can be in the foraging table
//for a given zone.
#define FORAGE_ITEM_LIMIT 50
/*
The fishing and foraging need some work...
foraging currently gives each item an equal chance of dropping
fishing gives items which come in last from the select a very
very low chance of dropping.
Schema:
CREATE TABLE forage (
id int(11) NOT NULL auto_increment,
zoneid int(4) NOT NULL default '0',
Itemid int(11) NOT NULL default '0',
level smallint(6) NOT NULL default '0',
chance smallint(6) NOT NULL default '0',
PRIMARY KEY (id)
) TYPE=MyISAM;
old table upgrade:
alter table forage add chance smallint(6) NOT NULL default '0';
update forage set chance=100;
CREATE TABLE fishing (
id int(11) NOT NULL auto_increment,
zoneid int(4) NOT NULL default '0',
Itemid int(11) NOT NULL default '0',
skill_level smallint(6) NOT NULL default '0',
chance smallint(6) NOT NULL default '0',
npc_id int NOT NULL default 0,
npc_chance int NOT NULL default 0,
PRIMARY KEY (id)
) TYPE=MyISAM;
*/
// This allows EqEmu to have zone specific foraging - BoB
uint32 ZoneDatabase::GetZoneForage(uint32 ZoneID, uint8 skill) {
uint32 item[FORAGE_ITEM_LIMIT];
@@ -100,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;
}
@@ -111,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];
}
@@ -125,7 +83,7 @@ uint32 ZoneDatabase::GetZoneForage(uint32 ZoneID, uint8 skill) {
ret = 0;
uint32 rindex = MakeRandomInt(1, chancepool);
uint32 rindex = zone->random.Int(1, chancepool);
for(int i = 0; i < index; i++) {
if(rindex <= chance[i]) {
@@ -156,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;
}
@@ -178,7 +135,7 @@ uint32 ZoneDatabase::GetZoneFishing(uint32 ZoneID, uint8 skill, uint32 &npc_id,
if (index <= 0)
return 0;
uint32 random = MakeRandomInt(1, chancepool);
uint32 random = zone->random.Int(1, chancepool);
for (int i = 0; i < index; i++)
{
if (random > chance[i])
@@ -216,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);
@@ -225,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;
}
@@ -291,7 +249,7 @@ void Client::GoFish()
Bait = m_inv.GetItem(bslot);
//if the bait isnt equipped, need to add its skill bonus
if(bslot >= EmuConstants::GENERAL_BEGIN && Bait->GetItem()->SkillModType == SkillFishing) {
if(bslot >= EmuConstants::GENERAL_BEGIN && Bait != nullptr && Bait->GetItem()->SkillModType == SkillFishing) {
fishing_skill += Bait->GetItem()->SkillModValue;
}
@@ -300,21 +258,23 @@ void Client::GoFish()
fishing_skill = 100+((fishing_skill-100)/2);
}
if (MakeRandomInt(0,175) < fishing_skill) {
if (zone->random.Int(0,175) < fishing_skill) {
uint32 food_id = 0;
//25% chance to fish an item.
if (MakeRandomInt(0, 399) <= fishing_skill ) {
if (zone->random.Int(0, 399) <= fishing_skill ) {
uint32 npc_id = 0;
uint8 npc_chance = 0;
food_id = database.GetZoneFishing(m_pp.zone_id, fishing_skill, npc_id, npc_chance);
//check for add NPC
if(npc_chance > 0 && npc_id) {
if(npc_chance < MakeRandomInt(0, 99)) {
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
@@ -331,7 +291,7 @@ void Client::GoFish()
DeleteItemInInventory(bslot, 1, true); //do we need client update?
if(food_id == 0) {
int index = MakeRandomInt(0, MAX_COMMON_FISH_IDS-1);
int index = zone->random.Int(0, MAX_COMMON_FISH_IDS-1);
food_id = common_fish_ids[index];
}
@@ -366,11 +326,11 @@ void Client::GoFish()
else
{
//chance to use bait when you dont catch anything...
if (MakeRandomInt(0, 4) == 1) {
if (zone->random.Int(0, 4) == 1) {
DeleteItemInInventory(bslot, 1, true); //do we need client update?
Message_StringID(MT_Skills, FISHING_LOST_BAIT); //You lost your bait!
} else {
if (MakeRandomInt(0, 15) == 1) //give about a 1 in 15 chance to spill your beer. we could make this a rule, but it doesn't really seem worth it
if (zone->random.Int(0, 15) == 1) //give about a 1 in 15 chance to spill your beer. we could make this a rule, but it doesn't really seem worth it
//TODO: check for & consume an alcoholic beverage from inventory when this triggers, and set it as a rule that's disabled by default
Message_StringID(MT_Skills, FISHING_SPILL_BEER); //You spill your beer while bringing in your line.
else
@@ -383,7 +343,7 @@ void Client::GoFish()
//chance to break fishing pole...
//this is potentially exploitable in that they can fish
//and then swap out items in primary slot... too lazy to fix right now
if (MakeRandomInt(0, 49) == 1) {
if (zone->random.Int(0, 49) == 1) {
Message_StringID(MT_Skills, FISHING_POLE_BROKE); //Your fishing pole broke!
DeleteItemInInventory(MainPrimary, 0, true);
}
@@ -412,25 +372,25 @@ void Client::ForageItem(bool guarantee) {
};
// these may need to be fine tuned, I am just guessing here
if (guarantee || MakeRandomInt(0,199) < skill_level) {
if (guarantee || zone->random.Int(0,199) < skill_level) {
uint32 foragedfood = 0;
uint32 stringid = FORAGE_NOEAT;
if (MakeRandomInt(0,99) <= 25) {
if (zone->random.Roll(25)) {
foragedfood = database.GetZoneForage(m_pp.zone_id, skill_level);
}
//not an else in case theres no DB food
if(foragedfood == 0) {
uint8 index = 0;
index = MakeRandomInt(0, MAX_COMMON_FOOD_IDS-1);
index = zone->random.Int(0, MAX_COMMON_FOOD_IDS-1);
foragedfood = common_food_ids[index];
}
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;
}
@@ -480,7 +440,7 @@ void Client::ForageItem(bool guarantee) {
}
int ChanceSecondForage = aabonuses.ForageAdditionalItems + itembonuses.ForageAdditionalItems + spellbonuses.ForageAdditionalItems;
if(!guarantee && MakeRandomInt(0,99) < ChanceSecondForage) {
if(!guarantee && zone->random.Roll(ChanceSecondForage)) {
Message_StringID(MT_Skills, FORAGE_MASTERY);
ForageItem(true);
}
+290 -157
View File
File diff suppressed because it is too large Load Diff
+19 -10
View File
@@ -18,14 +18,14 @@
#ifndef GROUPS_H
#define GROUPS_H
#include "../common/types.h"
#include "../common/linked_list.h"
#include "../common/emu_opcodes.h"
#include "../common/eq_packet_structs.h"
#include "entity.h"
#include "../common/types.h"
#include "mob.h"
#include "../common/features.h"
#include "../common/servertalk.h"
class Client;
class EQApplicationPacket;
class Mob;
#define MAX_MARKED_NPCS 3
@@ -51,7 +51,7 @@ public:
Group(uint32 gid);
~Group();
bool AddMember(Mob* newmember, const char* NewMemberName = nullptr, uint32 CharacterID = 0);
bool AddMember(Mob* newmember, const char* NewMemberName = nullptr, uint32 CharacterID = 0, bool ismerc = false);
void AddMember(const char* NewMemberName);
void SendUpdate(uint32 type,Mob* member);
void SendLeadershipAAUpdate();
@@ -63,6 +63,7 @@ public:
bool IsGroupMember(const char *Name);
bool Process();
bool IsGroup() { return true; }
void SendGroupJoinOOZ(Mob* NewMember);
void CastGroupSpell(Mob* caster,uint16 spellid);
void GroupBardPulse(Mob* caster,uint16 spellid);
void SplitExp(uint32 exp, Mob* other);
@@ -86,9 +87,9 @@ public:
uint16 GetAvgLevel();
bool LearnMembers();
void VerifyGroup();
void BalanceHP(int32 penalty, int32 range = 0, Mob* caster = nullptr, int32 limit = 0);
void BalanceMana(int32 penalty, int32 range = 0, Mob* caster = nullptr, int32 limit = 0);
void HealGroup(uint32 heal_amt, Mob* caster, int32 range = 0);
void BalanceHP(int32 penalty, float range = 0, Mob* caster = nullptr, int32 limit = 0);
void BalanceMana(int32 penalty, float range = 0, Mob* caster = nullptr, int32 limit = 0);
void HealGroup(uint32 heal_amt, Mob* caster, float range = 0);
inline void SetGroupAAs(GroupLeadershipAA_Struct *From) { memcpy(&LeaderAbilities, From, sizeof(GroupLeadershipAA_Struct)); }
inline void GetGroupAAs(GroupLeadershipAA_Struct *Into) { memcpy(Into, &LeaderAbilities, sizeof(GroupLeadershipAA_Struct)); }
void UpdateGroupAAs();
@@ -132,6 +133,11 @@ public:
const char *GetClientNameByIndex(uint8 index);
void UpdateXTargetMarkedNPC(uint32 Number, Mob *m);
void SetGroupMentor(int percent, char *name);
void ClearGroupMentor();
inline int GetMentorPercent() { return mentor_percent; }
inline Client *GetMentoree() { return mentoree; }
Mob* members[MAX_GROUP_MEMBERS];
char membername[MAX_GROUP_MEMBERS][64];
uint8 MemberRoles[MAX_GROUP_MEMBERS];
@@ -151,6 +157,9 @@ private:
uint16 PullerTargetID;
uint16 MarkedNPCs[MAX_MARKED_NPCS];
std::string mentoree_name;
Client *mentoree;
int mentor_percent;
};
#endif
+15 -31
View File
@@ -15,23 +15,13 @@
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 "masterentity.h"
#include "worldserver.h"
#include "net.h"
#include "../common/database.h"
#include "../common/spdat.h"
#include "../common/packet_dump.h"
#include "../common/packet_functions.h"
#include "petitions.h"
#include "../common/serverinfo.h"
#include "../common/zone_numbers.h"
#include "../common/moremath.h"
#include "../common/guilds.h"
#include "../common/string_util.h"
#include "guild_mgr.h"
#include "string_ids.h"
#include "npc_ai.h"
#include "worldserver.h"
extern WorldServer worldserver;
@@ -66,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())
@@ -95,7 +84,7 @@ void Client::SendGuildURL()
void Client::SendGuildChannel()
{
if(GetClientVersion() < EQClientSoF)
if(GetClientVersion() < ClientVersion::SoF)
return;
if(IsInAGuild())
@@ -117,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
@@ -155,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
@@ -182,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);
}
@@ -204,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);
@@ -236,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;
}
@@ -348,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);
@@ -423,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;
}
@@ -443,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;
}
+23 -29
View File
@@ -15,14 +15,15 @@
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 "guild_mgr.h"
#include "zonedb.h"
#include "worldserver.h"
#include "../common/servertalk.h"
#include "../common/string_util.h"
#include "client.h"
#include "entity.h"
#include "guild_mgr.h"
#include "worldserver.h"
#include "zonedb.h"
ZoneGuildManager guild_mgr;
GuildBankManager *GuildBanks;
@@ -31,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;
@@ -45,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)) {
@@ -55,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;
@@ -88,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;
@@ -260,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);
@@ -294,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);
@@ -321,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();
}
@@ -337,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;
@@ -363,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);
@@ -416,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];
@@ -432,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);
@@ -602,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;
}
@@ -683,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;
}
@@ -799,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;
}
@@ -845,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;
}
@@ -856,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;
}
@@ -921,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;
}
@@ -973,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;
}
@@ -1123,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;
}
@@ -1135,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;
}
@@ -1298,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;
}
+251 -238
View File
@@ -1,70 +1,73 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
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 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.
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
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 <assert.h>
#include <stdlib.h>
#include <math.h>
#include <list>
#include "masterentity.h"
#include "client.h"
#include "entity.h"
#include "groups.h"
#include "mob.h"
#include "raids.h"
#include "../common/rulesys.h"
#include "../common/misc_functions.h"
#include "hate_list.h"
#include "quest_parser_collection.h"
#include "zone.h"
#include "water_map.h"
#include <stdlib.h>
#include <list>
extern Zone *zone;
HateList::HateList()
{
owner = nullptr;
hate_owner = nullptr;
}
HateList::~HateList()
{
}
// neotokyo: added for frenzy support
// added for frenzy support
// checks if target still is in frenzy mode
void HateList::CheckFrenzyHate()
void HateList::IsEntityInFrenzyMode()
{
auto iterator = list.begin();
while(iterator != list.end())
while (iterator != list.end())
{
if ((*iterator)->ent->GetHPRatio() >= 20)
(*iterator)->bFrenzy = false;
if ((*iterator)->entity_on_hatelist->GetHPRatio() >= 20)
(*iterator)->is_entity_frenzy = false;
++iterator;
}
}
void HateList::Wipe()
void HateList::WipeHateList()
{
auto iterator = list.begin();
while(iterator != list.end())
while (iterator != list.end())
{
Mob* m = (*iterator)->ent;
if(m)
Mob* m = (*iterator)->entity_on_hatelist;
if (m)
{
parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), m, "0", 0);
parse->EventNPC(EVENT_HATE_LIST, hate_owner->CastToNPC(), m, "0", 0);
if(m->IsClient())
if (m->IsClient())
m->CastToClient()->DecrementAggroCount();
}
delete (*iterator);
@@ -73,38 +76,38 @@ void HateList::Wipe()
}
}
bool HateList::IsOnHateList(Mob *mob)
bool HateList::IsEntOnHateList(Mob *mob)
{
if(Find(mob))
if (Find(mob))
return true;
return false;
}
tHateEntry *HateList::Find(Mob *ent)
struct_HateList *HateList::Find(Mob *in_entity)
{
auto iterator = list.begin();
while(iterator != list.end())
while (iterator != list.end())
{
if((*iterator)->ent == ent)
if ((*iterator)->entity_on_hatelist == in_entity)
return (*iterator);
++iterator;
}
return nullptr;
}
void HateList::Set(Mob* other, uint32 in_hate, uint32 in_dam)
void HateList::SetHateAmountOnEnt(Mob* other, uint32 in_hate, uint32 in_damage)
{
tHateEntry *p = Find(other);
if(p)
struct_HateList *entity = Find(other);
if (entity)
{
if(in_dam > 0)
p->damage = in_dam;
if(in_hate > 0)
p->hate = in_hate;
if (in_damage > 0)
entity->hatelist_damage = in_damage;
if (in_hate > 0)
entity->stored_hate_amount = in_hate;
}
}
Mob* HateList::GetDamageTop(Mob* hater)
Mob* HateList::GetDamageTopOnHateList(Mob* hater)
{
Mob* current = nullptr;
Group* grp = nullptr;
@@ -112,119 +115,117 @@ Mob* HateList::GetDamageTop(Mob* hater)
uint32 dmg_amt = 0;
auto iterator = list.begin();
while(iterator != list.end())
while (iterator != list.end())
{
grp = nullptr;
r = nullptr;
if((*iterator)->ent && (*iterator)->ent->IsClient()){
r = entity_list.GetRaidByClient((*iterator)->ent->CastToClient());
if ((*iterator)->entity_on_hatelist && (*iterator)->entity_on_hatelist->IsClient()){
r = entity_list.GetRaidByClient((*iterator)->entity_on_hatelist->CastToClient());
}
grp = entity_list.GetGroupByMob((*iterator)->ent);
grp = entity_list.GetGroupByMob((*iterator)->entity_on_hatelist);
if((*iterator)->ent && r){
if(r->GetTotalRaidDamage(hater) >= dmg_amt)
if ((*iterator)->entity_on_hatelist && r){
if (r->GetTotalRaidDamage(hater) >= dmg_amt)
{
current = (*iterator)->ent;
current = (*iterator)->entity_on_hatelist;
dmg_amt = r->GetTotalRaidDamage(hater);
}
}
else if ((*iterator)->ent != nullptr && grp != nullptr)
else if ((*iterator)->entity_on_hatelist != nullptr && grp != nullptr)
{
if (grp->GetTotalGroupDamage(hater) >= dmg_amt)
{
current = (*iterator)->ent;
current = (*iterator)->entity_on_hatelist;
dmg_amt = grp->GetTotalGroupDamage(hater);
}
}
else if ((*iterator)->ent != nullptr && (uint32)(*iterator)->damage >= dmg_amt)
else if ((*iterator)->entity_on_hatelist != nullptr && (uint32)(*iterator)->hatelist_damage >= dmg_amt)
{
current = (*iterator)->ent;
dmg_amt = (*iterator)->damage;
current = (*iterator)->entity_on_hatelist;
dmg_amt = (*iterator)->hatelist_damage;
}
++iterator;
}
return current;
}
Mob* HateList::GetClosest(Mob *hater) {
Mob* close = nullptr;
float closedist = 99999.9f;
float thisdist;
Mob* HateList::GetClosestEntOnHateList(Mob *hater) {
Mob* close_entity = nullptr;
float close_distance = 99999.9f;
float this_distance;
auto iterator = list.begin();
while(iterator != list.end()) {
thisdist = (*iterator)->ent->DistNoRootNoZ(*hater);
if((*iterator)->ent != nullptr && thisdist <= closedist) {
closedist = thisdist;
close = (*iterator)->ent;
while (iterator != list.end()) {
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;
}
++iterator;
}
if ((!close && hater->IsNPC()) || (close && close->DivineAura()))
close = hater->CastToNPC()->GetHateTop();
if ((!close_entity && hater->IsNPC()) || (close_entity && close_entity->DivineAura()))
close_entity = hater->CastToNPC()->GetHateTop();
return close;
return close_entity;
}
// neotokyo: a few comments added, rearranged code for readability
void HateList::Add(Mob *ent, int32 in_hate, int32 in_dam, bool bFrenzy, bool iAddIfNotExist)
void HateList::AddEntToHateList(Mob *in_entity, int32 in_hate, int32 in_damage, bool in_is_entity_frenzied, bool iAddIfNotExist)
{
if(!ent)
if (!in_entity)
return;
if(ent->IsCorpse())
if (in_entity->IsCorpse())
return;
if(ent->IsClient() && ent->CastToClient()->IsDead())
if (in_entity->IsClient() && in_entity->CastToClient()->IsDead())
return;
tHateEntry *p = Find(ent);
if (p)
struct_HateList *entity = Find(in_entity);
if (entity)
{
p->damage+=(in_dam>=0)?in_dam:0;
p->hate+=in_hate;
p->bFrenzy = bFrenzy;
entity->hatelist_damage += (in_damage >= 0) ? in_damage : 0;
entity->stored_hate_amount += in_hate;
entity->is_entity_frenzy = in_is_entity_frenzied;
}
else if (iAddIfNotExist) {
p = new tHateEntry;
p->ent = ent;
p->damage = (in_dam>=0)?in_dam:0;
p->hate = in_hate;
p->bFrenzy = bFrenzy;
list.push_back(p);
parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), ent, "1", 0);
entity = new struct_HateList;
entity->entity_on_hatelist = in_entity;
entity->hatelist_damage = (in_damage >= 0) ? in_damage : 0;
entity->stored_hate_amount = in_hate;
entity->is_entity_frenzy = in_is_entity_frenzied;
list.push_back(entity);
parse->EventNPC(EVENT_HATE_LIST, hate_owner->CastToNPC(), in_entity, "1", 0);
if (ent->IsClient()) {
if (owner->CastToNPC()->IsRaidTarget())
ent->CastToClient()->SetEngagedRaidTarget(true);
ent->CastToClient()->IncrementAggroCount();
if (in_entity->IsClient()) {
if (hate_owner->CastToNPC()->IsRaidTarget())
in_entity->CastToClient()->SetEngagedRaidTarget(true);
in_entity->CastToClient()->IncrementAggroCount();
}
}
}
bool HateList::RemoveEnt(Mob *ent)
bool HateList::RemoveEntFromHateList(Mob *in_entity)
{
if (!ent)
if (!in_entity)
return false;
bool found = false;
bool is_found = false;
auto iterator = list.begin();
while(iterator != list.end())
while (iterator != list.end())
{
if((*iterator)->ent == ent)
if ((*iterator)->entity_on_hatelist == in_entity)
{
if(ent)
parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), ent, "0", 0);
found = true;
if (in_entity)
parse->EventNPC(EVENT_HATE_LIST, hate_owner->CastToNPC(), in_entity, "0", 0);
is_found = true;
if(ent && ent->IsClient())
ent->CastToClient()->DecrementAggroCount();
if (in_entity && in_entity->IsClient())
in_entity->CastToClient()->DecrementAggroCount();
delete (*iterator);
iterator = list.erase(iterator);
@@ -233,123 +234,128 @@ bool HateList::RemoveEnt(Mob *ent)
else
++iterator;
}
return found;
return is_found;
}
void HateList::DoFactionHits(int32 nfl_id) {
if (nfl_id <= 0)
void HateList::DoFactionHits(int32 npc_faction_level_id) {
if (npc_faction_level_id <= 0)
return;
auto iterator = list.begin();
while(iterator != list.end())
while (iterator != list.end())
{
Client *p;
Client *client;
if ((*iterator)->ent && (*iterator)->ent->IsClient())
p = (*iterator)->ent->CastToClient();
if ((*iterator)->entity_on_hatelist && (*iterator)->entity_on_hatelist->IsClient())
client = (*iterator)->entity_on_hatelist->CastToClient();
else
p = nullptr;
client = nullptr;
if (p)
p->SetFactionLevel(p->CharacterID(), nfl_id, p->GetBaseClass(), p->GetBaseRace(), p->GetDeity());
if (client)
client->SetFactionLevel(client->CharacterID(), npc_faction_level_id, client->GetBaseClass(), client->GetBaseRace(), client->GetDeity());
++iterator;
}
}
int HateList::SummonedPetCount(Mob *hater) {
int HateList::GetSummonedPetCountOnHateList(Mob *hater) {
//Function to get number of 'Summoned' pets on a targets hate list to allow calculations for certian spell effects.
//Unclear from description that pets are required to be 'summoned body type'. Will not require at this time.
int petcount = 0;
int pet_count = 0;
auto iterator = list.begin();
while(iterator != list.end()) {
while (iterator != list.end()) {
if((*iterator)->ent != nullptr && (*iterator)->ent->IsNPC() && ((*iterator)->ent->CastToNPC()->IsPet() || ((*iterator)->ent->CastToNPC()->GetSwarmOwner() > 0)))
if ((*iterator)->entity_on_hatelist != nullptr && (*iterator)->entity_on_hatelist->IsNPC() && ((*iterator)->entity_on_hatelist->CastToNPC()->IsPet() || ((*iterator)->entity_on_hatelist->CastToNPC()->GetSwarmOwner() > 0)))
{
++petcount;
++pet_count;
}
++iterator;
}
return petcount;
return pet_count;
}
Mob *HateList::GetTop(Mob *center)
Mob *HateList::GetEntWithMostHateOnList(Mob *center)
{
Mob* top = nullptr;
int32 hate = -1;
if(center == nullptr)
// hack fix for zone shutdown crashes on some servers
if (!zone->IsLoaded())
return nullptr;
if (RuleB(Aggro,SmartAggroList)){
Mob* topClientTypeInRange = nullptr;
int32 hateClientTypeInRange = -1;
Mob* top_hate = nullptr;
int32 hate = -1;
if (center == nullptr)
return nullptr;
if (RuleB(Aggro, SmartAggroList)){
Mob* top_client_type_in_range = nullptr;
int32 hate_client_type_in_range = -1;
int skipped_count = 0;
auto iterator = list.begin();
while(iterator != list.end())
while (iterator != list.end())
{
tHateEntry *cur = (*iterator);
int16 aggroMod = 0;
struct_HateList *cur = (*iterator);
int16 aggro_mod = 0;
if(!cur){
if (!cur){
++iterator;
continue;
}
if(!cur->ent){
if (!cur->entity_on_hatelist){
++iterator;
continue;
}
if(center->IsNPC() && center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
if(!zone->watermap->InLiquid(cur->ent->GetX(), cur->ent->GetY(), cur->ent->GetZ())) {
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(hateEntryPosition)) {
skipped_count++;
++iterator;
continue;
}
}
if (cur->ent->Sanctuary()) {
if(hate == -1)
if (cur->entity_on_hatelist->Sanctuary()) {
if (hate == -1)
{
top = cur->ent;
top_hate = cur->entity_on_hatelist;
hate = 1;
}
++iterator;
continue;
}
if(cur->ent->DivineAura() || cur->ent->IsMezzed() || cur->ent->IsFeared()){
if(hate == -1)
if (cur->entity_on_hatelist->DivineAura() || cur->entity_on_hatelist->IsMezzed() || cur->entity_on_hatelist->IsFeared()){
if (hate == -1)
{
top = cur->ent;
top_hate = cur->entity_on_hatelist;
hate = 0;
}
++iterator;
continue;
}
int32 currentHate = cur->hate;
int32 current_hate = cur->stored_hate_amount;
if(cur->ent->IsClient()){
if (cur->entity_on_hatelist->IsClient()){
if(cur->ent->CastToClient()->IsSitting()){
aggroMod += RuleI(Aggro, SittingAggroMod);
if (cur->entity_on_hatelist->CastToClient()->IsSitting()){
aggro_mod += RuleI(Aggro, SittingAggroMod);
}
if(center){
if(center->GetTarget() == cur->ent)
aggroMod += RuleI(Aggro, CurrentTargetAggroMod);
if(RuleI(Aggro, MeleeRangeAggroMod) != 0)
if (center){
if (center->GetTarget() == cur->entity_on_hatelist)
aggro_mod += RuleI(Aggro, CurrentTargetAggroMod);
if (RuleI(Aggro, MeleeRangeAggroMod) != 0)
{
if(center->CombatRange(cur->ent)){
aggroMod += RuleI(Aggro, MeleeRangeAggroMod);
if (center->CombatRange(cur->entity_on_hatelist)){
aggro_mod += RuleI(Aggro, MeleeRangeAggroMod);
if(currentHate > hateClientTypeInRange || cur->bFrenzy){
hateClientTypeInRange = currentHate;
topClientTypeInRange = cur->ent;
if (current_hate > hate_client_type_in_range || cur->is_entity_frenzy){
hate_client_type_in_range = current_hate;
top_client_type_in_range = cur->entity_on_hatelist;
}
}
}
@@ -357,105 +363,112 @@ Mob *HateList::GetTop(Mob *center)
}
else{
if(center){
if(center->GetTarget() == cur->ent)
aggroMod += RuleI(Aggro, CurrentTargetAggroMod);
if(RuleI(Aggro, MeleeRangeAggroMod) != 0)
if (center){
if (center->GetTarget() == cur->entity_on_hatelist)
aggro_mod += RuleI(Aggro, CurrentTargetAggroMod);
if (RuleI(Aggro, MeleeRangeAggroMod) != 0)
{
if(center->CombatRange(cur->ent)){
aggroMod += RuleI(Aggro, MeleeRangeAggroMod);
if (center->CombatRange(cur->entity_on_hatelist)){
aggro_mod += RuleI(Aggro, MeleeRangeAggroMod);
}
}
}
}
if(cur->ent->GetMaxHP() != 0 && ((cur->ent->GetHP()*100/cur->ent->GetMaxHP()) < 20)){
aggroMod += RuleI(Aggro, CriticallyWoundedAggroMod);
if (cur->entity_on_hatelist->GetMaxHP() != 0 && ((cur->entity_on_hatelist->GetHP() * 100 / cur->entity_on_hatelist->GetMaxHP()) < 20)){
aggro_mod += RuleI(Aggro, CriticallyWoundedAggroMod);
}
if(aggroMod){
currentHate += (currentHate * aggroMod / 100);
if (aggro_mod){
current_hate += (current_hate * aggro_mod / 100);
}
if(currentHate > hate || cur->bFrenzy){
hate = currentHate;
top = cur->ent;
if (current_hate > hate || cur->is_entity_frenzy){
hate = current_hate;
top_hate = cur->entity_on_hatelist;
}
++iterator;
}
if(topClientTypeInRange != nullptr && top != nullptr) {
bool isTopClientType = top->IsClient();
if (top_client_type_in_range != nullptr && top_hate != nullptr) {
bool isTopClientType = top_hate->IsClient();
#ifdef BOTS
if(!isTopClientType) {
if(top->IsBot()) {
if (!isTopClientType) {
if (top_hate->IsBot()) {
isTopClientType = true;
topClientTypeInRange = top;
top_client_type_in_range = top_hate;
}
}
#endif //BOTS
if(!isTopClientType) {
if(top->IsMerc()) {
if (!isTopClientType) {
if (top_hate->IsMerc()) {
isTopClientType = true;
topClientTypeInRange = top;
top_client_type_in_range = top_hate;
}
}
if(!isTopClientType)
return topClientTypeInRange ? topClientTypeInRange : nullptr;
if (!isTopClientType) {
if (top_hate->GetSpecialAbility(ALLOW_TO_TANK)){
isTopClientType = true;
top_client_type_in_range = top_hate;
}
}
return top ? top : nullptr;
if (!isTopClientType)
return top_client_type_in_range ? top_client_type_in_range : nullptr;
return top_hate ? top_hate : nullptr;
}
else {
if(top == nullptr && skipped_count > 0) {
if (top_hate == nullptr && skipped_count > 0) {
return center->GetTarget() ? center->GetTarget() : nullptr;
}
return top ? top : nullptr;
return top_hate ? top_hate : nullptr;
}
}
else{
auto iterator = list.begin();
int skipped_count = 0;
while(iterator != list.end())
while (iterator != list.end())
{
tHateEntry *cur = (*iterator);
if(center->IsNPC() && center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
if(!zone->watermap->InLiquid(cur->ent->GetX(), cur->ent->GetY(), cur->ent->GetZ())) {
struct_HateList *cur = (*iterator);
if (center->IsNPC() && center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
if(!zone->watermap->InLiquid(glm::vec3(cur->entity_on_hatelist->GetPosition()))) {
skipped_count++;
++iterator;
continue;
}
}
if(cur->ent != nullptr && ((cur->hate > hate) || cur->bFrenzy ))
if (cur->entity_on_hatelist != nullptr && ((cur->stored_hate_amount > hate) || cur->is_entity_frenzy))
{
top = cur->ent;
hate = cur->hate;
top_hate = cur->entity_on_hatelist;
hate = cur->stored_hate_amount;
}
++iterator;
}
if(top == nullptr && skipped_count > 0) {
if (top_hate == nullptr && skipped_count > 0) {
return center->GetTarget() ? center->GetTarget() : nullptr;
}
return top ? top : nullptr;
return top_hate ? top_hate : nullptr;
}
return nullptr;
}
Mob *HateList::GetMostHate(){
Mob *HateList::GetEntWithMostHateOnList(){
Mob* top = nullptr;
int32 hate = -1;
auto iterator = list.begin();
while(iterator != list.end())
while (iterator != list.end())
{
tHateEntry *cur = (*iterator);
if(cur->ent != nullptr && (cur->hate > hate))
struct_HateList *cur = (*iterator);
if (cur->entity_on_hatelist != nullptr && (cur->stored_hate_amount > hate))
{
top = cur->ent;
hate = cur->hate;
top = cur->entity_on_hatelist;
hate = cur->stored_hate_amount;
}
++iterator;
}
@@ -463,57 +476,55 @@ Mob *HateList::GetMostHate(){
}
Mob *HateList::GetRandom()
Mob *HateList::GetRandomEntOnHateList()
{
int count = list.size();
if(count == 0) //If we don't have any entries it'll crash getting a random 0, -1 position.
if (count == 0) //If we don't have any entries it'll crash getting a random 0, -1 position.
return NULL;
if(count == 1) //No need to do all that extra work if we only have one hate entry
if (count == 1) //No need to do all that extra work if we only have one hate entry
{
if(*list.begin()) // Just in case tHateEntry is invalidated somehow...
return (*list.begin())->ent;
if (*list.begin()) // Just in case tHateEntry is invalidated somehow...
return (*list.begin())->entity_on_hatelist;
return NULL;
}
auto iterator = list.begin();
int random = MakeRandomInt(0, count - 1);
int random = zone->random.Int(0, count - 1);
for (int i = 0; i < random; i++)
++iterator;
return (*iterator)->ent;
return (*iterator)->entity_on_hatelist;
}
int32 HateList::GetEntHate(Mob *ent, bool damage)
int32 HateList::GetEntHateAmount(Mob *in_entity, bool damage)
{
tHateEntry *p;
struct_HateList *entity;
p = Find(ent);
entity = Find(in_entity);
if ( p && damage)
return p->damage;
else if (p)
return p->hate;
if (entity && damage)
return entity->hatelist_damage;
else if (entity)
return entity->stored_hate_amount;
else
return 0;
}
//looking for any mob with hate > -1
bool HateList::IsEmpty() {
bool HateList::IsHateListEmpty() {
return(list.size() == 0);
}
// Prints hate list to a client
void HateList::PrintToClient(Client *c)
void HateList::PrintHateListToClient(Client *c)
{
auto iterator = list.begin();
while (iterator != list.end())
{
tHateEntry *e = (*iterator);
struct_HateList *e = (*iterator);
c->Message(0, "- name: %s, damage: %d, hate: %d",
(e->ent && e->ent->GetName()) ? e->ent->GetName() : "(null)",
e->damage, e->hate);
(e->entity_on_hatelist && e->entity_on_hatelist->GetName()) ? e->entity_on_hatelist->GetName() : "(null)",
e->hatelist_damage, e->stored_hate_amount);
++iterator;
}
@@ -521,7 +532,7 @@ void HateList::PrintToClient(Client *c)
int HateList::AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOptions *opts)
{
if(!target || !caster)
if (!target || !caster)
return 0;
int ret = 0;
@@ -529,25 +540,25 @@ int HateList::AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOption
auto iterator = list.begin();
while (iterator != list.end())
{
tHateEntry *h = (*iterator);
struct_HateList *h = (*iterator);
++iterator;
if(h && h->ent && h->ent != caster)
if (h && h->entity_on_hatelist && h->entity_on_hatelist != caster)
{
if(caster->CombatRange(h->ent))
if (caster->CombatRange(h->entity_on_hatelist))
{
id_list.push_back(h->ent->GetID());
id_list.push_back(h->entity_on_hatelist->GetID());
++ret;
}
}
}
std::list<uint32>::iterator iter = id_list.begin();
while(iter != id_list.end())
while (iter != id_list.end())
{
Mob *cur = entity_list.GetMobID((*iter));
if(cur)
if (cur)
{
for(int i = 0; i < count; ++i) {
for (int i = 0; i < count; ++i) {
caster->Attack(cur, MainPrimary, false, false, false, opts);
}
}
@@ -557,12 +568,15 @@ int HateList::AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOption
return ret;
}
void HateList::SpellCast(Mob *caster, uint32 spell_id, float range)
void HateList::SpellCast(Mob *caster, uint32 spell_id, float range, Mob* ae_center)
{
if(!caster)
{
if (!caster)
return;
}
Mob* center = caster;
if (ae_center)
center = ae_center;
//this is slower than just iterating through the list but avoids
//crashes when people kick the bucket in the middle of this call
@@ -575,33 +589,32 @@ void HateList::SpellCast(Mob *caster, uint32 spell_id, float range)
auto iterator = list.begin();
while (iterator != list.end())
{
tHateEntry *h = (*iterator);
if(range > 0)
struct_HateList *h = (*iterator);
if (range > 0)
{
dist_targ = caster->DistNoRoot(*h->ent);
if(dist_targ <= range && dist_targ >= min_range2)
dist_targ = DistanceSquared(center->GetPosition(), h->entity_on_hatelist->GetPosition());
if (dist_targ <= range && dist_targ >= min_range2)
{
id_list.push_back(h->ent->GetID());
h->ent->CalcSpellPowerDistanceMod(spell_id, dist_targ);
id_list.push_back(h->entity_on_hatelist->GetID());
h->entity_on_hatelist->CalcSpellPowerDistanceMod(spell_id, dist_targ);
}
}
else
{
id_list.push_back(h->ent->GetID());
h->ent->CalcSpellPowerDistanceMod(spell_id, 0, caster);
id_list.push_back(h->entity_on_hatelist->GetID());
h->entity_on_hatelist->CalcSpellPowerDistanceMod(spell_id, 0, caster);
}
++iterator;
}
std::list<uint32>::iterator iter = id_list.begin();
while(iter != id_list.end())
while (iter != id_list.end())
{
Mob *cur = entity_list.GetMobID((*iter));
if(cur)
if (cur)
{
caster->SpellOnTarget(spell_id, cur);
}
iter++;
}
}
+47 -55
View File
@@ -1,29 +1,36 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
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 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.
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
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 HATELIST_H
#define HATELIST_H
struct tHateEntry
class Client;
class Group;
class Mob;
class Raid;
struct ExtraAttackOptions;
struct struct_HateList
{
Mob *ent;
int32 damage, hate;
bool bFrenzy;
Mob *entity_on_hatelist;
int32 hatelist_damage;
uint32 stored_hate_amount;
bool is_entity_frenzy;
};
class HateList
@@ -32,53 +39,38 @@ public:
HateList();
~HateList();
// adds a mob to the hatelist
void Add(Mob *ent, int32 in_hate=0, int32 in_dam=0, bool bFrenzy = false, bool iAddIfNotExist = true);
// sets existing hate
void Set(Mob *other, uint32 in_hate, uint32 in_dam);
// removes mobs from hatelist
bool RemoveEnt(Mob *ent);
// Remove all
void Wipe();
// ???
void DoFactionHits(int32 nfl_id);
// Gets Hate amount for mob
int32 GetEntHate(Mob *ent, bool damage = false);
// gets top hated mob
Mob *GetTop(Mob *center);
// gets any on the list
Mob *GetRandom();
// get closest mob or nullptr if list empty
Mob *GetClosest(Mob *hater);
// gets top mob or nullptr if hate list empty
Mob *GetDamageTop(Mob *hater);
// used to check if mob is on hatelist
bool IsOnHateList(Mob *);
// used to remove or add frenzy hate
void CheckFrenzyHate();
//Gets the target with the most hate regardless of things like frenzy etc.
Mob* GetMostHate();
// Count 'Summoned' pets on hatelist
int SummonedPetCount(Mob *hater);
Mob *GetClosestEntOnHateList(Mob *hater);
Mob *GetDamageTopOnHateList(Mob *hater);
Mob *GetEntWithMostHateOnList(Mob *center);
Mob *GetRandomEntOnHateList();
Mob* GetEntWithMostHateOnList();
bool IsEntOnHateList(Mob *mob);
bool IsHateListEmpty();
bool RemoveEntFromHateList(Mob *ent);
int AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOptions *opts);
int GetSummonedPetCountOnHateList(Mob *hater);
void SpellCast(Mob *caster, uint32 spell_id, float range);
int32 GetEntHateAmount(Mob *ent, bool in_damage = false);
bool IsEmpty();
void PrintToClient(Client *c);
std::list<struct_HateList*>& GetHateList() { return list; }
//For accessing the hate list via perl; don't use for anything else
std::list<tHateEntry*>& GetHateList() { return list; }
void AddEntToHateList(Mob *ent, int32 in_hate = 0, int32 in_damage = 0, bool in_is_frenzied = false, bool add_to_hate_list_if_not_exist = true);
void DoFactionHits(int32 npc_faction_level_id);
void IsEntityInFrenzyMode();
void PrintHateListToClient(Client *c);
void SetHateAmountOnEnt(Mob *other, uint32 in_hate, uint32 in_damage);
void SetHateOwner(Mob *new_hate_owner) { hate_owner = new_hate_owner; }
void SpellCast(Mob *caster, uint32 spell_id, float range, Mob *ae_center = nullptr);
void WipeHateList();
//setting owner
void SetOwner(Mob *newOwner) { owner = newOwner; }
protected:
tHateEntry* Find(Mob *ent);
struct_HateList* Find(Mob *ent);
private:
std::list<tHateEntry*> list;
Mob *owner;
std::list<struct_HateList*> list;
Mob *hate_owner;
};
#endif
#endif
+12 -12
View File
@@ -16,20 +16,21 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "masterentity.h"
#include "../common/item.h"
#include "../common/global_define.h"
#include "../common/eqemu_logsys.h"
#include "../common/linked_list.h"
#include "../common/string_util.h"
#include <math.h>
#include <assert.h>
#include "worldserver.h"
#include "client.h"
#include "entity.h"
#include "horse.h"
#include "mob.h"
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.
+6 -2
View File
@@ -18,14 +18,18 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
#ifndef HORSES_H
#define HORSES_H
#include "../common/debug.h"
#include "npc.h"
#include <map>
class Client;
class Mob;
struct NPCType;
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);
+739 -458
View File
File diff suppressed because it is too large Load Diff
+53 -32
View File
@@ -15,16 +15,25 @@
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 <stdio.h>
#include <iostream>
#include <stdlib.h>
#include "npc.h"
#include "masterentity.h"
#include "zonedb.h"
#include "../common/global_define.h"
#include "../common/loottable.h"
#include "../common/misc_functions.h"
#include "../common/data_verification.h"
#include "client.h"
#include "entity.h"
#include "mob.h"
#include "npc.h"
#include "zonedb.h"
#include <iostream>
#include <stdlib.h>
#ifdef _WINDOWS
#define snprintf _snprintf
#endif
// Queries the loottable: adds item & coin to the npc
void ZoneDatabase::AddLootTableToNPC(NPC* npc,uint32 loottable_id, ItemList* itemlist, uint32* copper, uint32* silver, uint32* gold, uint32* plat) {
const LootTable_Struct* lts = nullptr;
@@ -46,17 +55,17 @@ void ZoneDatabase::AddLootTableToNPC(NPC* npc,uint32 loottable_id, ItemList* ite
}
uint32 cash = 0;
if(max_cash > 0 && EQEmu::ValueWithin(lts->avgcoin, min_cash, max_cash)) {
if(max_cash > 0 && lts->avgcoin > 0 && EQEmu::ValueWithin(lts->avgcoin, min_cash, max_cash)) {
float upper_chance = (float)(lts->avgcoin - min_cash) / (float)(max_cash - min_cash);
float avg_cash_roll = (float)MakeRandomFloat(0.0, 1.0);
if(avg_cash_roll <= upper_chance) {
cash = MakeRandomInt(lts->avgcoin, max_cash);
float avg_cash_roll = (float)zone->random.Real(0.0, 1.0);
if(avg_cash_roll < upper_chance) {
cash = zone->random.Int(lts->avgcoin, max_cash);
} else {
cash = MakeRandomInt(min_cash, lts->avgcoin);
cash = zone->random.Int(min_cash, lts->avgcoin);
}
} else {
cash = MakeRandomInt(min_cash, max_cash);
cash = zone->random.Int(min_cash, max_cash);
}
if(cash != 0) {
@@ -84,7 +93,7 @@ void ZoneDatabase::AddLootTableToNPC(NPC* npc,uint32 loottable_id, ItemList* ite
float drop_chance = 0.0f;
if(ltchance > 0.0 && ltchance < 100.0) {
drop_chance = (float)MakeRandomFloat(0.0, 100.0);
drop_chance = (float)zone->random.Real(0.0, 100.0);
}
if (ltchance != 0.0 && (ltchance == 100.0 || drop_chance <= ltchance)) {
@@ -109,7 +118,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml
for(uint32 i = 0; i < lds->NumEntries; ++i) {
int charges = lds->Entries[i].multiplier;
for(int j = 0; j < charges; ++j) {
if(MakeRandomFloat(0.0, 100.0) <= lds->Entries[i].chance) {
if(zone->random.Real(0.0, 100.0) <= lds->Entries[i].chance) {
const Item_Struct* dbitem = GetItem(lds->Entries[i].item_id);
npc->AddLootDrop(dbitem, itemlist, lds->Entries[i].item_charges, lds->Entries[i].minlevel,
lds->Entries[i].maxlevel, lds->Entries[i].equip_item > 0 ? true : false, false);
@@ -144,9 +153,9 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml
}
mindrop = EQEmu::ClampLower(mindrop, (uint8)1);
int item_count = MakeRandomInt(mindrop, droplimit);
int item_count = zone->random.Int(mindrop, droplimit);
for(int i = 0; i < item_count; ++i) {
float roll = (float)MakeRandomFloat(0.0, roll_t);
float roll = (float)zone->random.Real(0.0, roll_t);
for(uint32 j = 0; j < lds->NumEntries; ++j) {
const Item_Struct* db_item = GetItem(lds->Entries[j].item_id);
if(db_item) {
@@ -158,7 +167,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml
charges = EQEmu::ClampLower(charges, 1);
for(int k = 1; k < charges; ++k) {
float c_roll = (float)MakeRandomFloat(0.0, 100.0);
float c_roll = (float)zone->random.Real(0.0, 100.0);
if(c_roll <= lds->Entries[i].chance) {
npc->AddLootDrop(db_item, itemlist, lds->Entries[j].item_charges, lds->Entries[j].minlevel,
lds->Entries[j].maxlevel, lds->Entries[j].equip_item > 0 ? true : false, false);
@@ -173,7 +182,12 @@ 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 +201,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;
@@ -200,14 +214,17 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge
}
item->item_id = item2->ID;
item->charges = (uint8)charges;
item->aug1 = 0;
item->aug2 = 0;
item->aug3 = 0;
item->aug4 = 0;
item->aug5 = 0;
item->minlevel = minlevel;
item->maxlevel = maxlevel;
item->charges = charges;
item->aug_1 = 0;
item->aug_2 = 0;
item->aug_3 = 0;
item->aug_4 = 0;
item->aug_5 = 0;
item->aug_6 = 0;
item->attuned = 0;
item->min_level = minlevel;
item->max_level = maxlevel;
if (equipit) {
uint8 eslot = 0xFF;
char newid[20];
@@ -287,7 +304,7 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge
eslot = MaterialPrimary;
}
else if (foundslot == MainSecondary
&& (GetOwner() != nullptr || (GetLevel() >= 13 && MakeRandomInt(0,99) < NPC_DW_CHANCE) || (item2->Damage==0)) &&
&& (GetOwner() != nullptr || (GetLevel() >= 13 && zone->random.Roll(NPC_DW_CHANCE)) || (item2->Damage==0)) &&
(item2->ItemType == ItemType1HSlash || item2->ItemType == ItemType1HBlunt || item2->ItemType == ItemTypeShield ||
item2->ItemType == ItemType1HPiercing))
{
@@ -322,7 +339,7 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge
what was this about???
if (((npc->GetRace()==127) && (npc->CastToMob()->GetOwnerID()!=0)) && (item2->Slots==24576) || (item2->Slots==8192) || (item2->Slots==16384)){
npc->d_meele_texture2=atoi(newid);
npc->d_melee_texture2=atoi(newid);
wc->wear_slot_id=8;
if (item2->Material >0)
wc->material=item2->Material;
@@ -345,7 +362,7 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge
if (found) {
CalcBonuses(); // This is less than ideal for bulk adding of items
}
item->equipSlot = item2->Slots;
item->equip_slot = item2->Slots;
}
if(itemlist != nullptr)
@@ -357,6 +374,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) {
+21 -15
View File
@@ -235,19 +235,24 @@ void Lua_Client::SetBindPoint(int to_zone) {
self->SetBindPoint(to_zone);
}
void Lua_Client::SetBindPoint(int to_zone, float new_x) {
void Lua_Client::SetBindPoint(int to_zone, int to_instance) {
Lua_Safe_Call_Void();
self->SetBindPoint(to_zone, new_x);
self->SetBindPoint(to_zone, to_instance);
}
void Lua_Client::SetBindPoint(int to_zone, float new_x, float new_y) {
void Lua_Client::SetBindPoint(int to_zone, int to_instance, float new_x) {
Lua_Safe_Call_Void();
self->SetBindPoint(to_zone, new_x, new_y);
self->SetBindPoint(to_zone, to_instance, glm::vec3(new_x,0.0f,0.0f));
}
void Lua_Client::SetBindPoint(int to_zone, float new_x, float new_y, float new_z) {
void Lua_Client::SetBindPoint(int to_zone, int to_instance, float new_x, float new_y) {
Lua_Safe_Call_Void();
self->SetBindPoint(to_zone, new_x, new_y, new_z);
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, glm::vec3(new_x, new_y, new_z));
}
float Lua_Client::GetBindX() {
@@ -695,16 +700,16 @@ 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, attuned);
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, attuned, to_slot);
self->SummonItem(item_id, charges, aug1, aug2, aug3, aug4, aug5, 0, attuned, to_slot);
}
void Lua_Client::SetStats(int type, int value) {
@@ -829,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() {
@@ -1297,9 +1302,10 @@ luabind::scope lua_register_client() {
.def("SetEXP", (void(Lua_Client::*)(uint32,uint32,bool))&Lua_Client::SetEXP)
.def("SetBindPoint", (void(Lua_Client::*)(void))&Lua_Client::SetBindPoint)
.def("SetBindPoint", (void(Lua_Client::*)(int))&Lua_Client::SetBindPoint)
.def("SetBindPoint", (void(Lua_Client::*)(int,float))&Lua_Client::SetBindPoint)
.def("SetBindPoint", (void(Lua_Client::*)(int,float,float))&Lua_Client::SetBindPoint)
.def("SetBindPoint", (void(Lua_Client::*)(int,float,float,float))&Lua_Client::SetBindPoint)
.def("SetBindPoint", (void(Lua_Client::*)(int,int))&Lua_Client::SetBindPoint)
.def("SetBindPoint", (void(Lua_Client::*)(int,int,float))&Lua_Client::SetBindPoint)
.def("SetBindPoint", (void(Lua_Client::*)(int,int,float,float))&Lua_Client::SetBindPoint)
.def("SetBindPoint", (void(Lua_Client::*)(int,int,float,float, float))&Lua_Client::SetBindPoint)
.def("GetBindX", (float(Lua_Client::*)(void))&Lua_Client::GetBindX)
.def("GetBindX", (float(Lua_Client::*)(int))&Lua_Client::GetBindX)
.def("GetBindY", (float(Lua_Client::*)(void))&Lua_Client::GetBindY)
@@ -1390,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)
+4 -3
View File
@@ -73,9 +73,10 @@ public:
void SetEXP(uint32 set_exp, uint32 set_aaxp, bool resexp);
void SetBindPoint();
void SetBindPoint(int to_zone);
void SetBindPoint(int to_zone, float new_x);
void SetBindPoint(int to_zone, float new_x, float new_y);
void SetBindPoint(int to_zone, float new_x, float new_y, float new_z);
void SetBindPoint(int to_zone, int to_instance);
void SetBindPoint(int to_zone, int to_instance, float new_x);
void SetBindPoint(int to_zone, int to_instance, float new_x, float new_y);
void SetBindPoint(int to_zone, int to_instance, float new_x, float new_y, float new_z);
float GetBindX();
float GetBindX(int index);
float GetBindY();
+4 -4
View File
@@ -39,12 +39,12 @@ void Lua_Corpse::ResetLooter() {
uint32 Lua_Corpse::GetDBID() {
Lua_Safe_Call_Int();
return self->GetDBID();
return self->GetCorpseDBID();
}
bool Lua_Corpse::IsRezzed() {
Lua_Safe_Call_Bool();
return self->Rezzed();
return self->IsRezzed();
}
const char* Lua_Corpse::GetOwnerName() {
@@ -114,12 +114,12 @@ void Lua_Corpse::SetDecayTimer(uint32 decaytime) {
bool Lua_Corpse::CanMobLoot(int charid) {
Lua_Safe_Call_Bool();
return self->CanMobLoot(charid);
return self->CanPlayerLoot(charid);
}
void Lua_Corpse::AllowMobLoot(Lua_Mob them, uint8 slot) {
Lua_Safe_Call_Void();
self->AllowMobLoot(them, slot);
self->AllowPlayerLoot(them, slot);
}
bool Lua_Corpse::Summon(Lua_Client client, bool spell, bool checkdistance) {
+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() {
+332 -46
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 { };
@@ -32,41 +33,107 @@ struct lua_registered_event {
};
extern std::map<std::string, std::list<lua_registered_event>> lua_encounter_events_registered;
extern std::map<std::string, bool> lua_encounters_loaded;
extern void MapOpcodes();
extern void ClearMappedOpcode(EmuOpcode op);
void unregister_event(std::string package_name, std::string name, int evt);
void load_encounter(std::string name) {
if(lua_encounters_loaded.count(name) > 0)
return;
lua_encounters_loaded[name] = true;
parse->EventEncounter(EVENT_ENCOUNTER_LOAD, name, 0);
}
void load_encounter_with_data(std::string name, std::string info_str) {
if(lua_encounters_loaded.count(name) > 0)
return;
lua_encounters_loaded[name] = true;
std::vector<EQEmu::Any> info_ptrs;
info_ptrs.push_back(&info_str);
parse->EventEncounter(EVENT_ENCOUNTER_LOAD, name, 0, &info_ptrs);
}
void unload_encounter(std::string name) {
if(lua_encounters_loaded.count(name) == 0)
return;
auto liter = lua_encounter_events_registered.begin();
while(liter != lua_encounter_events_registered.end()) {
std::list<lua_registered_event> &elist = liter->second;
auto iter = elist.begin();
while(iter != elist.end()) {
if((*iter).encounter_name.compare(name) == 0) {
iter = elist.erase(iter);
} else {
++iter;
}
}
if(elist.size() == 0) {
lua_encounter_events_registered.erase(liter++);
} else {
++liter;
}
}
lua_encounters_loaded.erase(name);
parse->EventEncounter(EVENT_ENCOUNTER_UNLOAD, name, 0);
}
void unload_encounter_with_data(std::string name, std::string info_str) {
if(lua_encounters_loaded.count(name) == 0)
return;
auto liter = lua_encounter_events_registered.begin();
while(liter != lua_encounter_events_registered.end()) {
std::list<lua_registered_event> &elist = liter->second;
auto iter = elist.begin();
while(iter != elist.end()) {
if((*iter).encounter_name.compare(name) == 0) {
iter = elist.erase(iter);
}
else {
++iter;
}
}
if(elist.size() == 0) {
lua_encounter_events_registered.erase(liter++);
}
else {
++liter;
}
}
lua_encounters_loaded.erase(name);
std::vector<EQEmu::Any> info_ptrs;
info_ptrs.push_back(&info_str);
parse->EventEncounter(EVENT_ENCOUNTER_UNLOAD, name, 0, &info_ptrs);
}
void register_event(std::string package_name, std::string name, int evt, luabind::adl::object func) {
if(lua_encounters_loaded.count(name) == 0)
return;
unregister_event(package_name, name, evt);
lua_registered_event e;
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;
elist.push_back(e);
lua_encounter_events_registered[package_name] = elist;
} else {
std::list<lua_registered_event> elist = liter->second;
auto iter = elist.begin();
while(iter != elist.end()) {
if(iter->event_id == evt && iter->encounter_name.compare(name) == 0) {
//already registered this event for this encounter
return;
}
++iter;
}
std::list<lua_registered_event> &elist = liter->second;
elist.push_back(e);
lua_encounter_events_registered[package_name] = elist;
}
}
@@ -78,7 +145,9 @@ void unregister_event(std::string package_name, std::string name, int evt) {
while(iter != elist.end()) {
if(iter->event_id == evt && iter->encounter_name.compare(name) == 0) {
iter = elist.erase(iter);
break;
}
++iter;
}
lua_encounter_events_registered[package_name] = elist;
}
@@ -93,6 +162,11 @@ void register_npc_event(std::string name, int evt, int npc_id, luabind::adl::obj
}
}
void register_npc_event(int evt, int npc_id, luabind::adl::object func) {
std::string name = quest_manager.GetEncounter();
register_npc_event(name, evt, npc_id, func);
}
void unregister_npc_event(std::string name, int evt, int npc_id) {
std::stringstream package_name;
package_name << "npc_" << npc_id;
@@ -100,32 +174,57 @@ void unregister_npc_event(std::string name, int evt, int npc_id) {
unregister_event(package_name.str(), name, evt);
}
void unregister_npc_event(int evt, int npc_id) {
std::string name = quest_manager.GetEncounter();
unregister_npc_event(name, evt, npc_id);
}
void register_player_event(std::string name, int evt, luabind::adl::object func) {
if(luabind::type(func) == LUA_TFUNCTION) {
register_event("player", name, evt, func);
}
}
void register_player_event(int evt, luabind::adl::object func) {
std::string name = quest_manager.GetEncounter();
register_player_event(name, evt, func);
}
void unregister_player_event(std::string name, int evt) {
unregister_event("player", name, evt);
}
void unregister_player_event(int evt) {
std::string name = quest_manager.GetEncounter();
unregister_player_event(name, 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);
}
}
void register_item_event(int evt, int item_id, luabind::adl::object func) {
std::string name = quest_manager.GetEncounter();
register_item_event(name, evt, item_id, 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);
}
void unregister_item_event(int evt, int item_id) {
std::string name = quest_manager.GetEncounter();
unregister_item_event(name, evt, item_id);
}
void register_spell_event(std::string name, int evt, int spell_id, luabind::adl::object func) {
if(luabind::type(func) == LUA_TFUNCTION) {
std::stringstream package_name;
@@ -135,6 +234,11 @@ void register_spell_event(std::string name, int evt, int spell_id, luabind::adl:
}
}
void register_spell_event(int evt, int spell_id, luabind::adl::object func) {
std::string name = quest_manager.GetEncounter();
register_spell_event(name, evt, spell_id, func);
}
void unregister_spell_event(std::string name, int evt, int spell_id) {
std::stringstream package_name;
package_name << "spell_" << spell_id;
@@ -142,14 +246,19 @@ void unregister_spell_event(std::string name, int evt, int spell_id) {
unregister_event(package_name.str(), name, evt);
}
void unregister_spell_event(int evt, int spell_id) {
std::string name = quest_manager.GetEncounter();
unregister_spell_event(name, evt, 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) {
@@ -313,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() {
@@ -377,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) {
@@ -577,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) {
@@ -928,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 {
@@ -1109,6 +1218,10 @@ Lua_ItemInst lua_get_quest_item() {
return quest_manager.GetQuestItem();
}
std::string lua_get_encounter() {
return quest_manager.GetEncounter();
}
void lua_map_opcodes() {
MapOpcodes();
}
@@ -1136,19 +1249,186 @@ 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) { \
try { \
npc_type->name = luabind::object_cast<c_type>(cur); \
} \
catch(luabind::cast_failed) { \
npc_type->size = default_value; \
} \
} \
else { \
npc_type->size = default_value; \
} \
} while(0)
#define LuaCreateNPCParseString(name, str_length, default_value) do { \
cur = table[#name]; \
if(luabind::type(cur) != LUA_TNIL) { \
try { \
std::string tmp = luabind::object_cast<std::string>(cur); \
strncpy(npc_type->name, tmp.c_str(), str_length); \
} \
catch(luabind::cast_failed) { \
strncpy(npc_type->name, default_value, str_length); \
} \
} \
else { \
strncpy(npc_type->name, default_value, str_length); \
} \
} while(0)
void lua_create_npc(luabind::adl::object table, float x, float y, float z, float heading) {
if(luabind::type(table) != LUA_TTABLE) {
return;
}
NPCType* npc_type = new NPCType;
memset(npc_type, 0, sizeof(NPCType));
luabind::adl::index_proxy<luabind::adl::object> cur = table["name"];
LuaCreateNPCParseString(name, 64, "_");
LuaCreateNPCParseString(lastname, 64, "");
LuaCreateNPCParse(cur_hp, int32, 30);
LuaCreateNPCParse(max_hp, int32, 30);
LuaCreateNPCParse(size, float, 6.0f);
LuaCreateNPCParse(runspeed, float, 1.25f);
LuaCreateNPCParse(gender, uint8, 0);
LuaCreateNPCParse(race, uint16, 1);
LuaCreateNPCParse(class_, uint8, WARRIOR);
LuaCreateNPCParse(bodytype, uint8, 0);
LuaCreateNPCParse(deity, uint8, 0);
LuaCreateNPCParse(level, uint8, 1);
LuaCreateNPCParse(npc_id, uint32, 1);
LuaCreateNPCParse(texture, uint8, 0);
LuaCreateNPCParse(helmtexture, uint8, 0);
LuaCreateNPCParse(loottable_id, uint32, 0);
LuaCreateNPCParse(npc_spells_id, uint32, 0);
LuaCreateNPCParse(npc_spells_effects_id, uint32, 0);
LuaCreateNPCParse(npc_faction_id, int32, 0);
LuaCreateNPCParse(merchanttype, uint32, 0);
LuaCreateNPCParse(alt_currency_type, uint32, 0);
LuaCreateNPCParse(adventure_template, uint32, 0);
LuaCreateNPCParse(trap_template, uint32, 0);
LuaCreateNPCParse(light, uint8, 0);
LuaCreateNPCParse(AC, uint32, 0);
LuaCreateNPCParse(Mana, uint32, 0);
LuaCreateNPCParse(ATK, uint32, 0);
LuaCreateNPCParse(STR, uint32, 75);
LuaCreateNPCParse(STA, uint32, 75);
LuaCreateNPCParse(DEX, uint32, 75);
LuaCreateNPCParse(AGI, uint32, 75);
LuaCreateNPCParse(INT, uint32, 75);
LuaCreateNPCParse(WIS, uint32, 75);
LuaCreateNPCParse(CHA, uint32, 75);
LuaCreateNPCParse(MR, int32, 25);
LuaCreateNPCParse(FR, int32, 25);
LuaCreateNPCParse(CR, int32, 25);
LuaCreateNPCParse(PR, int32, 25);
LuaCreateNPCParse(DR, int32, 25);
LuaCreateNPCParse(Corrup, int32, 25);
LuaCreateNPCParse(PhR, int32, 0);
LuaCreateNPCParse(haircolor, uint8, 0);
LuaCreateNPCParse(beardcolor, uint8, 0);
LuaCreateNPCParse(eyecolor1, uint8, 0);
LuaCreateNPCParse(eyecolor2, uint8, 0);
LuaCreateNPCParse(hairstyle, uint8, 0);
LuaCreateNPCParse(luclinface, uint8, 0);
LuaCreateNPCParse(beard, uint8, 0);
LuaCreateNPCParse(drakkin_heritage, uint32, 0);
LuaCreateNPCParse(drakkin_tattoo, uint32, 0);
LuaCreateNPCParse(drakkin_details, uint32, 0);
LuaCreateNPCParse(armor_tint[0], uint32, 0);
LuaCreateNPCParse(armor_tint[1], uint32, 0);
LuaCreateNPCParse(armor_tint[2], uint32, 0);
LuaCreateNPCParse(armor_tint[3], uint32, 0);
LuaCreateNPCParse(armor_tint[4], uint32, 0);
LuaCreateNPCParse(armor_tint[5], uint32, 0);
LuaCreateNPCParse(armor_tint[6], uint32, 0);
LuaCreateNPCParse(armor_tint[7], uint32, 0);
LuaCreateNPCParse(armor_tint[8], uint32, 0);
LuaCreateNPCParse(min_dmg, uint32, 2);
LuaCreateNPCParse(max_dmg, uint32, 4);
LuaCreateNPCParse(attack_count, int16, 0);
LuaCreateNPCParseString(special_abilities, 512, "");
LuaCreateNPCParse(d_melee_texture1, uint16, 0);
LuaCreateNPCParse(d_melee_texture2, uint16, 0);
LuaCreateNPCParseString(ammo_idfile, 30, "");
LuaCreateNPCParse(prim_melee_type, uint8, 0);
LuaCreateNPCParse(sec_melee_type, uint8, 0);
LuaCreateNPCParse(ranged_type, uint8, 0);
LuaCreateNPCParse(hp_regen, int32, 1);
LuaCreateNPCParse(mana_regen, int32, 1);
LuaCreateNPCParse(aggroradius, int32, 0);
LuaCreateNPCParse(assistradius, int32, 0);
LuaCreateNPCParse(see_invis, uint8, 0);
LuaCreateNPCParse(see_invis_undead, bool, false);
LuaCreateNPCParse(see_hide, bool, false);
LuaCreateNPCParse(see_improved_hide, bool, false);
LuaCreateNPCParse(qglobal, bool, false);
LuaCreateNPCParse(npc_aggro, bool, false);
LuaCreateNPCParse(spawn_limit, uint8, false);
LuaCreateNPCParse(mount_color, uint8, false);
LuaCreateNPCParse(attack_speed, float, 0);
LuaCreateNPCParse(attack_delay, uint8, 30);
LuaCreateNPCParse(accuracy_rating, int, 0);
LuaCreateNPCParse(avoidance_rating, int, 0);
LuaCreateNPCParse(findable, bool, false);
LuaCreateNPCParse(trackable, bool, false);
LuaCreateNPCParse(slow_mitigation, int16, 0);
LuaCreateNPCParse(maxlevel, uint8, 0);
LuaCreateNPCParse(scalerate, uint32, 0);
LuaCreateNPCParse(private_corpse, bool, false);
LuaCreateNPCParse(unique_spawn_by_name, bool, false);
LuaCreateNPCParse(underwater, bool, false);
LuaCreateNPCParse(emoteid, uint32, 0);
LuaCreateNPCParse(spellscale, float, 0);
LuaCreateNPCParse(healscale, float, 0);
LuaCreateNPCParse(no_target_hotkey, bool, false);
LuaCreateNPCParse(raid_target, bool, false);
LuaCreateNPCParse(probability, uint8, 0);
NPC* npc = new NPC(npc_type, nullptr, glm::vec4(x, y, z, heading), FlyMode3);
npc->GiveNPCTypeData(npc_type);
entity_list.AddNPC(npc);
}
luabind::scope lua_register_general() {
return luabind::namespace_("eq")
[
luabind::def("load_encounter", &load_encounter),
luabind::def("unload_encounter", &unload_encounter),
luabind::def("register_npc_event", &register_npc_event),
luabind::def("unregister_npc_event", &unregister_npc_event),
luabind::def("register_player_event", &register_player_event),
luabind::def("unregister_player_event", &unregister_player_event),
luabind::def("register_item_event", &register_item_event),
luabind::def("unregister_item_event", &unregister_item_event),
luabind::def("register_spell_event", &register_spell_event),
luabind::def("unregister_spell_event", &unregister_spell_event),
luabind::def("load_encounter_with_data", &load_encounter_with_data),
luabind::def("unload_encounter_with_data", &unload_encounter_with_data),
luabind::def("register_npc_event", (void(*)(std::string, int, int, luabind::adl::object))&register_npc_event),
luabind::def("register_npc_event", (void(*)(int, int, luabind::adl::object))&register_npc_event),
luabind::def("unregister_npc_event", (void(*)(std::string, int, int))&unregister_npc_event),
luabind::def("unregister_npc_event", (void(*)(int, int))&unregister_npc_event),
luabind::def("register_player_event", (void(*)(std::string, int, luabind::adl::object))&register_player_event),
luabind::def("register_player_event", (void(*)(int, luabind::adl::object))&register_player_event),
luabind::def("unregister_player_event", (void(*)(std::string, int))&unregister_player_event),
luabind::def("unregister_player_event", (void(*)(int))&unregister_player_event),
luabind::def("register_item_event", (void(*)(std::string, int, int, luabind::adl::object))&register_item_event),
luabind::def("register_item_event", (void(*)(int, int, luabind::adl::object))&register_item_event),
luabind::def("unregister_item_event", (void(*)(std::string, int, int))&unregister_item_event),
luabind::def("unregister_item_event", (void(*)(int, int))&unregister_item_event),
luabind::def("register_spell_event", (void(*)(std::string, int, int, luabind::adl::object func))&register_spell_event),
luabind::def("register_spell_event", (void(*)(int, int, luabind::adl::object func))&register_spell_event),
luabind::def("unregister_spell_event", (void(*)(std::string, int, int))&unregister_spell_event),
luabind::def("unregister_spell_event", (void(*)(int, int))&unregister_spell_event),
luabind::def("spawn2", (Lua_Mob(*)(int,int,int,double,double,double,double))&lua_spawn2),
luabind::def("unique_spawn", (Lua_Mob(*)(int,int,int,double,double,double))&lua_unique_spawn),
luabind::def("unique_spawn", (Lua_Mob(*)(int,int,int,double,double,double,double))&lua_unique_spawn),
@@ -1306,12 +1586,16 @@ luabind::scope lua_register_general() {
luabind::def("get_initiator", &lua_get_initiator),
luabind::def("get_owner", &lua_get_owner),
luabind::def("get_quest_item", &lua_get_quest_item),
luabind::def("get_encounter", &lua_get_encounter),
luabind::def("map_opcodes", &lua_map_opcodes),
luabind::def("clear_opcode", &lua_clear_opcode),
luabind::def("enable_recipe", &lua_enable_recipe),
luabind::def("disable_recipe", &lua_disable_recipe),
luabind::def("clear_npctype_cache", &lua_clear_npctype_cache),
luabind::def("clock", &lua_clock)
luabind::def("clock", &lua_clock),
luabind::def("create_npc", &lua_create_npc),
luabind::def("debug", (void(*)(std::string))&lua_debug),
luabind::def("debug", (void(*)(std::string, int))&lua_debug)
];
}
@@ -1341,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)),
@@ -1487,13 +1772,14 @@ luabind::scope lua_register_client_version() {
return luabind::class_<ClientVersions>("ClientVersion")
.enum_("constants")
[
luabind::value("Unknown", static_cast<int>(EQClientUnknown)),
luabind::value("62", static_cast<int>(EQClient62)),
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))
];
}
+8 -8
View File
@@ -12,42 +12,42 @@
Lua_Mob Lua_HateEntry::GetEnt() {
Lua_Safe_Call_Class(Lua_Mob);
return Lua_Mob(self->ent);
return Lua_Mob(self->entity_on_hatelist);
}
void Lua_HateEntry::SetEnt(Lua_Mob e) {
Lua_Safe_Call_Void();
self->ent = e;
self->entity_on_hatelist = e;
}
int Lua_HateEntry::GetDamage() {
Lua_Safe_Call_Int();
return self->damage;
return self->hatelist_damage;
}
void Lua_HateEntry::SetDamage(int value) {
Lua_Safe_Call_Void();
self->damage = value;
self->hatelist_damage = value;
}
int Lua_HateEntry::GetHate() {
Lua_Safe_Call_Int();
return self->hate;
return self->stored_hate_amount;
}
void Lua_HateEntry::SetHate(int value) {
Lua_Safe_Call_Void();
self->hate = value;
self->stored_hate_amount = value;
}
int Lua_HateEntry::GetFrenzy() {
Lua_Safe_Call_Int();
return self->bFrenzy;
return self->is_entity_frenzy;
}
void Lua_HateEntry::SetFrenzy(bool value) {
Lua_Safe_Call_Void();
self->bFrenzy = value;
self->is_entity_frenzy = value;
}
luabind::scope lua_register_hate_entry() {
+4 -4
View File
@@ -5,17 +5,17 @@
#include "lua_ptr.h"
class Lua_Mob;
struct tHateEntry;
struct struct_HateList;
luabind::scope lua_register_hate_entry();
luabind::scope lua_register_hate_list();
class Lua_HateEntry : public Lua_Ptr<tHateEntry>
class Lua_HateEntry : public Lua_Ptr<struct_HateList>
{
typedef tHateEntry NativeType;
typedef struct_HateList NativeType;
public:
Lua_HateEntry() : Lua_Ptr(nullptr) { }
Lua_HateEntry(tHateEntry *d) : Lua_Ptr(d) { }
Lua_HateEntry(struct_HateList *d) : Lua_Ptr(d) { }
virtual ~Lua_HateEntry() { }
Lua_Mob GetEnt();
+2 -2
View File
@@ -166,12 +166,12 @@ uint32 Lua_ItemInst::GetColor() {
bool Lua_ItemInst::IsInstNoDrop() {
Lua_Safe_Call_Bool();
return self->IsInstNoDrop();
return self->IsAttuned();
}
void Lua_ItemInst::SetInstNoDrop(bool flag) {
Lua_Safe_Call_Void();
return self->SetInstNoDrop(flag);
return self->SetAttuned(flag);
}
std::string Lua_ItemInst::GetCustomDataString() {
+25 -19
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()) {
@@ -895,17 +900,17 @@ void Lua_Mob::AddToHateList(Lua_Mob other, int hate, int damage, bool yell_for_h
void Lua_Mob::SetHate(Lua_Mob other) {
Lua_Safe_Call_Void();
self->SetHate(other);
self->SetHateAmountOnEnt(other);
}
void Lua_Mob::SetHate(Lua_Mob other, int hate) {
Lua_Safe_Call_Void();
self->SetHate(other, hate);
self->SetHateAmountOnEnt(other, hate);
}
void Lua_Mob::SetHate(Lua_Mob other, int hate, int damage) {
Lua_Safe_Call_Void();
self->SetHate(other, hate, damage);
self->SetHateAmountOnEnt(other, hate, damage);
}
void Lua_Mob::HalveAggro(Lua_Mob other) {
@@ -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) {
+52 -20
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",
@@ -126,6 +127,7 @@ struct lua_registered_event {
};
std::map<std::string, std::list<lua_registered_event>> lua_encounter_events_registered;
std::map<std::string, bool> lua_encounters_loaded;
LuaParser::LuaParser() {
for(int i = 0; i < _LargestEventID; ++i) {
@@ -163,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;
@@ -234,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);
}
@@ -424,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);
}
@@ -498,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);
}
@@ -601,7 +604,13 @@ int LuaParser::_EventEncounter(std::string package_name, QuestEventID evt, std::
lua_pushstring(L, encounter_name.c_str());
lua_setfield(L, -2, "name");
quest_manager.StartQuest(nullptr, nullptr, nullptr);
if(extra_pointers) {
std::string *str = EQEmu::any_cast<std::string*>(extra_pointers->at(0));
lua_pushstring(L, str->c_str());
lua_setfield(L, -2, "data");
}
quest_manager.StartQuest(nullptr, nullptr, nullptr, encounter_name);
if(lua_pcall(L, 1, 1, 0)) {
std::string error = lua_tostring(L, -1);
AddError(error);
@@ -639,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);
@@ -681,20 +690,23 @@ 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);
}
bool LuaParser::ItemHasQuestSub(ItemInst *itm, QuestEventID evt) {
if (itm == nullptr) {
return false;
}
evt = ConvertLuaEvent(evt);
if(evt >= _LargestEventID) {
return false;
}
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);
@@ -713,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);
}
@@ -731,14 +743,16 @@ void LuaParser::LoadGlobalPlayerScript(std::string filename) {
}
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);
}
@@ -770,6 +784,7 @@ void LuaParser::ReloadQuests() {
loaded_.clear();
errors_.clear();
lua_encounter_events_registered.clear();
lua_encounters_loaded.clear();
if(L) {
lua_close(L);
@@ -839,7 +854,7 @@ void LuaParser::ReloadQuests() {
if(f) {
fclose(f);
if(luaL_dofile(L, "quests/global/script_init.lua")) {
if(luaL_dofile(L, path.c_str())) {
std::string error = lua_tostring(L, -1);
AddError(error);
}
@@ -849,7 +864,9 @@ void LuaParser::ReloadQuests() {
if(zone) {
std::string zone_script = "quests/";
zone_script += zone->GetShortName();
zone_script += "/script_init.lua";
zone_script += "/script_init_v";
zone_script += std::to_string(zone->GetInstanceVersion());
zone_script += ".lua";
f = fopen(zone_script.c_str(), "r");
if(f) {
fclose(f);
@@ -858,6 +875,21 @@ void LuaParser::ReloadQuests() {
std::string error = lua_tostring(L, -1);
AddError(error);
}
return;
}
zone_script = "quests/";
zone_script += zone->GetShortName();
zone_script += "/script_init.lua";
f = fopen(zone_script.c_str(), "r");
if(f) {
fclose(f);
if(luaL_dofile(L, zone_script.c_str())) {
std::string error = lua_tostring(L, -1);
AddError(error);
}
}
}
}
@@ -981,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()) {
@@ -1055,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();
@@ -1099,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,
+47 -46
View File
@@ -1,15 +1,15 @@
#include "../common/debug.h"
#include "../common/global_define.h"
#include "../common/misc_functions.h"
#include "map.h"
#include "raycast_mesh.h"
#include "zone.h"
#include <stdint.h>
#include <algorithm>
#include <locale>
#include <vector>
#include <map>
#include <memory>
#include <tuple>
#include <map>
#include <vector>
#include <zlib.h>
uint32 InflateData(const char* buffer, uint32 len, char* out_buffer, uint32 out_len_max) {
@@ -58,20 +58,21 @@ Map::Map() {
Map::~Map() {
if(imp) {
imp->rm->release();
safe_delete(imp);
}
}
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;
@@ -92,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;
@@ -138,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;
@@ -183,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;
@@ -249,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;
}
@@ -308,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;
};
@@ -375,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) {
@@ -392,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);
}
@@ -412,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;
@@ -433,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);
@@ -455,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) {
@@ -486,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) {
@@ -595,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];
@@ -617,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);
@@ -723,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);
@@ -789,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;
}
@@ -800,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;
}
@@ -811,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;
}
@@ -822,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;
}
@@ -858,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);
@@ -877,14 +878,14 @@ 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 -27
View File
@@ -22,47 +22,30 @@
#ifndef ZONE_MAP_H
#define ZONE_MAP_H
#include "position.h"
#include <stdio.h>
#include <string>
#define BEST_Z_INVALID -99999
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
+2130 -1843
View File
File diff suppressed because it is too large Load Diff
+180 -166
View File
@@ -1,15 +1,29 @@
#ifndef MERC_H
#define MERC_H
#include "mob.h"
#include "zonedb.h"
#include "npc.h"
class Client;
class Corpse;
class Group;
class Mob;
class Raid;
struct Item_Struct;
struct MercTemplate;
struct NPCType;
struct NewSpawn_Struct;
#define MAXMERCS 1
#define MERC_DEBUG 0
#define TANK 1
#define HEALER 2
#define MELEEDPS 9
#define CASTERDPS 12
#define TANK 1
#define HEALER 2
#define MELEEDPS 9
#define CASTERDPS 12
#define NO_MERC_ID 0
#define MERC_STATE_NORMAL 5
#define MERC_STATE_SUSPENDED 1
#define NOT_SUSPENDED_TIME 0
const int MercAISpellRange = 100; // TODO: Write a method that calcs what the merc's spell range is based on spell, equipment, AA, whatever and replace this
enum MercStanceType {
@@ -25,19 +39,19 @@ enum MercStanceType {
};
struct MercSpell {
uint16 spellid; // <= 0 = no spell
uint32 type; // 0 = never, must be one (and only one) of the defined values
int16 stance; // 0 = all, + = only this stance, - = all except this stance
int16 slot;
uint16 proc_chance;
uint32 time_cancast; // when we can cast this spell next
uint16 spellid; // <= 0 = no spell
uint32 type; // 0 = never, must be one (and only one) of the defined values
int16 stance; // 0 = all, + = only this stance, - = all except this stance
int16 slot;
uint16 proc_chance;
uint32 time_cancast; // when we can cast this spell next
};
struct MercTimer {
uint16 timerid; // EndurTimerIndex
uint8 timertype; // 1 = spell, 2 = disc
uint16 spellid; // <= 0 = no spell
uint32 time_cancast; // when we can cast this spell next
uint16 timerid; // EndurTimerIndex
uint8 timertype; // 1 = spell, 2 = disc
uint16 spellid; // <= 0 = no spell
uint32 time_cancast; // when we can cast this spell next
};
class Merc : public NPC {
@@ -48,8 +62,8 @@ public:
//abstract virtual function implementations requird by base abstract class
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill);
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false);
virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = false,
bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr);
virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = false,
bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr);
virtual bool HasRaid() { return false; }
virtual bool HasGroup() { return (GetGroup() ? true : false); }
virtual Raid* GetRaid() { return 0; }
@@ -77,8 +91,6 @@ public:
Corpse* GetGroupMemberCorpse();
// Merc Spell Casting Methods
virtual int32 GetActSpellDamage(uint16 spell_id, int32 value, Mob* target = nullptr);
virtual int32 GetActSpellHealing(uint16 spell_id, int32 value, Mob* target = nullptr);
virtual int32 GetActSpellCasttime(uint16 spell_id, int32 casttime);
virtual int32 GetActSpellCost(uint16 spell_id, int32 cost);
int8 GetChanceToCastBySpellType(int16 spellType);
@@ -125,22 +137,23 @@ 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 UpdateMercAppearance(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);
bool Dismiss();
bool Suspend();
bool Unsuspend(bool setMaxStats);
bool MercJoinClientGroup();
void Zone();
virtual void Depop();
virtual bool Save();
bool GetDepop() { return p_depop; }
bool IsDead() { return GetHP() < 0;};
bool IsMedding() {return _medding; };
bool IsSuspended() {return _suspended; };
bool IsMedding() { return _medding; };
bool IsSuspended() { return _suspended; };
static uint32 CalcPurchaseCost( uint32 templateID , uint8 level, uint8 currency_type = 0);
static uint32 CalcUpkeepCost( uint32 templateID , uint8 level, uint8 currency_type = 0);
@@ -164,75 +177,76 @@ public:
inline const uint8 GetClientVersion() const { return _OwnerClientVersion; }
virtual void SetTarget(Mob* mob);
bool HasSkill(SkillUseTypes skill_id) const;
bool CanHaveSkill(SkillUseTypes skill_id) const;
uint16 MaxSkill(SkillUseTypes skillid, uint16 class_, uint16 level) const;
inline uint16 MaxSkill(SkillUseTypes skillid) const { return MaxSkill(skillid, GetClass(), GetLevel()); }
bool HasSkill(SkillUseTypes skill_id) const;
bool CanHaveSkill(SkillUseTypes skill_id) const;
uint16 MaxSkill(SkillUseTypes skillid, uint16 class_, uint16 level) const;
inline uint16 MaxSkill(SkillUseTypes skillid) const { return MaxSkill(skillid, GetClass(), GetLevel()); }
virtual void DoClassAttacks(Mob *target);
void CheckHateList();
bool CheckTaunt();
bool CheckAETaunt();
bool CheckConfidence();
bool TryHide();
void CheckHateList();
bool CheckTaunt();
bool CheckAETaunt();
bool CheckConfidence();
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 int16 GetAC() const { return AC; }
inline virtual int16 GetATK() const { return ATK; }
inline virtual int16 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; }
int GetRawACNoShield(int &shield_ac) const;
int32 GetEndurance() const {return cur_end;} //This gets our current endurance
inline virtual int32 GetAC() const { return AC; }
inline virtual int32 GetATK() const { return ATK; }
inline virtual int32 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; }
int32 GetRawACNoShield(int &shield_ac) const;
inline virtual int16 GetSTR() const { return STR; }
inline virtual int16 GetSTA() const { return STA; }
inline virtual int16 GetDEX() const { return DEX; }
inline virtual int16 GetAGI() const { return AGI; }
inline virtual int16 GetINT() const { return INT; }
inline virtual int16 GetWIS() const { return WIS; }
inline virtual int16 GetCHA() const { return CHA; }
inline virtual int16 GetMR() const { return MR; }
inline virtual int16 GetFR() const { return FR; }
inline virtual int16 GetDR() const { return DR; }
inline virtual int16 GetPR() const { return PR; }
inline virtual int16 GetCR() const { return CR; }
inline virtual int16 GetCorrup() const { return Corrup; }
inline virtual int32 GetSTR() const { return STR; }
inline virtual int32 GetSTA() const { return STA; }
inline virtual int32 GetDEX() const { return DEX; }
inline virtual int32 GetAGI() const { return AGI; }
inline virtual int32 GetINT() const { return INT; }
inline virtual int32 GetWIS() const { return WIS; }
inline virtual int32 GetCHA() const { return CHA; }
inline virtual int32 GetMR() const { return MR; }
inline virtual int32 GetFR() const { return FR; }
inline virtual int32 GetDR() const { return DR; }
inline virtual int32 GetPR() const { return PR; }
inline virtual int32 GetCR() const { return CR; }
inline virtual int32 GetCorrup() const { return Corrup; }
inline virtual int16 GetHeroicSTR() const { return itembonuses.HeroicSTR; }
inline virtual int16 GetHeroicSTA() const { return itembonuses.HeroicSTA; }
inline virtual int16 GetHeroicDEX() const { return itembonuses.HeroicDEX; }
inline virtual int16 GetHeroicAGI() const { return itembonuses.HeroicAGI; }
inline virtual int16 GetHeroicINT() const { return itembonuses.HeroicINT; }
inline virtual int16 GetHeroicWIS() const { return itembonuses.HeroicWIS; }
inline virtual int16 GetHeroicCHA() const { return itembonuses.HeroicCHA; }
inline virtual int16 GetHeroicMR() const { return itembonuses.HeroicMR; }
inline virtual int16 GetHeroicFR() const { return itembonuses.HeroicFR; }
inline virtual int16 GetHeroicDR() const { return itembonuses.HeroicDR; }
inline virtual int16 GetHeroicPR() const { return itembonuses.HeroicPR; }
inline virtual int16 GetHeroicCR() const { return itembonuses.HeroicCR; }
inline virtual int16 GetHeroicCorrup() const { return itembonuses.HeroicCorrup; }
inline virtual int32 GetHeroicSTR() const { return itembonuses.HeroicSTR; }
inline virtual int32 GetHeroicSTA() const { return itembonuses.HeroicSTA; }
inline virtual int32 GetHeroicDEX() const { return itembonuses.HeroicDEX; }
inline virtual int32 GetHeroicAGI() const { return itembonuses.HeroicAGI; }
inline virtual int32 GetHeroicINT() const { return itembonuses.HeroicINT; }
inline virtual int32 GetHeroicWIS() const { return itembonuses.HeroicWIS; }
inline virtual int32 GetHeroicCHA() const { return itembonuses.HeroicCHA; }
inline virtual int32 GetHeroicMR() const { return itembonuses.HeroicMR; }
inline virtual int32 GetHeroicFR() const { return itembonuses.HeroicFR; }
inline virtual int32 GetHeroicDR() const { return itembonuses.HeroicDR; }
inline virtual int32 GetHeroicPR() const { return itembonuses.HeroicPR; }
inline virtual int32 GetHeroicCR() const { return itembonuses.HeroicCR; }
inline virtual int32 GetHeroicCorrup() const { return itembonuses.HeroicCorrup; }
// Mod2
inline virtual int16 GetShielding() const { return itembonuses.MeleeMitigation; }
inline virtual int16 GetSpellShield() const { return itembonuses.SpellShield; }
inline virtual int16 GetDoTShield() const { return itembonuses.DoTShielding; }
inline virtual int16 GetStunResist() const { return itembonuses.StunResist; }
inline virtual int16 GetStrikeThrough() const { return itembonuses.StrikeThrough; }
inline virtual int16 GetAvoidance() const { return itembonuses.AvoidMeleeChance; }
inline virtual int16 GetAccuracy() const { return itembonuses.HitChance; }
inline virtual int16 GetCombatEffects() const { return itembonuses.ProcChance; }
inline virtual int16 GetDS() const { return itembonuses.DamageShield; }
inline virtual int32 GetShielding() const { return itembonuses.MeleeMitigation; }
inline virtual int32 GetSpellShield() const { return itembonuses.SpellShield; }
inline virtual int32 GetDoTShield() const { return itembonuses.DoTShielding; }
inline virtual int32 GetStunResist() const { return itembonuses.StunResist; }
inline virtual int32 GetStrikeThrough() const { return itembonuses.StrikeThrough; }
inline virtual int32 GetAvoidance() const { return itembonuses.AvoidMeleeChance; }
inline virtual int32 GetAccuracy() const { return itembonuses.HitChance; }
inline virtual int32 GetCombatEffects() const { return itembonuses.ProcChance; }
inline virtual int32 GetDS() const { return itembonuses.DamageShield; }
// Mod3
inline virtual int16 GetHealAmt() const { return itembonuses.HealAmt; }
inline virtual int16 GetSpellDmg() const { return itembonuses.SpellDmg; }
inline virtual int16 GetClair() const { return itembonuses.Clairvoyance; }
inline virtual int16 GetDSMit() const { return itembonuses.DSMitigation; }
inline virtual int32 GetHealAmt() const { return itembonuses.HealAmt; }
inline virtual int32 GetSpellDmg() const { return itembonuses.SpellDmg; }
inline virtual int32 GetClair() const { return itembonuses.Clairvoyance; }
inline virtual int32 GetDSMit() const { return itembonuses.DSMitigation; }
inline virtual int16 GetSingMod() const { return itembonuses.singingMod; }
inline virtual int16 GetBrassMod() const { return itembonuses.brassMod; }
inline virtual int16 GetPercMod() const { return itembonuses.percussionMod; }
inline virtual int16 GetStringMod() const { return itembonuses.stringedMod; }
inline virtual int16 GetWindMod() const { return itembonuses.windMod; }
inline virtual int32 GetSingMod() const { return itembonuses.singingMod; }
inline virtual int32 GetBrassMod() const { return itembonuses.brassMod; }
inline virtual int32 GetPercMod() const { return itembonuses.percussionMod; }
inline virtual int32 GetStringMod() const { return itembonuses.stringedMod; }
inline virtual int32 GetWindMod() const { return itembonuses.windMod; }
inline virtual int16 GetDelayDeath() const { return aabonuses.DelayDeath + spellbonuses.DelayDeath + itembonuses.DelayDeath + 11; }
inline virtual int32 GetDelayDeath() const { return aabonuses.DelayDeath + spellbonuses.DelayDeath + itembonuses.DelayDeath + 11; }
// "SET" Class Methods
void SetMercData (uint32 templateID );
@@ -267,67 +281,66 @@ protected:
void AddItemBonuses(const Item_Struct *item, StatBonuses* newbon);
int CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat);
int16 GetFocusEffect(focusType type, uint16 spell_id);
int16 GetFocusEffect(focusType type, uint16 spell_id);
std::vector<MercSpell> merc_spells;
std::map<uint32,MercTimer> timers;
uint16 skills[HIGHEST_SKILL+1];
uint32 equipment[EmuConstants::EQUIPMENT_SIZE]; //this is an array of item IDs
uint16 d_meele_texture1; //this is an item Material value
uint16 d_meele_texture2; //this is an item Material value (offhand)
uint8 prim_melee_type; //Sets the Primary Weapon attack message and animation
uint8 sec_melee_type; //Sets the Secondary Weapon attack message and animation
uint16 skills[HIGHEST_SKILL+1];
uint32 equipment[EmuConstants::EQUIPMENT_SIZE]; //this is an array of item IDs
uint16 d_melee_texture1; //this is an item Material value
uint16 d_melee_texture2; //this is an item Material value (offhand)
uint8 prim_melee_type; //Sets the Primary Weapon attack message and animation
uint8 sec_melee_type; //Sets the Secondary Weapon attack message and animation
private:
int16 CalcAC();
int16 GetACMit();
int16 GetACAvoid();
int16 acmod();
int16 CalcATK();
//int CalcHaste();
int32 CalcAC();
int32 GetACMit();
int32 GetACAvoid();
int32 acmod();
int32 CalcATK();
//int CalcHaste();
int16 CalcSTR();
int16 CalcSTA();
int16 CalcDEX();
int16 CalcAGI();
int16 CalcINT();
int16 CalcWIS();
int16 CalcCHA();
int32 CalcSTR();
int32 CalcSTA();
int32 CalcDEX();
int32 CalcAGI();
int32 CalcINT();
int32 CalcWIS();
int32 CalcCHA();
int16 CalcMR();
int16 CalcFR();
int16 CalcDR();
int16 CalcPR();
int16 CalcCR();
int16 CalcCorrup();
int32 CalcMaxHP();
int32 CalcBaseHP();
int32 GetClassHPFactor();
int32 CalcHPRegen();
int32 CalcHPRegenCap();
int32 CalcMaxMana();
int32 CalcBaseMana();
int32 CalcManaRegen();
int32 CalcBaseManaRegen();
int32 CalcManaRegenCap();
void CalcMaxEndurance(); //This calculates the maximum endurance we can have
int32 CalcBaseEndurance(); //Calculates Base End
int32 GetMaxEndurance() const {return max_end;} //This gets our endurance from the last CalcMaxEndurance() call
int32 CalcEnduranceRegen(); //Calculates endurance regen used in DoEnduranceRegen()
int32 CalcEnduranceRegenCap();
void SetEndurance(int32 newEnd); //This sets the current endurance to the new value
void DoEnduranceUpkeep(); //does the endurance upkeep
void CalcRestState();
int32 CalcMR();
int32 CalcFR();
int32 CalcDR();
int32 CalcPR();
int32 CalcCR();
int32 CalcCorrup();
int32 CalcMaxHP();
int32 CalcBaseHP();
int32 GetClassHPFactor();
int32 CalcHPRegen();
int32 CalcHPRegenCap();
int32 CalcMaxMana();
int32 CalcBaseMana();
int32 CalcManaRegen();
int32 CalcBaseManaRegen();
int32 CalcManaRegenCap();
void CalcMaxEndurance(); //This calculates the maximum endurance we can have
int32 CalcBaseEndurance(); //Calculates Base End
int32 GetMaxEndurance() const {return max_end;} //This gets our endurance from the last CalcMaxEndurance() call
int32 CalcEnduranceRegen(); //Calculates endurance regen used in DoEnduranceRegen()
int32 CalcEnduranceRegenCap();
void SetEndurance(int32 newEnd); //This sets the current endurance to the new value
void DoEnduranceUpkeep(); //does the endurance upkeep
void CalcRestState();
int GroupLeadershipAAHealthEnhancement();
int GroupLeadershipAAManaEnhancement();
int GroupLeadershipAAHealthRegeneration();
int GroupLeadershipAAOffenseEnhancement();
int GroupLeadershipAAHealthEnhancement();
int GroupLeadershipAAManaEnhancement();
int GroupLeadershipAAHealthRegeneration();
int GroupLeadershipAAOffenseEnhancement();
void GetMercSize();
void GenerateAppearance();
float GetDefaultSize();
bool LoadMercSpells();
bool CheckStance(int16 stance);
@@ -335,23 +348,24 @@ private:
// Private "base stats" Members
int32 base_mana;
int _baseAC;
uint16 _baseSTR;
uint16 _baseSTA;
uint16 _baseDEX;
uint16 _baseAGI;
uint16 _baseINT;
uint16 _baseWIS;
uint16 _baseCHA;
uint16 _baseATK;
uint16 _baseRace; // Necessary to preserve the race otherwise mercs get their race updated in the db when they get an illusion.
uint8 _baseGender; // Merc gender. Necessary to preserve the original value otherwise it can be changed by illusions.
uint16 _baseMR;
uint16 _baseCR;
uint16 _baseDR;
uint16 _baseFR;
uint16 _basePR;
uint16 _baseCorrup;
int32 base_end;
int32 _baseAC;
uint32 _baseSTR;
uint32 _baseSTA;
uint32 _baseDEX;
uint32 _baseAGI;
uint32 _baseINT;
uint32 _baseWIS;
uint32 _baseCHA;
uint32 _baseATK;
uint32 _baseRace; // Necessary to preserve the race otherwise mercs get their race updated in the db when they get an illusion.
uint8 _baseGender; // Merc gender. Necessary to preserve the original value otherwise it can be changed by illusions.
uint32 _baseMR;
uint32 _baseCR;
uint32 _baseDR;
uint32 _baseFR;
uint32 _basePR;
uint32 _baseCorrup;
uint32 RestRegenHP;
uint32 RestRegenMana;
uint32 RestRegenEndurance;
@@ -368,19 +382,19 @@ private:
uint32 _currentStance;
Inventory m_inv;
int32 max_end;
int32 cur_end;
bool _medding;
bool _suspended;
bool p_depop;
bool _check_confidence;
bool _lost_confidence;
int _hatedCount;
uint32 owner_char_id;
Timer endupkeep_timer;
Timer rest_timer;
Timer confidence_timer;
Timer check_target_timer;
int32 max_end;
int32 cur_end;
bool _medding;
bool _suspended;
bool p_depop;
bool _check_confidence;
bool _lost_confidence;
int _hatedCount;
uint32 owner_char_id;
Timer endupkeep_timer;
Timer rest_timer;
Timer confidence_timer;
Timer check_target_timer;
};
#endif // MERC_H
#endif // MERC_H
+808 -539
View File
File diff suppressed because it is too large Load Diff
+207 -179
View File
@@ -18,21 +18,30 @@
#ifndef MOB_H
#define MOB_H
#include "../common/features.h"
#include "common.h"
#include "entity.h"
#include "hate_list.h"
#include "pathing.h"
#include "position.h"
#include <set>
#include <vector>
#include <string>
#include <memory>
char* strn0cpy(char* dest, const char* source, uint32 size);
#define MAX_SPECIAL_ATTACK_PARAMS 8
class EGNode;
class MobFearState;
class Client;
class EQApplicationPacket;
class Group;
class ItemInst;
class NPC;
class Raid;
struct Item_Struct;
struct NewSpawn_Struct;
struct PlayerPositionUpdateServer_Struct;
class Mob : public Entity {
public:
enum CLIENT_CONN_STATUS { CLIENT_CONNECTING, CLIENT_CONNECTED, CLIENT_LINKDEAD,
@@ -70,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,
@@ -117,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
@@ -164,7 +170,7 @@ public:
virtual void SendTextureWC(uint8 slot, uint16 texture, uint32 hero_forge_model = 0, uint32 elite_material = 0,
uint32 unknown06 = 0, uint32 unknown18 = 0);
virtual void SetSlotTint(uint8 material_slot, uint8 red_tint, uint8 green_tint, uint8 blue_tint);
virtual void WearChange(uint8 material_slot, uint16 texture, uint32 color);
virtual void WearChange(uint8 material_slot, uint16 texture, uint32 color, uint32 hero_forge_model = 0);
void DoAnim(const int animnum, int type=0, bool ackreq = true, eqFilterType filter = FilterNone);
void ProjectileAnimation(Mob* to, int item_id, bool IsArrow = false, float speed = 0,
float angle = 0, float tilt = 0, float arc = 0, const char *IDFile = nullptr, SkillUseTypes skillInUse = SkillArchery);
@@ -176,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);
@@ -191,11 +197,12 @@ public:
bool item_bonus = false, uint32 ticsremaining = 0, int buffslot = -1,
bool IsAISpellEffect = false, uint16 effect_id = 0, int32 se_base = 0, int32 se_limit = 0, int32 se_max = 0);
void NegateSpellsBonuses(uint16 spell_id);
virtual float GetActSpellRange(uint16 spell_id, float range, bool IsBard = false) { return range;}
virtual int32 GetActSpellDamage(uint16 spell_id, int32 value, Mob* target = nullptr) { return value; }
virtual int32 GetActSpellHealing(uint16 spell_id, int32 value, Mob* target = nullptr) { return value; }
virtual float GetActSpellRange(uint16 spell_id, float range, bool IsBard = false);
virtual int32 GetActSpellDamage(uint16 spell_id, int32 value, Mob* target = nullptr);
virtual int32 GetActDoTDamage(uint16 spell_id, int32 value, Mob* target);
virtual int32 GetActSpellHealing(uint16 spell_id, int32 value, Mob* target = nullptr);
virtual int32 GetActSpellCost(uint16 spell_id, int32 cost){ return cost;}
virtual int32 GetActSpellDuration(uint16 spell_id, int32 duration){ return duration;}
virtual int32 GetActSpellDuration(uint16 spell_id, int32 duration);
virtual int32 GetActSpellCasttime(uint16 spell_id, int32 casttime);
float ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use_resist_override = false,
int resist_override = 0, bool CharismaCheck = false, bool CharmTick = false, bool IsRoot = false);
@@ -230,12 +237,13 @@ public:
uint16 CastingSpellID() const { return casting_spell_id; }
bool DoCastingChecks();
bool TryDispel(uint8 caster_level, uint8 buff_level, int level_modifier);
void SpellProjectileEffect();
bool TrySpellProjectile(Mob* spell_target, uint16 spell_id);
bool TrySpellProjectile(Mob* spell_target, uint16 spell_id, float speed = 1.5f);
void ResourceTap(int32 damage, uint16 spell_id);
void TryTriggerThreshHold(int32 damage, int effect_id, Mob* attacker);
bool CheckSpellCategory(uint16 spell_id, int category_id, int effect_id);
void CalcDestFromHeading(float heading, float distance, float MaxZDiff, float StartX, float StartY, float &dX, float &dY, float &dZ);
void BeamDirectional(uint16 spell_id, int16 resist_adjust);
void ConeDirectional(uint16 spell_id, int16 resist_adjust);
//Buff
void BuffProcess();
@@ -273,7 +281,7 @@ public:
int16 GetBuffSlotFromType(uint16 type);
uint16 GetSpellIDFromSlot(uint8 slot);
int CountDispellableBuffs();
void CheckNumHitsRemaining(uint8 type, uint32 buff_slot=0, 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; }
@@ -287,6 +295,12 @@ public:
inline virtual uint32 GetNimbusEffect2() const { return nimbus_effect2; }
inline virtual uint32 GetNimbusEffect3() const { return nimbus_effect3; }
void RemoveNimbusEffect(int effectid);
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; }
//Basic Stats/Inventory
virtual void SetLevel(uint8 in_level, bool command = false) { level = in_level; }
@@ -298,8 +312,10 @@ public:
virtual uint16 GetSkill(SkillUseTypes skill_num) const { return 0; }
virtual uint32 GetEquipment(uint8 material_slot) const { return(0); }
virtual int32 GetEquipmentMaterial(uint8 material_slot) const;
virtual int32 GetHerosForgeModel(uint8 material_slot) const;
virtual uint32 GetEquipmentColor(uint8 material_slot) const;
virtual uint32 IsEliteMaterialItem(uint8 material_slot) const;
bool CanClassEquipItem(uint32 item_id);
bool AffectedBySpellExcludingSlot(int slot, int effect);
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) = 0;
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill,
@@ -340,39 +356,39 @@ public:
inline Mob* GetTarget() const { return target; }
virtual void SetTarget(Mob* mob);
virtual inline float GetHPRatio() const { return max_hp == 0 ? 0 : ((float)cur_hp/max_hp*100); }
inline virtual int16 GetAC() const { return AC + itembonuses.AC + spellbonuses.AC; }
inline virtual int16 GetATK() const { return ATK + itembonuses.ATK + spellbonuses.ATK; }
inline virtual int16 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; }
inline virtual int16 GetSTR() const { return STR + itembonuses.STR + spellbonuses.STR; }
inline virtual int16 GetSTA() const { return STA + itembonuses.STA + spellbonuses.STA; }
inline virtual int16 GetDEX() const { return DEX + itembonuses.DEX + spellbonuses.DEX; }
inline virtual int16 GetAGI() const { return AGI + itembonuses.AGI + spellbonuses.AGI; }
inline virtual int16 GetINT() const { return INT + itembonuses.INT + spellbonuses.INT; }
inline virtual int16 GetWIS() const { return WIS + itembonuses.WIS + spellbonuses.WIS; }
inline virtual int16 GetCHA() const { return CHA + itembonuses.CHA + spellbonuses.CHA; }
inline virtual int16 GetMR() const { return MR + itembonuses.MR + spellbonuses.MR; }
inline virtual int16 GetFR() const { return FR + itembonuses.FR + spellbonuses.FR; }
inline virtual int16 GetDR() const { return DR + itembonuses.DR + spellbonuses.DR; }
inline virtual int16 GetPR() const { return PR + itembonuses.PR + spellbonuses.PR; }
inline virtual int16 GetCR() const { return CR + itembonuses.CR + spellbonuses.CR; }
inline virtual int16 GetCorrup() const { return Corrup + itembonuses.Corrup + spellbonuses.Corrup; }
inline virtual int16 GetPhR() const { return PhR; }
inline virtual int32 GetAC() const { return AC + itembonuses.AC + spellbonuses.AC; }
inline virtual int32 GetATK() const { return ATK + itembonuses.ATK + spellbonuses.ATK; }
inline virtual int32 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; }
inline virtual int32 GetSTR() const { return STR + itembonuses.STR + spellbonuses.STR; }
inline virtual int32 GetSTA() const { return STA + itembonuses.STA + spellbonuses.STA; }
inline virtual int32 GetDEX() const { return DEX + itembonuses.DEX + spellbonuses.DEX; }
inline virtual int32 GetAGI() const { return AGI + itembonuses.AGI + spellbonuses.AGI; }
inline virtual int32 GetINT() const { return INT + itembonuses.INT + spellbonuses.INT; }
inline virtual int32 GetWIS() const { return WIS + itembonuses.WIS + spellbonuses.WIS; }
inline virtual int32 GetCHA() const { return CHA + itembonuses.CHA + spellbonuses.CHA; }
inline virtual int32 GetMR() const { return MR + itembonuses.MR + spellbonuses.MR; }
inline virtual int32 GetFR() const { return FR + itembonuses.FR + spellbonuses.FR; }
inline virtual int32 GetDR() const { return DR + itembonuses.DR + spellbonuses.DR; }
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; } // PhR bonuses not implemented yet
inline StatBonuses GetItemBonuses() const { return itembonuses; }
inline StatBonuses GetSpellBonuses() const { return spellbonuses; }
inline StatBonuses GetAABonuses() const { return aabonuses; }
inline virtual int16 GetMaxSTR() const { return GetSTR(); }
inline virtual int16 GetMaxSTA() const { return GetSTA(); }
inline virtual int16 GetMaxDEX() const { return GetDEX(); }
inline virtual int16 GetMaxAGI() const { return GetAGI(); }
inline virtual int16 GetMaxINT() const { return GetINT(); }
inline virtual int16 GetMaxWIS() const { return GetWIS(); }
inline virtual int16 GetMaxCHA() const { return GetCHA(); }
inline virtual int16 GetMaxMR() const { return 255; }
inline virtual int16 GetMaxPR() const { return 255; }
inline virtual int16 GetMaxDR() const { return 255; }
inline virtual int16 GetMaxCR() const { return 255; }
inline virtual int16 GetMaxFR() const { return 255; }
inline virtual int16 GetDelayDeath() const { return 0; }
inline virtual int32 GetMaxSTR() const { return GetSTR(); }
inline virtual int32 GetMaxSTA() const { return GetSTA(); }
inline virtual int32 GetMaxDEX() const { return GetDEX(); }
inline virtual int32 GetMaxAGI() const { return GetAGI(); }
inline virtual int32 GetMaxINT() const { return GetINT(); }
inline virtual int32 GetMaxWIS() const { return GetWIS(); }
inline virtual int32 GetMaxCHA() const { return GetCHA(); }
inline virtual int32 GetMaxMR() const { return 255; }
inline virtual int32 GetMaxPR() const { return 255; }
inline virtual int32 GetMaxDR() const { return 255; }
inline virtual int32 GetMaxCR() const { return 255; }
inline virtual int32 GetMaxFR() const { return 255; }
inline virtual int32 GetDelayDeath() const { return 0; }
inline int32 GetHP() const { return cur_hp; }
inline int32 GetMaxHP() const { return max_hp; }
virtual int32 CalcMaxHP();
@@ -385,18 +401,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;
@@ -411,9 +428,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)); }
@@ -423,43 +440,43 @@ 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);
inline uint32 GetLevelCon(uint8 iOtherLevel) const {
return this ? GetLevelCon(GetLevel(), iOtherLevel) : CON_GREEN; }
virtual void AddToHateList(Mob* other, int32 hate = 0, int32 damage = 0, bool iYellForHelp = true,
virtual void AddToHateList(Mob* other, uint32 hate = 0, int32 damage = 0, bool iYellForHelp = true,
bool bFrenzy = false, bool iBuffTic = false);
bool RemoveFromHateList(Mob* mob);
void SetHate(Mob* other, int32 hate = 0, int32 damage = 0) { hate_list.Set(other,hate,damage);}
void HalveAggro(Mob *other) { uint32 in_hate = GetHateAmount(other); SetHate(other, (in_hate > 1 ? in_hate / 2 : 1)); }
void DoubleAggro(Mob *other) { uint32 in_hate = GetHateAmount(other); SetHate(other, (in_hate ? in_hate * 2 : 1)); }
uint32 GetHateAmount(Mob* tmob, bool is_dam = false) { return hate_list.GetEntHate(tmob,is_dam);}
uint32 GetDamageAmount(Mob* tmob) { return hate_list.GetEntHate(tmob, true);}
Mob* GetHateTop() { return hate_list.GetTop(this);}
Mob* GetHateDamageTop(Mob* other) { return hate_list.GetDamageTop(other);}
Mob* GetHateRandom() { return hate_list.GetRandom();}
Mob* GetHateMost() { return hate_list.GetMostHate();}
bool IsEngaged() { return(!hate_list.IsEmpty()); }
void SetHateAmountOnEnt(Mob* other, int32 hate = 0, int32 damage = 0) { hate_list.SetHateAmountOnEnt(other,hate,damage);}
void HalveAggro(Mob *other) { uint32 in_hate = GetHateAmount(other); SetHateAmountOnEnt(other, (in_hate > 1 ? in_hate / 2 : 1)); }
void DoubleAggro(Mob *other) { uint32 in_hate = GetHateAmount(other); SetHateAmountOnEnt(other, (in_hate ? in_hate * 2 : 1)); }
uint32 GetHateAmount(Mob* tmob, bool is_dam = false) { return hate_list.GetEntHateAmount(tmob,is_dam);}
uint32 GetDamageAmount(Mob* tmob) { return hate_list.GetEntHateAmount(tmob, true);}
Mob* GetHateTop() { return hate_list.GetEntWithMostHateOnList(this);}
Mob* GetHateDamageTop(Mob* other) { return hate_list.GetDamageTopOnHateList(other);}
Mob* GetHateRandom() { return hate_list.GetRandomEntOnHateList();}
Mob* GetHateMost() { return hate_list.GetEntWithMostHateOnList();}
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);
void ClearFeignMemory();
void PrintHateListToClient(Client *who) { hate_list.PrintToClient(who); }
std::list<tHateEntry*>& GetHateList() { return hate_list.GetHateList(); }
void PrintHateListToClient(Client *who) { hate_list.PrintHateListToClient(who); }
std::list<struct_HateList*>& GetHateList() { return hate_list.GetHateList(); }
bool CheckLosFN(Mob* other);
bool CheckLosFN(float posX, float posY, float posZ, float mobSize);
inline void SetChanged() { pLastChange = Timer::GetCurrentTime(); }
@@ -484,6 +501,7 @@ public:
//Util
static uint32 RandomTimer(int min, int max);
static uint8 GetDefaultGender(uint16 in_race, uint8 in_gender = 0xFF);
static bool IsPlayerRace(uint16 in_race);
uint16 GetSkillByItemType(int ItemType);
uint8 GetItemTypeBySkill(SkillUseTypes skill);
virtual void MakePet(uint16 spell_id, const char* pettype, const char *petname = nullptr);
@@ -495,13 +513,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);
@@ -519,12 +530,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);
@@ -559,21 +564,22 @@ 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);
virtual void UnStun();
inline void Silence(bool newval) { silenced = newval; }
inline void Amnesia(bool newval) { amnesiad = newval; }
void TemporaryPets(uint16 spell_id, Mob *target, const char *name_override = nullptr, uint32 duration_override = 0);
void TypesTemporaryPets(uint32 typesid, Mob *target, const char *name_override = nullptr, uint32 duration_override = 0, bool followme = false);
void TemporaryPets(uint16 spell_id, Mob *target, const char *name_override = nullptr, uint32 duration_override = 0, bool followme=true, bool sticktarg=false);
void TypesTemporaryPets(uint32 typesid, Mob *target, const char *name_override = nullptr, uint32 duration_override = 0, bool followme=true, bool sticktarg=false);
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);
@@ -610,7 +616,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);
@@ -647,6 +653,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();
@@ -661,14 +676,23 @@ public:
bool IsFamiliar() const { return(typeofpet == petFamiliar); }
bool IsAnimation() const { return(typeofpet == petAnimation); }
bool IsCharmed() const { return(typeofpet == petCharmed); }
bool IsTargetLockPet() const { return(typeofpet == petTargetLock); }
inline uint32 GetPetTargetLockID() { return pet_targetlock_id; };
inline void SetPetTargetLockID(uint32 value) { pet_targetlock_id = value; };
void SetOwnerID(uint16 NewOwnerID);
inline uint16 GetOwnerID() const { return ownerid; }
inline virtual bool HasOwner() { if(GetOwnerID()==0){return false;} return( entity_list.GetMob(GetOwnerID()) != 0); }
inline virtual bool IsPet() { return(HasOwner() && !IsMerc()); }
inline bool HasPet() const { if(GetPetID()==0){return false;} return (entity_list.GetMob(GetPetID()) != 0);}
bool HadTempPets() const { return(hasTempPet); }
void TempPets(bool i) { hasTempPet = i; }
inline bool HasTempPetsActive() const { return(hasTempPet); }
inline void SetTempPetsActive(bool i) { hasTempPet = i; }
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 void SetPetOwnerClient(bool value) { pet_owner_client = value; }
inline bool IsTempPet() const { return _IsTempPet; }
inline void SetTempPet(bool value) { _IsTempPet = value; }
inline const bodyType GetBodyType() const { return bodytype; }
inline const bodyType GetOrigBodyType() const { return orig_bodytype; }
@@ -697,7 +721,7 @@ public:
bool CanThisClassBlock(void) const;
int GetMonkHandToHandDelay(void);
uint16 GetClassLevelFactor();
uint32 GetClassLevelFactor();
void Mesmerize();
inline bool IsMezzed() const { return mezzed; }
inline bool IsStunned() const { return stunned; }
@@ -709,9 +733,14 @@ public:
int32 ReduceAllDamage(int32 damage);
virtual void DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool HitChance=false, bool CanAvoid=true);
virtual void DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const Item_Struct* item=nullptr, uint16 weapon_damage=0, int16 chance_mod=0,int16 focus=0, int ReuseTime=0);
virtual void DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const Item_Struct* AmmoItem=nullptr, uint16 weapon_damage=0, int16 chance_mod=0,int16 focus=0, int ReuseTime=0, uint32 range_id=0, int AmmoSlot=0, float speed = 4.0f);
virtual void DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse, int16 chance_mod=0, int16 focus=0, bool CanRiposte=false, int ReuseTime=0);
virtual void DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const ItemInst* Ammo=nullptr, uint16 weapon_damage=0, int16 chance_mod=0, int16 focus=0, int ReuseTime=0);
virtual void DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const ItemInst* Ammo=nullptr, uint16 weapon_damage=0, int16 chance_mod=0, int16 focus=0, int ReuseTime=0, uint32 range_id=0, uint32 ammo_id=0, const Item_Struct *AmmoItem=nullptr, int AmmoSlot=0, float speed= 4.0f);
bool TryProjectileAttack(Mob* other, const Item_Struct *item, SkillUseTypes skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo, int AmmoSlot, float speed);
void ProjectileAttack();
inline bool HasProjectileAttack() const { return ActiveProjectileATK; }
inline void SetProjectileAttack(bool value) { ActiveProjectileATK = value; }
float GetRangeDistTargetSizeMod(Mob* other);
bool CanDoSpecialAttack(Mob *other);
bool Flurry(ExtraAttackOptions *opts);
bool Rampage(ExtraAttackOptions *opts);
@@ -770,7 +799,7 @@ public:
void CheckFlee();
inline bool IsBlind() { return spellbonuses.IsBlind; }
inline bool CheckAggro(Mob* other) {return hate_list.IsOnHateList(other);}
inline bool CheckAggro(Mob* other) {return hate_list.IsEntOnHateList(other);}
float CalculateHeadingToTarget(float in_x, float in_y);
bool CalculateNewPosition(float x, float y, float z, float speed, bool checkZ = false);
virtual bool CalculateNewPosition2(float x, float y, float z, float speed, bool checkZ = true);
@@ -793,16 +822,16 @@ 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; }
void SetRaidGrouped(bool v);
inline bool IsLooting() const { return islooting; }
void SetLooting(bool val) { islooting = val; }
inline uint16 IsLooting() const { return entity_id_being_looted; }
void SetLooting(uint16 val) { entity_id_being_looted = val; }
bool CheckWillAggro(Mob *mob);
@@ -818,7 +847,7 @@ public:
virtual int32 CheckHealAggroAmount(uint16 spell_id, uint32 heal_possible = 0);
virtual uint32 GetAA(uint32 aa_id) const { return(0); }
uint16 GetInstrumentMod(uint16 spell_id) const;
uint32 GetInstrumentMod(uint16 spell_id) const;
int CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level = 1, Mob *caster = nullptr, int ticsremaining = 0);
int CalcSpellEffectValue_formula(int formula, int base, int max, int caster_level, uint16 spell_id, int ticsremaining = 0);
virtual int CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, int caster_level2, Mob* caster1 = nullptr, Mob* caster2 = nullptr, int buffslot = -1);
@@ -827,7 +856,7 @@ public:
// HP Event
inline int GetNextHPEvent() const { return nexthpevent; }
void SetNextHPEvent( int hpevent );
void SendItemAnimation(Mob *to, const Item_Struct *item, SkillUseTypes skillInUse);
void SendItemAnimation(Mob *to, const Item_Struct *item, SkillUseTypes skillInUse, float velocity= 4.0);
inline int& GetNextIncHPEvent() { return nextinchpevent; }
void SetNextIncHPEvent( int inchpevent );
@@ -847,19 +876,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; }
@@ -902,6 +928,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);
@@ -927,26 +963,26 @@ protected:
bool isgrouped;
bool israidgrouped;
bool pendinggroup;
bool islooting;
uint16 entity_id_being_looted; //the id of the entity being looted, 0 if not looting.
uint8 texture;
uint8 helmtexture;
int AC;
int16 ATK;
int16 STR;
int16 STA;
int16 DEX;
int16 AGI;
int16 INT;
int16 WIS;
int16 CHA;
int16 MR;
int16 CR;
int16 FR;
int16 DR;
int16 PR;
int16 Corrup;
int16 PhR;
int32 ATK;
int32 STR;
int32 STA;
int32 DEX;
int32 AGI;
int32 INT;
int32 WIS;
int32 CHA;
int32 MR;
int32 CR;
int32 FR;
int32 DR;
int32 PR;
int32 Corrup;
int32 PhR;
bool moving;
int targeted;
bool findable;
@@ -985,10 +1021,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;
@@ -1018,9 +1051,10 @@ protected:
int GetKickDamage();
int GetBashDamage();
virtual void ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg);
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);
@@ -1036,32 +1070,31 @@ 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;
float attack_speed; //% increase/decrease in attack speed (not haste)
int8 attack_delay; //delay between attacks in 10ths of seconds
float slow_mitigation; // Allows for a slow mitigation (100 = 100%, 50% = 50%)
int16 slow_mitigation; // Allows for a slow mitigation (100 = 100%, 50% = 50%)
Timer tic_timer;
Timer mana_timer;
//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;
@@ -1077,15 +1110,11 @@ protected:
uint8 bardsong_slot;
uint32 bardsong_target_id;
Timer projectile_timer;
uint32 projectile_spell_id[MAX_SPELL_PROJECTILE];
uint16 projectile_target_id[MAX_SPELL_PROJECTILE];
uint8 projectile_increment[MAX_SPELL_PROJECTILE];
float projectile_x[MAX_SPELL_PROJECTILE], projectile_y[MAX_SPELL_PROJECTILE], projectile_z[MAX_SPELL_PROJECTILE];
bool ActiveProjectileATK;
tProjatk ProjectileAtk[MAX_SPELL_PROJECTILE];
glm::vec3 m_RewindLocation;
float rewind_x;
float rewind_y;
float rewind_z;
Timer rewind_timer;
// Currently 3 max nimbus particle effects at a time
@@ -1127,6 +1156,7 @@ protected:
int16 SpellPowerDistanceMod;
bool last_los_check;
bool pseudo_rooted;
bool endur_upkeep;
// Bind wound
Timer bindwound_timer;
@@ -1145,14 +1175,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;
@@ -1180,25 +1210,21 @@ 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::list<int> Route;
std::deque<int> Route;
LOSType PathingLOSState;
Timer *PathingLOSCheckTimer;
Timer *PathingRouteUpdateTimerShort;
@@ -1219,18 +1245,20 @@ protected:
//temppet
bool hasTempPet;
bool _IsTempPet;
int16 count_TempPet;
bool pet_owner_client; //Flags regular and pets as belonging to a client
uint32 pet_targetlock_id;
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;
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;
bool m_targetable;
+180 -188
View File
@@ -15,25 +15,25 @@
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 <iostream>
#include <iomanip>
#include <stdlib.h>
#include <math.h>
#include <algorithm>
#include "npc.h"
#include "masterentity.h"
#include "npc_ai.h"
#include "map.h"
#include "../common/moremath.h"
#include "string_ids.h"
#include "../common/misc_functions.h"
#include "../common/string_util.h"
#include "../common/rulesys.h"
#include "../common/global_define.h"
#include "../common/features.h"
#include "../common/rulesys.h"
#include "../common/string_util.h"
#include "client.h"
#include "entity.h"
#include "map.h"
#include "mob.h"
#include "npc.h"
#include "quest_parser_collection.h"
#include "string_ids.h"
#include "water_map.h"
#include <algorithm>
#include <iostream>
#include <math.h>
extern EntityList entity_list;
extern Zone *zone;
@@ -43,7 +43,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) {
@@ -57,7 +56,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
return false;
if (iChance < 100) {
if (MakeRandomInt(0, 100) >= iChance)
if (zone->random.Int(0, 100) >= iChance)
return false;
}
@@ -67,7 +66,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.
@@ -94,7 +93,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
dist2 <= spells[AIspells[i].spellid].range*spells[AIspells[i].spellid].range
)
&& (mana_cost <= GetMana() || GetMana() == GetMaxMana())
&& (AIspells[i].time_cancast + (MakeRandomInt(0, 4) * 1000)) <= Timer::GetCurrentTime() //break up the spelling casting over a period of time.
&& (AIspells[i].time_cancast + (zone->random.Int(0, 4) * 1000)) <= Timer::GetCurrentTime() //break up the spelling casting over a period of time.
) {
#if MobAI_DEBUG_Spells >= 21
@@ -126,7 +125,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
}
case SpellType_Root: {
Mob *rootee = GetHateRandom();
if (rootee && !rootee->IsRooted() && MakeRandomInt(0, 99) < 50
if (rootee && !rootee->IsRooted() && zone->random.Roll(50)
&& rootee->DontRootMeBefore() < Timer::GetCurrentTime()
&& rootee->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0
) {
@@ -165,7 +164,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
}
case SpellType_InCombatBuff: {
if(MakeRandomInt(0, 99) < 50)
if(zone->random.Roll(50))
{
AIDoSpellCast(i, tar, mana_cost);
return true;
@@ -184,7 +183,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
case SpellType_Slow:
case SpellType_Debuff: {
Mob * debuffee = GetHateRandom();
if (debuffee && manaR >= 10 && MakeRandomInt(0, 99 < 70) &&
if (debuffee && manaR >= 10 && zone->random.Roll(70) &&
debuffee->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0) {
if (!checked_los) {
if (!CheckLosFN(debuffee))
@@ -198,7 +197,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
}
case SpellType_Nuke: {
if (
manaR >= 10 && MakeRandomInt(0, 99) < 70
manaR >= 10 && zone->random.Roll(70)
&& tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0
) {
if(!checked_los) {
@@ -212,7 +211,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
break;
}
case SpellType_Dispel: {
if(MakeRandomInt(0, 99) < 15)
if(zone->random.Roll(15))
{
if(!checked_los) {
if(!CheckLosFN(tar))
@@ -228,7 +227,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
break;
}
case SpellType_Mez: {
if(MakeRandomInt(0, 99) < 20)
if(zone->random.Roll(20))
{
Mob * mezTar = nullptr;
mezTar = entity_list.GetTargetForMez(this);
@@ -244,7 +243,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
case SpellType_Charm:
{
if(!IsPet() && MakeRandomInt(0, 99) < 20)
if(!IsPet() && zone->random.Roll(20))
{
Mob * chrmTar = GetHateRandom();
if(chrmTar && chrmTar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0)
@@ -258,7 +257,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
case SpellType_Pet: {
//keep mobs from recasting pets when they have them.
if (!IsPet() && !GetPetID() && MakeRandomInt(0, 99) < 25) {
if (!IsPet() && !GetPetID() && zone->random.Roll(25)) {
AIDoSpellCast(i, tar, mana_cost);
return true;
}
@@ -266,7 +265,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
}
case SpellType_Lifetap: {
if (GetHPRatio() <= 95
&& MakeRandomInt(0, 99) < 50
&& zone->random.Roll(50)
&& tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0
) {
if(!checked_los) {
@@ -282,7 +281,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
case SpellType_Snare: {
if (
!tar->IsRooted()
&& MakeRandomInt(0, 99) < 50
&& zone->random.Roll(50)
&& tar->DontSnareMeBefore() < Timer::GetCurrentTime()
&& tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0
) {
@@ -300,7 +299,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
}
case SpellType_DOT: {
if (
MakeRandomInt(0, 99) < 60
zone->random.Roll(60)
&& tar->DontDotMeBefore() < Timer::GetCurrentTime()
&& tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0
) {
@@ -355,7 +354,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);
}
@@ -369,7 +368,7 @@ bool EntityList::AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float
return false;
if (iChance < 100) {
uint8 tmp = MakeRandomInt(0, 99);
uint8 tmp = zone->random.Int(0, 99);
if (tmp >= iChance)
return false;
}
@@ -401,7 +400,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
@@ -423,14 +422,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);
@@ -442,10 +442,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;
@@ -459,8 +458,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;
}
@@ -475,13 +474,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();
@@ -491,12 +490,9 @@ void Mob::AI_Start(uint32 iMoveDelay) {
pAggroRange = 70;
if (GetAssistRange() == 0)
pAssistRange = 70;
hate_list.Wipe();
hate_list.WipeHateList();
delta_heading = 0;
delta_x = 0;
delta_y = 0;
delta_z = 0;
m_Delta = glm::vec4();
pRunAnimSpeed = 0;
pLastChange = Timer::GetCurrentTime();
}
@@ -520,10 +516,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);
}
@@ -544,19 +540,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.Wipe();
hate_list.WipeHateList();
}
void NPC::AI_Stop() {
Waypoints.clear();
safe_delete(AIautocastspell_timer);
AIautocastspell_timer.reset(nullptr);
}
void Client::AI_Stop() {
@@ -597,7 +593,6 @@ void Mob::AI_ShutDown() {
tic_timer.Disable();
mana_timer.Disable();
spellend_timer.Disable();
projectile_timer.Disable();
rewind_timer.Disable();
bindwound_timer.Disable();
stunned_timer.Disable();
@@ -626,7 +621,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;
@@ -688,7 +683,7 @@ void Client::AI_SpellCast()
}
else
{
uint32 idx = MakeRandomInt(0, (valid_spells.size()-1));
uint32 idx = zone->random.Int(0, (valid_spells.size()-1));
spell_to_cast = valid_spells[idx];
slot_to_use = slots[idx];
}
@@ -788,17 +783,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)
@@ -815,12 +811,12 @@ void Client::AI_Process()
if (engaged)
{
if (IsRooted())
SetTarget(hate_list.GetClosest(this));
SetTarget(hate_list.GetClosestEntOnHateList(this));
else
{
if(AItarget_check_timer->Check())
{
SetTarget(hate_list.GetTop(this));
SetTarget(hate_list.GetEntWithMostHateOnList(this));
}
}
@@ -876,7 +872,7 @@ void Client::AI_Process()
if (flurrychance)
{
if(MakeRandomInt(0, 100) < flurrychance)
if(zone->random.Roll(flurrychance))
{
Message_StringID(MT_NPCFlurry, YOU_FLURRY);
Attack(GetTarget(), MainPrimary, false);
@@ -893,7 +889,7 @@ void Client::AI_Process()
wpn->GetItem()->ItemType == ItemType2HBlunt ||
wpn->GetItem()->ItemType == ItemType2HPiercing )
{
if(MakeRandomInt(0, 100) < ExtraAttackChanceBonus)
if(zone->random.Roll(ExtraAttackChanceBonus))
{
Attack(GetTarget(), MainPrimary, false);
}
@@ -932,7 +928,7 @@ void Client::AI_Process()
int16 DWBonus = spellbonuses.DualWieldChance + itembonuses.DualWieldChance;
DualWieldProbability += DualWieldProbability*float(DWBonus)/ 100.0f;
if(MakeRandomFloat(0.0, 1.0) < DualWieldProbability)
if(zone->random.Roll(DualWieldProbability))
{
Attack(GetTarget(), MainSecondary);
if(CheckDoubleAttack())
@@ -954,7 +950,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)
@@ -1001,7 +997,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();
@@ -1040,7 +1036,7 @@ void Mob::AI_Process() {
//
if(RuleB(Combat, EnableFearPathing)){
if(curfp) {
if(IsRooted() || (IsBlind() && CombatRange(hate_list.GetClosest(this)))) {
if(IsRooted() || (IsBlind() && CombatRange(hate_list.GetClosestEntOnHateList(this)))) {
//make sure everybody knows were not moving, for appearance sake
if(IsMoving())
{
@@ -1056,17 +1052,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)
@@ -1089,19 +1086,19 @@ void Mob::AI_Process() {
{
// we are prevented from getting here if we are blind and don't have a target in range
// from above, so no extra blind checks needed
if (IsRooted() || IsBlind())
SetTarget(hate_list.GetClosest(this));
if ((IsRooted() && !GetSpecialAbility(IGNORE_ROOT_AGGRO_RULES)) || IsBlind())
SetTarget(hate_list.GetClosestEntOnHateList(this));
else
{
if(AItarget_check_timer->Check())
{
if (IsFocused()) {
if (!target) {
SetTarget(hate_list.GetTop(this));
SetTarget(hate_list.GetEntWithMostHateOnList(this));
}
} else {
if (!ImprovedTaunt())
SetTarget(hate_list.GetTop(this));
SetTarget(hate_list.GetEntWithMostHateOnList(this));
}
}
@@ -1128,19 +1125,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();
@@ -1192,7 +1190,7 @@ void Mob::AI_Process() {
//we use this random value in three comparisons with different
//thresholds, and if its truely random, then this should work
//out reasonably and will save us compute resources.
int32 RandRoll = MakeRandomInt(0, 99);
int32 RandRoll = zone->random.Int(0, 99);
if ((CanThisClassDoubleAttack() || GetSpecialAbility(SPECATK_TRIPLE)
|| GetSpecialAbility(SPECATK_QUAD))
//check double attack, this is NOT the same rules that clients use...
@@ -1216,7 +1214,7 @@ void Mob::AI_Process() {
int flurry_chance = GetSpecialAbilityParam(SPECATK_FLURRY, 0);
flurry_chance = flurry_chance > 0 ? flurry_chance : RuleI(Combat, NPCFlurryChance);
if (MakeRandomInt(0, 99) < flurry_chance) {
if (zone->random.Roll(flurry_chance)) {
ExtraAttackOptions opts;
int cur = GetSpecialAbilityParam(SPECATK_FLURRY, 2);
if (cur > 0)
@@ -1258,7 +1256,7 @@ void Mob::AI_Process() {
int16 flurry_chance = owner->aabonuses.PetFlurry +
owner->spellbonuses.PetFlurry + owner->itembonuses.PetFlurry;
if (flurry_chance && (MakeRandomInt(0, 99) < flurry_chance))
if (flurry_chance && zone->random.Roll(flurry_chance))
Flurry(nullptr);
}
}
@@ -1267,7 +1265,7 @@ void Mob::AI_Process() {
{
int rampage_chance = GetSpecialAbilityParam(SPECATK_RAMPAGE, 0);
rampage_chance = rampage_chance > 0 ? rampage_chance : 20;
if(MakeRandomInt(0, 99) < rampage_chance) {
if(zone->random.Roll(rampage_chance)) {
ExtraAttackOptions opts;
int cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 2);
if(cur > 0) {
@@ -1306,7 +1304,7 @@ void Mob::AI_Process() {
{
int rampage_chance = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 0);
rampage_chance = rampage_chance > 0 ? rampage_chance : 20;
if(MakeRandomInt(0, 99) < rampage_chance) {
if(zone->random.Roll(rampage_chance)) {
ExtraAttackOptions opts;
int cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 2);
if(cur > 0) {
@@ -1350,13 +1348,12 @@ void Mob::AI_Process() {
//can only dual wield without a weapon if your a monk
if(GetSpecialAbility(SPECATK_INNATE_DW) || (GetEquipment(MaterialSecondary) != 0 && GetLevel() > 29) || myclass == MONK || myclass == MONKGM) {
float DualWieldProbability = (GetSkill(SkillDualWield) + GetLevel()) / 400.0f;
if(MakeRandomFloat(0.0, 1.0) < DualWieldProbability)
if(zone->random.Roll(DualWieldProbability))
{
Attack(target, MainSecondary);
if (CanThisClassDoubleAttack())
{
int32 RandRoll = MakeRandomInt(0, 99);
if (RandRoll < (GetLevel() + 20))
if (zone->random.Roll(GetLevel() + 20))
{
Attack(target, MainSecondary);
}
@@ -1375,8 +1372,9 @@ 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())) {
Mob *tar = hate_list.GetTop(this);
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();
Heal();
@@ -1406,14 +1404,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)
@@ -1438,7 +1436,7 @@ void Mob::AI_Process() {
else
{
if(AIfeignremember_timer->Check()) {
// EverHood - 6/14/06
// 6/14/06
// Improved Feign Death Memory
// check to see if any of our previous feigned targets have gotten up.
std::set<uint32>::iterator RememberedCharID;
@@ -1495,7 +1493,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 +1548,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
@@ -1620,12 +1618,12 @@ void NPC::AI_DoMovement() {
)
{
float movedist = roambox_distance*roambox_distance;
float movex = MakeRandomFloat(0, movedist);
float movex = zone->random.Real(0, movedist);
float movey = movedist - movex;
movex = sqrtf(movex);
movey = sqrtf(movey);
movex *= MakeRandomInt(0, 1) ? 1 : -1;
movey *= MakeRandomInt(0, 1) ? 1 : -1;
movex *= zone->random.Int(0, 1) ? 1 : -1;
movey *= zone->random.Int(0, 1) ? 1 : -1;
roambox_movingto_x = GetX() + movex;
roambox_movingto_y = GetY() + movey;
//Try to calculate new coord using distance.
@@ -1636,12 +1634,12 @@ void NPC::AI_DoMovement() {
//New coord is still invalid, ignore distance and just pick a new random coord.
//If we're here we may have a roambox where one side is shorter than the specified distance. Commons, Wkarana, etc.
if (roambox_movingto_x > roambox_max_x || roambox_movingto_x < roambox_min_x)
roambox_movingto_x = MakeRandomFloat(roambox_min_x+1,roambox_max_x-1);
roambox_movingto_x = zone->random.Real(roambox_min_x+1,roambox_max_x-1);
if (roambox_movingto_y > roambox_max_y || roambox_movingto_y < roambox_min_y)
roambox_movingto_y = MakeRandomFloat(roambox_min_y+1,roambox_max_y-1);
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 +1692,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 +1725,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 +1749,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 +1773,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 +1787,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 +1809,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());
}
@@ -1880,8 +1878,8 @@ void Mob::AI_Event_NoLongerEngaged() {
if (minLastFightingDelayMoving == maxLastFightingDelayMoving)
pLastFightingDelayMoving += minLastFightingDelayMoving;
else
pLastFightingDelayMoving += MakeRandomInt(minLastFightingDelayMoving, maxLastFightingDelayMoving);
// EverHood - So mobs don't keep running as a ghost until AIwalking_timer fires
pLastFightingDelayMoving += zone->random.Int(minLastFightingDelayMoving, maxLastFightingDelayMoving);
// So mobs don't keep running as a ghost until AIwalking_timer fires
// if they were moving prior to losing all hate
if(IsMoving()){
SetRunAnimSpeed(0);
@@ -1907,7 +1905,7 @@ void Mob::AI_Event_NoLongerEngaged() {
}
//this gets called from InterruptSpell() for failure or SpellFinished() for success
void NPC::AI_Event_SpellCastFinished(bool iCastSucceeded, uint8 slot) {
void NPC::AI_Event_SpellCastFinished(bool iCastSucceeded, uint16 slot) {
if (slot == 1) {
uint32 recovery_time = 0;
if (iCastSucceeded) {
@@ -1936,7 +1934,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)) {
@@ -1959,7 +1957,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);
@@ -2336,7 +2334,6 @@ create table npc_spells_entries (
bool IsSpellInList(DBnpcspells_Struct* spell_list, int16 iSpellID);
bool IsSpellEffectInList(DBnpcspellseffects_Struct* spelleffect_list, uint16 iSpellEffectID, int32 base, int32 limit, int32 max);
bool Compare_AI_Spells(AISpells_Struct i, AISpells_Struct j);
bool NPC::AI_AddNPCSpells(uint32 iDBSpellsID) {
// ok, this function should load the list, and the parent list then shove them into the struct and sort
@@ -2461,7 +2458,9 @@ bool NPC::AI_AddNPCSpells(uint32 iDBSpellsID) {
spell_list->entries[i].resist_adjust);
}
}
std::sort(AIspells.begin(), AIspells.end(), Compare_AI_Spells);
std::sort(AIspells.begin(), AIspells.end(), [](const AISpells_Struct& a, const AISpells_Struct& b) {
return a.priority > b.priority;
});
if (IsValidSpell(attack_proc_spell))
AddProcToWeapon(attack_proc_spell, true, proc_chance);
@@ -2601,11 +2600,6 @@ bool IsSpellInList(DBnpcspells_Struct* spell_list, int16 iSpellID) {
return false;
}
bool Compare_AI_Spells(AISpells_Struct i, AISpells_Struct j)
{
return(i.priority > j.priority);
}
// adds a spell to the list, taking into account priority and resorting list as needed.
void NPC::AddSpellToNPCList(int16 iPriority, int16 iSpellID, uint16 iType,
int16 iManaCost, int32 iRecastDelay, int16 iResistAdjust)
@@ -2663,7 +2657,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;
}
}
@@ -2686,7 +2680,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;
}
@@ -2722,7 +2715,6 @@ DBnpcspells_Struct* ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID) {
if (!results.Success())
{
std::cerr << "Error in AddNPCSpells query1 '" << query << "' " << results.ErrorMessage() << std::endl;
return nullptr;
}
@@ -2733,7 +2725,7 @@ DBnpcspells_Struct* ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID) {
npc_spells_cache[iDBSpellsID]->attack_proc = tmpattack_proc;
npc_spells_cache[iDBSpellsID]->proc_chance = tmpproc_chance;
npc_spells_cache[iDBSpellsID]->range_proc = tmprange_proc;
npc_spells_cache[iDBSpellsID]->rproc_chance = tmpdproc_chance;
npc_spells_cache[iDBSpellsID]->rproc_chance = tmprproc_chance;
npc_spells_cache[iDBSpellsID]->defensive_proc = tmpdefensive_proc;
npc_spells_cache[iDBSpellsID]->dproc_chance = tmpdproc_chance;
npc_spells_cache[iDBSpellsID]->fail_recast = tmppfail_recast;
@@ -2779,7 +2771,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;
}
@@ -2794,16 +2785,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;
}
}
@@ -2811,54 +2803,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() {
@@ -2866,7 +2859,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;
}
+10 -17
View File
@@ -1,22 +1,15 @@
#include "../common/debug.h"
#include "../common/timer.h"
#include <cmath>
#include <stdlib.h>
#include "spawn2.h"
#include "entity.h"
#include "masterentity.h"
#include "zone.h"
#include "spawngroup.h"
#include "zonedb.h"
#include "npc.h"
#include "mob.h"
#include "client.h"
#include "entity.h"
#include "mob.h"
#include "npc.h"
#include "worldserver.h"
#include "quest_parser_collection.h"
#include "event_codes.h"
#include "embparser.h"
#include <string>
#include <iostream>
#include "zone.h"
class ItemInst;
class Spawn2;
struct Consider_Struct;
struct DBTradeskillRecipe_Struct;
struct Item_Struct;
extern EntityList entity_list;
extern Zone* zone;
+87 -112
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"
@@ -58,7 +61,7 @@
#include "quest_parser_collection.h"
#include "embparser.h"
#include "lua_parser.h"
#include "client_logs.h"
#include "questmgr.h"
#include <iostream>
@@ -69,6 +72,7 @@
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <ctime>
#ifdef _CRTDBG_MAP_ALLOC
#undef new
@@ -97,9 +101,10 @@ extern Zone* zone;
EQStreamFactory eqsf(ZoneStream);
npcDecayTimes_Struct npcCorpseDecayTimes[100];
TitleManager title_manager;
QueryServ *QServ = 0;
QueryServ *QServ = 0;
TaskManager *taskmanager = 0;
QuestParserCollection *parse = 0;
EQEmuLogSys Log;
const SPDat_Spell_Struct* spells;
void LoadSpells(EQEmu::MemoryMappedFile **mmf);
@@ -109,11 +114,10 @@ void Shutdown();
extern void MapOpcodes();
int main(int argc, char** argv) {
RegisterExecutablePlatform(ExePlatformZone);
set_exception_handler();
const char *zone_name;
RegisterExecutablePlatform(ExePlatformZone);
Log.LoadLogSettingsDefaults();
set_exception_handler();
const char *zone_name;
QServ = new QueryServ;
if(argc == 3) {
@@ -142,144 +146,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();
}
@@ -296,17 +300,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
@@ -317,9 +315,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;
}
@@ -328,13 +326,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;
@@ -346,13 +344,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;
@@ -366,7 +363,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
}
@@ -378,7 +375,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);
}
@@ -423,10 +420,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) {
@@ -449,25 +444,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()) {
@@ -475,7 +451,7 @@ int main(int argc, char** argv) {
}
#endif
#endif
} //end extra profiler block
} //end extra profiler block
Sleep(ZoneTimerResolution);
}
@@ -502,14 +478,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;
}
@@ -518,9 +494,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()
@@ -609,7 +585,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;
}
@@ -642,4 +618,3 @@ void UpdateWindowTitle(char* iNewTitle) {
SetConsoleTitle(tmp);
#endif
}
-3
View File
@@ -26,9 +26,6 @@
#include <netdb.h>
#endif
#include <errno.h>
#include <fcntl.h>
#include "../common/types.h"
#include "../common/timer.h"
void CatchSignal(int);
+385 -365
View File
File diff suppressed because it is too large Load Diff
+54 -49
View File
@@ -18,20 +18,17 @@
#ifndef NPC_H
#define NPC_H
class NPC;
#include "zonedb.h"
#include "mob.h"
//#include "spawn.h"
#include <list>
#include <deque>
#include "spawn2.h"
#include "../common/loottable.h"
#include "zonedump.h"
#include "qglobals.h"
#include "../common/rulesys.h"
#include "mob.h"
#include "qglobals.h"
#include "zonedb.h"
#include "zonedump.h"
#include <deque>
#include <list>
#ifdef _WINDOWS
#define M_PI 3.141592
#endif
@@ -67,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 {
@@ -86,18 +83,22 @@ struct AISpellsVar_Struct {
uint32 idle_no_sp_recast_min;
uint32 idle_no_sp_recast_max;
uint8 idle_beneficial_chance;
};
};
class AA_SwarmPetInfo;
class Client;
class Group;
class Raid;
class Spawn2;
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();
@@ -127,16 +128,13 @@ public:
virtual bool AI_PursueCastCheck();
virtual bool AI_IdleCastCheck();
virtual void AI_Event_SpellCastFinished(bool iCastSucceeded, uint8 slot);
virtual void AI_Event_SpellCastFinished(bool iCastSucceeded, uint16 slot);
void LevelScale();
void CalcNPCResists();
void CalcNPCRegen();
void CalcNPCDamage();
int32 GetActSpellDamage(uint16 spell_id, int32 value, Mob* target = nullptr);
int32 GetActSpellHealing(uint16 spell_id, int32 value, Mob* target = nullptr);
virtual void SetTarget(Mob* mob);
virtual uint16 GetSkill(SkillUseTypes skill_num) const { if (skill_num <= HIGHEST_SKILL) { return skills[skill_num]; } return 0; }
@@ -157,13 +155,14 @@ public:
virtual void RangedAttack(Mob* other);
virtual void ThrowingAttack(Mob* other) { }
int32 GetNumberOfAttacks() const { return attack_count; }
void DoRangedAttackDmg(Mob* other, bool Launch=true, int16 damage_mod=0, int16 chance_mod=0, SkillUseTypes skill=SkillArchery, float speed=4.0f, const char *IDFile = nullptr);
bool DatabaseCastAccepted(int spell_id);
bool IsFactionListAlly(uint32 other_faction);
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);
@@ -188,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; }
@@ -211,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; }
@@ -243,33 +237,37 @@ public:
uint32 GetSwarmOwner();
uint32 GetSwarmTarget();
void SetSwarmTarget(int target_id = 0);
void DepopSwarmPets();
void PetOnSpawn(NewSpawn_Struct* ns);
void SignalNPC(int _signal_id);
inline int32 GetNPCFactionID() const { return npc_faction_id; }
inline int32 GetPrimaryFaction() const { return primary_faction; }
int32 GetNPCHate(Mob* in_ent) {return hate_list.GetEntHate(in_ent);}
bool IsOnHatelist(Mob*p) { return hate_list.IsOnHateList(p);}
int32 GetNPCHate(Mob* in_ent) {return hate_list.GetEntHateAmount(in_ent);}
bool IsOnHatelist(Mob*p) { return hate_list.IsEntOnHateList(p);}
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;}
float GetSlowMitigation() const { return slow_mitigation; }
float GetAttackSpeed() const {return attack_speed;}
uint8 GetAttackDelay() const {return attack_delay;}
bool IsAnimal() const { return(bodytype == BT_Animal); }
uint16 GetPetSpellID() const {return pet_spell_id;}
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);
virtual void DoClassAttacks(Mob *target);
void CheckSignal();
inline bool IsTargetableWithHotkey() const { return no_target_hotkey; }
inline bool IsNotTargetableWithHotkey() const { return no_target_hotkey; }
int32 GetNPCHPRegen() const { return hp_regen + itembonuses.HPRegen + spellbonuses.HPRegen; }
inline const char* GetAmmoIDfile() const { return ammo_idfile; }
@@ -285,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);
@@ -357,8 +355,9 @@ public:
const bool GetCombatEvent() const { return combat_event; }
void SetCombatEvent(bool b) { combat_event = b; }
//The corpse we make can only be looted by people who got credit for the kill
/* Only allows players that killed corpse to loot */
const bool HasPrivateCorpse() const { return NPCTypedata->private_corpse; }
const bool IsUnderwaterOnly() const { return NPCTypedata->underwater; }
const char* GetRawNPCTypeName() const { return NPCTypedata->name; }
@@ -383,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;}
@@ -400,6 +399,9 @@ public:
void mod_npc_killed(Mob* oos);
void AISpellsList(Client *c);
uint32 GetHeroForgeModel() const { return herosforgemodel; }
void SetHeroForgeModel(uint32 model) { herosforgemodel = model; }
bool IsRaidTarget() const { return raid_target; };
protected:
@@ -434,14 +436,15 @@ 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;
virtual bool AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes);
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;
@@ -471,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;
@@ -487,8 +490,10 @@ protected:
uint16 skills[HIGHEST_SKILL+1];
uint32 equipment[EmuConstants::EQUIPMENT_SIZE]; //this is an array of item IDs
uint16 d_meele_texture1; //this is an item Material value
uint16 d_meele_texture2; //this is an item Material value (offhand)
uint32 herosforgemodel; //this is the Hero Forge Armor Model (i.e 63 or 84 or 203)
uint16 d_melee_texture1; //this is an item Material value
uint16 d_melee_texture2; //this is an item Material value (offhand)
const char* ammo_idfile; //this determines projectile graphic "IT###" (see item field 'idfile')
uint8 prim_melee_type; //Sets the Primary Weapon attack message and animation
uint8 sec_melee_type; //Sets the Secondary Weapon attack message and animation
@@ -508,7 +513,7 @@ protected:
//mercenary stuff
std::list<MercType> mercTypeList;
std::list<MercData> mercDataList;
bool raid_target;
uint8 probability;
+76 -23
View File
@@ -16,20 +16,18 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include <iostream>
#include <stdlib.h>
#include "masterentity.h"
#include "zonedb.h"
#include "../common/packet_functions.h"
#include "../common/packet_dump.h"
#include "../common/misc_functions.h"
#include "../common/global_define.h"
#include "../common/string_util.h"
#include "../common/features.h"
#include "string_ids.h"
#include "client.h"
#include "entity.h"
#include "mob.h"
#include "object.h"
#include "quest_parser_collection.h"
#include "zonedb.h"
#include <iostream>
const char DEFAULT_OBJECT_NAME[] = "IT63_ACTORDEF";
const char DEFAULT_OBJECT_NAME_SUFFIX[] = "_ACTORDEF";
@@ -88,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();
@@ -120,7 +117,15 @@ Object::Object(Client* client, const ItemInst* inst)
m_data.heading = client->GetHeading();
m_data.x = client->GetX();
m_data.y = client->GetY();
m_data.z = client->GetZ();
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);
}
else
{
m_data.z = client->GetZ();
}
m_data.zone_id = zone->GetZoneID();
decay_timer.Start();
@@ -318,11 +323,19 @@ void Object::Delete(bool reset_state)
}
}
const ItemInst* Object::GetItem(uint8 index) {
if (index < EmuConstants::MAP_WORLD_SIZE) {
return m_inst->GetItem(index);
}
return nullptr;
}
// Add item to object (only logical for world tradeskill containers
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;
}
@@ -433,8 +446,8 @@ void Object::RandomSpawn(bool send_packet) {
if(!m_ground_spawn)
return;
m_data.x = MakeRandomFloat(m_min_x, m_max_x);
m_data.y = MakeRandomFloat(m_min_y, m_max_y);
m_data.x = zone->random.Real(m_min_x, m_max_x);
m_data.y = zone->random.Real(m_min_y, m_max_y);
respawn_timer.Disable();
if(send_packet) {
@@ -454,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);
@@ -584,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;
}
@@ -621,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;
}
@@ -640,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;
}
@@ -666,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());
}
}
@@ -790,6 +807,42 @@ void Object::SetModelName(const char* modelname)
safe_delete(app2);
}
void Object::SetSize(uint16 size)
{
m_data.unknown008 = size;
EQApplicationPacket* app = new EQApplicationPacket();
EQApplicationPacket* app2 = new EQApplicationPacket();
this->CreateDeSpawnPacket(app);
this->CreateSpawnPacket(app2);
entity_list.QueueClients(0, app);
entity_list.QueueClients(0, app2);
safe_delete(app);
safe_delete(app2);
}
void Object::SetSolidType(uint16 solidtype)
{
m_data.unknown010 = solidtype;
EQApplicationPacket* app = new EQApplicationPacket();
EQApplicationPacket* app2 = new EQApplicationPacket();
this->CreateDeSpawnPacket(app);
this->CreateSpawnPacket(app2);
entity_list.QueueClients(0, app);
entity_list.QueueClients(0, app2);
safe_delete(app);
safe_delete(app2);
}
uint16 Object::GetSize()
{
return m_data.unknown008;
}
uint16 Object::GetSolidType()
{
return m_data.unknown010;
}
const char* Object::GetModelName()
{
return this->m_data.object_name;
+12 -8
View File
@@ -21,16 +21,15 @@
// Object Class:
// Represents Zone Objects (forges, ovens, brew barrels, items dropped to ground, etc)
#include "../common/types.h"
#include "../common/linked_list.h"
#include "../common/emu_opcodes.h"
#include "../common/eq_packet_structs.h"
#include "../common/item.h"
#include "client.h"
#include "mob.h"
#include "npc.h"
#include "entity.h"
#include "../common/timer.h"
#include "../common/types.h"
#include "entity.h"
class Client;
class EQApplicationPacket;
class ItemInst;
/*
item icon numbers (showeq)
@@ -121,6 +120,7 @@ public:
void StartDecay() {decay_timer.Start();}
// Container functions
const ItemInst* GetItem(uint8 index);
void PutItem(uint8 index, const ItemInst* inst);
void DeleteItem(uint8 index); // Item inside container
ItemInst* PopItem(uint8 index); // Pop item out of container
@@ -156,6 +156,10 @@ public:
void SetZ(float pos);
void SetModelName(const char* modelname);
const char* GetModelName();
uint16 GetSize();
void SetSize(uint16 size);
uint16 GetSolidType();
void SetSolidType(uint16 size);
const char* GetEntityVariable(const char *id);
void SetEntityVariable(const char *id, const char *m_var);
-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
{
+194 -196
View File
File diff suppressed because it is too large Load Diff
+12 -13
View File
@@ -1,13 +1,12 @@
#ifndef PATHING_H
#define PATHING_H
#include <algorithm>
#include "map.h"
#include "../common/timer.h"
#include <list>
#include <vector>
#include <algorithm>
#include <deque>
class Client;
class Mob;
#define PATHNODENEIGHBOURS 50
@@ -31,7 +30,7 @@ struct NeighbourNode {
struct PathNode {
uint16 id;
Map::Vertex v;
glm::vec3 v;
float bestz;
NeighbourNode Neighbours[PATHNODENEIGHBOURS];
};
@@ -61,17 +60,17 @@ public:
static PathManager *LoadPathFile(const char *ZoneName);
bool loadPaths(FILE *fp);
void PrintPathing();
std::list<int> FindRoute(Map::Vertex Start, Map::Vertex End);
std::list<int> FindRoute(int startID, int endID);
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);
+98 -32
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
@@ -1023,11 +1023,12 @@ XS(XS_Client_SetBindPoint); /* prototype to pass -Wmissing-prototypes */
XS(XS_Client_SetBindPoint)
{
dXSARGS;
if (items < 1 || items > 5)
Perl_croak(aTHX_ "Usage: Client::SetBindPoint(THIS, to_zone= -1, new_x= 0.0f, new_y= 0.0f, new_z= 0.0f)");
if (items < 1 || items > 6)
Perl_croak(aTHX_ "Usage: Client::SetBindPoint(THIS, to_zone= -1, to_instance = 0, new_x= 0.0f, new_y= 0.0f, new_z= 0.0f)");
{
Client * THIS;
int to_zone;
int to_instance;
float new_x;
float new_y;
float new_z;
@@ -1047,25 +1048,31 @@ XS(XS_Client_SetBindPoint)
to_zone = (int)SvIV(ST(1));
}
if (items < 3)
new_x = 0.0f;
if(items < 3)
to_instance = 0;
else {
new_x = (float)SvNV(ST(2));
to_instance = (int)SvIV(ST(2));
}
if (items < 4)
new_y = 0.0f;
new_x = 0.0f;
else {
new_y = (float)SvNV(ST(3));
new_x = (float)SvNV(ST(3));
}
if (items < 5)
new_z = 0.0f;
new_y = 0.0f;
else {
new_z = (float)SvNV(ST(4));
new_y = (float)SvNV(ST(4));
}
THIS->SetBindPoint(to_zone, new_x, new_y, new_z);
if (items < 6)
new_z = 0.0f;
else {
new_z = (float)SvNV(ST(5));
}
THIS->SetBindPoint(to_zone, to_instance, glm::vec3(new_x, new_y, new_z));
}
XSRETURN_EMPTY;
}
@@ -1264,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");
}
@@ -1310,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");
}
@@ -3127,7 +3134,7 @@ XS(XS_Client_SummonItem)
slot_id = (uint16)SvUV(ST(9));
}
THIS->SummonItem(item_id, charges, aug1, aug2, aug3, aug4, aug5, attune, slot_id);
THIS->SummonItem(item_id, charges, aug1, aug2, aug3, aug4, aug5, 0, attune, slot_id);
}
XSRETURN_EMPTY;
}
@@ -3892,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);
@@ -5050,14 +5057,21 @@ XS(XS_Client_UpdateTaskActivity); /* prototype to pass -Wmissing-prototypes */
XS(XS_Client_UpdateTaskActivity)
{
dXSARGS;
if (items != 4)
Perl_croak(aTHX_ "Usage: Client::UpdateTaskActivity(THIS, TaskID, ActivityID, Count)");
if (items < 4)
Perl_croak(aTHX_ "Usage: Client::UpdateTaskActivity(THIS, TaskID, ActivityID, Count, [ignore_quest_update])");
{
bool ignore_quest_update = false;
Client * THIS;
int TaskID = (int)SvIV(ST(1));
int ActivityID = (int)SvIV(ST(2));
int Count = (int)SvUV(ST(3));
if (items == 5){
ignore_quest_update = (bool)SvTRUE(ST(4));
}
if (sv_derived_from(ST(0), "Client")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(Client *,tmp);
@@ -5067,7 +5081,7 @@ XS(XS_Client_UpdateTaskActivity)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
THIS->UpdateTaskActivity(TaskID, ActivityID, Count);
THIS->UpdateTaskActivity(TaskID, ActivityID, Count, ignore_quest_update);
}
XSRETURN_EMPTY;
}
@@ -5080,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;
@@ -5094,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);
}
@@ -5337,6 +5351,30 @@ XS(XS_Client_AssignToInstance)
XSRETURN_EMPTY;
}
XS(XS_Client_RemoveFromInstance); /* prototype to pass -Wmissing-prototypes */
XS(XS_Client_RemoveFromInstance)
{
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: Client::RemoveFromInstance(THIS, instance_id)");
{
Client * THIS;
uint16 instance_id = (uint16)SvUV(ST(1));
if (sv_derived_from(ST(0), "Client")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(Client *, tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type Client");
if (THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
THIS->RemoveFromInstance(instance_id);
}
XSRETURN_EMPTY;
}
XS(XS_Client_Freeze);
XS(XS_Client_Freeze)
{
@@ -5914,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);
@@ -5925,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)));
@@ -6046,6 +6084,32 @@ XS(XS_Client_SendColoredText)
XSRETURN_EMPTY;
}
XS(XS_Client_SendSpellAnim); /* prototype to pass -Wmissing-prototypes */
XS(XS_Client_SendSpellAnim)
{
dXSARGS;
if (items != 3)
Perl_croak(aTHX_ "Usage: SendSpellAnim(uint16 spell_id, uint32 seq)");
{
Client * THIS;
uint16 targetid = (uint16)SvUV(ST(1));
uint16 spell_id = (uint16)SvUV(ST(2));
dXSTARG;
if (sv_derived_from(ST(0), "Client")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(Client *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type Client");
if(THIS == NULL)
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
THIS->SendSpellAnim(targetid,spell_id);
}
XSRETURN_EMPTY;
}
#ifdef __cplusplus
extern "C"
#endif
@@ -6105,7 +6169,7 @@ XS(boot_Client)
newXSproto(strcpy(buf, "SetDeity"), XS_Client_SetDeity, file, "$$");
newXSproto(strcpy(buf, "AddEXP"), XS_Client_AddEXP, file, "$$;$$");
newXSproto(strcpy(buf, "SetEXP"), XS_Client_SetEXP, file, "$$$;$");
newXSproto(strcpy(buf, "SetBindPoint"), XS_Client_SetBindPoint, file, "$;$$$$");
newXSproto(strcpy(buf, "SetBindPoint"), XS_Client_SetBindPoint, file, "$;$$$$$");
newXSproto(strcpy(buf, "GetBindX"), XS_Client_GetBindX, file, "$$");
newXSproto(strcpy(buf, "GetBindY"), XS_Client_GetBindY, file, "$$");
newXSproto(strcpy(buf, "GetBindZ"), XS_Client_GetBindZ, file, "$$");
@@ -6248,7 +6312,7 @@ XS(boot_Client)
newXSproto(strcpy(buf, "ClearCompassMark"), XS_Client_ClearCompassMark, file, "$");
newXSproto(strcpy(buf, "GetFreeSpellBookSlot"), XS_Client_GetFreeSpellBookSlot, file, "$;$");
newXSproto(strcpy(buf, "GetSpellBookSlotBySpellID"), XS_Client_GetSpellBookSlotBySpellID, file, "$$");
newXSproto(strcpy(buf, "UpdateTaskActivity"), XS_Client_UpdateTaskActivity, file, "$$$$");
newXSproto(strcpy(buf, "UpdateTaskActivity"), XS_Client_UpdateTaskActivity, file, "$$$$;$");
newXSproto(strcpy(buf, "AssignTask"), XS_Client_AssignTask, file, "$$$");
newXSproto(strcpy(buf, "FailTask"), XS_Client_FailTask, file, "$$");
newXSproto(strcpy(buf, "IsTaskCompleted"), XS_Client_IsTaskCompleted, file, "$$");
@@ -6286,6 +6350,8 @@ XS(boot_Client)
newXSproto(strcpy(buf, "ExpeditionMessage"), XS_Client_ExpeditionMessage, file, "$$$");
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
+10 -10
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
@@ -40,19 +40,19 @@ XS(XS_HateEntry_GetEnt)
if (items != 1)
Perl_croak(aTHX_ "Usage: HateEntry::GetData(THIS)");
{
tHateEntry * THIS;
struct_HateList * THIS;
Mob * RETVAL;
if (sv_derived_from(ST(0), "HateEntry")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(tHateEntry *,tmp);
THIS = INT2PTR(struct_HateList *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type tHateEntry");
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->ent;
RETVAL = THIS->entity_on_hatelist;
ST(0) = sv_newmortal();
sv_setref_pv(ST(0), "Mob", (void*)RETVAL);
}
@@ -66,20 +66,20 @@ XS(XS_HateEntry_GetHate)
if (items != 1)
Perl_croak(aTHX_ "Usage: HateEntry::GetHate(THIS)");
{
tHateEntry * THIS;
struct_HateList * THIS;
int32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "HateEntry")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(tHateEntry *,tmp);
THIS = INT2PTR(struct_HateList *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type tHateEntry");
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->hate;
RETVAL = THIS->stored_hate_amount;
XSprePUSH; PUSHi((IV)RETVAL);
}
XSRETURN(1);
@@ -92,20 +92,20 @@ XS(XS_HateEntry_GetDamage)
if (items != 1)
Perl_croak(aTHX_ "Usage: HateEntry::GetDamage(THIS)");
{
tHateEntry * THIS;
struct_HateList * THIS;
int32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "HateEntry")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(tHateEntry *,tmp);
THIS = INT2PTR(struct_HateList *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type tHateEntry");
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->damage;
RETVAL = THIS->hatelist_damage;
XSprePUSH; PUSHi((IV)RETVAL);
}
XSRETURN(1);
+288 -56
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
@@ -1517,14 +1517,15 @@ XS(XS_Mob_MakeTempPet); /* prototype to pass -Wmissing-prototypes */
XS(XS_Mob_MakeTempPet)
{
dXSARGS;
if (items < 2 || items > 5)
Perl_croak(aTHX_ "Usage: Mob::MakeTempPet(THIS, spell_id, name=nullptr, duration=0, target=nullptr)");
if (items < 2 || items > 6)
Perl_croak(aTHX_ "Usage: Mob::MakeTempPet(THIS, spell_id, name=nullptr, duration=0, target=nullptr, sticktarg=0)");
{
Mob * THIS;
uint16 spell_id = (uint16)SvUV(ST(1));
char * name;
uint32 duration;
Mob * target;
bool sticktarg;
if (sv_derived_from(ST(0), "Mob")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
@@ -1554,7 +1555,13 @@ XS(XS_Mob_MakeTempPet)
else
Perl_croak(aTHX_ "owner is not of type Mob");
THIS->TemporaryPets(spell_id, target, name, duration);
if (items < 6)
sticktarg = false;
else {
sticktarg = (bool)SvTRUE(ST(5));
}
THIS->TemporaryPets(spell_id, target, name, duration, true, sticktarg);
}
XSRETURN_EMPTY;
}
@@ -1563,15 +1570,16 @@ XS(XS_Mob_TypesTempPet); /* prototype to pass -Wmissing-prototypes */
XS(XS_Mob_TypesTempPet)
{
dXSARGS;
if (items < 2 || items > 6)
Perl_croak(aTHX_ "Usage: Mob::TypesTempPet(THIS, typesid, name=nullptr, duration=0, target=nullptr, follow=0)");
if (items < 2 || items > 7)
Perl_croak(aTHX_ "Usage: Mob::TypesTempPet(THIS, typesid, name=nullptr, duration=0, follow=0, target=nullptr, sticktarg=0,)");
{
Mob * THIS;
uint32 typesid = (uint32)SvUV(ST(1));
char * name;
uint32 duration;
Mob * target;
bool follow;
Mob * target;
bool sticktarg;
if (sv_derived_from(ST(0), "Mob")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
@@ -1593,21 +1601,28 @@ XS(XS_Mob_TypesTempPet)
duration = (uint32)SvUV(ST(3));
if (items < 5)
follow = true;
else {
follow = (bool)SvTRUE(ST(4));
}
if (items < 6)
target = nullptr;
else if (sv_derived_from(ST(4), "Mob")) {
IV tmp = SvIV((SV*)SvRV(ST(4)));
else if (sv_derived_from(ST(5), "Mob")) {
IV tmp = SvIV((SV*)SvRV(ST(5)));
target = INT2PTR(Mob *,tmp);
}
else
Perl_croak(aTHX_ "target is not of type Mob");
if (items < 6)
follow = false;
if (items < 7)
sticktarg = false;
else {
follow = (bool)SvTRUE(ST(5));
sticktarg = (bool)SvTRUE(ST(6));
}
THIS->TypesTemporaryPets(typesid, target, name, duration, follow);
THIS->TypesTemporaryPets(typesid, target, name, duration, follow, sticktarg);
}
XSRETURN_EMPTY;
}
@@ -2536,7 +2551,7 @@ XS(XS_Mob_GetAC)
Perl_croak(aTHX_ "Usage: Mob::GetAC(THIS)");
{
Mob * THIS;
uint16 RETVAL;
uint32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "Mob")) {
@@ -2562,7 +2577,7 @@ XS(XS_Mob_GetATK)
Perl_croak(aTHX_ "Usage: Mob::GetATK(THIS)");
{
Mob * THIS;
uint16 RETVAL;
uint32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "Mob")) {
@@ -2588,7 +2603,7 @@ XS(XS_Mob_GetSTR)
Perl_croak(aTHX_ "Usage: Mob::GetSTR(THIS)");
{
Mob * THIS;
int16 RETVAL;
int32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "Mob")) {
@@ -2614,7 +2629,7 @@ XS(XS_Mob_GetSTA)
Perl_croak(aTHX_ "Usage: Mob::GetSTA(THIS)");
{
Mob * THIS;
int16 RETVAL;
int32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "Mob")) {
@@ -2640,7 +2655,7 @@ XS(XS_Mob_GetDEX)
Perl_croak(aTHX_ "Usage: Mob::GetDEX(THIS)");
{
Mob * THIS;
int16 RETVAL;
int32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "Mob")) {
@@ -2666,7 +2681,7 @@ XS(XS_Mob_GetAGI)
Perl_croak(aTHX_ "Usage: Mob::GetAGI(THIS)");
{
Mob * THIS;
int16 RETVAL;
int32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "Mob")) {
@@ -2692,7 +2707,7 @@ XS(XS_Mob_GetINT)
Perl_croak(aTHX_ "Usage: Mob::GetINT(THIS)");
{
Mob * THIS;
int16 RETVAL;
int32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "Mob")) {
@@ -2718,7 +2733,7 @@ XS(XS_Mob_GetWIS)
Perl_croak(aTHX_ "Usage: Mob::GetWIS(THIS)");
{
Mob * THIS;
int16 RETVAL;
int32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "Mob")) {
@@ -2744,7 +2759,7 @@ XS(XS_Mob_GetCHA)
Perl_croak(aTHX_ "Usage: Mob::GetCHA(THIS)");
{
Mob * THIS;
int16 RETVAL;
int32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "Mob")) {
@@ -2770,7 +2785,7 @@ XS(XS_Mob_GetMR)
Perl_croak(aTHX_ "Usage: Mob::GetMR(THIS)");
{
Mob * THIS;
int16 RETVAL;
int32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "Mob")) {
@@ -2796,7 +2811,7 @@ XS(XS_Mob_GetFR)
Perl_croak(aTHX_ "Usage: Mob::GetFR(THIS)");
{
Mob * THIS;
int16 RETVAL;
int32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "Mob")) {
@@ -2822,7 +2837,7 @@ XS(XS_Mob_GetDR)
Perl_croak(aTHX_ "Usage: Mob::GetDR(THIS)");
{
Mob * THIS;
int16 RETVAL;
int32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "Mob")) {
@@ -2848,7 +2863,7 @@ XS(XS_Mob_GetPR)
Perl_croak(aTHX_ "Usage: Mob::GetPR(THIS)");
{
Mob * THIS;
int16 RETVAL;
int32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "Mob")) {
@@ -2874,7 +2889,7 @@ XS(XS_Mob_GetCR)
Perl_croak(aTHX_ "Usage: Mob::GetCR(THIS)");
{
Mob * THIS;
int16 RETVAL;
int32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "Mob")) {
@@ -2900,7 +2915,7 @@ XS(XS_Mob_GetCorruption)
Perl_croak(aTHX_ "Usage: Mob::GetCorruption(THIS)");
{
Mob * THIS;
int16 RETVAL;
int32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "Mob")) {
@@ -2918,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)
{
@@ -2926,7 +2967,7 @@ XS(XS_Mob_GetMaxSTR)
Perl_croak(aTHX_ "Usage: Mob::GetMaxSTR(THIS)");
{
Mob * THIS;
int16 RETVAL;
int32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "Mob")) {
@@ -2952,7 +2993,7 @@ XS(XS_Mob_GetMaxSTA)
Perl_croak(aTHX_ "Usage: Mob::GetMaxSTA(THIS)");
{
Mob * THIS;
int16 RETVAL;
int32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "Mob")) {
@@ -2978,7 +3019,7 @@ XS(XS_Mob_GetMaxDEX)
Perl_croak(aTHX_ "Usage: Mob::GetMaxDEX(THIS)");
{
Mob * THIS;
int16 RETVAL;
int32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "Mob")) {
@@ -3004,7 +3045,7 @@ XS(XS_Mob_GetMaxAGI)
Perl_croak(aTHX_ "Usage: Mob::GetMaxAGI(THIS)");
{
Mob * THIS;
int16 RETVAL;
int32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "Mob")) {
@@ -3030,7 +3071,7 @@ XS(XS_Mob_GetMaxINT)
Perl_croak(aTHX_ "Usage: Mob::GetMaxINT(THIS)");
{
Mob * THIS;
int16 RETVAL;
int32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "Mob")) {
@@ -3056,7 +3097,7 @@ XS(XS_Mob_GetMaxWIS)
Perl_croak(aTHX_ "Usage: Mob::GetMaxWIS(THIS)");
{
Mob * THIS;
int16 RETVAL;
int32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "Mob")) {
@@ -3082,7 +3123,7 @@ XS(XS_Mob_GetMaxCHA)
Perl_croak(aTHX_ "Usage: Mob::GetMaxCHA(THIS)");
{
Mob * THIS;
int16 RETVAL;
int32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "Mob")) {
@@ -3510,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);
@@ -3536,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);
@@ -3562,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);
@@ -3588,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);
@@ -3956,7 +3997,10 @@ XS(XS_Mob_CastSpell)
resist_adjust = (int16)SvIV(ST(6));
}
THIS->CastSpell(spell_id, target_id, slot, casttime, mana_cost, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, &resist_adjust);
if (resist_adjust == 0)//If you do not pass resist adjust as nullptr it will ignore the spells default resist adjust
THIS->CastSpell(spell_id, target_id, slot, casttime, mana_cost, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0);
else
THIS->CastSpell(spell_id, target_id, slot, casttime, mana_cost, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, &resist_adjust);
}
XSRETURN_EMPTY;
}
@@ -5336,7 +5380,7 @@ XS(XS_Mob_SetHate)
damage = (int32)SvIV(ST(3));
}
THIS->SetHate(other, hate, damage);
THIS->SetHateAmountOnEnt(other, hate, damage);
}
XSRETURN_EMPTY;
}
@@ -6259,7 +6303,7 @@ XS(XS_Mob_CheckAggroAmount)
Perl_croak(aTHX_ "Usage: Mob::CheckAggroAmount(THIS, spellid)");
{
Mob * THIS;
uint16 RETVAL;
uint32 RETVAL;
dXSTARG;
uint16 spellid = (uint16)SvUV(ST(1));
@@ -6286,7 +6330,7 @@ XS(XS_Mob_CheckHealAggroAmount)
Perl_croak(aTHX_ "Usage: Mob::CheckHealAggroAmount(THIS, spellid, possible_heal_amt)");
{
Mob * THIS;
uint16 RETVAL;
uint32 RETVAL;
dXSTARG;
uint16 spellid = (uint16)SvUV(ST(1));
uint32 possible = 0;
@@ -6581,7 +6625,7 @@ XS(XS_Mob_GetHateList)
while(iter != hate_list.end())
{
tHateEntry *entry = (*iter);
struct_HateList *entry = (*iter);
ST(0) = sv_newmortal();
sv_setref_pv(ST(0), "HateEntry", (void*)entry);
XPUSHs(ST(0));
@@ -7442,12 +7486,13 @@ XS(XS_Mob_WearChange)
{
dXSARGS;
if (items < 3 || items > 4)
Perl_croak(aTHX_ "Usage: Mob::WearChange(THIS, material_slot, texture, color)");
Perl_croak(aTHX_ "Usage: Mob::WearChange(THIS, material_slot, texture, [color, hero_forge_model])");
{
Mob * THIS;
uint8 material_slot = (uint8)SvIV(ST(1));
uint16 texture = (uint16)SvUV(ST(2));
uint32 color = 0;
uint32 hero_forge_model = 0;
if (sv_derived_from(ST(0), "Mob")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
@@ -7461,8 +7506,11 @@ XS(XS_Mob_WearChange)
if (items > 3) {
color = (uint32)SvUV(ST(3));
}
if (items > 4) {
hero_forge_model = (uint32)SvUV(ST(3));
}
THIS->WearChange(material_slot, texture, color);
THIS->WearChange(material_slot, texture, color, hero_forge_model);
}
XSRETURN_EMPTY;
}
@@ -7614,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)));
@@ -7628,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;
}
@@ -8169,6 +8214,185 @@ XS(XS_Mob_GetSpellStat)
XSRETURN(1);
}
XS(XS_Mob_GetSpecialAbility); /* prototype to pass -Wmissing-prototypes */
XS(XS_Mob_GetSpecialAbility)
{
dXSARGS;
if(items != 2)
Perl_croak(aTHX_ "Usage: Mob::GetSpecialAbility(THIS, special_ability)");
{
int RETVAL;
Mob* THIS;
int ability = SvIV(ST(1));
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->GetSpecialAbility(ability);
XSprePUSH; PUSHi((IV)RETVAL);
}
XSRETURN(1);
}
XS(XS_Mob_GetSpecialAbilityParam); /* prototype to pass -Wmissing-prototypes */
XS(XS_Mob_GetSpecialAbilityParam)
{
dXSARGS;
if(items != 3)
Perl_croak(aTHX_ "Usage: Mob::GetSpecialAbilityParam(THIS, special_ability, param)");
{
int RETVAL;
Mob* THIS;
int ability = SvIV(ST(1));
int param = SvIV(ST(2));
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->GetSpecialAbilityParam(ability, param);
XSprePUSH; PUSHi((IV)RETVAL);
}
XSRETURN(1);
}
XS(XS_Mob_SetSpecialAbility); /* prototype to pass -Wmissing-prototypes */
XS(XS_Mob_SetSpecialAbility)
{
dXSARGS;
if(items != 3)
Perl_croak(aTHX_ "Usage: Mob::SetSpecialAbility(THIS, ability, value)");
{
Mob* THIS;
int ability = SvIV(ST(1));
int value = SvIV(ST(2));
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.");
THIS->SetSpecialAbility(ability, value);
}
XSRETURN_EMPTY;
}
XS(XS_Mob_SetSpecialAbilityParam); /* prototype to pass -Wmissing-prototypes */
XS(XS_Mob_SetSpecialAbilityParam)
{
dXSARGS;
if(items != 4)
Perl_croak(aTHX_ "Usage: Mob::SetSpecialAbilityParam(THIS, ability, param, value)");
{
Mob* THIS;
int ability = SvIV(ST(1));
int param = SvIV(ST(2));
int value = SvIV(ST(3));
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.");
THIS->SetSpecialAbilityParam(ability, param, value);
}
XSRETURN_EMPTY;
}
XS(XS_Mob_ClearSpecialAbilities); /* prototype to pass -Wmissing-prototypes */
XS(XS_Mob_ClearSpecialAbilities)
{
dXSARGS;
if(items != 1)
Perl_croak(aTHX_ "Usage: Mob::ClearSpecialAbilities(THIS)");
{
Mob* THIS;
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.");
THIS->ClearSpecialAbilities();
}
XSRETURN_EMPTY;
}
XS(XS_Mob_ProcessSpecialAbilities); /* prototype to pass -Wmissing-prototypes */
XS(XS_Mob_ProcessSpecialAbilities)
{
dXSARGS;
if(items != 2)
Perl_croak(aTHX_ "Usage: Mob::ProcessSpecialAbilities(THIS, str)");
{
Mob* THIS;
const char *str = (const char*)SvPV_nolen(ST(1));
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.");
THIS->ProcessSpecialAbilities(str);
}
XSRETURN_EMPTY;
}
XS(XS_Mob_CanClassEquipItem); /* prototype to pass -Wmissing-prototypes */
XS(XS_Mob_CanClassEquipItem)
{
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: Mob::CanClassEquipItem(THIS, item_id)");
{
Mob * THIS;
bool RETVAL;
uint32 item_id = (uint32)SvUV(ST(1));
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->CanClassEquipItem(item_id);
ST(0) = boolSV(RETVAL);
sv_2mortal(ST(0));
}
XSRETURN(1);
}
#ifdef __cplusplus
extern "C"
@@ -8288,7 +8512,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, "$");
@@ -8433,7 +8658,8 @@ XS(boot_Mob)
newXSproto(strcpy(buf, "SetRace"), XS_Mob_SetRace, file, "$$");
newXSproto(strcpy(buf, "SetGender"), XS_Mob_SetGender, file, "$$");
newXSproto(strcpy(buf, "SendIllusion"), XS_Mob_SendIllusion, file, "$$;$$$$$$$$$$$$");
newXSproto(strcpy(buf, "MakeTempPet"), XS_Mob_MakeTempPet, file, "$$;$$$");
newXSproto(strcpy(buf, "MakeTempPet"), XS_Mob_MakeTempPet, file, "$$;$$$$");
newXSproto(strcpy(buf, "TypesTempPet"), XS_Mob_TypesTempPet, file, "$$;$$$$$");
newXSproto(strcpy(buf, "QuestReward"), XS_Mob_QuestReward, file, "$$;$$$");
newXSproto(strcpy(buf, "CameraEffect"), XS_Mob_CameraEffect, file, "$$;$$$");
newXSproto(strcpy(buf, "SpellEffect"), XS_Mob_SpellEffect, file, "$$;$$$$$$");
@@ -8443,7 +8669,7 @@ XS(boot_Mob)
newXSproto(strcpy(buf, "TarGlobal"), XS_Mob_TarGlobal, file, "$$$$$$$");
newXSproto(strcpy(buf, "DelGlobal"), XS_Mob_DelGlobal, file, "$$");
newXSproto(strcpy(buf, "SetSlotTint"), XS_Mob_SetSlotTint, file, "$$$$$");
newXSproto(strcpy(buf, "WearChange"), XS_Mob_WearChange, file, "$$$;$");
newXSproto(strcpy(buf, "WearChange"), XS_Mob_WearChange, file, "$$$;$$");
newXSproto(strcpy(buf, "DoKnockback"), XS_Mob_DoKnockback, file, "$$$$");
newXSproto(strcpy(buf, "RemoveNimbusEffect"), XS_Mob_RemoveNimbusEffect, file, "$$");
newXSproto(strcpy(buf, "IsRunning"), XS_Mob_IsRunning, file, "$");
@@ -8466,11 +8692,17 @@ XS(boot_Mob)
newXSproto(strcpy(buf, "DoArcheryAttackDmg"), XS_Mob_DoArcheryAttackDmg, file, "$$$$$$$");
newXSproto(strcpy(buf, "DoThrowingAttackDmg"), XS_Mob_DoThrowingAttackDmg, file, "$$$$$$$");
newXSproto(strcpy(buf, "SetDisableMelee"), XS_Mob_SetDisableMelee, file, "$$");
newXSproto(strcpy(buf, "IsMeleeDisabled"), XS_Mob_IsMeleeDisabled, file, "$$");
newXSproto(strcpy(buf, "IsMeleeDisabled"), XS_Mob_IsMeleeDisabled, file, "$");
newXSproto(strcpy(buf, "SetFlurryChance"), XS_Mob_SetFlurryChance, file, "$$");
newXSproto(strcpy(buf, "GetFlurryChance"), XS_Mob_GetFlurryChance, file, "$");
newXSproto(strcpy(buf, "GetSpellStat"), XS_Mob_GetSpellStat, file, "$$$$");
newXSproto(strcpy(buf, "GetSpecialAbility"), XS_Mob_GetSpecialAbility, file, "$$");
newXSproto(strcpy(buf, "GetSpecialAbilityParam"), XS_Mob_GetSpecialAbilityParam, file, "$$$");
newXSproto(strcpy(buf, "SetSpecialAbility"), XS_Mob_SetSpecialAbility, file, "$$$");
newXSproto(strcpy(buf, "SetSpecialAbilityParam"), XS_Mob_SetSpecialAbilityParam, file, "$$$$");
newXSproto(strcpy(buf, "ClearSpecialAbilities"), XS_Mob_ClearSpecialAbilities, file, "$");
newXSproto(strcpy(buf, "ProcessSpecialAbilities"), XS_Mob_ProcessSpecialAbilities, file, "$$");
newXSproto(strcpy(buf, "CanClassEquipItem"), XS_Mob_CanClassEquipItem, file, "$$");
XSRETURN_YES;
}
+142 -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);
@@ -2119,6 +2120,32 @@ XS(XS_NPC_GetAttackSpeed)
XSRETURN(1);
}
XS(XS_NPC_GetAttackDelay); /* prototype to pass -Wmissing-prototypes */
XS(XS_NPC_GetAttackDelay)
{
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: NPC::GetAttackDelay(THIS)");
{
NPC * THIS;
float RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "NPC")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(NPC *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type NPC");
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetAttackDelay();
XSprePUSH; PUSHn((double)RETVAL);
}
XSRETURN(1);
}
XS(XS_NPC_GetAccuracyRating); /* prototype to pass -Wmissing-prototypes */
XS(XS_NPC_GetAccuracyRating)
{
@@ -2145,6 +2172,32 @@ XS(XS_NPC_GetAccuracyRating)
XSRETURN(1);
}
XS(XS_NPC_GetAvoidanceRating); /* prototype to pass -Wmissing-prototypes */
XS(XS_NPC_GetAvoidanceRating)
{
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: NPC::GetAvoidanceyRating(THIS)");
{
NPC * THIS;
int32 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "NPC")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(NPC *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type NPC");
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetAvoidanceRating();
XSprePUSH; PUSHu((UV)RETVAL);
}
XSRETURN(1);
}
XS(XS_NPC_GetSpawnKillCount); /* prototype to pass -Wmissing-prototypes */
XS(XS_NPC_GetSpawnKillCount)
{
@@ -2245,6 +2298,81 @@ XS(XS_NPC_GetMerchantProbability) {
XSRETURN(1);
}
XS(XS_NPC_AddMeleeProc);
XS(XS_NPC_AddMeleeProc) {
dXSARGS;
if (items != 3)
Perl_croak(aTHX_ "Usage: NPC::AddMeleeProc(THIS,spellid,chance)");
{
NPC * THIS;
int spell_id = (int)SvIV(ST(1));
int chance = (int)SvIV(ST(2));
dXSTARG;
if (sv_derived_from(ST(0), "NPC")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(NPC *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type NPC");
if(THIS == NULL)
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
THIS->AddProcToWeapon(spell_id, true, chance);
}
XSRETURN_EMPTY;
}
XS(XS_NPC_AddRangedProc);
XS(XS_NPC_AddRangedProc) {
dXSARGS;
if (items != 3)
Perl_croak(aTHX_ "Usage: NPC::AddRangedProc(THIS,spellid,chance)");
{
NPC * THIS;
int spell_id = (int)SvIV(ST(1));
int chance = (int)SvIV(ST(2));
dXSTARG;
if (sv_derived_from(ST(0), "NPC")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(NPC *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type NPC");
if(THIS == NULL)
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
THIS->AddDefensiveProc(spell_id,chance);
}
XSRETURN_EMPTY;
}
XS(XS_NPC_AddDefensiveProc);
XS(XS_NPC_AddDefensiveProc) {
dXSARGS;
if (items != 3)
Perl_croak(aTHX_ "Usage: NPC::AddDefensiveProc(THIS,spellid,chance)");
{
NPC * THIS;
int spell_id = (int)SvIV(ST(1));
int chance = (int)SvIV(ST(2));
dXSTARG;
if (sv_derived_from(ST(0), "NPC")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(NPC *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type NPC");
if(THIS == NULL)
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
THIS->AddProcToWeapon(spell_id, true, chance);
}
XSRETURN_EMPTY;
}
#ifdef __cplusplus
extern "C"
#endif
@@ -2342,11 +2470,16 @@ XS(boot_NPC)
newXSproto(strcpy(buf, "GetSpellFocusHeal"), XS_NPC_GetSpellFocusHeal, file, "$");
newXSproto(strcpy(buf, "GetSlowMitigation"), XS_NPC_GetSlowMitigation, file, "$");
newXSproto(strcpy(buf, "GetAttackSpeed"), XS_NPC_GetAttackSpeed, file, "$");
newXSproto(strcpy(buf, "GetAttackDelay"), XS_NPC_GetAttackDelay, file, "$");
newXSproto(strcpy(buf, "GetAccuracyRating"), XS_NPC_GetAccuracyRating, file, "$");
newXSproto(strcpy(buf, "GetAvoidanceRating"), XS_NPC_GetAvoidanceRating, file, "$");
newXSproto(strcpy(buf, "GetSpawnKillCount"), XS_NPC_GetSpawnKillCount, file, "$");
newXSproto(strcpy(buf, "GetScore"), XS_NPC_GetScore, file, "$");
newXSproto(strcpy(buf, "SetMerchantProbability"), XS_NPC_SetMerchantProbability, file, "$$");
newXSproto(strcpy(buf, "GetMerchantProbability"), XS_NPC_GetMerchantProbability, file, "$");
newXSproto(strcpy(buf, "AddMeleeProc"), XS_NPC_AddMeleeProc, file, "$$$");
newXSproto(strcpy(buf, "AddRangedProc"), XS_NPC_AddRangedProc, file, "$$$");
newXSproto(strcpy(buf, "AddDefensiveProc"), XS_NPC_AddDefensiveProc, file, "$$$");
XSRETURN_YES;
}
+106 -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
@@ -909,6 +909,107 @@ XS(XS_Object_SetEntityVariable)
XSRETURN_EMPTY;
}
XS(XS_Object_GetSolidType); /* prototype to pass -Wmissing-prototypes */
XS(XS_Object_GetSolidType)
{
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: Object::GetSolidType(THIS)");
{
Object * THIS;
uint16 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "Object")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(Object *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type Object");
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetSolidType();
XSprePUSH; PUSHu((UV)RETVAL);
}
XSRETURN(1);
}
XS(XS_Object_SetSolidType); /* prototype to pass -Wmissing-prototypes */
XS(XS_Object_SetSolidType)
{
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: Object::SetSolidType(THIS, type)");
{
Object * THIS;
uint16 type = (uint16)SvUV(ST(1));
if (sv_derived_from(ST(0), "Object")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(Object *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type Object");
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
THIS->SetSolidType(type);
}
XSRETURN_EMPTY;
}
XS(XS_Object_GetSize); /* prototype to pass -Wmissing-prototypes */
XS(XS_Object_GetSize)
{
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: Object::GetSize(THIS)");
{
Object * THIS;
uint16 RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "Object")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(Object *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type Object");
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetSize();
XSprePUSH; PUSHu((UV)RETVAL);
}
XSRETURN(1);
}
XS(XS_Object_SetSize); /* prototype to pass -Wmissing-prototypes */
XS(XS_Object_SetSize)
{
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: Object::SetSize(THIS, type)");
{
Object * THIS;
uint16 size = (uint16)SvUV(ST(1));
if (sv_derived_from(ST(0), "Object")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(Object *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type Object");
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
THIS->SetSize(size);
}
XSRETURN_EMPTY;
}
#ifdef __cplusplus
extern "C"
@@ -961,6 +1062,10 @@ XS(boot_Object)
newXSproto(strcpy(buf, "GetEntityVariable"), XS_Object_GetEntityVariable, file, "$$");
newXSproto(strcpy(buf, "SetEntityVariable"), XS_Object_SetEntityVariable, file, "$$$");
newXSproto(strcpy(buf, "EntityVariableExists"), XS_Object_EntityVariableExists, file, "$$");
newXSproto(strcpy(buf, "SetSolidType"),XS_Object_SetSolidType, file, "$$");
newXSproto(strcpy(buf, "GetSolidType"),XS_Object_GetSolidType, file, "$");
newXSproto(strcpy(buf, "SetSize"),XS_Object_SetSize, file, "$$");
newXSproto(strcpy(buf, "GetSize"),XS_Object_GetSize, file, "$");
XSRETURN_YES;
}
#endif //EMBPERL_XS_CLASSES
+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
+6 -6
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
@@ -208,7 +208,7 @@ XS(XS_Corpse_GetDBID)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetDBID();
RETVAL = THIS->GetCorpseDBID();
XSprePUSH; PUSHu((UV)RETVAL);
}
XSRETURN(1);
@@ -662,7 +662,7 @@ XS(XS_Corpse_CompleteRezz)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
THIS->CompleteRezz();
THIS->CompleteResurrection();
}
XSRETURN_EMPTY;
}
@@ -687,7 +687,7 @@ XS(XS_Corpse_CanMobLoot)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->CanMobLoot(charid);
RETVAL = THIS->CanPlayerLoot(charid);
ST(0) = boolSV(RETVAL);
sv_2mortal(ST(0));
}
@@ -723,7 +723,7 @@ XS(XS_Corpse_AllowMobLoot)
if(them == nullptr)
Perl_croak(aTHX_ "them is nullptr, avoiding crash.");
THIS->AllowMobLoot(them, slot);
THIS->AllowPlayerLoot(them, slot);
}
XSRETURN_EMPTY;
}
@@ -780,7 +780,7 @@ XS(XS_Corpse_IsRezzed)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->Rezzed();
RETVAL = THIS->IsRezzed();
ST(0) = boolSV(RETVAL);
sv_2mortal(ST(0));
}
+2 -2
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
@@ -160,7 +160,7 @@ XS(XS_QuestItem_IsAttuned)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->IsInstNoDrop();
RETVAL = THIS->IsAttuned();
ST(0) = boolSV(RETVAL);
sv_2mortal(ST(0));
}
+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;
+7 -22
View File
@@ -15,11 +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 <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>
#include "../common/global_define.h"
#include "../common/eqemu_logsys.h"
#include <string.h>
#ifdef _WINDOWS
#include <process.h>
@@ -32,16 +29,13 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
#endif
#include "../common/string_util.h"
#include "../common/packet_functions.h"
#include "../common/packet_dump.h"
#include "../common/packet_dump_file.h"
#include "../common/emu_opcodes.h"
#include "../common/eq_packet_structs.h"
#include "../common/servertalk.h"
#include "entity.h"
#include "masterentity.h"
#include "../common/string_util.h"
#include "entity.h"
#include "petitions.h"
#include "worldserver.h"
@@ -49,7 +43,6 @@ PetitionList petition_list;
extern WorldServer worldserver;
void Petition::SendPetitionToPlayer(Client* clientto) {
EQApplicationPacket* outapp = new EQApplicationPacket(OP_PetitionCheckout,sizeof(Petition_Struct));
Petition_Struct* pet = (Petition_Struct*) outapp->pBuffer;
@@ -219,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) {
@@ -233,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)
@@ -261,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
}
@@ -280,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;
}
+7 -4
View File
@@ -19,11 +19,14 @@
#define PETITIONS_H
#include "../common/linked_list.h"
#include "../common/types.h"
#include "zonedb.h"
#include "client.h"
#include "../common/mutex.h"
#include "../common/misc_functions.h"
#include "../common/mutex.h"
#include "../common/types.h"
#include "client.h"
#include "zonedb.h"
class Client;
class Petition
{
+94 -85
View File
@@ -15,30 +15,24 @@
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/spdat.h"
#include "masterentity.h"
#include "../common/packet_dump.h"
#include "../common/moremath.h"
#include "../common/item.h"
#include "zonedb.h"
#include "worldserver.h"
#include "../common/skills.h"
#include "../common/bodytypes.h"
#include "../common/classes.h"
#include "../common/string_util.h"
#include "../common/types.h"
#include "entity.h"
#include "client.h"
#include "mob.h"
#include "pets.h"
#include <math.h>
#include <assert.h>
#include "zonedb.h"
#ifndef WIN32
#include <stdlib.h>
#include "../common/unix.h"
#endif
#include "string_ids.h"
///////////////////////////////////////////////////////////////////////////////
// pet related functions
const char *GetRandPetName()
{
@@ -113,7 +107,7 @@ const char *GetRandPetName()
"Zibann","Zibarer","Zibartik","Zibekn","Zibn","Zibobn","Zobaner","Zobann",
"Zobarn","Zober","Zobn","Zonanab","Zonaner","Zonann","Zonantik","Zonarer",
"Zonartik","Zonobn","Zonobtik","Zontik","Ztik" };
int r = MakeRandomInt(0, (sizeof(petnames)/sizeof(const char *))-1);
int r = zone->random.Int(0, (sizeof(petnames)/sizeof(const char *))-1);
printf("Pet being created: %s\n",petnames[r]); // DO NOT COMMENT THIS OUT!
return petnames[r];
}
@@ -234,7 +228,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
int16 act_power = 0; // The actual pet power we'll use.
if (petpower == -1) {
if (this->IsClient()) {
act_power = CastToClient()->GetFocusEffect(focusPetPower, spell_id);
act_power = CastToClient()->GetFocusEffect(focusPetPower, spell_id);//Client only
act_power = CastToClient()->mod_pet_power(act_power, spell_id);
}
}
@@ -249,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;
}
@@ -257,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;
}
@@ -367,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);
@@ -399,8 +392,9 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
npc_type->gender = monster->gender;
npc_type->luclinface = monster->luclinface;
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);
}
@@ -423,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,12 +426,26 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
entity_list.AddNPC(npc, true, true);
SetPetID(npc->GetID());
// We need to handle PetType 5 (petHatelist), add the current target to the hatelist of the pet
if (record.petcontrol == petTargetLock)
{
Mob* target = GetTarget();
if (target){
npc->AddToHateList(target, 1);
npc->SetPetTargetLockID(target->GetID());
npc->SetSpecialAbility(IMMUNE_AGGRO, 1);
}
else
npc->Kill(); //On live casts spell 892 Unsummon (Kayen - Too limiting to use that for emu since pet can have more than 20k HP)
}
}
/* This is why the pets ghost - pets were being spawned too far away from its npc owner and some
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;
@@ -443,6 +453,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) {
@@ -454,31 +466,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() {
@@ -658,41 +670,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;
+35 -21
View File
@@ -1,28 +1,42 @@
#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 Pet : public NPC {
class Mob;
struct NPCType;
class Pet : public NPC {
public:
Pet(NPCType *type_data, Mob *owner, PetType type, uint16 spell_id, int16 power);

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