Hopefully completely merged from master in what is the biggest merge ever

This commit is contained in:
KimLS
2014-12-07 13:23:16 -08:00
513 changed files with 68160 additions and 63864 deletions
+22 -21
View File
@@ -1,7 +1,7 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
SET(zone_sources
AA.cpp
aa.cpp
aggro.cpp
attack.cpp
beacon.cpp
@@ -16,7 +16,7 @@ SET(zone_sources
command.cpp
corpse.cpp
doors.cpp
effects.cpp
effects.cpp
embparser.cpp
embparser_api.cpp
embperl.cpp
@@ -69,12 +69,12 @@ SET(zone_sources
map.cpp
merc.cpp
mob.cpp
MobAI.cpp
mob_ai.cpp
mod_functions.cpp
net.cpp
npc.cpp
NpcAI.cpp
Object.cpp
npc_ai.cpp
object.cpp
oriented_bounding_box.cpp
pathing.cpp
perl_client.cpp
@@ -86,17 +86,18 @@ SET(zone_sources
perl_npc.cpp
perl_object.cpp
perl_perlpacket.cpp
perl_PlayerCorpse.cpp
perl_player_corpse.cpp
perl_questitem.cpp
perl_raids.cpp
perlpacket.cpp
petitions.cpp
pets.cpp
QGlobals.cpp
qglobals.cpp
queryserv.cpp
questmgr.cpp
QuestParserCollection.cpp
quest_parser_collection.cpp
raids.cpp
RaycastMesh.cpp
raycast_mesh.cpp
remote_call.cpp
remote_call_subscribe.cpp
spawn2.cpp
@@ -118,18 +119,17 @@ SET(zone_sources
worldserver.cpp
zone.cpp
zone_logsys.cpp
ZoneConfig.cpp
zone_config.cpp
zonedb.cpp
zonedbasync.cpp
zoning.cpp
)
SET(zone_headers
AA.h
aa.h
basic_functions.h
beacon.h
bot.h
botStructs.h
bot_structs.h
client.h
client_logs.h
client_packet.h
@@ -177,27 +177,29 @@ SET(zone_headers
mob.h
net.h
npc.h
NpcAI.h
npc_ai.h
object.h
oriented_bounding_box.h
pathing.h
perlpacket.h
petitions.h
pets.h
QGlobals.h
QuestInterface.h
qglobals.h
quest_interface.h
queryserv.h
quest_interface.h
questmgr.h
QuestParserCollection.h
quest_parser_collection.h
raid.h
raids.h
RaycastMesh.h
raycast_mesh.h
remote_call.h
remote_call_subscribe.h
skills.h
spawn2.cpp
spawn2.h
spawngroup.h
StringIDs.h
string_ids.h
tasks.h
titles.h
trap.h
@@ -206,9 +208,8 @@ SET(zone_headers
water_map_v2.h
worldserver.h
zone.h
ZoneConfig.h
zone_config.h
zonedb.h
zonedbasync.h
zonedump.h
)
File diff suppressed because it is too large Load Diff
+3 -2
View File
@@ -2,7 +2,8 @@
#ifndef AA_H
#define AA_H
#include "../common/eq_packet_structs.h"
struct AA_Ability;
struct SendAA_Struct;
#define MANA_BURN 664
@@ -2134,7 +2135,7 @@ struct AALevelCost_Struct
uint32 Cost;
};
//assumes that no activatable AA has more than 5 ranks
//assumes that no activatable aa.has more than 5 ranks
#define MAX_AA_ACTION_RANKS 20
extern AA_DBAction AA_Actions[aaHighestID][MAX_AA_ACTION_RANKS]; //[aaid][rank]
extern std::map<uint16, AA_SwarmPet> AA_SwarmPets; //key=spell_id
+32 -3
View File
@@ -23,9 +23,9 @@
#include "map.h"
#include "../common/spdat.h"
#include "../common/skills.h"
#include "../common/MiscFunctions.h"
#include "../common/misc_functions.h"
#include "../common/rulesys.h"
#include "StringIDs.h"
#include "string_ids.h"
#include <iostream>
extern Zone* zone;
@@ -873,7 +873,34 @@ bool Mob::CombatRange(Mob* other)
if (size_mod > 10000)
size_mod = size_mod / 7;
if (DistNoRoot(*other) <= size_mod)
float _DistNoRoot = DistNoRoot(*other);
if (GetSpecialAbility(NPC_CHASE_DISTANCE)){
bool DoLoSCheck = true;
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))
DoLoSCheck = false; //Ignore line of sight check
if (max_dist == 1)
max_dist = 250.0f; //Default it to 250 if you forget to put a value
max_dist = max_dist * max_dist;
if (!min_dist)
min_dist = size_mod; //Default to melee range
else
min_dist = min_dist * min_dist;
if ((DoLoSCheck && CheckLastLosState()) && (_DistNoRoot >= min_dist && _DistNoRoot <= max_dist))
SetPseudoRoot(true);
else
SetPseudoRoot(false);
}
if (_DistNoRoot <= size_mod)
{
return true;
}
@@ -887,6 +914,8 @@ bool Mob::CheckLosFN(Mob* other) {
if(other)
Result = CheckLosFN(other->GetX(), other->GetY(), other->GetZ(), other->GetSize());
SetLastLosState(Result);
return Result;
}
+330 -136
View File
@@ -21,28 +21,25 @@
#endif
#include "../common/debug.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <iostream>
#include <assert.h>
#include "masterentity.h"
#include "NpcAI.h"
#include "../common/packet_dump.h"
#include "../common/eq_packet_structs.h"
#include "../common/eq_constants.h"
#include "../common/eq_packet_structs.h"
#include "../common/rulesys.h"
#include "../common/skills.h"
#include "../common/spdat.h"
#include "zone.h"
#include "StringIDs.h"
#include "../common/StringUtil.h"
#include "../common/rulesys.h"
#include "QuestParserCollection.h"
#include "../common/string_util.h"
#include "queryserv.h"
#include "quest_parser_collection.h"
#include "string_ids.h"
#include "water_map.h"
#include "worldserver.h"
#include "remote_call_subscribe.h"
#include "zone.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
extern QueryServ* QServ;
extern WorldServer worldserver;
#ifdef _WINDOWS
@@ -449,19 +446,16 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte)
&& (other->InFrontMob(this, other->GetX(), other->GetY()) || bShieldBlockFromRear)) {
float bonusShieldBlock = 0.0f;
bonusShieldBlock = aabonuses.ShieldBlock + spellbonuses.ShieldBlock + itembonuses.ShieldBlock;
bonusShieldBlock = static_cast<float>(aabonuses.ShieldBlock + spellbonuses.ShieldBlock + itembonuses.ShieldBlock);
RollTable[1] += bonusShieldBlock;
}
if(damage > 0 && (aabonuses.TwoHandBluntBlock || spellbonuses.TwoHandBluntBlock || itembonuses.TwoHandBluntBlock)
if(IsClient() && damage > 0 && (aabonuses.TwoHandBluntBlock || spellbonuses.TwoHandBluntBlock || itembonuses.TwoHandBluntBlock)
&& (other->InFrontMob(this, other->GetX(), other->GetY()) || bShieldBlockFromRear)) {
bool equiped2 = CastToClient()->m_inv.GetItem(MainPrimary);
if(equiped2) {
uint8 TwoHandBlunt = CastToClient()->m_inv.GetItem(MainPrimary)->GetItem()->ItemType;
if(CastToClient()->m_inv.GetItem(MainPrimary)) {
float bonusStaffBlock = 0.0f;
if(TwoHandBlunt == ItemType2HBlunt) {
bonusStaffBlock = aabonuses.TwoHandBluntBlock + spellbonuses.TwoHandBluntBlock + itembonuses.TwoHandBluntBlock;
if (CastToClient()->m_inv.GetItem(MainPrimary)->GetItem()->ItemType == ItemType2HBlunt){
bonusStaffBlock = static_cast<float>(aabonuses.TwoHandBluntBlock + spellbonuses.TwoHandBluntBlock + itembonuses.TwoHandBluntBlock);
RollTable[1] += bonusStaffBlock;
}
}
@@ -666,7 +660,7 @@ void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttac
////////////////////////////////////////////////////////
// Scorpious2k: Include AC in the calculation
// use serverop variables to set values
int myac = GetAC();
int32 myac = GetAC();
if(opts) {
myac *= (1.0f - opts->armor_pen_percent);
myac -= opts->armor_pen_flat;
@@ -697,7 +691,7 @@ void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttac
}
if (acreduction>0) {
damage -= (int) (GetAC() * acreduction/100.0f);
damage -= (int32) (GetAC() * acreduction/100.0f);
}
if (acrandom>0) {
damage -= (myac * MakeRandomInt(0, acrandom) / 10000);
@@ -1286,15 +1280,18 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
mlog(COMBAT__DAMAGE, "Damage calculated to %d (min %d, max %d, str %d, skill %d, DMG %d, lv %d)",
damage, min_hit, max_hit, GetSTR(), GetSkill(skillinuse), weapon_damage, mylevel);
int hit_chance_bonus = 0;
if(opts) {
damage *= opts->damage_percent;
damage += opts->damage_flat;
hate *= opts->hate_percent;
hate += opts->hate_flat;
hit_chance_bonus += opts->hit_chance;
}
//check to see if we hit..
if(!other->CheckHitChance(this, skillinuse, Hand)) {
if(!other->CheckHitChance(this, skillinuse, Hand, hit_chance_bonus)) {
mlog(COMBAT__ATTACKS, "Attack missed. Damage set to 0.");
damage = 0;
} else { //we hit, try to avoid it
@@ -1314,7 +1311,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
if (Hand == MainSecondary) {// Do we even have it & was attack with mainhand? If not, don't bother with other calculations
//Live AA - SlipperyAttacks
//This spell effect most likely directly modifies the actual riposte chance when using offhand attack.
int16 OffhandRiposteFail = aabonuses.OffhandRiposteFail + itembonuses.OffhandRiposteFail + spellbonuses.OffhandRiposteFail;
int32 OffhandRiposteFail = aabonuses.OffhandRiposteFail + itembonuses.OffhandRiposteFail + spellbonuses.OffhandRiposteFail;
OffhandRiposteFail *= -1; //Live uses a negative value for this.
if (OffhandRiposteFail &&
@@ -1332,7 +1329,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
}
if (((damage < 0) || slippery_attack) && !bRiposte && !IsStrikethrough) { // Hack to still allow Strikethrough chance w/ Slippery Attacks AA
int16 bonusStrikeThrough = itembonuses.StrikeThrough + spellbonuses.StrikeThrough + aabonuses.StrikeThrough;
int32 bonusStrikeThrough = itembonuses.StrikeThrough + spellbonuses.StrikeThrough + aabonuses.StrikeThrough;
if(bonusStrikeThrough && (MakeRandomInt(0, 100) < bonusStrikeThrough)) {
Message_StringID(MT_StrikeThrough, STRIKETHROUGH_STRING); // You strike through your opponents defenses!
@@ -1360,11 +1357,8 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
MeleeLifeTap(damage);
if (damage > 0){
CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess);
if (HasSkillProcSuccess() && other && other->GetHP() > 0)
TrySkillProc(other, skillinuse, 0, true, Hand);
}
if (damage > 0 && HasSkillProcSuccess() && other && other->GetHP() > 0)
TrySkillProc(other, skillinuse, 0, true, Hand);
CommonBreakInvisible();
@@ -1403,7 +1397,7 @@ void Client::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes att
}
// cut all PVP spell damage to 2/3 -solar
// EverHood - Blasting ourselfs is considered PvP
// Blasting ourselfs is considered PvP
//Don't do PvP mitigation if the caster is damaging himself
if(other && other->IsClient() && (other != this) && damage > 0) {
int PvPMitigation = 100;
@@ -1456,14 +1450,14 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
int exploss = 0;
mlog(COMBAT__HITS, "Fatal blow dealt by %s with %d damage, spell %d, skill %d", killerMob ? killerMob->GetName() : "Unknown", damage, spell, attack_skill);
//
// #1: Send death packet to everyone
//
/*
#1: Send death packet to everyone
*/
uint8 killed_level = GetLevel();
SendLogoutPackets();
//make our become corpse packet, and queue to ourself before OP_Death.
/* Make self become corpse packet */
EQApplicationPacket app2(OP_BecomeCorpse, sizeof(BecomeCorpse_Struct));
BecomeCorpse_Struct* bc = (BecomeCorpse_Struct*)app2.pBuffer;
bc->spawn_id = GetID();
@@ -1472,7 +1466,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
bc->z = GetZ();
QueuePacket(&app2);
// make death packet
/* Make Death Packet */
EQApplicationPacket app(OP_Death, sizeof(Death_Struct));
Death_Struct* d = (Death_Struct*)app.pBuffer;
d->spawn_id = GetID();
@@ -1485,9 +1479,9 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
app.priority = 6;
entity_list.QueueClients(this, &app);
//
// #2: figure out things that affect the player dying and mark them dead
//
/*
#2: figure out things that affect the player dying and mark them dead
*/
InterruptSpell();
SetPet(0);
@@ -1542,9 +1536,9 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
//remove ourself from all proximities
ClearAllProximities();
//
// #3: exp loss and corpse generation
//
/*
#3: exp loss and corpse generation
*/
// figure out if they should lose exp
if(RuleB(Character, UseDeathExpLossMult)){
@@ -1629,14 +1623,14 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
database.GetVariable("PvPitem", tmp2, 9);
int pvpitem = atoi(tmp2);
if(pvpitem>0 && pvpitem<200000)
new_corpse->SetPKItem(pvpitem);
new_corpse->SetPlayerKillItemID(pvpitem);
}
else if(reward==2)
new_corpse->SetPKItem(-1);
new_corpse->SetPlayerKillItemID(-1);
else if(reward==1)
new_corpse->SetPKItem(1);
new_corpse->SetPlayerKillItemID(1);
else
new_corpse->SetPKItem(0);
new_corpse->SetPlayerKillItemID(0);
if(killerMob->CastToClient()->isgrouped) {
Group* group = entity_list.GetGroupByClient(killerMob->CastToClient());
if(group != 0)
@@ -1645,7 +1639,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
{
if(group->members[i] != nullptr)
{
new_corpse->AllowMobLoot(group->members[i],i);
new_corpse->AllowPlayerLoot(group->members[i],i);
}
}
}
@@ -1660,27 +1654,21 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
LeftCorpse = true;
}
// if(!IsLD())//Todo: make it so an LDed client leaves corpse if its enabled
// MakeCorpse(exploss);
} else {
BuffFadeDetrimental();
}
//
// Finally, send em home
//
/*
Finally, send em home
// we change the mob variables, not pp directly, because Save() will copy
// from these and overwrite what we set in pp anyway
//
We change the mob variables, not pp directly, because Save() will copy
from these and overwrite what we set in pp anyway
*/
if(LeftCorpse && (GetClientVersionBit() & BIT_SoFAndLater) && RuleB(Character, RespawnFromHover))
{
ClearDraggedCorpses();
RespawnFromHoverTimer.Start(RuleI(Character, RespawnFromHoverTimer) * 1000);
ClearDraggedCorpses();
RespawnFromHoverTimer.Start(RuleI(Character, RespawnFromHoverTimer) * 1000);
SendRespawnBinds();
}
else
@@ -1697,17 +1685,22 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
if(r)
r->MemberZoned(this);
dead_timer.Start(5000, true);
dead_timer.Start(5000, true);
m_pp.zone_id = m_pp.binds[0].zoneId;
m_pp.zoneInstance = 0;
database.MoveCharacterToZone(this->CharacterID(), database.GetZoneName(m_pp.zone_id));
Save();
m_pp.zoneInstance = m_pp.binds[0].instance_id;
database.MoveCharacterToZone(this->CharacterID(), database.GetZoneName(m_pp.zone_id));
Save();
GoToDeath();
}
/* QS: PlayerLogDeaths */
if (RuleB(QueryServ, PlayerLogDeaths)){
const char * killer_name = "";
if (killerMob && killerMob->GetCleanName()){ killer_name = killerMob->GetCleanName(); }
std::string event_desc = StringFormat("Died in zoneid:%i instid:%i by '%s', spellid:%i, damage:%i", this->GetZoneID(), this->GetInstanceID(), killer_name, spell, damage);
QServ->PlayerLogEvent(Player_Log_Deaths, this->CharacterID(), event_desc);
}
parse->EventPlayer(EVENT_DEATH_COMPLETE, this, buffer, 0);
return true;
}
@@ -1820,7 +1813,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
//ele and bane dmg too
//NPCs add this differently than PCs
//if NPCs can't inheriently hit the target we don't add bane/magic dmg which isn't exactly the same as PCs
uint16 eleBane = 0;
uint32 eleBane = 0;
if(weapon){
if(weapon->BaneDmgBody == other->GetBodyType()){
eleBane += weapon->BaneDmgAmt;
@@ -1889,14 +1882,18 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
other->AddToHateList(this, hate);
} else {
int hit_chance_bonus = 0;
if(opts) {
damage *= opts->damage_percent;
damage += opts->damage_flat;
hate *= opts->hate_percent;
hate += opts->hate_flat;
hit_chance_bonus += opts->hit_chance;
}
if(!other->CheckHitChance(this, skillinuse, Hand)) {
if(!other->CheckHitChance(this, skillinuse, Hand, hit_chance_bonus)) {
damage = 0; //miss
} else { //hit, check for damage avoidance
other->AvoidDamage(this, damage);
@@ -2058,6 +2055,13 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
}
SetHP(0);
SetPet(0);
if (GetSwarmOwner()){
Mob* owner = entity_list.GetMobID(GetSwarmOwner());
if (owner)
owner->SetTempPetCount(owner->GetTempPetCount() - 1);
}
Mob* killer = GetHateDamageTop(this);
entity_list.RemoveFromTargets(this, p_depop);
@@ -2120,7 +2124,7 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
give_exp_client = give_exp->CastToClient();
bool IsLdonTreasure = (this->GetClass() == LDON_TREASURE);
if (give_exp_client && !IsCorpse() && MerchantType == 0)
if (give_exp_client && !IsCorpse())
{
Group *kg = entity_list.GetGroupByClient(give_exp_client);
Raid *kr = entity_list.GetRaidByClient(give_exp_client);
@@ -2130,15 +2134,19 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
if(kr)
{
if(!IsLdonTreasure) {
if(!IsLdonTreasure && MerchantType == 0) {
kr->SplitExp((finalxp), this);
if(killerMob && (kr->IsRaidMember(killerMob->GetName()) || kr->IsRaidMember(killerMob->GetUltimateOwner()->GetName())))
killerMob->TrySpellOnKill(killed_level,spell);
}
/* Send the EVENT_KILLED_MERIT event for all raid members */
for (int i = 0; i < MAX_RAID_MEMBERS; i++) {
if (kr->members[i].member != nullptr) { // If Group Member is Client
parse->EventNPC(EVENT_KILLED_MERIT, this, kr->members[i].member, "killed", 0);
if (kr->members[i].member != nullptr && kr->members[i].member->IsClient()) { // If Group Member is Client
Client *c = kr->members[i].member;
parse->EventNPC(EVENT_KILLED_MERIT, this, c, "killed", 0);
if(RuleB(NPC, EnableMeritBasedFaction))
c->SetFactionLevel(c->CharacterID(), GetNPCFactionID(), c->GetBaseClass(), c->GetBaseRace(), c->GetDeity());
mod_npc_killed_merit(kr->members[i].member);
@@ -2157,7 +2165,7 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
QS->s1.ZoneID = this->GetZoneID();
QS->s1.Type = 2; // Raid Fight
for (int i = 0; i < MAX_RAID_MEMBERS; i++) {
if (kr->members[i].member != nullptr) { // If Group Member is Client
if (kr->members[i].member != nullptr && kr->members[i].member->IsClient()) { // If Group Member is Client
Client *c = kr->members[i].member;
QS->Chars[PlayerCount].char_id = c->CharacterID();
PlayerCount++;
@@ -2171,7 +2179,7 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
}
else if (give_exp_client->IsGrouped() && kg != nullptr)
{
if(!IsLdonTreasure) {
if(!IsLdonTreasure && MerchantType == 0) {
kg->SplitExp((finalxp), this);
if(killerMob && (kg->IsGroupMember(killerMob->GetName()) || kg->IsGroupMember(killerMob->GetUltimateOwner()->GetName())))
killerMob->TrySpellOnKill(killed_level,spell);
@@ -2183,6 +2191,9 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
Client *c = kg->members[i]->CastToClient();
parse->EventNPC(EVENT_KILLED_MERIT, this, c, "killed", 0);
if(RuleB(NPC, EnableMeritBasedFaction))
c->SetFactionLevel(c->CharacterID(), GetNPCFactionID(), c->GetBaseClass(), c->GetBaseRace(), c->GetDeity());
mod_npc_killed_merit(c);
if(RuleB(TaskSystem, EnableTaskSystem))
@@ -2214,14 +2225,13 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
}
else
{
if(!IsLdonTreasure) {
if(!IsLdonTreasure && MerchantType == 0) {
int conlevel = give_exp->GetLevelCon(GetLevel());
if (conlevel != CON_GREEN)
{
if(GetOwner() && GetOwner()->IsClient()){
}
else {
give_exp_client->AddEXP((finalxp), conlevel); // Pyro: Comment this if NPC death crashes zone
if(!GetOwner() || (GetOwner() && !GetOwner()->IsClient()))
{
give_exp_client->AddEXP((finalxp), conlevel);
if(killerMob && (killerMob->GetID() == give_exp_client->GetID() || killerMob->GetUltimateOwner()->GetID() == give_exp_client->GetID()))
killerMob->TrySpellOnKill(killed_level,spell);
}
@@ -2230,6 +2240,10 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
/* Send the EVENT_KILLED_MERIT event */
parse->EventNPC(EVENT_KILLED_MERIT, this, give_exp_client, "killed", 0);
if(RuleB(NPC, EnableMeritBasedFaction))
give_exp_client->SetFactionLevel(give_exp_client->CharacterID(), GetNPCFactionID(), give_exp_client->GetBaseClass(),
give_exp_client->GetBaseRace(), give_exp_client->GetDeity());
mod_npc_killed_merit(give_exp_client);
if(RuleB(TaskSystem, EnableTaskSystem))
@@ -2253,7 +2267,7 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
}
//do faction hits even if we are a merchant, so long as a player killed us
if(give_exp_client)
if(give_exp_client && !RuleB(NPC, EnableMeritBasedFaction))
hate_list.DoFactionHits(GetNPCFactionID());
if (!HasOwner() && !IsMerc() && class_ != MERCHANT && class_ != ADVENTUREMERCHANT && !GetSwarmInfo()
@@ -2281,13 +2295,13 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
if(killer != 0 && emoteid != 0)
corpse->CastToNPC()->DoNPCEmote(AFTERDEATH, emoteid);
if(killer != 0 && killer->IsClient()) {
corpse->AllowMobLoot(killer, 0);
corpse->AllowPlayerLoot(killer, 0);
if(killer->IsGrouped()) {
Group* group = entity_list.GetGroupByClient(killer->CastToClient());
if(group != 0) {
for(int i=0;i<6;i++) { // Doesnt work right, needs work
if(group->members[i] != nullptr) {
corpse->AllowMobLoot(group->members[i],i);
corpse->AllowPlayerLoot(group->members[i],i);
}
}
}
@@ -2303,30 +2317,30 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
case 0:
case 1:
if(r->members[x].member && r->members[x].IsRaidLeader){
corpse->AllowMobLoot(r->members[x].member, i);
corpse->AllowPlayerLoot(r->members[x].member, i);
i++;
}
break;
case 2:
if(r->members[x].member && r->members[x].IsRaidLeader){
corpse->AllowMobLoot(r->members[x].member, i);
corpse->AllowPlayerLoot(r->members[x].member, i);
i++;
}
else if(r->members[x].member && r->members[x].IsGroupLeader){
corpse->AllowMobLoot(r->members[x].member, i);
corpse->AllowPlayerLoot(r->members[x].member, i);
i++;
}
break;
case 3:
if(r->members[x].member && r->members[x].IsLooter){
corpse->AllowMobLoot(r->members[x].member, i);
corpse->AllowPlayerLoot(r->members[x].member, i);
i++;
}
break;
case 4:
if(r->members[x].member)
{
corpse->AllowMobLoot(r->members[x].member, i);
corpse->AllowPlayerLoot(r->members[x].member, i);
i++;
}
break;
@@ -2420,7 +2434,7 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp,
AddRampage(other);
int hatemod = 100 + other->spellbonuses.hatemod + other->itembonuses.hatemod + other->aabonuses.hatemod;
int16 shieldhatemod = other->spellbonuses.ShieldEquipHateMod + other->itembonuses.ShieldEquipHateMod + other->aabonuses.ShieldEquipHateMod;
int32 shieldhatemod = other->spellbonuses.ShieldEquipHateMod + other->itembonuses.ShieldEquipHateMod + other->aabonuses.ShieldEquipHateMod;
if (shieldhatemod && other->HasShieldEquiped())
hatemod += shieldhatemod;
@@ -2542,6 +2556,10 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp,
if (myowner->IsAIControlled() && !myowner->GetSpecialAbility(IMMUNE_AGGRO))
myowner->hate_list.Add(other, 0, 0, bFrenzy);
}
if (other->GetTempPetCount())
entity_list.AddTempPetsToHateList(other, this, bFrenzy);
if (!wasengaged) {
if(IsNPC() && other->IsClient() && other->CastToClient())
parse->EventNPC(EVENT_AGGRO, this->CastToNPC(), other, "", 0);
@@ -2596,7 +2614,7 @@ void Mob::DamageShield(Mob* attacker, bool spell_ds) {
//Spell data for damage shield mitigation shows a negative value for spells for clients and positive
//value for spells that effect pets. Unclear as to why. For now will convert all positive to be consistent.
if (attacker->IsOffHandAtk()){
int16 mitigation = attacker->itembonuses.DSMitigationOffHand +
int32 mitigation = attacker->itembonuses.DSMitigationOffHand +
attacker->spellbonuses.DSMitigationOffHand +
attacker->aabonuses.DSMitigationOffHand;
DS -= DS*mitigation/100;
@@ -3326,7 +3344,10 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
if(damage < 1)
return 0;
//Regular runes absorb spell damage (except dots) - Confirmed on live.
if (spellbonuses.MeleeRune[0] && spellbonuses.MeleeRune[1] >= 0)
damage = RuneAbsorb(damage, SE_Rune);
if (spellbonuses.AbsorbMagicAtt[0] && spellbonuses.AbsorbMagicAtt[1] >= 0)
damage = RuneAbsorb(damage, SE_AbsorbMagicAtt);
@@ -3342,10 +3363,13 @@ int32 Mob::ReduceAllDamage(int32 damage)
if(damage <= 0)
return damage;
if(spellbonuses.ManaAbsorbPercentDamage[0] && (GetMana() > damage * spellbonuses.ManaAbsorbPercentDamage[0] / 100)) {
damage -= (damage * spellbonuses.ManaAbsorbPercentDamage[0] / 100);
SetMana(GetMana() - damage);
TryTriggerOnValueAmount(false, true);
if(spellbonuses.ManaAbsorbPercentDamage[0]) {
int32 mana_reduced = damage * spellbonuses.ManaAbsorbPercentDamage[0] / 100;
if (GetMana() >= mana_reduced){
damage -= mana_reduced;
SetMana(GetMana() - mana_reduced);
TryTriggerOnValueAmount(false, true);
}
}
CheckNumHitsRemaining(NUMHIT_IncomingDamage);
@@ -3399,7 +3423,7 @@ bool Mob::HasRangedProcs() const
bool Client::CheckDoubleAttack(bool tripleAttack) {
//Check for bonuses that give you a double attack chance regardless of skill (ie Bestial Frenzy/Harmonious Attack AA)
uint16 bonusGiveDA = aabonuses.GiveDoubleAttack + spellbonuses.GiveDoubleAttack + itembonuses.GiveDoubleAttack;
uint32 bonusGiveDA = aabonuses.GiveDoubleAttack + spellbonuses.GiveDoubleAttack + itembonuses.GiveDoubleAttack;
if(!HasSkill(SkillDoubleAttack) && !bonusGiveDA)
return false;
@@ -3408,7 +3432,7 @@ bool Client::CheckDoubleAttack(bool tripleAttack) {
uint16 skill = GetSkill(SkillDoubleAttack);
int16 bonusDA = aabonuses.DoubleAttackChance + spellbonuses.DoubleAttackChance + itembonuses.DoubleAttackChance;
int32 bonusDA = aabonuses.DoubleAttackChance + spellbonuses.DoubleAttackChance + itembonuses.DoubleAttackChance;
//Use skill calculations otherwise, if you only have AA applied GiveDoubleAttack chance then use that value as the base.
if (skill)
@@ -3422,7 +3446,7 @@ bool Client::CheckDoubleAttack(bool tripleAttack) {
//Kayen: Need to decide if we can implement triple attack skill before working in over the cap effect.
if(tripleAttack) {
// Only some Double Attack classes get Triple Attack [This is already checked in client_processes.cpp]
int16 triple_bonus = spellbonuses.TripleAttackChance + itembonuses.TripleAttackChance;
int32 triple_bonus = spellbonuses.TripleAttackChance + itembonuses.TripleAttackChance;
chance *= 0.2f; //Baseline chance is 20% of your double attack chance.
chance *= float(100.0f+triple_bonus)/100.0f; //Apply modifiers.
}
@@ -3435,7 +3459,7 @@ bool Client::CheckDoubleAttack(bool tripleAttack) {
bool Client::CheckDoubleRangedAttack() {
int16 chance = spellbonuses.DoubleRangedAttack + itembonuses.DoubleRangedAttack + aabonuses.DoubleRangedAttack;
int32 chance = spellbonuses.DoubleRangedAttack + itembonuses.DoubleRangedAttack + aabonuses.DoubleRangedAttack;
if(chance && (MakeRandomInt(0, 100) < chance))
return true;
@@ -3527,7 +3551,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
if(spell_id == SPELL_UNKNOWN) {
damage = ReduceDamage(damage);
mlog(COMBAT__HITS, "Melee Damage reduced to %d", damage);
ReduceAllDamage(damage);
damage = ReduceAllDamage(damage);
TryTriggerThreshHold(damage, SE_TriggerMeleeThreshold, attacker);
} else {
int32 origdmg = damage;
@@ -3540,7 +3564,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
//Kayen: Probably need to add a filter for this - Not sure if this msg is correct but there should be a message for spell negate/runes.
Message(263, "%s tries to cast on YOU, but YOUR magical skin absorbs the spell.",attacker->GetCleanName());
}
ReduceAllDamage(damage);
damage = ReduceAllDamage(damage);
TryTriggerThreshHold(damage, SE_TriggerSpellThreshold, attacker);
}
@@ -3582,12 +3606,12 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
TryTriggerOnValueAmount(true);
//fade mez if we are mezzed
if (IsMezzed()) {
if (IsMezzed() && attacker) {
mlog(COMBAT__HITS, "Breaking mez due to attack.");
entity_list.MessageClose_StringID(this, true, 100, MT_WornOff,
HAS_BEEN_AWAKENED, GetCleanName(), attacker->GetCleanName());
BuffFadeByEffect(SE_Mez);
}
}
//check stun chances if bashing
if (damage > 0 && ((skill_used == SkillBash || skill_used == SkillKick) && attacker)) {
@@ -3775,7 +3799,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
safe_delete(outapp);
} else {
//else, it is a buff tic...
// Everhood - So we can see our dot dmg like live shows it.
// So we can see our dot dmg like live shows it.
if(spell_id != SPELL_UNKNOWN && damage > 0 && attacker && attacker != this && attacker->IsClient()) {
//might filter on (attack_skill>200 && attack_skill<250), but I dont think we need it
attacker->FilteredMessage_StringID(attacker, MT_DoTDamage, FilterDOT,
@@ -3867,7 +3891,7 @@ float Mob::GetProcChances(float ProcBonus, uint16 hand)
int mydex = GetDEX();
float ProcChance = 0.0f;
uint16 weapon_speed = GetWeaponSpeedbyHand(hand);
uint32 weapon_speed = GetWeaponSpeedbyHand(hand);
if (RuleB(Combat, AdjustProcPerMinute)) {
ProcChance = (static_cast<float>(weapon_speed) *
@@ -3893,7 +3917,7 @@ float Mob::GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 h
ProcBonus = 0;
ProcChance = 0;
uint16 weapon_speed = GetWeaponSpeedbyHand(hand);
uint32 weapon_speed = GetWeaponSpeedbyHand(hand);
ProcChance = (static_cast<float>(weapon_speed) * RuleR(Combat, AvgDefProcsPerMinute) / 60000.0f); // compensate for weapon_speed being in ms
ProcBonus += static_cast<float>(myagi) * RuleR(Combat, DefProcPerMinAgiContrib) / 100.0f;
@@ -4148,7 +4172,7 @@ void Mob::TryPetCriticalHit(Mob *defender, uint16 skill, int32 &damage)
Mob *owner = nullptr;
float critChance = 0.0f;
critChance += RuleI(Combat, MeleeBaseCritChance);
uint16 critMod = 163;
uint32 critMod = 163;
if (damage < 1) //We can't critical hit if we don't hit.
return;
@@ -4163,8 +4187,8 @@ void Mob::TryPetCriticalHit(Mob *defender, uint16 skill, int32 &damage)
if (!owner)
return;
int16 CritPetChance = owner->aabonuses.PetCriticalHit + owner->itembonuses.PetCriticalHit + owner->spellbonuses.PetCriticalHit;
int16 CritChanceBonus = GetCriticalChanceBonus(skill);
int32 CritPetChance = owner->aabonuses.PetCriticalHit + owner->itembonuses.PetCriticalHit + owner->spellbonuses.PetCriticalHit;
int32 CritChanceBonus = GetCriticalChanceBonus(skill);
if (CritPetChance || critChance) {
@@ -4208,24 +4232,26 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack
}
#endif //BOTS
float critChance = 0.0f;
bool IsBerskerSPA = false;
//1: Try Slay Undead
if(defender && defender->GetBodyType() == BT_Undead || defender->GetBodyType() == BT_SummonedUndead || defender->GetBodyType() == BT_Vampire){
int16 SlayRateBonus = aabonuses.SlayUndead[0] + itembonuses.SlayUndead[0] + spellbonuses.SlayUndead[0];
if (defender && (defender->GetBodyType() == BT_Undead ||
defender->GetBodyType() == BT_SummonedUndead || defender->GetBodyType() == BT_Vampire)) {
int32 SlayRateBonus = aabonuses.SlayUndead[0] + itembonuses.SlayUndead[0] + spellbonuses.SlayUndead[0];
if (SlayRateBonus) {
critChance += (float(SlayRateBonus)/100.0f);
critChance /= 100.0f;
if(MakeRandomFloat(0, 1) < critChance){
int16 SlayDmgBonus = aabonuses.SlayUndead[1] + itembonuses.SlayUndead[1] + spellbonuses.SlayUndead[1];
damage = (damage*SlayDmgBonus*2.25)/100;
entity_list.MessageClose(this, false, 200, MT_CritMelee, "%s cleanses %s target!(%d)", GetCleanName(), this->GetGender() == 0 ? "his" : this->GetGender() == 1 ? "her" : "its", damage);
float slayChance = static_cast<float>(SlayRateBonus) / 10000.0f;
if (MakeRandomFloat(0, 1) < slayChance) {
int32 SlayDmgBonus = aabonuses.SlayUndead[1] + itembonuses.SlayUndead[1] + spellbonuses.SlayUndead[1];
damage = (damage * SlayDmgBonus * 2.25) / 100;
if (GetGender() == 1) // female
entity_list.FilteredMessageClose_StringID(this, false, 200,
MT_CritMelee, FilterMeleeCrits, FEMALE_SLAYUNDEAD,
GetCleanName(), itoa(damage));
else // males and neuter I guess
entity_list.FilteredMessageClose_StringID(this, false, 200,
MT_CritMelee, FilterMeleeCrits, MALE_SLAYUNDEAD,
GetCleanName(), itoa(damage));
return;
}
}
@@ -4288,9 +4314,9 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack
if(MakeRandomFloat(0, 1) < critChance)
{
uint16 critMod = 200;
uint32 critMod = 200;
bool crip_success = false;
int16 CripplingBlowChance = GetCrippBlowChance();
int32 CripplingBlowChance = GetCrippBlowChance();
//Crippling Blow Chance: The percent value of the effect is applied
//to the your Chance to Critical. (ie You have 10% chance to critical and you
@@ -4346,7 +4372,7 @@ bool Mob::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse)
uint32 FB_Dmg = aabonuses.FinishingBlow[1] + spellbonuses.FinishingBlow[1] + itembonuses.FinishingBlow[1];
uint16 FB_Level = 0;
uint32 FB_Level = 0;
FB_Level = aabonuses.FinishingBlowLvl[0];
if (FB_Level < spellbonuses.FinishingBlowLvl[0])
FB_Level = spellbonuses.FinishingBlowLvl[0];
@@ -4374,7 +4400,7 @@ void Mob::DoRiposte(Mob* defender) {
defender->Attack(this, MainPrimary, true);
if (HasDied()) return;
int16 DoubleRipChance = defender->aabonuses.GiveDoubleRiposte[0] +
int32 DoubleRipChance = defender->aabonuses.GiveDoubleRiposte[0] +
defender->spellbonuses.GiveDoubleRiposte[0] +
defender->itembonuses.GiveDoubleRiposte[0];
@@ -4422,7 +4448,7 @@ void Mob::ApplyMeleeDamageBonus(uint16 skill, int32 &damage){
bool Mob::HasDied() {
bool Result = false;
int16 hp_below = 0;
int32 hp_below = 0;
hp_below = (GetDelayDeath() * -1);
@@ -4436,7 +4462,7 @@ uint16 Mob::GetDamageTable(SkillUseTypes skillinuse)
{
if(GetLevel() <= 51)
{
uint16 ret_table = 0;
uint32 ret_table = 0;
int str_over_75 = 0;
if(GetSTR() > 75)
str_over_75 = GetSTR() - 75;
@@ -4459,7 +4485,7 @@ uint16 Mob::GetDamageTable(SkillUseTypes skillinuse)
}
else
{
uint16 dmg_table[] = {
uint32 dmg_table[] = {
275, 275, 275, 275, 275,
280, 280, 280, 280, 285,
285, 285, 290, 290, 295,
@@ -4636,7 +4662,7 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
float Mob::GetSkillProcChances(uint16 ReuseTime, uint16 hand) {
uint16 weapon_speed;
uint32 weapon_speed;
float ProcChance = 0;
if (!ReuseTime && hand) {
@@ -4713,7 +4739,7 @@ int32 Mob::RuneAbsorb(int32 damage, uint16 type)
if (type == SE_Rune){
for(uint32 slot = 0; slot < buff_max; slot++) {
if(slot == spellbonuses.MeleeRune[1] && spellbonuses.MeleeRune[0] && buffs[slot].melee_rune && IsValidSpell(buffs[slot].spellid)){
uint32 melee_rune_left = buffs[slot].melee_rune;
int melee_rune_left = buffs[slot].melee_rune;
if(melee_rune_left > damage)
{
@@ -4738,7 +4764,7 @@ int32 Mob::RuneAbsorb(int32 damage, uint16 type)
else{
for(uint32 slot = 0; slot < buff_max; slot++) {
if(slot == spellbonuses.AbsorbMagicAtt[1] && spellbonuses.AbsorbMagicAtt[0] && buffs[slot].magic_rune && IsValidSpell(buffs[slot].spellid)){
uint32 magic_rune_left = buffs[slot].magic_rune;
int magic_rune_left = buffs[slot].magic_rune;
if(magic_rune_left > damage)
{
magic_rune_left -= damage;
@@ -4814,3 +4840,171 @@ void Mob::CommonBreakInvisible()
hidden = false;
improved_hidden = false;
}
/* Dev quotes:
* Old formula
* Final delay = (Original Delay / (haste mod *.01f)) + ((Hundred Hands / 100) * Original Delay)
* New formula
* Final delay = (Original Delay / (haste mod *.01f)) + ((Hundred Hands / 1000) * (Original Delay / (haste mod *.01f))
* Base Delay 20 25 30 37
* Haste 2.25 2.25 2.25 2.25
* HHE (old) -17 -17 -17 -17
* Final Delay 5.488888889 6.861111111 8.233333333 10.15444444
*
* Base Delay 20 25 30 37
* Haste 2.25 2.25 2.25 2.25
* HHE (new) -383 -383 -383 -383
* Final Delay 5.484444444 6.855555556 8.226666667 10.14622222
*
* Difference -0.004444444 -0.005555556 -0.006666667 -0.008222222
*
* These times are in 10th of a second
*/
void Mob::SetAttackTimer()
{
attack_timer.SetAtTrigger(4000, true);
}
void Client::SetAttackTimer()
{
float haste_mod = GetHaste() * 0.01f;
//default value for attack timer in case they have
//an invalid weapon equipped:
attack_timer.SetAtTrigger(4000, true);
Timer *TimerToUse = nullptr;
const Item_Struct *PrimaryWeapon = nullptr;
for (int i = MainRange; i <= MainSecondary; i++) {
//pick a timer
if (i == MainPrimary)
TimerToUse = &attack_timer;
else if (i == MainRange)
TimerToUse = &ranged_timer;
else if (i == MainSecondary)
TimerToUse = &attack_dw_timer;
else //invalid slot (hands will always hit this)
continue;
const Item_Struct *ItemToUse = nullptr;
//find our item
ItemInst *ci = GetInv().GetItem(i);
if (ci)
ItemToUse = ci->GetItem();
//special offhand stuff
if (i == MainSecondary) {
//if we have a 2H weapon in our main hand, no dual
if (PrimaryWeapon != nullptr) {
if (PrimaryWeapon->ItemClass == ItemClassCommon
&& (PrimaryWeapon->ItemType == ItemType2HSlash
|| PrimaryWeapon->ItemType == ItemType2HBlunt
|| PrimaryWeapon->ItemType == ItemType2HPiercing)) {
attack_dw_timer.Disable();
continue;
}
}
//if we cant dual wield, skip it
if (!CanThisClassDualWield()) {
attack_dw_timer.Disable();
continue;
}
}
//see if we have a valid weapon
if (ItemToUse != nullptr) {
//check type and damage/delay
if (ItemToUse->ItemClass != ItemClassCommon
|| ItemToUse->Damage == 0
|| ItemToUse->Delay == 0) {
//no weapon
ItemToUse = nullptr;
}
// Check to see if skill is valid
else if ((ItemToUse->ItemType > ItemTypeLargeThrowing) &&
(ItemToUse->ItemType != ItemTypeMartial) &&
(ItemToUse->ItemType != ItemType2HPiercing)) {
//no weapon
ItemToUse = nullptr;
}
}
int hhe = itembonuses.HundredHands + spellbonuses.HundredHands;
int speed = 0;
int delay = 36;
float quiver_haste = 0.0f;
//if we have no weapon..
if (ItemToUse == nullptr) {
//above checks ensure ranged weapons do not fall into here
// Work out if we're a monk
if (GetClass() == MONK || GetClass() == BEASTLORD)
delay = GetMonkHandToHandDelay();
} else {
//we have a weapon, use its delay
delay = ItemToUse->Delay;
if (ItemToUse->ItemType == ItemTypeBow || ItemToUse->ItemType == ItemTypeLargeThrowing)
quiver_haste = GetQuiverHaste();
}
if (RuleB(Spells, Jun182014HundredHandsRevamp))
speed = static_cast<int>(((delay / haste_mod) + ((hhe / 1000.0f) * (delay / haste_mod))) * 100);
else
speed = static_cast<int>(((delay / haste_mod) + ((hhe / 100.0f) * delay)) * 100);
// this is probably wrong
if (quiver_haste > 0)
speed *= quiver_haste;
TimerToUse->SetAtTrigger(std::max(RuleI(Combat, MinHastedDelay), speed), true);
if (i == MainPrimary)
PrimaryWeapon = ItemToUse;
}
}
void NPC::SetAttackTimer()
{
float haste_mod = GetHaste() * 0.01f;
//default value for attack timer in case they have
//an invalid weapon equipped:
attack_timer.SetAtTrigger(4000, true);
Timer *TimerToUse = nullptr;
int hhe = itembonuses.HundredHands + spellbonuses.HundredHands;
// Technically NPCs should do some logic for weapons, but the effect is minimal
// What they do is take the lower of their set delay and the weapon's
// ex. Mob's delay set to 20, weapon set to 19, delay 19
// Mob's delay set to 20, weapon set to 21, delay 20
int speed = 0;
if (RuleB(Spells, Jun182014HundredHandsRevamp))
speed = static_cast<int>(((attack_delay / haste_mod) + ((hhe / 1000.0f) * (attack_delay / haste_mod))) * 100);
else
speed = static_cast<int>(((attack_delay / haste_mod) + ((hhe / 100.0f) * attack_delay)) * 100);
for (int i = MainRange; i <= MainSecondary; i++) {
//pick a timer
if (i == MainPrimary)
TimerToUse = &attack_timer;
else if (i == MainRange)
TimerToUse = &ranged_timer;
else if (i == MainSecondary)
TimerToUse = &attack_dw_timer;
else //invalid slot (hands will always hit this)
continue;
//special offhand stuff
if (i == MainSecondary) {
//NPCs get it for free at 13
if(GetLevel() < 13) {
attack_dw_timer.Disable();
continue;
}
}
TimerToUse->SetAtTrigger(std::max(RuleI(Combat, MinHastedDelay), speed), true);
}
}
+59 -28
View File
@@ -20,13 +20,13 @@
#include "masterentity.h"
#include "../common/packet_dump.h"
#include "../common/moremath.h"
#include "../common/Item.h"
#include "../common/item.h"
#include "worldserver.h"
#include "../common/skills.h"
#include "../common/bodytypes.h"
#include "../common/classes.h"
#include "../common/rulesys.h"
#include "QuestParserCollection.h"
#include "quest_parser_collection.h"
#include <math.h>
#include <assert.h>
#include <iostream>
@@ -35,7 +35,7 @@
#include "../common/unix.h"
#endif
#include "StringIDs.h"
#include "string_ids.h"
void Mob::CalcBonuses()
{
@@ -104,6 +104,8 @@ void Client::CalcBonuses()
CalcMaxMana();
CalcMaxEndurance();
SetAttackTimer();
rooted = FindType(SE_Root);
XPRate = 100 + spellbonuses.XPRateMod;
@@ -174,8 +176,6 @@ void Client::CalcItemBonuses(StatBonuses* newbon) {
if(newbon->EnduranceRegen > CalcEnduranceRegenCap())
newbon->EnduranceRegen = CalcEnduranceRegenCap();
SetAttackTimer();
}
void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, bool isTribute) {
@@ -306,7 +306,7 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAu
}
//FatherNitwit: New style haste, shields, and regens
if(newbon->haste < (int16)item->Haste) {
if(newbon->haste < (int32)item->Haste) {
newbon->haste = item->Haste;
}
if(item->Regen > 0)
@@ -1392,7 +1392,7 @@ void Mob::CalcSpellBonuses(StatBonuses* newbon)
newbon->AggroRange = -1;
newbon->AssistRange = -1;
uint32 buff_count = GetMaxTotalSlots();
int buff_count = GetMaxTotalSlots();
for(i = 0; i < buff_count; i++) {
if(buffs[i].spellid != SPELL_UNKNOWN){
ApplySpellsBonuses(buffs[i].spellid, buffs[i].casterlevel, newbon, buffs[i].casterid, false, buffs[i].ticsremaining,i);
@@ -1477,19 +1477,19 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
// redundant to have level check here
if(newbon->AggroRange == -1 || effect_value < newbon->AggroRange)
{
newbon->AggroRange = effect_value;
newbon->AggroRange = static_cast<float>(effect_value);
}
break;
}
case SE_Harmony:
{
// neotokyo: Harmony effect as buff - kinda tricky
// Harmony effect as buff - kinda tricky
// harmony could stack with a lull spell, which has better aggro range
// take the one with less range in any case
if(newbon->AssistRange == -1 || effect_value < newbon->AssistRange)
{
newbon->AssistRange = effect_value;
newbon->AssistRange = static_cast<float>(effect_value);
}
break;
}
@@ -1546,6 +1546,11 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
case SE_AttackSpeed4:
{
// These don't generate the IMMUNE_ATKSPEED message and the icon shows up
// but have no effect on the mobs attack speed
if (GetSpecialAbility(UNSLOWABLE))
break;
if (effect_value < 0) //A few spells use negative values(Descriptions all indicate it should be a slow)
effect_value = effect_value * -1;
@@ -2467,7 +2472,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
}
break;
}
case SE_ManaAbsorbPercentDamage:
{
if (newbon->ManaAbsorbPercentDamage[0] < effect_value){
@@ -2488,7 +2493,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
case SE_ShieldBlock:
newbon->ShieldBlock += effect_value;
break;
case SE_ShieldEquipHateMod:
newbon->ShieldEquipHateMod += effect_value;
break;
@@ -2502,6 +2507,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
newbon->BlockBehind += effect_value;
break;
case SE_Blind:
newbon->IsBlind = true;
break;
case SE_Fear:
newbon->IsFeared = true;
break;
@@ -2799,7 +2808,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|| ((effect_value < 0) && (newbon->AlterNPCLevel > effect_value))
|| ((effect_value > 0) && (newbon->AlterNPCLevel < effect_value))) {
int16 tmp_lv = GetOrigLevel() + effect_value;
int tmp_lv = GetOrigLevel() + effect_value;
if (tmp_lv < 1)
tmp_lv = 1;
else if (tmp_lv > 255)
@@ -3083,7 +3092,7 @@ void Client::CalcItemScale() {
bool Client::CalcItemScale(uint32 slot_x, uint32 slot_y) {
// behavior change: 'slot_y' is now [RANGE]_END and not [RANGE]_END + 1
bool changed = false;
int i;
uint32 i;
for (i = slot_x; i <= slot_y; i++) {
if (i == MainAmmo) // moved here from calling procedure to facilitate future range changes where MainAmmo may not be the last slot
continue;
@@ -3177,7 +3186,7 @@ void Client::DoItemEnterZone() {
bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) {
// behavior change: 'slot_y' is now [RANGE]_END and not [RANGE]_END + 1
bool changed = false;
for(int i = slot_x; i <= slot_y; i++) {
for(uint32 i = slot_x; i <= slot_y; i++) {
if (i == MainAmmo) // moved here from calling procedure to facilitate future range changes where MainAmmo may not be the last slot
continue;
@@ -3371,15 +3380,15 @@ void Mob::NegateSpellsBonuses(uint16 spell_id)
break;
case SE_ChangeFrenzyRad:
spellbonuses.AggroRange = effect_value;
aabonuses.AggroRange = effect_value;
itembonuses.AggroRange = effect_value;
spellbonuses.AggroRange = static_cast<float>(effect_value);
aabonuses.AggroRange = static_cast<float>(effect_value);
itembonuses.AggroRange = static_cast<float>(effect_value);
break;
case SE_Harmony:
spellbonuses.AssistRange = effect_value;
aabonuses.AssistRange = effect_value;
itembonuses.AssistRange = effect_value;
spellbonuses.AssistRange = static_cast<float>(effect_value);
aabonuses.AssistRange = static_cast<float>(effect_value);
itembonuses.AssistRange = static_cast<float>(effect_value);
break;
case SE_AttackSpeed:
@@ -4081,6 +4090,10 @@ void Mob::NegateSpellsBonuses(uint16 spell_id)
itembonuses.BlockBehind = effect_value;
break;
case SE_Blind:
spellbonuses.IsBlind = false;
break;
case SE_Fear:
spellbonuses.IsFeared = false;
break;
@@ -4334,11 +4347,11 @@ void Mob::NegateSpellsBonuses(uint16 spell_id)
break;
case SE_TriggerMeleeThreshold:
spellbonuses.TriggerMeleeThreshold = effect_value;
spellbonuses.TriggerMeleeThreshold = false;
break;
case SE_TriggerSpellThreshold:
spellbonuses.TriggerSpellThreshold = effect_value;
spellbonuses.TriggerSpellThreshold = false;
break;
case SE_DivineAura:
@@ -4364,7 +4377,7 @@ void Mob::NegateSpellsBonuses(uint16 spell_id)
break;
case SE_DistanceRemoval:
spellbonuses.DistanceRemoval = effect_value;
spellbonuses.DistanceRemoval = false;
break;
case SE_ImprovedTaunt:
@@ -4467,7 +4480,7 @@ void Mob::NegateSpellsBonuses(uint16 spell_id)
break;
case SE_Sanctuary:
spellbonuses.Sanctuary = effect_value;
spellbonuses.Sanctuary = false;
break;
case SE_FactionModPct:
@@ -4483,10 +4496,28 @@ void Mob::NegateSpellsBonuses(uint16 spell_id)
break;
case SE_IllusionPersistence:
spellbonuses.IllusionPersistence = effect_value;
itembonuses.IllusionPersistence = effect_value;
aabonuses.IllusionPersistence = effect_value;
spellbonuses.IllusionPersistence = false;
itembonuses.IllusionPersistence = false;
aabonuses.IllusionPersistence = false;
break;
case SE_SkillProcSuccess:{
for(int e = 0; e < MAX_SKILL_PROCS; e++)
{
spellbonuses.SkillProcSuccess[e] = effect_value;
itembonuses.SkillProcSuccess[e] = effect_value;
aabonuses.SkillProcSuccess[e] = effect_value;
}
}
case SE_SkillProc:{
for(int e = 0; e < MAX_SKILL_PROCS; e++)
{
spellbonuses.SkillProc[e] = effect_value;
itembonuses.SkillProc[e] = effect_value;
aabonuses.SkillProc[e] = effect_value;
}
}
}
}
}
+1000 -1415
View File
File diff suppressed because it is too large Load Diff
+107 -107
View File
@@ -3,15 +3,15 @@
#ifdef BOTS
#include "botStructs.h"
#include "bot_structs.h"
#include "mob.h"
#include "client.h"
#include "pets.h"
#include "groups.h"
#include "corpse.h"
#include "zonedb.h"
#include "StringIDs.h"
#include "../common/MiscFunctions.h"
#include "string_ids.h"
#include "../common/misc_functions.h"
#include "../common/debug.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()); }
@@ -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();
@@ -311,11 +311,11 @@ public:
virtual float GetAOERange(uint16 spell_id);
virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100);
virtual void DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caster_level, Mob* caster = 0);
virtual bool CastSpell(uint16 spell_id, uint16 target_id, uint16 slot = 10, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, int16 *resist_adjust = nullptr);
virtual bool CastSpell(uint16 spell_id, uint16 target_id, uint16 slot = USE_ITEM_SPELL_SLOT, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, int16 *resist_adjust = nullptr);
virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar);
virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster);
virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction);
virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot = 10, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF);
virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot = USE_ITEM_SPELL_SLOT, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF);
// Bot Action Command Methods
bool MesmerizeTarget(Mob* target);
@@ -465,57 +465,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; }
@@ -556,13 +556,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,7 +601,7 @@ private:
int32 base_end;
int32 cur_end;
int32 max_end;
int16 end_regen;
int32 end_regen;
uint32 timers[MaxTimer];
bool _hasBeenSummoned;
float _preSummonX;
@@ -626,26 +626,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 +670,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();
+1 -1
View File
@@ -1,7 +1,7 @@
#ifdef BOTS
#include "bot.h"
#include "../common/StringUtil.h"
#include "../common/string_util.h"
bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
+849 -719
View File
File diff suppressed because it is too large Load Diff
+727 -729
View File
File diff suppressed because it is too large Load Diff
+1 -2
View File
@@ -33,8 +33,6 @@ void ClientLogs::subscribe(EQEMuLog::LogIDs id, Client *c) {
if(c == nullptr)
return;
//make sure they arnt allready subscribed.
std::vector<Client *>::iterator cur,end;
cur = entries[id].begin();
end = entries[id].end();
@@ -98,6 +96,7 @@ void ClientLogs::msg(EQEMuLog::LogIDs id, const char *buf) {
for(; cur != end; ++cur) {
if(!(*cur)->InZone())
continue;
(*cur)->Message(CLIENT_LOG_CHANNEL, buf);
}
}
+109 -90
View File
@@ -18,31 +18,25 @@
#include <algorithm>
#include "../common/debug.h"
#include "../common/spdat.h"
#include "../common/packet_dump.h"
#include "../common/packet_functions.h"
#include "../common/serverinfo.h"
#include "../common/ZoneNumbers.h"
#include "../common/moremath.h"
#include "../common/guilds.h"
#include "../common/logsys.h"
#include "../common/spdat.h"
#include "../common/rulesys.h"
#include "masterentity.h"
#include "npc_ai.h"
#include "petitions.h"
#include "string_ids.h"
#include "worldserver.h"
#include "zonedb.h"
#include "petitions.h"
#include "StringIDs.h"
#include "NpcAI.h"
// Return max stat value for level
int16 Client::GetMaxStat() const {
int32 Client::GetMaxStat() const {
if((RuleI(Character, StatCap)) > 0)
return (RuleI(Character, StatCap));
int level = GetLevel();
int16 base = 0;
int32 base = 0;
if (level < 61) {
base = 255;
@@ -60,11 +54,11 @@ int16 Client::GetMaxStat() const {
return(base);
}
int16 Client::GetMaxResist() const
int32 Client::GetMaxResist() const
{
int level = GetLevel();
int16 base = 500;
int32 base = 500;
if(level > 60)
base += ((level - 60) * 5);
@@ -72,79 +66,79 @@ int16 Client::GetMaxResist() const
return base;
}
int16 Client::GetMaxSTR() const {
int32 Client::GetMaxSTR() const {
return GetMaxStat()
+ itembonuses.STRCapMod
+ spellbonuses.STRCapMod
+ aabonuses.STRCapMod;
}
int16 Client::GetMaxSTA() const {
int32 Client::GetMaxSTA() const {
return GetMaxStat()
+ itembonuses.STACapMod
+ spellbonuses.STACapMod
+ aabonuses.STACapMod;
}
int16 Client::GetMaxDEX() const {
int32 Client::GetMaxDEX() const {
return GetMaxStat()
+ itembonuses.DEXCapMod
+ spellbonuses.DEXCapMod
+ aabonuses.DEXCapMod;
}
int16 Client::GetMaxAGI() const {
int32 Client::GetMaxAGI() const {
return GetMaxStat()
+ itembonuses.AGICapMod
+ spellbonuses.AGICapMod
+ aabonuses.AGICapMod;
}
int16 Client::GetMaxINT() const {
int32 Client::GetMaxINT() const {
return GetMaxStat()
+ itembonuses.INTCapMod
+ spellbonuses.INTCapMod
+ aabonuses.INTCapMod;
}
int16 Client::GetMaxWIS() const {
int32 Client::GetMaxWIS() const {
return GetMaxStat()
+ itembonuses.WISCapMod
+ spellbonuses.WISCapMod
+ aabonuses.WISCapMod;
}
int16 Client::GetMaxCHA() const {
int32 Client::GetMaxCHA() const {
return GetMaxStat()
+ itembonuses.CHACapMod
+ spellbonuses.CHACapMod
+ aabonuses.CHACapMod;
}
int16 Client::GetMaxMR() const {
int32 Client::GetMaxMR() const {
return GetMaxResist()
+ itembonuses.MRCapMod
+ spellbonuses.MRCapMod
+ aabonuses.MRCapMod;
}
int16 Client::GetMaxPR() const {
int32 Client::GetMaxPR() const {
return GetMaxResist()
+ itembonuses.PRCapMod
+ spellbonuses.PRCapMod
+ aabonuses.PRCapMod;
}
int16 Client::GetMaxDR() const {
int32 Client::GetMaxDR() const {
return GetMaxResist()
+ itembonuses.DRCapMod
+ spellbonuses.DRCapMod
+ aabonuses.DRCapMod;
}
int16 Client::GetMaxCR() const {
int32 Client::GetMaxCR() const {
return GetMaxResist()
+ itembonuses.CRCapMod
+ spellbonuses.CRCapMod
+ aabonuses.CRCapMod;
}
int16 Client::GetMaxFR() const {
int32 Client::GetMaxFR() const {
return GetMaxResist()
+ itembonuses.FRCapMod
+ spellbonuses.FRCapMod
+ aabonuses.FRCapMod;
}
int16 Client::GetMaxCorrup() const {
int32 Client::GetMaxCorrup() const {
return GetMaxResist()
+ itembonuses.CorrupCapMod
+ spellbonuses.CorrupCapMod
@@ -265,8 +259,8 @@ int32 Client::CalcMaxHP() {
return max_hp;
}
uint16 Mob::GetClassLevelFactor(){
uint16 multiplier = 0;
uint32 Mob::GetClassLevelFactor(){
uint32 multiplier = 0;
uint8 mlevel=GetLevel();
switch(GetClass())
{
@@ -386,8 +380,8 @@ int32 Client::CalcBaseHP()
}
}
else {
uint16 Post255;
uint16 lm=GetClassLevelFactor();
uint32 Post255;
uint32 lm=GetClassLevelFactor();
if((GetSTA()-255)/2 > 0)
Post255 = (GetSTA()-255)/2;
else
@@ -446,8 +440,8 @@ uint32 Client::GetClassHPFactor() {
}
// This should return the combined AC of all the items the player is wearing.
int16 Client::GetRawItemAC() {
int16 Total = 0;
int32 Client::GetRawItemAC() {
int32 Total = 0;
// this skips MainAmmo..add an '=' conditional if that slot is required (original behavior)
for (int16 slot_id = EmuConstants::EQUIPMENT_BEGIN; slot_id < EmuConstants::EQUIPMENT_END; slot_id++) {
@@ -460,7 +454,7 @@ int16 Client::GetRawItemAC() {
return Total;
}
int16 Client::acmod() {
int32 Client::acmod() {
int agility = GetAGI();
int level = GetLevel();
if(agility < 1 || level < 1)
@@ -838,7 +832,7 @@ int16 Client::acmod() {
// ac1 and ac2 are probably the damage migitation and damage avoidance numbers, not sure which is which.
// I forgot to include the iksar defense bonus and i cant find my notes now...
// AC from spells are not included (cant even cast spells yet..)
int16 Client::CalcAC() {
int32 Client::CalcAC() {
// new formula
int avoidance = (acmod() + ((GetSkill(SkillDefense) + itembonuses.HeroicAGI/10)*16)/9);
@@ -889,7 +883,7 @@ int16 Client::CalcAC() {
return(AC);
}
int16 Client::GetACMit() {
int32 Client::GetACMit() {
int mitigation = 0;
if (m_pp.class_ == WIZARD || m_pp.class_ == MAGICIAN || m_pp.class_ == NECROMANCER || m_pp.class_ == ENCHANTER) {
@@ -915,9 +909,9 @@ int16 Client::GetACMit() {
return(mitigation*1000/847);
}
int16 Client::GetACAvoid() {
int32 Client::GetACAvoid() {
int avoidance = (acmod() + ((GetSkill(SkillDefense) + itembonuses.HeroicAGI/10)*16)/9);
int32 avoidance = (acmod() + ((GetSkill(SkillDefense) + itembonuses.HeroicAGI/10)*16)/9);
if (avoidance < 0)
avoidance = 0;
@@ -1186,7 +1180,7 @@ uint32 Client::CalcCurrentWeight() {
return Total;
}
int16 Client::CalcAlcoholPhysicalEffect()
int32 Client::CalcAlcoholPhysicalEffect()
{
if(m_pp.intoxication <= 55)
return 0;
@@ -1194,10 +1188,10 @@ int16 Client::CalcAlcoholPhysicalEffect()
return (m_pp.intoxication - 40) / 16;
}
int16 Client::CalcSTR() {
int16 val = m_pp.STR + itembonuses.STR + spellbonuses.STR + CalcAlcoholPhysicalEffect();
int32 Client::CalcSTR() {
int32 val = m_pp.STR + itembonuses.STR + spellbonuses.STR + CalcAlcoholPhysicalEffect();
int16 mod = aabonuses.STR;
int32 mod = aabonuses.STR;
STR = val + mod;
@@ -1211,10 +1205,10 @@ int16 Client::CalcSTR() {
return(STR);
}
int16 Client::CalcSTA() {
int16 val = m_pp.STA + itembonuses.STA + spellbonuses.STA + CalcAlcoholPhysicalEffect();;
int32 Client::CalcSTA() {
int32 val = m_pp.STA + itembonuses.STA + spellbonuses.STA + CalcAlcoholPhysicalEffect();;
int16 mod = aabonuses.STA;
int32 mod = aabonuses.STA;
STA = val + mod;
@@ -1228,18 +1222,18 @@ int16 Client::CalcSTA() {
return(STA);
}
int16 Client::CalcAGI() {
int16 val = m_pp.AGI + itembonuses.AGI + spellbonuses.AGI - CalcAlcoholPhysicalEffect();;
int16 mod = aabonuses.AGI;
int32 Client::CalcAGI() {
int32 val = m_pp.AGI + itembonuses.AGI + spellbonuses.AGI - CalcAlcoholPhysicalEffect();;
int32 mod = aabonuses.AGI;
int16 str = GetSTR();
int32 str = GetSTR();
//Encumbered penalty
if(weight > (str * 10)) {
//AGI is halved when we double our weight, zeroed (defaults to 1) when we triple it. this includes AGI from AAs
float total_agi = float(val + mod);
float str_float = float(str);
AGI = (int16)(((-total_agi) / (str_float * 2)) * (((float)weight / 10) - str_float) + total_agi); //casting to an int assumes this will be floor'd. without using floats & casting to int16, the calculation doesn't work right
AGI = (int32)(((-total_agi) / (str_float * 2)) * (((float)weight / 10) - str_float) + total_agi); //casting to an int assumes this will be floor'd. without using floats & casting to int16, the calculation doesn't work right
} else
AGI = val + mod;
@@ -1253,10 +1247,10 @@ int16 Client::CalcAGI() {
return(AGI);
}
int16 Client::CalcDEX() {
int16 val = m_pp.DEX + itembonuses.DEX + spellbonuses.DEX - CalcAlcoholPhysicalEffect();;
int32 Client::CalcDEX() {
int32 val = m_pp.DEX + itembonuses.DEX + spellbonuses.DEX - CalcAlcoholPhysicalEffect();;
int16 mod = aabonuses.DEX;
int32 mod = aabonuses.DEX;
DEX = val + mod;
@@ -1270,16 +1264,16 @@ int16 Client::CalcDEX() {
return(DEX);
}
int16 Client::CalcINT() {
int16 val = m_pp.INT + itembonuses.INT + spellbonuses.INT;
int32 Client::CalcINT() {
int32 val = m_pp.INT + itembonuses.INT + spellbonuses.INT;
int16 mod = aabonuses.INT;
int32 mod = aabonuses.INT;
INT = val + mod;
if(m_pp.intoxication)
{
int16 AlcINT = INT - (int16)((float)m_pp.intoxication / 200.0f * (float)INT) - 1;
int32 AlcINT = INT - (int32)((float)m_pp.intoxication / 200.0f * (float)INT) - 1;
if((AlcINT < (int)(0.2 * INT)))
INT = (int)(0.2f * (float)INT);
@@ -1297,16 +1291,16 @@ int16 Client::CalcINT() {
return(INT);
}
int16 Client::CalcWIS() {
int16 val = m_pp.WIS + itembonuses.WIS + spellbonuses.WIS;
int32 Client::CalcWIS() {
int32 val = m_pp.WIS + itembonuses.WIS + spellbonuses.WIS;
int16 mod = aabonuses.WIS;
int32 mod = aabonuses.WIS;
WIS = val + mod;
if(m_pp.intoxication)
{
int16 AlcWIS = WIS - (int16)((float)m_pp.intoxication / 200.0f * (float)WIS) - 1;
int32 AlcWIS = WIS - (int32)((float)m_pp.intoxication / 200.0f * (float)WIS) - 1;
if((AlcWIS < (int)(0.2 * WIS)))
WIS = (int)(0.2f * (float)WIS);
@@ -1324,10 +1318,10 @@ int16 Client::CalcWIS() {
return(WIS);
}
int16 Client::CalcCHA() {
int16 val = m_pp.CHA + itembonuses.CHA + spellbonuses.CHA;
int32 Client::CalcCHA() {
int32 val = m_pp.CHA + itembonuses.CHA + spellbonuses.CHA;
int16 mod = aabonuses.CHA;
int32 mod = aabonuses.CHA;
CHA = val + mod;
@@ -1341,12 +1335,45 @@ int16 Client::CalcCHA() {
return(CHA);
}
int Client::CalcHaste() {
int h = spellbonuses.haste + spellbonuses.hastetype2;
int Client::CalcHaste()
{
/* Tests: (based on results in newer char window)
* 68 v1 + 46 item + 25 over + 35 inhib = 204%
* 46 item + 5 v2 + 25 over + 35 inhib = 65%
* 68 v1 + 46 item + 5 v2 + 25 over + 35 inhib = 209%
* 75% slow + 35 inhib = 25%
* 35 inhib = 65%
* 75% slow = 25%
* Conclusions:
* the bigger effect in slow v. inhib wins
* slow negates all other hastes
* inhib will only negate all other hastes if you don't have v1 (ex. VQ)
*/
// slow beats all! Besides a better inhibit
if (spellbonuses.haste < 0) {
if (-spellbonuses.haste <= spellbonuses.inhibitmelee)
Haste = 100 - spellbonuses.inhibitmelee;
else
Haste = 100 + spellbonuses.haste;
return Haste;
}
// No haste and inhibit, kills all other hastes
if (spellbonuses.haste == 0 && spellbonuses.inhibitmelee) {
Haste = 100 - spellbonuses.inhibitmelee;
return Haste;
}
int h = 0;
int cap = 0;
int overhaste = 0;
int level = GetLevel();
// we know we have a haste spell and not slowed, no extra inhibit melee checks needed
if (spellbonuses.haste)
h += spellbonuses.haste - spellbonuses.inhibitmelee;
if (spellbonuses.hastetype2 && level > 49) // type 2 is capped at 10% and only available to 50+
h += spellbonuses.hastetype2 > 10 ? 10 : spellbonuses.hastetype2;
// 26+ no cap, 1-25 10
if (level > 25) // 26+
h += itembonuses.haste;
@@ -1368,30 +1395,22 @@ int Client::CalcHaste() {
// 51+ 25 (despite there being higher spells...), 1-50 10
if (level > 50) // 51+
overhaste = spellbonuses.hastetype3 > 25 ? 25 : spellbonuses.hastetype3;
h += spellbonuses.hastetype3 > 25 ? 25 : spellbonuses.hastetype3;
else // 1-50
overhaste = spellbonuses.hastetype3 > 10 ? 10 : spellbonuses.hastetype3;
h += spellbonuses.hastetype3 > 10 ? 10 : spellbonuses.hastetype3;
h += overhaste;
h += ExtraHaste; //GM granted haste.
h = mod_client_haste(h);
if (spellbonuses.inhibitmelee) {
if (h >= 0)
h -= spellbonuses.inhibitmelee;
else
h -= ((100 + h) * spellbonuses.inhibitmelee / 100);
}
Haste = h;
return(Haste);
Haste = 100 + h;
return Haste;
}
//The AA multipliers are set to be 5, but were 2 on WR
//The resistant discipline which I think should be here is implemented
//in Mob::ResistSpell
int16 Client::CalcMR()
int32 Client::CalcMR()
{
//racial bases
switch(GetBaseRace()) {
@@ -1461,7 +1480,7 @@ int16 Client::CalcMR()
return(MR);
}
int16 Client::CalcFR()
int32 Client::CalcFR()
{
//racial bases
switch(GetBaseRace()) {
@@ -1537,7 +1556,7 @@ int16 Client::CalcFR()
return(FR);
}
int16 Client::CalcDR()
int32 Client::CalcDR()
{
//racial bases
switch(GetBaseRace()) {
@@ -1620,7 +1639,7 @@ int16 Client::CalcDR()
return(DR);
}
int16 Client::CalcPR()
int32 Client::CalcPR()
{
//racial bases
switch(GetBaseRace()) {
@@ -1703,7 +1722,7 @@ int16 Client::CalcPR()
return(PR);
}
int16 Client::CalcCR()
int32 Client::CalcCR()
{
//racial bases
switch(GetBaseRace()) {
@@ -1779,7 +1798,7 @@ int16 Client::CalcCR()
return(CR);
}
int16 Client::CalcCorrup()
int32 Client::CalcCorrup()
{
Corrup = GetBaseCorrup() + itembonuses.Corrup + spellbonuses.Corrup + aabonuses.Corrup;
@@ -1789,17 +1808,17 @@ int16 Client::CalcCorrup()
return(Corrup);
}
int16 Client::CalcATK() {
int32 Client::CalcATK() {
ATK = itembonuses.ATK + spellbonuses.ATK + aabonuses.ATK + GroupLeadershipAAOffenseEnhancement();
return(ATK);
}
uint16 Mob::GetInstrumentMod(uint16 spell_id) const
uint32 Mob::GetInstrumentMod(uint16 spell_id) const
{
if (GetClass() != BARD)
return 10;
uint16 effectmod = 10;
uint32 effectmod = 10;
int effectmodcap = RuleI(Character, BaseInstrumentSoftCap);
//this should never use spell modifiers...
@@ -1882,7 +1901,7 @@ uint16 Mob::GetInstrumentMod(uint16 spell_id) const
void Client::CalcMaxEndurance()
{
max_end = CalcBaseEndurance() + spellbonuses.Endurance + itembonuses.Endurance;
max_end = CalcBaseEndurance() + spellbonuses.Endurance + itembonuses.Endurance + aabonuses.Endurance;
if (max_end < 0) {
max_end = 0;
+12213 -12014
View File
File diff suppressed because it is too large Load Diff
+281 -277
View File
@@ -1,291 +1,295 @@
void Handle_Connect_OP_SetDataRate(const EQApplicationPacket *app);
void Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app);
void Handle_Connect_OP_SetServerFilter(const EQApplicationPacket *app);
void Handle_Connect_OP_SendAATable(const EQApplicationPacket *app);
void Handle_Connect_OP_SendTributes(const EQApplicationPacket *app);
void Handle_Connect_OP_SendGuildTributes(const EQApplicationPacket *app);
void Handle_Connect_OP_SendAAStats(const EQApplicationPacket *app);
/* 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);
void Handle_Connect_OP_ClientReady(const EQApplicationPacket *app);
void Handle_Connect_OP_ClientUpdate(const EQApplicationPacket *app);
void Handle_Connect_OP_ReqClientSpawn(const EQApplicationPacket *app);
void Handle_Connect_OP_ReqNewZone(const EQApplicationPacket *app);
void Handle_Connect_OP_SendAAStats(const EQApplicationPacket *app);
void Handle_Connect_OP_SendAATable(const EQApplicationPacket *app);
void Handle_Connect_OP_SendExpZonein(const EQApplicationPacket *app);
void Handle_Connect_OP_SendGuildTributes(const EQApplicationPacket *app);
void Handle_Connect_OP_SendTributes(const EQApplicationPacket *app);
void Handle_Connect_OP_SetDataRate(const EQApplicationPacket *app);
void Handle_Connect_OP_SetServerFilter(const EQApplicationPacket *app);
void Handle_Connect_OP_SpawnAppearance(const EQApplicationPacket *app);
void Handle_Connect_OP_TGB(const EQApplicationPacket *app);
void Handle_Connect_OP_UpdateAA(const EQApplicationPacket *app);
void Handle_Connect_OP_WearChange(const EQApplicationPacket *app);
void Handle_Connect_OP_WorldObjectsSent(const EQApplicationPacket *app);
void Handle_Connect_OP_ZoneComplete(const EQApplicationPacket *app);
void Handle_Connect_OP_ReqNewZone(const EQApplicationPacket *app);
void Handle_Connect_OP_SpawnAppearance(const EQApplicationPacket *app);
void Handle_Connect_OP_WearChange(const EQApplicationPacket *app);
void Handle_Connect_OP_ClientUpdate(const EQApplicationPacket *app);
void Handle_Connect_OP_ClientError(const EQApplicationPacket *app);
void Handle_Connect_OP_ApproveZone(const EQApplicationPacket *app);
void Handle_Connect_OP_ClientReady(const EQApplicationPacket *app);
void Handle_Connect_OP_UpdateAA(const EQApplicationPacket *app);
void Handle_Connect_OP_TGB(const EQApplicationPacket *app);
void Handle_OP_ClientUpdate(const EQApplicationPacket *app);
void Handle_OP_AutoAttack(const EQApplicationPacket *app);
void Handle_OP_AutoAttack2(const EQApplicationPacket *app);
void Handle_OP_Consent(const EQApplicationPacket *app);
void Handle_OP_ConsentDeny(const EQApplicationPacket *app);
void Handle_OP_TargetMouse(const EQApplicationPacket *app);
void Handle_OP_TargetCommand(const EQApplicationPacket *app);
void Handle_OP_Shielding(const EQApplicationPacket *app);
void Handle_OP_Jump(const EQApplicationPacket *app);
void Handle_OP_AdventureInfoRequest(const EQApplicationPacket *app);
void Handle_OP_AdventureRequest(const EQApplicationPacket *app);
void Handle_OP_LDoNButton(const EQApplicationPacket *app);
void Handle_OP_LeaveAdventure(const EQApplicationPacket *app);
void Handle_OP_Consume(const EQApplicationPacket *app);
void Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app);
void Handle_OP_AdventureMerchantRequest(const EQApplicationPacket *app);
void Handle_OP_AdventureMerchantPurchase(const EQApplicationPacket *app);
void Handle_OP_ConsiderCorpse(const EQApplicationPacket *app);
void Handle_OP_Consider(const EQApplicationPacket *app);
void Handle_OP_Begging(const EQApplicationPacket *app);
void Handle_OP_TestBuff(const EQApplicationPacket *app);
void Handle_OP_Surname(const EQApplicationPacket *app);
void Handle_OP_ClearSurname(const EQApplicationPacket *app);
void Handle_OP_YellForHelp(const EQApplicationPacket *app);
void Handle_OP_Assist(const EQApplicationPacket *app);
void Handle_OP_AssistGroup(const EQApplicationPacket *app);
void Handle_OP_GMTraining(const EQApplicationPacket *app);
void Handle_OP_GMEndTraining(const EQApplicationPacket *app);
void Handle_OP_GMTrainSkill(const EQApplicationPacket *app);
void Handle_OP_DuelResponse(const EQApplicationPacket *app);
void Handle_OP_DuelResponse2(const EQApplicationPacket *app);
void Handle_OP_RequestDuel(const EQApplicationPacket *app);
void Handle_OP_SpawnAppearance(const EQApplicationPacket *app);
void Handle_OP_BazaarInspect(const EQApplicationPacket *app);
void Handle_OP_Death(const EQApplicationPacket *app);
void Handle_OP_MoveCoin(const EQApplicationPacket *app);
void Handle_OP_ItemLinkClick(const EQApplicationPacket *app);
void Handle_OP_ItemLinkResponse(const EQApplicationPacket *app);
void Handle_OP_MoveItem(const EQApplicationPacket *app);
void Handle_OP_Camp(const EQApplicationPacket *app);
void Handle_OP_Logout(const EQApplicationPacket *app);
void Handle_OP_SenseHeading(const EQApplicationPacket *app);
void Handle_OP_LDoNOpen(const EQApplicationPacket *app);
void Handle_OP_LDoNDisarmTraps(const EQApplicationPacket *app);
void Handle_OP_LDoNSenseTraps(const EQApplicationPacket *app);
void Handle_OP_LDoNInspect(const EQApplicationPacket *app);
void Handle_OP_LDoNPickLock(const EQApplicationPacket *app);
void Handle_OP_FeignDeath(const EQApplicationPacket *app);
void Handle_OP_Sneak(const EQApplicationPacket *app);
void Handle_OP_Hide(const EQApplicationPacket *app);
void Handle_OP_ChannelMessage(const EQApplicationPacket *app);
void Handle_OP_WearChange(const EQApplicationPacket *app);
void Handle_OP_ZoneChange(const EQApplicationPacket *app);
void Handle_OP_DeleteSpawn(const EQApplicationPacket *app);
void Handle_OP_SaveOnZoneReq(const EQApplicationPacket *app);
void Handle_OP_Save(const EQApplicationPacket *app);
void Handle_OP_WhoAllRequest(const EQApplicationPacket *app);
void Handle_OP_GMZoneRequest(const EQApplicationPacket *app);
void Handle_OP_GMZoneRequest2(const EQApplicationPacket *app);
void Handle_OP_EndLootRequest(const EQApplicationPacket *app);
void Handle_OP_LootRequest(const EQApplicationPacket *app);
void Handle_OP_Dye(const EQApplicationPacket *app);
void Handle_OP_LootItem(const EQApplicationPacket *app);
void Handle_OP_GuildDelete(const EQApplicationPacket *app);
void Handle_OP_GuildPublicNote(const EQApplicationPacket *app);
void Handle_OP_GetGuildsList(const EQApplicationPacket *app);
void Handle_OP_SetGuildMOTD(const EQApplicationPacket *app);
void Handle_OP_GuildPeace(const EQApplicationPacket *app);
void Handle_OP_GuildWar(const EQApplicationPacket *app);
void Handle_OP_GuildLeader(const EQApplicationPacket *app);
void Handle_OP_GuildDemote(const EQApplicationPacket *app);
void Handle_OP_GuildInvite(const EQApplicationPacket *app);
void Handle_OP_GuildRemove(const EQApplicationPacket *app);
void Handle_OP_GetGuildMOTD(const EQApplicationPacket *app);
void Handle_OP_GuildManageBanker(const EQApplicationPacket *app);
void Handle_OP_GuildInviteAccept(const EQApplicationPacket *app);
void Handle_OP_ManaChange(const EQApplicationPacket *app);
void Handle_OP_MemorizeSpell(const EQApplicationPacket *app);
void Handle_OP_SwapSpell(const EQApplicationPacket *app);
void Handle_OP_CastSpell(const EQApplicationPacket *app);
void Handle_OP_DeleteItem(const EQApplicationPacket *app);
void Handle_OP_CombatAbility(const EQApplicationPacket *app);
void Handle_OP_Taunt(const EQApplicationPacket *app);
void Handle_OP_InstillDoubt(const EQApplicationPacket *app);
void Handle_OP_RezzAnswer(const EQApplicationPacket *app);
void Handle_OP_GMSummon(const EQApplicationPacket *app);
void Handle_OP_TradeRequest(const EQApplicationPacket *app);
void Handle_OP_TradeRequestAck(const EQApplicationPacket *app);
void Handle_OP_CancelTrade(const EQApplicationPacket *app);
void Handle_OP_TradeAcceptClick(const EQApplicationPacket *app);
void Handle_OP_BoardBoat(const EQApplicationPacket *app);
void Handle_OP_LeaveBoat(const EQApplicationPacket *app);
void Handle_OP_RandomReq(const EQApplicationPacket *app);
void Handle_OP_Buff(const EQApplicationPacket *app);
void Handle_OP_GMHideMe(const EQApplicationPacket *app);
void Handle_OP_GMNameChange(const EQApplicationPacket *app);
void Handle_OP_GMKill(const EQApplicationPacket *app);
void Handle_OP_GMLastName(const EQApplicationPacket *app);
void Handle_OP_GMToggle(const EQApplicationPacket *app);
void Handle_OP_LFGCommand(const EQApplicationPacket *app);
void Handle_OP_GMGoto(const EQApplicationPacket *app);
void Handle_OP_TraderShop(const EQApplicationPacket *app);
void Handle_OP_ShopRequest(const EQApplicationPacket *app);
void Handle_OP_BazaarSearch(const EQApplicationPacket *app);
void Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app);
void Handle_OP_ShopPlayerSell(const EQApplicationPacket *app);
void Handle_OP_ShopEnd(const EQApplicationPacket *app);
// void Handle_OP_CloseContainer(const EQApplicationPacket *app);
void Handle_OP_ClickObjectAction(const EQApplicationPacket *app);
void Handle_OP_ClickObject(const EQApplicationPacket *app);
void Handle_OP_RecipesFavorite(const EQApplicationPacket *app);
void Handle_OP_RecipesSearch(const EQApplicationPacket *app);
void Handle_OP_RecipeDetails(const EQApplicationPacket *app);
void Handle_OP_RecipeAutoCombine(const EQApplicationPacket *app);
void Handle_OP_TradeSkillCombine(const EQApplicationPacket *app);
void Handle_OP_ItemName(const EQApplicationPacket *app);
void Handle_OP_AugmentItem(const EQApplicationPacket *app);
void Handle_OP_ClickDoor(const EQApplicationPacket *app);
void Handle_OP_CreateObject(const EQApplicationPacket *app);
void Handle_OP_FaceChange(const EQApplicationPacket *app);
void Handle_OP_GroupInvite(const EQApplicationPacket *app);
void Handle_OP_GroupInvite2(const EQApplicationPacket *app);
void Handle_OP_GroupAcknowledge(const EQApplicationPacket *app);
void Handle_OP_GroupCancelInvite(const EQApplicationPacket *app);
void Handle_OP_GroupFollow(const EQApplicationPacket *app);
void Handle_OP_GroupFollow2(const EQApplicationPacket *app);
void Handle_OP_GroupDisband(const EQApplicationPacket *app);
void Handle_OP_GroupDelete(const EQApplicationPacket *app);
void Handle_OP_GMEmoteZone(const EQApplicationPacket *app);
void Handle_OP_InspectRequest(const EQApplicationPacket *app);
void Handle_OP_InspectAnswer(const EQApplicationPacket *app);
void Handle_OP_InspectMessageUpdate(const EQApplicationPacket *app);
void Handle_OP_Medding(const EQApplicationPacket *app);
void Handle_OP_DeleteSpell(const EQApplicationPacket *app);
void Handle_OP_PetitionBug(const EQApplicationPacket *app);
void Handle_OP_Bug(const EQApplicationPacket *app);
void Handle_OP_Petition(const EQApplicationPacket *app);
void Handle_OP_PetitionCheckIn(const EQApplicationPacket *app);
void Handle_OP_PetitionResolve(const EQApplicationPacket *app);
void Handle_OP_PetitionDelete(const EQApplicationPacket *app);
void Handle_OP_PetCommands(const EQApplicationPacket *app);
void Handle_OP_PetitionUnCheckout(const EQApplicationPacket *app);
void Handle_OP_PetitionQue(const EQApplicationPacket *app);
void Handle_OP_PDeletePetition(const EQApplicationPacket *app);
void Handle_OP_PetitionCheckout(const EQApplicationPacket *app);
void Handle_OP_PetitionRefresh(const EQApplicationPacket *app);
void Handle_OP_ReadBook(const EQApplicationPacket *app);
void Handle_OP_Emote(const EQApplicationPacket *app);
void Handle_OP_Animation(const EQApplicationPacket *app);
void Handle_OP_SetServerFilter(const EQApplicationPacket *app);
void Handle_OP_GMDelCorpse(const EQApplicationPacket *app);
void Handle_OP_GMKick(const EQApplicationPacket *app);
void Handle_OP_GMServers(const EQApplicationPacket *app);
void Handle_OP_Illusion(const EQApplicationPacket *app);
void Handle_OP_GMBecomeNPC(const EQApplicationPacket *app);
void Handle_OP_Fishing(const EQApplicationPacket *app);
void Handle_OP_Forage(const EQApplicationPacket *app);
void Handle_OP_Mend(const EQApplicationPacket *app);
void Handle_OP_EnvDamage(const EQApplicationPacket *app);
void Handle_OP_Damage(const EQApplicationPacket *app);
void Handle_OP_AAAction(const EQApplicationPacket *app);
void Handle_OP_TraderBuy(const EQApplicationPacket *app);
void Handle_OP_Trader(const EQApplicationPacket *app);
void Handle_OP_GMFind(const EQApplicationPacket *app);
void Handle_OP_PickPocket(const EQApplicationPacket *app);
void Handle_OP_Bind_Wound(const EQApplicationPacket *app);
void Handle_OP_TrackTarget(const EQApplicationPacket *app);
void Handle_OP_Track(const EQApplicationPacket *app);
void Handle_OP_TrackUnknown(const EQApplicationPacket *app);
void Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app);
/* Connected opcode handlers*/
void Handle_0x0193(const EQApplicationPacket *app);
void Handle_0x01e7(const EQApplicationPacket *app);
void Handle_OP_ClientError(const EQApplicationPacket *app);
void Handle_OP_ReloadUI(const EQApplicationPacket *app);
void Handle_OP_TGB(const EQApplicationPacket *app);
void Handle_OP_Split(const EQApplicationPacket *app);
void Handle_OP_SenseTraps(const EQApplicationPacket *app);
void Handle_OP_DisarmTraps(const EQApplicationPacket *app);
void Handle_OP_OpenTributeMaster(const EQApplicationPacket *app);
void Handle_OP_OpenGuildTributeMaster(const EQApplicationPacket *app);
void Handle_OP_TributeItem(const EQApplicationPacket *app);
void Handle_OP_TributeMoney(const EQApplicationPacket *app);
void Handle_OP_SelectTribute(const EQApplicationPacket *app);
void Handle_OP_TributeUpdate(const EQApplicationPacket *app);
void Handle_OP_TributeToggle(const EQApplicationPacket *app);
void Handle_OP_TributeNPC(const EQApplicationPacket *app);
void Handle_OP_ConfirmDelete(const EQApplicationPacket *app);
void Handle_OP_CrashDump(const EQApplicationPacket *app);
void Handle_OP_ControlBoat(const EQApplicationPacket *app);
void Handle_OP_DumpName(const EQApplicationPacket *app);
void Handle_OP_SetRunMode(const EQApplicationPacket *app);
void Handle_OP_SafeFallSuccess(const EQApplicationPacket *app);
void Handle_OP_Heartbeat(const EQApplicationPacket *app);
void Handle_OP_SafePoint(const EQApplicationPacket *app);
void Handle_OP_FindPersonRequest(const EQApplicationPacket *app);
void Handle_OP_BankerChange(const EQApplicationPacket *app);
void Handle_OP_LeadershipExpToggle(const EQApplicationPacket *app);
void Handle_OP_SetTitle(const EQApplicationPacket *app);
void Handle_OP_RequestTitles(const EQApplicationPacket *app);
void Handle_OP_PurchaseLeadershipAA(const EQApplicationPacket *app);
void Handle_OP_Ignore(const EQApplicationPacket *app);
void Handle_OP_LoadSpellSet(const EQApplicationPacket *app);
void Handle_OP_AutoFire(const EQApplicationPacket *app);
void Handle_OP_Rewind(const EQApplicationPacket *app);
void Handle_OP_RaidCommand(const EQApplicationPacket *app);
void Handle_OP_Translocate(const EQApplicationPacket *app);
void Handle_OP_Sacrifice(const EQApplicationPacket *app);
void Handle_OP_AAAction(const EQApplicationPacket *app);
void Handle_OP_AcceptNewTask(const EQApplicationPacket *app);
void Handle_OP_CancelTask(const EQApplicationPacket *app);
void Handle_OP_TaskHistoryRequest(const EQApplicationPacket *app);
void Handle_OP_KeyRing(const EQApplicationPacket *app);
void Handle_OP_FriendsWho(const EQApplicationPacket *app);
void Handle_OP_Bandolier(const EQApplicationPacket *app);
void Handle_OP_PopupResponse(const EQApplicationPacket *app);
void Handle_OP_PotionBelt(const EQApplicationPacket *app);
void Handle_OP_LFGGetMatchesRequest(const EQApplicationPacket *app);
void Handle_OP_LFPCommand(const EQApplicationPacket *app);
void Handle_OP_LFPGetMatchesRequest(const EQApplicationPacket *app);
void Handle_OP_Barter(const EQApplicationPacket *app);
void Handle_OP_VoiceMacroIn(const EQApplicationPacket *app);
void Handle_OP_DoGroupLeadershipAbility(const EQApplicationPacket *app);
void Handle_OP_ClearNPCMarks(const EQApplicationPacket *app);
void Handle_OP_DelegateAbility(const EQApplicationPacket *app);
void Handle_OP_ApplyPoison(const EQApplicationPacket *app);
void Handle_OP_AugmentInfo(const EQApplicationPacket *app);
void Handle_OP_PVPLeaderBoardRequest(const EQApplicationPacket *app);
void Handle_OP_PVPLeaderBoardDetailsRequest(const EQApplicationPacket *app);
void Handle_OP_AdventureMerchantSell(const EQApplicationPacket *app);
void Handle_OP_AdventureStatsRequest(const EQApplicationPacket *app);
void Handle_OP_AdventureInfoRequest(const EQApplicationPacket *app);
void Handle_OP_AdventureLeaderboardRequest(const EQApplicationPacket *app);
void Handle_OP_RespawnWindow(const EQApplicationPacket *app);
void Handle_OP_GroupUpdate(const EQApplicationPacket *app);
void Handle_OP_SetStartCity(const EQApplicationPacket *app);
void Handle_OP_Report(const EQApplicationPacket *app);
void Handle_OP_VetClaimRequest(const EQApplicationPacket *app);
void Handle_OP_GMSearchCorpse(const EQApplicationPacket *app);
void Handle_OP_GuildBank(const EQApplicationPacket *app);
void Handle_OP_GroupRoles(const EQApplicationPacket *app);
void Handle_OP_HideCorpse(const EQApplicationPacket *app);
void Handle_OP_TradeBusy(const EQApplicationPacket *app);
void Handle_OP_GuildUpdateURLAndChannel(const EQApplicationPacket *app);
void Handle_OP_GuildStatus(const EQApplicationPacket *app);
void Handle_OP_BlockedBuffs(const EQApplicationPacket *app);
void Handle_OP_RemoveBlockedBuffs(const EQApplicationPacket *app);
void Handle_OP_ClearBlockedBuffs(const EQApplicationPacket *app);
void Handle_OP_BuffRemoveRequest(const EQApplicationPacket *app);
void Handle_OP_CorpseDrag(const EQApplicationPacket *app);
void Handle_OP_CorpseDrop(const EQApplicationPacket *app);
void Handle_OP_GroupMakeLeader(const EQApplicationPacket *app);
void Handle_OP_GuildCreate(const EQApplicationPacket *app);
void Handle_OP_AdventureMerchantPurchase(const EQApplicationPacket *app);
void Handle_OP_AdventureMerchantRequest(const EQApplicationPacket *app);
void Handle_OP_AdventureMerchantSell(const EQApplicationPacket *app);
void Handle_OP_AdventureRequest(const EQApplicationPacket *app);
void Handle_OP_AdventureStatsRequest(const EQApplicationPacket *app);
void Handle_OP_AltCurrencyMerchantRequest(const EQApplicationPacket *app);
void Handle_OP_AltCurrencySellSelection(const EQApplicationPacket *app);
void Handle_OP_AltCurrencyPurchase(const EQApplicationPacket *app);
void Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app);
void Handle_OP_AltCurrencySell(const EQApplicationPacket *app);
void Handle_OP_CrystalReclaim(const EQApplicationPacket *app);
void Handle_OP_CrystalCreate(const EQApplicationPacket *app);
void Handle_OP_LFGuild(const EQApplicationPacket *app);
void Handle_OP_XTargetRequest(const EQApplicationPacket *app);
void Handle_OP_XTargetAutoAddHaters(const EQApplicationPacket *app);
void Handle_OP_ItemPreview(const EQApplicationPacket *app);
void Handle_OP_MercenaryDataRequest(const EQApplicationPacket *app);
void Handle_OP_MercenaryHire(const EQApplicationPacket *app);
void Handle_OP_MercenaryCommand(const EQApplicationPacket *app);
void Handle_OP_MercenaryDataUpdateRequest(const EQApplicationPacket *app);
void Handle_OP_MercenarySuspendRequest(const EQApplicationPacket *app);
void Handle_OP_MercenaryDismiss(const EQApplicationPacket *app);
void Handle_OP_MercenaryTimerRequest(const EQApplicationPacket *app);
void Handle_OP_OpenInventory(const EQApplicationPacket *app);
void Handle_OP_OpenContainer(const EQApplicationPacket *app);
void Handle_OP_AltCurrencySellSelection(const EQApplicationPacket *app);
void Handle_OP_Animation(const EQApplicationPacket *app);
void Handle_OP_ApplyPoison(const EQApplicationPacket *app);
void Handle_OP_Assist(const EQApplicationPacket *app);
void Handle_OP_AssistGroup(const EQApplicationPacket *app);
void Handle_OP_AugmentInfo(const EQApplicationPacket *app);
void Handle_OP_AugmentItem(const EQApplicationPacket *app);
void Handle_OP_AutoAttack(const EQApplicationPacket *app);
void Handle_OP_AutoAttack2(const EQApplicationPacket *app);
void Handle_OP_AutoFire(const EQApplicationPacket *app);
void Handle_OP_Bandolier(const EQApplicationPacket *app);
void Handle_OP_BankerChange(const EQApplicationPacket *app);
void Handle_OP_Barter(const EQApplicationPacket *app);
void Handle_OP_BazaarInspect(const EQApplicationPacket *app);
void Handle_OP_BazaarSearch(const EQApplicationPacket *app);
void Handle_OP_Begging(const EQApplicationPacket *app);
void Handle_OP_Bind_Wound(const EQApplicationPacket *app);
void Handle_OP_BlockedBuffs(const EQApplicationPacket *app);
void Handle_OP_BoardBoat(const EQApplicationPacket *app);
void Handle_OP_Buff(const EQApplicationPacket *app);
void Handle_OP_BuffRemoveRequest(const EQApplicationPacket *app);
void Handle_OP_Bug(const EQApplicationPacket *app);
void Handle_OP_Camp(const EQApplicationPacket *app);
void Handle_OP_CancelTask(const EQApplicationPacket *app);
void Handle_OP_CancelTrade(const EQApplicationPacket *app);
void Handle_OP_CastSpell(const EQApplicationPacket *app);
void Handle_OP_ChannelMessage(const EQApplicationPacket *app);
void Handle_OP_ClearBlockedBuffs(const EQApplicationPacket *app);
void Handle_OP_ClearNPCMarks(const EQApplicationPacket *app);
void Handle_OP_ClearSurname(const EQApplicationPacket *app);
void Handle_OP_ClickDoor(const EQApplicationPacket *app);
void Handle_OP_ClickObject(const EQApplicationPacket *app);
void Handle_OP_ClickObjectAction(const EQApplicationPacket *app);
void Handle_OP_ClientError(const EQApplicationPacket *app);
void Handle_OP_ClientTimeStamp(const EQApplicationPacket *app);
void Handle_OP_ClientUpdate(const EQApplicationPacket *app);
// void Handle_OP_CloseContainer(const EQApplicationPacket *app);
void Handle_OP_CombatAbility(const EQApplicationPacket *app);
void Handle_OP_ConfirmDelete(const EQApplicationPacket *app);
void Handle_OP_Consent(const EQApplicationPacket *app);
void Handle_OP_ConsentDeny(const EQApplicationPacket *app);
void Handle_OP_Consider(const EQApplicationPacket *app);
void Handle_OP_ConsiderCorpse(const EQApplicationPacket *app);
void Handle_OP_Consume(const EQApplicationPacket *app);
void Handle_OP_ControlBoat(const EQApplicationPacket *app);
void Handle_OP_CorpseDrag(const EQApplicationPacket *app);
void Handle_OP_CorpseDrop(const EQApplicationPacket *app);
void Handle_OP_CrashDump(const EQApplicationPacket *app);
void Handle_OP_CreateObject(const EQApplicationPacket *app);
void Handle_OP_CrystalCreate(const EQApplicationPacket *app);
void Handle_OP_CrystalReclaim(const EQApplicationPacket *app);
void Handle_OP_Damage(const EQApplicationPacket *app);
void Handle_OP_Death(const EQApplicationPacket *app);
void Handle_OP_DelegateAbility(const EQApplicationPacket *app);
void Handle_OP_DeleteItem(const EQApplicationPacket *app);
void Handle_OP_DeleteSpawn(const EQApplicationPacket *app);
void Handle_OP_DeleteSpell(const EQApplicationPacket *app);
void Handle_OP_DisarmTraps(const EQApplicationPacket *app);
void Handle_OP_DoGroupLeadershipAbility(const EQApplicationPacket *app);
void Handle_OP_DuelResponse(const EQApplicationPacket *app);
void Handle_OP_DuelResponse2(const EQApplicationPacket *app);
void Handle_OP_DumpName(const EQApplicationPacket *app);
void Handle_OP_Dye(const EQApplicationPacket *app);
void Handle_OP_Emote(const EQApplicationPacket *app);
void Handle_OP_EndLootRequest(const EQApplicationPacket *app);
void Handle_OP_EnvDamage(const EQApplicationPacket *app);
void Handle_OP_FaceChange(const EQApplicationPacket *app);
void Handle_OP_FeignDeath(const EQApplicationPacket *app);
void Handle_OP_FindPersonRequest(const EQApplicationPacket *app);
void Handle_OP_Fishing(const EQApplicationPacket *app);
void Handle_OP_Forage(const EQApplicationPacket *app);
void Handle_OP_FriendsWho(const EQApplicationPacket *app);
void Handle_OP_GetGuildMOTD(const EQApplicationPacket *app);
void Handle_OP_GetGuildsList(const EQApplicationPacket *app);
void Handle_OP_GMBecomeNPC(const EQApplicationPacket *app);
void Handle_OP_GMDelCorpse(const EQApplicationPacket *app);
void Handle_OP_GMEmoteZone(const EQApplicationPacket *app);
void Handle_OP_GMEndTraining(const EQApplicationPacket *app);
void Handle_OP_GMFind(const EQApplicationPacket *app);
void Handle_OP_GMGoto(const EQApplicationPacket *app);
void Handle_OP_GMHideMe(const EQApplicationPacket *app);
void Handle_OP_GMKick(const EQApplicationPacket *app);
void Handle_OP_GMKill(const EQApplicationPacket *app);
void Handle_OP_GMLastName(const EQApplicationPacket *app);
void Handle_OP_GMNameChange(const EQApplicationPacket *app);
void Handle_OP_GMSearchCorpse(const EQApplicationPacket *app);
void Handle_OP_GMServers(const EQApplicationPacket *app);
void Handle_OP_GMSummon(const EQApplicationPacket *app);
void Handle_OP_GMToggle(const EQApplicationPacket *app);
void Handle_OP_GMTraining(const EQApplicationPacket *app);
void Handle_OP_GMTrainSkill(const EQApplicationPacket *app);
void Handle_OP_GMZoneRequest(const EQApplicationPacket *app);
void Handle_OP_GMZoneRequest2(const EQApplicationPacket *app);
void Handle_OP_GroupAcknowledge(const EQApplicationPacket *app);
void Handle_OP_GroupCancelInvite(const EQApplicationPacket *app);
void Handle_OP_GroupDelete(const EQApplicationPacket *app);
void Handle_OP_GroupDisband(const EQApplicationPacket *app);
void Handle_OP_GroupFollow(const EQApplicationPacket *app);
void Handle_OP_GroupFollow2(const EQApplicationPacket *app);
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);
void Handle_OP_GuildCreate(const EQApplicationPacket *app);
void Handle_OP_GuildDelete(const EQApplicationPacket *app);
void Handle_OP_GuildDemote(const EQApplicationPacket *app);
void Handle_OP_GuildInvite(const EQApplicationPacket *app);
void Handle_OP_GuildInviteAccept(const EQApplicationPacket *app);
void Handle_OP_GuildLeader(const EQApplicationPacket *app);
void Handle_OP_GuildManageBanker(const EQApplicationPacket *app);
void Handle_OP_GuildPeace(const EQApplicationPacket *app);
void Handle_OP_GuildPromote(const EQApplicationPacket *app);
void Handle_OP_GuildPublicNote(const EQApplicationPacket *app);
void Handle_OP_GuildRemove(const EQApplicationPacket *app);
void Handle_OP_GuildStatus(const EQApplicationPacket *app);
void Handle_OP_GuildUpdateURLAndChannel(const EQApplicationPacket *app);
void Handle_OP_GuildWar(const EQApplicationPacket *app);
void Handle_OP_Heartbeat(const EQApplicationPacket *app);
void Handle_OP_Hide(const EQApplicationPacket *app);
void Handle_OP_HideCorpse(const EQApplicationPacket *app);
void Handle_OP_Ignore(const EQApplicationPacket *app);
void Handle_OP_Illusion(const EQApplicationPacket *app);
void Handle_OP_InspectAnswer(const EQApplicationPacket *app);
void Handle_OP_InspectMessageUpdate(const EQApplicationPacket *app);
void Handle_OP_InspectRequest(const EQApplicationPacket *app);
void Handle_OP_InstillDoubt(const EQApplicationPacket *app);
void Handle_OP_ItemLinkClick(const EQApplicationPacket *app);
void Handle_OP_ItemLinkResponse(const EQApplicationPacket *app);
void Handle_OP_ItemName(const EQApplicationPacket *app);
void Handle_OP_ItemPreview(const EQApplicationPacket *app);
void Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app);
void Handle_OP_Jump(const EQApplicationPacket *app);
void Handle_OP_KeyRing(const EQApplicationPacket *app);
void Handle_OP_LDoNButton(const EQApplicationPacket *app);
void Handle_OP_LDoNDisarmTraps(const EQApplicationPacket *app);
void Handle_OP_LDoNInspect(const EQApplicationPacket *app);
void Handle_OP_LDoNOpen(const EQApplicationPacket *app);
void Handle_OP_LDoNPickLock(const EQApplicationPacket *app);
void Handle_OP_LDoNSenseTraps(const EQApplicationPacket *app);
void Handle_OP_LeadershipExpToggle(const EQApplicationPacket *app);
void Handle_OP_LeaveAdventure(const EQApplicationPacket *app);
void Handle_OP_LeaveBoat(const EQApplicationPacket *app);
void Handle_OP_LFGCommand(const EQApplicationPacket *app);
void Handle_OP_LFGGetMatchesRequest(const EQApplicationPacket *app);
void Handle_OP_LFGuild(const EQApplicationPacket *app);
void Handle_OP_LFPCommand(const EQApplicationPacket *app);
void Handle_OP_LFPGetMatchesRequest(const EQApplicationPacket *app);
void Handle_OP_LoadSpellSet(const EQApplicationPacket *app);
void Handle_OP_Logout(const EQApplicationPacket *app);
void Handle_OP_LootItem(const EQApplicationPacket *app);
void Handle_OP_LootRequest(const EQApplicationPacket *app);
void Handle_OP_ManaChange(const EQApplicationPacket *app);
void Handle_OP_Medding(const EQApplicationPacket *app);
void Handle_OP_MemorizeSpell(const EQApplicationPacket *app);
void Handle_OP_Mend(const EQApplicationPacket *app);
void Handle_OP_MercenaryCommand(const EQApplicationPacket *app);
void Handle_OP_MercenaryDataRequest(const EQApplicationPacket *app);
void Handle_OP_MercenaryDataUpdateRequest(const EQApplicationPacket *app);
void Handle_OP_MercenaryDismiss(const EQApplicationPacket *app);
void Handle_OP_MercenaryHire(const EQApplicationPacket *app);
void Handle_OP_MercenarySuspendRequest(const EQApplicationPacket *app);
void Handle_OP_MercenaryTimerRequest(const EQApplicationPacket *app);
void Handle_OP_MoveCoin(const EQApplicationPacket *app);
void Handle_OP_MoveItem(const EQApplicationPacket *app);
void Handle_OP_OpenContainer(const EQApplicationPacket *app);
void Handle_OP_OpenGuildTributeMaster(const EQApplicationPacket *app);
void Handle_OP_OpenInventory(const EQApplicationPacket *app);
void Handle_OP_OpenTributeMaster(const EQApplicationPacket *app);
void Handle_OP_PDeletePetition(const EQApplicationPacket *app);
void Handle_OP_PetCommands(const EQApplicationPacket *app);
void Handle_OP_Petition(const EQApplicationPacket *app);
void Handle_OP_PetitionBug(const EQApplicationPacket *app);
void Handle_OP_PetitionCheckIn(const EQApplicationPacket *app);
void Handle_OP_PetitionCheckout(const EQApplicationPacket *app);
void Handle_OP_PetitionDelete(const EQApplicationPacket *app);
void Handle_OP_PetitionQue(const EQApplicationPacket *app);
void Handle_OP_PetitionRefresh(const EQApplicationPacket *app);
void Handle_OP_PetitionResolve(const EQApplicationPacket *app);
void Handle_OP_PetitionUnCheckout(const EQApplicationPacket *app);
void Handle_OP_PickPocket(const EQApplicationPacket *app);
void Handle_OP_PopupResponse(const EQApplicationPacket *app);
void Handle_OP_PotionBelt(const EQApplicationPacket *app);
void Handle_OP_PurchaseLeadershipAA(const EQApplicationPacket *app);
void Handle_OP_PVPLeaderBoardDetailsRequest(const EQApplicationPacket *app);
void Handle_OP_PVPLeaderBoardRequest(const EQApplicationPacket *app);
void Handle_OP_RaidCommand(const EQApplicationPacket *app);
void Handle_OP_RandomReq(const EQApplicationPacket *app);
void Handle_OP_ReadBook(const EQApplicationPacket *app);
void Handle_OP_RecipeAutoCombine(const EQApplicationPacket *app);
void Handle_OP_RecipeDetails(const EQApplicationPacket *app);
void Handle_OP_RecipesFavorite(const EQApplicationPacket *app);
void Handle_OP_RecipesSearch(const EQApplicationPacket *app);
void Handle_OP_ReloadUI(const EQApplicationPacket *app);
void Handle_OP_RemoveBlockedBuffs(const EQApplicationPacket *app);
void Handle_OP_Report(const EQApplicationPacket *app);
void Handle_OP_RequestDuel(const EQApplicationPacket *app);
void Handle_OP_RequestTitles(const EQApplicationPacket *app);
void Handle_OP_RespawnWindow(const EQApplicationPacket *app);
void Handle_OP_Rewind(const EQApplicationPacket *app);
void Handle_OP_RezzAnswer(const EQApplicationPacket *app);
void Handle_OP_Sacrifice(const EQApplicationPacket *app);
void Handle_OP_SafeFallSuccess(const EQApplicationPacket *app);
void Handle_OP_SafePoint(const EQApplicationPacket *app);
void Handle_OP_Save(const EQApplicationPacket *app);
void Handle_OP_SaveOnZoneReq(const EQApplicationPacket *app);
void Handle_OP_SelectTribute(const EQApplicationPacket *app);
void Handle_OP_SenseHeading(const EQApplicationPacket *app);
void Handle_OP_SenseTraps(const EQApplicationPacket *app);
void Handle_OP_SetGuildMOTD(const EQApplicationPacket *app);
void Handle_OP_SetRunMode(const EQApplicationPacket *app);
void Handle_OP_SetServerFilter(const EQApplicationPacket *app);
void Handle_OP_SetStartCity(const EQApplicationPacket *app);
void Handle_OP_SetTitle(const EQApplicationPacket *app);
void Handle_OP_Shielding(const EQApplicationPacket *app);
void Handle_OP_ShopEnd(const EQApplicationPacket *app);
void Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app);
void Handle_OP_ShopPlayerSell(const EQApplicationPacket *app);
void Handle_OP_ShopRequest(const EQApplicationPacket *app);
void Handle_OP_Sneak(const EQApplicationPacket *app);
void Handle_OP_SpawnAppearance(const EQApplicationPacket *app);
void Handle_OP_Split(const EQApplicationPacket *app);
void Handle_OP_Surname(const EQApplicationPacket *app);
void Handle_OP_SwapSpell(const EQApplicationPacket *app);
void Handle_OP_TargetCommand(const EQApplicationPacket *app);
void Handle_OP_TargetMouse(const EQApplicationPacket *app);
void Handle_OP_TaskHistoryRequest(const EQApplicationPacket *app);
void Handle_OP_Taunt(const EQApplicationPacket *app);
void Handle_OP_TestBuff(const EQApplicationPacket *app);
void Handle_OP_TGB(const EQApplicationPacket *app);
void Handle_OP_Track(const EQApplicationPacket *app);
void Handle_OP_TrackTarget(const EQApplicationPacket *app);
void Handle_OP_TrackUnknown(const EQApplicationPacket *app);
void Handle_OP_TradeAcceptClick(const EQApplicationPacket *app);
void Handle_OP_TradeBusy(const EQApplicationPacket *app);
void Handle_OP_Trader(const EQApplicationPacket *app);
void Handle_OP_TraderBuy(const EQApplicationPacket *app);
void Handle_OP_TradeRequest(const EQApplicationPacket *app);
void Handle_OP_TradeRequestAck(const EQApplicationPacket *app);
void Handle_OP_TraderShop(const EQApplicationPacket *app);
void Handle_OP_TradeSkillCombine(const EQApplicationPacket *app);
void Handle_OP_Translocate(const EQApplicationPacket *app);
void Handle_OP_TributeItem(const EQApplicationPacket *app);
void Handle_OP_TributeMoney(const EQApplicationPacket *app);
void Handle_OP_TributeNPC(const EQApplicationPacket *app);
void Handle_OP_TributeToggle(const EQApplicationPacket *app);
void Handle_OP_TributeUpdate(const EQApplicationPacket *app);
void Handle_OP_VetClaimRequest(const EQApplicationPacket *app);
void Handle_OP_VoiceMacroIn(const EQApplicationPacket *app);
void Handle_OP_WearChange(const EQApplicationPacket *app);
void Handle_OP_WhoAllRequest(const EQApplicationPacket *app);
void Handle_OP_XTargetAutoAddHaters(const EQApplicationPacket *app);
void Handle_OP_XTargetRequest(const EQApplicationPacket *app);
void Handle_OP_YellForHelp(const EQApplicationPacket *app);
void Handle_OP_ZoneChange(const EQApplicationPacket *app);
+155 -125
View File
@@ -20,13 +20,8 @@
*/
#include "../common/debug.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 +36,22 @@
#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/StringUtil.h"
#include "../common/spdat.h"
#include "petitions.h"
#include "NpcAI.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 "StringIDs.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 "QuestParserCollection.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;
extern volatile bool ZoneLoaded;
extern WorldServer worldserver;
@@ -76,7 +64,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();
}
@@ -143,10 +132,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;
@@ -174,14 +165,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)
{
@@ -190,7 +183,8 @@ bool Client::Process() {
return false; //delete client
}
if (camp_timer.Check()) {
if (camp_timer.Check())
{
LeaveGroup();
Save();
if (GetMerc())
@@ -226,20 +220,21 @@ 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();
}
if(p_timers.Expired(&database, pTimerMercSuspend, false))
{
CheckMercSuspendTimer();
}
}
if(IsAIControlled())
@@ -570,8 +565,7 @@ bool Client::Process() {
viral_timer_counter = 0;
}
if(projectile_timer.Check())
SpellProjectileEffect();
ProjectileAttack();
if(spellbonuses.GravityEffect == 1) {
if(gravity_timer.Check())
@@ -713,16 +707,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())
@@ -730,23 +721,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);
}
@@ -770,38 +770,47 @@ bool Client::Process() {
return ret;
}
//just a set of actions preformed all over in Client::Process
/* Just a set of actions preformed all over in Client::Process */
void Client::OnDisconnect(bool hard_disconnect) {
if(hard_disconnect) {
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();
Mob *Other = trade->With();
if(Other)
{
mlog(TRADING__CLIENT, "Client disconnected during a trade. Returning their items.");
mlog(TRADING__CLIENT, "Client disconnected during a trade. Returning their items.");
FinishTrade(this);
if(Other->IsClient())
Other->CastToClient()->FinishTrade(Other);
trade->Reset();
/* Reset both sides of the trade */
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);
@@ -832,8 +841,6 @@ void Client::BulkSendInventoryItems() {
}
}
// Where are cursor buffer items processed? They need to be validated as well... -U
bool deletenorent = database.NoRentExpired(GetName());
if(deletenorent){ RemoveNoRent(false); } //client was offline for more than 30 minutes, delete no rent items
@@ -965,92 +972,96 @@ 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.
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(GetLevel() < ml.level_required) {
if (merch->CastToNPC()->GetMerchantProbability() > ml.probability)
continue;
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 = MakeRandomInt(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)
LogFile->write(EQEMuLog::Debug, "(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)
@@ -1066,32 +1077,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 = MakeRandomInt(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());
}
@@ -1544,7 +1555,12 @@ 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{
if (to_bucket == &m_pp.platinum_shared || from_bucket == &m_pp.platinum_shared){
this->Message(13, "::: WARNING! ::: SHARED BANK IS DISABLED AND YOUR PLATINUM WILL BE DESTROYED IF YOU PUT IT HERE");
}
}
}
@@ -1577,7 +1593,7 @@ void Client::OPMoveCoin(const EQApplicationPacket* app)
safe_delete(outapp);
}
Save();
SaveCurrency();
}
void Client::OPGMTraining(const EQApplicationPacket *app)
@@ -1600,16 +1616,19 @@ void Client::OPGMTraining(const EQApplicationPacket *app)
if(DistNoRoot(*pTrainer) > 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
@@ -1712,6 +1731,7 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app)
}
uint16 skilllevel = GetRawSkill(skill);
if(skilllevel == 0) {
//this is a new skill..
uint16 t_level = SkillTrainLevel(skill, GetClass());
@@ -1721,7 +1741,7 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app)
}
SetSkill(skill, t_level);
} else {
} else {
switch(skill) {
case SkillBrewing:
case SkillMakePoison:
@@ -1917,16 +1937,21 @@ void Client::DoEnduranceRegen()
}
void Client::DoEnduranceUpkeep() {
if (!HasEndurUpkeep())
return;
int upkeep_sum = 0;
int cost_redux = spellbonuses.EnduranceReduction + itembonuses.EnduranceReduction;
int cost_redux = spellbonuses.EnduranceReduction + itembonuses.EnduranceReduction + aabonuses.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
@@ -1946,6 +1971,9 @@ void Client::DoEnduranceUpkeep() {
SetEndurance(GetEndurance() - upkeep_sum);
TryTriggerOnValueAmount(false, false, true);
}
if (!has_effect)
SetEndurUpkeep(false);
}
void Client::CalcRestState() {
@@ -2076,7 +2104,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;
@@ -2085,7 +2114,7 @@ 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)
{
@@ -2129,8 +2158,8 @@ void Client::HandleRespawnFromHover(uint32 Option)
_log(SPELLS__REZ, "Found corpse. Marking corpse as rezzed.");
corpse->Rezzed(true);
corpse->CompleteRezz();
corpse->IsRezzed(true);
corpse->CompleteResurrection();
}
}
else //Not rez
@@ -2141,6 +2170,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;
@@ -2186,13 +2216,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);
+2876 -3686
View File
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -20,9 +20,10 @@
#ifndef COMMAND_H
#define COMMAND_H
#include "../common/seperator.h"
#include "../common/EQStream.h"
#include "client.h"
class Client;
class Seperator;
#include "../common/types.h"
#define COMMAND_CHAR '#'
#define CMDALIASES 5
@@ -125,7 +126,6 @@ void command_worldshutdown(Client *c, const Seperator *sep);
void command_sendzonespawns(Client *c, const Seperator *sep);
void command_zsave(Client *c, const Seperator *sep);
void command_dbspawn2(Client *c, const Seperator *sep);
void command_copychar(Client *c, const Seperator *sep);
void command_shutdown(Client *c, const Seperator *sep);
void command_delacct(Client *c, const Seperator *sep);
void command_setpass(Client *c, const Seperator *sep);
@@ -151,9 +151,9 @@ void command_texture(Client *c, const Seperator *sep);
void command_npctypespawn(Client *c, const Seperator *sep);
void command_heal(Client *c, const Seperator *sep);
void command_appearance(Client *c, const Seperator *sep);
void command_charbackup(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);
@@ -217,7 +217,6 @@ void command_guild(Client *c, const Seperator *sep);
bool helper_guild_edit(Client *c, uint32 dbid, uint32 eqid, uint8 rank, const char* what, const char* value);
void command_zonestatus(Client *c, const Seperator *sep);
void command_manaburn(Client *c, const Seperator *sep);
void command_viewmessage(Client *c, const Seperator *sep);
void command_doanim(Client *c, const Seperator *sep);
void command_randomfeatures(Client *c, const Seperator *sep);
void command_face(Client *c, const Seperator *sep);
@@ -325,6 +324,7 @@ void command_showspellslist(Client *c, const Seperator *sep);
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);
#ifdef EQPROFILE
void command_profiledump(Client *c, const Seperator *sep);
+196 -167
View File
@@ -17,6 +17,11 @@
#define _NPCPET(x) (x && x->IsNPC() && x->CastToMob()->GetOwner() && x->CastToMob()->GetOwner()->IsNPC())
#define _BECOMENPCPET(x) (x && x->CastToMob()->GetOwner() && x->CastToMob()->GetOwner()->IsClient() && x->CastToMob()->GetOwner()->CastToClient()->IsBecomeNPC())
#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
//LOS Parameters:
#define HEAD_POSITION 0.9f //ratio of GetSize() where NPCs see from
@@ -127,7 +132,9 @@ enum {
FLEE_PERCENT = 37,
ALLOW_BENEFICIAL = 38,
DISABLE_MELEE = 39,
MAX_SPECIAL_ATTACK = 40
NPC_CHASE_DISTANCE = 40,
ALLOW_TO_TANK = 41,
MAX_SPECIAL_ATTACK = 42
};
@@ -187,7 +194,7 @@ struct Buffs_Struct {
};
struct StatBonuses {
int16 AC;
int32 AC;
int32 HP;
int32 HPRegen;
int32 MaxHP;
@@ -195,47 +202,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;
@@ -245,90 +252,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
int16 StunResist; //i
int16 MeleeSkillCheck; //i
bool IsBlind; //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
@@ -336,64 +344,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[1]; // For buff stack blocking 0=Exists 1=Effect_value
int16 BStacker[1]; // For buff stack blocking 0=Exists 1=Effect_value
int16 CStacker[1]; // For buff stack blocking 0=Exists 1=Effect_value
int16 DStacker[1]; // 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
@@ -401,36 +409,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
@@ -451,6 +459,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
@@ -488,6 +514,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;
@@ -526,7 +554,7 @@ public:
Mob* With();
// Add item from cursor slot to trade bucket (automatically does bag data too)
void AddEntity(uint16 from_slot_id, uint16 trade_slot_id);
void AddEntity(uint16 trade_slot_id, uint32 stack_size);
// Audit trade
void LogTrade();
@@ -557,7 +585,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;
@@ -568,6 +596,7 @@ struct ExtraAttackOptions {
float crit_flat;
float hate_percent;
int hate_flat;
int hit_chance;
};
#endif
+591 -1194
View File
File diff suppressed because it is too large Load Diff
+94 -86
View File
@@ -26,122 +26,130 @@ class NPC;
#define MAX_LOOTERS 72
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);
class Corpse : public Mob {
public:
static void SendEndLootErrorPacket(Client* client);
static void SendLootReqErrorPacket(Client* client, uint8 response = 2);
Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NPCType** in_npctypedata, uint32 in_decaytime = 600000);
Corpse(Client* client, int32 in_rezexp);
Corpse(uint32 in_corpseid, uint32 in_charid, 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();
Corpse(uint32 in_corpseid, uint32 in_charid, const char* in_charname, ItemList* in_itemlist, uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_plat, float in_x, float in_y, float in_z, float in_heading, float in_size, uint8 in_gender, uint16 in_race, uint8 in_class, uint8 in_deity, uint8 in_level, uint8 in_texture, uint8 in_helmtexture, uint32 in_rezexp, bool wasAtGraveyard = false);
~Corpse();
static Corpse* LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std::string in_charname, float in_x, float in_y, float in_z, float in_heading, std::string time_of_death, bool rezzed, bool was_at_graveyard);
//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 Delete();
void Bury();
void CalcCorpseName();
void LoadPlayerCorpseDecayTime(uint32 dbid);
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);
/* 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; }
protected:
std::list<uint32> MoveItemToCorpse(Client *client, ItemInst *item, int16 equipslot);
private:
bool p_PlayerCorpse; bool pIsChanged;
bool pLocked;
int32 pkitem;
uint32 dbid;
uint32 charid;
ItemList itemlist;
uint32 copper;
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;
Timer corpse_delay_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
+110 -131
View File
@@ -21,11 +21,11 @@
#include <string.h>
#include "masterentity.h"
#include "worldserver.h"
#include "StringIDs.h"
#include "string_ids.h"
#include "zonedb.h"
#include "../common/packet_functions.h"
#include "../common/packet_dump.h"
#include "../common/StringUtil.h"
#include "../common/string_util.h"
#include "guild_mgr.h"
#define OPEN_DOOR 0x02
@@ -50,7 +50,7 @@ Doors::Doors(const Door* door)
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;
@@ -253,8 +253,7 @@ void Doors::HandleClick(Client* sender, uint8 trigger)
strcpy(tmpmsg, "Door is locked by an unknown guild");
}
sender->Message(4, tmpmsg);
// safe_delete(outapp);
// /\ possible missing line..all other 'fail' returns seem to have it
safe_delete(outapp);
return;
}
// a key is required or the door is locked but can be picked or both
@@ -569,157 +568,137 @@ void Doors::DumpDoor(){
}
int32 ZoneDatabase::GetDoorsCount(uint32* oMaxID, const char *zone_name, int16 version) {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
query = new char[256];
sprintf(query, "SELECT MAX(id), count(*) FROM doors WHERE zone='%s' AND (version=%u OR version=-1)", zone_name, version);
if (RunQuery(query, strlen(query), errbuf, &result)) {
safe_delete_array(query);
row = mysql_fetch_row(result);
if (row != nullptr && row[1] != 0) {
int32 ret = atoi(row[1]);
if (oMaxID) {
if (row[0])
*oMaxID = atoi(row[0]);
else
*oMaxID = 0;
}
mysql_free_result(result);
return ret;
}
mysql_free_result(result);
}
else {
std::cerr << "Error in GetDoorsCount query '" << query << "' " << errbuf << std::endl;
safe_delete_array(query);
std::string query = StringFormat("SELECT MAX(id), count(*) FROM doors "
"WHERE zone = '%s' AND (version = %u OR version = -1)",
zone_name, version);
auto results = QueryDatabase(query);
if (!results.Success()) {
std::cerr << "Error in GetDoorsCount query '" << query << "' " << results.ErrorMessage() << std::endl;
return -1;
}
}
if (results.RowCount() != 1)
return -1;
auto row = results.begin();
if (!oMaxID)
return atoi(row[1]);
if (row[0])
*oMaxID = atoi(row[0]);
else
*oMaxID = 0;
return atoi(row[1]);
return -1;
}
int32 ZoneDatabase::GetDoorsCountPlusOne(const char *zone_name, int16 version) {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
uint32 oMaxID = 0;
MYSQL_RES *result;
MYSQL_ROW row;
query = new char[256];
sprintf(query, "SELECT MAX(id) FROM doors WHERE zone='%s' AND version=%u", zone_name, version);
if (RunQuery(query, strlen(query), errbuf, &result)) {
safe_delete_array(query);
row = mysql_fetch_row(result);
if (row != nullptr && row[1] != 0) {
if (row[0])
oMaxID = atoi(row[0]) + 1;
else
oMaxID = 0;
mysql_free_result(result);
return oMaxID;
}
mysql_free_result(result);
}
else {
std::cerr << "Error in GetDoorsCountPlusOne query '" << query << "' " << errbuf << std::endl;
safe_delete_array(query);
std::string query = StringFormat("SELECT MAX(id) FROM doors "
"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;
}
}
return -1;
if (results.RowCount() != 1)
return -1;
auto row = results.begin();
if (!row[0])
return 0;
return atoi(row[0]) + 1;
}
int32 ZoneDatabase::GetDoorsDBCountPlusOne(const char *zone_name, int16 version) {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
uint32 oMaxID = 0;
MYSQL_RES *result;
MYSQL_ROW row;
query = new char[256];
sprintf(query, "SELECT MAX(doorid) FROM doors WHERE zone='%s' AND (version=%u OR version=-1)", zone_name, version);
if (RunQuery(query, strlen(query), errbuf, &result)) {
safe_delete_array(query);
row = mysql_fetch_row(result);
if (row != nullptr && row[1] != 0) {
if (row[0])
oMaxID = atoi(row[0]) + 1;
else
oMaxID = 0;
mysql_free_result(result);
return oMaxID;
}
mysql_free_result(result);
}
else {
std::cerr << "Error in GetDoorsCountPlusOne query '" << query << "' " << errbuf << std::endl;
safe_delete_array(query);
std::string query = StringFormat("SELECT MAX(doorid) FROM doors "
"WHERE zone = '%s' AND (version = %u OR version = -1)",
zone_name, version);
auto results = QueryDatabase(query);
if (!results.Success()) {
std::cerr << "Error in GetDoorsCountPlusOne query '" << query << "' " << results.ErrorMessage() << std::endl;
return -1;
}
return -1;
if (results.RowCount() != 1)
return -1;
auto row = results.begin();
if (!row[0])
return 0;
return atoi(row[0]) + 1;
}
bool ZoneDatabase::LoadDoors(int32 iDoorCount, Door *into, const char *zone_name, int16 version) {
LogFile->write(EQEMuLog::Status, "Loading Doors from database...");
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
// Door tmpDoor;
MakeAnyLenString(&query, "SELECT id,doorid,zone,name,pos_x,pos_y,pos_z,heading,"
"opentype,guild,lockpick,keyitem,nokeyring,triggerdoor,triggertype,dest_zone,dest_instance,dest_x,"
"dest_y,dest_z,dest_heading,door_param,invert_state,incline,size,is_ldon_door,client_version_mask "
"FROM doors WHERE zone='%s' AND (version=%u OR version=-1) ORDER BY doorid asc", zone_name, version);
if (RunQuery(query, strlen(query), errbuf, &result)) {
safe_delete_array(query);
int32 r;
for(r = 0; (row = mysql_fetch_row(result)); r++) {
if(r >= iDoorCount) {
std::cerr << "Error, Door Count of " << iDoorCount << " exceeded." << std::endl;
break;
}
memset(&into[r], 0, sizeof(Door));
into[r].db_id = atoi(row[0]);
into[r].door_id = atoi(row[1]);
strn0cpy(into[r].zone_name,row[2],32);
strn0cpy(into[r].door_name,row[3],32);
into[r].pos_x = (float)atof(row[4]);
into[r].pos_y = (float)atof(row[5]);
into[r].pos_z = (float)atof(row[6]);
into[r].heading = (float)atof(row[7]);
into[r].opentype = atoi(row[8]);
into[r].guild_id = atoi(row[9]);
into[r].lockpick = atoi(row[10]);
into[r].keyitem = atoi(row[11]);
into[r].nokeyring = atoi(row[12]);
into[r].trigger_door = atoi(row[13]);
into[r].trigger_type = atoi(row[14]);
strn0cpy(into[r].dest_zone, row[15], 32);
into[r].dest_instance_id = atoi(row[16]);
into[r].dest_x = (float) atof(row[17]);
into[r].dest_y = (float) atof(row[18]);
into[r].dest_z = (float) atof(row[19]);
into[r].dest_heading = (float) atof(row[20]);
into[r].door_param=atoi(row[21]);
into[r].invert_state=atoi(row[22]);
into[r].incline=atoi(row[23]);
into[r].size=atoi(row[24]);
into[r].is_ldon_door=atoi(row[25]);
into[r].client_version_mask = (uint32)strtoul(row[26], nullptr, 10);
}
mysql_free_result(result);
}
else
{
std::cerr << "Error in DBLoadDoors query '" << query << "' " << errbuf << std::endl;
safe_delete_array(query);
std::string query = StringFormat("SELECT id, doorid, zone, name, pos_x, pos_y, pos_z, heading, "
"opentype, guild, lockpick, keyitem, nokeyring, triggerdoor, triggertype, "
"dest_zone, dest_instance, dest_x, dest_y, dest_z, dest_heading, "
"door_param, invert_state, incline, size, is_ldon_door, client_version_mask "
"FROM doors WHERE zone = '%s' AND (version = %u OR version = -1) "
"ORDER BY doorid asc", zone_name, version);
auto results = QueryDatabase(query);
if (!results.Success()){
std::cerr << "Error in DBLoadDoors query '" << query << "' " << results.ErrorMessage() << std::endl;
return false;
}
int32 rowIndex = 0;
for(auto row = results.begin(); row != results.end(); ++row, ++rowIndex) {
if(rowIndex >= iDoorCount) {
std::cerr << "Error, Door Count of " << iDoorCount << " exceeded." << std::endl;
break;
}
memset(&into[rowIndex], 0, sizeof(Door));
into[rowIndex].db_id = atoi(row[0]);
into[rowIndex].door_id = atoi(row[1]);
strn0cpy(into[rowIndex].zone_name,row[2],32);
strn0cpy(into[rowIndex].door_name,row[3],32);
into[rowIndex].pos_x = (float)atof(row[4]);
into[rowIndex].pos_y = (float)atof(row[5]);
into[rowIndex].pos_z = (float)atof(row[6]);
into[rowIndex].heading = (float)atof(row[7]);
into[rowIndex].opentype = atoi(row[8]);
into[rowIndex].guild_id = atoi(row[9]);
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]);
into[rowIndex].trigger_type = atoi(row[14]);
strn0cpy(into[rowIndex].dest_zone, row[15], 32);
into[rowIndex].dest_instance_id = atoi(row[16]);
into[rowIndex].dest_x = (float) atof(row[17]);
into[rowIndex].dest_y = (float) atof(row[18]);
into[rowIndex].dest_z = (float) atof(row[19]);
into[rowIndex].dest_heading = (float) atof(row[20]);
into[rowIndex].door_param=atoi(row[21]);
into[rowIndex].invert_state=atoi(row[22]);
into[rowIndex].incline=atoi(row[23]);
into[rowIndex].size=atoi(row[24]);
into[rowIndex].is_ldon_door=atoi(row[25]);
into[rowIndex].client_version_mask = (uint32)strtoul(row[26], nullptr, 10);
}
return true;
}
+62 -30
View File
@@ -24,11 +24,11 @@
#include "../common/packet_functions.h"
#include "petitions.h"
#include "../common/serverinfo.h"
#include "../common/ZoneNumbers.h"
#include "../common/zone_numbers.h"
#include "../common/moremath.h"
#include "../common/guilds.h"
#include "StringIDs.h"
#include "NpcAI.h"
#include "string_ids.h"
#include "npc_ai.h"
float Client::GetActSpellRange(uint16 spell_id, float range, bool IsBard)
{
@@ -56,7 +56,7 @@ int32 NPC::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
value -= target->GetFcDamageAmtIncoming(this, spell_id)/spells[spell_id].buffduration;
}
value += dmg*SpellFocusDMG/100;
value += dmg*GetSpellFocusDMG()/100;
if (AI_HasSpellsEffects()){
int16 chance = 0;
@@ -260,7 +260,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;
@@ -275,7 +275,7 @@ int32 NPC::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
//Scale all NPC spell healing via SetSpellFocusHeal(value)
value += value*SpellFocusHeal/100;
value += value*GetSpellFocusHeal()/100;
if (target) {
value += target->GetFocusIncoming(focusFcHealAmtIncoming, SE_FcHealAmtIncoming, this, spell_id);
@@ -408,11 +408,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:
@@ -451,7 +451,7 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost)
// 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;
@@ -606,6 +606,7 @@ bool Client::TrainDiscipline(uint32 itemid) {
return(false);
} else if(m_pp.disciplines.values[r] == 0) {
m_pp.disciplines.values[r] = spell_id;
database.SaveCharacterDisc(this->CharacterID(), r, spell_id);
SendDisciplineUpdate();
Message(0, "You have learned a new discipline!");
return(true);
@@ -616,13 +617,9 @@ bool Client::TrainDiscipline(uint32 itemid) {
}
void Client::SendDisciplineUpdate() {
//this dosent seem to work right now
EQApplicationPacket app(OP_DisciplineUpdate, sizeof(Disciplines_Struct));
Disciplines_Struct *d = (Disciplines_Struct*)app.pBuffer;
//dunno why I dont just send the one from m_pp
memcpy(d, &m_pp.disciplines, sizeof(m_pp.disciplines));
QueuePacket(&app);
}
@@ -686,19 +683,20 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) {
{
uint32 reduced_recast = spell.recast_time / 1000;
reduced_recast -= CastToClient()->GetFocusEffect(focusReduceRecastTime, spell_id);
if(reduced_recast < 0)
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
{
@@ -707,6 +705,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)
@@ -745,7 +756,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) {
@@ -757,8 +772,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 = curmob->DistNoRoot(caster->GetTargetRingX(), caster->GetTargetRingY(), caster->GetTargetRingZ());
}
else if (center) {
dist_targ = center->DistNoRoot(*curmob);
}
if (dist_targ > dist2) //make sure they are in range
continue;
if (dist_targ < min_range2) //make sure they are in range
@@ -780,7 +807,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 && !center->CheckLosFN(curmob))
continue;
if (!center && !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.
@@ -800,10 +829,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++;
}
}
+15 -13
View File
@@ -20,13 +20,13 @@
#include "../common/debug.h"
#include "../common/seperator.h"
#include "../common/MiscFunctions.h"
#include "../common/StringUtil.h"
#include "../common/misc_functions.h"
#include "../common/string_util.h"
#include "../common/features.h"
#include "masterentity.h"
#include "embparser.h"
#include "questmgr.h"
#include "QGlobals.h"
#include "qglobals.h"
#include "zone.h"
#include <algorithm>
#include <sstream>
@@ -154,7 +154,7 @@ void PerlembParser::ReloadQuests() {
}
int PerlembParser::EventCommon(QuestEventID event, uint32 objid, const char * data, NPC* npcmob, ItemInst* iteminst, Mob* mob,
uint32 extradata, bool global, std::vector<void*> *extra_pointers)
uint32 extradata, bool global, std::vector<EQEmu::Any> *extra_pointers)
{
if(!perl)
return 0;
@@ -211,32 +211,32 @@ int PerlembParser::EventCommon(QuestEventID event, uint32 objid, const char * da
}
int PerlembParser::EventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
return EventCommon(evt, npc->GetNPCTypeID(), data.c_str(), npc, nullptr, init, extra_data, false, extra_pointers);
}
int PerlembParser::EventGlobalNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
return EventCommon(evt, npc->GetNPCTypeID(), data.c_str(), npc, nullptr, init, extra_data, true, extra_pointers);
}
int PerlembParser::EventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
return EventCommon(evt, 0, data.c_str(), nullptr, nullptr, client, extra_data, false, extra_pointers);
}
int PerlembParser::EventGlobalPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
return EventCommon(evt, 0, data.c_str(), nullptr, nullptr, client, extra_data, true, extra_pointers);
}
int PerlembParser::EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
return EventCommon(evt, item->GetID(), nullptr, nullptr, item, client, extra_data, false, extra_pointers);
}
int PerlembParser::EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
return EventCommon(evt, 0, itoa(spell_id), npc, nullptr, client, extra_data, false, extra_pointers);
}
@@ -1114,7 +1114,7 @@ void PerlembParser::ExportItemVariables(std::string &package_name, Mob *mob) {
#undef HASITEM_ISNULLITEM
void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID event, uint32 objid, const char * data,
NPC* npcmob, ItemInst* iteminst, Mob* mob, uint32 extradata, std::vector<void*> *extra_pointers)
NPC* npcmob, ItemInst* iteminst, Mob* mob, uint32 extradata, std::vector<EQEmu::Any> *extra_pointers)
{
switch (event) {
case EVENT_SAY: {
@@ -1130,8 +1130,10 @@ void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID
case EVENT_TRADE: {
if(extra_pointers) {
for(size_t i = 0; i < extra_pointers->size(); ++i) {
ItemInst *inst = reinterpret_cast<ItemInst*>(extra_pointers->at(i));
size_t sz = extra_pointers->size();
for(size_t i = 0; i < sz; ++i) {
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));
+10 -10
View File
@@ -20,8 +20,8 @@
#define EQMEU_EMBPARSER_H
#ifdef EMBPERL
#include "QuestParserCollection.h"
#include "QuestInterface.h"
#include "quest_parser_collection.h"
#include "quest_interface.h"
#include <string>
#include <queue>
#include <map>
@@ -45,17 +45,17 @@ public:
~PerlembParser();
virtual int EventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
virtual int EventGlobalNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
virtual int EventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
virtual int EventGlobalPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
virtual int EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
virtual int EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
virtual bool HasQuestSub(uint32 npcid, QuestEventID evt);
virtual bool HasGlobalQuestSub(QuestEventID evt);
@@ -86,7 +86,7 @@ private:
void ExportVarComplex(const char *pkgprefix, const char *varname, const char *value);
int EventCommon(QuestEventID event, uint32 objid, const char * data, NPC* npcmob, ItemInst* iteminst, Mob* mob,
uint32 extradata, bool global, std::vector<void*> *extra_pointers);
uint32 extradata, bool global, std::vector<EQEmu::Any> *extra_pointers);
int SendCommands(const char *pkgprefix, const char *event, uint32 npcid, Mob* other, Mob* mob, ItemInst *iteminst);
void MapFunctions();
@@ -103,7 +103,7 @@ private:
void ExportZoneVariables(std::string &package_name);
void ExportItemVariables(std::string &package_name, Mob *mob);
void ExportEventVariables(std::string &package_name, QuestEventID event, uint32 objid, const char * data,
NPC* npcmob, ItemInst* iteminst, Mob* mob, uint32 extradata, std::vector<void*> *extra_pointers);
NPC* npcmob, ItemInst* iteminst, Mob* mob, uint32 extradata, std::vector<EQEmu::Any> *extra_pointers);
std::map<uint32, PerlQuestStatus> npc_quest_status_;
PerlQuestStatus global_npc_quest_status_;
+148 -10
View File
@@ -22,14 +22,16 @@
#ifdef EMBPERL_XS
#include "../common/debug.h"
#include "../common/MiscFunctions.h"
#include "../common/misc_functions.h"
#include "embparser.h"
#include "questmgr.h"
#include "embxs.h"
#include "entity.h"
#include "zone.h"
#include "queryserv.h"
extern Zone* zone;
extern QueryServ* QServ;
/*
@@ -2857,14 +2859,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;
}
@@ -2873,10 +2915,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;
}
@@ -2885,10 +2927,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;
}
@@ -3370,6 +3436,71 @@ XS(XS__clear_npctype_cache)
XSRETURN_EMPTY;
}
XS(XS__qs_send_query);
XS(XS__qs_send_query)
{
dXSARGS;
if (items != 1){
Perl_croak(aTHX_ "Usage: qs_send_query(query)");
}
else{
// char *Query = (char *)SvPV_nolen(ST(0));
std::string Query = (std::string)SvPV_nolen(ST(0));
QServ->SendQuery(Query);
}
XSRETURN_EMPTY;
}
XS(XS__qs_player_event);
XS(XS__qs_player_event)
{
dXSARGS;
if (items != 2){
Perl_croak(aTHX_ "Usage: qs_player_event(char_id, event_desc)");
}
else{
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);
}
XSRETURN_EMPTY;
}
XS(XS__crosszonesetentityvariablebynpctypeid);
XS(XS__crosszonesetentityvariablebynpctypeid)
{
dXSARGS;
if (items != 3)
Perl_croak(aTHX_ "Usage: crosszonesetentityvariablebynpctypeid(npctype_id, id, m_var)");
if (items == 3) {
uint32 npctype_id = (uint32)SvIV(ST(0));
const char *id = (const char *)SvPV_nolen(ST(1));
const char *m_var = (const char *)SvPV_nolen(ST(2));
quest_manager.CrossZoneSetEntityVariableByNPCTypeID(npctype_id, id, m_var);
}
XSRETURN_EMPTY;
}
XS(XS__crosszonesignalnpcbynpctypeid);
XS(XS__crosszonesignalnpcbynpctypeid)
{
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: crosszonesignalnpcbynpctypeid(npctype_id, data)");
if (items == 2) {
uint32 npctype_id = (uint32)SvIV(ST(0));
uint32 data = (uint32)SvIV(ST(1));
quest_manager.CrossZoneSignalNPCByNPCTypeID(npctype_id, data);
}
XSRETURN_EMPTY;
}
/*
This is the callback perl will look for to setup the
quest package's XSUBs
@@ -3561,9 +3692,12 @@ EXTERN_C XS(boot_quest)
newXS(strcpy(buf, "CreateInstance"), XS__CreateInstance, file);
newXS(strcpy(buf, "DestroyInstance"), XS__DestroyInstance, file);
newXS(strcpy(buf, "GetInstanceID"), XS__GetInstanceID, file);
newXS(strcpy(buf, "GetCharactersInInstance"), XS__GetCharactersInInstance, 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, "RemoveFromInstance"), XS__RemoveFromInstance, file);
newXS(strcpy(buf, "RemoveAllFromInstance"), XS__RemoveAllFromInstance, file);
newXS(strcpy(buf, "MovePCInstance"), XS__MovePCInstance, file);
newXS(strcpy(buf, "FlagInstanceByGroupLeader"), XS__FlagInstanceByGroupLeader, file);
newXS(strcpy(buf, "FlagInstanceByRaidLeader"), XS__FlagInstanceByRaidLeader, file);
@@ -3591,6 +3725,10 @@ EXTERN_C XS(boot_quest)
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);
XSRETURN_YES;
}
+198 -130
View File
@@ -19,7 +19,6 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>
#include <string.h>
#include <iostream>
@@ -31,22 +30,18 @@
#include "../common/unix.h"
#endif
#include "net.h"
#include "masterentity.h"
#include "worldserver.h"
#include "../common/guilds.h"
#include "../common/packet_dump.h"
#include "../common/packet_functions.h"
#include "petitions.h"
#include "../common/spdat.h"
#include "../common/features.h"
#include "StringIDs.h"
#include "../common/dbasync.h"
#include "../common/guilds.h"
#include "../common/spdat.h"
#include "guild_mgr.h"
#include "net.h"
#include "petitions.h"
#include "quest_parser_collection.h"
#include "raids.h"
#include "QuestParserCollection.h"
#include "remote_call.h"
#include "remote_call_subscribe.h"
#include "string_ids.h"
#include "worldserver.h"
#ifdef _WINDOWS
#define snprintf _snprintf
@@ -60,7 +55,6 @@ extern WorldServer worldserver;
extern NetConnection net;
extern uint32 numclients;
extern PetitionList petition_list;
extern DBAsync *dbasync;
extern char errorname[32];
extern uint16 adverrornum;
@@ -68,12 +62,12 @@ extern uint16 adverrornum;
Entity::Entity()
{
id = 0;
pDBAsyncWorkID = 0;
spawn_timestamp = time(nullptr);
}
Entity::~Entity()
{
dbasync->CancelWork(pDBAsyncWorkID);
}
Client *Entity::CastToClient()
@@ -496,23 +490,36 @@ void EntityList::MobProcess()
#endif
auto it = mob_list.begin();
while (it != mob_list.end()) {
if (!it->second) {
uint16 id = it->first;
Mob *mob = it->second;
size_t sz = mob_list.size();
bool p_val = mob->Process();
size_t a_sz = mob_list.size();
if(a_sz > sz) {
//increased size can potentially screw with iterators so reset it to current value
//if buckets are re-orderered we may skip a process here and there but since
//process happens so often it shouldn't matter much
it = mob_list.find(id);
++it;
} else {
++it;
continue;
}
if (!it->second->Process()) {
Mob *mob = it->second;
uint16 tempid = it->first;
++it; // we don't erase here because the destructor will
if (mob->IsNPC()) {
entity_list.RemoveNPC(mob->CastToNPC()->GetID());
} else if (mob->IsMerc()) {
entity_list.RemoveMerc(mob->CastToMerc()->GetID());
if(!p_val) {
if(mob->IsNPC()) {
entity_list.RemoveNPC(id);
}
else if(mob->IsMerc()) {
entity_list.RemoveMerc(id);
#ifdef BOTS
} else if (mob->IsBot()) {
entity_list.RemoveBot(mob->CastToBot()->GetID());
}
else if(mob->IsBot()) {
entity_list.RemoveBot(id);
#endif
} else {
}
else {
#ifdef _WINDOWS
struct in_addr in;
in.s_addr = mob->CastToClient()->GetIP();
@@ -520,20 +527,19 @@ void EntityList::MobProcess()
#endif
zone->StartShutdownTimer();
Group *g = GetGroupByMob(mob);
if (g) {
if(g) {
LogFile->write(EQEMuLog::Error, "About to delete a client still in a group.");
g->DelMember(mob);
}
Raid *r = entity_list.GetRaidByClient(mob->CastToClient());
if (r) {
if(r) {
LogFile->write(EQEMuLog::Error, "About to delete a client still in a raid.");
r->MemberZoned(mob->CastToClient());
}
entity_list.RemoveClient(mob->GetID());
entity_list.RemoveClient(id);
}
entity_list.RemoveMob(tempid);
} else {
++it;
entity_list.RemoveMob(id);
}
}
}
@@ -625,6 +631,7 @@ void EntityList::AddCorpse(Corpse *corpse, uint32 in_id)
void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue)
{
npc->SetID(GetFreeID());
npc->SetMerchantProbability((uint8) MakeRandomInt(0, 99));
parse->EventNPC(EVENT_SPAWN, npc, nullptr, "", 0);
/* Web Interface: NPC Spawn (Pop) */
@@ -668,10 +675,12 @@ void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue)
void EntityList::AddMerc(Merc *merc, bool SendSpawnPacket, bool dontqueue)
{
if (merc) {
if (merc)
{
merc->SetID(GetFreeID());
if (SendSpawnPacket) {
if (SendSpawnPacket)
{
if (dontqueue) {
// Send immediately
EQApplicationPacket *outapp = new EQApplicationPacket();
@@ -683,12 +692,10 @@ void EntityList::AddMerc(Merc *merc, bool SendSpawnPacket, bool dontqueue)
// Queue the packet
NewSpawn_Struct *ns = new NewSpawn_Struct;
memset(ns, 0, sizeof(NewSpawn_Struct));
merc->FillSpawnStruct(ns, merc);
merc->FillSpawnStruct(ns, 0);
AddToSpawnQueue(merc->GetID(), &ns);
safe_delete(ns);
}
//parse->EventMERC(EVENT_SPAWN, merc, nullptr, "", 0);
}
merc_list.insert(std::pair<uint16, Merc *>(merc->GetID(), merc));
@@ -1358,7 +1365,7 @@ void EntityList::RefreshClientXTargets(Client *c)
}
void EntityList::QueueClientsByTarget(Mob *sender, const EQApplicationPacket *app,
bool iSendToSender, Mob *SkipThisMob, bool ackreq, bool HoTT, uint32 ClientVersionBits)
bool iSendToSender, Mob *SkipThisMob, bool ackreq, bool HoTT, uint32 ClientVersionBits, bool inspect_buffs)
{
auto it = client_list.begin();
while (it != client_list.end()) {
@@ -1372,8 +1379,7 @@ void EntityList::QueueClientsByTarget(Mob *sender, const EQApplicationPacket *ap
Mob *TargetsTarget = nullptr;
if (Target)
TargetsTarget = Target->GetTarget();
TargetsTarget = Target->GetTarget();
bool Send = false;
@@ -1385,11 +1391,30 @@ void EntityList::QueueClientsByTarget(Mob *sender, const EQApplicationPacket *ap
Send = true;
if (c != sender) {
if (Target == sender)
Send = true;
else if (HoTT)
if (TargetsTarget == sender)
if (Target == sender) {
if (inspect_buffs) { // if inspect_buffs is true we're sending a mob's buffs to those with the LAA
if (c->IsRaidGrouped()) {
Raid *raid = c->GetRaid();
if (!raid)
continue;
uint32 gid = raid->GetGroup(c);
if (gid > 11 || raid->GroupCount(gid) < 3)
continue;
if (raid->GetLeadershipAA(groupAAInspectBuffs, gid))
Send = true;
} else {
Group *group = c->GetGroup();
if (!group || group->GroupCount() < 3)
continue;
if (group->GetLeadershipAA(groupAAInspectBuffs))
Send = true;
}
} else {
Send = true;
}
} else if (HoTT && TargetsTarget == sender) {
Send = true;
}
}
if (Send && (c->GetClientVersionBit() & ClientVersionBits))
@@ -1492,7 +1517,7 @@ void EntityList::QueueClientsStatus(Mob *sender, const EQApplicationPacket *app,
void EntityList::DuelMessage(Mob *winner, Mob *loser, bool flee)
{
if (winner->GetLevelCon(winner->GetLevel(), loser->GetLevel()) > 2) {
std::vector<void*> args;
std::vector<EQEmu::Any> args;
args.push_back(winner);
args.push_back(loser);
@@ -1594,7 +1619,7 @@ Corpse *EntityList::GetCorpseByDBID(uint32 dbid)
{
auto it = corpse_list.begin();
while (it != corpse_list.end()) {
if (it->second->GetDBID() == dbid)
if (it->second->GetCorpseDBID() == dbid)
return it->second;
++it;
}
@@ -1614,7 +1639,7 @@ Corpse *EntityList::GetCorpseByName(const char *name)
Spawn2 *EntityList::GetSpawnByID(uint32 id)
{
if (!zone)
if (!zone || !zone->IsLoaded())
return nullptr;
LinkedListIterator<Spawn2 *> iterator(zone->spawn2_list);
@@ -1648,7 +1673,7 @@ void EntityList::RemoveCorpseByDBID(uint32 dbid)
{
auto it = corpse_list.begin();
while (it != corpse_list.end()) {
if (it->second->GetDBID() == dbid) {
if (it->second->GetCorpseDBID() == dbid) {
safe_delete(it->second);
free_ids.push(it->first);
it = corpse_list.erase(it);
@@ -1665,9 +1690,9 @@ int EntityList::RezzAllCorpsesByCharID(uint32 charid)
auto it = corpse_list.begin();
while (it != corpse_list.end()) {
if (it->second->GetCharID() == charid) {
RezzExp += it->second->GetRezzExp();
it->second->Rezzed(true);
it->second->CompleteRezz();
RezzExp += it->second->GetRezExp();
it->second->IsRezzed(true);
it->second->CompleteResurrection();
}
++it;
}
@@ -2654,7 +2679,7 @@ int32 EntityList::DeleteNPCCorpses()
auto it = corpse_list.begin();
while (it != corpse_list.end()) {
if (it->second->IsNPCCorpse()) {
it->second->Depop();
it->second->DepopNPCCorpse();
x++;
}
++it;
@@ -2874,7 +2899,7 @@ void EntityList::ClearFeignAggro(Mob *targ)
}
if (targ->IsClient()) {
std::vector<void*> args;
std::vector<EQEmu::Any> args;
args.push_back(it->second);
int i = parse->EventPlayer(EVENT_FEIGN_DEATH, targ->CastToClient(), "", 0, &args);
if (i != 0) {
@@ -2934,8 +2959,14 @@ void EntityList::SignalMobsByNPCID(uint32 snpc, int signal_id)
}
}
bool tracking_compare(const std::pair<Mob *, float> &a, const std::pair<Mob *, float> &b)
{
return a.first->GetSpawnTimeStamp() > b.first->GetSpawnTimeStamp();
}
bool EntityList::MakeTrackPacket(Client *client)
{
std::list<std::pair<Mob *, float> > tracking_list;
uint32 distance = 0;
float MobDistance;
@@ -2950,60 +2981,43 @@ bool EntityList::MakeTrackPacket(Client *client)
if (distance < 300)
distance = 300;
uint32 spe= 0;
bool ret = false;
spe = mob_list.size() + 50;
uchar *buffer1 = new uchar[sizeof(Track_Struct)];
Track_Struct *track_ent = (Track_Struct*) buffer1;
uchar *buffer2 = new uchar[sizeof(Track_Struct)*spe];
Tracking_Struct *track_array = (Tracking_Struct*) buffer2;
memset(track_array, 0, sizeof(Track_Struct)*spe);
uint32 array_counter = 0;
Group *g = client->GetGroup();
auto it = mob_list.begin();
while (it != mob_list.end()) {
if (it->second && ((MobDistance = it->second->DistNoZ(*client)) <= distance)) {
if ((it->second != client) && it->second->IsTrackable()) {
memset(track_ent, 0, sizeof(Track_Struct));
Mob *cur_entity = it->second;
track_ent->entityid = cur_entity->GetID();
track_ent->distance = MobDistance;
track_ent->level = cur_entity->GetLevel();
track_ent->NPC = !cur_entity->IsClient();
if (g && cur_entity->IsClient() && g->IsGroupMember(cur_entity->CastToMob()))
track_ent->GroupMember = 1;
else
track_ent->GroupMember = 0;
strn0cpy(track_ent->name, cur_entity->GetName(), sizeof(track_ent->name));
memcpy(&track_array->Entrys[array_counter], track_ent, sizeof(Track_Struct));
array_counter++;
}
}
for (auto it = mob_list.cbegin(); it != mob_list.cend(); ++it) {
if (!it->second || it->second == client || !it->second->IsTrackable() ||
it->second->IsInvisible(client))
continue;
++it;
MobDistance = it->second->DistNoZ(*client);
if (MobDistance > distance)
continue;
tracking_list.push_back(std::make_pair(it->second, MobDistance));
}
if (array_counter <= spe) {
EQApplicationPacket* outapp = new EQApplicationPacket(OP_Track,sizeof(Track_Struct)*(array_counter));
memcpy(outapp->pBuffer, track_array,sizeof(Track_Struct)*(array_counter));
outapp->priority = 6;
client->QueuePacket(outapp);
safe_delete(outapp);
ret = true;
} else {
LogFile->write(EQEMuLog::Status, "ERROR: Unable to transmit a Tracking_Struct packet. Mobs in zone = %i. Mobs in packet = %i", array_counter, spe);
tracking_list.sort(tracking_compare);
EQApplicationPacket *outapp = new EQApplicationPacket(OP_Track, sizeof(Track_Struct) * tracking_list.size());
Tracking_Struct *outtrack = (Tracking_Struct *)outapp->pBuffer;
outapp->priority = 6;
int index = 0;
for (auto it = tracking_list.cbegin(); it != tracking_list.cend(); ++it, ++index) {
Mob *cur_entity = it->first;
outtrack->Entrys[index].entityid = cur_entity->GetID();
outtrack->Entrys[index].distance = it->second;
outtrack->Entrys[index].level = cur_entity->GetLevel();
outtrack->Entrys[index].NPC = !cur_entity->IsClient();
if (g && cur_entity->IsClient() && g->IsGroupMember(cur_entity->CastToMob()))
outtrack->Entrys[index].GroupMember = 1;
else
outtrack->Entrys[index].GroupMember = 0;
strn0cpy(outtrack->Entrys[index].name, cur_entity->GetName(), sizeof(outtrack->Entrys[index].name));
}
safe_delete_array(buffer1);
safe_delete_array(buffer2);
client->QueuePacket(outapp);
safe_delete(outapp);
return ret;
return true;
}
void EntityList::MessageGroup(Mob *sender, bool skipclose, uint32 type, const char *message, ...)
@@ -3269,9 +3283,10 @@ void EntityList::ProcessMove(Client *c, float x, float y, float z)
for (auto iter = events.begin(); iter != events.end(); ++iter) {
quest_proximity_event& evt = (*iter);
if (evt.npc) {
parse->EventNPC(evt.event_id, evt.npc, evt.client, "", 0);
std::vector<EQEmu::Any> args;
parse->EventNPC(evt.event_id, evt.npc, evt.client, "", 0, &args);
} else {
std::vector<void*> args;
std::vector<EQEmu::Any> args;
args.push_back(&evt.area_id);
args.push_back(&evt.area_type);
parse->EventPlayer(evt.event_id, evt.client, "", 0, &args);
@@ -3325,7 +3340,7 @@ void EntityList::ProcessMove(NPC *n, float x, float y, float z)
for (auto iter = events.begin(); iter != events.end(); ++iter) {
quest_proximity_event& evt = (*iter);
std::vector<void*> args;
std::vector<EQEmu::Any> args;
args.push_back(&evt.area_id);
args.push_back(&evt.area_type);
parse->EventNPC(evt.event_id, evt.npc, evt.client, "", 0, &args);
@@ -3632,6 +3647,43 @@ void EntityList::DestroyTempPets(Mob *owner)
}
}
int16 EntityList::CountTempPets(Mob *owner)
{
int16 count = 0;
auto it = npc_list.begin();
while (it != npc_list.end()) {
NPC* n = it->second;
if (n->GetSwarmInfo()) {
if (n->GetSwarmInfo()->owner_id == owner->GetID()) {
count++;
}
}
++it;
}
owner->SetTempPetCount(count);
return count;
}
void EntityList::AddTempPetsToHateList(Mob *owner, Mob* other, bool bFrenzy)
{
if (!other || !owner)
return;
auto it = npc_list.begin();
while (it != npc_list.end()) {
NPC* n = it->second;
if (n->GetSwarmInfo()) {
if (n->GetSwarmInfo()->owner_id == owner->GetID()) {
if (!n->GetSpecialAbility(IMMUNE_AGGRO))
n->hate_list.Add(other, 0, 0, bFrenzy);
}
}
++it;
}
}
bool Entity::CheckCoordLosNoZLeaps(float cur_x, float cur_y, float cur_z,
float trg_x, float trg_y, float trg_z, float perwalk)
{
@@ -4137,15 +4189,10 @@ void EntityList::UnMarkNPC(uint16 ID)
// each group to remove the dead mobs entity ID from the groups list of NPCs marked via the
// Group Leadership AA Mark NPC ability.
//
auto it = client_list.begin();
while (it != client_list.end()) {
if (it->second) {
Group *g = nullptr;
g = it->second->GetGroup();
if (g)
g->UnMarkNPC(ID);
}
auto it = group_list.begin();
while (it != group_list.end()) {
if (*it)
(*it)->UnMarkNPC(ID);
++it;
}
}
@@ -4197,6 +4244,20 @@ void EntityList::SignalAllClients(uint32 data)
}
}
uint16 EntityList::GetClientCount(){
uint16 ClientCount = 0;
std::list<Client*> client_list;
entity_list.GetClientList(client_list);
std::list<Client*>::iterator iter = client_list.begin();
while (iter != client_list.end()) {
Client *entry = (*iter);
entry->GetCleanName();
ClientCount++;
iter++;
}
return ClientCount;
}
void EntityList::GetMobList(std::list<Mob *> &m_list)
{
m_list.clear();
@@ -4602,42 +4663,49 @@ Client *EntityList::FindCorpseDragger(uint16 CorpseID)
return nullptr;
}
Mob *EntityList::GetTargetForVirus(Mob *spreader)
Mob *EntityList::GetTargetForVirus(Mob *spreader, int range)
{
int max_spread_range = RuleI(Spells, VirusSpreadDistance);
if (range)
max_spread_range = range;
std::vector<Mob *> TargetsInRange;
auto it = mob_list.begin();
while (it != mob_list.end()) {
Mob *cur = it->second;
// Make sure the target is in range, has los and is not the mob doing the spreading
if ((it->second->GetID() != spreader->GetID()) &&
(it->second->CalculateDistance(spreader->GetX(), spreader->GetY(),
if ((cur->GetID() != spreader->GetID()) &&
(cur->CalculateDistance(spreader->GetX(), spreader->GetY(),
spreader->GetZ()) <= max_spread_range) &&
(spreader->CheckLosFN(it->second))) {
(spreader->CheckLosFN(cur))) {
// If the spreader is an npc it can only spread to other npc controlled mobs
if (spreader->IsNPC() && !spreader->IsPet() && it->second->IsNPC()) {
TargetsInRange.push_back(it->second);
if (spreader->IsNPC() && !spreader->IsPet() && !spreader->CastToNPC()->GetSwarmOwner() && cur->IsNPC()) {
TargetsInRange.push_back(cur);
}
// If the spreader is an npc controlled pet it can spread to any other npc or an npc controlled pet
else if (spreader->IsNPC() && spreader->IsPet() && spreader->GetOwner()->IsNPC()) {
if (it->second->IsNPC() && !it->second->IsPet()) {
TargetsInRange.push_back(it->second);
} else if (it->second->IsNPC() && it->second->IsPet() && it->second->GetOwner()->IsNPC()) {
TargetsInRange.push_back(it->second);
if (cur->IsNPC() && !cur->IsPet()) {
TargetsInRange.push_back(cur);
} else if (cur->IsNPC() && cur->IsPet() && cur->GetOwner()->IsNPC()) {
TargetsInRange.push_back(cur);
}
else if (cur->IsNPC() && cur->CastToNPC()->GetSwarmOwner() && cur->GetOwner()->IsNPC()) {
TargetsInRange.push_back(cur);
}
}
// if the spreader is anything else(bot, pet, etc) then it should spread to everything but non client controlled npcs
else if (!spreader->IsNPC() && !it->second->IsNPC()) {
TargetsInRange.push_back(it->second);
else if (!spreader->IsNPC() && !cur->IsNPC()) {
TargetsInRange.push_back(cur);
}
// if its a pet we need to determine appropriate targets(pet to client, pet to pet, pet to bot, etc)
else if (spreader->IsNPC() && spreader->IsPet() && !spreader->GetOwner()->IsNPC()) {
if (!it->second->IsNPC()) {
TargetsInRange.push_back(it->second);
else if (spreader->IsNPC() && (spreader->IsPet() || spreader->CastToNPC()->GetSwarmOwner()) && !spreader->GetOwner()->IsNPC()) {
if (!cur->IsNPC()) {
TargetsInRange.push_back(cur);
}
else if (it->second->IsNPC() && it->second->IsPet() && !it->second->GetOwner()->IsNPC()) {
TargetsInRange.push_back(it->second);
else if (cur->IsNPC() && (cur->IsPet() || cur->CastToNPC()->GetSwarmOwner()) && !cur->GetOwner()->IsNPC()) {
TargetsInRange.push_back(cur);
}
}
}
+9 -6
View File
@@ -28,8 +28,7 @@
#include "zonedb.h"
#include "zonedump.h"
#include "zonedbasync.h"
#include "QGlobals.h"
#include "qglobals.h"
class EQApplicationPacket;
@@ -53,7 +52,7 @@ class Bot;
class BotRaids;
#endif
extern EntityList entity_list;
extern EntityList entity_list;
class Entity
{
@@ -98,9 +97,9 @@ 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 ""; }
virtual void DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) { pDBAsyncWorkID = 0; }
bool CheckCoordLosNoZLeaps(float cur_x, float cur_y, float cur_z, float trg_x, float trg_y, float trg_z, float perwalk=1);
#ifdef BOTS
@@ -114,6 +113,7 @@ protected:
uint32 pDBAsyncWorkID;
private:
uint16 id;
time_t spawn_timestamp;
};
class EntityList
@@ -136,7 +136,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);
@@ -251,6 +251,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);
@@ -299,7 +301,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);
@@ -398,6 +400,7 @@ public:
void UpdateFindableNPCState(NPC *n, bool Remove);
void HideCorpses(Client *c, uint8 CurrentMode, uint8 NewMode);
uint16 GetClientCount();
void GetMobList(std::list<Mob*> &m_list);
void GetNPCList(std::list<NPC*> &n_list);
void GetMercList(std::list<Merc*> &n_list);
+118 -83
View File
@@ -18,10 +18,13 @@
#include "../common/debug.h"
#include "../common/features.h"
#include "masterentity.h"
#include "StringIDs.h"
#include "../common/StringUtil.h"
#include "string_ids.h"
#include "../common/string_util.h"
#include "../common/rulesys.h"
#include "QuestParserCollection.h"
#include "quest_parser_collection.h"
#include "queryserv.h"
extern QueryServ* QServ;
static uint32 MaxBankedGroupLeadershipPoints(int Level)
@@ -48,6 +51,8 @@ static uint32 MaxBankedRaidLeadershipPoints(int Level)
void Client::AddEXP(uint32 in_add_exp, uint8 conlevel, bool resexp) {
this->EVENT_ITEM_ScriptStopReturn();
uint32 add_exp = in_add_exp;
if(!resexp && (XPRate != 0))
@@ -128,30 +133,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);
}
}
}
}
@@ -203,7 +238,6 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
return; // Must be invalid class/race
}
if ((set_exp + set_aaxp) > (m_pp.exp+m_pp.expAA)) {
if (isrezzexp)
this->Message_StringID(MT_Experience, REZ_REGAIN);
@@ -279,6 +313,14 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
//Message(15, "You have gained %d skill points!!", m_pp.aapoints - last_unspentAA);
char val1[20]={0};
Message_StringID(MT_Experience, GAIN_ABILITY_POINT,ConvertArray(m_pp.aapoints, val1),m_pp.aapoints == 1 ? "" : "(s)"); //You have gained an ability point! You now have %1 ability point%2.
/* QS: PlayerLogAARate */
if (RuleB(QueryServ, PlayerLogAARate)){
int add_points = (m_pp.aapoints - last_unspentAA);
std::string query = StringFormat("INSERT INTO `qs_player_aa_rate_hourly` (char_id, aa_count, hour_time) VALUES (%i, %i, UNIX_TIMESTAMP() - MOD(UNIX_TIMESTAMP(), 3600)) ON DUPLICATE KEY UPDATE `aa_count` = `aa_count` + %i", this->CharacterID(), add_points, add_points);
QServ->SendQuery(query.c_str());
}
//Message(15, "You now have %d skill points available to spend.", m_pp.aapoints);
}
@@ -290,12 +332,10 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
if(check_level > maxlevel) {
check_level = maxlevel;
if(RuleB(Character, KeepLevelOverMax))
{
if(RuleB(Character, KeepLevelOverMax)) {
set_exp = GetEXPForLevel(GetLevel()+1);
}
else
{
else {
set_exp = GetEXPForLevel(maxlevel);
}
}
@@ -305,8 +345,7 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
if(MaxLevel){
if(GetLevel() >= MaxLevel){
uint32 expneeded = GetEXPForLevel(MaxLevel);
if(set_exp > expneeded)
{
if(set_exp > expneeded) {
set_exp = expneeded;
}
}
@@ -318,11 +357,11 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
if (GetLevel() == check_level-1){
Message_StringID(MT_Experience, GAIN_LEVEL,ConvertArray(check_level,val1));
SendLevelAppearance();
//Message(15, "You have gained a level! Welcome to level %i!", check_level);
/* Message(15, "You have gained a level! Welcome to level %i!", check_level); */
}
if (GetLevel() == check_level){
Message_StringID(MT_Experience, LOSE_LEVEL,ConvertArray(check_level,val1));
//Message(15, "You lost a level! You are now level %i!", check_level);
/* Message(15, "You lost a level! You are now level %i!", check_level); */
}
else
Message(15, "Welcome to level %i!", check_level);
@@ -343,8 +382,7 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
//If were at max level then stop gaining experience if we make it to the cap
if(GetLevel() == maxlevel - 1){
uint32 expneeded = GetEXPForLevel(maxlevel);
if(set_exp > expneeded)
{
if(set_exp > expneeded) {
set_exp = expneeded;
}
}
@@ -396,15 +434,13 @@ void Client::SetLevel(uint8 set_level, bool command)
level = set_level;
if(IsRaidGrouped())
{
if(IsRaidGrouped()) {
Raid *r = this->GetRaid();
if(r){
r->UpdateLevel(GetName(), set_level);
}
}
if(set_level > m_pp.level2)
{
if(set_level > m_pp.level2) {
if(m_pp.level2 == 0)
m_pp.points += 5;
else
@@ -414,6 +450,18 @@ void Client::SetLevel(uint8 set_level, bool command)
}
if(set_level > m_pp.level) {
parse->EventPlayer(EVENT_LEVEL_UP, this, "", 0);
/* QS: PlayerLogLevels */
if (RuleB(QueryServ, PlayerLogLevels)){
std::string event_desc = StringFormat("Leveled UP :: to Level:%i from Level:%i in zoneid:%i instid:%i", set_level, m_pp.level, this->GetZoneID(), this->GetInstanceID());
QServ->PlayerLogEvent(Player_Log_Levels, this->CharacterID(), event_desc);
}
}
else if (set_level < m_pp.level){
/* QS: PlayerLogLevels */
if (RuleB(QueryServ, PlayerLogLevels)){
std::string event_desc = StringFormat("Leveled DOWN :: to Level:%i from Level:%i in zoneid:%i instid:%i", set_level, m_pp.level, this->GetZoneID(), this->GetInstanceID());
QServ->PlayerLogEvent(Player_Log_Levels, this->CharacterID(), event_desc);
}
}
m_pp.level = set_level;
@@ -423,34 +471,34 @@ void Client::SetLevel(uint8 set_level, bool command)
lu->exp = 0;
}
else {
float tmpxp = (float) ( (float) m_pp.exp - GetEXPForLevel( GetLevel() )) /
( (float) GetEXPForLevel(GetLevel()+1) - GetEXPForLevel(GetLevel()));
float tmpxp = (float) ( (float) m_pp.exp - GetEXPForLevel( GetLevel() )) / ( (float) GetEXPForLevel(GetLevel()+1) - GetEXPForLevel(GetLevel()));
lu->exp = (uint32)(330.0f * tmpxp);
}
QueuePacket(outapp);
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);
LogFile->write(EQEMuLog::Normal,"Setting Level for %s to %i", GetName(), set_level);
CalcBonuses();
if(!RuleB(Character, HealOnLevel))
{
if(!RuleB(Character, HealOnLevel)) {
int mhp = CalcMaxHP();
if(GetHP() > mhp)
SetHP(mhp);
}
else
{
else {
SetHP(CalcMaxHP()); // Why not, lets give them a free heal
}
DoTributeUpdate();
DoTributeUpdate();
SendHPUpdate();
SetMana(CalcMaxMana());
UpdateWho();
if(GetMerc())
UpdateMercLevel();
if(GetMerc())
UpdateMercLevel();
Save();
}
@@ -499,23 +547,13 @@ uint32 Client::GetEXPForLevel(uint16 check_level)
uint32 finalxp = uint32(base * mod);
finalxp = mod_client_xp_for_level(finalxp, check_level);
return(finalxp);
return finalxp;
}
void Client::AddLevelBasedExp(uint8 exp_percentage, uint8 max_level) {
if (exp_percentage > 100)
{
exp_percentage = 100;
}
if (!max_level || GetLevel() < max_level)
{
max_level = GetLevel();
}
uint32 newexp = GetEXP() + ((GetEXPForLevel(max_level + 1) - GetEXPForLevel(max_level)) * exp_percentage / 100);
void Client::AddLevelBasedExp(uint8 exp_percentage, uint8 max_level) {
if (exp_percentage > 100) { exp_percentage = 100; }
if (!max_level || GetLevel() < max_level) { max_level = GetLevel(); }
uint32 newexp = GetEXP() + ((GetEXPForLevel(max_level + 1) - GetEXPForLevel(max_level)) * exp_percentage / 100);
SetEXP(newexp, GetAAXP());
}
@@ -657,28 +695,25 @@ void Client::SendLeadershipEXPUpdate() {
}
uint32 Client::GetCharMaxLevelFromQGlobal() {
QGlobalCache *char_c = nullptr;
char_c = this->GetQGlobals();
QGlobalCache *char_c = nullptr;
char_c = this->GetQGlobals();
std::list<QGlobal> globalMap;
uint32 ntype = 0;
std::list<QGlobal> globalMap;
uint32 ntype = 0;
if(char_c) {
QGlobalCache::Combine(globalMap, char_c->GetBucket(), ntype, this->CharacterID(), zone->GetZoneID());
}
if(char_c)
{
QGlobalCache::Combine(globalMap, char_c->GetBucket(), ntype, this->CharacterID(), zone->GetZoneID());
}
std::list<QGlobal>::iterator iter = globalMap.begin();
uint32 gcount = 0;
while(iter != globalMap.end()) {
if((*iter).name.compare("CharMaxLevel") == 0){
return atoi((*iter).value.c_str());
}
++iter;
++gcount;
}
std::list<QGlobal>::iterator iter = globalMap.begin();
uint32 gcount = 0;
while(iter != globalMap.end())
{
if((*iter).name.compare("CharMaxLevel") == 0){
return atoi((*iter).value.c_str());
}
++iter;
++gcount;
}
return false; // Default is false
return false;
}
+19 -32
View File
@@ -23,7 +23,7 @@
#include <cstdlib>
#include "../common/rulesys.h"
#include "../common/MiscFunctions.h"
#include "../common/misc_functions.h"
#include "map.h"
#include "zone.h"
#include "pathing.h"
@@ -31,12 +31,10 @@
#define snprintf _snprintf
#endif
extern Zone* zone;
#define FEAR_PATHING_DEBUG
//this is called whenever we are damaged to process possible fleeing
void Mob::CheckFlee() {
//if were allready fleeing, dont need to check more...
@@ -55,7 +53,7 @@ void Mob::CheckFlee() {
float ratio = GetHPRatio();
float fleeratio = GetSpecialAbility(FLEE_PERCENT);
fleeratio = fleeratio > 0 ? fleeratio : RuleI(Combat, FleeHPRatio);
if(ratio >= fleeratio)
return;
@@ -101,12 +99,13 @@ void Mob::CheckFlee() {
}
}
void Mob::ProcessFlee() {
void Mob::ProcessFlee()
{
//Stop fleeing if effect is applied after they start to run.
//When ImmuneToFlee effect fades it will turn fear back on and check if it can still flee.
if(flee_mode && (GetSpecialAbility(IMMUNE_FLEEING) || spellbonuses.ImmuneToFlee) && !spellbonuses.IsFeared){
if (flee_mode && (GetSpecialAbility(IMMUNE_FLEEING) || spellbonuses.ImmuneToFlee) &&
!spellbonuses.IsFeared && !spellbonuses.IsBlind) {
curfp = false;
return;
}
@@ -114,40 +113,42 @@ void Mob::ProcessFlee() {
//see if we are still dying, if so, do nothing
float fleeratio = GetSpecialAbility(FLEE_PERCENT);
fleeratio = fleeratio > 0 ? fleeratio : RuleI(Combat, FleeHPRatio);
if(GetHPRatio() < fleeratio)
if (GetHPRatio() < fleeratio)
return;
//we are not dying anymore... see what we do next
flee_mode = false;
//see if we are legitimately feared now
if(!spellbonuses.IsFeared) {
//not feared... were done...
//see if we are legitimately feared or blind now
if (!spellbonuses.IsFeared && !spellbonuses.IsBlind) {
//not feared or blind... were done...
curfp = false;
return;
}
}
float Mob::GetFearSpeed() {
if(flee_mode) {
float Mob::GetFearSpeed()
{
if (flee_mode) {
//we know ratio < FLEE_HP_RATIO
float speed = GetBaseRunspeed();
float ratio = GetHPRatio();
float multiplier = RuleR(Combat, FleeMultiplier);
if(GetSnaredAmount() > 40)
if (GetSnaredAmount() > 40)
multiplier = multiplier / 6.0f;
speed = speed * ratio * multiplier / 100;
//NPC will eventually stop. Snares speeds this up.
if(speed < 0.09)
if (speed < 0.09)
speed = 0.0001f;
return(speed);
return speed;
}
return(GetRunspeed());
// fear and blind use their normal run speed
return GetRunspeed();
}
void Mob::CalculateNewFearpoint()
@@ -209,17 +210,3 @@ void Mob::CalculateNewFearpoint()
}
}
+81 -129
View File
@@ -15,82 +15,35 @@
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 "StringIDs.h"
#include "../common/MiscFunctions.h"
#include "../common/StringUtil.h"
#include "../common/misc_functions.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 "QuestParserCollection.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) {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
uint8 index = 0;
uint32 item[FORAGE_ITEM_LIMIT];
uint32 chance[FORAGE_ITEM_LIMIT];
uint32 ret;
@@ -100,31 +53,32 @@ uint32 ZoneDatabase::GetZoneForage(uint32 ZoneID, uint8 skill) {
}
uint32 chancepool = 0;
if (RunQuery(query, MakeAnyLenString(&query, "SELECT itemid,chance FROM forage WHERE zoneid= '%i' and level <= '%i' LIMIT %i", ZoneID, skill, FORAGE_ITEM_LIMIT), errbuf, &result))
{
safe_delete_array(query);
while ((row = mysql_fetch_row(result)) && (index < FORAGE_ITEM_LIMIT)) {
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]);
chancepool = chance[index];
index++;
}
mysql_free_result(result);
}
else {
LogFile->write(EQEMuLog::Error, "Error in Forage query '%s': %s", query, errbuf);
safe_delete_array(query);
std::string query = StringFormat("SELECT itemid, chance FROM "
"forage WHERE zoneid = '%i' and level <= '%i' "
"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;
}
uint8 index = 0;
for (auto row = results.begin(); row != results.end(); ++row, ++index) {
if (index >= FORAGE_ITEM_LIMIT)
break;
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]);
chancepool = chance[index];
}
if(chancepool == 0 || index < 1)
return(0);
return 0;
if(index == 1) {
return(item[0]);
return item[0];
}
ret = 0;
@@ -143,12 +97,6 @@ LogFile->write(EQEMuLog::Error, "Possible Forage: %d with a %d chance", item[ind
uint32 ZoneDatabase::GetZoneFishing(uint32 ZoneID, uint8 skill, uint32 &npc_id, uint8 &npc_chance)
{
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
uint8 index = 0;
uint32 item[50];
uint32 chance[50];
uint32 npc_ids[50];
@@ -161,44 +109,44 @@ uint32 ZoneDatabase::GetZoneFishing(uint32 ZoneID, uint8 skill, uint32 &npc_id,
chance[c]=0;
}
if (RunQuery(query, MakeAnyLenString(&query, "SELECT itemid,chance,npc_id,npc_chance FROM fishing WHERE (zoneid= '%i' || zoneid = 0) and skill_level <= '%i'",ZoneID, skill ), errbuf, &result))
{
safe_delete_array(query);
while ((row = mysql_fetch_row(result))&&(index<50)) {
item[index] = atoi(row[0]);
chance[index] = atoi(row[1])+chancepool;
chancepool = chance[index];
npc_ids[index] = atoi(row[2]);
npc_chances[index] = atoi(row[3]);
index++;
}
mysql_free_result(result);
}
else {
std::cerr << "Error in Fishing query '" << query << "' " << errbuf << std::endl;
safe_delete_array(query);
std::string query = StringFormat("SELECT itemid, chance, npc_id, npc_chance "
"FROM fishing WHERE (zoneid = '%i' || zoneid = 0) AND skill_level <= '%i'",
ZoneID, skill);
auto results = QueryDatabase(query);
if (!results.Success()) {
std::cerr << "Error in Fishing query '" << query << "' " << results.ErrorMessage() << std::endl;
return 0;
}
}
uint8 index = 0;
for (auto row = results.begin(); row != results.end(); ++row, ++index) {
if (index >= 50)
break;
item[index] = atoi(row[0]);
chance[index] = atoi(row[1])+chancepool;
chancepool = chance[index];
npc_ids[index] = atoi(row[2]);
npc_chances[index] = atoi(row[3]);
}
npc_id = 0;
npc_chance = 0;
if (index>0) {
uint32 random = MakeRandomInt(1, chancepool);
for (int i = 0; i < index; i++)
{
if (random <= chance[i])
{
ret = item[i];
npc_id = npc_ids[i];
npc_chance = npc_chances[i];
break;
}
}
} else {
ret = 0;
}
if (index <= 0)
return 0;
uint32 random = MakeRandomInt(1, chancepool);
for (int i = 0; i < index; i++)
{
if (random > chance[i])
continue;
ret = item[i];
npc_id = npc_ids[i];
npc_chance = npc_chances[i];
break;
}
return ret;
}
@@ -245,7 +193,7 @@ bool Client::CanFish() {
dest.y = RodY;
dest.z = z_pos+10;
RodZ = zone->zonemap->FindBestZ(dest, nullptr) - 1;
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);
//Message(0, "Rod is at %4.3f, %4.3f, %4.3f, InWater says %d, InLava says %d", RodX, RodY, RodZ, in_water, in_lava);
@@ -365,11 +313,13 @@ void Client::GoFish()
safe_delete(inst);
inst = m_inv.GetItem(MainCursor);
}
}
std::vector<void*> args;
args.push_back(inst);
parse->EventPlayer(EVENT_FISH_SUCCESS, this, "", inst != nullptr ? inst->GetItem()->ID : 0, &args);
if(inst) {
std::vector<EQEmu::Any> args;
args.push_back(inst);
parse->EventPlayer(EVENT_FISH_SUCCESS, this, "", inst->GetID(), &args);
}
}
}
else
{
@@ -479,11 +429,13 @@ void Client::ForageItem(bool guarantee) {
safe_delete(inst);
inst = m_inv.GetItem(MainCursor);
}
}
std::vector<void*> args;
args.push_back(inst);
parse->EventPlayer(EVENT_FORAGE_SUCCESS, this, "", inst ? inst->GetItem()->ID : 0, &args);
if(inst) {
std::vector<EQEmu::Any> args;
args.push_back(inst);
parse->EventPlayer(EVENT_FORAGE_SUCCESS, this, "", inst->GetID(), &args);
}
}
int ChanceSecondForage = aabonuses.ForageAdditionalItems + itembonuses.ForageAdditionalItems + spellbonuses.ForageAdditionalItems;
if(!guarantee && MakeRandomInt(0,99) < ChanceSecondForage) {
+287 -159
View File
@@ -17,10 +17,10 @@
*/
#include "../common/debug.h"
#include "masterentity.h"
#include "NpcAI.h"
#include "npc_ai.h"
#include "../common/packet_functions.h"
#include "../common/packet_dump.h"
#include "../common/StringUtil.h"
#include "../common/string_util.h"
#include "worldserver.h"
extern EntityList entity_list;
extern WorldServer worldserver;
@@ -46,6 +46,7 @@ Group::Group(uint32 gid)
: GroupIDConsumer(gid)
{
leader = nullptr;
mentoree = nullptr;
memset(members,0,sizeof(Mob*) * MAX_GROUP_MEMBERS);
AssistTargetID = 0;
TankTargetID = 0;
@@ -81,6 +82,7 @@ Group::Group(Mob* leader)
TankTargetID = 0;
PullerTargetID = 0;
memset(&LeaderAbilities, 0, sizeof(GroupLeadershipAA_Struct));
mentoree = nullptr;
uint32 i;
for(i=0;i<MAX_GROUP_MEMBERS;i++)
{
@@ -193,37 +195,42 @@ void Group::SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinu
for (i = 0; i < MAX_GROUP_MEMBERS; i++) {
if (members[i] != nullptr && members[i]->IsClient()) { // If Group Member is Client
Client *c = members[i]->CastToClient();
//I could not get MoneyOnCorpse to work, so we use this
c->AddMoneyToPP(cpsplit, spsplit, gpsplit, ppsplit, true);
c->Message(2, msg.c_str());
Client *c = members[i]->CastToClient();
//I could not get MoneyOnCorpse to work, so we use this
c->AddMoneyToPP(cpsplit, spsplit, gpsplit, ppsplit, true);
c->Message(2, msg.c_str());
}
}
}
bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 CharacterID)
bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 CharacterID, bool ismerc)
{
bool InZone = true;
bool ismerc = false;
// This method should either be passed a Mob*, if the new member is in this zone, or a nullptr Mob*
// and the name and CharacterID of the new member, if they are out of zone.
//
if(!newmember && !NewMemberName)
return false;
{
return false;
}
if(GroupCount() >= MAX_GROUP_MEMBERS) //Sanity check for merging groups together.
{
return false;
}
if(!newmember)
{
InZone = false;
}
else
{
NewMemberName = newmember->GetCleanName();
if(newmember->IsClient())
{
CharacterID = newmember->CastToClient()->CharacterID();
}
if(newmember->IsMerc())
{
Client* owner = newmember->CastToMerc()->GetMercOwner();
@@ -231,18 +238,20 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte
{
CharacterID = owner->CastToClient()->CharacterID();
NewMemberName = newmember->GetName();
ismerc = true;
}
ismerc = true;
}
}
uint32 i = 0;
// See if they are already in the group
//
uint32 i = 0;
for (i = 0; i < MAX_GROUP_MEMBERS; ++i)
{
if(!strcasecmp(membername[i], NewMemberName))
{
return false;
}
}
// Put them in the group
for (i = 0; i < MAX_GROUP_MEMBERS; ++i)
@@ -250,17 +259,20 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte
if (membername[i][0] == '\0')
{
if(InZone)
{
members[i] = newmember;
}
strcpy(membername[i], NewMemberName);
MemberRoles[i] = 0;
break;
}
}
// Is this even possible based on the above loops? Remove?
if (i == MAX_GROUP_MEMBERS)
{
return false;
strcpy(membername[i], NewMemberName);
MemberRoles[i] = 0;
}
int x=1;
@@ -269,11 +281,12 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte
GroupJoin_Struct* gj = (GroupJoin_Struct*) outapp->pBuffer;
strcpy(gj->membername, NewMemberName);
gj->action = groupActJoin;
gj->leader_aas = LeaderAbilities;
for (i = 0;i < MAX_GROUP_MEMBERS; i++) {
if (members[i] != nullptr && members[i] != newmember) {
for (i = 0;i < MAX_GROUP_MEMBERS; i++)
{
if (members[i] != nullptr && members[i] != newmember)
{
//fill in group join & send it
if(members[i]->IsMerc())
{
@@ -283,18 +296,23 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte
{
strcpy(gj->yourname, members[i]->GetCleanName());
}
if(members[i]->IsClient()) {
if(members[i]->IsClient())
{
members[i]->CastToClient()->QueuePacket(outapp);
//put new member into existing person's list
//put new member into existing group members' list(s)
strcpy(members[i]->CastToClient()->GetPP().groupMembers[this->GroupCount()-1], NewMemberName);
}
//put this existing person into the new member's list
if(InZone && newmember->IsClient()) {
//put existing group member(s) into the new member's list
if(InZone && newmember->IsClient())
{
if(IsLeader(members[i]))
{
strcpy(newmember->CastToClient()->GetPP().groupMembers[0], members[i]->GetCleanName());
else {
}
else
{
strcpy(newmember->CastToClient()->GetPP().groupMembers[x], members[i]->GetCleanName());
x++;
}
@@ -336,7 +354,9 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte
#endif //BOTS
}
else
{
database.SetGroupID(NewMemberName, GetID(), CharacterID, ismerc);
}
safe_delete(outapp);
@@ -468,6 +488,11 @@ bool Group::UpdatePlayer(Mob* update){
return true;
}
}
// mentoree isn't set, the name has a length and the name is ours! update the pointer
if (update->IsClient() && !mentoree && mentoree_name.length() && !mentoree_name.compare(update->GetName()))
mentoree = update->CastToClient();
return false;
}
@@ -501,6 +526,33 @@ void Group::MemberZoned(Mob* removemob) {
if(removemob->IsClient() && HasRole(removemob, RolePuller))
SetGroupPullerTarget(0);
if (removemob->IsClient() && removemob == mentoree)
mentoree = nullptr;
}
void Group::SendGroupJoinOOZ(Mob* NewMember) {
if (NewMember == nullptr)
{
return;
}
if (!NewMember->HasGroup())
{
return;
}
//send updates to clients out of zone...
ServerPacket* pack = new ServerPacket(ServerOP_GroupJoin, sizeof(ServerGroupJoin_Struct));
ServerGroupJoin_Struct* gj = (ServerGroupJoin_Struct*)pack->pBuffer;
gj->gid = GetID();
gj->zoneid = zone->GetZoneID();
gj->instance_id = zone->GetInstanceID();
strcpy(gj->member_name, NewMember->GetName());
worldserver.SendPacket(pack);
safe_delete(pack);
}
bool Group::DelMemberOOZ(const char *Name) {
@@ -529,6 +581,8 @@ bool Group::DelMemberOOZ(const char *Name) {
}
ClearAllNPCMarks();
}
if (Name == mentoree_name)
ClearGroupMentor();
return true;
}
}
@@ -538,12 +592,15 @@ bool Group::DelMemberOOZ(const char *Name) {
bool Group::DelMember(Mob* oldmember,bool ignoresender)
{
if (oldmember == nullptr){
if (oldmember == nullptr)
{
return false;
}
for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) {
if (members[i] == oldmember) {
for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++)
{
if (members[i] == oldmember)
{
members[i] = nullptr;
membername[i][0] = '\0';
memset(membername[i],0,64);
@@ -552,15 +609,40 @@ bool Group::DelMember(Mob* oldmember,bool ignoresender)
}
}
/* This may seem pointless but the case above does not cover the following situation:
* Group has Leader a, member b, member c
* b and c are out of zone
* a disconnects/quits
* b or c zone back in and disconnects/quits
* a is still "leader" from GetLeader()'s perspective and will crash the zone when we DelMember(b)
* Ultimately we should think up a better solution to this.
*/
if(oldmember == GetLeader())
{
SetLeader(nullptr);
}
//handle leader quitting group gracefully
if (oldmember == GetLeader() && GroupCount() >= 2) {
for(uint32 nl = 0; nl < MAX_GROUP_MEMBERS; nl++) {
if(members[nl]) {
ChangeLeader(members[nl]);
break;
if (oldmember == GetLeader() && GroupCount() >= 2)
{
for(uint32 nl = 0; nl < MAX_GROUP_MEMBERS; nl++)
{
if(members[nl])
{
if (members[nl]->IsClient())
{
ChangeLeader(members[nl]);
break;
}
}
}
}
if (GetLeader() == nullptr)
{
DisbandGroup();
return true;
}
ServerPacket* pack = new ServerPacket(ServerOP_GroupLeave, sizeof(ServerGroupLeave_Struct));
ServerGroupLeave_Struct* gl = (ServerGroupLeave_Struct*)pack->pBuffer;
@@ -596,7 +678,8 @@ bool Group::DelMember(Mob* oldmember,bool ignoresender)
#endif //BOTS
}
if (!ignoresender) {
if (!ignoresender)
{
strcpy(gu->yourname,oldmember->GetCleanName());
strcpy(gu->membername,oldmember->GetCleanName());
gu->action = groupActLeave;
@@ -606,7 +689,18 @@ bool Group::DelMember(Mob* oldmember,bool ignoresender)
}
if(oldmember->IsClient())
database.SetGroupID(oldmember->GetCleanName(), 0, oldmember->CastToClient()->CharacterID());
{
database.SetGroupID(oldmember->GetCleanName(), 0, oldmember->CastToClient()->CharacterID(), false);
}
if(oldmember->IsMerc())
{
Client* owner = oldmember->CastToMerc()->GetMercOwner();
if(owner)
{
database.SetGroupID(oldmember->GetName(), 0, owner->CharacterID(), true);
}
}
oldmember->SetGrouped(false);
disbandcheck = true;
@@ -631,6 +725,9 @@ bool Group::DelMember(Mob* oldmember,bool ignoresender)
UnDelegatePuller(oldmember->GetName());
}
if (oldmember->GetName() == mentoree_name)
ClearGroupMentor();
if(oldmember->IsClient())
SendMarkedNPCsToMember(oldmember->CastToClient(), true);
@@ -667,7 +764,7 @@ void Group::CastGroupSpell(Mob* caster, uint16 spell_id) {
if(members[z] == caster) {
caster->SpellOnTarget(spell_id, caster);
#ifdef GROUP_BUFF_PETS
if(caster->GetPet() && caster->HasPetAffinity() && !caster->GetPet()->IsCharmed())
if(spells[spell_id].targettype != ST_GroupNoPets && caster->GetPet() && caster->HasPetAffinity() && !caster->GetPet()->IsCharmed())
caster->SpellOnTarget(spell_id, caster->GetPet());
#endif
}
@@ -678,7 +775,7 @@ void Group::CastGroupSpell(Mob* caster, uint16 spell_id) {
members[z]->CalcSpellPowerDistanceMod(spell_id, distance);
caster->SpellOnTarget(spell_id, members[z]);
#ifdef GROUP_BUFF_PETS
if(members[z]->GetPet() && members[z]->HasPetAffinity() && !members[z]->GetPet()->IsCharmed())
if(spells[spell_id].targettype != ST_GroupNoPets && members[z]->GetPet() && members[z]->HasPetAffinity() && !members[z]->GetPet()->IsCharmed())
caster->SpellOnTarget(spell_id, members[z]->GetPet());
#endif
} else
@@ -793,20 +890,33 @@ void Group::DisbandGroup() {
Client *Leader = nullptr;
uint32 i;
for (i = 0; i < MAX_GROUP_MEMBERS; i++) {
if (members[i] == nullptr) {
for (i = 0; i < MAX_GROUP_MEMBERS; i++)
{
if (members[i] == nullptr)
{
continue;
}
if (members[i]->IsClient()) {
if (members[i]->IsClient())
{
if(IsLeader(members[i]))
{
Leader = members[i]->CastToClient();
}
strcpy(gu->yourname, members[i]->GetName());
database.SetGroupID(members[i]->GetName(), 0, members[i]->CastToClient()->CharacterID());
database.SetGroupID(members[i]->GetName(), 0, members[i]->CastToClient()->CharacterID(), false);
members[i]->CastToClient()->QueuePacket(outapp);
SendMarkedNPCsToMember(members[i]->CastToClient(), true);
}
if (members[i]->IsMerc())
{
Client* owner = members[i]->CastToMerc()->GetMercOwner();
if(owner)
{
database.SetGroupID(members[i]->GetName(), 0, owner->CharacterID(), true);
}
}
members[i]->SetGrouped(false);
@@ -826,9 +936,12 @@ void Group::DisbandGroup() {
entity_list.RemoveGroup(GetID());
if(GetID() != 0)
{
database.ClearGroup(GetID());
}
if(Leader && (Leader->IsLFP())) {
if(Leader && (Leader->IsLFP()))
{
Leader->UpdateLFP();
}
@@ -910,8 +1023,12 @@ uint8 Group::GroupCount() {
uint8 MemberCount = 0;
for(uint8 i = 0; i < MAX_GROUP_MEMBERS; ++i)
{
if(membername[i][0])
{
++MemberCount;
}
}
return MemberCount;
}
@@ -958,31 +1075,28 @@ void Group::TeleportGroup(Mob* sender, uint32 zoneID, uint16 instance_id, float
}
bool Group::LearnMembers() {
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if (database.RunQuery(query,MakeAnyLenString(&query, "SELECT name FROM group_id WHERE groupid=%lu", (unsigned long)GetID()),
errbuf,&result)){
safe_delete_array(query);
if(mysql_num_rows(result) < 1) { //could prolly be 2
mysql_free_result(result);
LogFile->write(EQEMuLog::Error, "Error getting group members for group %lu: %s", (unsigned long)GetID(), errbuf);
return(false);
}
int i = 0;
while((row = mysql_fetch_row(result))) {
if(!row[0])
continue;
members[i] = nullptr;
strn0cpy(membername[i], row[0], 64);
std::string query = StringFormat("SELECT name FROM group_id WHERE groupid = %lu", (unsigned long)GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
return false;
i++;
}
mysql_free_result(result);
if (results.RowCount() == 0) {
LogFile->write(EQEMuLog::Error, "Error getting group members for group %lu: %s", (unsigned long)GetID(), results.ErrorMessage().c_str());
return false;
}
int memberIndex = 0;
for(auto row = results.begin(); row != results.end(); ++row) {
if(!row[0])
continue;
members[memberIndex] = nullptr;
strn0cpy(membername[memberIndex], row[0], 64);
memberIndex++;
}
return(true);
return true;
}
void Group::VerifyGroup() {
@@ -1046,27 +1160,49 @@ void Group::GroupMessage_StringID(Mob* sender, uint32 type, uint32 string_id, co
void Client::LeaveGroup() {
Group *g = GetGroup();
if(g) {
if(g->GroupCount() < 3)
if(g)
{
int32 MemberCount = g->GroupCount();
// Account for both client and merc leaving the group
if (GetMerc() && GetMerc()->HasGroup() && GetMerc()->GetGroup() == g)
{
MemberCount -= 1;
}
if(MemberCount < 3)
{
g->DisbandGroup();
}
else
{
g->DelMember(this);
} else {
if (GetMerc() && GetMerc()->HasGroup() && GetMerc()->GetGroup() == g)
{
GetMerc()->RemoveMercFromGroup(GetMerc(), GetMerc()->GetGroup());
}
}
}
else
{
//force things a little
database.SetGroupID(GetName(), 0, CharacterID());
database.SetGroupID(GetName(), 0, CharacterID(), false);
if (GetMerc())
{
database.SetGroupID(GetMerc()->GetName(), 0, CharacterID(), true);
}
}
isgrouped = false;
}
void Group::HealGroup(uint32 heal_amt, Mob* caster, int32 range)
void Group::HealGroup(uint32 heal_amt, Mob* caster, float range)
{
if (!caster)
return;
if (!range)
range = 200;
float distance;
float range2 = range*range;
@@ -1097,16 +1233,16 @@ void Group::HealGroup(uint32 heal_amt, Mob* caster, int32 range)
}
void Group::BalanceHP(int32 penalty, int32 range, Mob* caster, int32 limit)
void Group::BalanceHP(int32 penalty, float range, Mob* caster, int32 limit)
{
if (!caster)
return;
if (!range)
range = 200;
range = 200;
int dmgtaken = 0, numMem = 0, dmgtaken_tmp = 0;
float distance;
float range2 = range*range;
@@ -1147,22 +1283,22 @@ void Group::BalanceHP(int32 penalty, int32 range, Mob* caster, int32 limit)
}
}
void Group::BalanceMana(int32 penalty, int32 range, Mob* caster, int32 limit)
void Group::BalanceMana(int32 penalty, float range, Mob* caster, int32 limit)
{
if (!caster)
return;
if (!range)
range = 200;
range = 200;
float distance;
float range2 = range*range;
int manataken = 0, numMem = 0, manataken_tmp = 0;
unsigned int gi = 0;
for(; gi < MAX_GROUP_MEMBERS; gi++)
{
if(members[gi] && (members[gi]->GetMaxMana() > 0)){
if(members[gi] && (members[gi]->GetMaxMana() > 0)){
distance = caster->DistNoRoot(*members[gi]);
if(distance <= range2){
@@ -1330,15 +1466,12 @@ void Group::DelegateMainTank(const char *NewMainTankName, uint8 toggle)
}
if(updateDB) {
char errbuff[MYSQL_ERRMSG_SIZE];
char *Query = nullptr;
if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET maintank='%s' WHERE gid=%i LIMIT 1",
MainTankName.c_str(), GetID()), errbuff))
LogFile->write(EQEMuLog::Error, "Unable to set group main tank: %s\n", errbuff);
safe_delete_array(Query);
std::string query = StringFormat("UPDATE group_leaders SET maintank = '%s' WHERE gid = %i LIMIT 1",
MainTankName.c_str(), GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to set group main tank: %s\n", results.ErrorMessage().c_str());
}
}
@@ -1379,15 +1512,13 @@ void Group::DelegateMainAssist(const char *NewMainAssistName, uint8 toggle)
}
if(updateDB) {
char errbuff[MYSQL_ERRMSG_SIZE];
char *Query = nullptr;
std::string query = StringFormat("UPDATE group_leaders SET assist = '%s' WHERE gid = %i LIMIT 1",
MainAssistName.c_str(), GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to set group main assist: %s\n", results.ErrorMessage().c_str());
if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET assist='%s' WHERE gid=%i LIMIT 1",
MainAssistName.c_str(), GetID()), errbuff))
LogFile->write(EQEMuLog::Error, "Unable to set group main assist: %s\n", errbuff);
safe_delete_array(Query);
}
}
@@ -1428,15 +1559,13 @@ void Group::DelegatePuller(const char *NewPullerName, uint8 toggle)
}
if(updateDB) {
char errbuff[MYSQL_ERRMSG_SIZE];
char *Query = nullptr;
std::string query = StringFormat("UPDATE group_leaders SET puller = '%s' WHERE gid = %i LIMIT 1",
PullerName.c_str(), GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to set group main puller: %s\n", results.ErrorMessage().c_str());
if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET puller='%s' WHERE gid=%i LIMIT 1",
PullerName.c_str(), GetID()), errbuff))
LogFile->write(EQEMuLog::Error, "Unable to set group main puller: %s\n", errbuff);
safe_delete_array(Query);
}
}
@@ -1582,15 +1711,11 @@ void Group::UnDelegateMainTank(const char *OldMainTankName, uint8 toggle)
// informing them of the change and update the group_leaders table.
//
if(OldMainTankName == MainTankName) {
char errbuff[MYSQL_ERRMSG_SIZE];
char *Query = 0;
if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET maintank='' WHERE gid=%i LIMIT 1",
GetID()), errbuff))
LogFile->write(EQEMuLog::Error, "Unable to clear group main tank: %s\n", errbuff);
safe_delete_array(Query);
std::string query = StringFormat("UPDATE group_leaders SET maintank = '' WHERE gid = %i LIMIT 1", GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to clear group main tank: %s\n", results.ErrorMessage().c_str());
if(!toggle) {
for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) {
@@ -1636,15 +1761,10 @@ void Group::UnDelegateMainAssist(const char *OldMainAssistName, uint8 toggle)
safe_delete(outapp);
char errbuff[MYSQL_ERRMSG_SIZE];
char *Query = 0;
if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET assist='' WHERE gid=%i LIMIT 1",
GetID()), errbuff))
LogFile->write(EQEMuLog::Error, "Unable to clear group main assist: %s\n", errbuff);
safe_delete_array(Query);
std::string query = StringFormat("UPDATE group_leaders SET assist = '' WHERE gid = %i LIMIT 1", GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to clear group main assist: %s\n", results.ErrorMessage().c_str());
if(!toggle)
{
@@ -1668,15 +1788,11 @@ void Group::UnDelegatePuller(const char *OldPullerName, uint8 toggle)
// informing them of the change and update the group_leaders table.
//
if(OldPullerName == PullerName) {
char errbuff[MYSQL_ERRMSG_SIZE];
char *Query = 0;
if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET puller='' WHERE gid=%i LIMIT 1",
GetID()), errbuff))
LogFile->write(EQEMuLog::Error, "Unable to clear group main puller: %s\n", errbuff);
safe_delete_array(Query);
std::string query = StringFormat("UPDATE group_leaders SET puller = '' WHERE gid = %i LIMIT 1", GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to clear group main puller: %s\n", results.ErrorMessage().c_str());
if(!toggle) {
for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) {
@@ -1748,6 +1864,31 @@ void Group::SetGroupPullerTarget(Mob *m)
}
}
void Group::SetGroupMentor(int percent, char *name)
{
mentoree_name = name;
mentor_percent = percent;
Client *client = entity_list.GetClientByName(name);
mentoree = client ? client : nullptr;
std::string query = StringFormat("UPDATE group_leaders SET mentoree = '%s', mentor_percent = %i WHERE gid = %i LIMIT 1",
mentoree_name.c_str(), mentor_percent, GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to set group mentor: %s\n", results.ErrorMessage().c_str());
}
void Group::ClearGroupMentor()
{
mentoree_name.clear();
mentor_percent = 0;
mentoree = nullptr;
std::string query = StringFormat("UPDATE group_leaders SET mentoree = '', mentor_percent = 0 WHERE gid = %i LIMIT 1", GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to clear group mentor: %s\n", results.ErrorMessage().c_str());
}
void Group::NotifyAssistTarget(Client *c)
{
// Send a packet to the specified client notifying them of the group target selected by the Main Assist.
@@ -1811,16 +1952,11 @@ void Group::DelegateMarkNPC(const char *NewNPCMarkerName)
if(members[i] && members[i]->IsClient())
NotifyMarkNPC(members[i]->CastToClient());
char errbuff[MYSQL_ERRMSG_SIZE];
char *Query = 0;
if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET marknpc='%s' WHERE gid=%i LIMIT 1",
NewNPCMarkerName, GetID()), errbuff))
LogFile->write(EQEMuLog::Error, "Unable to set group mark npc: %s\n", errbuff);
safe_delete_array(Query);
std::string query = StringFormat("UPDATE group_leaders SET marknpc = '%s' WHERE gid = %i LIMIT 1",
NewNPCMarkerName, GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to set group mark npc: %s\n", results.ErrorMessage().c_str());
}
void Group::NotifyMarkNPC(Client *c)
@@ -1897,37 +2033,29 @@ void Group::UnDelegateMarkNPC(const char *OldNPCMarkerName)
NPCMarkerName.clear();
char errbuff[MYSQL_ERRMSG_SIZE];
char *Query = 0;
std::string query = StringFormat("UPDATE group_leaders SET marknpc = '' WHERE gid = %i LIMIT 1", GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to clear group marknpc: %s\n", results.ErrorMessage().c_str());
if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET marknpc='' WHERE gid=%i LIMIT 1",
GetID()), errbuff))
LogFile->write(EQEMuLog::Error, "Unable to clear group marknpc: %s\n", errbuff);
safe_delete_array(Query);
}
void Group::SaveGroupLeaderAA()
{
// Stores the Group Leaders Leadership AA data from the Player Profile as a blob in the group_leaders table.
// This is done so that group members not in the same zone as the Leader still have access to this information.
char *queryBuffer = new char[sizeof(GroupLeadershipAA_Struct) * 2 + 1];
database.DoEscapeString(queryBuffer, (char*)&LeaderAbilities, sizeof(GroupLeadershipAA_Struct));
char *Query = new char[200 + sizeof(GroupLeadershipAA_Struct)*2];
std::string query = "UPDATE group_leaders SET leadershipaa = '";
query += queryBuffer;
query += StringFormat("' WHERE gid = %i LIMIT 1", GetID());
safe_delete_array(queryBuffer);
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to store LeadershipAA: %s\n", results.ErrorMessage().c_str());
char *End = Query;
End += sprintf(End, "UPDATE group_leaders SET leadershipaa='");
End += database.DoEscapeString(End, (char*)&LeaderAbilities, sizeof(GroupLeadershipAA_Struct));
End += sprintf(End,"' WHERE gid=%i LIMIT 1", GetID());
char errbuff[MYSQL_ERRMSG_SIZE];
if (!database.RunQuery(Query, End - Query, errbuff))
LogFile->write(EQEMuLog::Error, "Unable to store LeadershipAA: %s\n", errbuff);
safe_delete_array(Query);
}
void Group::UnMarkNPC(uint16 ID)
+13 -4
View File
@@ -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
+34 -57
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/ZoneNumbers.h"
#include "../common/moremath.h"
#include "../common/guilds.h"
#include "../common/StringUtil.h"
#include "../common/string_util.h"
#include "guild_mgr.h"
#include "StringIDs.h"
#include "NpcAI.h"
#include "worldserver.h"
extern WorldServer worldserver;
@@ -160,9 +150,17 @@ void Client::SendGuildSpawnAppearance() {
uint8 rank = guild_mgr.GetDisplayedRank(GuildID(), GuildRank(), CharacterID());
mlog(GUILDS__OUT_PACKETS, "Sending spawn appearance for guild %d at rank %d", GuildID(), rank);
SendAppearancePacket(AT_GuildID, GuildID());
if(GetClientVersion() >= EQClientRoF)
{
switch (rank) {
case 0: { rank = 5; break; } // GUILD_MEMBER 0
case 1: { rank = 3; break; } // GUILD_OFFICER 1
case 2: { rank = 1; break; } // GUILD_LEADER 2
default: { break; } // GUILD_NONE
}
}
SendAppearancePacket(AT_GuildRank, rank);
}
UpdateWho();
}
@@ -409,57 +407,36 @@ void Client::GuildChangeRank(const char* name, uint32 guild_id, uint32 oldrank,
}*/
bool ZoneDatabase::CheckGuildDoor(uint8 doorid,uint16 guild_id,const char* zone) {
MYSQL_ROW row;
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
if (!RunQuery(query, MakeAnyLenString(&query,
"SELECT guild FROM doors where doorid=%i AND zone='%s'",
doorid-128, zone), errbuf, &result))
{
LogFile->write(EQEMuLog::Error, "Error in CheckGuildDoor query '%s': %s", query, errbuf);
safe_delete_array(query);
return false;
} else {
if (mysql_num_rows(result) == 1) {
row = mysql_fetch_row(result);
if (atoi(row[0]) == guild_id)
{
mysql_free_result(result);
return true;
}
else
{
mysql_free_result(result);
return false;
}
bool ZoneDatabase::CheckGuildDoor(uint8 doorid, uint16 guild_id, const char* zone) {
// code below will never be reached
mysql_free_result(result);
return false;
}
std::string query = StringFormat("SELECT guild FROM doors WHERE doorid = %i AND zone = '%s'",
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;
}
return false;
if (results.RowCount() != 1)
return false;
auto row = results.begin();
return atoi(row[0]) == guild_id;
}
bool ZoneDatabase::SetGuildDoor(uint8 doorid,uint16 guild_id, const char* zone) {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
uint32 affected_rows = 0;
if (doorid > 127)
doorid = doorid - 128;
if (!RunQuery(query, MakeAnyLenString(&query,
"UPDATE doors SET guild = %i WHERE (doorid=%i) AND (zone='%s')",
guild_id, doorid, zone), errbuf, 0,&affected_rows))
{
LogFile->write(EQEMuLog::Error, "Error in SetGuildDoor query '%s': %s", query, errbuf);
safe_delete_array(query);
std::string query = StringFormat("UPDATE doors SET guild = %i WHERE (doorid=%i) AND (zone='%s')",
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;
}
safe_delete_array(query);
return(affected_rows > 0);
return (results.RowsAffected() > 0);
}
+175 -315
View File
@@ -20,63 +20,10 @@
#include "zonedb.h"
#include "worldserver.h"
#include "../common/servertalk.h"
#include "../common/StringUtil.h"
#include "../common/string_util.h"
#include "client.h"
#include "entity.h"
/*
CREATE TABLE guilds (
id MEDIUMINT UNSIGNED NOT NULL,
name VARCHAR(32) NOT NULL,
leader int NOT NULL,
minstatus SMALLINT NOT NULL,
tribute INT UNSIGNED NOT NULL,
motd TEXT NOT NULL DEFAULT '',
PRIMARY KEY(id),
UNIQUE KEY(name),
UNIQUE KEY(leader)
);
CREATE TABLE guild_ranks (
guild_id MEDIUMINT UNSIGNED NOT NULL,
rank TINYINT UNSIGNED NOT NULL,
title VARCHAR(128) NOT NULL,
can_hear TINYINT UNSIGNED NOT NULL,
can_speak TINYINT UNSIGNED NOT NULL,
can_invite TINYINT UNSIGNED NOT NULL,
can_remove TINYINT UNSIGNED NOT NULL,
can_promote TINYINT UNSIGNED NOT NULL,
can_demote TINYINT UNSIGNED NOT NULL,
can_motd TINYINT UNSIGNED NOT NULL,
can_warpeace TINYINT UNSIGNED NOT NULL,
PRIMARY KEY(guild_id,rank)
);
# guild1 < guild2 by definition.
CREATE TABLE guild_relations (
guild1 MEDIUMINT UNSIGNED NOT NULL,
guild2 MEDIUMINT UNSIGNED NOT NULL,
relation TINYINT NOT NULL,
PRIMARY KEY(guild1, guild1)
);
CREATE TABLE guild_members (
char_id INT NOT NULL,
guild_id MEDIUMINT UNSIGNED NOT NULL,
rank TINYINT UNSIGNED NOT NULL,
tribute_enable TINYINT UNSIGNED NOT NULL DEFAULT 0,
total_tribute INT UNSIGNED NOT NULL DEFAULT 0,
last_tribute INT UNSIGNED NOT NULL DEFAULT 0,
banker TINYINT UNSIGNED NOT NULL DEFAULT 0,
public_note TEXT NOT NULL DEFAULT '',
PRIMARY KEY(char_id)
);
*/
ZoneGuildManager guild_mgr;
GuildBankManager *GuildBanks;
@@ -374,6 +321,10 @@ 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)
{
c->SendGuildRanks();
}
}
@@ -644,104 +595,73 @@ GuildBankManager::~GuildBankManager()
}
}
bool GuildBankManager::Load(uint32 GuildID)
bool GuildBankManager::Load(uint32 guildID)
{
const char *LoadQuery = "SELECT `area`, `slot`, `itemid`, `qty`, `donator`, `permissions`, `whofor` from `guild_bank` "
"WHERE `guildid` = %i";
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if(database.RunQuery(query, MakeAnyLenString(&query, LoadQuery, GuildID), errbuf, &result))
{
GuildBank *Bank = new GuildBank;
Bank->GuildID = GuildID;
for(int i = 0; i < GUILD_BANK_MAIN_AREA_SIZE; ++i)
Bank->Items.MainArea[i].ItemID = 0;
for(int i = 0; i < GUILD_BANK_DEPOSIT_AREA_SIZE; ++i)
Bank->Items.DepositArea[i].ItemID = 0;
char Donator[64], WhoFor[64];
while((row = mysql_fetch_row(result)))
{
int Area = atoi(row[0]);
int Slot = atoi(row[1]);
int ItemID = atoi(row[2]);
int Qty = atoi(row[3]);
if(row[4])
strn0cpy(Donator, row[4], sizeof(Donator));
else
Donator[0] = '\0';
int Permissions = atoi(row[5]);
if(row[6])
strn0cpy(WhoFor, row[6], sizeof(WhoFor));
else
WhoFor[0] = '\0';
if(Area == GuildBankMainArea)
{
if((Slot >= 0) && (Slot < GUILD_BANK_MAIN_AREA_SIZE))
{
Bank->Items.MainArea[Slot].ItemID = ItemID;
Bank->Items.MainArea[Slot].Quantity = Qty;
strn0cpy(Bank->Items.MainArea[Slot].Donator, Donator, sizeof(Donator));
Bank->Items.MainArea[Slot].Permissions = Permissions;
strn0cpy(Bank->Items.MainArea[Slot].WhoFor, WhoFor, sizeof(WhoFor));
}
}
else
{
if((Slot >= 0 ) && (Slot < GUILD_BANK_DEPOSIT_AREA_SIZE))
{
Bank->Items.DepositArea[Slot].ItemID = ItemID;
Bank->Items.DepositArea[Slot].Quantity = Qty;
strn0cpy(Bank->Items.DepositArea[Slot].Donator, Donator, sizeof(Donator));
Bank->Items.DepositArea[Slot].Permissions = Permissions;
strn0cpy(Bank->Items.DepositArea[Slot].WhoFor, WhoFor, sizeof(WhoFor));
}
}
}
mysql_free_result(result);
safe_delete_array(query);
Banks.push_back(Bank);
}
else
{
_log(GUILDS__BANK_ERROR, "Error Loading guild bank: %s, %s", query, errbuf);
safe_delete_array(query);
std::string query = StringFormat("SELECT `area`, `slot`, `itemid`, `qty`, `donator`, `permissions`, `whofor` "
"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;
}
return true;
GuildBank *bank = new GuildBank;
bank->GuildID = guildID;
for(int i = 0; i < GUILD_BANK_MAIN_AREA_SIZE; ++i)
bank->Items.MainArea[i].ItemID = 0;
for(int i = 0; i < GUILD_BANK_DEPOSIT_AREA_SIZE; ++i)
bank->Items.DepositArea[i].ItemID = 0;
char donator[64], whoFor[64];
for (auto row = results.begin(); row != results.end(); ++row)
{
int area = atoi(row[0]);
int slot = atoi(row[1]);
int itemID = atoi(row[2]);
int qty = atoi(row[3]);
if(row[4])
strn0cpy(donator, row[4], sizeof(donator));
else
donator[0] = '\0';
int permissions = atoi(row[5]);
if(row[6])
strn0cpy(whoFor, row[6], sizeof(whoFor));
else
whoFor[0] = '\0';
if(slot < 0)
continue;
GuildBankItem *itemSection = nullptr;
if (area == GuildBankMainArea && slot < GUILD_BANK_MAIN_AREA_SIZE)
itemSection = bank->Items.MainArea;
else if (area != GuildBankMainArea && slot < GUILD_BANK_DEPOSIT_AREA_SIZE)
itemSection = bank->Items.DepositArea;
else
continue;
itemSection[slot].ItemID = itemID;
itemSection[slot].Quantity = qty;
strn0cpy(itemSection[slot].Donator, donator, sizeof(donator));
itemSection[slot].Permissions = permissions;
strn0cpy(itemSection[slot].WhoFor, whoFor, sizeof(whoFor));
}
Banks.push_back(bank);
return true;
}
bool GuildBankManager::IsLoaded(uint32 GuildID)
@@ -930,24 +850,16 @@ bool GuildBankManager::AddItem(uint32 GuildID, uint8 Area, uint32 ItemID, int32
return false;
}
const char *Query="INSERT INTO `guild_bank` (`guildid`, `area`, `slot`, `itemid`, `qty`, `donator`, `permissions`, `WhoFor`) "
"VALUES (%i, %i, %i, %i, %i, '%s', %i, '%s')";
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
if(!database.RunQuery(query, MakeAnyLenString(&query, Query, GuildID, Area, Slot, ItemID, QtyOrCharges, Donator, Permissions, WhoFor), errbuf))
{
_log(GUILDS__BANK_ERROR, "Insert Error: %s : %s", query, errbuf);
safe_delete_array(query);
std::string query = StringFormat("INSERT INTO `guild_bank` "
"(`guildid`, `area`, `slot`, `itemid`, `qty`, `donator`, `permissions`, `WhoFor`) "
"VALUES (%i, %i, %i, %i, %i, '%s', %i, '%s')",
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;
}
safe_delete_array(query);
const Item_Struct *Item = database.GetItem(ItemID);
GuildBankItemUpdate_Struct gbius;
@@ -973,156 +885,127 @@ bool GuildBankManager::AddItem(uint32 GuildID, uint8 Area, uint32 ItemID, int32
return true;
}
int GuildBankManager::Promote(uint32 GuildID, int SlotID)
int GuildBankManager::Promote(uint32 guildID, int slotID)
{
if((SlotID < 0) || (SlotID > (GUILD_BANK_DEPOSIT_AREA_SIZE - 1)))
if((slotID < 0) || (slotID > (GUILD_BANK_DEPOSIT_AREA_SIZE - 1)))
return -1;
std::list<GuildBank*>::iterator Iterator = GetGuildBank(GuildID);
auto iter = GetGuildBank(guildID);
if(Iterator == Banks.end())
{
if(iter == Banks.end())
return -1;
}
if((*Iterator)->Items.DepositArea[SlotID].ItemID == 0)
{
if((*iter)->Items.DepositArea[slotID].ItemID == 0)
return -1;
}
int MainSlot = -1;
int mainSlot = -1;
for(int i = 0; i < GUILD_BANK_MAIN_AREA_SIZE; ++i)
if((*Iterator)->Items.MainArea[i].ItemID == 0)
{
MainSlot = i;
if((*iter)->Items.MainArea[i].ItemID == 0) {
mainSlot = i;
break;
}
if(MainSlot == -1)
if(mainSlot == -1)
return -1;
(*iter)->Items.MainArea[mainSlot].ItemID = (*iter)->Items.DepositArea[slotID].ItemID;
(*iter)->Items.MainArea[mainSlot].Quantity = (*iter)->Items.DepositArea[slotID].Quantity;
(*iter)->Items.MainArea[mainSlot].Permissions = (*iter)->Items.DepositArea[slotID].Permissions;
(*Iterator)->Items.MainArea[MainSlot].ItemID = (*Iterator)->Items.DepositArea[SlotID].ItemID;
(*Iterator)->Items.MainArea[MainSlot].Quantity = (*Iterator)->Items.DepositArea[SlotID].Quantity;
strn0cpy((*Iterator)->Items.MainArea[MainSlot].Donator, (*Iterator)->Items.DepositArea[SlotID].Donator, sizeof((*Iterator)->Items.MainArea[MainSlot].Donator));
(*Iterator)->Items.MainArea[MainSlot].Permissions = (*Iterator)->Items.DepositArea[SlotID].Permissions;
strn0cpy((*Iterator)->Items.MainArea[MainSlot].WhoFor, (*Iterator)->Items.DepositArea[SlotID].WhoFor, sizeof((*Iterator)->Items.MainArea[MainSlot].WhoFor));
const char *Query="UPDATE `guild_bank` SET `area` = 1, `slot` = %i WHERE `guildid` = %i AND `area` = 0 AND `slot` = %i LIMIT 1";
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
if(!database.RunQuery(query, MakeAnyLenString(&query, Query, MainSlot, GuildID, SlotID), errbuf))
{
_log(GUILDS__BANK_ERROR, "error promoting item: %s : %s", query, errbuf);
safe_delete_array(query);
strn0cpy((*iter)->Items.MainArea[mainSlot].Donator, (*iter)->Items.DepositArea[slotID].Donator, sizeof((*iter)->Items.MainArea[mainSlot].Donator));
strn0cpy((*iter)->Items.MainArea[mainSlot].WhoFor, (*iter)->Items.DepositArea[slotID].WhoFor, sizeof((*iter)->Items.MainArea[mainSlot].WhoFor));
std::string query = StringFormat("UPDATE `guild_bank` SET `area` = 1, `slot` = %i "
"WHERE `guildid` = %i AND `area` = 0 AND `slot` = %i "
"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;
}
safe_delete_array(query);
(*iter)->Items.DepositArea[slotID].ItemID = 0;
(*Iterator)->Items.DepositArea[SlotID].ItemID = 0;
const Item_Struct *Item = database.GetItem((*Iterator)->Items.MainArea[MainSlot].ItemID);
const Item_Struct *Item = database.GetItem((*iter)->Items.MainArea[mainSlot].ItemID);
GuildBankItemUpdate_Struct gbius;
if(!Item->Stackable)
gbius.Init(GuildBankItemUpdate, 1, MainSlot, GuildBankMainArea, 1, Item->ID, Item->Icon, 1, 0, 0, 0);
gbius.Init(GuildBankItemUpdate, 1, mainSlot, GuildBankMainArea, 1, Item->ID, Item->Icon, 1, 0, 0, 0);
else
{
if((*Iterator)->Items.MainArea[MainSlot].Quantity == Item->StackSize)
gbius.Init(GuildBankItemUpdate, 1, MainSlot, GuildBankMainArea, 1, Item->ID, Item->Icon,
(*Iterator)->Items.MainArea[MainSlot].Quantity, 0, 0, 0);
if((*iter)->Items.MainArea[mainSlot].Quantity == Item->StackSize)
gbius.Init(GuildBankItemUpdate, 1, mainSlot, GuildBankMainArea, 1, Item->ID, Item->Icon,
(*iter)->Items.MainArea[mainSlot].Quantity, 0, 0, 0);
else
gbius.Init(GuildBankItemUpdate, 1, MainSlot, GuildBankMainArea, 1, Item->ID, Item->Icon,
(*Iterator)->Items.MainArea[MainSlot].Quantity, 0, 1, 0);
gbius.Init(GuildBankItemUpdate, 1, mainSlot, GuildBankMainArea, 1, Item->ID, Item->Icon,
(*iter)->Items.MainArea[mainSlot].Quantity, 0, 1, 0);
}
strn0cpy(gbius.ItemName, Item->Name, sizeof(gbius.ItemName));
entity_list.QueueClientsGuildBankItemUpdate(&gbius, GuildID);
entity_list.QueueClientsGuildBankItemUpdate(&gbius, guildID);
gbius.Init(GuildBankItemUpdate, 1, SlotID, GuildBankDepositArea, 0, 0, 0, 0, 0, 0, 0);
gbius.Init(GuildBankItemUpdate, 1, slotID, GuildBankDepositArea, 0, 0, 0, 0, 0, 0, 0);
entity_list.QueueClientsGuildBankItemUpdate(&gbius, GuildID);
entity_list.QueueClientsGuildBankItemUpdate(&gbius, guildID);
return MainSlot;
return mainSlot;
}
void GuildBankManager::SetPermissions(uint32 GuildID, uint16 SlotID, uint32 Permissions, const char *MemberName)
void GuildBankManager::SetPermissions(uint32 guildID, uint16 slotID, uint32 permissions, const char *memberName)
{
if((SlotID > (GUILD_BANK_MAIN_AREA_SIZE - 1)))
if((slotID > (GUILD_BANK_MAIN_AREA_SIZE - 1)))
return;
std::list<GuildBank*>::iterator Iterator = GetGuildBank(GuildID);
auto iter = GetGuildBank(guildID);
if(Iterator == Banks.end())
if(iter == Banks.end())
return;
if((*iter)->Items.MainArea[slotID].ItemID == 0)
return;
std::string query = StringFormat("UPDATE `guild_bank` SET `permissions` = %i, `whofor` = '%s' "
"WHERE `guildid` = %i AND `area` = 1 AND `slot` = %i LIMIT 1",
permissions, memberName, guildID, slotID);
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;
}
if((*Iterator)->Items.MainArea[SlotID].ItemID == 0)
{
return;
}
(*iter)->Items.MainArea[slotID].Permissions = permissions;
const char *Query="UPDATE `guild_bank` SET `permissions` = %i, `whofor` = '%s' WHERE `guildid` = %i AND `area` = 1 AND `slot` = %i LIMIT 1";
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
if(!database.RunQuery(query, MakeAnyLenString(&query, Query, Permissions, MemberName, GuildID, SlotID), errbuf))
{
_log(GUILDS__BANK_ERROR, "error changing permissions: %s : %s", query, errbuf);
safe_delete_array(query);
return;
}
safe_delete_array(query);
(*Iterator)->Items.MainArea[SlotID].Permissions = Permissions;
if(Permissions == GuildBankSingleMember)
strn0cpy((*Iterator)->Items.MainArea[SlotID].WhoFor, MemberName, sizeof((*Iterator)->Items.MainArea[SlotID].WhoFor));
if(permissions == GuildBankSingleMember)
strn0cpy((*iter)->Items.MainArea[slotID].WhoFor, memberName, sizeof((*iter)->Items.MainArea[slotID].WhoFor));
else
(*Iterator)->Items.MainArea[SlotID].WhoFor[0] = '\0';
(*iter)->Items.MainArea[slotID].WhoFor[0] = '\0';
const Item_Struct *Item = database.GetItem((*Iterator)->Items.MainArea[SlotID].ItemID);
const Item_Struct *Item = database.GetItem((*iter)->Items.MainArea[slotID].ItemID);
GuildBankItemUpdate_Struct gbius;
if(!Item->Stackable)
gbius.Init(GuildBankItemUpdate, 1, SlotID, GuildBankMainArea, 1, Item->ID, Item->Icon, 1, (*Iterator)->Items.MainArea[SlotID].Permissions, 0, 0);
gbius.Init(GuildBankItemUpdate, 1, slotID, GuildBankMainArea, 1, Item->ID, Item->Icon, 1, (*iter)->Items.MainArea[slotID].Permissions, 0, 0);
else
{
if((*Iterator)->Items.MainArea[SlotID].Quantity == Item->StackSize)
gbius.Init(GuildBankItemUpdate, 1, SlotID, GuildBankMainArea, 1, Item->ID, Item->Icon,
(*Iterator)->Items.MainArea[SlotID].Quantity, (*Iterator)->Items.MainArea[SlotID].Permissions, 0, 0);
if((*iter)->Items.MainArea[slotID].Quantity == Item->StackSize)
gbius.Init(GuildBankItemUpdate, 1, slotID, GuildBankMainArea, 1, Item->ID, Item->Icon,
(*iter)->Items.MainArea[slotID].Quantity, (*iter)->Items.MainArea[slotID].Permissions, 0, 0);
else
gbius.Init(GuildBankItemUpdate, 1, SlotID, GuildBankMainArea, 1, Item->ID, Item->Icon,
(*Iterator)->Items.MainArea[SlotID].Quantity, (*Iterator)->Items.MainArea[SlotID].Permissions, 1, 0);
gbius.Init(GuildBankItemUpdate, 1, slotID, GuildBankMainArea, 1, Item->ID, Item->Icon,
(*iter)->Items.MainArea[slotID].Quantity, (*iter)->Items.MainArea[slotID].Permissions, 1, 0);
}
strn0cpy(gbius.ItemName, Item->Name, sizeof(gbius.ItemName));
strn0cpy(gbius.WhoFor, (*Iterator)->Items.MainArea[SlotID].WhoFor, sizeof(gbius.WhoFor));
strn0cpy(gbius.WhoFor, (*iter)->Items.MainArea[slotID].WhoFor, sizeof(gbius.WhoFor));
entity_list.QueueClientsGuildBankItemUpdate(&gbius, GuildID);
entity_list.QueueClientsGuildBankItemUpdate(&gbius, guildID);
}
ItemInst* GuildBankManager::GetItem(uint32 GuildID, uint16 Area, uint16 SlotID, uint32 Quantity)
@@ -1208,90 +1091,73 @@ std::list<GuildBank*>::iterator GuildBankManager::GetGuildBank(uint32 GuildID)
return Iterator;
}
bool GuildBankManager::DeleteItem(uint32 GuildID, uint16 Area, uint16 SlotID, uint32 Quantity)
bool GuildBankManager::DeleteItem(uint32 guildID, uint16 area, uint16 slotID, uint32 quantity)
{
std::list<GuildBank*>::iterator Iterator = GetGuildBank(GuildID);
auto iter = GetGuildBank(guildID);
if(Iterator == Banks.end())
if(iter == Banks.end())
return false;
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
GuildBankItem* BankArea = nullptr;
if(Area == GuildBankMainArea)
if(area == GuildBankMainArea)
{
if(SlotID > (GUILD_BANK_MAIN_AREA_SIZE - 1))
if(slotID > (GUILD_BANK_MAIN_AREA_SIZE - 1))
return false;
BankArea = &(*Iterator)->Items.MainArea[0];
}
else
{
if(SlotID > (GUILD_BANK_DEPOSIT_AREA_SIZE - 1))
BankArea = &(*iter)->Items.MainArea[0];
} else {
if(slotID > (GUILD_BANK_DEPOSIT_AREA_SIZE - 1))
return false;
BankArea = &(*Iterator)->Items.DepositArea[0];
BankArea = &(*iter)->Items.DepositArea[0];
}
bool deleted = true;
bool Deleted = true;
const Item_Struct *Item = database.GetItem(BankArea[SlotID].ItemID);
if(!Item->Stackable || (Quantity >= BankArea[SlotID].Quantity))
{
const char *Query = "DELETE from `guild_bank` where `guildid` = %i AND `area` = %i AND `slot` = %i LIMIT 1";
if(!database.RunQuery(query, MakeAnyLenString(&query, Query, GuildID, Area, SlotID), errbuf))
{
_log(GUILDS__BANK_ERROR, "Delete item failed. %s : %s", query, errbuf);
safe_delete_array(query);
const Item_Struct *Item = database.GetItem(BankArea[slotID].ItemID);
if(!Item->Stackable || (quantity >= BankArea[slotID].Quantity)) {
std::string query = StringFormat("DELETE FROM `guild_bank` WHERE `guildid` = %i "
"AND `area` = %i AND `slot` = %i LIMIT 1",
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;
}
safe_delete_array(query);
BankArea[SlotID].ItemID = 0;
}
else
{
const char *Query = "UPDATE `guild_bank` SET `qty` = %i where `guildid` = %i AND `area` = %i AND `slot` = %i LIMIT 1";
if(!database.RunQuery(query, MakeAnyLenString(&query, Query, BankArea[SlotID].Quantity - Quantity,
GuildID, Area, SlotID), errbuf))
{
_log(GUILDS__BANK_ERROR, "Update item failed. %s : %s", query, errbuf);
safe_delete_array(query);
BankArea[slotID].ItemID = 0;
} else {
std::string query = StringFormat("UPDATE `guild_bank` SET `qty` = %i WHERE `guildid` = %i "
"AND `area` = %i AND `slot` = %i LIMIT 1",
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;
}
safe_delete_array(query);
BankArea[slotID].Quantity -= quantity;
BankArea[SlotID].Quantity -= Quantity;
Deleted = false;
deleted = false;
}
GuildBankItemUpdate_Struct gbius;
if(!Deleted)
if(!deleted)
{
gbius.Init(GuildBankItemUpdate, 1, SlotID, Area, 1, Item->ID, Item->Icon, BankArea[SlotID].Quantity, BankArea[SlotID].Permissions, 1, 0);
gbius.Init(GuildBankItemUpdate, 1, slotID, area, 1, Item->ID, Item->Icon, BankArea[slotID].Quantity, BankArea[slotID].Permissions, 1, 0);
strn0cpy(gbius.ItemName, Item->Name, sizeof(gbius.ItemName));
strn0cpy(gbius.WhoFor, BankArea[SlotID].WhoFor, sizeof(gbius.WhoFor));
strn0cpy(gbius.WhoFor, BankArea[slotID].WhoFor, sizeof(gbius.WhoFor));
}
else
gbius.Init(GuildBankItemUpdate, 1, SlotID, Area, 0, 0, 0, 0, 0, 0, 0);
gbius.Init(GuildBankItemUpdate, 1, slotID, area, 0, 0, 0, 0, 0, 0, 0);
entity_list.QueueClientsGuildBankItemUpdate(&gbius, GuildID);
entity_list.QueueClientsGuildBankItemUpdate(&gbius, guildID);
return true;
@@ -1422,26 +1288,20 @@ bool GuildBankManager::SplitStack(uint32 GuildID, uint16 SlotID, uint32 Quantity
return true;
}
void GuildBankManager::UpdateItemQuantity(uint32 GuildID, uint16 Area, uint16 SlotID, uint32 Quantity)
void GuildBankManager::UpdateItemQuantity(uint32 guildID, uint16 area, uint16 slotID, uint32 quantity)
{
// Helper method for MergeStacks. Assuming all passed parameters are valid.
//
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
const char *Query = "UPDATE `guild_bank` SET `qty` = %i where `guildid` = %i AND `area` = %i AND `slot` = %i LIMIT 1";
if(!database.RunQuery(query, MakeAnyLenString(&query, Query, Quantity, GuildID, Area, SlotID), errbuf))
{
_log(GUILDS__BANK_ERROR, "Update item quantity failed. %s : %s", query, errbuf);
safe_delete_array(query);
std::string query = StringFormat("UPDATE `guild_bank` SET `qty` = %i "
"WHERE `guildid` = %i AND `area` = %i "
"AND `slot` = %i LIMIT 1",
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;
}
safe_delete_array(query);
}
bool GuildBankManager::AllowedToWithdraw(uint32 GuildID, uint16 Area, uint16 SlotID, const char *Name)
+20 -10
View File
@@ -23,9 +23,9 @@
#include <list>
#include "masterentity.h"
#include "../common/rulesys.h"
#include "../common/MiscFunctions.h"
#include "../common/misc_functions.h"
#include "hate_list.h"
#include "QuestParserCollection.h"
#include "quest_parser_collection.h"
#include "zone.h"
#include "water_map.h"
@@ -40,7 +40,7 @@ HateList::~HateList()
{
}
// neotokyo: added for frenzy support
// added for frenzy support
// checks if target still is in frenzy mode
void HateList::CheckFrenzyHate()
{
@@ -163,14 +163,14 @@ Mob* HateList::GetClosest(Mob *hater) {
++iterator;
}
if (close == 0 && hater->IsNPC() || close->DivineAura())
if ((!close && hater->IsNPC()) || (close && close->DivineAura()))
close = hater->CastToNPC()->GetHateTop();
return close;
}
// neotokyo: a few comments added, rearranged code for readability
// a few comments added, rearranged code for readability
void HateList::Add(Mob *ent, int32 in_hate, int32 in_dam, bool bFrenzy, bool iAddIfNotExist)
{
if(!ent)
@@ -311,7 +311,7 @@ Mob *HateList::GetTop(Mob *center)
}
}
if (cur->ent->Sanctuary()) {
if (cur->ent->Sanctuary()) {
if(hate == -1)
{
top = cur->ent;
@@ -403,6 +403,13 @@ Mob *HateList::GetTop(Mob *center)
}
}
if (!isTopClientType) {
if (top->GetSpecialAbility(ALLOW_TO_TANK)){
isTopClientType = true;
topClientTypeInRange = top;
}
}
if(!isTopClientType)
return topClientTypeInRange ? topClientTypeInRange : nullptr;
@@ -557,12 +564,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)
{
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
@@ -578,7 +588,7 @@ void HateList::SpellCast(Mob *caster, uint32 spell_id, float range)
tHateEntry *h = (*iterator);
if(range > 0)
{
dist_targ = caster->DistNoRoot(*h->ent);
dist_targ = center->DistNoRoot(*h->ent);
if(dist_targ <= range && dist_targ >= min_range2)
{
id_list.push_back(h->ent->GetID());
+1 -1
View File
@@ -63,7 +63,7 @@ public:
int AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOptions *opts);
void SpellCast(Mob *caster, uint32 spell_id, float range);
void SpellCast(Mob *caster, uint32 spell_id, float range, Mob *ae_center = nullptr);
bool IsEmpty();
void PrintToClient(Client *c);
+43 -62
View File
@@ -18,9 +18,9 @@
#include "../common/debug.h"
#include "masterentity.h"
#include "../common/Item.h"
#include "../common/item.h"
#include "../common/linked_list.h"
#include "../common/StringUtil.h"
#include "../common/string_util.h"
#include <math.h>
#include <assert.h>
#include "worldserver.h"
@@ -67,70 +67,51 @@ const NPCType *Horse::GetHorseType(uint16 spell_id) {
const NPCType *Horse::BuildHorseType(uint16 spell_id) {
const char* FileName = spells[spell_id].teleport_zone;
const char* fileName = spells[spell_id].teleport_zone;
char mount_color = 0;
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if (database.RunQuery(query,MakeAnyLenString(&query, "SELECT race,gender,texture,mountspeed FROM horses WHERE filename='%s'", FileName), errbuf, &result)) {
safe_delete_array(query);
if (mysql_num_rows(result) == 1) {
row = mysql_fetch_row(result);
NPCType* npc_type = new NPCType;
memset(npc_type, 0, sizeof(NPCType));
strcpy(npc_type->name,"Unclaimed_Mount"); //this should never get used
strcpy(npc_type->special_abilities, "19,1^20,1^24,1");
npc_type->cur_hp = 1;
npc_type->max_hp = 1;
npc_type->race = atoi(row[0]);
npc_type->gender = atoi(row[1]); // Drogmor's are female horses. Yuck.
npc_type->class_ = 1;
npc_type->deity= 1;
npc_type->level = 1;
npc_type->npc_id = 0;
npc_type->loottable_id = 0;
npc_type->texture = atoi(row[2]);
npc_type->helmtexture = atoi(row[2]);
npc_type->runspeed = atof(row[3]);
mount_color = atoi(row[2]);
npc_type->light = 0;
npc_type->STR = 75;
npc_type->STA = 75;
npc_type->DEX = 75;
npc_type->AGI = 75;
npc_type->INT = 75;
npc_type->WIS = 75;
npc_type->CHA = 75;
horses_auto_delete.Insert(npc_type);
mysql_free_result(result);
return(npc_type);
}
else {
LogFile->write(EQEMuLog::Error, "No Database entry for mount: %s, check the horses table", FileName);
//Message(13, "Unable to find data for mount %s", FileName);
safe_delete_array(query);
}
mysql_free_result(result);
return nullptr;
}
else {
LogFile->write(EQEMuLog::Error, "Error in Mount query '%s': %s", query, errbuf);
safe_delete_array(query);
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);
return nullptr;
}
auto row = results.begin();
NPCType* npc_type = new NPCType;
memset(npc_type, 0, sizeof(NPCType));
strcpy(npc_type->name,"Unclaimed_Mount"); //this should never get used
strcpy(npc_type->special_abilities, "19,1^20,1^24,1");
npc_type->cur_hp = 1;
npc_type->max_hp = 1;
npc_type->race = atoi(row[0]);
npc_type->gender = atoi(row[1]); // Drogmor's are female horses. Yuck.
npc_type->class_ = 1;
npc_type->deity= 1;
npc_type->level = 1;
npc_type->npc_id = 0;
npc_type->loottable_id = 0;
npc_type->texture = atoi(row[2]); // mount color
npc_type->helmtexture = atoi(row[2]); // mount color
npc_type->runspeed = atof(row[3]);
npc_type->light = 0;
npc_type->STR = 75;
npc_type->STA = 75;
npc_type->DEX = 75;
npc_type->AGI = 75;
npc_type->INT = 75;
npc_type->WIS = 75;
npc_type->CHA = 75;
horses_auto_delete.Insert(npc_type);
return npc_type;
}
void Client::SummonHorse(uint16 spell_id) {
+362 -64
View File
@@ -15,24 +15,14 @@
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 "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/ZoneNumbers.h"
#include "../common/moremath.h"
#include "../common/guilds.h"
#include "../common/logsys.h"
#include "../common/StringUtil.h"
#include "StringIDs.h"
#include "NpcAI.h"
#include "QuestParserCollection.h"
#include "../common/string_util.h"
#include "quest_parser_collection.h"
#include "worldserver.h"
#include "zonedb.h"
extern WorldServer worldserver;
// @merth: this needs to be touched up
@@ -199,7 +189,9 @@ bool Client::CheckLoreConflict(const Item_Struct* item) {
return (m_inv.HasItemByLoreGroup(item->LoreGroup, ~invWhereSharedBank) != INVALID_INDEX);
}
bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, bool attuned, uint16 to_slot) {
bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, bool attuned, uint16 to_slot, uint32 ornament_icon, uint32 ornament_idfile) {
this->EVENT_ITEM_ScriptStopReturn();
// TODO: update calling methods and script apis to handle a failure return
const Item_Struct* item = database.GetItem(item_id);
@@ -555,6 +547,11 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
// attune item
if(attuned && inst->GetItem()->Attuneable)
inst->SetInstNoDrop(true);
if(ornament_icon > 0 && ornament_idfile > 0) {
inst->SetOrnamentIcon(ornament_icon);
inst->SetOrnamentationIDFile(ornament_idfile);
}
// check to see if item is usable in requested slot
if(enforceusable && (((to_slot >= MainCharm) && (to_slot <= MainAmmo)) || (to_slot == MainPowerSource))) {
@@ -813,25 +810,24 @@ bool Client::PushItemOnCursor(const ItemInst& inst, bool client_update)
return database.SaveCursor(CharacterID(), s, e);
}
bool Client::PutItemInInventory(int16 slot_id, const ItemInst& inst, bool client_update)
{
bool Client::PutItemInInventory(int16 slot_id, const ItemInst& inst, bool client_update) {
mlog(INVENTORY__SLOTS, "Putting item %s (%d) into slot %d", inst.GetItem()->Name, inst.GetItem()->ID, slot_id);
if (slot_id == MainCursor)
{
return PushItemOnCursor(inst,client_update);
}
return PushItemOnCursor(inst, client_update);
else
m_inv.PutItem(slot_id, inst);
if (client_update) {
SendItemPacket(slot_id, &inst, (slot_id == MainCursor) ? ItemPacketSummonItem : ItemPacketTrade);
}
if (client_update)
SendItemPacket(slot_id, &inst, ((slot_id == MainCursor) ? ItemPacketSummonItem : ItemPacketTrade));
if (slot_id == MainCursor) {
std::list<ItemInst*>::const_iterator s=m_inv.cursor_begin(),e=m_inv.cursor_end();
std::list<ItemInst*>::const_iterator s = m_inv.cursor_begin(), e = m_inv.cursor_end();
return database.SaveCursor(this->CharacterID(), s, e);
} else
}
else {
return database.SaveInventory(this->CharacterID(), &inst, slot_id);
}
CalcBonuses();
}
@@ -857,7 +853,7 @@ void Client::PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootI
{
if(bag_item_data[i] == nullptr)
continue;
const ItemInst *bagitem = database.CreateItem(bag_item_data[i]->item_id, bag_item_data[i]->charges, bag_item_data[i]->aug1, bag_item_data[i]->aug2, bag_item_data[i]->aug3, bag_item_data[i]->aug4, bag_item_data[i]->aug5);
const ItemInst *bagitem = database.CreateItem(bag_item_data[i]->item_id, bag_item_data[i]->charges, bag_item_data[i]->aug_1, bag_item_data[i]->aug_2, bag_item_data[i]->aug_3, bag_item_data[i]->aug_4, bag_item_data[i]->aug_5);
interior_slot = Inventory::CalcSlotId(slot_id, i);
mlog(INVENTORY__SLOTS, "Putting bag loot item %s (%d) into slot %d (bag slot %d)", inst.GetItem()->Name, inst.GetItem()->ID, interior_slot, i);
PutLootInInventory(interior_slot, *bagitem);
@@ -1479,6 +1475,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
}
world_inst->SetCharges(world_charges);
m_tradeskill_object->PutItem(world_idx, world_inst);
m_tradeskill_object->Save();
if (src_charges == 0) {
@@ -1530,7 +1527,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
// Also sends trade information to other client of trade session
if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit
trade->AddEntity(src_slot_id, dst_slot_id);
trade->AddEntity(dst_slot_id, move_in->number_in_stack);
return true;
} else {
@@ -1869,7 +1866,9 @@ void Client::DyeArmor(DyeStruct* dye){
uint8 slot2=SlotConvert(i);
ItemInst* inst = this->m_inv.GetItem(slot2);
if(inst){
inst->SetColor((dye->dye[i].rgb.red*65536)+(dye->dye[i].rgb.green*256)+(dye->dye[i].rgb.blue));
uint32 armor_color = (dye->dye[i].rgb.red * 65536) + (dye->dye[i].rgb.green * 256) + (dye->dye[i].rgb.blue);
inst->SetColor(armor_color);
database.SaveCharacterMaterialColor(this->CharacterID(), i, armor_color);
database.SaveInventory(CharacterID(),inst,slot2);
if(dye->dye[i].rgb.use_tint)
m_pp.item_tint[i].rgb.use_tint = 0xFF;
@@ -1890,7 +1889,7 @@ void Client::DyeArmor(DyeStruct* dye){
EQApplicationPacket* outapp=new EQApplicationPacket(OP_Dye,0);
QueuePacket(outapp);
safe_delete(outapp);
Save();
}
/*bool Client::DecreaseByItemType(uint32 type, uint8 amt) {
@@ -1994,11 +1993,10 @@ bool Client::DecreaseByID(uint32 type, uint8 amt) {
}
void Client::RemoveNoRent(bool client_update) {
int16 slot_id = 0;
int16 slot_id;
// personal
for(slot_id = MAIN_BEGIN; slot_id < EmuConstants::MAP_POSSESSIONS_SIZE; slot_id++) {
// equipment
for(slot_id = EmuConstants::EQUIPMENT_BEGIN; slot_id <= EmuConstants::EQUIPMENT_END; slot_id++) {
const ItemInst* inst = m_inv[slot_id];
if(inst && !inst->GetItem()->NoRent) {
mlog(INVENTORY__SLOTS, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id);
@@ -2006,11 +2004,22 @@ void Client::RemoveNoRent(bool client_update) {
}
}
// general
for (slot_id = EmuConstants::GENERAL_BEGIN; slot_id <= EmuConstants::GENERAL_END; slot_id++) {
const ItemInst* inst = m_inv[slot_id];
if (inst && !inst->GetItem()->NoRent) {
mlog(INVENTORY__SLOTS, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id);
DeleteItemInInventory(slot_id, 0, client_update);
}
}
// power source
const ItemInst* inst = m_inv[MainPowerSource];
if(inst && !inst->GetItem()->NoRent) {
mlog(INVENTORY__SLOTS, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, MainPowerSource);
DeleteItemInInventory(MainPowerSource, 0, (GetClientVersion() >= EQClientSoF) ? client_update : false); // Ti slot non-existent
if (m_inv[MainPowerSource]) {
const ItemInst* inst = m_inv[MainPowerSource];
if (inst && !inst->GetItem()->NoRent) {
mlog(INVENTORY__SLOTS, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, MainPowerSource);
DeleteItemInInventory(MainPowerSource, 0, (GetClientVersion() >= EQClientSoF) ? client_update : false); // Ti slot non-existent
}
}
// containers
@@ -2057,15 +2066,42 @@ void Client::RemoveNoRent(bool client_update) {
DeleteItemInInventory(slot_id, 0, false); // Can't delete from client Shared Bank Container slots
}
}
// cursor & limbo
if (!m_inv.CursorEmpty()) {
std::list<ItemInst*> local;
ItemInst* inst = nullptr;
while (!m_inv.CursorEmpty()) {
inst = m_inv.PopItem(MainCursor);
if (inst)
local.push_back(inst);
}
std::list<ItemInst*>::iterator iter = local.begin();
while (iter != local.end()) {
inst = *iter;
if (!inst->GetItem()->NoRent)
mlog(INVENTORY__SLOTS, "NoRent Timer Lapse: Deleting %s from `Limbo`", inst->GetItem()->Name);
else
m_inv.PushCursor(**iter);
safe_delete(*iter);
iter = local.erase(iter);
}
std::list<ItemInst*>::const_iterator s = m_inv.cursor_begin(), e = m_inv.cursor_end();
database.SaveCursor(this->CharacterID(), s, e);
local.clear();
}
}
// Two new methods to alleviate perpetual login desyncs
void Client::RemoveDuplicateLore(bool client_update) {
// Split-charge stacking may be added at some point -U
int16 slot_id;
int16 slot_id = 0;
// personal
for(slot_id = MAIN_BEGIN; slot_id < EmuConstants::MAP_POSSESSIONS_SIZE; slot_id++) {
// equipment
for(slot_id = EmuConstants::EQUIPMENT_BEGIN; slot_id <= EmuConstants::EQUIPMENT_END; slot_id++) {
ItemInst* inst = m_inv.PopItem(slot_id);
if(inst) {
if(CheckLoreConflict(inst->GetItem())) {
@@ -2079,17 +2115,34 @@ void Client::RemoveDuplicateLore(bool client_update) {
}
}
// general
for (slot_id = EmuConstants::GENERAL_BEGIN; slot_id <= EmuConstants::GENERAL_END; slot_id++) {
ItemInst* inst = m_inv.PopItem(slot_id);
if (inst) {
if (CheckLoreConflict(inst->GetItem())) {
mlog(INVENTORY__ERROR, "Lore Duplication Error: Deleting %s from slot %i", inst->GetItem()->Name, slot_id);
database.SaveInventory(character_id, nullptr, slot_id);
}
else {
m_inv.PutItem(slot_id, *inst);
}
safe_delete(inst);
}
}
// power source
ItemInst* inst = m_inv.PopItem(MainPowerSource);
if(inst) {
if(CheckLoreConflict(inst->GetItem())) {
mlog(INVENTORY__ERROR, "Lore Duplication Error: Deleting %s from slot %i", inst->GetItem()->Name, slot_id);
database.SaveInventory(character_id, nullptr, MainPowerSource);
if (m_inv[MainPowerSource]) {
ItemInst* inst = m_inv.PopItem(MainPowerSource);
if (inst) {
if (CheckLoreConflict(inst->GetItem())) {
mlog(INVENTORY__ERROR, "Lore Duplication Error: Deleting %s from slot %i", inst->GetItem()->Name, slot_id);
database.SaveInventory(character_id, nullptr, MainPowerSource);
}
else {
m_inv.PutItem(MainPowerSource, *inst);
}
safe_delete(inst);
}
else {
m_inv.PutItem(MainPowerSource, *inst);
}
safe_delete(inst);
}
// containers
@@ -2138,11 +2191,56 @@ void Client::RemoveDuplicateLore(bool client_update) {
}
// Shared Bank and Shared Bank Containers are not checked due to their allowing duplicate lore items -U
// cursor & limbo
if (!m_inv.CursorEmpty()) {
std::list<ItemInst*> local;
ItemInst* inst = nullptr;
while (!m_inv.CursorEmpty()) {
inst = m_inv.PopItem(MainCursor);
if (inst)
local.push_back(inst);
}
std::list<ItemInst*>::iterator iter = local.begin();
while (iter != local.end()) {
inst = *iter;
if (CheckLoreConflict(inst->GetItem())) {
mlog(INVENTORY__ERROR, "Lore Duplication Error: Deleting %s from `Limbo`", inst->GetItem()->Name);
safe_delete(*iter);
iter = local.erase(iter);
}
else {
++iter;
}
}
iter = local.begin();
while (iter != local.end()) {
inst = *iter;
if (!inst->GetItem()->LoreFlag ||
((inst->GetItem()->LoreGroup == -1) && (m_inv.HasItem(inst->GetID(), 0, invWhereCursor) == INVALID_INDEX)) ||
(inst->GetItem()->LoreGroup && ~inst->GetItem()->LoreGroup && (m_inv.HasItemByLoreGroup(inst->GetItem()->LoreGroup, invWhereCursor) == INVALID_INDEX))) {
m_inv.PushCursor(**iter);
}
else {
mlog(INVENTORY__ERROR, "Lore Duplication Error: Deleting %s from `Limbo`", inst->GetItem()->Name);
}
safe_delete(*iter);
iter = local.erase(iter);
}
std::list<ItemInst*>::const_iterator s = m_inv.cursor_begin(), e = m_inv.cursor_end();
database.SaveCursor(this->CharacterID(), s, e);
local.clear();
}
}
void Client::MoveSlotNotAllowed(bool client_update) {
int16 slot_id;
int16 slot_id = 0;
// equipment
for(slot_id = EmuConstants::EQUIPMENT_BEGIN; slot_id <= EmuConstants::EQUIPMENT_END; slot_id++) {
@@ -2310,10 +2408,8 @@ void Client::CreateBandolier(const EQApplicationPacket *app) {
_log(INVENTORY__BANDOLIER, "Char: %s Creating Bandolier Set %i, Set Name: %s", GetName(), bs->number, bs->name);
strcpy(m_pp.bandoliers[bs->number].name, bs->name);
const ItemInst* InvItem;
const Item_Struct *BaseItem;
const ItemInst* InvItem;
const Item_Struct *BaseItem;
int16 WeaponSlot;
for(int BandolierSlot = bandolierMainHand; BandolierSlot <= bandolierAmmo; BandolierSlot++) {
@@ -2324,6 +2420,7 @@ void Client::CreateBandolier(const EQApplicationPacket *app) {
_log(INVENTORY__BANDOLIER, "Char: %s adding item %s to slot %i", GetName(),BaseItem->Name, WeaponSlot);
m_pp.bandoliers[bs->number].items[BandolierSlot].item_id = BaseItem->ID;
m_pp.bandoliers[bs->number].items[BandolierSlot].icon = BaseItem->Icon;
database.SaveCharacterBandolier(this->CharacterID(), bs->number, BandolierSlot, m_pp.bandoliers[bs->number].items[BandolierSlot].item_id, m_pp.bandoliers[bs->number].items[BandolierSlot].icon, bs->name);
}
else {
_log(INVENTORY__BANDOLIER, "Char: %s no item in slot %i", GetName(), WeaponSlot);
@@ -2331,21 +2428,17 @@ void Client::CreateBandolier(const EQApplicationPacket *app) {
m_pp.bandoliers[bs->number].items[BandolierSlot].icon = 0;
}
}
Save();
}
void Client::RemoveBandolier(const EQApplicationPacket *app) {
// Delete bandolier with the specified number
BandolierDelete_Struct *bds = (BandolierDelete_Struct*)app->pBuffer;
_log(INVENTORY__BANDOLIER, "Char: %s removing set", GetName(), bds->number);
memset(m_pp.bandoliers[bds->number].name, 0, 32);
for(int i = bandolierMainHand; i <= bandolierAmmo; i++) {
m_pp.bandoliers[bds->number].items[i].item_id = 0;
m_pp.bandoliers[bds->number].items[i].icon = 0;
m_pp.bandoliers[bds->number].items[i].icon = 0;
}
Save();
database.DeleteCharacterBandolier(this->CharacterID(), bds->number);
}
void Client::SetBandolier(const EQApplicationPacket *app) {
@@ -2634,6 +2727,211 @@ bool Client::MoveItemToInventory(ItemInst *ItemToReturn, bool UpdateClient) {
return true;
}
bool Client::InterrogateInventory(Client* requester, bool log, bool silent, bool allowtrip, bool& error, bool autolog)
{
if (!requester)
return false;
std::map<int16, const ItemInst*> instmap;
// build reference map
for (int16 index = MAIN_BEGIN; index < EmuConstants::MAP_POSSESSIONS_SIZE; ++index)
if (m_inv[index])
instmap[index] = m_inv[index];
for (int16 index = EmuConstants::TRIBUTE_BEGIN; index <= EmuConstants::TRIBUTE_END; ++index)
if (m_inv[index])
instmap[index] = m_inv[index];
for (int16 index = EmuConstants::BANK_BEGIN; index <= EmuConstants::BANK_END; ++index)
if (m_inv[index])
instmap[index] = m_inv[index];
for (int16 index = EmuConstants::SHARED_BANK_BEGIN; index <= EmuConstants::SHARED_BANK_END; ++index)
if (m_inv[index])
instmap[index] = m_inv[index];
for (int16 index = EmuConstants::TRADE_BEGIN; index <= EmuConstants::TRADE_END; ++index)
if (m_inv[index])
instmap[index] = m_inv[index];
if (Object* tsobject = GetTradeskillObject())
for (int16 index = MAIN_BEGIN; index < EmuConstants::MAP_WORLD_SIZE; ++index)
if (tsobject->GetItem(index))
instmap[EmuConstants::WORLD_BEGIN + index] = tsobject->GetItem(index);
int limbo = 0;
for (iter_queue cursor_itr = m_inv.cursor_begin(); cursor_itr != m_inv.cursor_end(); ++cursor_itr, ++limbo) {
if (cursor_itr == m_inv.cursor_begin()) // m_inv.cursor_begin() is referenced as MainCursor in MapPossessions above
continue;
instmap[8000 + limbo] = *cursor_itr;
}
if (m_inv[MainPowerSource])
instmap[MainPowerSource] = m_inv[MainPowerSource];
// call InterrogateInventory_ for error check
for (std::map<int16, const ItemInst*>::iterator instmap_itr = instmap.begin(); (instmap_itr != instmap.end()) && (!error); ++instmap_itr)
InterrogateInventory_(true, requester, instmap_itr->first, INVALID_INDEX, instmap_itr->second, nullptr, log, silent, error, 0);
if (autolog && error && (!log))
log = true;
if (log)
_log(INVENTORY__ERROR, "Client::InterrogateInventory() called for %s by %s with an error state of %s", GetName(), requester->GetName(), (error ? "TRUE" : "FALSE"));
if (!silent)
requester->Message(1, "--- Inventory Interrogation Report for %s (requested by: %s, error state: %s) ---", GetName(), requester->GetName(), (error ? "TRUE" : "FALSE"));
// call InterrogateInventory_ for report
for (std::map<int16, const ItemInst*>::iterator instmap_itr = instmap.begin(); (instmap_itr != instmap.end()); ++instmap_itr)
InterrogateInventory_(false, requester, instmap_itr->first, INVALID_INDEX, instmap_itr->second, nullptr, log, silent, error, 0);
if (error) {
Message(13, "An error has been discovered in your inventory!");
Message(13, "Do not log out, zone or re-arrange items until this");
Message(13, "issue has been resolved or item loss may occur!");
if (allowtrip)
TripInterrogateInvState();
}
if (log) {
_log(INVENTORY__ERROR, "Target interrogate inventory flag: %s", (GetInterrogateInvState() ? "TRUE" : "FALSE"));
_log(INVENTORY__ERROR, "Client::InterrogateInventory() -- End");
}
if (!silent) {
requester->Message(1, "Target interrogation flag: %s", (GetInterrogateInvState() ? "TRUE" : "FALSE"));
requester->Message(1, "--- End of Interrogation Report ---");
}
instmap.clear();
return true;
}
void Client::InterrogateInventory_(bool errorcheck, Client* requester, int16 head, int16 index, const ItemInst* inst, const ItemInst* parent, bool log, bool silent, bool &error, int depth)
{
if (depth >= 10) {
_log(INVENTORY__ERROR, "Client::InterrogateInventory_() - Recursion count has exceeded the maximum allowable (You have a REALLY BIG PROBLEM!!)");
return;
}
if (errorcheck) {
if (InterrogateInventory_error(head, index, inst, parent, depth)) {
error = true;
}
else {
if (inst)
for (int16 sub = SUB_BEGIN; (sub < EmuConstants::ITEM_CONTAINER_SIZE) && (!error); ++sub) // treat any ItemInst as having the max internal slots available
if (inst->GetItem(sub))
InterrogateInventory_(true, requester, head, sub, inst->GetItem(sub), inst, log, silent, error, depth + 1);
}
}
else {
bool localerror = InterrogateInventory_error(head, index, inst, parent, depth);
std::string i;
std::string p;
std::string e;
if (inst) { i = StringFormat("%s (class: %u | augtype: %u)", inst->GetItem()->Name, inst->GetItem()->ItemClass, inst->GetItem()->AugType); }
else { i = "NONE"; }
if (parent) { p = StringFormat("%s (class: %u | augtype: %u), index: %i", parent->GetItem()->Name, parent->GetItem()->ItemClass, parent->GetItem()->AugType, index); }
else { p = "NONE"; }
if (localerror) { e = " [ERROR]"; }
else { e = ""; }
if (log)
_log(INVENTORY__ERROR, "Head: %i, Depth: %i, Instance: %s, Parent: %s%s",
head, depth, i.c_str(), p.c_str(), e.c_str());
if (!silent)
requester->Message(1, "%i:%i - inst: %s - parent: %s%s",
head, depth, i.c_str(), p.c_str(), e.c_str());
if (inst)
for (int16 sub = SUB_BEGIN; (sub < EmuConstants::ITEM_CONTAINER_SIZE); ++sub)
if (inst->GetItem(sub))
InterrogateInventory_(false, requester, head, sub, inst->GetItem(sub), inst, log, silent, error, depth + 1);
}
return;
}
bool Client::InterrogateInventory_error(int16 head, int16 index, const ItemInst* inst, const ItemInst* parent, int depth)
{
// very basic error checking - can be elaborated upon if more in-depth testing is needed...
if (
(head >= EmuConstants::EQUIPMENT_BEGIN && head <= EmuConstants::EQUIPMENT_END) ||
(head >= EmuConstants::TRIBUTE_BEGIN && head <= EmuConstants::TRIBUTE_END) ||
(head >= EmuConstants::WORLD_BEGIN && head <= EmuConstants::WORLD_END) ||
(head >= 8000 && head <= 8101) ||
(head == MainPowerSource)) {
switch (depth)
{
case 0: // requirement: inst is extant
if (!inst)
return true;
break;
case 1: // requirement: parent is common and inst is augment
if ((!parent) || (!inst))
return true;
if (!parent->IsType(ItemClassCommon))
return true;
if (index >= EmuConstants::ITEM_COMMON_SIZE)
return true;
break;
default: // requirement: none (something bad happened...)
return true;
}
}
else if (
(head >= EmuConstants::GENERAL_BEGIN && head <= EmuConstants::GENERAL_END) ||
(head == MainCursor) ||
(head >= EmuConstants::BANK_BEGIN && head <= EmuConstants::BANK_END) ||
(head >= EmuConstants::SHARED_BANK_BEGIN && head <= EmuConstants::SHARED_BANK_END) ||
(head >= EmuConstants::TRADE_BEGIN && head <= EmuConstants::TRADE_END)) {
switch (depth)
{
case 0: // requirement: inst is extant
if (!inst)
return true;
break;
case 1: // requirement: parent is common and inst is augment ..or.. parent is container and inst is extant
if ((!parent) || (!inst))
return true;
if (parent->IsType(ItemClassContainer))
break;
if (parent->IsType(ItemClassBook))
return true;
if (parent->IsType(ItemClassCommon)) {
if (!(inst->GetItem()->AugType > 0))
return true;
if (index >= EmuConstants::ITEM_COMMON_SIZE)
return true;
}
break;
case 2: // requirement: parent is common and inst is augment
if ((!parent) || (!inst))
return true;
if (parent->IsType(ItemClassContainer))
return true;
if (parent->IsType(ItemClassBook))
return true;
if (parent->IsType(ItemClassCommon)) {
if (!(inst->GetItem()->AugType > 0))
return true;
if (index >= EmuConstants::ITEM_COMMON_SIZE)
return true;
}
break;
default: // requirement: none (something bad happened again...)
return true;
}
}
else {
return true;
}
return false;
}
void Inventory::SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, std::string value) {
ItemInst *inst = GetItem(slot_id);
if(inst) {
+10 -9
View File
@@ -22,7 +22,8 @@
#include "npc.h"
#include "masterentity.h"
#include "zonedb.h"
#include "../common/MiscFunctions.h"
#include "../common/loottable.h"
#include "../common/misc_functions.h"
#ifdef _WINDOWS
#define snprintf _snprintf
#endif
@@ -195,13 +196,13 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge
item->item_id = item2->ID;
item->charges = charges;
item->aug1 = 0;
item->aug2 = 0;
item->aug3 = 0;
item->aug4 = 0;
item->aug5 = 0;
item->minlevel = minlevel;
item->maxlevel = maxlevel;
item->aug_1 = 0;
item->aug_2 = 0;
item->aug_3 = 0;
item->aug_4 = 0;
item->aug_5 = 0;
item->min_level = minlevel;
item->max_level = maxlevel;
if (equipit) {
uint8 eslot = 0xFF;
char newid[20];
@@ -339,7 +340,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)
+22 -10
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, new_x);
}
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, new_x, new_y);
}
void Lua_Client::SetBindPoint(int to_zone, int to_instance, float new_x, float new_y, float new_z) {
Lua_Safe_Call_Void();
self->SetBindPoint(to_zone, to_instance, new_x, new_y, new_z);
}
float Lua_Client::GetBindX() {
@@ -1134,7 +1139,7 @@ void Lua_Client::Signal(uint32 id) {
void Lua_Client::AddAlternateCurrencyValue(uint32 currency, int amount) {
Lua_Safe_Call_Void();
self->AddAlternateCurrencyValue(currency, amount);
self->AddAlternateCurrencyValue(currency, amount, 1);
}
void Lua_Client::SendWebLink(const char *site) {
@@ -1239,6 +1244,11 @@ void Lua_Client::SendMarqueeMessage(uint32 type, uint32 priority, uint32 fade_in
self->SendMarqueeMessage(type, priority, fade_in, fade_out, duration, msg);
}
void Lua_Client::SendColoredText(uint32 type, std::string msg) {
Lua_Safe_Call_Void();
self->SendColoredText(type, msg);
}
void Lua_Client::PlayMP3(std::string file)
{
Lua_Safe_Call_Void();
@@ -1292,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)
@@ -1492,6 +1503,7 @@ luabind::scope lua_register_client() {
.def("SetThirst", (void(Lua_Client::*)(int))&Lua_Client::SetThirst)
.def("SetConsumption", (void(Lua_Client::*)(int, int))&Lua_Client::SetConsumption)
.def("SendMarqueeMessage", (void(Lua_Client::*)(uint32, uint32, uint32, uint32, uint32, std::string))&Lua_Client::SendMarqueeMessage)
.def("SendColoredText", (void(Lua_Client::*)(uint32, std::string))&Lua_Client::SendColoredText)
.def("PlayMP3", (void(Lua_Client::*)(std::string))&Lua_Client::PlayMP3);
}
+5 -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();
@@ -275,6 +276,7 @@ public:
void SetThirst(int in_thirst);
void SetConsumption(int in_hunger, int in_thirst);
void SendMarqueeMessage(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string msg);
void SendColoredText(uint32 type, std::string msg);
void PlayMP3(std::string file);
};
+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) {
+7 -1
View File
@@ -416,6 +416,11 @@ void Lua_EntityList::SignalAllClients(int signal) {
self->SignalAllClients(signal);
}
void Lua_EntityList::ChannelMessage(Lua_Mob from, int channel_num, int language, const char *message) {
Lua_Safe_Call_Void();
self->ChannelMessage(from, channel_num, language, message);
}
luabind::scope lua_register_entity_list() {
return luabind::class_<Lua_EntityList>("EntityList")
.def(luabind::constructor<>())
@@ -479,7 +484,8 @@ luabind::scope lua_register_entity_list() {
.def("GetObjectList", (Lua_Object_List(Lua_EntityList::*)(void))&Lua_EntityList::GetObjectList)
.def("GetDoorsList", (Lua_Doors_List(Lua_EntityList::*)(void))&Lua_EntityList::GetDoorsList)
.def("GetSpawnList", (Lua_Spawn_List(Lua_EntityList::*)(void))&Lua_EntityList::GetSpawnList)
.def("SignalAllClients", (void(Lua_EntityList::*)(int))&Lua_EntityList::SignalAllClients);
.def("SignalAllClients", (void(Lua_EntityList::*)(int))&Lua_EntityList::SignalAllClients)
.def("ChannelMessage", (void(Lua_EntityList::*)(Lua_Mob,int,int,const char*))&Lua_EntityList::ChannelMessage);
}
luabind::scope lua_register_mob_list() {
+1
View File
@@ -106,6 +106,7 @@ public:
Lua_Doors_List GetDoorsList();
Lua_Spawn_List GetSpawnList();
void SignalAllClients(int signal);
void ChannelMessage(Lua_Mob from, int channel_num, int language, const char *message);
};
#endif
+294 -29
View File
@@ -13,9 +13,9 @@
#include "lua_client.h"
#include "lua_npc.h"
#include "lua_entity_list.h"
#include "QuestParserCollection.h"
#include "quest_parser_collection.h"
#include "questmgr.h"
#include "QGlobals.h"
#include "qglobals.h"
#include "../common/timer.h"
struct Events { };
@@ -32,18 +32,94 @@ 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;
@@ -55,18 +131,8 @@ void register_event(std::string package_name, std::string name, int evt, luabind
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 +144,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 +161,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,16 +173,31 @@ 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));
@@ -119,6 +207,11 @@ void register_item_event(std::string name, int evt, int item_id, luabind::adl::o
}
}
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));
@@ -126,6 +219,11 @@ void unregister_item_event(std::string name, int evt, int 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 +233,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,6 +245,11 @@ 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)));
@@ -1109,6 +1217,11 @@ 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,175 @@ double lua_clock() {
return static_cast<double>(t) / 1000.0;
}
#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_meele_texture1, uint16, 0);
LuaCreateNPCParse(d_meele_texture2, uint16, 0);
LuaCreateNPCParseString(ammo_idfile, 32, "");
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, 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 +1575,14 @@ 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)
];
}
@@ -1451,11 +1722,7 @@ luabind::scope lua_register_slot() {
luabind::value("General6", static_cast<int>(MainGeneral6)),
luabind::value("General7", static_cast<int>(MainGeneral7)),
luabind::value("General8", static_cast<int>(MainGeneral8)),
//luabind::value("General9", static_cast<int>(MainGeneral9)),
//luabind::value("General10", static_cast<int>(MainGeneral10)),
luabind::value("Cursor", static_cast<int>(MainCursor)),
//luabind::value("EquipmentBegin", static_cast<int>(EmuConstants::EQUIPMENT_BEGIN)),
//luabind::value("EquipmentEnd", static_cast<int>(EmuConstants::EQUIPMENT_END)),
luabind::value("PersonalBegin", static_cast<int>(EmuConstants::GENERAL_BEGIN)), // deprecated
luabind::value("GeneralBegin", static_cast<int>(EmuConstants::GENERAL_BEGIN)),
luabind::value("PersonalEnd", static_cast<int>(EmuConstants::GENERAL_END)), // deprecated
@@ -1483,7 +1750,6 @@ luabind::scope lua_register_material() {
luabind::value("Secondary", static_cast<int>(MaterialSecondary)),
luabind::value("Max", static_cast<int>(_MaterialCount)), // deprecated
luabind::value("Count", static_cast<int>(_MaterialCount)),
//luabind::value("TintCount", static_cast<int>(_MaterialCount - 2)),
luabind::value("Invalid", static_cast<int>(_MaterialInvalid))
];
}
@@ -1498,8 +1764,7 @@ luabind::scope lua_register_client_version() {
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("RoF2", static_cast<int>(EQClientRoF2))
luabind::value("RoF", static_cast<int>(EQClientRoF))
];
}
+25 -2
View File
@@ -407,8 +407,18 @@ void Lua_NPC::SetSpellFocusHeal(int focus) {
self->SetSpellFocusHeal(focus);
}
float Lua_NPC::GetSlowMitigation() {
int Lua_NPC::GetSpellFocusDMG() {
Lua_Safe_Call_Int();
return self->GetSpellFocusDMG();
}
int Lua_NPC::GetSpellFocusHeal() {
Lua_Safe_Call_Int();
return self->GetSpellFocusHeal();
}
float Lua_NPC::GetSlowMitigation() {
Lua_Safe_Call_Real();
return self->GetSlowMitigation();
}
@@ -442,6 +452,15 @@ void Lua_NPC::MerchantCloseShop() {
self->MerchantCloseShop();
}
void Lua_NPC::SetMerchantProbability(uint8 amt) {
Lua_Safe_Call_Void();
self->SetMerchantProbability(amt);
}
uint8 Lua_NPC::GetMerchantProbability() {
Lua_Safe_Call_Int();
return self->GetMerchantProbability();
}
luabind::scope lua_register_npc() {
return luabind::class_<Lua_NPC, Lua_Mob>("NPC")
@@ -526,13 +545,17 @@ luabind::scope lua_register_npc() {
.def("RemoveAISpell", (void(Lua_NPC::*)(int))&Lua_NPC::RemoveAISpell)
.def("SetSpellFocusDMG", (void(Lua_NPC::*)(int))&Lua_NPC::SetSpellFocusDMG)
.def("SetSpellFocusHeal", (void(Lua_NPC::*)(int))&Lua_NPC::SetSpellFocusHeal)
.def("GetSpellFocusDMG", (void(Lua_NPC::*)(int))&Lua_NPC::GetSpellFocusDMG)
.def("GetSpellFocusHeal", (void(Lua_NPC::*)(int))&Lua_NPC::GetSpellFocusHeal)
.def("GetSlowMitigation", (int(Lua_NPC::*)(void))&Lua_NPC::GetSlowMitigation)
.def("GetAttackSpeed", (float(Lua_NPC::*)(void))&Lua_NPC::GetAttackSpeed)
.def("GetAccuracyRating", (int(Lua_NPC::*)(void))&Lua_NPC::GetAccuracyRating)
.def("GetSpawnKillCount", (int(Lua_NPC::*)(void))&Lua_NPC::GetSpawnKillCount)
.def("GetScore", (int(Lua_NPC::*)(void))&Lua_NPC::GetScore)
.def("MerchantOpenShop", (void(Lua_NPC::*)(void))&Lua_NPC::MerchantOpenShop)
.def("MerchantCloseShop", (void(Lua_NPC::*)(void))&Lua_NPC::MerchantCloseShop);
.def("MerchantCloseShop", (void(Lua_NPC::*)(void))&Lua_NPC::MerchantCloseShop)
.def("SetMerchantProbability", (void(Lua_NPC::*)(void))&Lua_NPC::SetMerchantProbability)
.def("GetMerchantProbability", (uint8(Lua_NPC::*)(void))&Lua_NPC::GetMerchantProbability);
}
#endif
+4
View File
@@ -107,6 +107,8 @@ public:
void RemoveAISpell(int spell_id);
void SetSpellFocusDMG(int focus);
void SetSpellFocusHeal(int focus);
int GetSpellFocusDMG();
int GetSpellFocusHeal();
float GetSlowMitigation();
float GetAttackSpeed();
int GetAccuracyRating();
@@ -114,6 +116,8 @@ public:
int GetScore();
void MerchantOpenShop();
void MerchantCloseShop();
void SetMerchantProbability(uint8 amt);
uint8 GetMerchantProbability();
};
#endif
+44 -6
View File
@@ -14,14 +14,31 @@ Lua_Packet::Lua_Packet(int opcode, int size) {
owned_ = true;
}
Lua_Packet::Lua_Packet(int opcode, int size, bool raw) {
if(raw) {
SetLuaPtrData(new EQApplicationPacket(OP_Unknown, size));
owned_ = true;
EQApplicationPacket *self = reinterpret_cast<EQApplicationPacket*>(d_);
self->SetOpcodeBypass(opcode);
} else {
SetLuaPtrData(new EQApplicationPacket(static_cast<EmuOpcode>(opcode), size));
owned_ = true;
}
}
Lua_Packet& Lua_Packet::operator=(const Lua_Packet& o) {
if(o.owned_) {
owned_ = true;
EQApplicationPacket *app = reinterpret_cast<EQApplicationPacket*>(o.d_);
if(app)
if(app) {
d_ = new EQApplicationPacket(app->GetOpcode(), app->pBuffer, app->size);
else
EQApplicationPacket *self = reinterpret_cast<EQApplicationPacket*>(d_);
self->SetOpcodeBypass(app->GetOpcodeBypass());
} else {
d_ = nullptr;
}
} else {
owned_ = false;
d_ = o.d_;
@@ -33,10 +50,14 @@ Lua_Packet::Lua_Packet(const Lua_Packet& o) {
if(o.owned_) {
owned_ = true;
EQApplicationPacket *app = reinterpret_cast<EQApplicationPacket*>(o.d_);
if(app)
if(app) {
d_ = new EQApplicationPacket(app->GetOpcode(), app->pBuffer, app->size);
else
EQApplicationPacket *self = reinterpret_cast<EQApplicationPacket*>(d_);
self->SetOpcodeBypass(app->GetOpcodeBypass());
} else {
d_ = nullptr;
}
} else {
owned_ = false;
d_ = o.d_;
@@ -54,6 +75,16 @@ int Lua_Packet::GetOpcode() {
}
void Lua_Packet::SetOpcode(int op) {
Lua_Safe_Call_Void();
self->SetOpcodeBypass(static_cast<uint16>(op));
}
int Lua_Packet::GetRawOpcode() {
Lua_Safe_Call_Int();
return static_cast<int>(self->GetOpcodeBypass());
}
void Lua_Packet::SetRawOpcode(int op) {
Lua_Safe_Call_Void();
self->SetOpcode(static_cast<EmuOpcode>(op));
}
@@ -244,11 +275,14 @@ luabind::scope lua_register_packet() {
return luabind::class_<Lua_Packet>("Packet")
.def(luabind::constructor<>())
.def(luabind::constructor<int,int>())
.def(luabind::constructor<int,int,bool>())
.property("null", &Lua_Packet::Null)
.property("valid", &Lua_Packet::Valid)
.def("GetSize", &Lua_Packet::GetSize)
.def("GetOpcode", &Lua_Packet::GetOpcode)
.def("SetOpcode", &Lua_Packet::SetOpcode)
.def("GetRawOpcode", &Lua_Packet::GetRawOpcode)
.def("SetRawOpcode", &Lua_Packet::SetRawOpcode)
.def("WriteInt8", &Lua_Packet::WriteInt8)
.def("WriteInt16", &Lua_Packet::WriteInt16)
.def("WriteInt32", &Lua_Packet::WriteInt32)
@@ -267,6 +301,7 @@ luabind::scope lua_register_packet() {
.def("ReadFixedLengthString", &Lua_Packet::ReadFixedLengthString);
}
//TODO: Reorder these to match emu_oplist.h again
luabind::scope lua_register_packet_opcodes() {
return luabind::class_<Opcodes>("Opcode")
.enum_("constants")
@@ -412,7 +447,7 @@ luabind::scope lua_register_packet_opcodes() {
luabind::value("YellForHelp", static_cast<int>(OP_YellForHelp)),
luabind::value("SafePoint", static_cast<int>(OP_SafePoint)),
luabind::value("Buff", static_cast<int>(OP_Buff)),
luabind::value("BuffFadeMsg", static_cast<int>(OP_BuffFadeMsg)),
luabind::value("ColoredText", static_cast<int>(OP_ColoredText)),
luabind::value("SpecialMesg", static_cast<int>(OP_SpecialMesg)),
luabind::value("Consent", static_cast<int>(OP_Consent)),
luabind::value("ConsentResponse", static_cast<int>(OP_ConsentResponse)),
@@ -809,7 +844,10 @@ luabind::scope lua_register_packet_opcodes() {
luabind::value("MercenaryDismiss", static_cast<int>(OP_MercenaryDismiss)),
luabind::value("MercenaryTimerRequest", static_cast<int>(OP_MercenaryTimerRequest)),
luabind::value("OpenInventory", static_cast<int>(OP_OpenInventory)),
luabind::value("OpenContainer", static_cast<int>(OP_OpenContainer))
luabind::value("OpenContainer", static_cast<int>(OP_OpenContainer)),
luabind::value("Marquee", static_cast<int>(OP_Marquee)),
luabind::value("ClientTimeStamp", static_cast<int>(OP_ClientTimeStamp)),
luabind::value("GuildPromote", static_cast<int>(OP_GuildPromote))
];
}
+3
View File
@@ -21,6 +21,7 @@ public:
Lua_Packet() : Lua_Ptr(nullptr), owned_(false) { }
Lua_Packet(EQApplicationPacket *d) : Lua_Ptr(d), owned_(false) { }
Lua_Packet(int opcode, int size);
Lua_Packet(int opcode, int size, bool raw);
Lua_Packet& operator=(const Lua_Packet& o);
Lua_Packet(const Lua_Packet& o);
virtual ~Lua_Packet() { if(owned_) { EQApplicationPacket *ptr = GetLuaPtrData(); if(ptr) { delete ptr; } } }
@@ -28,6 +29,8 @@ public:
int GetSize();
int GetOpcode();
void SetOpcode(int op);
int GetRawOpcode();
void SetRawOpcode(int op);
void WriteInt8(int offset, int value);
void WriteInt16(int offset, int value);
void WriteInt32(int offset, int value);
+44 -19
View File
@@ -126,6 +126,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) {
@@ -220,7 +221,7 @@ LuaParser::~LuaParser() {
}
int LuaParser::EventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
evt = ConvertLuaEvent(evt);
if(evt >= _LargestEventID) {
return 0;
@@ -239,7 +240,7 @@ int LuaParser::EventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data,
}
int LuaParser::EventGlobalNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
evt = ConvertLuaEvent(evt);
if(evt >= _LargestEventID) {
return 0;
@@ -257,7 +258,7 @@ int LuaParser::EventGlobalNPC(QuestEventID evt, NPC* npc, Mob *init, std::string
}
int LuaParser::_EventNPC(std::string package_name, QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers, luabind::adl::object *l_func) {
std::vector<EQEmu::Any> *extra_pointers, luabind::adl::object *l_func) {
const char *sub_name = LuaEvents[evt];
int start = lua_gettop(L);
@@ -316,7 +317,7 @@ int LuaParser::_EventNPC(std::string package_name, QuestEventID evt, NPC* npc, M
}
int LuaParser::EventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
evt = ConvertLuaEvent(evt);
if(evt >= _LargestEventID) {
return 0;
@@ -334,7 +335,7 @@ int LuaParser::EventPlayer(QuestEventID evt, Client *client, std::string data, u
}
int LuaParser::EventGlobalPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
evt = ConvertLuaEvent(evt);
if(evt >= _LargestEventID) {
return 0;
@@ -352,7 +353,7 @@ int LuaParser::EventGlobalPlayer(QuestEventID evt, Client *client, std::string d
}
int LuaParser::_EventPlayer(std::string package_name, QuestEventID evt, Client *client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers, luabind::adl::object *l_func) {
std::vector<EQEmu::Any> *extra_pointers, luabind::adl::object *l_func) {
const char *sub_name = LuaEvents[evt];
int start = lua_gettop(L);
@@ -409,7 +410,7 @@ int LuaParser::_EventPlayer(std::string package_name, QuestEventID evt, Client *
}
int LuaParser::EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
evt = ConvertLuaEvent(evt);
if(evt >= _LargestEventID) {
return 0;
@@ -429,7 +430,7 @@ int LuaParser::EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *
}
int LuaParser::_EventItem(std::string package_name, QuestEventID evt, Client *client, ItemInst *item, Mob *mob,
std::string data, uint32 extra_data, std::vector<void*> *extra_pointers, luabind::adl::object *l_func) {
std::string data, uint32 extra_data, std::vector<EQEmu::Any> *extra_pointers, luabind::adl::object *l_func) {
const char *sub_name = LuaEvents[evt];
int start = lua_gettop(L);
@@ -492,7 +493,7 @@ int LuaParser::_EventItem(std::string package_name, QuestEventID evt, Client *cl
}
int LuaParser::EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
evt = ConvertLuaEvent(evt);
if(evt >= _LargestEventID) {
return 0;
@@ -508,7 +509,7 @@ int LuaParser::EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spe
}
int LuaParser::_EventSpell(std::string package_name, QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers, luabind::adl::object *l_func) {
std::vector<EQEmu::Any> *extra_pointers, luabind::adl::object *l_func) {
const char *sub_name = LuaEvents[evt];
int start = lua_gettop(L);
@@ -572,7 +573,7 @@ int LuaParser::_EventSpell(std::string package_name, QuestEventID evt, NPC* npc,
return 0;
}
int LuaParser::EventEncounter(QuestEventID evt, std::string encounter_name, uint32 extra_data, std::vector<void*> *extra_pointers) {
int LuaParser::EventEncounter(QuestEventID evt, std::string encounter_name, uint32 extra_data, std::vector<EQEmu::Any> *extra_pointers) {
evt = ConvertLuaEvent(evt);
if(evt >= _LargestEventID) {
return 0;
@@ -588,7 +589,7 @@ int LuaParser::EventEncounter(QuestEventID evt, std::string encounter_name, uint
}
int LuaParser::_EventEncounter(std::string package_name, QuestEventID evt, std::string encounter_name, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
const char *sub_name = LuaEvents[evt];
int start = lua_gettop(L);
@@ -601,7 +602,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);
@@ -770,6 +777,7 @@ void LuaParser::ReloadQuests() {
loaded_.clear();
errors_.clear();
lua_encounter_events_registered.clear();
lua_encounters_loaded.clear();
if(L) {
lua_close(L);
@@ -839,7 +847,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 +857,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 +868,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);
}
}
}
}
@@ -972,7 +997,7 @@ void LuaParser::MapFunctions(lua_State *L) {
}
int LuaParser::DispatchEventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
evt = ConvertLuaEvent(evt);
if(evt >= _LargestEventID) {
return 0;
@@ -1018,7 +1043,7 @@ int LuaParser::DispatchEventNPC(QuestEventID evt, NPC* npc, Mob *init, std::stri
}
int LuaParser::DispatchEventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
evt = ConvertLuaEvent(evt);
if(evt >= _LargestEventID) {
return 0;
@@ -1047,7 +1072,7 @@ int LuaParser::DispatchEventPlayer(QuestEventID evt, Client *client, std::string
}
int LuaParser::DispatchEventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
evt = ConvertLuaEvent(evt);
if(evt >= _LargestEventID) {
return 0;
@@ -1093,7 +1118,7 @@ int LuaParser::DispatchEventItem(QuestEventID evt, Client *client, ItemInst *ite
}
int LuaParser::DispatchEventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
evt = ConvertLuaEvent(evt);
if(evt >= _LargestEventID) {
return 0;
+18 -18
View File
@@ -2,8 +2,8 @@
#define _EQE_LUA_PARSER_H
#ifdef LUA_EQEMU
#include "QuestParserCollection.h"
#include "QuestInterface.h"
#include "quest_parser_collection.h"
#include "quest_interface.h"
#include <string>
#include <list>
#include <map>
@@ -28,19 +28,19 @@ public:
~LuaParser();
virtual int EventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
virtual int EventGlobalNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
virtual int EventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
virtual int EventGlobalPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
virtual int EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
virtual int EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
virtual int EventEncounter(QuestEventID evt, std::string encounter_name, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
virtual bool HasQuestSub(uint32 npc_id, QuestEventID evt);
virtual bool HasGlobalQuestSub(QuestEventID evt);
@@ -65,25 +65,25 @@ public:
virtual uint32 GetIdentifier() { return 0xb0712acc; }
virtual int DispatchEventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
virtual int DispatchEventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
virtual int DispatchEventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
virtual int DispatchEventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
private:
int _EventNPC(std::string package_name, QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers, luabind::adl::object *l_func = nullptr);
std::vector<EQEmu::Any> *extra_pointers, luabind::adl::object *l_func = nullptr);
int _EventPlayer(std::string package_name, QuestEventID evt, Client *client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers, luabind::adl::object *l_func = nullptr);
std::vector<EQEmu::Any> *extra_pointers, luabind::adl::object *l_func = nullptr);
int _EventItem(std::string package_name, QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data,
uint32 extra_data, std::vector<void*> *extra_pointers, luabind::adl::object *l_func = nullptr);
uint32 extra_data, std::vector<EQEmu::Any> *extra_pointers, luabind::adl::object *l_func = nullptr);
int _EventSpell(std::string package_name, QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers, luabind::adl::object *l_func = nullptr);
std::vector<EQEmu::Any> *extra_pointers, luabind::adl::object *l_func = nullptr);
int _EventEncounter(std::string package_name, QuestEventID evt, std::string encounter_name, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void LoadScript(std::string filename, std::string package_name);
bool HasFunction(std::string function, std::string package_name);
+86 -83
View File
@@ -5,12 +5,12 @@
#include <luabind/luabind.hpp>
#include <luabind/object.hpp>
#include "QuestParserCollection.h"
#include "QuestInterface.h"
#include "quest_parser_collection.h"
#include "quest_interface.h"
#include "masterentity.h"
#include "../common/seperator.h"
#include "../common/MiscFunctions.h"
#include "../common/misc_functions.h"
#include "lua_item.h"
#include "lua_iteminst.h"
#include "lua_entity.h"
@@ -27,7 +27,7 @@
//NPC
void handle_npc_event_say(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
npc->DoQuestPause(init);
Lua_Client l_client(reinterpret_cast<Client*>(init));
@@ -43,7 +43,7 @@ void handle_npc_event_say(QuestInterface *parse, lua_State* L, NPC* npc, Mob *in
}
void handle_npc_event_trade(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
Lua_Client l_client(reinterpret_cast<Client*>(init));
luabind::adl::object l_client_o = luabind::adl::object(L, l_client);
l_client_o.push(L);
@@ -54,9 +54,12 @@ void handle_npc_event_trade(QuestInterface *parse, lua_State* L, NPC* npc, Mob *
ident << npc->GetNPCTypeID();
if(extra_pointers) {
for(size_t i = 0; i < extra_pointers->size(); ++i) {
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));
Lua_ItemInst l_inst = reinterpret_cast<ItemInst*>(extra_pointers->at(i));
ItemInst *inst = EQEmu::any_cast<ItemInst*>(extra_pointers->at(i));
Lua_ItemInst l_inst = inst;
luabind::adl::object l_inst_o = luabind::adl::object(L, l_inst);
l_inst_o.push(L);
@@ -79,7 +82,7 @@ void handle_npc_event_trade(QuestInterface *parse, lua_State* L, NPC* npc, Mob *
}
void handle_npc_event_hp(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
if(extra_data == 1) {
lua_pushinteger(L, -1);
lua_setfield(L, -2, "hp_event");
@@ -96,7 +99,7 @@ void handle_npc_event_hp(QuestInterface *parse, lua_State* L, NPC* npc, Mob *ini
}
void handle_npc_single_mob(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
Lua_Mob l_mob(init);
luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob);
l_mob_o.push(L);
@@ -104,7 +107,7 @@ void handle_npc_single_mob(QuestInterface *parse, lua_State* L, NPC* npc, Mob *i
}
void handle_npc_single_client(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
Lua_Client l_client(reinterpret_cast<Client*>(init));
luabind::adl::object l_client_o = luabind::adl::object(L, l_client);
l_client_o.push(L);
@@ -112,7 +115,7 @@ void handle_npc_single_client(QuestInterface *parse, lua_State* L, NPC* npc, Mob
}
void handle_npc_single_npc(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
Lua_NPC l_npc(reinterpret_cast<NPC*>(init));
luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc);
l_npc_o.push(L);
@@ -120,7 +123,7 @@ void handle_npc_single_npc(QuestInterface *parse, lua_State* L, NPC* npc, Mob *i
}
void handle_npc_task_accepted(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
Lua_Client l_client(reinterpret_cast<Client*>(init));
luabind::adl::object l_client_o = luabind::adl::object(L, l_client);
l_client_o.push(L);
@@ -131,7 +134,7 @@ void handle_npc_task_accepted(QuestInterface *parse, lua_State* L, NPC* npc, Mob
}
void handle_npc_popup(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
Lua_Mob l_mob(init);
luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob);
l_mob_o.push(L);
@@ -142,7 +145,7 @@ void handle_npc_popup(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init,
}
void handle_npc_waypoint(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
Lua_Mob l_mob(init);
luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob);
l_mob_o.push(L);
@@ -153,7 +156,7 @@ void handle_npc_waypoint(QuestInterface *parse, lua_State* L, NPC* npc, Mob *ini
}
void handle_npc_hate(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
Lua_Mob l_mob(init);
luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob);
l_mob_o.push(L);
@@ -165,19 +168,19 @@ void handle_npc_hate(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, s
void handle_npc_signal(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
lua_pushinteger(L, std::stoi(data));
lua_setfield(L, -2, "signal");
}
void handle_npc_timer(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
lua_pushstring(L, data.c_str());
lua_setfield(L, -2, "timer");
}
void handle_npc_death(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
Lua_Mob l_mob(init);
luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob);
l_mob_o.push(L);
@@ -205,7 +208,7 @@ void handle_npc_death(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init,
}
void handle_npc_cast(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
int spell_id = std::stoi(data);
if(IsValidSpell(spell_id)) {
Lua_Spell l_spell(&spells[spell_id]);
@@ -221,21 +224,21 @@ void handle_npc_cast(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, s
}
void handle_npc_area(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
lua_pushinteger(L, *reinterpret_cast<int*>(extra_pointers->at(0)));
std::vector<EQEmu::Any> *extra_pointers) {
lua_pushinteger(L, *EQEmu::any_cast<int*>(extra_pointers->at(0)));
lua_setfield(L, -2, "area_id");
lua_pushinteger(L, *reinterpret_cast<int*>(extra_pointers->at(1)));
lua_pushinteger(L, *EQEmu::any_cast<int*>(extra_pointers->at(1)));
lua_setfield(L, -2, "area_type");
}
void handle_npc_null(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
}
//Player
void handle_player_say(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
lua_pushstring(L, data.c_str());
lua_setfield(L, -2, "message");
@@ -244,7 +247,7 @@ void handle_player_say(QuestInterface *parse, lua_State* L, Client* client, std:
}
void handle_player_death(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
Seperator sep(data.c_str());
Mob *o = entity_list.GetMobID(std::stoi(sep.arg[0]));
@@ -274,13 +277,13 @@ void handle_player_death(QuestInterface *parse, lua_State* L, Client* client, st
}
void handle_player_timer(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
lua_pushstring(L, data.c_str());
lua_setfield(L, -2, "timer");
}
void handle_player_discover_item(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
const Item_Struct *item = database.GetItem(extra_data);
if(item) {
Lua_Item l_item(item);
@@ -296,51 +299,51 @@ void handle_player_discover_item(QuestInterface *parse, lua_State* L, Client* cl
}
void handle_player_fish_forage_success(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
Lua_ItemInst l_item(reinterpret_cast<ItemInst*>(extra_pointers->at(0)));
std::vector<EQEmu::Any> *extra_pointers) {
Lua_ItemInst l_item(EQEmu::any_cast<ItemInst*>(extra_pointers->at(0)));
luabind::adl::object l_item_o = luabind::adl::object(L, l_item);
l_item_o.push(L);
lua_setfield(L, -2, "item");
}
void handle_player_click_object(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
Lua_Object l_object(reinterpret_cast<Object*>(extra_pointers->at(0)));
std::vector<EQEmu::Any> *extra_pointers) {
Lua_Object l_object(EQEmu::any_cast<Object*>(extra_pointers->at(0)));
luabind::adl::object l_object_o = luabind::adl::object(L, l_object);
l_object_o.push(L);
lua_setfield(L, -2, "object");
}
void handle_player_click_door(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
Lua_Door l_door(reinterpret_cast<Doors*>(extra_pointers->at(0)));
std::vector<EQEmu::Any> *extra_pointers) {
Lua_Door l_door(EQEmu::any_cast<Doors*>(extra_pointers->at(0)));
luabind::adl::object l_door_o = luabind::adl::object(L, l_door);
l_door_o.push(L);
lua_setfield(L, -2, "door");
}
void handle_player_signal(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
lua_pushinteger(L, std::stoi(data));
lua_setfield(L, -2, "signal");
}
void handle_player_popup_response(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
lua_pushinteger(L, std::stoi(data));
lua_setfield(L, -2, "popup_id");
}
void handle_player_pick_up(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
Lua_ItemInst l_item(reinterpret_cast<ItemInst*>(extra_pointers->at(0)));
std::vector<EQEmu::Any> *extra_pointers) {
Lua_ItemInst l_item(EQEmu::any_cast<ItemInst*>(extra_pointers->at(0)));
luabind::adl::object l_item_o = luabind::adl::object(L, l_item);
l_item_o.push(L);
lua_setfield(L, -2, "item");
}
void handle_player_cast(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
int spell_id = std::stoi(data);
if(IsValidSpell(spell_id)) {
Lua_Spell l_spell(&spells[spell_id]);
@@ -356,48 +359,48 @@ void handle_player_cast(QuestInterface *parse, lua_State* L, Client* client, std
}
void handle_player_task_fail(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
lua_pushinteger(L, std::stoi(data));
lua_setfield(L, -2, "task_id");
}
void handle_player_zone(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
lua_pushinteger(L, std::stoi(data));
lua_setfield(L, -2, "zone_id");
}
void handle_player_duel_win(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
Lua_Client l_client(reinterpret_cast<Client*>(extra_pointers->at(1)));
std::vector<EQEmu::Any> *extra_pointers) {
Lua_Client l_client(EQEmu::any_cast<Client*>(extra_pointers->at(1)));
luabind::adl::object l_client_o = luabind::adl::object(L, l_client);
l_client_o.push(L);
lua_setfield(L, -2, "other");
}
void handle_player_duel_loss(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
Lua_Client l_client(reinterpret_cast<Client*>(extra_pointers->at(0)));
std::vector<EQEmu::Any> *extra_pointers) {
Lua_Client l_client(EQEmu::any_cast<Client*>(extra_pointers->at(0)));
luabind::adl::object l_client_o = luabind::adl::object(L, l_client);
l_client_o.push(L);
lua_setfield(L, -2, "other");
}
void handle_player_loot(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
Lua_ItemInst l_item(reinterpret_cast<ItemInst*>(extra_pointers->at(0)));
std::vector<EQEmu::Any> *extra_pointers) {
Lua_ItemInst l_item(EQEmu::any_cast<ItemInst*>(extra_pointers->at(0)));
luabind::adl::object l_item_o = luabind::adl::object(L, l_item);
l_item_o.push(L);
lua_setfield(L, -2, "item");
Lua_Corpse l_corpse(reinterpret_cast<Corpse*>(extra_pointers->at(1)));
Lua_Corpse l_corpse(EQEmu::any_cast<Corpse*>(extra_pointers->at(1)));
luabind::adl::object l_corpse_o = luabind::adl::object(L, l_corpse);
l_corpse_o.push(L);
lua_setfield(L, -2, "corpse");
}
void handle_player_task_stage_complete(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
Seperator sep(data.c_str());
lua_pushinteger(L, std::stoi(sep.arg[0]));
lua_setfield(L, -2, "task_id");
@@ -407,7 +410,7 @@ void handle_player_task_stage_complete(QuestInterface *parse, lua_State* L, Clie
}
void handle_player_task_update(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
Seperator sep(data.c_str());
lua_pushinteger(L, std::stoi(sep.arg[0]));
lua_setfield(L, -2, "count");
@@ -420,7 +423,7 @@ void handle_player_task_update(QuestInterface *parse, lua_State* L, Client* clie
}
void handle_player_command(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
Seperator sep(data.c_str(), ' ', 10, 100, true);
std::string command(sep.arg[0] + 1);
lua_pushstring(L, command.c_str());
@@ -439,7 +442,7 @@ void handle_player_command(QuestInterface *parse, lua_State* L, Client* client,
}
void handle_player_combine(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
lua_pushinteger(L, extra_data);
lua_setfield(L, -2, "recipe_id");
@@ -448,24 +451,24 @@ void handle_player_combine(QuestInterface *parse, lua_State* L, Client* client,
}
void handle_player_feign(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
Lua_NPC l_npc(reinterpret_cast<NPC*>(extra_pointers->at(0)));
std::vector<EQEmu::Any> *extra_pointers) {
Lua_NPC l_npc(EQEmu::any_cast<NPC*>(extra_pointers->at(0)));
luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc);
l_npc_o.push(L);
lua_setfield(L, -2, "other");
}
void handle_player_area(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
lua_pushinteger(L, *reinterpret_cast<int*>(extra_pointers->at(0)));
std::vector<EQEmu::Any> *extra_pointers) {
lua_pushinteger(L, *EQEmu::any_cast<int*>(extra_pointers->at(0)));
lua_setfield(L, -2, "area_id");
lua_pushinteger(L, *reinterpret_cast<int*>(extra_pointers->at(1)));
lua_pushinteger(L, *EQEmu::any_cast<int*>(extra_pointers->at(1)));
lua_setfield(L, -2, "area_type");
}
void handle_player_respawn(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
lua_pushinteger(L, std::stoi(data));
lua_setfield(L, -2, "option");
@@ -474,8 +477,8 @@ void handle_player_respawn(QuestInterface *parse, lua_State* L, Client* client,
}
void handle_player_packet(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
Lua_Packet l_packet(reinterpret_cast<EQApplicationPacket*>(extra_pointers->at(0)));
std::vector<EQEmu::Any> *extra_pointers) {
Lua_Packet l_packet(EQEmu::any_cast<EQApplicationPacket*>(extra_pointers->at(0)));
luabind::adl::object l_packet_o = luabind::adl::object(L, l_packet);
l_packet_o.push(L);
lua_setfield(L, -2, "packet");
@@ -485,24 +488,24 @@ void handle_player_packet(QuestInterface *parse, lua_State* L, Client* client, s
}
void handle_player_null(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
}
//Item
void handle_item_click(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
lua_pushinteger(L, extra_data);
lua_setfield(L, -2, "slot_id");
}
void handle_item_timer(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
lua_pushstring(L, data.c_str());
lua_setfield(L, -2, "timer");
}
void handle_item_proc(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
Lua_Mob l_mob(mob);
luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob);
@@ -523,7 +526,7 @@ void handle_item_proc(QuestInterface *parse, lua_State* L, Client* client, ItemI
}
void handle_item_loot(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
if(mob && mob->IsCorpse()) {
Lua_Corpse l_corpse(mob->CastToCorpse());
luabind::adl::object l_corpse_o = luabind::adl::object(L, l_corpse);
@@ -538,14 +541,14 @@ void handle_item_loot(QuestInterface *parse, lua_State* L, Client* client, ItemI
}
void handle_item_equip(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
lua_pushinteger(L, extra_data);
lua_setfield(L, -2, "slot_id");
}
void handle_item_augment(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
Lua_ItemInst l_item(reinterpret_cast<ItemInst*>(extra_pointers->at(0)));
std::vector<EQEmu::Any> *extra_pointers) {
Lua_ItemInst l_item(EQEmu::any_cast<ItemInst*>(extra_pointers->at(0)));
luabind::adl::object l_item_o = luabind::adl::object(L, l_item);
l_item_o.push(L);
lua_setfield(L, -2, "aug");
@@ -555,8 +558,8 @@ void handle_item_augment(QuestInterface *parse, lua_State* L, Client* client, It
}
void handle_item_augment_insert(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
Lua_ItemInst l_item(reinterpret_cast<ItemInst*>(extra_pointers->at(0)));
std::vector<EQEmu::Any> *extra_pointers) {
Lua_ItemInst l_item(EQEmu::any_cast<ItemInst*>(extra_pointers->at(0)));
luabind::adl::object l_item_o = luabind::adl::object(L, l_item);
l_item_o.push(L);
lua_setfield(L, -2, "item");
@@ -566,8 +569,8 @@ void handle_item_augment_insert(QuestInterface *parse, lua_State* L, Client* cli
}
void handle_item_augment_remove(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
Lua_ItemInst l_item(reinterpret_cast<ItemInst*>(extra_pointers->at(0)));
std::vector<EQEmu::Any> *extra_pointers) {
Lua_ItemInst l_item(EQEmu::any_cast<ItemInst*>(extra_pointers->at(0)));
luabind::adl::object l_item_o = luabind::adl::object(L, l_item);
l_item_o.push(L);
lua_setfield(L, -2, "item");
@@ -575,17 +578,17 @@ void handle_item_augment_remove(QuestInterface *parse, lua_State* L, Client* cli
lua_pushinteger(L, extra_data);
lua_setfield(L, -2, "slot_id");
lua_pushboolean(L, *reinterpret_cast<bool*>(extra_pointers->at(1)));
lua_pushboolean(L, *EQEmu::any_cast<bool*>(extra_pointers->at(1)));
lua_setfield(L, -2, "destroyed");
}
void handle_item_null(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
}
//Spell
void handle_spell_effect(QuestInterface *parse, lua_State* L, NPC* npc, Client* client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
if(npc) {
Lua_Mob l_npc(npc);
luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc);
@@ -602,7 +605,7 @@ void handle_spell_effect(QuestInterface *parse, lua_State* L, NPC* npc, Client*
lua_setfield(L, -2, "target");
lua_pushinteger(L, *reinterpret_cast<int*>(extra_pointers->at(0)));
lua_pushinteger(L, *EQEmu::any_cast<int*>(extra_pointers->at(0)));
lua_setfield(L, -2, "buff_slot");
lua_pushinteger(L, extra_data);
@@ -610,7 +613,7 @@ void handle_spell_effect(QuestInterface *parse, lua_State* L, NPC* npc, Client*
}
void handle_spell_tic(QuestInterface *parse, lua_State* L, NPC* npc, Client* client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
if(npc) {
Lua_Mob l_npc(npc);
luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc);
@@ -627,13 +630,13 @@ void handle_spell_tic(QuestInterface *parse, lua_State* L, NPC* npc, Client* cli
lua_setfield(L, -2, "target");
lua_pushinteger(L, *reinterpret_cast<int*>(extra_pointers->at(0)));
lua_pushinteger(L, *EQEmu::any_cast<int*>(extra_pointers->at(0)));
lua_setfield(L, -2, "tics_remaining");
lua_pushinteger(L, *reinterpret_cast<uint8*>(extra_pointers->at(1)));
lua_pushinteger(L, *EQEmu::any_cast<uint8*>(extra_pointers->at(1)));
lua_setfield(L, -2, "caster_level");
lua_pushinteger(L, *reinterpret_cast<int*>(extra_pointers->at(2)));
lua_pushinteger(L, *EQEmu::any_cast<int*>(extra_pointers->at(2)));
lua_setfield(L, -2, "buff_slot");
lua_pushinteger(L, extra_data);
@@ -641,7 +644,7 @@ void handle_spell_tic(QuestInterface *parse, lua_State* L, NPC* npc, Client* cli
}
void handle_spell_fade(QuestInterface *parse, lua_State* L, NPC* npc, Client* client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
if(npc) {
Lua_Mob l_npc(npc);
luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc);
@@ -661,12 +664,12 @@ void handle_spell_fade(QuestInterface *parse, lua_State* L, NPC* npc, Client* cl
lua_pushinteger(L, extra_data);
lua_setfield(L, -2, "buff_slot");
lua_pushinteger(L, *reinterpret_cast<uint16*>(extra_pointers->at(0)));
lua_pushinteger(L, *EQEmu::any_cast<uint16*>(extra_pointers->at(0)));
lua_setfield(L, -2, "caster_id");
}
void handle_translocate_finish(QuestInterface *parse, lua_State* L, NPC* npc, Client* client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
if(npc) {
Lua_Mob l_npc(npc);
luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc);
@@ -685,7 +688,7 @@ void handle_translocate_finish(QuestInterface *parse, lua_State* L, NPC* npc, Cl
}
void handle_spell_null(QuestInterface *parse, lua_State* L, NPC* npc, Client* client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
}
#endif
+59 -59
View File
@@ -2,128 +2,128 @@
#define _EQE_LUA_PARSER_EVENTS_H
#ifdef LUA_EQEMU
typedef void(*NPCArgumentHandler)(QuestInterface*, lua_State*, NPC*, Mob*, std::string, uint32, std::vector<void*>*);
typedef void(*PlayerArgumentHandler)(QuestInterface*, lua_State*, Client*, std::string, uint32, std::vector<void*>*);
typedef void(*ItemArgumentHandler)(QuestInterface*, lua_State*, Client*, ItemInst*, Mob*, std::string, uint32, std::vector<void*>*);
typedef void(*SpellArgumentHandler)(QuestInterface*, lua_State*, NPC*, Client*, uint32, uint32, std::vector<void*>*);
typedef void(*NPCArgumentHandler)(QuestInterface*, lua_State*, NPC*, Mob*, std::string, uint32, std::vector<EQEmu::Any>*);
typedef void(*PlayerArgumentHandler)(QuestInterface*, lua_State*, Client*, std::string, uint32, std::vector<EQEmu::Any>*);
typedef void(*ItemArgumentHandler)(QuestInterface*, lua_State*, Client*, ItemInst*, Mob*, std::string, uint32, std::vector<EQEmu::Any>*);
typedef void(*SpellArgumentHandler)(QuestInterface*, lua_State*, NPC*, Client*, uint32, uint32, std::vector<EQEmu::Any>*);
//NPC
void handle_npc_event_say(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_npc_event_trade(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_npc_event_hp(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_npc_single_mob(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_npc_single_client(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_npc_single_npc(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_npc_task_accepted(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_npc_popup(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_npc_waypoint(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_npc_hate(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_npc_signal(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_npc_timer(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_npc_death(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_npc_cast(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_npc_area(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_npc_null(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
//Player
void handle_player_say(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
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<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_player_timer(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_player_discover_item(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_player_fish_forage_success(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_player_click_object(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_player_click_door(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_player_signal(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_player_popup_response(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_player_pick_up(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_player_cast(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_player_task_fail(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_player_zone(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_player_duel_win(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_player_duel_loss(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_player_loot(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_player_task_stage_complete(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_player_task_update(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_player_command(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_player_combine(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_player_feign(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_player_area(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_player_respawn(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_player_packet(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_player_null(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
//Item
void handle_item_click(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_item_timer(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_item_proc(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_item_loot(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_item_equip(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_item_augment(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_item_augment_insert(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_item_augment_remove(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_item_null(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
//Spell
void handle_spell_effect(QuestInterface *parse, lua_State* L, NPC* npc, Client* client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_spell_tic(QuestInterface *parse, lua_State* L, NPC* npc, Client* client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_spell_fade(QuestInterface *parse, lua_State* L, NPC* npc, Client* client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_translocate_finish(QuestInterface *parse, lua_State* L, NPC* npc, Client* client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
void handle_spell_null(QuestInterface *parse, lua_State* L, NPC* npc, Client* client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
#endif
#endif
+60
View File
@@ -419,6 +419,56 @@ bool Lua_Spell::GetAllowRest() {
return self->AllowRest;
}
bool Lua_Spell::GetInCombat() {
Lua_Safe_Call_Bool();
return self->InCombat;
}
bool Lua_Spell::GetOutOfCombat() {
Lua_Safe_Call_Bool();
return self->OutofCombat;
}
int Lua_Spell::GetAEMaxTargets() {
Lua_Safe_Call_Int();
return self->aemaxtargets;
}
int Lua_Spell::GetMaxTargets() {
Lua_Safe_Call_Int();
return self->maxtargets;
}
bool Lua_Spell::GetPersistDeath() {
Lua_Safe_Call_Bool();
return self->persistdeath;
}
float Lua_Spell::GetMinDist() {
Lua_Safe_Call_Real();
return self->min_dist;
}
float Lua_Spell::GetMinDistMod() {
Lua_Safe_Call_Real();
return self->min_dist_mod;
}
float Lua_Spell::GetMaxDist() {
Lua_Safe_Call_Real();
return self->max_dist;
}
float Lua_Spell::GetMaxDistMod() {
Lua_Safe_Call_Real();
return self->max_dist_mod;
}
float Lua_Spell::GetMinRange() {
Lua_Safe_Call_Real();
return self->min_range;
}
int Lua_Spell::GetDamageShieldType() {
Lua_Safe_Call_Int();
return self->DamageShieldType;
@@ -501,6 +551,16 @@ luabind::scope lua_register_spell() {
.def("PowerfulFlag", &Lua_Spell::GetPowerfulFlag)
.def("CastRestriction", &Lua_Spell::GetCastRestriction)
.def("AllowRest", &Lua_Spell::GetAllowRest)
.def("InCombat", &Lua_Spell::GetInCombat)
.def("OutOfCombat", &Lua_Spell::GetOutOfCombat)
.def("AEMaxTargets", &Lua_Spell::GetAEMaxTargets)
.def("MaxTargets", &Lua_Spell::GetMaxTargets)
.def("PersistDeath", &Lua_Spell::GetPersistDeath)
.def("MinDist", &Lua_Spell::GetMinDist)
.def("MinDistMod", &Lua_Spell::GetMinDistMod)
.def("MaxDist", &Lua_Spell::GetMaxDist)
.def("MaxDistMod", &Lua_Spell::GetMaxDistMod)
.def("MinRange", &Lua_Spell::GetMinRange)
.def("DamageShieldType", &Lua_Spell::GetDamageShieldType);
}
+10
View File
@@ -96,6 +96,16 @@ public:
int GetPowerfulFlag();
int GetCastRestriction();
bool GetAllowRest();
bool GetInCombat();
bool GetOutOfCombat();
int GetAEMaxTargets();
int GetMaxTargets();
bool GetPersistDeath();
float GetMinDist();
float GetMinDistMod();
float GetMaxDist();
float GetMaxDistMod();
float GetMinRange();
int GetDamageShieldType();
};
+2 -2
View File
@@ -1,7 +1,7 @@
#include "../common/debug.h"
#include "../common/MiscFunctions.h"
#include "../common/misc_functions.h"
#include "map.h"
#include "RaycastMesh.h"
#include "raycast_mesh.h"
#include "zone.h"
#include <stdint.h>
#include <algorithm>
+1969 -1688
View File
File diff suppressed because it is too large Load Diff
+166 -161
View File
@@ -4,12 +4,18 @@
#include "zonedb.h"
#include "npc.h"
#define MAXMERCS 1
#define MERC_DEBUG 0
#define TANK 1
#define HEALER 2
#define MELEEDPS 9
#define CASTERDPS 12
#define MAXMERCS 1
#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 +31,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 +54,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; }
@@ -126,21 +132,21 @@ public:
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 UpdateMercAppearance();
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 +170,75 @@ 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 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 +273,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_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
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 +340,23 @@ 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 _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 +373,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
+679 -522
View File
File diff suppressed because it is too large Load Diff
+115 -77
View File
@@ -18,21 +18,28 @@
#ifndef MOB_H
#define MOB_H
#include "../common/features.h"
#include "common.h"
#include "entity.h"
#include "hate_list.h"
#include "pathing.h"
#include <set>
#include <vector>
#include <string>
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,
@@ -205,7 +212,7 @@ public:
void SendSpellBarEnable(uint16 spellid);
void ZeroCastingVars();
virtual void SpellProcess();
virtual bool CastSpell(uint16 spell_id, uint16 target_id, uint16 slot = 10, int32 casttime = -1,
virtual bool CastSpell(uint16 spell_id, uint16 target_id, uint16 slot = USE_ITEM_SPELL_SLOT, int32 casttime = -1,
int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF,
uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, uint32 type = 0, int16 *resist_adjust = nullptr);
virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot = 10, int32 casttime = -1,
@@ -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(uint8 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,11 @@ public:
inline virtual uint32 GetNimbusEffect2() const { return nimbus_effect2; }
inline virtual uint32 GetNimbusEffect3() const { return nimbus_effect3; }
void RemoveNimbusEffect(int effectid);
inline float GetTargetRingX() const { return targetring_x; }
inline float GetTargetRingY() const { return targetring_y; }
inline float GetTargetRingZ() const { return targetring_z; }
inline 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; }
@@ -340,39 +353,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; }
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();
@@ -464,6 +477,8 @@ public:
bool CheckLosFN(float posX, float posY, float posZ, float mobSize);
inline void SetChanged() { pLastChange = Timer::GetCurrentTime(); }
inline const uint32 LastChange() const { return pLastChange; }
inline void SetLastLosState(bool value) { last_los_check = value; }
inline bool CheckLastLosState() const { return last_los_check; }
//Quest
void QuestReward(Client *c = nullptr, uint32 silver = 0, uint32 gold = 0, uint32 platinum = 0);
@@ -482,6 +497,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);
@@ -524,7 +540,7 @@ public:
//More stuff to sort:
virtual bool IsRaidTarget() { return false; };
virtual bool IsRaidTarget() const { return false; };
virtual bool IsAttackAllowed(Mob *target, bool isSpellAttack = false);
bool IsTargeted() const { return (targeted > 0); }
inline void IsTargeted(int in_tar) { targeted += in_tar; if(targeted < 0) targeted = 0;}
@@ -561,13 +577,14 @@ public:
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 = 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();
@@ -577,8 +594,7 @@ public:
void DoBuffWearOffEffect(uint32 index);
void TryTriggerOnCast(uint32 spell_id, bool aa_trigger);
void TriggerOnCast(uint32 focus_spell, uint32 spell_id, bool aa_trigger);
void TrySpellTrigger(Mob *target, uint32 spell_id);
void TryApplyEffect(Mob *target, uint32 spell_id);
bool TrySpellTrigger(Mob *target, uint32 spell_id, int effect);
void TryTriggerOnValueAmount(bool IsHP = false, bool IsMana = false, bool IsEndur = false, bool IsPet = false);
void TryTwincast(Mob *caster, Mob *target, uint32 spell_id);
void TrySympatheticProc(Mob *target, uint32 spell_id);
@@ -619,6 +635,7 @@ public:
void CalcSpellPowerDistanceMod(uint16 spell_id, float range, Mob* caster = nullptr);
inline int16 GetSpellPowerDistanceMod() const { return SpellPowerDistanceMod; };
inline void SetSpellPowerDistanceMod(int16 value) { SpellPowerDistanceMod = value; };
int32 GetSpellStat(uint32 spell_id, const char *identifier, uint8 slot = 0);
void ModSkillDmgTaken(SkillUseTypes skill_num, int value);
int16 GetModSkillDmgTaken(const SkillUseTypes skill_num);
@@ -664,9 +681,15 @@ public:
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; }
@@ -695,7 +718,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; }
@@ -707,9 +730,13 @@ 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; }
bool CanDoSpecialAttack(Mob *other);
bool Flurry(ExtraAttackOptions *opts);
bool Rampage(ExtraAttackOptions *opts);
@@ -725,6 +752,7 @@ public:
virtual void AI_Init();
virtual void AI_Start(uint32 iMoveDelay = 0);
virtual void AI_Stop();
virtual void AI_ShutDown();
virtual void AI_Process();
const char* GetEntityVariable(const char *id);
@@ -752,7 +780,8 @@ public:
inline const bool IsRooted() const { return rooted || permarooted; }
inline const bool HasVirus() const { return has_virus; }
int GetSnaredAmount();
inline const bool IsPseudoRooted() const { return pseudo_rooted; }
inline void SetPseudoRoot(bool prState) { pseudo_rooted = prState; }
int GetCurWp() { return cur_wp; }
@@ -764,6 +793,7 @@ public:
inline void StartFleeing() { flee_mode = true; CalculateNewFearpoint(); }
void ProcessFlee();
void CheckFlee();
inline bool IsBlind() { return spellbonuses.IsBlind; }
inline bool CheckAggro(Mob* other) {return hate_list.IsOnHateList(other);}
float CalculateHeadingToTarget(float in_x, float in_y);
@@ -796,8 +826,8 @@ public:
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);
@@ -813,7 +843,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);
@@ -822,7 +852,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 );
@@ -838,7 +868,7 @@ public:
void StopSpecialAbilityTimer(int ability);
Timer *GetSpecialAbilityTimer(int ability);
void ClearSpecialAbilities();
void ProcessSpecialAbilities(const std::string str);
void ProcessSpecialAbilities(const std::string &str);
Shielders_Struct shielder[MAX_SHIELDERS];
Trade* trade;
@@ -922,26 +952,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;
@@ -1048,7 +1078,8 @@ protected:
Timer attack_dw_timer;
Timer ranged_timer;
float attack_speed; //% increase/decrease in attack speed (not haste)
float slow_mitigation; // Allows for a slow mitigation (100 = 100%, 50% = 50%)
int8 attack_delay; //delay between attacks in 10ths of seconds
int16 slow_mitigation; // Allows for a slow mitigation (100 = 100%, 50% = 50%)
Timer tic_timer;
Timer mana_timer;
@@ -1071,11 +1102,8 @@ 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];
float rewind_x;
float rewind_y;
@@ -1119,6 +1147,9 @@ protected:
bool has_MGB;
bool has_ProjectIllusion;
int16 SpellPowerDistanceMod;
bool last_los_check;
bool pseudo_rooted;
bool endur_upkeep;
// Bind wound
Timer bindwound_timer;
@@ -1211,6 +1242,9 @@ protected:
//temppet
bool hasTempPet;
bool _IsTempPet;
int16 count_TempPet;
bool pet_owner_client; //Flags regular and pets as belonging to a client
EGNode *_egnode; //the EG node we are in
float tarx;
@@ -1223,6 +1257,10 @@ protected:
float tar_vz;
float test_vector;
float targetring_x;
float targetring_y;
float targetring_z;
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;
+231 -228
View File
@@ -23,15 +23,15 @@
#include <algorithm>
#include "npc.h"
#include "masterentity.h"
#include "NpcAI.h"
#include "npc_ai.h"
#include "map.h"
#include "../common/moremath.h"
#include "StringIDs.h"
#include "../common/MiscFunctions.h"
#include "../common/StringUtil.h"
#include "string_ids.h"
#include "../common/misc_functions.h"
#include "../common/string_util.h"
#include "../common/rulesys.h"
#include "../common/features.h"
#include "QuestParserCollection.h"
#include "quest_parser_collection.h"
#include "water_map.h"
#include "remote_call.h"
#include "remote_call_subscribe.h"
@@ -543,13 +543,16 @@ void NPC::AI_Start(uint32 iMoveDelay) {
void Mob::AI_Stop() {
if (!IsAIControlled())
return;
pAIControlled = false;
safe_delete(AIthink_timer);
safe_delete(AIwalking_timer);
safe_delete(AImovement_timer);
safe_delete(AItarget_check_timer)
safe_delete(AItarget_check_timer);
safe_delete(AIscanarea_timer);
safe_delete(AIfeignremember_timer);
hate_list.Wipe();
}
@@ -584,6 +587,33 @@ void Client::AI_Stop() {
}
}
// only call this on a zone shutdown event
void Mob::AI_ShutDown() {
safe_delete(PathingLOSCheckTimer);
safe_delete(PathingRouteUpdateTimerShort);
safe_delete(PathingRouteUpdateTimerLong);
attack_timer.Disable();
attack_dw_timer.Disable();
ranged_timer.Disable();
tic_timer.Disable();
mana_timer.Disable();
spellend_timer.Disable();
rewind_timer.Disable();
bindwound_timer.Disable();
stunned_timer.Disable();
spun_timer.Disable();
bardsong_timer.Disable();
gravity_timer.Disable();
viral_timer.Disable();
flee_timer.Disable();
for (int sat = 0; sat < MAX_SPECIAL_ATTACK; ++sat) {
if (SpecialAbilities[sat].timer)
SpecialAbilities[sat].timer->Disable();
}
}
//todo: expand the logic here to cover:
//redundant debuffs
//buffing owner
@@ -1011,7 +1041,7 @@ void Mob::AI_Process() {
//
if(RuleB(Combat, EnableFearPathing)){
if(curfp) {
if(IsRooted()) {
if(IsRooted() || (IsBlind() && CombatRange(hate_list.GetClosest(this)))) {
//make sure everybody knows were not moving, for appearance sake
if(IsMoving())
{
@@ -1058,7 +1088,9 @@ void Mob::AI_Process() {
if (engaged)
{
if (IsRooted())
// 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));
else
{
@@ -1183,7 +1215,7 @@ void Mob::AI_Process() {
if (GetSpecialAbility(SPECATK_FLURRY)) {
int flurry_chance = GetSpecialAbilityParam(SPECATK_FLURRY, 0);
flurry_chance = flurry_chance > 0 ? flurry_chance : RuleI(Combat, NPCFlurryChance);
flurry_chance = flurry_chance > 0 ? flurry_chance : RuleI(Combat, NPCFlurryChance);
if (MakeRandomInt(0, 99) < flurry_chance) {
ExtraAttackOptions opts;
@@ -1217,16 +1249,16 @@ void Mob::AI_Process() {
if (IsPet() || (IsNPC() && CastToNPC()->GetSwarmOwner())) {
Mob *owner = nullptr;
if (IsPet())
owner = GetOwner();
else
else
owner = entity_list.GetMobID(CastToNPC()->GetSwarmOwner());
if (owner) {
int16 flurry_chance = owner->aabonuses.PetFlurry +
owner->spellbonuses.PetFlurry + owner->itembonuses.PetFlurry;
if (flurry_chance && (MakeRandomInt(0, 99) < flurry_chance))
Flurry(nullptr);
}
@@ -1407,7 +1439,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;
@@ -1571,11 +1603,7 @@ void Mob::AI_Process() {
//Do Ranged attack here
if(doranged)
{
int attacks = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 0);
attacks = attacks > 0 ? attacks : 1;
for(int i = 0; i < attacks; ++i) {
RangedAttack(target);
}
RangedAttack(target);
}
}
@@ -1606,7 +1634,7 @@ void NPC::AI_DoMovement() {
roambox_movingto_x -= movex * 2;
if (roambox_movingto_y > roambox_max_y || roambox_movingto_y < roambox_min_y)
roambox_movingto_y -= movey * 2;
//New coord is still invalid, ignore distance and just pick a new random coord.
//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);
@@ -1863,7 +1891,7 @@ void Mob::AI_Event_NoLongerEngaged() {
pLastFightingDelayMoving += minLastFightingDelayMoving;
else
pLastFightingDelayMoving += MakeRandomInt(minLastFightingDelayMoving, maxLastFightingDelayMoving);
// EverHood - So mobs don't keep running as a ghost until AIwalking_timer fires
// So mobs don't keep running as a ghost until AIwalking_timer fires
// if they were moving prior to losing all hate
if(IsMoving()){
SetRunAnimSpeed(0);
@@ -1898,7 +1926,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) {
@@ -2426,7 +2454,7 @@ bool NPC::AI_AddNPCSpells(uint32 iDBSpellsID) {
}
//If any casting variables are defined in the current list, ignore those in the parent list.
if (spell_list->fail_recast || spell_list->engaged_no_sp_recast_min || spell_list->engaged_no_sp_recast_max
if (spell_list->fail_recast || spell_list->engaged_no_sp_recast_min || spell_list->engaged_no_sp_recast_max
|| spell_list->engaged_beneficial_self_chance || spell_list->engaged_beneficial_other_chance || spell_list->engaged_detrimental_chance
|| spell_list->pursue_no_sp_recast_min || spell_list->pursue_no_sp_recast_max || spell_list->pursue_detrimental_chance
|| spell_list->idle_no_sp_recast_min || spell_list->idle_no_sp_recast_max || spell_list->idle_beneficial_chance) {
@@ -2477,7 +2505,7 @@ bool NPC::AI_AddNPCSpells(uint32 iDBSpellsID) {
AISpellVar.idle_no_sp_recast_min = (_idle_no_sp_recast_min) ? _idle_no_sp_recast_min : RuleI(Spells, AI_IdleNoSpellMinRecast);
AISpellVar.idle_no_sp_recast_max = (_idle_no_sp_recast_max) ? _idle_no_sp_recast_max : RuleI(Spells, AI_IdleNoSpellMaxRecast);
AISpellVar.idle_beneficial_chance = (_idle_beneficial_chance) ? _idle_beneficial_chance : RuleI(Spells, AI_IdleBeneficialChance);
if (AIspells.size() == 0)
AIautocastspell_timer->Disable();
else
@@ -2489,12 +2517,12 @@ bool NPC::AI_AddNPCSpellsEffects(uint32 iDBSpellsEffectsID) {
npc_spells_effects_id = iDBSpellsEffectsID;
AIspellsEffects.clear();
if (iDBSpellsEffectsID == 0)
if (iDBSpellsEffectsID == 0)
return false;
DBnpcspellseffects_Struct* spell_effects_list = database.GetNPCSpellsEffects(iDBSpellsEffectsID);
if (!spell_effects_list) {
return false;
}
@@ -2522,9 +2550,9 @@ bool NPC::AI_AddNPCSpellsEffects(uint32 iDBSpellsEffectsID) {
if (parentlist) {
for (i=0; i<parentlist->numentries; i++) {
if (GetLevel() >= parentlist->entries[i].minlevel && GetLevel() <= parentlist->entries[i].maxlevel && parentlist->entries[i].spelleffectid > 0) {
if (!IsSpellEffectInList(spell_effects_list, parentlist->entries[i].spelleffectid, parentlist->entries[i].base,
if (!IsSpellEffectInList(spell_effects_list, parentlist->entries[i].spelleffectid, parentlist->entries[i].base,
parentlist->entries[i].limit, parentlist->entries[i].max))
{
{
AddSpellEffectToNPCList(parentlist->entries[i].spelleffectid,
parentlist->entries[i].base, parentlist->entries[i].limit,
parentlist->entries[i].max);
@@ -2548,10 +2576,10 @@ void NPC::ApplyAISpellEffects(StatBonuses* newbon)
{
if (!AI_HasSpellsEffects())
return;
for(int i=0; i < AIspellsEffects.size(); i++)
{
ApplySpellsBonuses(0, 0, newbon, 0, false, 0,-1,
ApplySpellsBonuses(0, 0, newbon, 0, false, 0,-1,
true, AIspellsEffects[i].spelleffectid, AIspellsEffects[i].base, AIspellsEffects[i].limit,AIspellsEffects[i].max);
}
@@ -2561,10 +2589,10 @@ void NPC::ApplyAISpellEffects(StatBonuses* newbon)
// adds a spell to the list, taking into account priority and resorting list as needed.
void NPC::AddSpellEffectToNPCList(uint16 iSpellEffectID, int32 base, int32 limit, int32 max)
{
if(!iSpellEffectID)
return;
HasAISpellEffects = true;
AISpellsEffects_Struct t;
@@ -2647,7 +2675,7 @@ void NPC::AISpellsList(Client *c)
DBnpcspells_Struct* ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID) {
if (iDBSpellsID == 0)
return 0;
return nullptr;
if (!npc_spells_cache) {
npc_spells_maxid = GetMaxNPCSpellsID();
@@ -2660,144 +2688,134 @@ DBnpcspells_Struct* ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID) {
}
if (iDBSpellsID > npc_spells_maxid)
return 0;
return nullptr;
if (npc_spells_cache[iDBSpellsID]) { // it's in the cache, easy =)
return npc_spells_cache[iDBSpellsID];
}
else if (!npc_spells_loadtried[iDBSpellsID]) { // no reason to ask the DB again if we have failed once already
npc_spells_loadtried[iDBSpellsID] = true;
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if (RunQuery(query, MakeAnyLenString(&query, "SELECT id, parent_list, attack_proc, proc_chance, range_proc, rproc_chance, defensive_proc, dproc_chance, fail_recast, engaged_no_sp_recast_min, engaged_no_sp_recast_max, engaged_b_self_chance, engaged_b_other_chance, engaged_d_chance, pursue_no_sp_recast_min, pursue_no_sp_recast_max, pursue_d_chance, idle_no_sp_recast_min, idle_no_sp_recast_max, idle_b_chance from npc_spells where id=%d", iDBSpellsID), errbuf, &result)) {
safe_delete_array(query);
if (mysql_num_rows(result) == 1) {
row = mysql_fetch_row(result);
uint32 tmpparent_list = atoi(row[1]);
uint16 tmpattack_proc = atoi(row[2]);
uint8 tmpproc_chance = atoi(row[3]);
uint16 tmprange_proc = atoi(row[4]);
int16 tmprproc_chance = atoi(row[5]);
uint16 tmpdefensive_proc = atoi(row[6]);
int16 tmpdproc_chance = atoi(row[7]);
uint32 tmppfail_recast = atoi(row[8]);
uint32 tmpengaged_no_sp_recast_min = atoi(row[9]);
uint32 tmpengaged_no_sp_recast_max = atoi(row[10]);
uint8 tmpengaged_b_self_chance = atoi(row[11]);
uint8 tmpengaged_b_other_chance = atoi(row[12]);
uint8 tmpengaged_d_chance = atoi(row[13]);
uint32 tmppursue_no_sp_recast_min = atoi(row[14]);
uint32 tmppursue_no_sp_recast_max = atoi(row[15]);
uint8 tmppursue_d_chance = atoi(row[16]);
uint32 tmpidle_no_sp_recast_min = atoi(row[17]);
uint32 tmpidle_no_sp_recast_max = atoi(row[18]);
uint8 tmpidle_b_chance = atoi(row[19]);
mysql_free_result(result);
if (RunQuery(query, MakeAnyLenString(&query, "SELECT spellid, type, minlevel, maxlevel, manacost, recast_delay, priority, resist_adjust from npc_spells_entries where npc_spells_id=%d ORDER BY minlevel", iDBSpellsID), errbuf, &result)) {
safe_delete_array(query);
uint32 tmpSize = sizeof(DBnpcspells_Struct) + (sizeof(DBnpcspells_entries_Struct) * mysql_num_rows(result));
npc_spells_cache[iDBSpellsID] = (DBnpcspells_Struct*) new uchar[tmpSize];
memset(npc_spells_cache[iDBSpellsID], 0, tmpSize);
npc_spells_cache[iDBSpellsID]->parent_list = tmpparent_list;
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]->defensive_proc = tmpdefensive_proc;
npc_spells_cache[iDBSpellsID]->dproc_chance = tmpdproc_chance;
npc_spells_cache[iDBSpellsID]->fail_recast = tmppfail_recast;
npc_spells_cache[iDBSpellsID]->engaged_no_sp_recast_min = tmpengaged_no_sp_recast_min;
npc_spells_cache[iDBSpellsID]->engaged_no_sp_recast_max = tmpengaged_no_sp_recast_max;
npc_spells_cache[iDBSpellsID]->engaged_beneficial_self_chance = tmpengaged_b_self_chance;
npc_spells_cache[iDBSpellsID]->engaged_beneficial_other_chance = tmpengaged_b_other_chance;
npc_spells_cache[iDBSpellsID]->engaged_detrimental_chance = tmpengaged_d_chance;
npc_spells_cache[iDBSpellsID]->pursue_no_sp_recast_min = tmppursue_no_sp_recast_min;
npc_spells_cache[iDBSpellsID]->pursue_no_sp_recast_max = tmppursue_no_sp_recast_max;
npc_spells_cache[iDBSpellsID]->pursue_detrimental_chance = tmppursue_d_chance;
npc_spells_cache[iDBSpellsID]->idle_no_sp_recast_min = tmpidle_no_sp_recast_min;
npc_spells_cache[iDBSpellsID]->idle_no_sp_recast_max = tmpidle_no_sp_recast_max;
npc_spells_cache[iDBSpellsID]->idle_beneficial_chance = tmpidle_b_chance;
npc_spells_cache[iDBSpellsID]->numentries = mysql_num_rows(result);
int j = 0;
while ((row = mysql_fetch_row(result))) {
int spell_id = atoi(row[0]);
npc_spells_cache[iDBSpellsID]->entries[j].spellid = spell_id;
npc_spells_cache[iDBSpellsID]->entries[j].type = atoi(row[1]);
npc_spells_cache[iDBSpellsID]->entries[j].minlevel = atoi(row[2]);
npc_spells_cache[iDBSpellsID]->entries[j].maxlevel = atoi(row[3]);
npc_spells_cache[iDBSpellsID]->entries[j].manacost = atoi(row[4]);
npc_spells_cache[iDBSpellsID]->entries[j].recast_delay = atoi(row[5]);
npc_spells_cache[iDBSpellsID]->entries[j].priority = atoi(row[6]);
if(row[7])
{
npc_spells_cache[iDBSpellsID]->entries[j].resist_adjust = atoi(row[7]);
}
else
{
if(IsValidSpell(spell_id))
{
npc_spells_cache[iDBSpellsID]->entries[j].resist_adjust = spells[spell_id].ResistDiff;
}
}
j++;
}
mysql_free_result(result);
return npc_spells_cache[iDBSpellsID];
}
else {
std::cerr << "Error in AddNPCSpells query1 '" << query << "' " << errbuf << std::endl;
safe_delete_array(query);
return 0;
}
}
else {
mysql_free_result(result);
}
}
else {
std::cerr << "Error in AddNPCSpells query1 '" << query << "' " << errbuf << std::endl;
safe_delete_array(query);
return 0;
}
std::string query = StringFormat("SELECT id, parent_list, attack_proc, proc_chance, "
"range_proc, rproc_chance, defensive_proc, dproc_chance, "
"fail_recast, engaged_no_sp_recast_min, engaged_no_sp_recast_max, "
"engaged_b_self_chance, engaged_b_other_chance, engaged_d_chance, "
"pursue_no_sp_recast_min, pursue_no_sp_recast_max, "
"pursue_d_chance, idle_no_sp_recast_min, idle_no_sp_recast_max, "
"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;
}
return 0;
}
return 0;
if (results.RowCount() != 1)
return nullptr;
auto row = results.begin();
uint32 tmpparent_list = atoi(row[1]);
uint16 tmpattack_proc = atoi(row[2]);
uint8 tmpproc_chance = atoi(row[3]);
uint16 tmprange_proc = atoi(row[4]);
int16 tmprproc_chance = atoi(row[5]);
uint16 tmpdefensive_proc = atoi(row[6]);
int16 tmpdproc_chance = atoi(row[7]);
uint32 tmppfail_recast = atoi(row[8]);
uint32 tmpengaged_no_sp_recast_min = atoi(row[9]);
uint32 tmpengaged_no_sp_recast_max = atoi(row[10]);
uint8 tmpengaged_b_self_chance = atoi(row[11]);
uint8 tmpengaged_b_other_chance = atoi(row[12]);
uint8 tmpengaged_d_chance = atoi(row[13]);
uint32 tmppursue_no_sp_recast_min = atoi(row[14]);
uint32 tmppursue_no_sp_recast_max = atoi(row[15]);
uint8 tmppursue_d_chance = atoi(row[16]);
uint32 tmpidle_no_sp_recast_min = atoi(row[17]);
uint32 tmpidle_no_sp_recast_max = atoi(row[18]);
uint8 tmpidle_b_chance = atoi(row[19]);
query = StringFormat("SELECT spellid, type, minlevel, maxlevel, "
"manacost, recast_delay, priority, resist_adjust "
"FROM npc_spells_entries "
"WHERE npc_spells_id=%d ORDER BY minlevel", iDBSpellsID);
results = QueryDatabase(query);
if (!results.Success())
{
std::cerr << "Error in AddNPCSpells query1 '" << query << "' " << results.ErrorMessage() << std::endl;
return nullptr;
}
uint32 tmpSize = sizeof(DBnpcspells_Struct) + (sizeof(DBnpcspells_entries_Struct) * results.RowCount());
npc_spells_cache[iDBSpellsID] = (DBnpcspells_Struct*) new uchar[tmpSize];
memset(npc_spells_cache[iDBSpellsID], 0, tmpSize);
npc_spells_cache[iDBSpellsID]->parent_list = tmpparent_list;
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]->defensive_proc = tmpdefensive_proc;
npc_spells_cache[iDBSpellsID]->dproc_chance = tmpdproc_chance;
npc_spells_cache[iDBSpellsID]->fail_recast = tmppfail_recast;
npc_spells_cache[iDBSpellsID]->engaged_no_sp_recast_min = tmpengaged_no_sp_recast_min;
npc_spells_cache[iDBSpellsID]->engaged_no_sp_recast_max = tmpengaged_no_sp_recast_max;
npc_spells_cache[iDBSpellsID]->engaged_beneficial_self_chance = tmpengaged_b_self_chance;
npc_spells_cache[iDBSpellsID]->engaged_beneficial_other_chance = tmpengaged_b_other_chance;
npc_spells_cache[iDBSpellsID]->engaged_detrimental_chance = tmpengaged_d_chance;
npc_spells_cache[iDBSpellsID]->pursue_no_sp_recast_min = tmppursue_no_sp_recast_min;
npc_spells_cache[iDBSpellsID]->pursue_no_sp_recast_max = tmppursue_no_sp_recast_max;
npc_spells_cache[iDBSpellsID]->pursue_detrimental_chance = tmppursue_d_chance;
npc_spells_cache[iDBSpellsID]->idle_no_sp_recast_min = tmpidle_no_sp_recast_min;
npc_spells_cache[iDBSpellsID]->idle_no_sp_recast_max = tmpidle_no_sp_recast_max;
npc_spells_cache[iDBSpellsID]->idle_beneficial_chance = tmpidle_b_chance;
npc_spells_cache[iDBSpellsID]->numentries = results.RowCount();
int entryIndex = 0;
for (row = results.begin(); row != results.end(); ++row, ++entryIndex)
{
int spell_id = atoi(row[0]);
npc_spells_cache[iDBSpellsID]->entries[entryIndex].spellid = spell_id;
npc_spells_cache[iDBSpellsID]->entries[entryIndex].type = atoi(row[1]);
npc_spells_cache[iDBSpellsID]->entries[entryIndex].minlevel = atoi(row[2]);
npc_spells_cache[iDBSpellsID]->entries[entryIndex].maxlevel = atoi(row[3]);
npc_spells_cache[iDBSpellsID]->entries[entryIndex].manacost = atoi(row[4]);
npc_spells_cache[iDBSpellsID]->entries[entryIndex].recast_delay = atoi(row[5]);
npc_spells_cache[iDBSpellsID]->entries[entryIndex].priority = atoi(row[6]);
if(row[7])
npc_spells_cache[iDBSpellsID]->entries[entryIndex].resist_adjust = atoi(row[7]);
else if(IsValidSpell(spell_id))
npc_spells_cache[iDBSpellsID]->entries[entryIndex].resist_adjust = spells[spell_id].ResistDiff;
}
return npc_spells_cache[iDBSpellsID];
}
return nullptr;
}
uint32 ZoneDatabase::GetMaxNPCSpellsID() {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if (RunQuery(query, MakeAnyLenString(&query, "SELECT max(id) from npc_spells"), errbuf, &result)) {
safe_delete_array(query);
if (mysql_num_rows(result) == 1) {
row = mysql_fetch_row(result);
uint32 ret = 0;
if (row[0])
ret = atoi(row[0]);
mysql_free_result(result);
return ret;
}
mysql_free_result(result);
}
else {
std::cerr << "Error in GetMaxNPCSpellsID query '" << query << "' " << errbuf << std::endl;
safe_delete_array(query);
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;
}
return 0;
if (results.RowCount() != 1)
return 0;
auto row = results.begin();
if (!row[0])
return 0;
return atoi(row[0]);
}
DBnpcspellseffects_Struct* ZoneDatabase::GetNPCSpellsEffects(uint32 iDBSpellsEffectsID) {
if (iDBSpellsEffectsID == 0)
return 0;
return nullptr;
if (!npc_spellseffects_cache) {
npc_spellseffects_maxid = GetMaxNPCSpellsEffectsID();
@@ -2810,89 +2828,74 @@ DBnpcspellseffects_Struct* ZoneDatabase::GetNPCSpellsEffects(uint32 iDBSpellsEff
}
if (iDBSpellsEffectsID > npc_spellseffects_maxid)
return 0;
if (npc_spellseffects_cache[iDBSpellsEffectsID]) { // it's in the cache, easy =)
return nullptr;
if (npc_spellseffects_cache[iDBSpellsEffectsID]) // it's in the cache, easy =)
return npc_spellseffects_cache[iDBSpellsEffectsID];
}
else if (!npc_spellseffects_loadtried[iDBSpellsEffectsID]) { // no reason to ask the DB again if we have failed once already
npc_spellseffects_loadtried[iDBSpellsEffectsID] = true;
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if (npc_spellseffects_loadtried[iDBSpellsEffectsID])
return nullptr;
if (RunQuery(query, MakeAnyLenString(&query, "SELECT id, parent_list from npc_spells_effects where id=%d", iDBSpellsEffectsID), errbuf, &result)) {
safe_delete_array(query);
if (mysql_num_rows(result) == 1) {
row = mysql_fetch_row(result);
uint32 tmpparent_list = atoi(row[1]);
mysql_free_result(result);
if (RunQuery(query, MakeAnyLenString(&query, "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), errbuf, &result)) {
safe_delete_array(query);
uint32 tmpSize = sizeof(DBnpcspellseffects_Struct) + (sizeof(DBnpcspellseffects_entries_Struct) * mysql_num_rows(result));
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 = mysql_num_rows(result);
int j = 0;
while ((row = mysql_fetch_row(result))) {
int spell_effect_id = atoi(row[0]);
npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].spelleffectid = spell_effect_id;
npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].minlevel = atoi(row[1]);
npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].maxlevel = atoi(row[2]);
npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].base = atoi(row[3]);
npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].limit = atoi(row[4]);
npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].max = atoi(row[5]);
j++;
}
mysql_free_result(result);
return npc_spellseffects_cache[iDBSpellsEffectsID];
}
else {
std::cerr << "Error in AddNPCSpells query1 '" << query << "' " << errbuf << std::endl;
safe_delete_array(query);
return 0;
}
}
else {
mysql_free_result(result);
}
}
else {
std::cerr << "Error in AddNPCSpells query1 '" << query << "' " << errbuf << std::endl;
safe_delete_array(query);
return 0;
}
return 0;
}
return 0;
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;
}
if (results.RowCount() != 1)
return nullptr;
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;
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]);
}
return npc_spellseffects_cache[iDBSpellsEffectsID];
}
uint32 ZoneDatabase::GetMaxNPCSpellsEffectsID() {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if (RunQuery(query, MakeAnyLenString(&query, "SELECT max(id) from npc_spells_effects"), errbuf, &result)) {
safe_delete_array(query);
if (mysql_num_rows(result) == 1) {
row = mysql_fetch_row(result);
uint32 ret = 0;
if (row[0])
ret = atoi(row[0]);
mysql_free_result(result);
return ret;
}
mysql_free_result(result);
}
else {
std::cerr << "Error in GetMaxNPCSpellsEffectsID query '" << query << "' " << errbuf << std::endl;
safe_delete_array(query);
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;
}
return 0;
if (results.RowCount() != 1)
return 0;
auto row = results.begin();
if (!row[0])
return 0;
return atoi(row[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 "QuestParserCollection.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;
+1 -1
View File
@@ -12,7 +12,7 @@
#include "mob.h"
#include "client.h"
#include "worldserver.h"
#include "QuestParserCollection.h"
#include "quest_parser_collection.h"
#include "event_codes.h"
#include "embparser.h"
#include <string>
+16 -23
View File
@@ -22,20 +22,20 @@
#include "../common/features.h"
#include "../common/queue.h"
#include "../common/timer.h"
#include "../common/EQStream.h"
#include "../common/EQStreamFactory.h"
#include "../common/eq_stream.h"
#include "../common/eq_stream_factory.h"
#include "../common/eq_packet_structs.h"
#include "../common/Mutex.h"
#include "../common/mutex.h"
#include "../common/version.h"
#include "../common/EQEMuError.h"
#include "../common/eqemu_error.h"
#include "../common/packet_dump_file.h"
#include "../common/opcodemgr.h"
#include "../common/guilds.h"
#include "../common/EQStreamIdent.h"
#include "../common/eq_stream_ident.h"
#include "../common/patches/patches.h"
#include "../common/rulesys.h"
#include "../common/MiscFunctions.h"
#include "../common/StringUtil.h"
#include "../common/misc_functions.h"
#include "../common/string_util.h"
#include "../common/platform.h"
#include "../common/crash.h"
#include "../common/ipc_mutex.h"
@@ -43,17 +43,18 @@
#include "../common/eqemu_exception.h"
#include "../common/spdat.h"
#include "ZoneConfig.h"
#include "zone_config.h"
#include "masterentity.h"
#include "worldserver.h"
#include "net.h"
#include "zone.h"
#include "queryserv.h"
#include "command.h"
#include "ZoneConfig.h"
#include "zone_config.h"
#include "titles.h"
#include "guild_mgr.h"
#include "tasks.h"
#include "QuestParserCollection.h"
#include "quest_parser_collection.h"
#include "embparser.h"
#include "lua_parser.h"
#include "client_logs.h"
@@ -97,8 +98,7 @@ extern Zone* zone;
EQStreamFactory eqsf(ZoneStream);
npcDecayTimes_Struct npcCorpseDecayTimes[100];
TitleManager title_manager;
DBAsyncFinishedQueue MTdbafq;
DBAsync *dbasync = nullptr;
QueryServ *QServ = 0;
TaskManager *taskmanager = 0;
QuestParserCollection *parse = 0;
@@ -116,6 +116,8 @@ int main(int argc, char** argv) {
const char *zone_name;
QServ = new QueryServ;
if(argc == 3) {
worldserver.SetLauncherName(argv[2]);
worldserver.SetLaunchedName(argv[1]);
@@ -166,8 +168,6 @@ int main(int argc, char** argv) {
_log(ZONE__INIT_ERR, "Cannot continue without a database connection.");
return 1;
}
dbasync = new DBAsync(&database);
dbasync->AddFQ(&MTdbafq);
guild_mgr.SetDatabase(&database);
GuildBanks = nullptr;
@@ -446,10 +446,6 @@ int main(int argc, char** argv) {
}
}
}
DBAsyncWork* dbaw = 0;
while ((dbaw = MTdbafq.Pop())) {
DispatchFinishedDBAsync(dbaw);
}
if (InterserverTimer.Check()) {
InterserverTimer.Start();
database.ping();
@@ -509,8 +505,6 @@ int main(int argc, char** argv) {
//Fix for Linux world server problem.
eqsf.Close();
worldserver.Disconnect();
dbasync->CommitWrites();
dbasync->StopThread();
safe_delete(taskmanager);
command_deinit();
safe_delete(parse);
@@ -628,7 +622,7 @@ void LoadSpells(EQEmu::MemoryMappedFile **mmf) {
SPDAT_RECORDS = records;
}
/* Update Window Title with relevant information */
void UpdateWindowTitle(char* iNewTitle) {
#ifdef _WINDOWS
char tmp[500];
@@ -640,7 +634,7 @@ void UpdateWindowTitle(char* iNewTitle) {
#if defined(GOTFRAGS) || defined(_EQDEBUG)
snprintf(tmp, sizeof(tmp), "%i: %s, %i clients, %i", ZoneConfig::get()->ZonePort, zone->GetShortName(), numclients, getpid());
#else
snprintf(tmp, sizeof(tmp), "%i: %s, %i clients", ZoneConfig::get()->ZonePort, zone->GetShortName(), numclients);
snprintf(tmp, sizeof(tmp), "%s :: clients: %i inst_id: %i inst_ver: %i :: port: %i", zone->GetShortName(), numclients, zone->GetInstanceID(), zone->GetInstanceVersion(), ZoneConfig::get()->ZonePort);
#endif
}
else {
@@ -654,4 +648,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);
+491 -539
View File
File diff suppressed because it is too large Load Diff
+37 -26
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
@@ -88,8 +85,12 @@ struct AISpellsVar_Struct {
uint8 idle_beneficial_chance;
};
class AA_SwarmPetInfo;
class Client;
class Group;
class Raid;
class Spawn2;
struct Item_Struct;
class NPC : public Mob
{
@@ -127,20 +128,15 @@ 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);
inline void SetSpellFocusDMG(int32 NewSpellFocusDMG) {SpellFocusDMG = NewSpellFocusDMG;}
inline void SetSpellFocusHeal(int32 NewSpellFocusHeal) {SpellFocusHeal = NewSpellFocusHeal;}
int32 SpellFocusDMG;
int32 SpellFocusHeal;
virtual void SetTarget(Mob* mob);
virtual uint16 GetSkill(SkillUseTypes skill_num) const { if (skill_num <= HIGHEST_SKILL) { return skills[skill_num]; } return 0; }
@@ -158,6 +154,7 @@ public:
virtual void InitializeBuffSlots();
virtual void UninitializeBuffSlots();
virtual void SetAttackTimer();
virtual void RangedAttack(Mob* other);
virtual void ThrowingAttack(Mob* other) { }
int32 GetNumberOfAttacks() const { return attack_count; }
@@ -247,6 +244,8 @@ public:
uint32 GetSwarmOwner();
uint32 GetSwarmTarget();
void SetSwarmTarget(int target_id = 0);
void DepopSwarmPets();
void PetOnSpawn(NewSpawn_Struct* ns);
void SignalNPC(int _signal_id);
@@ -361,8 +360,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; }
@@ -387,15 +387,23 @@ 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;}
uint32 GetSpawnKillCount();
int GetScore();
void mod_prespawn(Spawn2 *sp);
int mod_npc_damage(int damage, SkillUseTypes skillinuse, int hand, const Item_Struct* weapon, Mob* other);
inline void SetSpellFocusHeal(int32 NewSpellFocusHeal) {SpellFocusHeal = NewSpellFocusHeal;}
inline int32 GetSpellFocusHeal() const {return SpellFocusHeal;}
uint32 GetSpawnKillCount();
int GetScore();
void SetMerchantProbability(uint8 amt) { probability = amt; }
uint8 GetMerchantProbability() { return probability; }
void mod_prespawn(Spawn2 *sp);
int mod_npc_damage(int damage, SkillUseTypes skillinuse, int hand, const Item_Struct* weapon, Mob* other);
void mod_npc_killed_merit(Mob* c);
void mod_npc_killed(Mob* oos);
void AISpellsList(Client *c);
void AISpellsList(Client *c);
bool IsRaidTarget() const { return raid_target; };
protected:
@@ -450,6 +458,8 @@ protected:
uint32 npc_mana;
float spellscale;
float healscale;
int32 SpellFocusDMG;
int32 SpellFocusHeal;
//pet crap:
uint16 pet_spell_id;
@@ -504,6 +514,7 @@ protected:
std::list<MercData> mercDataList;
bool raid_target;
uint8 probability;
private:
uint32 loottable_id;
View File
View File
+111 -89
View File
@@ -24,12 +24,12 @@
#include "zonedb.h"
#include "../common/packet_functions.h"
#include "../common/packet_dump.h"
#include "../common/MiscFunctions.h"
#include "../common/StringUtil.h"
#include "../common/misc_functions.h"
#include "../common/string_util.h"
#include "../common/features.h"
#include "StringIDs.h"
#include "string_ids.h"
#include "QuestParserCollection.h"
#include "quest_parser_collection.h"
const char DEFAULT_OBJECT_NAME[] = "IT63_ACTORDEF";
const char DEFAULT_OBJECT_NAME_SUFFIX[] = "_ACTORDEF";
@@ -318,6 +318,14 @@ 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)
{
@@ -465,7 +473,7 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object)
char buf[10];
snprintf(buf, 9, "%u", m_inst->GetItem()->ID);
buf[9] = '\0';
std::vector<void*> args;
std::vector<EQEmu::Any> args;
args.push_back(m_inst);
parse->EventPlayer(EVENT_PLAYER_PICKUP, sender, buf, 0, &args);
@@ -560,9 +568,6 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object)
// Add new Zone Object (theoretically only called for items dropped to ground)
uint32 ZoneDatabase::AddObject(uint32 type, uint32 icon, const Object_Struct& object, const ItemInst* inst)
{
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
uint32 database_id = 0;
uint32 item_id = 0;
int16 charges = 0;
@@ -577,35 +582,30 @@ uint32 ZoneDatabase::AddObject(uint32 type, uint32 icon, const Object_Struct& ob
char* object_name = new char[len];
DoEscapeString(object_name, object.object_name, strlen(object.object_name));
// Construct query
uint32 len_query = MakeAnyLenString(&query,
"insert into object (zoneid, xpos, ypos, zpos, heading, itemid, charges, objectname, "
"type, icon) values (%i, %f, %f, %f, %f, %i, %i, '%s', %i, %i)",
object.zone_id, object.x, object.y, object.z, object.heading,
item_id, charges, object_name, type, icon);
// Save new record for object
if (!RunQuery(query, len_query, errbuf, nullptr, nullptr, &database_id)) {
LogFile->write(EQEMuLog::Error, "Unable to insert object: %s", errbuf);
}
else {
// Save container contents, if container
if (inst && inst->IsType(ItemClassContainer)) {
SaveWorldContainer(object.zone_id, database_id, inst);
}
// Save new record for object
std::string query = StringFormat("INSERT INTO object "
"(zoneid, xpos, ypos, zpos, heading, "
"itemid, charges, objectname, type, icon) "
"values (%i, %f, %f, %f, %f, %i, %i, '%s', %i, %i)",
object.zone_id, object.x, object.y, object.z, object.heading,
item_id, charges, object_name, type, icon);
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());
return 0;
}
safe_delete_array(object_name);
safe_delete_array(query);
// Save container contents, if container
if (inst && inst->IsType(ItemClassContainer))
SaveWorldContainer(object.zone_id, database_id, inst);
return database_id;
}
// Update information about existing object in database
void ZoneDatabase::UpdateObject(uint32 id, uint32 type, uint32 icon, const Object_Struct& object, const ItemInst* inst)
{
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
uint32 item_id = 0;
int16 charges = 0;
@@ -619,77 +619,63 @@ void ZoneDatabase::UpdateObject(uint32 id, uint32 type, uint32 icon, const Objec
char* object_name = new char[len];
DoEscapeString(object_name, object.object_name, strlen(object.object_name));
// Construct query
uint32 len_query = MakeAnyLenString(&query,
"update object set zoneid=%i, xpos=%f, ypos=%f, zpos=%f, heading=%f, "
"itemid=%i, charges=%i, objectname='%s', type=%i, icon=%i where id=%i",
object.zone_id, object.x, object.y, object.z, object.heading,
item_id, charges, object_name, type, icon, id);
// Save new record for object
if (!RunQuery(query, len_query, errbuf)) {
LogFile->write(EQEMuLog::Error, "Unable to update object: %s", errbuf);
}
else {
// Save container contents, if container
if (inst && inst->IsType(ItemClassContainer)) {
SaveWorldContainer(object.zone_id, id, inst);
}
std::string query = StringFormat("UPDATE object SET "
"zoneid = %i, xpos = %f, ypos = %f, zpos = %f, heading = %f, "
"itemid = %i, charges = %i, objectname = '%s', type = %i, icon = %i "
"WHERE id = %i",
object.zone_id, object.x, object.y, object.z, object.heading,
item_id, charges, object_name, type, icon, id);
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());
return;
}
safe_delete_array(object_name);
safe_delete_array(query);
// Save container contents, if container
if (inst && inst->IsType(ItemClassContainer))
SaveWorldContainer(object.zone_id, id, inst);
}
Ground_Spawns* ZoneDatabase::LoadGroundSpawns(uint32 zone_id, int16 version, Ground_Spawns* gs){
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if (RunQuery(query, MakeAnyLenString(&query, "SELECT max_x,max_y,max_z,min_x,min_y,heading,name,item,max_allowed,respawn_timer from ground_spawns where zoneid=%i and (version=%u OR version=-1) limit 50", zone_id, version), errbuf, &result))
{
safe_delete_array(query);
int i=0;
while( (row=mysql_fetch_row(result) ) ) {
gs->spawn[i].max_x=atof(row[0]);
gs->spawn[i].max_y=atof(row[1]);
gs->spawn[i].max_z=atof(row[2]);
gs->spawn[i].min_x=atof(row[3]);
gs->spawn[i].min_y=atof(row[4]);
gs->spawn[i].heading=atof(row[5]);
strcpy(gs->spawn[i].name,row[6]);
gs->spawn[i].item=atoi(row[7]);
gs->spawn[i].max_allowed=atoi(row[8]);
gs->spawn[i].respawntimer=atoi(row[9]);
i++;
}
mysql_free_result(result);
}
else {
std::cerr << "Error in LoadGroundSpawns query '" << query << "' " << errbuf << std::endl;
safe_delete_array(query);
Ground_Spawns* ZoneDatabase::LoadGroundSpawns(uint32 zone_id, int16 version, Ground_Spawns* gs) {
std::string query = StringFormat("SELECT max_x, max_y, max_z, "
"min_x, min_y, heading, name, "
"item, max_allowed, respawn_timer "
"FROM ground_spawns "
"WHERE zoneid = %i AND (version = %u OR version = -1) "
"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;
}
int spawnIndex=0;
for (auto row = results.begin(); row != results.end(); ++row, ++spawnIndex) {
gs->spawn[spawnIndex].max_x=atof(row[0]);
gs->spawn[spawnIndex].max_y=atof(row[1]);
gs->spawn[spawnIndex].max_z=atof(row[2]);
gs->spawn[spawnIndex].min_x=atof(row[3]);
gs->spawn[spawnIndex].min_y=atof(row[4]);
gs->spawn[spawnIndex].heading=atof(row[5]);
strcpy(gs->spawn[spawnIndex].name,row[6]);
gs->spawn[spawnIndex].item=atoi(row[7]);
gs->spawn[spawnIndex].max_allowed=atoi(row[8]);
gs->spawn[spawnIndex].respawntimer=atoi(row[9]);
}
return gs;
}
void ZoneDatabase::DeleteObject(uint32 id)
{
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
// Construct query
uint32 len_query = MakeAnyLenString(&query,
"delete from object where id=%i", id);
// Save new record for object
if (!RunQuery(query, len_query, errbuf)) {
LogFile->write(EQEMuLog::Error, "Unable to delete object: %s", errbuf);
// delete record of object
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());
}
//else {
// Delete contained items, if any
// DeleteWorldContainer(id);
//}
safe_delete_array(query);
}
uint32 Object::GetDBID()
@@ -812,6 +798,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;
+6 -1
View File
@@ -25,7 +25,7 @@
#include "../common/linked_list.h"
#include "../common/emu_opcodes.h"
#include "../common/eq_packet_structs.h"
#include "../common/Item.h"
#include "../common/item.h"
#include "client.h"
#include "mob.h"
#include "npc.h"
@@ -121,6 +121,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 +157,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);
+3 -3
View File
@@ -67,12 +67,12 @@ extern volatile bool ZoneLoaded;
#include "../common/queue.h"
#include "../common/timer.h"
#include "../common/EQStream.h"
#include "../common/eq_stream.h"
#include "../common/eq_packet_structs.h"
#include "../common/Mutex.h"
#include "../common/mutex.h"
#include "../common/version.h"
#include "../common/files.h"
#include "../common/EQEMuError.h"
#include "../common/eqemu_error.h"
#include "../common/packet_dump_file.h"
#include "masterentity.h"
+1 -1
View File
@@ -7,7 +7,7 @@
#include <fstream>
#include "pathing.h"
#include "water_map.h"
#include "../common/MiscFunctions.h"
#include "../common/misc_functions.h"
#include "doors.h"
#include "client.h"
#include "zone.h"
+164 -13
View File
@@ -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, new_x, new_y, new_z);
}
XSRETURN_EMPTY;
}
@@ -1259,7 +1266,24 @@ XS(XS_Client_MovePC)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
THIS->MovePC(zoneID, x, y, z, heading);
if (THIS->IsClient()) {
THIS->MovePC(zoneID, x, y, z, heading);
}
else {
if (THIS->IsMerc())
_log(CLIENT__ERROR, "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");
#ifdef BOTS
else if (THIS->IsBot())
_log(CLIENT__ERROR, "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");
Perl_croak(aTHX_ "THIS is not of type Client");
}
}
XSRETURN_EMPTY;
}
@@ -1288,7 +1312,25 @@ XS(XS_Client_MovePCInstance)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
THIS->MovePC(zoneID, instanceID, x, y, z, heading);
if (THIS->IsClient()) {
THIS->MovePC(zoneID, instanceID, x, y, z, heading);
}
else {
if (THIS->IsMerc())
_log(CLIENT__ERROR, "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");
#ifdef BOTS
else if (THIS->IsBot())
_log(CLIENT__ERROR, "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");
Perl_croak(aTHX_ "THIS is not of type Client");
Perl_croak(aTHX_ "THIS is not of type Client");
}
}
XSRETURN_EMPTY;
}
@@ -5037,6 +5079,35 @@ XS(XS_Client_UpdateTaskActivity)
XSRETURN_EMPTY;
}
XS(XS_Client_GetTaskActivityDoneCount); /* prototype to pass -Wmissing-prototypes */
XS(XS_Client_GetTaskActivityDoneCount)
{
dXSARGS;
if (items != 3)
Perl_croak(aTHX_ "Usage: Client::GetTaskActivityDoneCount(THIS, TaskID, ActivityID)");
{
Client * THIS;
int RETVAL;
int TaskID = (int)SvIV(ST(1));
int ActivityID = (int)SvIV(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 == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetTaskActivityDoneCountFromTaskID(TaskID, ActivityID);
XSprePUSH; PUSHi((IV)RETVAL);
}
XSRETURN(1);
}
XS(XS_Client_AssignTask); /* prototype to pass -Wmissing-prototypes */
XS(XS_Client_AssignTask)
{
@@ -5273,6 +5344,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)
{
@@ -5956,6 +6051,58 @@ XS(XS_Client_SendMarqueeMessage)
XSRETURN_EMPTY;
}
XS(XS_Client_SendColoredText); /* prototype to pass -Wmissing-prototypes */
XS(XS_Client_SendColoredText)
{
dXSARGS;
if (items != 3)
Perl_croak(aTHX_ "Usage: Client::SendColoredText(color, message)");
{
Client * THIS;
uint32 color = (uint32)SvUV(ST(1));
std::string msg = (std::string)SvPV_nolen(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->SendColoredText(color, msg);
}
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
@@ -6015,7 +6162,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, "$$");
@@ -6164,6 +6311,7 @@ XS(boot_Client)
newXSproto(strcpy(buf, "IsTaskCompleted"), XS_Client_IsTaskCompleted, file, "$$");
newXSproto(strcpy(buf, "IsTaskActive"), XS_Client_IsTaskActive, file, "$$");
newXSproto(strcpy(buf, "IsTaskActivityActive"), XS_Client_IsTaskActivityActive, file, "$$$");
newXSproto(strcpy(buf, "GetTaskActivityDoneCount"), XS_Client_GetTaskActivityDoneCount, file, "$$$");
newXSproto(strcpy(buf, "GetCorpseCount"), XS_Client_GetCorpseCount, file, "$");
newXSproto(strcpy(buf, "GetCorpseID"), XS_Client_GetCorpseID, file, "$$");
newXSproto(strcpy(buf, "GetCorpseItemAt"), XS_Client_GetCorpseItemAt, file, "$$$");
@@ -6194,6 +6342,9 @@ XS(boot_Client)
newXSproto(strcpy(buf, "SendTargetCommand"), XS_Client_SendTargetCommand, file, "$$");
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;
}
+251 -41
View File
@@ -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")) {
@@ -2926,7 +2941,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 +2967,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 +2993,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 +3019,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 +3045,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 +3071,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 +3097,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")) {
@@ -3956,7 +3971,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;
}
@@ -6259,7 +6277,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 +6304,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;
@@ -7140,7 +7158,7 @@ XS(XS_Mob_SendIllusion)
uint32 drakkin_heritage = 0xFFFFFFFF;
uint32 drakkin_tattoo = 0xFFFFFFFF;
uint32 drakkin_details = 0xFFFFFFFF;
float size = 0xFFFFFFFF;
float size = -1.0f;
if (sv_derived_from(ST(0), "Mob")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
@@ -8137,6 +8155,191 @@ XS(XS_Mob_GetFlurryChance)
XSRETURN(1);
}
XS(XS_Mob_GetSpellStat); /* prototype to pass -Wmissing-prototypes */
XS(XS_Mob_GetSpellStat)
{
dXSARGS;
if (items < 3 || items > 4)
Perl_croak(aTHX_ "Usage: Mob::GetSpellStat(THIS, itemid, stat, slot)");
{
Mob * THIS;
int32 RETVAL;
uint32 spellid = (uint32)SvUV(ST(1));
Const_char * stat = (Const_char *)SvPV_nolen(ST(2));
uint8 slot = (uint8)SvUV(ST(3));
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.");
if (items > 4) { slot = 0; }
RETVAL = THIS->GetSpellStat(spellid, stat, slot);
XSprePUSH; PUSHi((IV)RETVAL);
}
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;
}
#ifdef __cplusplus
extern "C"
#endif
@@ -8400,7 +8603,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, "$$;$$$$$$");
@@ -8433,10 +8637,16 @@ 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, "$$");
XSRETURN_YES;
}
+106 -2
View File
@@ -1991,6 +1991,32 @@ XS(XS_NPC_SetSpellFocusDMG)
XSRETURN_EMPTY;
}
XS(XS_NPC_GetSpellFocusDMG); /* prototype to pass -Wmissing-prototypes */
XS(XS_NPC_GetSpellFocusDMG)
{
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: NPC::GetSpellFocusDMG(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->GetSpellFocusDMG();
XSprePUSH; PUSHu((UV)RETVAL);
}
XSRETURN(1);
}
XS(XS_NPC_SetSpellFocusHeal); /* prototype to pass -Wmissing-prototypes */
XS(XS_NPC_SetSpellFocusHeal)
{
@@ -2015,6 +2041,32 @@ XS(XS_NPC_SetSpellFocusHeal)
XSRETURN_EMPTY;
}
XS(XS_NPC_GetSpellFocusHeal); /* prototype to pass -Wmissing-prototypes */
XS(XS_NPC_GetSpellFocusHeal)
{
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: NPC::GetSpellFocusHeal(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->GetSpellFocusHeal();
XSprePUSH; PUSHu((UV)RETVAL);
}
XSRETURN(1);
}
XS(XS_NPC_GetSlowMitigation); /* prototype to pass -Wmissing-prototypes */
XS(XS_NPC_GetSlowMitigation)
{
@@ -2145,6 +2197,54 @@ XS(XS_NPC_GetScore)
XSRETURN(1);
}
XS(XS_NPC_SetMerchantProbability);
XS(XS_NPC_SetMerchantProbability) {
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: NPC::SetMerchantProbability(THIS, Probability)");
{
NPC *THIS;
uint8 Probability = (uint8)SvIV(ST(1));
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.");
THIS->SetMerchantProbability(Probability);
}
XSRETURN_EMPTY;
}
XS(XS_NPC_GetMerchantProbability);
XS(XS_NPC_GetMerchantProbability) {
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: NPC::GetMerchantProbability(THIS)");
{
NPC *THIS;
uint8 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 == NULL)
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
RETVAL = THIS->GetMerchantProbability();
XSprePUSH; PUSHu((UV)RETVAL);
}
XSRETURN(1);
}
#ifdef __cplusplus
extern "C"
#endif
@@ -2238,11 +2338,15 @@ XS(boot_NPC)
newXSproto(strcpy(buf, "RemoveAISpell"), XS_NPC_RemoveSpellFromNPCList, file, "$$");
newXSproto(strcpy(buf, "SetSpellFocusDMG"), XS_NPC_SetSpellFocusDMG, file, "$$");
newXSproto(strcpy(buf, "SetSpellFocusHeal"), XS_NPC_SetSpellFocusHeal, file, "$$");
newXSproto(strcpy(buf, "GetSlowMitigation"), XS_NPC_GetAttackSpeed, file, "$");
newXSproto(strcpy(buf, "GetAttackSpeed"), XS_NPC_GetSlowMitigation, file, "$");
newXSproto(strcpy(buf, "GetSpellFocusDMG"), XS_NPC_GetSpellFocusDMG, file, "$");
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, "GetAccuracyRating"), XS_NPC_GetAccuracyRating, 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, "$");
XSRETURN_YES;
}
+105
View File
@@ -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
@@ -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));
}
+1 -1
View File
@@ -26,7 +26,7 @@
#undef seed
#endif
#include "../common/Item.h"
#include "../common/item.h"
#ifdef THIS /* this macro seems to leak out on some systems */
#undef THIS
+1 -1
View File
@@ -22,7 +22,7 @@
#include "entity.h"
#include "../common/opcodemgr.h"
#include "../common/packet_dump.h"
#include "../common/MiscFunctions.h"
#include "../common/misc_functions.h"
PerlPacket::PerlPacket(const char *opcode, uint32 length) {
SetOpcode(opcode);
+68 -82
View File
@@ -16,10 +16,6 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
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 <string.h>
#ifdef _WINDOWS
#include <process.h>
@@ -32,16 +28,12 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
#endif
#include "../common/StringUtil.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 "../common/string_util.h"
#include "entity.h"
#include "masterentity.h"
#include "petitions.h"
#include "worldserver.h"
@@ -49,7 +41,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;
@@ -216,100 +207,95 @@ void PetitionList::UpdatePetition(Petition* pet) {
}
void ZoneDatabase::DeletePetitionFromDB(Petition* wpet) {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
uint32 affected_rows = 0;
uint8 checkedout = 0;
if (wpet->CheckedOut()) checkedout = 0;
else checkedout = 1;
if (!RunQuery(query, MakeAnyLenString(&query, "DELETE from petitions where petid = %i", wpet->GetID()), errbuf, 0, &affected_rows)) {
LogFile->write(EQEMuLog::Error, "Error in DeletePetitionFromDB query '%s': %s", query, errbuf);
}
safe_delete_array(query);
return;
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) {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
uint32 affected_rows = 0;
uint8 checkedout = 0;
if (wpet->CheckedOut()) checkedout = 1;
else checkedout = 0;
if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE petitions set gmtext = '%s', lastgm = '%s', urgency = %i, checkouts = %i, unavailables = %i, ischeckedout = %i where petid = %i", wpet->GetGMText(), wpet->GetLastGM(), wpet->GetUrgency(), wpet->GetCheckouts(), wpet->GetUnavails(), checkedout, wpet->GetID()), errbuf, 0, &affected_rows)) {
LogFile->write(EQEMuLog::Error, "Error in UpdatePetitionToDB query '%s': %s", query, errbuf);
}
safe_delete_array(query);
return;
std::string query = StringFormat("UPDATE petitions SET gmtext = '%s', lastgm = '%s', urgency = %i, "
"checkouts = %i, unavailables = %i, ischeckedout = %i "
"WHERE petid = %i",
wpet->GetGMText(), wpet->GetLastGM(), wpet->GetUrgency(),
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)
{
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
uint32 affected_rows = 0;
uint8 checkedout = 0;
if (wpet->CheckedOut())
checkedout = 1;
else
checkedout = 0;
uint32 len = strlen(wpet->GetPetitionText());
char* petitiontext = new char[2*len+1];
memset(petitiontext, 0, 2*len+1);
DoEscapeString(petitiontext, wpet->GetPetitionText(), len);
if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO petitions (petid, charname, accountname, lastgm, petitiontext, zone, urgency, charclass, charrace, charlevel, checkouts, unavailables, ischeckedout, senttime, gmtext) values (%i,'%s','%s','%s','%s',%i,%i,%i,%i,%i,%i,%i,%i,%i, '%s')", wpet->GetID(), wpet->GetCharName(), wpet->GetAccountName(), wpet->GetLastGM(), petitiontext, wpet->GetZone(), wpet->GetUrgency(), wpet->GetCharClass(), wpet->GetCharRace(), wpet->GetCharLevel(), wpet->GetCheckouts(), wpet->GetUnavails(), checkedout, wpet->GetSentTime(), wpet->GetGMText()), errbuf, 0, &affected_rows)) {
LogFile->write(EQEMuLog::Error, "Error in InsertPetitionToDB query '%s': %s", query, errbuf);
std::string query = StringFormat("INSERT INTO petitions "
"(petid, charname, accountname, lastgm, "
"petitiontext, zone, urgency, charclass, "
"charrace, charlevel, checkouts, unavailables, "
"ischeckedout, senttime, gmtext) "
"VALUES (%i, '%s', '%s', '%s', '%s', "
"%i, %i, %i, %i, %i, "
"%i, %i, %i, %i, '%s')",
wpet->GetID(), wpet->GetCharName(), wpet->GetAccountName(), wpet->GetLastGM(),
petitiontext, wpet->GetZone(), wpet->GetUrgency(), wpet->GetCharClass(),
wpet->GetCharRace(), wpet->GetCharLevel(), wpet->GetCheckouts(), wpet->GetUnavails(),
wpet->CheckedOut()? 1: 0, wpet->GetSentTime(), wpet->GetGMText());
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;
}
safe_delete_array(petitiontext);
safe_delete_array(query);
#if EQDEBUG >= 5
LogFile->write(EQEMuLog::Debug, "New petition created");
#endif
return;
}
void ZoneDatabase::RefreshPetitionsFromDB()
{
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
Petition* newpet;
if (RunQuery(query, MakeAnyLenString(&query, "SELECT petid, charname, accountname, lastgm, petitiontext, zone, urgency, charclass, charrace, charlevel, checkouts, unavailables, ischeckedout, senttime, gmtext from petitions order by petid"), errbuf, &result))
{
safe_delete_array(query);
while ((row = mysql_fetch_row(result))) {
newpet = new Petition(atoi(row[0]));
newpet->SetCName(row[1]);
newpet->SetAName(row[2]);
newpet->SetLastGM(row[3]);
newpet->SetPetitionText(row[4]);
newpet->SetZone(atoi(row[5]));
newpet->SetUrgency(atoi(row[6]));
newpet->SetClass(atoi(row[7]));
newpet->SetRace(atoi(row[8]));
newpet->SetLevel(atoi(row[9]));
newpet->SetCheckouts(atoi(row[10]));
newpet->SetUnavails(atoi(row[11]));
newpet->SetSentTime2(atol(row[13]));
newpet->SetGMText(row[14]);
std::cout << "Petition " << row[0] << " pettime = " << newpet->GetSentTime() << std::endl;
if (atoi(row[12]) == 1) newpet->SetCheckedOut(true);
else newpet->SetCheckedOut(false);
petition_list.AddPetition(newpet);
}
mysql_free_result(result);
}
else {
LogFile->write(EQEMuLog::Error, "Error in RefreshPetitionsFromDB query '%s': %s", query, errbuf);
safe_delete_array(query);
std::string query = "SELECT petid, charname, accountname, lastgm, petitiontext, "
"zone, urgency, charclass, charrace, charlevel, checkouts, "
"unavailables, ischeckedout, senttime, gmtext "
"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;
}
return;
for (auto row = results.begin(); row != results.end(); ++row) {
newpet = new Petition(atoi(row[0]));
newpet->SetCName(row[1]);
newpet->SetAName(row[2]);
newpet->SetLastGM(row[3]);
newpet->SetPetitionText(row[4]);
newpet->SetZone(atoi(row[5]));
newpet->SetUrgency(atoi(row[6]));
newpet->SetClass(atoi(row[7]));
newpet->SetRace(atoi(row[8]));
newpet->SetLevel(atoi(row[9]));
newpet->SetCheckouts(atoi(row[10]));
newpet->SetUnavails(atoi(row[11]));
newpet->SetSentTime2(atol(row[13]));
newpet->SetGMText(row[14]);
if (atoi(row[12]) == 1)
newpet->SetCheckedOut(true);
else
newpet->SetCheckedOut(false);
petition_list.AddPetition(newpet);
}
}
+5 -3
View File
@@ -19,11 +19,13 @@
#define PETITIONS_H
#include "../common/linked_list.h"
#include "../common/misc_functions.h"
#include "../common/mutex.h"
#include "../common/types.h"
#include "zonedb.h"
#include "client.h"
#include "../common/Mutex.h"
#include "../common/MiscFunctions.h"
#include "zonedb.h"
class Client;
class Petition
{
+97 -130
View File
@@ -15,30 +15,26 @@
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/misc_functions.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/StringUtil.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 "worldserver.h"
#include "zonedb.h"
#ifndef WIN32
#include <stdlib.h>
#include "../common/unix.h"
#endif
#include "StringIDs.h"
///////////////////////////////////////////////////////////////////////////////
// pet related functions
const char *GetRandPetName()
{
@@ -362,31 +358,34 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
// handle monster summoning pet appearance
if(record.monsterflag) {
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result = nullptr;
MYSQL_ROW row = nullptr;
uint32 monsterid;
uint32 monsterid = 0;
// get a random npc id from the spawngroups assigned to this zone
if (database.RunQuery(query, MakeAnyLenString(&query,
"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()), errbuf, &result))
{
row = mysql_fetch_row(result);
if (row)
monsterid = atoi(row[0]);
else
monsterid = 567; // since we don't have any monsters, just make it look like an earth pet for now
}
else { // if the database query failed
LogFile->write(EQEMuLog::Error, "Error querying database for monster summoning pet in zone %s (%s)", zone->GetShortName(), errbuf);
monsterid = 567;
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);
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());
}
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;
// give the summoned pet the attributes of the monster we found
const NPCType* monster = database.GetNPCType(monsterid);
if(monster) {
@@ -396,12 +395,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;
}
else {
} else
LogFile->write(EQEMuLog::Error, "Error loading NPC data for monster summoning pet (NPC ID %d)", monsterid);
}
safe_delete_array(query);
}
//this takes ownership of the npc_type data
@@ -450,46 +446,35 @@ bool ZoneDatabase::GetPetEntry(const char *pet_type, PetRecord *into) {
}
bool ZoneDatabase::GetPoweredPetEntry(const char *pet_type, int16 petpower, PetRecord *into) {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
uint32 querylen = 0;
MYSQL_RES *result;
MYSQL_ROW row;
std::string query;
if (petpower <= 0) {
querylen = MakeAnyLenString(&query,
"SELECT npcID, temp, petpower, petcontrol, petnaming, monsterflag, equipmentset FROM pets "
"WHERE type='%s' AND petpower<=0", pet_type);
}
else {
querylen = MakeAnyLenString(&query,
"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);
}
if (petpower <= 0)
query = StringFormat("SELECT npcID, temp, petpower, petcontrol, petnaming, monsterflag, equipmentset "
"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;
}
if (RunQuery(query, querylen, errbuf, &result)) {
safe_delete_array(query);
if (mysql_num_rows(result) == 1) {
row = mysql_fetch_row(result);
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();
mysql_free_result(result);
return(true);
}
mysql_free_result(result);
}
else {
LogFile->write(EQEMuLog::Error, "Error in GetPoweredPetEntry query '%s': %s", query, errbuf);
safe_delete_array(query);
}
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]);
return true;
}
Mob* Mob::GetPet() {
@@ -657,11 +642,6 @@ bool ZoneDatabase::GetBasePetItems(int32 equipmentset, uint32 *items) {
// A slot will only get an item put in it if it is empty. That way
// an equipmentset can overload a slot for the set(s) it includes.
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
uint32 querylen = 0;
MYSQL_RES *result;
MYSQL_ROW row;
int depth = 0;
int32 curset = equipmentset;
int32 nextset = -1;
@@ -673,56 +653,43 @@ bool ZoneDatabase::GetBasePetItems(int32 equipmentset, uint32 *items) {
// query pets_equipmentset_entries with the set_id and loop over
// 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) {
if (RunQuery(query,
MakeAnyLenString(&query, "SELECT nested_set FROM pets_equipmentset WHERE set_id='%s'", curset),
errbuf, &result))
{
safe_delete_array(query);
if (mysql_num_rows(result) == 1) {
row = mysql_fetch_row(result);
nextset = atoi(row[0]);
mysql_free_result(result);
if (RunQuery(query,
MakeAnyLenString(&query, "SELECT slot, item_id FROM pets_equipmentset_entries WHERE set_id='%s'", curset),
errbuf, &result))
{
safe_delete_array(query);
while ((row = mysql_fetch_row(result)))
{
slot = atoi(row[0]);
if (slot >= EmuConstants::EQUIPMENT_SIZE)
continue;
if (items[slot] == 0)
items[slot] = atoi(row[1]);
}
mysql_free_result(result);
}
else {
LogFile->write(EQEMuLog::Error, "Error in GetBasePetItems query '%s': %s", query, errbuf);
safe_delete_array(query);
}
curset = nextset;
depth++;
}
else
{
// invalid set reference, it doesn't exist
LogFile->write(EQEMuLog::Error, "Error in GetBasePetItems equipment set '%d' does not exist", curset);
mysql_free_result(result);
return false;
}
}
else
{
LogFile->write(EQEMuLog::Error, "Error in GetBasePetItems query '%s': %s", query, errbuf);
safe_delete_array(query);
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;
}
} // end while
}
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;
}
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]);
if (slot >= EmuConstants::EQUIPMENT_SIZE)
continue;
if (items[slot] == 0)
items[slot] = atoi(row[1]);
}
}
curset = nextset;
depth++;
}
return true;
}
+25 -62
View File
@@ -1,6 +1,6 @@
#include "../common/debug.h"
#include "../common/StringUtil.h"
#include "QGlobals.h"
#include "../common/string_util.h"
#include "qglobals.h"
#include "masterentity.h"
#include "zone.h"
#include "zonedb.h"
@@ -51,7 +51,7 @@ void QGlobalCache::Combine(std::list<QGlobal> &cacheA, std::list<QGlobal> cacheB
void QGlobalCache::GetQGlobals(std::list<QGlobal> &globals, NPC *n, Client *c, Zone *z) {
globals.clear();
QGlobalCache *npc_c = nullptr;
QGlobalCache *char_c = nullptr;
QGlobalCache *zone_c = nullptr;
@@ -139,75 +139,38 @@ void QGlobalCache::PurgeExpiredGlobals()
void QGlobalCache::LoadByNPCID(uint32 npcID)
{
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if (database.RunQuery(query, MakeAnyLenString(&query, "select name, charid, npcid, zoneid, value, expdate"
" from quest_globals where npcid = %d", npcID), errbuf, &result))
{
while((row = mysql_fetch_row(result)))
{
AddGlobal(0, QGlobal(std::string(row[0]), atoi(row[1]), atoi(row[2]), atoi(row[3]), row[4], row[5]?atoi(row[5]):0xFFFFFFFF));
}
mysql_free_result(result);
}
safe_delete_array(query);
std::string query = StringFormat("SELECT name, charid, npcid, zoneid, value, expdate "
"FROM quest_globals WHERE npcid = %d", npcID);
LoadBy(query);
}
void QGlobalCache::LoadByCharID(uint32 charID)
{
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if (database.RunQuery(query, MakeAnyLenString(&query, "select name, charid, npcid, zoneid, value, expdate from"
" quest_globals where charid = %d && npcid = 0", charID), errbuf, &result))
{
while((row = mysql_fetch_row(result)))
{
AddGlobal(0, QGlobal(std::string(row[0]), atoi(row[1]), atoi(row[2]), atoi(row[3]), row[4], row[5]?atoi(row[5]):0xFFFFFFFF));
}
mysql_free_result(result);
}
safe_delete_array(query);
std::string query = StringFormat("SELECT name, charid, npcid, zoneid, value, expdate "
"FROM quest_globals WHERE charid = %d && npcid = 0", charID);
LoadBy(query);
}
void QGlobalCache::LoadByZoneID(uint32 zoneID)
{
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if (database.RunQuery(query, MakeAnyLenString(&query, "select name, charid, npcid, zoneid, value, expdate from quest_globals"
" where zoneid = %d && npcid = 0 && charid = 0", zoneID), errbuf, &result))
{
while((row = mysql_fetch_row(result)))
{
AddGlobal(0, QGlobal(std::string(row[0]), atoi(row[1]), atoi(row[2]), atoi(row[3]), row[4], row[5]?atoi(row[5]):0xFFFFFFFF));
}
mysql_free_result(result);
}
safe_delete_array(query);
std::string query = StringFormat("SELECT name, charid, npcid, zoneid, value, expdate "
"FROM quest_globals WHERE zoneid = %d && npcid = 0 && charid = 0", zoneID);
LoadBy(query);
}
void QGlobalCache::LoadByGlobalContext()
{
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
std::string query = "SELECT name, charid, npcid, zoneid, value, expdate "
"FROM quest_globals WHERE zoneid = 0 && npcid = 0 && charid = 0";
LoadBy(query);
}
if (database.RunQuery(query, MakeAnyLenString(&query, "select name, charid, npcid, zoneid, value, expdate from quest_globals"
" where zoneid = 0 && npcid = 0 && charid = 0"), errbuf, &result))
{
while((row = mysql_fetch_row(result)))
{
AddGlobal(0, QGlobal(std::string(row[0]), atoi(row[1]), atoi(row[2]), atoi(row[3]), row[4], row[5]?atoi(row[5]):0xFFFFFFFF));
}
mysql_free_result(result);
}
safe_delete_array(query);
void QGlobalCache::LoadBy(const std::string &query)
{
auto results = database.QueryDatabase(query);
if (!results.Success())
return;
for (auto row = results.begin(); row != results.end(); ++row)
AddGlobal(0, QGlobal(row[0], atoi(row[1]), atoi(row[2]), atoi(row[3]), row[4], row[5] ? atoi(row[5]) : 0xFFFFFFFF));
}
+1
View File
@@ -42,6 +42,7 @@ public:
void LoadByZoneID(uint32 zoneID); //zone
void LoadByGlobalContext(); //zone
protected:
void LoadBy(const std::string &query);
std::list<QGlobal> qGlobalBucket;
};
+52
View File
@@ -0,0 +1,52 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2014 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/servertalk.h"
#include "../common/string_util.h"
#include "queryserv.h"
#include "worldserver.h"
#include "net.h"
#include <iostream>
extern WorldServer worldserver;
extern QueryServ* QServ;
QueryServ::QueryServ(){
}
QueryServ::~QueryServ(){
}
void QueryServ::SendQuery(std::string Query)
{
ServerPacket* pack = new ServerPacket(ServerOP_QSSendQuery, Query.length() + 5);
pack->WriteUInt32(Query.length()); /* Pack Query String Size so it can be dynamically broken out at queryserv */
pack->WriteString(Query.c_str()); /* Query */
worldserver.SendPacket(pack);
safe_delete(pack);
}
void QueryServ::PlayerLogEvent(int Event_Type, int Character_ID, std::string Event_Desc)
{
std::string query = StringFormat(
"INSERT INTO `qs_player_events` (event, char_id, event_desc, time) VALUES (%i, %i, '%s', UNIX_TIMESTAMP(now()))",
Event_Type, Character_ID, EscapeString(Event_Desc).c_str());
SendQuery(query);
}
+35
View File
@@ -0,0 +1,35 @@
#ifndef QUERYSERV_ZONE_H
#define QUERYSERV_ZONE_H
/*
enum PlayerGenericLogEventTypes
These Enums are for the generic logging table that are not complex and require more advanced logic
*/
enum PlayerGenericLogEventTypes {
Player_Log_Quest = 1,
Player_Log_Zoning,
Player_Log_Deaths,
Player_Log_Connect_State,
Player_Log_Levels,
Player_Log_Keyring_Addition,
Player_Log_QGlobal_Update,
Player_Log_Task_Updates,
Player_Log_AA_Purchases,
Player_Log_Trade_Skill_Events,
Player_Log_Issued_Commands,
Player_Log_Money_Transactions,
Player_Log_Alternate_Currency_Transactions,
};
class QueryServ{
public:
QueryServ();
~QueryServ();
void SendQuery(std::string Query);
void PlayerLogEvent(int Event_Type, int Character_ID, std::string Event_Desc);
};
#endif /* QUERYSERV_ZONE_H */
+1 -1
View File
@@ -29,7 +29,7 @@
#include "../common/unix.h"
#endif
#include "Quest.h"
#include "quest.h"
pquest_entry Quest::m_pQuests;
int Quest::m_nQuests;
View File
@@ -20,6 +20,7 @@
#define _EQE_QUESTINTERFACE_H
#include "../common/types.h"
#include "../common/any.h"
#include "event_codes.h"
class ItemInst;
@@ -29,19 +30,19 @@ class NPC;
class QuestInterface {
public:
virtual int EventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) { return 0; }
std::vector<EQEmu::Any> *extra_pointers) { return 0; }
virtual int EventGlobalNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) { return 0; }
std::vector<EQEmu::Any> *extra_pointers) { return 0; }
virtual int EventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) { return 0; }
std::vector<EQEmu::Any> *extra_pointers) { return 0; }
virtual int EventGlobalPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) { return 0; }
std::vector<EQEmu::Any> *extra_pointers) { return 0; }
virtual int EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) { return 0; }
std::vector<EQEmu::Any> *extra_pointers) { return 0; }
virtual int EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers) { return 0; }
std::vector<EQEmu::Any> *extra_pointers) { return 0; }
virtual int EventEncounter(QuestEventID evt, std::string encounter_name, uint32 extra_data,
std::vector<void*> *extra_pointers) { return 0; }
std::vector<EQEmu::Any> *extra_pointers) { return 0; }
virtual bool HasQuestSub(uint32 npcid, QuestEventID evt) { return false; }
virtual bool HasGlobalQuestSub(QuestEventID evt) { return false; }
@@ -60,13 +61,13 @@ public:
virtual void LoadEncounterScript(std::string filename, std::string encounter_name) { }
virtual int DispatchEventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) { return 0; }
std::vector<EQEmu::Any> *extra_pointers) { return 0; }
virtual int DispatchEventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) { return 0; }
std::vector<EQEmu::Any> *extra_pointers) { return 0; }
virtual int DispatchEventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) { return 0; }
std::vector<EQEmu::Any> *extra_pointers) { return 0; }
virtual int DispatchEventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers) { return 0; }
std::vector<EQEmu::Any> *extra_pointers) { return 0; }
virtual void AddVar(std::string name, std::string val) { }
virtual std::string GetVar(std::string name) { return std::string(); }
@@ -17,10 +17,10 @@
*/
#include "../common/debug.h"
#include "../common/MiscFunctions.h"
#include "../common/misc_functions.h"
#include "../common/features.h"
#include "QuestParserCollection.h"
#include "QuestInterface.h"
#include "quest_parser_collection.h"
#include "quest_interface.h"
#include "zone.h"
#include "questmgr.h"
@@ -234,7 +234,7 @@ bool QuestParserCollection::ItemHasQuestSub(ItemInst *itm, QuestEventID evt) {
}
int QuestParserCollection::EventNPC(QuestEventID evt, NPC *npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
int rd = DispatchEventNPC(evt, npc, init, data, extra_data, extra_pointers);
int rl = EventNPCLocal(evt, npc, init, data, extra_data, extra_pointers);
int rg = EventNPCGlobal(evt, npc, init, data, extra_data, extra_pointers);
@@ -252,7 +252,7 @@ int QuestParserCollection::EventNPC(QuestEventID evt, NPC *npc, Mob *init, std::
}
int QuestParserCollection::EventNPCLocal(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
std::map<uint32, uint32>::iterator iter = _npc_quest_status.find(npc->GetNPCTypeID());
if(iter != _npc_quest_status.end()) {
//loaded or failed to load
@@ -275,7 +275,7 @@ int QuestParserCollection::EventNPCLocal(QuestEventID evt, NPC* npc, Mob *init,
}
int QuestParserCollection::EventNPCGlobal(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
if(_global_npc_quest_status != QuestUnloaded && _global_npc_quest_status != QuestFailedToLoad) {
std::map<uint32, QuestInterface*>::iterator qiter = _interfaces.find(_global_npc_quest_status);
return qiter->second->EventGlobalNPC(evt, npc, init, data, extra_data, extra_pointers);
@@ -294,7 +294,7 @@ int QuestParserCollection::EventNPCGlobal(QuestEventID evt, NPC* npc, Mob *init,
}
int QuestParserCollection::EventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
int rd = DispatchEventPlayer(evt, client, data, extra_data, extra_pointers);
int rl = EventPlayerLocal(evt, client, data, extra_data, extra_pointers);
int rg = EventPlayerGlobal(evt, client, data, extra_data, extra_pointers);
@@ -312,7 +312,7 @@ int QuestParserCollection::EventPlayer(QuestEventID evt, Client *client, std::st
}
int QuestParserCollection::EventPlayerLocal(QuestEventID evt, Client *client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
if(_player_quest_status == QuestUnloaded) {
std::string filename;
QuestInterface *qi = GetQIByPlayerQuest(filename);
@@ -331,7 +331,7 @@ int QuestParserCollection::EventPlayerLocal(QuestEventID evt, Client *client, st
}
int QuestParserCollection::EventPlayerGlobal(QuestEventID evt, Client *client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
if(_global_player_quest_status == QuestUnloaded) {
std::string filename;
QuestInterface *qi = GetQIByGlobalPlayerQuest(filename);
@@ -350,7 +350,7 @@ int QuestParserCollection::EventPlayerGlobal(QuestEventID evt, Client *client, s
}
int QuestParserCollection::EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
std::string item_script;
if(item->GetItem()->ScriptFileID != 0) {
item_script = "script_";
@@ -396,7 +396,7 @@ int QuestParserCollection::EventItem(QuestEventID evt, Client *client, ItemInst
}
int QuestParserCollection::EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
std::map<uint32, uint32>::iterator iter = _spell_quest_status.find(spell_id);
if(iter != _spell_quest_status.end()) {
//loaded or failed to load
@@ -431,7 +431,7 @@ int QuestParserCollection::EventSpell(QuestEventID evt, NPC* npc, Client *client
}
int QuestParserCollection::EventEncounter(QuestEventID evt, std::string encounter_name, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
auto iter = _encounter_quest_status.find(encounter_name);
if(iter != _encounter_quest_status.end()) {
//loaded or failed to load
@@ -600,9 +600,8 @@ QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string
}
QuestInterface *QuestParserCollection::GetQIByPlayerQuest(std::string &filename) {
if(!zone)
return nullptr;
if(!zone || !zone->IsLoaded())
return nullptr;
//first look for /quests/zone/player_v[instance_version].ext (precedence)
filename = "quests/";
@@ -975,7 +974,7 @@ void QuestParserCollection::GetErrors(std::list<std::string> &err) {
}
int QuestParserCollection::DispatchEventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
int ret = 0;
auto iter = _load_precedence.begin();
while(iter != _load_precedence.end()) {
@@ -989,7 +988,7 @@ int QuestParserCollection::DispatchEventNPC(QuestEventID evt, NPC* npc, Mob *ini
}
int QuestParserCollection::DispatchEventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
int ret = 0;
auto iter = _load_precedence.begin();
while(iter != _load_precedence.end()) {
@@ -1003,7 +1002,7 @@ int QuestParserCollection::DispatchEventPlayer(QuestEventID evt, Client *client,
}
int QuestParserCollection::DispatchEventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data,
uint32 extra_data, std::vector<void*> *extra_pointers) {
uint32 extra_data, std::vector<EQEmu::Any> *extra_pointers) {
int ret = 0;
auto iter = _load_precedence.begin();
while(iter != _load_precedence.end()) {
@@ -1017,7 +1016,7 @@ int QuestParserCollection::DispatchEventItem(QuestEventID evt, Client *client, I
}
int QuestParserCollection::DispatchEventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers) {
std::vector<EQEmu::Any> *extra_pointers) {
int ret = 0;
auto iter = _load_precedence.begin();
while(iter != _load_precedence.end()) {
@@ -20,10 +20,10 @@
#define _EQE_QUESTPARSERCOLLECTION_H
#include "../common/types.h"
#include "../common/Item.h"
#include "../common/item.h"
#include "masterentity.h"
#include "QuestInterface.h"
#include "quest_interface.h"
#include <string.h>
#include <string>
@@ -51,15 +51,15 @@ public:
bool ItemHasQuestSub(ItemInst *itm, QuestEventID evt);
int EventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers = nullptr);
std::vector<EQEmu::Any> *extra_pointers = nullptr);
int EventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers = nullptr);
std::vector<EQEmu::Any> *extra_pointers = nullptr);
int EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers = nullptr);
std::vector<EQEmu::Any> *extra_pointers = nullptr);
int EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers = nullptr);
std::vector<EQEmu::Any> *extra_pointers = nullptr);
int EventEncounter(QuestEventID evt, std::string encounter_name, uint32 extra_data,
std::vector<void*> *extra_pointers = nullptr);
std::vector<EQEmu::Any> *extra_pointers = nullptr);
void GetErrors(std::list<std::string> &err);
@@ -69,10 +69,10 @@ private:
bool PlayerHasQuestSubLocal(QuestEventID evt);
bool PlayerHasQuestSubGlobal(QuestEventID evt);
int EventNPCLocal(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, std::vector<void*> *extra_pointers);
int EventNPCGlobal(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, std::vector<void*> *extra_pointers);
int EventPlayerLocal(QuestEventID evt, Client *client, std::string data, uint32 extra_data, std::vector<void*> *extra_pointers);
int EventPlayerGlobal(QuestEventID evt, Client *client, std::string data, uint32 extra_data, std::vector<void*> *extra_pointers);
int EventNPCLocal(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, std::vector<EQEmu::Any> *extra_pointers);
int EventNPCGlobal(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, std::vector<EQEmu::Any> *extra_pointers);
int EventPlayerLocal(QuestEventID evt, Client *client, std::string data, uint32 extra_data, std::vector<EQEmu::Any> *extra_pointers);
int EventPlayerGlobal(QuestEventID evt, Client *client, std::string data, uint32 extra_data, std::vector<EQEmu::Any> *extra_pointers);
QuestInterface *GetQIByNPCQuest(uint32 npcid, std::string &filename);
QuestInterface *GetQIByGlobalNPCQuest(std::string &filename);
@@ -83,13 +83,13 @@ private:
QuestInterface *GetQIByEncounterQuest(std::string encounter_name, std::string &filename);
int DispatchEventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
int DispatchEventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
int DispatchEventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
int DispatchEventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers);
std::vector<EQEmu::Any> *extra_pointers);
std::map<uint32, QuestInterface*> _interfaces;
std::map<uint32, std::string> _extensions;
+255 -317
View File
@@ -16,78 +16,37 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
Assuming you want to add a new perl quest function named joe
that takes 1 integer argument....
1. Add the prototype to the quest manager:
questmgr.h: add (~line 50)
void joe(int arg);
2. Define the actual function in questmgr.cpp:
void QuestManager::joe(int arg) {
//... do something
}
3. Copy one of the XS routines in perlparser.cpp, preferably
one with the same number of arguments as your routine. Rename
as needed.
Finally, add your routine to the list at the bottom of perlparser.cpp
4.
If you want it to work in old mode perl and .qst, edit parser.cpp
Parser::ExCommands (~line 777)
else if (!strcmp(command,"joe")) {
quest_manager.joe(atoi(arglist[0]));
}
And then at then end of embparser.cpp, add:
"sub joe{push(@cmd_queue,{func=>'joe',args=>join(',',@_)});}"
*/
#include "../common/debug.h"
#include "entity.h"
#include "masterentity.h"
#include <limits.h>
#include <sstream>
#include <iostream>
#include <list>
#include "worldserver.h"
#include "net.h"
#include "../common/skills.h"
#include "../common/classes.h"
#include "../common/races.h"
#include "zonedb.h"
#include "../common/debug.h"
#include "../common/rulesys.h"
#include "../common/skills.h"
#include "../common/spdat.h"
#include "../common/packet_functions.h"
#include "../common/StringUtil.h"
#include "spawn2.h"
#include "zone.h"
#include "../common/string_util.h"
#include "entity.h"
#include "event_codes.h"
#include "guild_mgr.h"
#include "../common/rulesys.h"
#include "QGlobals.h"
#include "QuestParserCollection.h"
#include "net.h"
#include "qglobals.h"
#include "queryserv.h"
#include "questmgr.h"
#include "quest_parser_collection.h"
#include "spawn2.h"
#include "worldserver.h"
#include "zone.h"
#include "zonedb.h"
#include <iostream>
#include <limits.h>
#include <list>
#ifdef BOTS
#include "bot.h"
#endif
extern QueryServ* QServ;
extern Zone* zone;
extern WorldServer worldserver;
extern EntityList entity_list;
#include "questmgr.h"
//declare our global instance
QuestManager quest_manager;
#define QuestManagerCurrentQuestVars() \
@@ -95,6 +54,7 @@ QuestManager quest_manager;
Client *initiator = nullptr; \
ItemInst* questitem = nullptr; \
bool depop_npc = false; \
std::string encounter; \
do { \
if(!quests_running_.empty()) { \
running_quest e = quests_running_.top(); \
@@ -102,6 +62,7 @@ QuestManager quest_manager;
initiator = e.initiator; \
questitem = e.questitem; \
depop_npc = e.depop_npc; \
encounter = e.encounter; \
} \
} while(0)
@@ -151,12 +112,13 @@ void QuestManager::Process() {
}
}
void QuestManager::StartQuest(Mob *_owner, Client *_initiator, ItemInst* _questitem) {
void QuestManager::StartQuest(Mob *_owner, Client *_initiator, ItemInst* _questitem, std::string encounter) {
running_quest run;
run.owner = _owner;
run.initiator = _initiator;
run.questitem = _questitem;
run.depop_npc = false;
run.encounter = encounter;
quests_running_.push(run);
}
@@ -173,7 +135,6 @@ void QuestManager::EndQuest() {
else
++cur;
}
run.owner->Depop();
}
quests_running_.pop();
@@ -448,7 +409,7 @@ void QuestManager::settimer(const char *timer_name, int seconds) {
end = QTimerList.end();
while (cur != end) {
if(cur->mob && cur->mob == owner && cur->name == timer_name)
if(cur->mob && cur->mob == owner && cur->name == timer_name)
{
cur->Timer_.Enable();
cur->Timer_.Start(seconds * 1000, false);
@@ -472,7 +433,7 @@ void QuestManager::settimerMS(const char *timer_name, int milliseconds) {
end = QTimerList.end();
while (cur != end) {
if(cur->mob && cur->mob == owner && cur->name == timer_name)
if(cur->mob && cur->mob == owner && cur->name == timer_name)
{
cur->Timer_.Enable();
cur->Timer_.Start(milliseconds, false);
@@ -905,7 +866,7 @@ uint16 QuestManager::scribespells(uint8 max_level, uint8 min_level) {
uint16 book_slot, count;
uint16 curspell;
uint16 Char_ID = initiator->CharacterID();
uint32 Char_ID = initiator->CharacterID();
bool SpellGlobalRule = RuleB(Spells, EnableSpellGlobals);
bool SpellGlobalCheckResult = 0;
@@ -947,7 +908,7 @@ uint16 QuestManager::traindiscs(uint8 max_level, uint8 min_level) {
uint16 count;
uint16 curspell;
uint16 Char_ID = initiator->CharacterID();
uint32 Char_ID = initiator->CharacterID();
bool SpellGlobalRule = RuleB(Spells, EnableSpellGlobals);
bool SpellGlobalCheckResult = 0;
@@ -961,7 +922,7 @@ uint16 QuestManager::traindiscs(uint8 max_level, uint8 min_level) {
spells[curspell].skill != 52 &&
( !RuleB(Spells, UseCHAScribeHack) || spells[curspell].effectid[EFFECT_COUNT - 1] != 10 )
)
{
{
if(IsDiscipline(curspell)){
//we may want to come up with a function like Client::GetNextAvailableSpellBookSlot() to help speed this up a little
for(uint32 r = 0; r < MAX_PP_DISCIPLINES; r++) {
@@ -975,18 +936,20 @@ uint16 QuestManager::traindiscs(uint8 max_level, uint8 min_level) {
SpellGlobalCheckResult = initiator->SpellGlobalCheck(curspell, Char_ID);
if (SpellGlobalCheckResult) {
initiator->GetPP().disciplines.values[r] = curspell;
database.SaveCharacterDisc(Char_ID, r, curspell);
initiator->SendDisciplineUpdate();
initiator->Message(0, "You have learned a new discipline!");
count++; //success counter
}
break; //continue the 1st loop
break; //continue the 1st loop
}
else {
initiator->GetPP().disciplines.values[r] = curspell;
initiator->SendDisciplineUpdate();
initiator->Message(0, "You have learned a new discipline!");
count++; //success counter
break; //continue the 1st loop
initiator->GetPP().disciplines.values[r] = curspell;
database.SaveCharacterDisc(Char_ID, r, curspell);
initiator->SendDisciplineUpdate();
initiator->Message(0, "You have learned a new discipline!");
count++; //success counter
break; //continue the 1st loop
}
} //if we get to this point, there's already a discipline in this slot, so we skip it
}
@@ -1289,38 +1252,34 @@ void QuestManager::signal(int npc_id, int wait_ms) {
void QuestManager::setglobal(const char *varname, const char *newvalue, int options, const char *duration) {
QuestManagerCurrentQuestVars();
int qgZoneid=zone->GetZoneID();
int qgCharid=0;
int qgNpcid = owner->GetNPCTypeID();
int qgZoneid = zone->GetZoneID();
int qgCharid = 0;
int qgNpcid = owner ? owner->GetNPCTypeID() : 0; // encounter scripts don't have an owner
/* options value determines the availability of global variables to NPCs when a quest begins
------------------------------------------------------------------
value npcid player zone
------------------------------------------------------------------
0 this this this
1 all this this
2 this all this
3 all all this
4 this this all
5 all this all
6 this all all
7 all all all
------------------------------------------------------------------
value npcid player zone
------------------------------------------------------------------
0 this this this
1 all this this
2 this all this
3 all all this
4 this this all
5 all this all
6 this all all
7 all all all
*/
if (initiator && initiator->IsClient()) // some events like waypoint and spawn don't have a player involved
{
if (initiator && initiator->IsClient()){ // some events like waypoint and spawn don't have a player involved
qgCharid=initiator->CharacterID();
}
else
{
else {
qgCharid=-qgNpcid; // make char id negative npc id as a fudge
}
if (options < 0 || options > 7)
{
if (options < 0 || options > 7) {
std::cerr << "Invalid options for global var " << varname << " using defaults" << std::endl;
} // default = 0 (only this npcid,player and zone)
else
{
else {
if (options & 1)
qgNpcid=0;
if (options & 2)
@@ -1330,143 +1289,130 @@ void QuestManager::setglobal(const char *varname, const char *newvalue, int opti
}
InsertQuestGlobal(qgCharid, qgNpcid, qgZoneid, varname, newvalue, QGVarDuration(duration));
/* QS: PlayerLogQGlobalUpdate */
if (RuleB(QueryServ, PlayerLogQGlobalUpdate) && qgCharid && qgCharid > 0 && initiator && initiator->IsClient()){
std::string event_desc = StringFormat("Update :: qglobal:%s to qvalue:%s zoneid:%i instid:%i", varname, newvalue, initiator->GetZoneID(), initiator->GetInstanceID());
QServ->PlayerLogEvent(Player_Log_QGlobal_Update, qgCharid, event_desc);
}
}
/* Inserts global variable into quest_globals table */
int QuestManager::InsertQuestGlobal(
int charid, int npcid, int zoneid,
const char *varname, const char *varvalue,
int duration)
{
char *query = 0;
char errbuf[MYSQL_ERRMSG_SIZE];
int QuestManager::InsertQuestGlobal(int charid, int npcid, int zoneid, const char *varname, const char *varvalue, int duration) {
// Make duration string either "unix_timestamp(now()) + xxx" or "NULL"
std::stringstream duration_ss;
if (duration == INT_MAX)
{
duration_ss << "NULL";
}
else
{
duration_ss << "unix_timestamp(now()) + " << duration;
}
std::string durationText = (duration == INT_MAX)? "NULL": StringFormat("unix_timestamp(now()) + %i", duration);
//NOTE: this should be escaping the contents of arglist
//npcwise a malicious script can arbitrarily alter the DB
uint32 last_id = 0;
if (!database.RunQuery(query, MakeAnyLenString(&query,
"REPLACE INTO quest_globals (charid, npcid, zoneid, name, value, expdate)"
"VALUES (%i, %i, %i, '%s', '%s', %s)",
charid, npcid, zoneid, varname, varvalue, duration_ss.str().c_str()
), errbuf, nullptr, nullptr, &last_id))
{
std::cerr << "setglobal error inserting " << varname << " : " << errbuf << std::endl;
}
safe_delete_array(query);
/*
NOTE: this should be escaping the contents of arglist
npcwise a malicious script can arbitrarily alter the DB
*/
if(zone)
{
//first delete our global
ServerPacket* pack = new ServerPacket(ServerOP_QGlobalDelete, sizeof(ServerQGlobalDelete_Struct));
ServerQGlobalDelete_Struct *qgd = (ServerQGlobalDelete_Struct*)pack->pBuffer;
qgd->npc_id = npcid;
qgd->char_id = charid;
qgd->zone_id = zoneid;
qgd->from_zone_id = zone->GetZoneID();
qgd->from_instance_id = zone->GetInstanceID();
strcpy(qgd->name, varname);
std::string query = StringFormat("REPLACE INTO quest_globals "
"(charid, npcid, zoneid, name, value, expdate)"
"VALUES (%i, %i, %i, '%s', '%s', %s)",
charid, npcid, zoneid, varname, varvalue, durationText.c_str());
auto results = database.QueryDatabase(query);
if (!results.Success())
std::cerr << "setglobal error inserting " << varname << " : " << results.ErrorMessage() << std::endl;
entity_list.DeleteQGlobal(std::string((char*)qgd->name), qgd->npc_id, qgd->char_id, qgd->zone_id);
zone->DeleteQGlobal(std::string((char*)qgd->name), qgd->npc_id, qgd->char_id, qgd->zone_id);
if(!zone)
return 0;
worldserver.SendPacket(pack);
safe_delete(pack);
/* Delete existing qglobal data and update zone processes */
ServerPacket* pack = new ServerPacket(ServerOP_QGlobalDelete, sizeof(ServerQGlobalDelete_Struct));
ServerQGlobalDelete_Struct *qgd = (ServerQGlobalDelete_Struct*)pack->pBuffer;
qgd->npc_id = npcid;
qgd->char_id = charid;
qgd->zone_id = zoneid;
qgd->from_zone_id = zone->GetZoneID();
qgd->from_instance_id = zone->GetInstanceID();
strcpy(qgd->name, varname);
//then create a new one with the new id
pack = new ServerPacket(ServerOP_QGlobalUpdate, sizeof(ServerQGlobalUpdate_Struct));
ServerQGlobalUpdate_Struct *qgu = (ServerQGlobalUpdate_Struct*)pack->pBuffer;
qgu->npc_id = npcid;
qgu->char_id = charid;
qgu->zone_id = zoneid;
if(duration == INT_MAX)
{
qgu->expdate = 0xFFFFFFFF;
}
else
{
qgu->expdate = Timer::GetTimeSeconds() + duration;
}
strcpy((char*)qgu->name, varname);
strn0cpy((char*)qgu->value, varvalue, 128);
qgu->id = last_id;
qgu->from_zone_id = zone->GetZoneID();
qgu->from_instance_id = zone->GetInstanceID();
entity_list.DeleteQGlobal(std::string((char*)qgd->name), qgd->npc_id, qgd->char_id, qgd->zone_id);
zone->DeleteQGlobal(std::string((char*)qgd->name), qgd->npc_id, qgd->char_id, qgd->zone_id);
QGlobal temp;
temp.npc_id = npcid;
temp.char_id = charid;
temp.zone_id = zoneid;
temp.expdate = qgu->expdate;
temp.name.assign(qgu->name);
temp.value.assign(qgu->value);
entity_list.UpdateQGlobal(qgu->id, temp);
zone->UpdateQGlobal(qgu->id, temp);
worldserver.SendPacket(pack);
safe_delete(pack);
worldserver.SendPacket(pack);
safe_delete(pack);
}
/* Create new qglobal data and update zone processes */
pack = new ServerPacket(ServerOP_QGlobalUpdate, sizeof(ServerQGlobalUpdate_Struct));
ServerQGlobalUpdate_Struct *qgu = (ServerQGlobalUpdate_Struct*)pack->pBuffer;
qgu->npc_id = npcid;
qgu->char_id = charid;
qgu->zone_id = zoneid;
qgu->expdate = (duration == INT_MAX)? 0xFFFFFFFF: Timer::GetTimeSeconds() + duration;
strcpy((char*)qgu->name, varname);
strn0cpy((char*)qgu->value, varvalue, 128);
qgu->id = results.LastInsertedID();
qgu->from_zone_id = zone->GetZoneID();
qgu->from_instance_id = zone->GetInstanceID();
QGlobal temp;
temp.npc_id = npcid;
temp.char_id = charid;
temp.zone_id = zoneid;
temp.expdate = qgu->expdate;
temp.name.assign(qgu->name);
temp.value.assign(qgu->value);
entity_list.UpdateQGlobal(qgu->id, temp);
zone->UpdateQGlobal(qgu->id, temp);
worldserver.SendPacket(pack);
safe_delete(pack);
return 0;
}
void QuestManager::targlobal(const char *varname, const char *value, const char *duration, int qgNpcid, int qgCharid, int qgZoneid)
{
void QuestManager::targlobal(const char *varname, const char *value, const char *duration, int qgNpcid, int qgCharid, int qgZoneid) {
InsertQuestGlobal(qgCharid, qgNpcid, qgZoneid, varname, value, QGVarDuration(duration));
}
void QuestManager::delglobal(const char *varname) {
QuestManagerCurrentQuestVars();
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
int qgZoneid=zone->GetZoneID();
int qgCharid=0;
int qgNpcid=owner->GetNPCTypeID();
int qgZoneid = zone->GetZoneID();
int qgCharid = 0;
int qgNpcid = owner ? owner->GetNPCTypeID() : 0; // encounter scripts don't have an owner
if (initiator && initiator->IsClient()) // some events like waypoint and spawn don't have a player involved
{
qgCharid=initiator->CharacterID();
}
else
{
qgCharid=-qgNpcid; // make char id negative npc id as a fudge
/* QS: PlayerLogQGlobalUpdate */
if (RuleB(QueryServ, PlayerLogQGlobalUpdate) && qgCharid && qgCharid > 0 && initiator && initiator->IsClient()){
std::string event_desc = StringFormat("Deleted :: qglobal:%s zoneid:%i instid:%i", varname, initiator->GetZoneID(), initiator->GetInstanceID());
QServ->PlayerLogEvent(Player_Log_QGlobal_Update, qgCharid, event_desc);
}
if (!database.RunQuery(query,
MakeAnyLenString(&query,
"DELETE FROM quest_globals WHERE name='%s'"
" && (npcid=0 || npcid=%i) && (charid=0 || charid=%i) && (zoneid=%i || zoneid=0)",
varname,qgNpcid,qgCharid,qgZoneid),errbuf))
{
std::cerr << "delglobal error deleting " << varname << " : " << errbuf << std::endl;
}
safe_delete_array(query);
if(zone)
{
ServerPacket* pack = new ServerPacket(ServerOP_QGlobalDelete, sizeof(ServerQGlobalDelete_Struct));
ServerQGlobalDelete_Struct *qgu = (ServerQGlobalDelete_Struct*)pack->pBuffer;
std::string query = StringFormat("DELETE FROM quest_globals "
"WHERE name = '%s' "
"&& (npcid=0 || npcid=%i) "
"&& (charid=0 || charid=%i) "
"&& (zoneid=%i || zoneid=0)",
varname, qgNpcid, qgCharid, qgZoneid);
auto results = database.QueryDatabase(query);
if (!results.Success())
std::cerr << "delglobal error deleting " << varname << " : " << results.ErrorMessage() << std::endl;
qgu->npc_id = qgNpcid;
qgu->char_id = qgCharid;
qgu->zone_id = qgZoneid;
strcpy(qgu->name, varname);
if(!zone)
return;
entity_list.DeleteQGlobal(std::string((char*)qgu->name), qgu->npc_id, qgu->char_id, qgu->zone_id);
zone->DeleteQGlobal(std::string((char*)qgu->name), qgu->npc_id, qgu->char_id, qgu->zone_id);
ServerPacket* pack = new ServerPacket(ServerOP_QGlobalDelete, sizeof(ServerQGlobalDelete_Struct));
ServerQGlobalDelete_Struct *qgu = (ServerQGlobalDelete_Struct*)pack->pBuffer;
worldserver.SendPacket(pack);
safe_delete(pack);
}
qgu->npc_id = qgNpcid;
qgu->char_id = qgCharid;
qgu->zone_id = qgZoneid;
strcpy(qgu->name, varname);
entity_list.DeleteQGlobal(std::string((char*)qgu->name), qgu->npc_id, qgu->char_id, qgu->zone_id);
zone->DeleteQGlobal(std::string((char*)qgu->name), qgu->npc_id, qgu->char_id, qgu->zone_id);
worldserver.SendPacket(pack);
safe_delete(pack);
}
// Converts duration string to duration value (in seconds)
@@ -1687,11 +1633,6 @@ void QuestManager::showgrid(int grid) {
if(initiator == nullptr)
return;
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
FindPerson_Point pt;
std::vector<FindPerson_Point> pts;
@@ -1701,25 +1642,25 @@ void QuestManager::showgrid(int grid) {
pts.push_back(pt);
// Retrieve all waypoints for this grid
if(database.RunQuery(query,MakeAnyLenString(&query,"SELECT `x`,`y`,`z` FROM grid_entries WHERE `gridid`=%i AND `zoneid`=%i ORDER BY `number`",grid,zone->GetZoneID()),errbuf,&result))
{
while((row = mysql_fetch_row(result)))
{
pt.x = atof(row[0]);
pt.y = atof(row[1]);
pt.z = atof(row[2]);
pts.push_back(pt);
}
mysql_free_result(result);
initiator->SendPathPacket(pts);
}
else // DB query error!
{
LogFile->write(EQEMuLog::Quest, "Error loading grid %d for showgrid(): %s", grid, errbuf);
std::string query = StringFormat("SELECT `x`,`y`,`z` FROM grid_entries "
"WHERE `gridid` = %i AND `zoneid` = %i "
"ORDER BY `number`", grid, zone->GetZoneID());
auto results = database.QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Quest, "Error loading grid %d for showgrid(): %s", grid, results.ErrorMessage().c_str());
return;
}
safe_delete_array(query);
}
for(auto row = results.begin(); row != results.end(); ++row) {
pt.x = atof(row[0]);
pt.y = atof(row[1]);
pt.z = atof(row[2]);
pts.push_back(pt);
}
initiator->SendPathPacket(pts);
}
//change the value of a spawn condition
@@ -1762,7 +1703,7 @@ bool QuestManager::summonburriedplayercorpse(uint32 char_id, float dest_x, float
bool Result = false;
if(char_id > 0) {
Corpse* PlayerCorpse = database.SummonBurriedPlayerCorpse(char_id, zone->GetZoneID(), zone->GetInstanceID(), dest_x, dest_y, dest_z, dest_heading);
Corpse* PlayerCorpse = database.SummonBuriedCharacterCorpses(char_id, zone->GetZoneID(), zone->GetInstanceID(), dest_x, dest_y, dest_z, dest_heading);
if(PlayerCorpse) {
Result = true;
}
@@ -1785,7 +1726,7 @@ uint32 QuestManager::getplayerburriedcorpsecount(uint32 char_id) {
uint32 Result = 0;
if(char_id > 0) {
Result = database.GetPlayerBurriedCorpseCount(char_id);
Result = database.GetCharacterBuriedCorpseCount(char_id);
}
return Result;
}
@@ -1799,12 +1740,12 @@ bool QuestManager::buryplayercorpse(uint32 char_id)
uint32 PlayerCorpse = database.GetFirstCorpseID(char_id);
if(PlayerCorpse > 0)
{
database.BuryPlayerCorpse(PlayerCorpse);
database.BuryCharacterCorpse(PlayerCorpse);
Corpse* corpse = entity_list.GetCorpseByDBID(PlayerCorpse);
if(corpse)
{
corpse->Save();
corpse->DepopCorpse();
corpse->DepopPlayerCorpse();
}
else
{
@@ -2295,19 +2236,19 @@ bool QuestManager::istaskappropriate(int task) {
}
void QuestManager::clearspawntimers() {
if(zone) {
//TODO: Dec 19, 2008, replace with code updated for current spawn timers.
LinkedListIterator<Spawn2*> iterator(zone->spawn2_list);
iterator.Reset();
while (iterator.MoreElements())
{
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
database.RunQuery(query, MakeAnyLenString(&query, "DELETE FROM respawn_times WHERE id=%lu AND "
"instance_id=%lu",(unsigned long)iterator.GetData()->GetID(), (unsigned long)zone->GetInstanceID()), errbuf);
safe_delete_array(query);
iterator.Advance();
}
if(!zone)
return;
//TODO: Dec 19, 2008, replace with code updated for current spawn timers.
LinkedListIterator<Spawn2*> iterator(zone->spawn2_list);
iterator.Reset();
while (iterator.MoreElements()) {
std::string query = StringFormat("DELETE FROM respawn_times "
"WHERE id = %lu AND instance_id = %lu",
(unsigned long)iterator.GetData()->GetID(),
(unsigned long)zone->GetInstanceID());
auto results = database.QueryDatabase(query);
iterator.Advance();
}
}
@@ -2566,7 +2507,7 @@ void QuestManager::DestroyInstance(uint16 instance_id)
uint16 QuestManager::GetInstanceID(const char *zone, int16 version)
{
QuestManagerCurrentQuestVars();
if(initiator)
if (initiator)
{
return database.GetInstanceID(zone, initiator->CharacterID(), version);
}
@@ -2576,7 +2517,7 @@ uint16 QuestManager::GetInstanceID(const char *zone, int16 version)
void QuestManager::AssignToInstance(uint16 instance_id)
{
QuestManagerCurrentQuestVars();
if(initiator)
if (initiator)
{
database.AddClientToInstance(instance_id, initiator->CharacterID());
}
@@ -2585,10 +2526,10 @@ void QuestManager::AssignToInstance(uint16 instance_id)
void QuestManager::AssignGroupToInstance(uint16 instance_id)
{
QuestManagerCurrentQuestVars();
if(initiator)
if (initiator)
{
Group *g = initiator->GetGroup();
if(g)
if (g)
{
uint32 gid = g->GetID();
database.AssignGroupToInstance(gid, instance_id);
@@ -2599,7 +2540,7 @@ void QuestManager::AssignGroupToInstance(uint16 instance_id)
void QuestManager::AssignRaidToInstance(uint16 instance_id)
{
QuestManagerCurrentQuestVars();
if(initiator)
if (initiator)
{
Raid *r = initiator->GetRaid();
if(r)
@@ -2613,36 +2554,28 @@ void QuestManager::AssignRaidToInstance(uint16 instance_id)
void QuestManager::RemoveFromInstance(uint16 instance_id)
{
QuestManagerCurrentQuestVars();
if(initiator) {
if(database.RemoveClientFromInstance(instance_id, initiator->CharacterID())) {
if (initiator)
{
if (database.RemoveClientFromInstance(instance_id, initiator->CharacterID()))
initiator->Message(MT_Say, "Removed client from instance.");
} else {
else
initiator->Message(MT_Say, "Failed to remove client from instance.");
}
}
}
void QuestManager::RemoveAllFromInstance(uint16 instance_id)
{
QuestManagerCurrentQuestVars();
if(initiator) {
if (initiator)
{
std::list<uint32> charid_list;
bool removed_all = true;
uint16 fail_count = 0;
database.GetCharactersInInstance(instance_id,charid_list);
auto iter = charid_list.begin();
while(iter != charid_list.end()) {
if(!database.RemoveClientFromInstance(instance_id, *iter)) {
removed_all = false;
++fail_count;
}
++iter;
}
if (removed_all) {
if (database.RemoveClientsFromInstance(instance_id))
initiator->Message(MT_Say, "Removed all players from instance.");
} else {
// once the expedition system is in, this message it not relevant
initiator->Message(MT_Say, "Failed to remove %i player(s) from instance.", fail_count);
else
{
database.GetCharactersInInstance(instance_id, charid_list);
initiator->Message(MT_Say, "Failed to remove %i player(s) from instance.", charid_list.size()); // once the expedition system is in, this message it not relevant
}
}
}
@@ -2684,11 +2617,6 @@ void QuestManager::FlagInstanceByRaidLeader(uint32 zone, int16 version)
const char* QuestManager::saylink(char* Phrase, bool silent, const char* LinkName) {
QuestManagerCurrentQuestVars();
const char *ERR_MYSQLERROR = "Error in saylink phrase queries";
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
int sayid = 0;
int sz = strlen(Phrase);
@@ -2696,70 +2624,50 @@ const char* QuestManager::saylink(char* Phrase, bool silent, const char* LinkNam
database.DoEscapeString(escaped_string, Phrase, sz);
// Query for an existing phrase and id in the saylink table
if(database.RunQuery(query,MakeAnyLenString(&query,"SELECT `id` FROM `saylink` WHERE `phrase` = '%s'", escaped_string),errbuf,&result))
{
if (mysql_num_rows(result) >= 1)
{
while((row = mysql_fetch_row(result)))
{
std::string query = StringFormat("SELECT `id` FROM `saylink` WHERE `phrase` = '%s'", escaped_string);
auto results = database.QueryDatabase(query);
if (results.Success()) {
if (results.RowCount() >= 1) {
for (auto row = results.begin();row != results.end(); ++row)
sayid = atoi(row[0]);
}
mysql_free_result(result);
}
else // Add a new saylink entry to the database and query it again for the new sayid number
{
safe_delete_array(query);
database.RunQuery(query,MakeAnyLenString(&query,"INSERT INTO `saylink` (`phrase`) VALUES ('%s')", escaped_string),errbuf);
safe_delete_array(query);
if(database.RunQuery(query,MakeAnyLenString(&query,"SELECT `id` FROM saylink WHERE `phrase` = '%s'", escaped_string),errbuf,&result))
{
if (mysql_num_rows(result) >= 1)
{
while((row = mysql_fetch_row(result)))
{
sayid = atoi(row[0]);
}
mysql_free_result(result);
} else { // Add a new saylink entry to the database and query it again for the new sayid number
std::string insert_query = StringFormat("INSERT INTO `saylink` (`phrase`) VALUES ('%s')", escaped_string);
results = database.QueryDatabase(insert_query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in saylink phrase queries", results.ErrorMessage().c_str());
} else {
results = database.QueryDatabase(query);
if (results.Success()) {
if (results.RowCount() >= 1)
for(auto row = results.begin(); row != results.end(); ++row)
sayid = atoi(row[0]);
} else {
LogFile->write(EQEMuLog::Error, "Error in saylink phrase queries", results.ErrorMessage().c_str());
}
}
else
{
LogFile->write(EQEMuLog::Error, ERR_MYSQLERROR, errbuf);
}
safe_delete_array(query);
}
}
safe_delete_array(query);
safe_delete_array(escaped_string);
if(silent)
if (silent)
sayid = sayid + 750000;
else
sayid = sayid + 500000;
//Create the say link as an item link hash
char linktext[250];
//Create the say link as an item link hash
char linktext[250];
if(initiator)
{
if (initiator) {
if (initiator->GetClientVersion() >= EQClientRoF)
{
sprintf(linktext,"%c%06X%s%s%c",0x12,sayid,"0000000000000000000000000000000000000000000000000",LinkName,0x12);
}
else if (initiator->GetClientVersion() >= EQClientSoF)
{
sprintf(linktext,"%c%06X%s%s%c",0x12,sayid,"00000000000000000000000000000000000000000000",LinkName,0x12);
}
else
{
sprintf(linktext,"%c%06X%s%s%c",0x12,sayid,"000000000000000000000000000000000000000",LinkName,0x12);
}
}
else { // If no initiator, create an RoF saylink, since older clients handle RoF ones better than RoF handles older ones.
} else { // If no initiator, create an RoF saylink, since older clients handle RoF ones better than RoF handles older ones.
sprintf(linktext,"%c%06X%s%s%c",0x12,sayid,"0000000000000000000000000000000000000000000000000",LinkName,0x12);
}
strcpy(Phrase,linktext);
return Phrase;
@@ -2951,6 +2859,15 @@ const char* QuestManager::GetZoneLongName(const char *zone) {
return ln.c_str();
}
void QuestManager::CrossZoneSignalNPCByNPCTypeID(uint32 npctype_id, uint32 data){
ServerPacket* pack = new ServerPacket(ServerOP_CZSignalNPC, sizeof(CZNPCSignal_Struct));
CZNPCSignal_Struct* CZSN = (CZNPCSignal_Struct*)pack->pBuffer;
CZSN->npctype_id = npctype_id;
CZSN->data = data;
worldserver.SendPacket(pack);
safe_delete(pack);
}
void QuestManager::CrossZoneSignalPlayerByCharID(int charid, uint32 data){
ServerPacket* pack = new ServerPacket(ServerOP_CZSignalClient, sizeof(CZClientSignal_Struct));
CZClientSignal_Struct* CZSC = (CZClientSignal_Struct*) pack->pBuffer;
@@ -2968,7 +2885,7 @@ void QuestManager::CrossZoneSignalPlayerByName(const char *CharName, uint32 data
CZSC->data = data;
worldserver.SendPacket(pack);
safe_delete(pack);
}
}
void QuestManager::CrossZoneMessagePlayerByName(uint32 Type, const char *CharName, const char *Message){
uint32 message_len = strlen(CharName) + 1;
@@ -2978,6 +2895,18 @@ void QuestManager::CrossZoneMessagePlayerByName(uint32 Type, const char *CharNam
CZSC->Type = Type;
strn0cpy(CZSC->CharName, CharName, 64);
strn0cpy(CZSC->Message, Message, 512);
worldserver.SendPacket(pack);
safe_delete(pack);
}
void QuestManager::CrossZoneSetEntityVariableByNPCTypeID(uint32 npctype_id, const char *id, const char *m_var){
uint32 message_len = strlen(id) + 1;
uint32 message_len2 = strlen(m_var) + 1;
ServerPacket* pack = new ServerPacket(ServerOP_CZSetEntityVariableByNPCTypeID, sizeof(CZSetEntVarByNPCTypeID_Struct) + message_len + message_len2);
CZSetEntVarByNPCTypeID_Struct* CZSNBYNID = (CZSetEntVarByNPCTypeID_Struct*)pack->pBuffer;
CZSNBYNID->npctype_id = npctype_id;
strn0cpy(CZSNBYNID->id, id, 256);
strn0cpy(CZSNBYNID->m_var, m_var, 256);
worldserver.SendPacket(pack);
safe_delete(pack);
}
@@ -3039,3 +2968,12 @@ ItemInst *QuestManager::GetQuestItem() const {
return nullptr;
}
std::string QuestManager::GetEncounter() const {
if(!quests_running_.empty()) {
running_quest e = quests_running_.top();
return e.encounter;
}
return "";
}
+9 -3
View File
@@ -25,8 +25,10 @@
#include <list>
#include <stack>
class NPC;
class Client;
class ItemInst;
class Mob;
class NPC;
class QuestManager {
struct running_quest {
@@ -34,12 +36,13 @@ class QuestManager {
Client *initiator;
ItemInst* questitem;
bool depop_npc;
std::string encounter;
};
public:
QuestManager();
virtual ~QuestManager();
void StartQuest(Mob *_owner, Client *_initiator = nullptr, ItemInst* _questitem = nullptr);
void StartQuest(Mob *_owner, Client *_initiator = nullptr, ItemInst* _questitem = nullptr, std::string encounter = "");
void EndQuest();
bool QuestsRunning() { return !quests_running_.empty(); }
@@ -239,8 +242,10 @@ public:
uint16 CreateDoor( const char* model, float x, float y, float z, float heading, uint8 opentype, uint16 size);
int32 GetZoneID(const char *zone);
const char *GetZoneLongName(const char *zone);
void CrossZoneSignalPlayerByCharID(int charid, uint32 data);
void CrossZoneSignalPlayerByCharID(int charid, uint32 data);
void CrossZoneSignalNPCByNPCTypeID(uint32 npctype_id, uint32 data);
void CrossZoneSignalPlayerByName(const char *CharName, uint32 data);
void CrossZoneSetEntityVariableByNPCTypeID(uint32 npctype_id, const char *id, const char *m_var);
void CrossZoneMessagePlayerByName(uint32 Type, const char *CharName, const char *Message);
bool EnableRecipe(uint32 recipe_id);
bool DisableRecipe(uint32 recipe_id);
@@ -250,6 +255,7 @@ public:
NPC *GetNPC() const;
Mob *GetOwner() const;
ItemInst *GetQuestItem() const;
std::string GetEncounter() const;
inline bool ProximitySayInUse() { return HaveProximitySays; }
#ifdef BOTS
+349 -199
View File
@@ -17,10 +17,10 @@
*/
#include "../common/debug.h"
#include "masterentity.h"
#include "NpcAI.h"
#include "npc_ai.h"
#include "../common/packet_functions.h"
#include "../common/packet_dump.h"
#include "../common/StringUtil.h"
#include "../common/string_util.h"
#include "worldserver.h"
extern EntityList entity_list;
extern WorldServer worldserver;
@@ -29,6 +29,12 @@ Raid::Raid(uint32 raidID)
: GroupIDConsumer(raidID)
{
memset(members ,0, (sizeof(RaidMember)*MAX_RAID_MEMBERS));
memset(&raid_aa, 0, sizeof(RaidLeadershipAA_Struct));
memset(group_aa, 0, sizeof(GroupLeadershipAA_Struct) * MAX_RAID_GROUPS);
for (int i = 0; i < MAX_RAID_GROUPS; i++) {
group_mentor[i].mentor_percent = 0;
group_mentor[i].mentoree = nullptr;
}
leader = nullptr;
memset(leadername, 0, 64);
locked = false;
@@ -39,6 +45,12 @@ Raid::Raid(Client* nLeader)
: GroupIDConsumer()
{
memset(members ,0, (sizeof(RaidMember)*MAX_RAID_MEMBERS));
memset(&raid_aa, 0, sizeof(RaidLeadershipAA_Struct));
memset(group_aa, 0, sizeof(GroupLeadershipAA_Struct) * MAX_RAID_GROUPS);
for (int i = 0; i < MAX_RAID_GROUPS; i++) {
group_mentor[i].mentor_percent = 0;
group_mentor[i].mentoree = nullptr;
}
leader = nLeader;
memset(leadername, 0, 64);
strn0cpy(leadername, nLeader->GetName(), 64);
@@ -74,21 +86,36 @@ void Raid::AddMember(Client *c, uint32 group, bool rleader, bool groupleader, bo
if(!c)
return;
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
if (database.RunQuery(query,MakeAnyLenString(&query, "INSERT INTO raid_members SET raidid=%lu, charid=%lu, groupid=%lu, _class=%d, level=%d, name='%s', isgroupleader=%d, israidleader=%d, islooter=%d", (unsigned long)GetID(), (unsigned long)c->CharacterID(), (unsigned long)group, c->GetClass(), c->GetLevel(), c->GetName(), groupleader, rleader, looter ),errbuf,&result)){
mysql_free_result(result);
std::string query = StringFormat("INSERT INTO raid_members SET raidid = %lu, charid = %lu, "
"groupid = %lu, _class = %d, level = %d, name = '%s', "
"isgroupleader = %d, israidleader = %d, islooter = %d",
(unsigned long)GetID(), (unsigned long)c->CharacterID(),
(unsigned long)group, c->GetClass(), c->GetLevel(),
c->GetName(), groupleader, rleader, looter);
auto results = database.QueryDatabase(query);
if(!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error inserting into raid members: %s", results.ErrorMessage().c_str());
}
safe_delete_array(query);
LearnMembers();
VerifyRaid();
if (rleader) {
database.SetRaidGroupLeaderInfo(RAID_GROUPLESS, GetID());
UpdateRaidAAs();
}
if (group != RAID_GROUPLESS && groupleader) {
database.SetRaidGroupLeaderInfo(group, GetID());
UpdateGroupAAs(group);
}
if(group < 12)
GroupUpdate(group);
else // get raid AAs, GroupUpdate will handles it otherwise
SendGroupLeadershipAA(c, RAID_GROUPLESS);
SendRaidAddAll(c->GetName());
c->SetRaidGrouped(true);
SendRaidMOTD(c);
ServerPacket *pack = new ServerPacket(ServerOP_RaidAdd, sizeof(ServerRaidGeneralAction_Struct));
ServerRaidGeneralAction_Struct *rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer;
@@ -100,32 +127,26 @@ void Raid::AddMember(Client *c, uint32 group, bool rleader, bool groupleader, bo
safe_delete(pack);
}
void Raid::RemoveMember(const char *c)
void Raid::RemoveMember(const char *characterName)
{
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
if (database.RunQuery(query,MakeAnyLenString(&query, "DELETE FROM raid_members where name='%s'", c ),errbuf,&result)){
mysql_free_result(result);
}
std::string query = StringFormat("DELETE FROM raid_members where name='%s'", characterName);
auto results = database.QueryDatabase(query);
Client *m = entity_list.GetClientByName(c);
safe_delete_array(query);
Client *client = entity_list.GetClientByName(characterName);
disbandCheck = true;
SendRaidRemoveAll(c);
SendRaidDisband(m);
SendRaidRemoveAll(characterName);
SendRaidDisband(client);
LearnMembers();
VerifyRaid();
if(m){
m->SetRaidGrouped(false);
}
if(client)
client->SetRaidGrouped(false);
ServerPacket *pack = new ServerPacket(ServerOP_RaidRemove, sizeof(ServerRaidGeneralAction_Struct));
ServerRaidGeneralAction_Struct *rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer;
rga->rid = GetID();
rga->instance_id = zone->GetInstanceID();
strn0cpy(rga->playername, c, 64);
strn0cpy(rga->playername, characterName, 64);
rga->zoneid = zone->GetZoneID();
worldserver.SendPacket(pack);
safe_delete(pack);
@@ -133,14 +154,9 @@ void Raid::RemoveMember(const char *c)
void Raid::DisbandRaid()
{
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
if (database.RunQuery(query,MakeAnyLenString(&query, "DELETE FROM raid_members WHERE raidid=%lu", (unsigned long)GetID()),errbuf,&result)){
mysql_free_result(result);
}
std::string query = StringFormat("DELETE FROM raid_members WHERE raidid = %lu", (unsigned long)GetID());
auto results = database.QueryDatabase(query);
safe_delete_array(query);
LearnMembers();
VerifyRaid();
SendRaidDisbandAll();
@@ -159,14 +175,10 @@ void Raid::DisbandRaid()
void Raid::MoveMember(const char *name, uint32 newGroup)
{
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
if (database.RunQuery(query,MakeAnyLenString(&query, "UPDATE raid_members SET groupid=%lu WHERE name='%s'", (unsigned long)newGroup, name),errbuf,&result)){
mysql_free_result(result);
}
std::string query = StringFormat("UPDATE raid_members SET groupid = %lu WHERE name = '%s'",
(unsigned long)newGroup, name);
auto results = database.QueryDatabase(query);
safe_delete_array(query);
LearnMembers();
VerifyRaid();
SendRaidMoveAll(name);
@@ -183,21 +195,13 @@ void Raid::MoveMember(const char *name, uint32 newGroup)
void Raid::SetGroupLeader(const char *who, bool glFlag)
{
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
if (database.RunQuery(query,MakeAnyLenString(&query, "UPDATE raid_members SET isgroupleader=%lu WHERE name='%s'", (unsigned long)glFlag, who),errbuf,&result)){
mysql_free_result(result);
}
std::string query = StringFormat("UPDATE raid_members SET isgroupleader = %lu WHERE name = '%s'",
(unsigned long)glFlag, who);
auto results = database.QueryDatabase(query);
safe_delete_array(query);
LearnMembers();
VerifyRaid();
//if(glFlag == true){ //we're setting the flag
//this->SendMakeGroupLeaderPacket(who);
//}
ServerPacket *pack = new ServerPacket(ServerOP_RaidGroupLeader, sizeof(ServerRaidGeneralAction_Struct));
ServerRaidGeneralAction_Struct *rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer;
rga->rid = GetID();
@@ -208,27 +212,29 @@ void Raid::SetGroupLeader(const char *who, bool glFlag)
safe_delete(pack);
}
Client *Raid::GetGroupLeader(uint32 group_id)
{
if (group_id == RAID_GROUPLESS)
return nullptr;
for (uint32 i = 0; i < MAX_RAID_MEMBERS; i++)
if (members[i].member && members[i].IsGroupLeader && members[i].GroupNumber == group_id)
return members[i].member;
return nullptr;
}
void Raid::SetRaidLeader(const char *wasLead, const char *name)
{
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
if (!database.RunQuery(query,MakeAnyLenString(&query, "UPDATE raid_members SET israidleader=0 WHERE name='%s'", wasLead),errbuf,&result)){
printf("Set Raid Leader error: %s\n", errbuf);
}
else
mysql_free_result(result);
std::string query = StringFormat("UPDATE raid_members SET israidleader = 0 WHERE name = '%s'", wasLead);
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Set Raid Leader error: %s\n", results.ErrorMessage().c_str());
safe_delete_array(query);
query = 0;
if (!database.RunQuery(query,MakeAnyLenString(&query, "UPDATE raid_members SET israidleader=1 WHERE name='%s'", name),errbuf,&result)){
printf("Set Raid Leader error: %s\n", errbuf);
}
else
mysql_free_result(result);
safe_delete_array(query);
query = StringFormat("UPDATE raid_members SET israidleader = 1 WHERE name = '%s'", name);
results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Set Raid Leader error: %s\n", results.ErrorMessage().c_str());
strn0cpy(leadername, name, 64);
@@ -250,6 +256,58 @@ void Raid::SetRaidLeader(const char *wasLead, const char *name)
safe_delete(pack);
}
void Raid::SaveGroupLeaderAA(uint32 gid)
{
char *queryBuffer = new char[sizeof(GroupLeadershipAA_Struct) * 2 + 1];
database.DoEscapeString(queryBuffer, (char*)&group_aa[gid], sizeof(GroupLeadershipAA_Struct));
std::string query = "UPDATE raid_leaders SET leadershipaa = '";
query += queryBuffer;
query += StringFormat("' WHERE gid = %lu AND rid = %lu LIMIT 1", gid, GetID());
safe_delete_array(queryBuffer);
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to store LeadershipAA: %s\n", results.ErrorMessage().c_str());
}
void Raid::SaveRaidLeaderAA()
{
char *queryBuffer = new char[sizeof(RaidLeadershipAA_Struct) * 2 + 1];
database.DoEscapeString(queryBuffer, (char*)&raid_aa, sizeof(RaidLeadershipAA_Struct));
std::string query = "UPDATE raid_leaders SET leadershipaa = '";
query += queryBuffer;
query += StringFormat("' WHERE gid = %lu AND rid = %lu LIMIT 1", RAID_GROUPLESS, GetID());
safe_delete_array(queryBuffer);
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to store LeadershipAA: %s\n", results.ErrorMessage().c_str());
}
void Raid::UpdateGroupAAs(uint32 gid)
{
Client *gl = GetGroupLeader(gid);
if (gl)
gl->GetGroupAAs(&group_aa[gid]);
else
memset(&group_aa[gid], 0, sizeof(GroupLeadershipAA_Struct));
SaveGroupLeaderAA(gid);
}
void Raid::UpdateRaidAAs()
{
Client *rl = GetLeader();
if (rl)
rl->GetRaidAAs(&raid_aa);
else
memset(&raid_aa, 0, sizeof(RaidLeadershipAA_Struct));
SaveRaidLeaderAA();
}
bool Raid::IsGroupLeader(const char *who)
{
for(int x = 0; x < MAX_RAID_MEMBERS; x++)
@@ -264,14 +322,10 @@ bool Raid::IsGroupLeader(const char *who)
void Raid::UpdateLevel(const char *name, int newLevel)
{
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
if (database.RunQuery(query,MakeAnyLenString(&query, "UPDATE raid_members SET level=%lu WHERE name='%s'", (unsigned long)newLevel, name),errbuf,&result)){
mysql_free_result(result);
}
std::string query = StringFormat("UPDATE raid_members SET level = %lu WHERE name = '%s'",
(unsigned long)newLevel, name);
auto results = database.QueryDatabase(query);
safe_delete_array(query);
LearnMembers();
VerifyRaid();
}
@@ -424,7 +478,7 @@ void Raid::CastGroupSpell(Mob* caster, uint16 spellid, uint32 gid)
if(members[x].member == caster) {
caster->SpellOnTarget(spellid, caster);
#ifdef GROUP_BUFF_PETS
if(caster->GetPet() && caster->HasPetAffinity() && !caster->GetPet()->IsCharmed())
if(spells[spellid].targettype != ST_GroupNoPets && caster->GetPet() && caster->HasPetAffinity() && !caster->GetPet()->IsCharmed())
caster->SpellOnTarget(spellid, caster->GetPet());
#endif
}
@@ -435,7 +489,7 @@ void Raid::CastGroupSpell(Mob* caster, uint16 spellid, uint32 gid)
if(distance <= range2){
caster->SpellOnTarget(spellid, members[x].member);
#ifdef GROUP_BUFF_PETS
if(members[x].member->GetPet() && members[x].member->HasPetAffinity() && !members[x].member->GetPet()->IsCharmed())
if(spells[spellid].targettype != ST_GroupNoPets && members[x].member->GetPet() && members[x].member->HasPetAffinity() && !members[x].member->GetPet()->IsCharmed())
caster->SpellOnTarget(spellid, members[x].member->GetPet());
#endif
}
@@ -461,7 +515,7 @@ uint32 Raid::GetTotalRaidDamage(Mob* other)
return total;
}
void Raid::HealGroup(uint32 heal_amt, Mob* caster, uint32 gid, int32 range)
void Raid::HealGroup(uint32 heal_amt, Mob* caster, uint32 gid, float range)
{
if (!caster)
return;
@@ -504,7 +558,7 @@ void Raid::HealGroup(uint32 heal_amt, Mob* caster, uint32 gid, int32 range)
}
void Raid::BalanceHP(int32 penalty, uint32 gid, int32 range, Mob* caster, int32 limit)
void Raid::BalanceHP(int32 penalty, uint32 gid, float range, Mob* caster, int32 limit)
{
if (!caster)
return;
@@ -514,7 +568,7 @@ void Raid::BalanceHP(int32 penalty, uint32 gid, int32 range, Mob* caster, int32
int dmgtaken = 0, numMem = 0, dmgtaken_tmp = 0;
int gi = 0;
float distance;
float range2 = range*range;
@@ -560,14 +614,14 @@ void Raid::BalanceHP(int32 penalty, uint32 gid, int32 range, Mob* caster, int32
}
}
void Raid::BalanceMana(int32 penalty, uint32 gid, int32 range, Mob* caster, int32 limit)
void Raid::BalanceMana(int32 penalty, uint32 gid, float range, Mob* caster, int32 limit)
{
if (!caster)
return;
if (!range)
range = 200;
float distance;
float range2 = range*range;
@@ -775,27 +829,16 @@ void Raid::TeleportRaid(Mob* sender, uint32 zoneID, uint16 instance_id, float x,
void Raid::ChangeLootType(uint32 type)
{
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
if (database.RunQuery(query,MakeAnyLenString(&query, "UPDATE raid_details SET loottype=%lu WHERE raidid=%lu", (unsigned long)type, (unsigned long)GetID()),errbuf,&result)){
mysql_free_result(result);
}
safe_delete_array(query);
std::string query = StringFormat("UPDATE raid_details SET loottype = %lu WHERE raidid = %lu",
(unsigned long)type, (unsigned long)GetID());
auto results = database.QueryDatabase(query);
LootType = type;
}
void Raid::AddRaidLooter(const char* looter)
{
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
if (database.RunQuery(query,MakeAnyLenString(&query, "UPDATE raid_members SET islooter=1 WHERE name='%s'", looter),errbuf,&result)){
mysql_free_result(result);
}
safe_delete_array(query);
std::string query = StringFormat("UPDATE raid_members SET islooter = 1 WHERE name = '%s'", looter);
auto results = database.QueryDatabase(query);
for(int x = 0; x < MAX_RAID_MEMBERS; x++)
{
@@ -812,36 +855,19 @@ void Raid::AddRaidLooter(const char* looter)
rga->instance_id = zone->GetInstanceID();
worldserver.SendPacket(pack);
safe_delete(pack);
/* For reference only at this time. This code adds a looter to the Raid Options Window.
EQApplicationPacket* outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct));
RaidGeneral_Struct *rgs = (RaidGeneral_Struct*)outapp->pBuffer;
rgs->action = 33;
strcpy(rgs->leader_name, looter);
QueuePacket(outapp);
safe_delete(outapp); */
}
void Raid::RemoveRaidLooter(const char* looter)
{
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
if (database.RunQuery(query,MakeAnyLenString(&query, "UPDATE raid_members SET islooter=0 WHERE name='%s'", looter),errbuf,&result)){
mysql_free_result(result);
}
safe_delete_array(query);
std::string query = StringFormat("UPDATE raid_members SET islooter = 0 WHERE name = '%s'", looter);
auto results = database.QueryDatabase(query);
for(int x = 0; x < MAX_RAID_MEMBERS; x++)
{
if(strcmp(looter, members[x].membername) == 0)
{
if(strcmp(looter, members[x].membername) == 0) {
members[x].IsLooter = 0;
break;
}
}
ServerPacket *pack = new ServerPacket(ServerOP_DetailsChange, sizeof(ServerRaidGeneralAction_Struct));
ServerRaidGeneralAction_Struct *rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer;
rga->rid = GetID();
@@ -849,15 +875,6 @@ void Raid::RemoveRaidLooter(const char* looter)
rga->instance_id = zone->GetInstanceID();
worldserver.SendPacket(pack);
safe_delete(pack);
/* For reference only at this time. This code removes a looter from the Raid Options Window.
EQApplicationPacket* outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct));
RaidGeneral_Struct *rgs = (RaidGeneral_Struct*)outapp->pBuffer;
rgs->action = 34;
strcpy(rgs->leader_name, looter);
QueuePacket(outapp);
safe_delete(outapp); */
}
bool Raid::IsRaidMember(const char *name){
@@ -1089,12 +1106,12 @@ void Raid::QueuePacket(const EQApplicationPacket *app, bool ack_req)
void Raid::SendMakeLeaderPacket(const char *who) //30
{
EQApplicationPacket* outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct));
RaidGeneral_Struct *rg = (RaidGeneral_Struct*)outapp->pBuffer;
EQApplicationPacket* outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidLeadershipUpdate_Struct));
RaidLeadershipUpdate_Struct *rg = (RaidLeadershipUpdate_Struct*)outapp->pBuffer;
rg->action = raidMakeLeader;
strn0cpy(rg->leader_name, who, 64);
strn0cpy(rg->player_name, who, 64);
rg->parameter = 0;
memcpy(&rg->raid, &raid_aa, sizeof(RaidLeadershipAA_Struct));
QueuePacket(outapp);
safe_delete(outapp);
}
@@ -1104,12 +1121,12 @@ void Raid::SendMakeLeaderPacketTo(const char *who, Client *to)
if(!to)
return;
EQApplicationPacket* outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct));
RaidGeneral_Struct *rg = (RaidGeneral_Struct*)outapp->pBuffer;
EQApplicationPacket* outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidLeadershipUpdate_Struct));
RaidLeadershipUpdate_Struct *rg = (RaidLeadershipUpdate_Struct*)outapp->pBuffer;
rg->action = raidMakeLeader;
strn0cpy(rg->leader_name, who, 64);
strn0cpy(rg->player_name, who, 64);
rg->parameter = 0;
memcpy(&rg->raid, &raid_aa, sizeof(RaidLeadershipAA_Struct));
to->QueuePacket(outapp);
safe_delete(outapp);
}
@@ -1167,6 +1184,7 @@ void Raid::SendGroupUpdate(Client *to)
strn0cpy(gu->leadersname, to->GetName(), 64);
}
strn0cpy(gu->yourname, to->GetName(), 64);
memcpy(&gu->leader_aas, &group_aa[grp], sizeof(GroupLeadershipAA_Struct));
to->FastQueuePacket(&outapp);
}
@@ -1179,8 +1197,10 @@ void Raid::GroupUpdate(uint32 gid, bool initial)
{
if(strlen(members[x].membername) > 0){
if(members[x].GroupNumber == gid){
if(members[x].member)
if(members[x].member) {
SendGroupUpdate(members[x].member);
SendGroupLeadershipAA(members[x].member, gid);
}
}
}
}
@@ -1279,16 +1299,78 @@ void Raid::SendRaidGroupRemove(const char *who, uint32 gid)
safe_delete(pack);
}
void Raid::SendRaidMOTD(Client *c)
{
if (!c || motd.empty())
return;
size_t size = motd.size() + 1;
EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidMOTD_Struct) + size);
RaidMOTD_Struct *rmotd = (RaidMOTD_Struct *)outapp->pBuffer;
rmotd->general.action = raidSetMotd;
strn0cpy(rmotd->general.player_name, c->GetName(), 64);
strn0cpy(rmotd->motd, motd.c_str(), size);
c->FastQueuePacket(&outapp);
}
void Raid::SendRaidMOTD()
{
if (motd.empty())
return;
for (uint32 i = 0; i < MAX_RAID_MEMBERS; i++)
if (members[i].member)
SendRaidMOTD(members[i].member);
}
void Raid::SendRaidMOTDToWorld()
{
if (motd.empty())
return;
size_t size = motd.size() + 1;
ServerPacket *pack = new ServerPacket(ServerOP_RaidMOTD, sizeof(ServerRaidMOTD_Struct) + size);
ServerRaidMOTD_Struct *smotd = (ServerRaidMOTD_Struct *)pack->pBuffer;
smotd->rid = GetID();
strn0cpy(smotd->motd, motd.c_str(), size);
worldserver.SendPacket(pack);
safe_delete(pack);
}
void Raid::SendGroupLeadershipAA(Client *c, uint32 gid)
{
EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidLeadershipUpdate_Struct));
RaidLeadershipUpdate_Struct *rlaa = (RaidLeadershipUpdate_Struct *)outapp->pBuffer;
rlaa->action = raidSetLeaderAbilities;
strn0cpy(rlaa->leader_name, c->GetName(), 64);
strn0cpy(rlaa->player_name, c->GetName(), 64);
if (gid != RAID_GROUPLESS)
memcpy(&rlaa->group, &group_aa[gid], sizeof(GroupLeadershipAA_Struct));
memcpy(&rlaa->raid, &raid_aa, sizeof(RaidLeadershipAA_Struct));
c->QueuePacket(outapp);
safe_delete(outapp);
}
void Raid::SendGroupLeadershipAA(uint32 gid)
{
for (uint32 i = 0; i < MAX_RAID_MEMBERS; i++)
if (members[i].member && members[i].GroupNumber == gid)
SendGroupLeadershipAA(members[i].member, gid);
}
void Raid::SendAllRaidLeadershipAA()
{
for (uint32 i = 0; i < MAX_RAID_MEMBERS; i++)
if (members[i].member)
SendGroupLeadershipAA(members[i].member, members[i].GroupNumber);
}
void Raid::LockRaid(bool lockFlag)
{
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
if (database.RunQuery(query,MakeAnyLenString(&query, "UPDATE raid_details SET locked=%d WHERE raidid=%lu", lockFlag, (unsigned long)GetID()),errbuf,&result)){
mysql_free_result(result);
}
std::string query = StringFormat("UPDATE raid_details SET locked = %d WHERE raidid = %lu",
lockFlag, (unsigned long)GetID());
auto results = database.QueryDatabase(query);
safe_delete_array(query);
locked = lockFlag;
if(lockFlag)
SendRaidLock();
@@ -1307,74 +1389,79 @@ void Raid::LockRaid(bool lockFlag)
void Raid::SetRaidDetails()
{
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
if (database.RunQuery(query,MakeAnyLenString(&query, "INSERT INTO raid_details SET raidid=%lu, loottype=4, locked=0", (unsigned long)GetID()),errbuf,&result)){
mysql_free_result(result);
}
safe_delete_array(query);
std::string query = StringFormat("INSERT INTO raid_details SET raidid = %lu, loottype = 4, locked = 0, motd = ''",
(unsigned long)GetID());
auto results = database.QueryDatabase(query);
}
void Raid::GetRaidDetails()
{
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if (database.RunQuery(query,MakeAnyLenString(&query, "SELECT locked, loottype FROM raid_details WHERE raidid=%lu", (unsigned long)GetID()),errbuf,&result)){
safe_delete_array(query);
if(mysql_num_rows(result) < 1) {
mysql_free_result(result);
LogFile->write(EQEMuLog::Error, "Error getting raid details for raid %lu: %s", (unsigned long)GetID(), errbuf);
return;
}
row = mysql_fetch_row(result);
if(row){
locked = atoi(row[0]);
LootType = atoi(row[1]);
}
mysql_free_result(result);
}
std::string query = StringFormat("SELECT locked, loottype, motd FROM raid_details WHERE raidid = %lu",
(unsigned long)GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
return;
if (results.RowCount() == 0) {
LogFile->write(EQEMuLog::Error, "Error getting raid details for raid %lu: %s", (unsigned long)GetID(), results.ErrorMessage().c_str());
return;
}
auto row = results.begin();
locked = atoi(row[0]);
LootType = atoi(row[1]);
motd = std::string(row[2]);
}
void Raid::SaveRaidMOTD()
{
std::string query = StringFormat("UPDATE raid_details SET motd = '%s' WHERE raidid = %lu",
EscapeString(motd).c_str(), (unsigned long)GetID());
auto results = database.QueryDatabase(query);
}
bool Raid::LearnMembers()
{
memset(members, 0, (sizeof(RaidMember)*MAX_RAID_MEMBERS));
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if (database.RunQuery(query,MakeAnyLenString(&query, "SELECT name, groupid, _class, level, isgroupleader, israidleader, islooter FROM raid_members WHERE raidid=%lu", (unsigned long)GetID()),errbuf,&result)){
safe_delete_array(query);
if(mysql_num_rows(result) < 1) {
mysql_free_result(result);
LogFile->write(EQEMuLog::Error, "Error getting raid members for raid %lu: %s", (unsigned long)GetID(), errbuf);
disbandCheck = true;
return(false);
}
int i = 0;
while((row = mysql_fetch_row(result))) {
if(!row[0])
continue;
members[i].member = nullptr;
strn0cpy(members[i].membername, row[0], 64);
int GroupNum = atoi(row[1]);
if(GroupNum > 11)
members[i].GroupNumber = 0xFFFFFFFF;
else
members[i].GroupNumber = GroupNum;
members[i]._class = atoi(row[2]);
members[i].level = atoi(row[3]);
members[i].IsGroupLeader = atoi(row[4]);
members[i].IsRaidLeader = atoi(row[5]);
members[i].IsLooter = atoi(row[6]);
i++;
}
mysql_free_result(result);
}
return(true);
std::string query = StringFormat("SELECT name, groupid, _class, level, "
"isgroupleader, israidleader, islooter "
"FROM raid_members WHERE raidid = %lu",
(unsigned long)GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
return false;
if(results.RowCount() == 0) {
LogFile->write(EQEMuLog::Error, "Error getting raid members for raid %lu: %s", (unsigned long)GetID(), results.ErrorMessage().c_str());
disbandCheck = true;
return false;
}
int index = 0;
for(auto row = results.begin(); row != results.end(); ++row) {
if(!row[0])
continue;
members[index].member = nullptr;
strn0cpy(members[index].membername, row[0], 64);
int groupNum = atoi(row[1]);
if(groupNum > 11)
members[index].GroupNumber = 0xFFFFFFFF;
else
members[index].GroupNumber = groupNum;
members[index]._class = atoi(row[2]);
members[index].level = atoi(row[3]);
members[index].IsGroupLeader = atoi(row[4]);
members[index].IsRaidLeader = atoi(row[5]);
members[index].IsLooter = atoi(row[6]);
++index;
}
return true;
}
void Raid::VerifyRaid()
@@ -1407,13 +1494,19 @@ void Raid::MemberZoned(Client *c)
if(!c)
return;
// Raid::GetGroup() goes over the members as well, this way we go over once
uint32 gid = RAID_GROUPLESS;
for(int x = 0; x < MAX_RAID_MEMBERS; x++)
{
if(members[x].member == c)
{
members[x].member = nullptr;
gid = members[x].GroupNumber;
}
}
if (gid < 12 && group_mentor[gid].mentoree == c)
group_mentor[gid].mentoree = nullptr;
}
void Raid::SendHPPacketsTo(Client *c)
@@ -1518,3 +1611,60 @@ void Raid::RaidMessage_StringID(Mob* sender, uint32 type, uint32 string_id, cons
}
}
void Raid::LoadLeadership()
{
database.GetRaidLeadershipInfo(GetID(), nullptr, nullptr, nullptr, nullptr, &raid_aa);
char mentor_name[64];
for (uint32 group_id = 0; group_id < MAX_RAID_GROUPS; group_id++) {
database.GetGroupLeadershipInfo(group_id, GetID(), nullptr, nullptr, nullptr, nullptr,
mentor_name, &group_mentor[group_id].mentor_percent, &group_aa[group_id]);
if (strlen(mentor_name)) {
group_mentor[group_id].name = mentor_name;
mentor_name[0] = '\0';
}
}
}
void Raid::SetGroupMentor(uint32 group_id, int percent, char *name)
{
if (group_id > 11)
return;
group_mentor[group_id].name = name;
group_mentor[group_id].mentor_percent = percent;
Client *client = entity_list.GetClientByName(name);
group_mentor[group_id].mentoree = client ? client : nullptr;
std::string query = StringFormat("UPDATE raid_leaders SET mentoree = '%s', mentor_percent = %i WHERE gid = %i AND rid = %i LIMIT 1",
name, percent, group_id, GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to set raid group mentor: %s\n", results.ErrorMessage().c_str());
}
void Raid::ClearGroupMentor(uint32 group_id)
{
if (group_id > 11)
return;
group_mentor[group_id].name.clear();
group_mentor[group_id].mentor_percent = 0;
group_mentor[group_id].mentoree = nullptr;
std::string query = StringFormat("UPDATE raid_leaders SET mentoree = '', mentor_percent = 0 WHERE gid = %i AND rid = %i LIMIT 1",
group_id, GetID());
auto results = database.QueryDatabase(query);
if (!results.Success())
LogFile->write(EQEMuLog::Error, "Unable to clear raid group mentor: %s\n", results.ErrorMessage().c_str());
}
// there isn't a nice place to add this in another function, unlike groups
// so we do it here instead
void Raid::CheckGroupMentor(uint32 group_id, Client *c)
{
if (!c || group_id > 11)
return;
if (group_mentor[group_id].name == c->GetName())
group_mentor[group_id].mentoree = c;
}
+47 -6
View File
@@ -38,13 +38,13 @@ enum { //raid packet types:
raidMembers = 6, //len 395+, details + members list
raidNoAssignLeadership = 7,
raidCreate = 8, //len 72
raidUnknown = 9,
raidUnknown = 9, // unused?
raidNoRaid = 10, //parameter=0
raidChangeLootType = 11,
raidStringID = 12,
raidChangeGroupLeader = 13, //136 raid leader, new group leader, group_id?
raidBecomeGroupLeader = 14, //472
raidUnknown2 = 15,
raidSetLeaderAbilities = 14, //472
raidSetLeaderData = 15, // 14,15 SoE names, not sure on difference, 14 packet has 0x100 bytes 15 0x214 in addition to raid general
raidChangeGroup = 16, //?? len 136 old leader, new leader, 0 (preceeded with a remove2)
raidLock = 17, //len 136 leader?, leader, 0
raidUnlock = 18, //len 136 leader?, leader, 0
@@ -79,6 +79,7 @@ enum { //raid command types
#define MAX_RAID_GROUPS 12
#define MAX_RAID_MEMBERS 72
const uint32 RAID_GROUPLESS = 0xFFFFFFFF;
struct RaidMember{
char membername[64];
@@ -91,6 +92,12 @@ struct RaidMember{
bool IsLooter;
};
struct GroupMentor {
std::string name;
Client *mentoree;
int mentor_percent;
};
class Raid : public GroupIDConsumer {
public:
Raid(Client *nLeader);
@@ -111,6 +118,7 @@ public:
void DisbandRaid();
void MoveMember(const char *name, uint32 newGroup);
void SetGroupLeader(const char *who, bool glFlag = true);
Client *GetGroupLeader(uint32 group_id);
void RemoveGroupLeader(const char *who);
bool IsGroupLeader(const char *who);
bool IsRaidMember(const char *name);
@@ -130,6 +138,8 @@ public:
void AddRaidLooter(const char* looter);
void RemoveRaidLooter(const char* looter);
inline void SetRaidMOTD(std::string in_motd) { motd = in_motd; };
//util func
//keeps me from having to keep iterating through the list
//when I want lots of data from the same entry
@@ -147,9 +157,9 @@ public:
void CastGroupSpell(Mob* caster,uint16 spellid, uint32 gid);
void SplitExp(uint32 exp, Mob* other);
uint32 GetTotalRaidDamage(Mob* other);
void BalanceHP(int32 penalty, uint32 gid, int32 range = 0, Mob* caster = nullptr, int32 limit = 0);
void BalanceMana(int32 penalty, uint32 gid, int32 range = 0, Mob* caster = nullptr, int32 limit = 0);
void HealGroup(uint32 heal_amt, Mob* caster, uint32 gid, int32 range = 0);
void BalanceHP(int32 penalty, uint32 gid, float range = 0, Mob* caster = nullptr, int32 limit = 0);
void BalanceMana(int32 penalty, uint32 gid, float range = 0, Mob* caster = nullptr, int32 limit = 0);
void HealGroup(uint32 heal_amt, Mob* caster, uint32 gid, float range = 0);
void SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client *splitter = nullptr);
void GroupBardPulse(Mob* caster, uint16 spellid, uint32 gid);
@@ -160,6 +170,7 @@ public:
//also learns raid structure based on db.
void SetRaidDetails();
void GetRaidDetails();
void SaveRaidMOTD();
bool LearnMembers();
void VerifyRaid();
void MemberZoned(Client *c);
@@ -194,9 +205,34 @@ public:
void SendMakeGroupLeaderPacketAll();
void SendMakeGroupLeaderPacket(const char *who); //13
void SendMakeGroupLeaderPacketTo(const char *who, Client *to);
void SendRaidMOTD(Client *c);
void SendRaidMOTD();
void SendRaidMOTDToWorld();
void QueuePacket(const EQApplicationPacket *app, bool ack_req = true);
// Leadership
void UpdateGroupAAs(uint32 gid);
void SaveGroupLeaderAA(uint32 gid);
void UpdateRaidAAs();
void SaveRaidLeaderAA();
void SendGroupLeadershipAA(Client *c, uint32 gid);
void SendGroupLeadershipAA(uint32 gid);
void SendAllRaidLeadershipAA();
void LoadLeadership();
inline int GetLeadershipAA(int AAID, uint32 gid = 0)
{ if (AAID >= 16) return raid_aa.ranks[AAID - 16]; else return group_aa[gid].ranks[AAID]; }
inline void SetGroupAAs(uint32 gid, GroupLeadershipAA_Struct *glaa)
{ memcpy(&group_aa[gid], glaa, sizeof(GroupLeadershipAA_Struct)); }
inline void SetRaidAAs(RaidLeadershipAA_Struct *rlaa)
{ memcpy(&raid_aa, rlaa, sizeof(RaidLeadershipAA_Struct)); }
void SetGroupMentor(uint32 group_id, int percent, char *name);
void ClearGroupMentor(uint32 group_id);
void CheckGroupMentor(uint32 group_id, Client *c); // this just checks if we should be fixing the pointer in group mentor struct on zone
inline int GetMentorPercent(uint32 group_id) { return group_mentor[group_id].mentor_percent; }
inline Client *GetMentoree(uint32 group_id) { return group_mentor[group_id].mentoree; }
RaidMember members[MAX_RAID_MEMBERS];
char leadername[64];
protected:
@@ -206,6 +242,11 @@ protected:
uint32 LootType;
bool disbandCheck;
bool forceDisband;
std::string motd;
RaidLeadershipAA_Struct raid_aa;
GroupLeadershipAA_Struct group_aa[MAX_RAID_GROUPS];
GroupMentor group_mentor[MAX_RAID_GROUPS];
};
@@ -1,4 +1,4 @@
#include "RaycastMesh.h"
#include "raycast_mesh.h"
#include <math.h>
#include <assert.h>
#include <stdio.h>

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