mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-16 18:52:22 +00:00
Merge branch 'master' of https://github.com/EQEmu/Server
This commit is contained in:
+8
-9
@@ -481,7 +481,7 @@ void EntityList::AIYellForHelp(Mob* sender, Mob* attacker) {
|
||||
}
|
||||
|
||||
/*
|
||||
solar: returns false if attack should not be allowed
|
||||
returns false if attack should not be allowed
|
||||
I try to list every type of conflict that's possible here, so it's easy
|
||||
to see how the decision is made. Yea, it could be condensed and made
|
||||
faster, but I'm doing it this way to make it readable and easy to modify
|
||||
@@ -550,7 +550,7 @@ bool Mob::IsAttackAllowed(Mob *target, bool isSpellAttack)
|
||||
}
|
||||
}
|
||||
|
||||
// solar: the format here is a matrix of mob type vs mob type.
|
||||
// the format here is a matrix of mob type vs mob type.
|
||||
// redundant ones are omitted and the reverse is tried if it falls through.
|
||||
|
||||
// first figure out if we're pets. we always look at the master's flags.
|
||||
@@ -701,7 +701,7 @@ type', in which case, the answer is yes.
|
||||
}
|
||||
|
||||
|
||||
// solar: this is to check if non detrimental things are allowed to be done
|
||||
// this is to check if non detrimental things are allowed to be done
|
||||
// to the target. clients cannot affect npcs and vice versa, and clients
|
||||
// cannot affect other clients that are not of the same pvp flag as them.
|
||||
// also goes for their pets
|
||||
@@ -717,7 +717,7 @@ bool Mob::IsBeneficialAllowed(Mob *target)
|
||||
if (target->GetAllowBeneficial())
|
||||
return true;
|
||||
|
||||
// solar: see IsAttackAllowed for notes
|
||||
// see IsAttackAllowed for notes
|
||||
|
||||
// first figure out if we're pets. we always look at the master's flags.
|
||||
// no need to compare pets to anything
|
||||
@@ -1233,7 +1233,7 @@ void Mob::ClearFeignMemory() {
|
||||
AIfeignremember_timer->Disable();
|
||||
}
|
||||
|
||||
bool Mob::PassCharismaCheck(Mob* caster, Mob* spellTarget, uint16 spell_id) {
|
||||
bool Mob::PassCharismaCheck(Mob* caster, uint16 spell_id) {
|
||||
|
||||
/*
|
||||
Charm formula is correct based on over 50 hours of personal live parsing - Kayen
|
||||
@@ -1260,9 +1260,9 @@ bool Mob::PassCharismaCheck(Mob* caster, Mob* spellTarget, uint16 spell_id) {
|
||||
return true;
|
||||
|
||||
if (RuleB(Spells, CharismaCharmDuration))
|
||||
resist_check = ResistSpell(spells[spell_id].resisttype, spell_id, caster,0,0,true,true);
|
||||
resist_check = ResistSpell(spells[spell_id].resisttype, spell_id, caster,false,0,true,true);
|
||||
else
|
||||
resist_check = ResistSpell(spells[spell_id].resisttype, spell_id, caster, 0,0, false, true);
|
||||
resist_check = ResistSpell(spells[spell_id].resisttype, spell_id, caster, false,0, false, true);
|
||||
|
||||
//2: The mob makes a resistance check against the charm
|
||||
if (resist_check == 100)
|
||||
@@ -1286,8 +1286,7 @@ bool Mob::PassCharismaCheck(Mob* caster, Mob* spellTarget, uint16 spell_id) {
|
||||
{
|
||||
// Assume this is a harmony/pacify spell
|
||||
// If 'Lull' spell resists, do a second resist check with a charisma modifier AND regular resist checks. If resists agian you gain aggro.
|
||||
resist_check = ResistSpell(spells[spell_id].resisttype, spell_id, caster, true);
|
||||
|
||||
resist_check = ResistSpell(spells[spell_id].resisttype, spell_id, caster, false,0,true);
|
||||
if (resist_check == 100)
|
||||
return true;
|
||||
}
|
||||
|
||||
+3
-3
@@ -343,7 +343,7 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c
|
||||
|
||||
bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte)
|
||||
{
|
||||
/* solar: called when a mob is attacked, does the checks to see if it's a hit
|
||||
/* called when a mob is attacked, does the checks to see if it's a hit
|
||||
* and does other mitigation checks. 'this' is the mob being attacked.
|
||||
*
|
||||
* special return values:
|
||||
@@ -1378,7 +1378,7 @@ void Client::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes att
|
||||
if(spell_id==0)
|
||||
spell_id = SPELL_UNKNOWN;
|
||||
|
||||
// cut all PVP spell damage to 2/3 -solar
|
||||
// cut all PVP spell damage to 2/3
|
||||
// Blasting ourselfs is considered PvP
|
||||
//Don't do PvP mitigation if the caster is damaging himself
|
||||
if(other && other->IsClient() && (other != this) && damage > 0) {
|
||||
@@ -2545,7 +2545,7 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b
|
||||
}
|
||||
}
|
||||
|
||||
// solar: this is called from Damage() when 'this' is attacked by 'other.
|
||||
// this is called from Damage() when 'this' is attacked by 'other.
|
||||
// 'this' is the one being attacked
|
||||
// 'other' is the attacker
|
||||
// a damage shield causes damage (or healing) to whoever attacks the wearer
|
||||
|
||||
+2
-2
@@ -18,7 +18,7 @@
|
||||
|
||||
/*
|
||||
|
||||
solar: Beacon class, extends Mob. Used for AE rain spells to have a mob
|
||||
Beacon class, extends Mob. Used for AE rain spells to have a mob
|
||||
target to center around.
|
||||
|
||||
*/
|
||||
@@ -48,7 +48,7 @@ class Zone;
|
||||
extern EntityList entity_list;
|
||||
extern Zone* zone;
|
||||
|
||||
// solar: if lifetime is 0 this is a permanent beacon.. not sure if that'll be
|
||||
// if lifetime is 0 this is a permanent beacon.. not sure if that'll be
|
||||
// useful for anything
|
||||
Beacon::Beacon(Mob *at_mob, int lifetime)
|
||||
:Mob
|
||||
|
||||
+1
-1
@@ -2976,7 +2976,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
||||
//Special custom cases for loading effects on to NPC from 'npc_spels_effects' table
|
||||
if (IsAISpellEffect) {
|
||||
|
||||
//Non-Focused Effect to modify incomming spell damage by resist type.
|
||||
//Non-Focused Effect to modify incoming spell damage by resist type.
|
||||
case SE_FcSpellVulnerability:
|
||||
ModVulnerability(base2, effect_value);
|
||||
break;
|
||||
|
||||
+2
-2
@@ -7406,7 +7406,7 @@ float Bot::GetProcChances(float ProcBonus, uint16 hand) {
|
||||
|
||||
bool Bot::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte)
|
||||
{
|
||||
/* solar: called when a mob is attacked, does the checks to see if it's a hit
|
||||
/* called when a mob is attacked, does the checks to see if it's a hit
|
||||
* and does other mitigation checks. 'this' is the mob being attacked.
|
||||
*
|
||||
* special return values:
|
||||
@@ -7781,7 +7781,7 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) {
|
||||
|
||||
if (bIsBehind || bCanFrontalBS){ // Bot is behind other OR can do Frontal Backstab
|
||||
|
||||
// solar - chance to assassinate
|
||||
// chance to assassinate
|
||||
int chance = 10 + (GetDEX()/10) + (itembonuses.HeroicDEX/10); //18.5% chance at 85 dex 40% chance at 300 dex
|
||||
if(
|
||||
level >= 60 && // bot is 60 or higher
|
||||
|
||||
+6
-3
@@ -305,6 +305,8 @@ Client::Client(EQStreamInterface* ieqs)
|
||||
|
||||
active_light = innate_light;
|
||||
spell_light = equip_light = NOT_USED;
|
||||
|
||||
AI_Init();
|
||||
}
|
||||
|
||||
Client::~Client() {
|
||||
@@ -402,6 +404,7 @@ Client::~Client() {
|
||||
//let the stream factory know were done with this stream
|
||||
eqs->Close();
|
||||
eqs->ReleaseFromUse();
|
||||
safe_delete(eqs);
|
||||
|
||||
UninitializeBuffSlots();
|
||||
}
|
||||
@@ -7275,7 +7278,7 @@ void Client::SendMercPersonalInfo()
|
||||
stancecount += zone->merc_stance_list[GetMercInfo().MercTemplateID].size();
|
||||
if(stancecount > MAX_MERC_STANCES || mercCount > MAX_MERC || mercTypeCount > MAX_MERC_GRADES)
|
||||
{
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: SendMercPersonalInfo canceled: (%i) (%i) (%i)", stancecount, mercCount, mercTypeCount);
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "SendMercPersonalInfo canceled: (%i) (%i) (%i) for %s", stancecount, mercCount, mercTypeCount, GetName());
|
||||
SendMercMerchantResponsePacket(0);
|
||||
return;
|
||||
}
|
||||
@@ -7369,13 +7372,13 @@ void Client::SendMercPersonalInfo()
|
||||
return;
|
||||
}
|
||||
}
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: SendMercPersonalInfo Send Successful");
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "SendMercPersonalInfo Send Successful for %s.", GetName());
|
||||
|
||||
SendMercMerchantResponsePacket(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: SendMercPersonalInfo Send Failed Due to no MercData for %i", GetMercInfo().MercTemplateID);
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "SendMercPersonalInfo Send Failed Due to no MercData (%i) for %s", GetMercInfo().MercTemplateID, GetName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-2
@@ -64,6 +64,7 @@ struct Item_Struct;
|
||||
#include <float.h>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
|
||||
#define CLIENT_TIMEOUT 90000
|
||||
@@ -201,7 +202,7 @@ struct ClientReward
|
||||
|
||||
class ClientFactory {
|
||||
public:
|
||||
Client *MakeClient(EQStream* ieqs);
|
||||
Client *MakeClient(std::shared_ptr<EQStream> ieqs);
|
||||
};
|
||||
|
||||
class Client : public Mob
|
||||
@@ -1138,7 +1139,7 @@ public:
|
||||
void HandleLFGuildResponse(ServerPacket *pack);
|
||||
void SendLFGuildStatus();
|
||||
void SendGuildLFGuildStatus();
|
||||
inline bool XTargettingAvailable() const { return ((ClientVersionBit & BIT_UnderfootAndLater) && RuleB(Character, EnableXTargetting)); }
|
||||
inline bool XTargettingAvailable() const { return ((ClientVersionBit & BIT_UFAndLater) && RuleB(Character, EnableXTargetting)); }
|
||||
inline uint8 GetMaxXTargets() const { return MaxXTargets; }
|
||||
void SetMaxXTargets(uint8 NewMax);
|
||||
bool IsXTarget(const Mob *m) const;
|
||||
|
||||
+41
-41
@@ -413,15 +413,6 @@ int Client::HandlePacket(const EQApplicationPacket *app)
|
||||
std::cout << "Received 0x" << std::hex << std::setw(4) << std::setfill('0') << opcode << ", size=" << std::dec << app->size << std::endl;
|
||||
#endif
|
||||
|
||||
#ifdef SOLAR
|
||||
if(0 && opcode != OP_ClientUpdate)
|
||||
{
|
||||
Log.LogDebug(Logs::General,"HandlePacket() OPCODE debug enabled client %s", GetName());
|
||||
std::cerr << "OPCODE: " << std::hex << std::setw(4) << std::setfill('0') << opcode << std::dec << ", size: " << app->size << std::endl;
|
||||
DumpPacket(app);
|
||||
}
|
||||
#endif
|
||||
|
||||
switch(client_state) {
|
||||
case CLIENT_CONNECTING: {
|
||||
if(ConnectingOpcodes.count(opcode) != 1) {
|
||||
@@ -848,7 +839,7 @@ void Client::CompleteConnect()
|
||||
worldserver.SendPacket(pack);
|
||||
delete pack;
|
||||
|
||||
if (IsClient() && CastToClient()->GetClientVersionBit() & BIT_UnderfootAndLater) {
|
||||
if (IsClient() && CastToClient()->GetClientVersionBit() & BIT_UFAndLater) {
|
||||
EQApplicationPacket *outapp = MakeBuffsPacket(false);
|
||||
CastToClient()->FastQueuePacket(&outapp);
|
||||
}
|
||||
@@ -1169,7 +1160,6 @@ void Client::Handle_Connect_OP_SendExpZonein(const EQApplicationPacket *app)
|
||||
|
||||
//No idea why live sends this if even were not in a guild
|
||||
SendGuildMOTD();
|
||||
SpawnMercOnZone();
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1227,8 +1217,7 @@ void Client::Handle_Connect_OP_WearChange(const EQApplicationPacket *app)
|
||||
|
||||
void Client::Handle_Connect_OP_WorldObjectsSent(const EQApplicationPacket *app)
|
||||
{
|
||||
//This is a copy of SendExpZonein created for SoF due to packet order change
|
||||
//This does not affect clients other than SoF
|
||||
//This is a copy of SendExpZonein created for SoF+ due to packet order change
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// Spawn Appearance Packet
|
||||
@@ -1295,7 +1284,10 @@ void Client::Handle_Connect_OP_WorldObjectsSent(const EQApplicationPacket *app)
|
||||
//No idea why live sends this if even were not in a guild
|
||||
SendGuildMOTD();
|
||||
|
||||
SpawnMercOnZone();
|
||||
if (RuleB(Mercs, AllowMercs))
|
||||
{
|
||||
SpawnMercOnZone();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1400,6 +1392,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
if (RuleB(Character, SharedBankPlat))
|
||||
m_pp.platinum_shared = database.GetSharedPlatinum(this->AccountID());
|
||||
|
||||
database.ClearOldRecastTimestamps(cid); /* Clear out our old recast timestamps to keep the DB clean */
|
||||
loaditems = database.GetInventory(cid, &m_inv); /* Load Character Inventory */
|
||||
database.LoadCharacterBandolier(cid, &m_pp); /* Load Character Bandolier */
|
||||
database.LoadCharacterBindPoint(cid, &m_pp); /* Load Character Bind */
|
||||
@@ -1864,7 +1857,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
if (ClientVersionBit & BIT_UnderfootAndLater) {
|
||||
if (ClientVersionBit & BIT_UFAndLater) {
|
||||
outapp = new EQApplicationPacket(OP_XTargetResponse, 8);
|
||||
outapp->WriteUInt32(GetMaxXTargets());
|
||||
outapp->WriteUInt32(0);
|
||||
@@ -5503,16 +5496,6 @@ void Client::Handle_OP_EnvDamage(const EQApplicationPacket *app)
|
||||
return;
|
||||
}
|
||||
EnvDamage2_Struct* ed = (EnvDamage2_Struct*)app->pBuffer;
|
||||
if (admin >= minStatusToAvoidFalling && GetGM()){
|
||||
Message(13, "Your GM status protects you from %i points of type %i environmental damage.", ed->damage, ed->dmgtype);
|
||||
SetHP(GetHP() - 1);//needed or else the client wont acknowledge
|
||||
return;
|
||||
}
|
||||
else if (GetInvul()) {
|
||||
Message(13, "Your invuln status protects you from %i points of type %i environmental damage.", ed->damage, ed->dmgtype);
|
||||
SetHP(GetHP() - 1);//needed or else the client wont acknowledge
|
||||
return;
|
||||
}
|
||||
|
||||
int damage = ed->damage;
|
||||
|
||||
@@ -5534,15 +5517,32 @@ void Client::Handle_OP_EnvDamage(const EQApplicationPacket *app)
|
||||
if (damage < 0)
|
||||
damage = 31337;
|
||||
|
||||
else if (zone->GetZoneID() == 183 || zone->GetZoneID() == 184)
|
||||
if (admin >= minStatusToAvoidFalling && GetGM()){
|
||||
Message(13, "Your GM status protects you from %i points of type %i environmental damage.", ed->damage, ed->dmgtype);
|
||||
SetHP(GetHP() - 1);//needed or else the client wont acknowledge
|
||||
return;
|
||||
else
|
||||
SetHP(GetHP() - damage);
|
||||
}
|
||||
else if (GetInvul()) {
|
||||
Message(13, "Your invuln status protects you from %i points of type %i environmental damage.", ed->damage, ed->dmgtype);
|
||||
SetHP(GetHP() - 1);//needed or else the client wont acknowledge
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetHP() <= 0)
|
||||
{
|
||||
mod_client_death_env();
|
||||
else if (zone->GetZoneID() == 183 || zone->GetZoneID() == 184){
|
||||
return;
|
||||
}
|
||||
else{
|
||||
SetHP(GetHP() - (damage * RuleR(Character, EnvironmentDamageMulipliter)));
|
||||
|
||||
/* EVENT_ENVIRONMENTAL_DAMAGE */
|
||||
int final_damage = (damage * RuleR(Character, EnvironmentDamageMulipliter));
|
||||
char buf[24];
|
||||
snprintf(buf, 23, "%u %u %i", ed->damage, ed->dmgtype, final_damage);
|
||||
parse->EventPlayer(EVENT_ENVIRONMENTAL_DAMAGE, this, buf, 0);
|
||||
}
|
||||
|
||||
if (GetHP() <= 0) {
|
||||
mod_client_death_env();
|
||||
Death(0, 32000, SPELL_UNKNOWN, SkillHandtoHand);
|
||||
}
|
||||
SendHPUpdate();
|
||||
@@ -9314,7 +9314,7 @@ void Client::Handle_OP_MercenaryCommand(const EQApplicationPacket *app)
|
||||
uint32 merc_command = mc->MercCommand; // Seen 0 (zone in with no merc or suspended), 1 (dismiss merc), 5 (normal state), 20 (unknown), 36 (zone in with merc)
|
||||
int32 option = mc->Option; // Seen -1 (zone in with no merc), 0 (setting to passive stance), 1 (normal or setting to balanced stance)
|
||||
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: Command %i, Option %i received.", merc_command, option);
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Command %i, Option %i received from %s.", merc_command, option, GetName());
|
||||
|
||||
if (!RuleB(Mercs, AllowMercs))
|
||||
return;
|
||||
@@ -9348,7 +9348,7 @@ void Client::Handle_OP_MercenaryCommand(const EQApplicationPacket *app)
|
||||
merc->SetStance(mercTemplate->Stances[option]);
|
||||
GetMercInfo().Stance = mercTemplate->Stances[option];
|
||||
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: Set Stance: %u", merc->GetStance());
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Set Stance: %u for %s (%s)", merc->GetStance(), merc->GetName(), GetName());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9371,7 +9371,7 @@ void Client::Handle_OP_MercenaryDataRequest(const EQApplicationPacket *app)
|
||||
uint32 merchant_id = mmsr->MercMerchantID;
|
||||
uint32 altCurrentType = 19;
|
||||
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: Data Request for Merchant ID (%i)", merchant_id);
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Data Request for Merchant ID (%i) for %s.", merchant_id, GetName());
|
||||
|
||||
//client is requesting data about currently owned mercenary
|
||||
if (merchant_id == 0) {
|
||||
@@ -9379,12 +9379,12 @@ void Client::Handle_OP_MercenaryDataRequest(const EQApplicationPacket *app)
|
||||
//send info about your current merc(s)
|
||||
if (GetMercInfo().mercid)
|
||||
{
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: SendMercPersonalInfo Request");
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "SendMercPersonalInfo Request for %s.", GetName());
|
||||
SendMercPersonalInfo();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: SendMercPersonalInfo Not Sent - MercID (%i)", GetMercInfo().mercid);
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "SendMercPersonalInfo Not Sent - MercID (%i) for %s.", GetMercInfo().mercid, GetName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9497,7 +9497,7 @@ void Client::Handle_OP_MercenaryDataUpdateRequest(const EQApplicationPacket *app
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: Data Update Request Received.");
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Data Update Request Received for %s.", GetName());
|
||||
|
||||
if (GetMercID())
|
||||
{
|
||||
@@ -9523,7 +9523,7 @@ void Client::Handle_OP_MercenaryDismiss(const EQApplicationPacket *app)
|
||||
Command = VARSTRUCT_DECODE_TYPE(uint8, InBuffer);
|
||||
}
|
||||
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: Dismiss Request ( %i ) Received.", Command);
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Dismiss Request ( %i ) Received for %s.", Command, GetName());
|
||||
|
||||
// Handle the dismiss here...
|
||||
DismissMerc(GetMercInfo().mercid);
|
||||
@@ -9548,7 +9548,7 @@ void Client::Handle_OP_MercenaryHire(const EQApplicationPacket *app)
|
||||
uint32 merc_unk1 = mmrq->MercUnk01;
|
||||
uint32 merc_unk2 = mmrq->MercUnk02;
|
||||
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: Template ID (%i), Merchant ID (%i), Unknown1 (%i), Unknown2 (%i)", merc_template_id, merchant_id, merc_unk1, merc_unk2);
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Template ID (%i), Merchant ID (%i), Unknown1 (%i), Unknown2 (%i), Client: %s", merc_template_id, merchant_id, merc_unk1, merc_unk2, GetName());
|
||||
|
||||
//HirePending = true;
|
||||
SetHoTT(0);
|
||||
@@ -9614,7 +9614,7 @@ void Client::Handle_OP_MercenarySuspendRequest(const EQApplicationPacket *app)
|
||||
SuspendMercenary_Struct* sm = (SuspendMercenary_Struct*)app->pBuffer;
|
||||
uint32 merc_suspend = sm->SuspendMerc; // Seen 30 for suspending or unsuspending
|
||||
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: Suspend ( %i ) received.", merc_suspend);
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Suspend ( %i ) received for %s.", merc_suspend, GetName());
|
||||
|
||||
if (!RuleB(Mercs, AllowMercs))
|
||||
return;
|
||||
@@ -9634,7 +9634,7 @@ void Client::Handle_OP_MercenaryTimerRequest(const EQApplicationPacket *app)
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: Timer Request received.");
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Timer Request received for %s.", GetName());
|
||||
|
||||
if (!RuleB(Mercs, AllowMercs)) {
|
||||
return;
|
||||
|
||||
@@ -960,6 +960,9 @@ void Client::BulkSendInventoryItems()
|
||||
void Client::BulkSendMerchantInventory(int merchant_id, int npcid) {
|
||||
const Item_Struct* handyitem = nullptr;
|
||||
uint32 numItemSlots = 80; //The max number of items passed in the transaction.
|
||||
if (ClientVersionBit & BIT_RoFAndLater) { // RoF+ can send 200 items
|
||||
numItemSlots = 200;
|
||||
}
|
||||
const Item_Struct *item;
|
||||
std::list<MerchantList> merlist = zone->merchanttable[merchant_id];
|
||||
std::list<MerchantList>::const_iterator itr;
|
||||
@@ -2231,7 +2234,7 @@ void Client::ClearHover()
|
||||
entity_list.QueueClients(this, outapp, false);
|
||||
safe_delete(outapp);
|
||||
|
||||
if(IsClient() && CastToClient()->GetClientVersionBit() & BIT_UnderfootAndLater)
|
||||
if(IsClient() && CastToClient()->GetClientVersionBit() & BIT_UFAndLater)
|
||||
{
|
||||
EQApplicationPacket *outapp = MakeBuffsPacket(false);
|
||||
CastToClient()->FastQueuePacket(&outapp);
|
||||
|
||||
+1041
-971
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -7,7 +7,7 @@
|
||||
#define HIGHEST_RESIST 9 //Max resist type value
|
||||
#define MAX_SPELL_PROJECTILE 10 //Max amount of spell projectiles that can be active by a single mob.
|
||||
|
||||
/* solar: macros for IsAttackAllowed, IsBeneficialAllowed */
|
||||
/* macros for IsAttackAllowed, IsBeneficialAllowed */
|
||||
#define _CLIENT(x) (x && x->IsClient() && !x->CastToClient()->IsBecomeNPC())
|
||||
#define _NPC(x) (x && x->IsNPC() && !x->CastToMob()->GetOwnerID())
|
||||
#define _BECOMENPC(x) (x && x->IsClient() && x->CastToClient()->IsBecomeNPC())
|
||||
|
||||
+61
-70
@@ -318,54 +318,30 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
|
||||
// get their tints
|
||||
memcpy(item_tint, &client->GetPP().item_tint, sizeof(item_tint));
|
||||
|
||||
// solar: TODO soulbound items need not be added to corpse, but they need
|
||||
// TODO soulbound items need not be added to corpse, but they need
|
||||
// to go into the regular slots on the player, out of bags
|
||||
|
||||
// possessions
|
||||
// TODO: accomodate soul-bound items
|
||||
std::list<uint32> removed_list;
|
||||
//bool cursor = false;
|
||||
for(i = MAIN_BEGIN; i < EmuConstants::MAP_POSSESSIONS_SIZE; i++) {
|
||||
|
||||
for(i = MAIN_BEGIN; i < EmuConstants::MAP_POSSESSIONS_SIZE; ++i) {
|
||||
if(i == MainAmmo && client->GetClientVersion() >= ClientVersion::SoF) {
|
||||
item = client->GetInv().GetItem(MainPowerSource);
|
||||
if((item && (!client->IsBecomeNPC())) || (item && client->IsBecomeNPC() && !item->GetItem()->NoRent)) {
|
||||
std::list<uint32> slot_list = MoveItemToCorpse(client, item, MainPowerSource);
|
||||
removed_list.merge(slot_list);
|
||||
if (item != nullptr) {
|
||||
if (!client->IsBecomeNPC() || (client->IsBecomeNPC() && !item->GetItem()->NoRent))
|
||||
MoveItemToCorpse(client, item, MainPowerSource, removed_list);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
item = client->GetInv().GetItem(i);
|
||||
if((item && (!client->IsBecomeNPC())) || (item && client->IsBecomeNPC() && !item->GetItem()->NoRent)) {
|
||||
std::list<uint32> slot_list = MoveItemToCorpse(client, item, i);
|
||||
removed_list.merge(slot_list);
|
||||
}
|
||||
if (item == nullptr) { continue; }
|
||||
|
||||
if(!client->IsBecomeNPC() || (client->IsBecomeNPC() && !item->GetItem()->NoRent))
|
||||
MoveItemToCorpse(client, item, i, removed_list);
|
||||
}
|
||||
|
||||
#if 0
|
||||
// This will either be re-enabled or deleted at some point. The client doesn't appear
|
||||
// to like to have items deleted from it's buffer..or, I just haven't figure out how -U
|
||||
// (Besides, the 'corpse' slots equal the size of MapPossessions..not MapPossessions + MapCorpse)
|
||||
|
||||
// cursor queue // (change to first client that supports 'death hover' mode, if not SoF.)
|
||||
if (!RuleB(Character, RespawnFromHover) || client->GetClientVersion() < EQClientSoF) {
|
||||
|
||||
// bumped starting assignment to 8001 because any in-memory 'slot 8000' item was moved above as 'slot 30'
|
||||
// this was mainly for client profile state reflection..should match db player inventory entries now.
|
||||
i = 8001;
|
||||
for (auto it = client->GetInv().cursor_begin(); it != client->GetInv().cursor_end(); ++it, i++) {
|
||||
item = *it;
|
||||
if ((item && (!client->IsBecomeNPC())) || (item && client->IsBecomeNPC() && !item->GetItem()->NoRent)) {
|
||||
std::list<uint32> slot_list = MoveItemToCorpse(client, item, i);
|
||||
removed_list.merge(slot_list);
|
||||
cursor = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
database.TransactionBegin();
|
||||
if (removed_list.size() != 0) {
|
||||
|
||||
// I have an untested process that avoids this snarl up when all possessions inventory is removed..but this isn't broke -U
|
||||
if (!removed_list.empty()) {
|
||||
std::stringstream ss("");
|
||||
ss << "DELETE FROM inventory WHERE charid=" << client->CharacterID();
|
||||
ss << " AND (";
|
||||
@@ -385,18 +361,6 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
|
||||
database.QueryDatabase(ss.str().c_str());
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (cursor) { // all cursor items should be on corpse (client < SoF or RespawnFromHover = false)
|
||||
while (!client->GetInv().CursorEmpty())
|
||||
client->DeleteItemInInventory(MainCursor, 0, false, false);
|
||||
}
|
||||
else { // only visible cursor made it to corpse (client >= Sof and RespawnFromHover = true)
|
||||
std::list<ItemInst*>::const_iterator start = client->GetInv().cursor_begin();
|
||||
std::list<ItemInst*>::const_iterator finish = client->GetInv().cursor_end();
|
||||
database.SaveCursor(client->CharacterID(), start, finish);
|
||||
}
|
||||
#endif
|
||||
|
||||
auto start = client->GetInv().cursor_begin();
|
||||
auto finish = client->GetInv().cursor_end();
|
||||
database.SaveCursor(client->CharacterID(), start, finish);
|
||||
@@ -406,8 +370,13 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
|
||||
|
||||
IsRezzed(false);
|
||||
Save();
|
||||
|
||||
database.TransactionCommit();
|
||||
|
||||
UpdateEquipLightValue();
|
||||
spell_light = NOT_USED;
|
||||
UpdateActiveLightValue();
|
||||
|
||||
return;
|
||||
} //end "not leaving naked corpses"
|
||||
|
||||
@@ -419,32 +388,49 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
|
||||
Save();
|
||||
}
|
||||
|
||||
std::list<uint32> Corpse::MoveItemToCorpse(Client *client, ItemInst *item, int16 equipslot)
|
||||
void Corpse::MoveItemToCorpse(Client *client, ItemInst *inst, int16 equipSlot, std::list<uint32> &removedList)
|
||||
{
|
||||
int bagindex;
|
||||
int16 interior_slot;
|
||||
ItemInst *interior_item;
|
||||
std::list<uint32> returnlist;
|
||||
AddItem(
|
||||
inst->GetItem()->ID,
|
||||
inst->GetCharges(),
|
||||
equipSlot,
|
||||
inst->GetAugmentItemID(0),
|
||||
inst->GetAugmentItemID(1),
|
||||
inst->GetAugmentItemID(2),
|
||||
inst->GetAugmentItemID(3),
|
||||
inst->GetAugmentItemID(4),
|
||||
inst->GetAugmentItemID(5),
|
||||
inst->IsAttuned()
|
||||
);
|
||||
removedList.push_back(equipSlot);
|
||||
|
||||
AddItem(item->GetItem()->ID, item->GetCharges(), equipslot, item->GetAugmentItemID(0), item->GetAugmentItemID(1), item->GetAugmentItemID(2), item->GetAugmentItemID(3), item->GetAugmentItemID(4), item->GetAugmentItemID(5), item->IsAttuned());
|
||||
returnlist.push_back(equipslot);
|
||||
while (true) {
|
||||
if (!inst->IsType(ItemClassContainer)) { break; }
|
||||
if (equipSlot < EmuConstants::GENERAL_BEGIN || equipSlot > MainCursor) { break; }
|
||||
|
||||
// Qualified bag slot iterations. processing bag slots that don't exist is probably not a good idea.
|
||||
if (item->IsType(ItemClassContainer) && ((equipslot >= EmuConstants::GENERAL_BEGIN && equipslot <= MainCursor))) {
|
||||
for (bagindex = SUB_BEGIN; bagindex <= EmuConstants::ITEM_CONTAINER_SIZE; bagindex++) {
|
||||
// For empty bags in cursor queue, slot was previously being resolved as SLOT_INVALID (-1)
|
||||
interior_slot = Inventory::CalcSlotId(equipslot, bagindex);
|
||||
interior_item = client->GetInv().GetItem(interior_slot);
|
||||
for (auto sub_index = SUB_BEGIN; sub_index < EmuConstants::ITEM_CONTAINER_SIZE; ++sub_index) {
|
||||
int16 real_bag_slot = Inventory::CalcSlotId(equipSlot, sub_index);
|
||||
auto bag_inst = client->GetInv().GetItem(real_bag_slot);
|
||||
if (bag_inst == nullptr) { continue; }
|
||||
|
||||
if (interior_item) {
|
||||
AddItem(interior_item->GetItem()->ID, interior_item->GetCharges(), interior_slot, interior_item->GetAugmentItemID(0), interior_item->GetAugmentItemID(1), interior_item->GetAugmentItemID(2), interior_item->GetAugmentItemID(3), interior_item->GetAugmentItemID(4), interior_item->GetAugmentItemID(5), item->IsAttuned());
|
||||
returnlist.push_back(Inventory::CalcSlotId(equipslot, bagindex));
|
||||
client->DeleteItemInInventory(interior_slot, 0, true, false);
|
||||
}
|
||||
AddItem(
|
||||
bag_inst->GetItem()->ID,
|
||||
bag_inst->GetCharges(),
|
||||
real_bag_slot,
|
||||
bag_inst->GetAugmentItemID(0),
|
||||
bag_inst->GetAugmentItemID(1),
|
||||
bag_inst->GetAugmentItemID(2),
|
||||
bag_inst->GetAugmentItemID(3),
|
||||
bag_inst->GetAugmentItemID(4),
|
||||
bag_inst->GetAugmentItemID(5),
|
||||
bag_inst->IsAttuned()
|
||||
);
|
||||
removedList.push_back(real_bag_slot);
|
||||
client->DeleteItemInInventory(real_bag_slot, 0, true, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
client->DeleteItemInInventory(equipslot, 0, true, false);
|
||||
return returnlist;
|
||||
client->DeleteItemInInventory(equipSlot, 0, true, false);
|
||||
}
|
||||
|
||||
// To be called from LoadFromDBData
|
||||
@@ -979,6 +965,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
|
||||
Save();
|
||||
}
|
||||
|
||||
auto timestamps = database.GetItemRecastTimestamps(client->CharacterID());
|
||||
outapp->priority = 6;
|
||||
client->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
@@ -987,6 +974,8 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
|
||||
const Item_Struct* item = database.GetItem(pkitem);
|
||||
ItemInst* inst = database.CreateItem(item, item->MaxCharges);
|
||||
if(inst) {
|
||||
if (item->RecastDelay)
|
||||
inst->SetRecastTimestamp(timestamps.count(item->RecastType) ? timestamps.at(item->RecastType) : 0);
|
||||
client->SendItemPacket(EmuConstants::CORPSE_BEGIN, inst, ItemPacketLoot);
|
||||
safe_delete(inst);
|
||||
}
|
||||
@@ -1018,6 +1007,8 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
|
||||
if(client && item) {
|
||||
ItemInst* inst = database.CreateItem(item, item_data->charges, item_data->aug_1, item_data->aug_2, item_data->aug_3, item_data->aug_4, item_data->aug_5, item_data->aug_6, item_data->attuned);
|
||||
if(inst) {
|
||||
if (item->RecastDelay)
|
||||
inst->SetRecastTimestamp(timestamps.count(item->RecastType) ? timestamps.at(item->RecastType) : 0);
|
||||
// MainGeneral1 is the corpse inventory start offset for Ti(EMu) - CORPSE_END = MainGeneral1 + MainCursor
|
||||
client->SendItemPacket(i + EmuConstants::CORPSE_BEGIN, inst, ItemPacketLoot);
|
||||
safe_delete(inst);
|
||||
@@ -1474,4 +1465,4 @@ void Corpse::LoadPlayerCorpseDecayTime(uint32 corpse_db_id){
|
||||
else {
|
||||
corpse_graveyard_timer.SetTimer(3000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -128,7 +128,7 @@ class Corpse : public Mob {
|
||||
virtual void UpdateEquipLightValue();
|
||||
|
||||
protected:
|
||||
std::list<uint32> MoveItemToCorpse(Client *client, ItemInst *item, int16 equipslot);
|
||||
void MoveItemToCorpse(Client *client, ItemInst *inst, int16 equipSlot, std::list<uint32> &removedList);
|
||||
|
||||
private:
|
||||
bool is_player_corpse; /* Determines if Player Corpse or not */
|
||||
|
||||
+2
-2
@@ -684,7 +684,7 @@ void EntityList::AETaunt(Client* taunter, float range)
|
||||
}
|
||||
}
|
||||
|
||||
// solar: causes caster to hit every mob within dist range of center with
|
||||
// causes caster to hit every mob within dist range of center with
|
||||
// spell_id.
|
||||
// NPC spells will only affect other NPCs with compatible faction
|
||||
void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster, int16 resist_adjust)
|
||||
@@ -820,7 +820,7 @@ void EntityList::MassGroupBuff(Mob *caster, Mob *center, uint16 spell_id, bool a
|
||||
}
|
||||
}
|
||||
|
||||
// solar: causes caster to hit every mob within dist range of center with
|
||||
// causes caster to hit every mob within dist range of center with
|
||||
// a bard pulse of spell_id.
|
||||
// NPC spells will only affect other NPCs with compatible faction
|
||||
void EntityList::AEBardPulse(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster)
|
||||
|
||||
@@ -65,6 +65,7 @@ const char *QuestEventSubroutines[_LargestEventID] = {
|
||||
"EVENT_AGGRO_SAY",
|
||||
"EVENT_PLAYER_PICKUP",
|
||||
"EVENT_POPUPRESPONSE",
|
||||
"EVENT_ENVIRONMENTAL_DAMAGE",
|
||||
"EVENT_PROXIMITY_SAY",
|
||||
"EVENT_CAST",
|
||||
"EVENT_CAST_BEGIN",
|
||||
@@ -1290,6 +1291,13 @@ void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID
|
||||
ExportVar(package_name.c_str(), "popupid", data);
|
||||
break;
|
||||
}
|
||||
case EVENT_ENVIRONMENTAL_DAMAGE:{
|
||||
Seperator sep(data);
|
||||
ExportVar(package_name.c_str(), "env_damage", sep.arg[0]);
|
||||
ExportVar(package_name.c_str(), "env_damage_type", sep.arg[1]);
|
||||
ExportVar(package_name.c_str(), "env_final_damage", sep.arg[2]);
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_PROXIMITY_SAY: {
|
||||
ExportVar(package_name.c_str(), "data", objid);
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "../common/global_define.h"
|
||||
#include "../common/misc_functions.h"
|
||||
#include "../common/eqemu_logsys.h"
|
||||
|
||||
#include "embparser.h"
|
||||
#include "embxs.h"
|
||||
@@ -3493,6 +3494,37 @@ XS(XS__crosszonesignalnpcbynpctypeid)
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS__debug);
|
||||
XS(XS__debug)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1 && items != 2){
|
||||
Perl_croak(aTHX_ "Usage: debug(message, [debug_level])");
|
||||
}
|
||||
else{
|
||||
std::string log_message = (std::string)SvPV_nolen(ST(0));
|
||||
uint8 debug_level = 1;
|
||||
|
||||
if (items == 2)
|
||||
debug_level = (uint8)SvIV(ST(1));
|
||||
|
||||
if (debug_level > Logs::Detail)
|
||||
return;
|
||||
|
||||
if (debug_level == Logs::General){
|
||||
Log.Out(Logs::General, Logs::QuestDebug, log_message);
|
||||
}
|
||||
else if (debug_level == Logs::Moderate){
|
||||
Log.Out(Logs::Moderate, Logs::QuestDebug, log_message);
|
||||
}
|
||||
else if (debug_level == Logs::Detail){
|
||||
Log.Out(Logs::Detail, Logs::QuestDebug, log_message);
|
||||
}
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
This is the callback perl will look for to setup the
|
||||
quest package's XSUBs
|
||||
@@ -3579,6 +3611,7 @@ EXTERN_C XS(boot_quest)
|
||||
newXS(strcpy(buf, "crosszonesignalclientbycharid"), XS__crosszonesignalclientbycharid, file);
|
||||
newXS(strcpy(buf, "crosszonesignalclientbyname"), XS__crosszonesignalclientbyname, file);
|
||||
newXS(strcpy(buf, "crosszonesignalnpcbynpctypeid"), XS__crosszonesignalnpcbynpctypeid, file);
|
||||
newXS(strcpy(buf, "debug"), XS__debug, file);
|
||||
newXS(strcpy(buf, "delglobal"), XS__delglobal, file);
|
||||
newXS(strcpy(buf, "depop"), XS__depop, file);
|
||||
newXS(strcpy(buf, "depop_withtimer"), XS__depop_withtimer, file);
|
||||
|
||||
@@ -33,6 +33,7 @@ typedef enum {
|
||||
EVENT_AGGRO_SAY,
|
||||
EVENT_PLAYER_PICKUP,
|
||||
EVENT_POPUP_RESPONSE,
|
||||
EVENT_ENVIRONMENTAL_DAMAGE,
|
||||
EVENT_PROXIMITY_SAY,
|
||||
EVENT_CAST,
|
||||
EVENT_CAST_BEGIN,
|
||||
|
||||
+1
-2
@@ -506,8 +506,7 @@ void Client::SetLevel(uint8 set_level, bool command)
|
||||
SetMana(CalcMaxMana());
|
||||
UpdateWho();
|
||||
|
||||
if(GetMerc())
|
||||
UpdateMercLevel();
|
||||
UpdateMercLevel();
|
||||
|
||||
Save();
|
||||
}
|
||||
|
||||
+2
-2
@@ -879,7 +879,7 @@ void Client::PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootI
|
||||
|
||||
if(bag_item_data) { // bag contents
|
||||
int16 interior_slot;
|
||||
// solar: our bag went into slot_id, now let's pack the contents in
|
||||
// our bag went into slot_id, now let's pack the contents in
|
||||
for(int i = SUB_BEGIN; i < EmuConstants::ITEM_CONTAINER_SIZE; i++) {
|
||||
if(bag_item_data[i] == nullptr)
|
||||
continue;
|
||||
@@ -993,7 +993,7 @@ bool Client::AutoPutLootInInventory(ItemInst& inst, bool try_worn, bool try_curs
|
||||
return false;
|
||||
}
|
||||
|
||||
// solar: helper function for AutoPutLootInInventory
|
||||
// helper function for AutoPutLootInInventory
|
||||
void Client::MoveItemCharges(ItemInst &from, int16 to_slot, uint8 type)
|
||||
{
|
||||
ItemInst *tmp_inst = m_inv.GetItem(to_slot);
|
||||
|
||||
@@ -1612,6 +1612,7 @@ luabind::scope lua_register_events() {
|
||||
luabind::value("cast_on", static_cast<int>(EVENT_CAST_ON)),
|
||||
luabind::value("task_accepted", static_cast<int>(EVENT_TASK_ACCEPTED)),
|
||||
luabind::value("task_stage_complete", static_cast<int>(EVENT_TASK_STAGE_COMPLETE)),
|
||||
luabind::value("environmental_damage", static_cast<int>(EVENT_ENVIRONMENTAL_DAMAGE)),
|
||||
luabind::value("task_update", static_cast<int>(EVENT_TASK_UPDATE)),
|
||||
luabind::value("task_complete", static_cast<int>(EVENT_TASK_COMPLETE)),
|
||||
luabind::value("task_fail", static_cast<int>(EVENT_TASK_FAIL)),
|
||||
@@ -1759,12 +1760,11 @@ luabind::scope lua_register_client_version() {
|
||||
.enum_("constants")
|
||||
[
|
||||
luabind::value("Unknown", static_cast<int>(ClientVersion::Unknown)),
|
||||
luabind::value("Titanium", static_cast<int>(ClientVersion::Tit)), // deprecated
|
||||
luabind::value("Tit", static_cast<int>(ClientVersion::Tit)),
|
||||
luabind::value("Titanium", static_cast<int>(ClientVersion::Titanium)),
|
||||
luabind::value("SoF", static_cast<int>(ClientVersion::SoF)),
|
||||
luabind::value("SoD", static_cast<int>(ClientVersion::SoD)),
|
||||
luabind::value("Underfoot", static_cast<int>(ClientVersion::Und)), // deprecated
|
||||
luabind::value("Und", static_cast<int>(ClientVersion::Und)),
|
||||
luabind::value("Underfoot", static_cast<int>(ClientVersion::UF)), // deprecated
|
||||
luabind::value("UF", static_cast<int>(ClientVersion::UF)),
|
||||
luabind::value("RoF", static_cast<int>(ClientVersion::RoF)),
|
||||
luabind::value("RoF2", static_cast<int>(ClientVersion::RoF2))
|
||||
];
|
||||
|
||||
+3
-1
@@ -35,13 +35,14 @@
|
||||
#include "zone.h"
|
||||
#include "lua_parser.h"
|
||||
|
||||
const char *LuaEvents[_LargestEventID] = {
|
||||
const char *LuaEvents[_LargestEventID] = {
|
||||
"event_say",
|
||||
"event_trade",
|
||||
"event_death",
|
||||
"event_spawn",
|
||||
"event_attack",
|
||||
"event_combat",
|
||||
"event_environmental_damage",
|
||||
"event_aggro",
|
||||
"event_slay",
|
||||
"event_npc_slay",
|
||||
@@ -164,6 +165,7 @@ LuaParser::LuaParser() {
|
||||
NPCArgumentDispatch[EVENT_LEAVE_AREA] = handle_npc_area;
|
||||
|
||||
PlayerArgumentDispatch[EVENT_SAY] = handle_player_say;
|
||||
PlayerArgumentDispatch[EVENT_ENVIRONMENTAL_DAMAGE] = handle_player_environmental_damage;
|
||||
PlayerArgumentDispatch[EVENT_DEATH] = handle_player_death;
|
||||
PlayerArgumentDispatch[EVENT_DEATH_COMPLETE] = handle_player_death;
|
||||
PlayerArgumentDispatch[EVENT_TIMER] = handle_player_timer;
|
||||
|
||||
@@ -246,6 +246,19 @@ void handle_player_say(QuestInterface *parse, lua_State* L, Client* client, std:
|
||||
lua_setfield(L, -2, "language");
|
||||
}
|
||||
|
||||
void handle_player_environmental_damage(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
||||
std::vector<EQEmu::Any> *extra_pointers){
|
||||
Seperator sep(data.c_str());
|
||||
lua_pushinteger(L, std::stoi(sep.arg[0]));
|
||||
lua_setfield(L, -2, "env_damage");
|
||||
|
||||
lua_pushinteger(L, std::stoi(sep.arg[1]));
|
||||
lua_setfield(L, -2, "env_damage_type");
|
||||
|
||||
lua_pushinteger(L, std::stoi(sep.arg[2]));
|
||||
lua_setfield(L, -2, "env_final_damage");
|
||||
}
|
||||
|
||||
void handle_player_death(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
||||
std::vector<EQEmu::Any> *extra_pointers) {
|
||||
Seperator sep(data.c_str());
|
||||
|
||||
@@ -44,6 +44,8 @@ void handle_npc_null(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, s
|
||||
//Player
|
||||
void handle_player_say(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
||||
std::vector<EQEmu::Any> *extra_pointers);
|
||||
void handle_player_environmental_damage(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
||||
std::vector<EQEmu::Any> *extra_pointers);
|
||||
void handle_player_death(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
||||
std::vector<EQEmu::Any> *extra_pointers);
|
||||
void handle_player_timer(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
||||
|
||||
+4
-4
@@ -413,9 +413,9 @@ bool Map::LoadV2(FILE *f) {
|
||||
buf += sizeof(uint32);
|
||||
}
|
||||
|
||||
std::map<std::string, std::shared_ptr<ModelEntry>> models;
|
||||
std::map<std::string, std::unique_ptr<ModelEntry>> models;
|
||||
for (uint32 i = 0; i < model_count; ++i) {
|
||||
std::shared_ptr<ModelEntry> me(new ModelEntry);
|
||||
std::unique_ptr<ModelEntry> me(new ModelEntry);
|
||||
std::string name = buf;
|
||||
buf += name.length() + 1;
|
||||
|
||||
@@ -456,7 +456,7 @@ bool Map::LoadV2(FILE *f) {
|
||||
me->polys[j] = p;
|
||||
}
|
||||
|
||||
models[name] = me;
|
||||
models[name] = std::move(me);
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < plac_count; ++i) {
|
||||
@@ -487,7 +487,7 @@ bool Map::LoadV2(FILE *f) {
|
||||
if (models.count(name) == 0)
|
||||
continue;
|
||||
|
||||
auto model = models[name];
|
||||
auto &model = models[name];
|
||||
auto &mod_polys = model->polys;
|
||||
auto &mod_verts = model->verts;
|
||||
for (uint32 j = 0; j < mod_polys.size(); ++j) {
|
||||
|
||||
+250
-101
@@ -42,7 +42,7 @@ Merc::Merc(const NPCType* d, float x, float y, float z, float heading)
|
||||
_baseFR = d->FR;
|
||||
_basePR = d->PR;
|
||||
_baseCorrup = d->Corrup;
|
||||
_OwnerClientVersion = static_cast<unsigned int>(ClientVersion::Tit);
|
||||
_OwnerClientVersion = static_cast<unsigned int>(ClientVersion::Titanium);
|
||||
RestRegenHP = 0;
|
||||
RestRegenMana = 0;
|
||||
RestRegenEndurance = 0;
|
||||
@@ -75,7 +75,6 @@ Merc::Merc(const NPCType* d, float x, float y, float z, float heading)
|
||||
SetMana(GetMaxMana());
|
||||
SetEndurance(GetMaxEndurance());
|
||||
|
||||
AI_Init();
|
||||
AI_Start();
|
||||
}
|
||||
|
||||
@@ -1737,7 +1736,6 @@ void Merc::AI_Process() {
|
||||
}
|
||||
|
||||
void Merc::AI_Start(int32 iMoveDelay) {
|
||||
NPC::AI_Start(iMoveDelay);
|
||||
if (!pAIControlled)
|
||||
return;
|
||||
|
||||
@@ -2244,7 +2242,7 @@ bool Merc::AICastSpell(int8 iChance, int32 iSpellTypes) {
|
||||
if(CheckAETaunt()) {
|
||||
//get AE taunt
|
||||
selectedMercSpell = GetBestMercSpellForAETaunt(this);
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "AE Taunting");
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "%s AE Taunting.", GetName());
|
||||
}
|
||||
|
||||
if(selectedMercSpell.spellid == 0 && CheckTaunt()) {
|
||||
@@ -4766,12 +4764,13 @@ Merc* Merc::LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id,
|
||||
npc_type->no_target_hotkey = 1;
|
||||
|
||||
Merc* merc = new Merc(npc_type, c->GetX(), c->GetY(), c->GetZ(), 0);
|
||||
merc->GiveNPCTypeData(npc_type); // for clean up, works a bit like pets
|
||||
|
||||
if(merc)
|
||||
{
|
||||
merc->SetMercData( merc_template->MercTemplateID );
|
||||
database.LoadMercEquipment(merc);
|
||||
merc->UpdateMercStats(c);
|
||||
merc->UpdateMercStats(c, true);
|
||||
|
||||
if(updateFromDB)
|
||||
{
|
||||
@@ -4809,6 +4808,7 @@ Merc* Merc::LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id,
|
||||
merc->LoadMercSpells();
|
||||
}
|
||||
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "LoadMerc Successful for %s (%s).", merc->GetName(), c->GetName());
|
||||
return merc;
|
||||
}
|
||||
}
|
||||
@@ -4837,50 +4837,184 @@ void Merc::UpdateMercInfo(Client *c) {
|
||||
c->GetMercInfo().drakkinDetails = drakkin_details;
|
||||
}
|
||||
|
||||
void Merc::UpdateMercStats(Client *c) {
|
||||
if(c->GetMercInfo().MercTemplateID >0)
|
||||
{
|
||||
const NPCType* npc_type = database.GetMercType( zone->GetMercTemplate(c->GetMercInfo().MercTemplateID)->MercNPCID, GetRace(), c->GetLevel());
|
||||
if (npc_type)
|
||||
{
|
||||
max_hp = (npc_type->max_hp * npc_type->scalerate) / 100;
|
||||
base_hp = (npc_type->max_hp * npc_type->scalerate) / 100;
|
||||
max_mana = (npc_type->Mana * npc_type->scalerate) / 100;
|
||||
base_mana = (npc_type->Mana * npc_type->scalerate) / 100;
|
||||
hp_regen = (npc_type->hp_regen * npc_type->scalerate) / 100;
|
||||
mana_regen = (npc_type->mana_regen * npc_type->scalerate) / 100;
|
||||
void Merc::UpdateMercStats(Client *c, bool setmax)
|
||||
{
|
||||
if (c->GetMercInfo().MercTemplateID > 0) {
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Updating Mercenary Stats for %s (%s).", GetName(),
|
||||
c->GetName());
|
||||
const NPCType *npc_type = database.GetMercType(
|
||||
zone->GetMercTemplate(c->GetMercInfo().MercTemplateID)->MercNPCID, GetRace(), c->GetLevel());
|
||||
if (npc_type) {
|
||||
max_hp = npc_type->max_hp;
|
||||
base_hp = npc_type->max_hp;
|
||||
max_mana = npc_type->Mana;
|
||||
base_mana = npc_type->Mana;
|
||||
max_end = npc_type->max_hp; // Hack since Endurance does not exist for NPCType yet
|
||||
base_end = npc_type->max_hp; // Hack since Endurance does not exist for NPCType yet
|
||||
hp_regen = npc_type->hp_regen;
|
||||
mana_regen = npc_type->mana_regen;
|
||||
max_dmg = npc_type->max_dmg;
|
||||
min_dmg = npc_type->min_dmg;
|
||||
|
||||
_baseAC = npc_type->AC;
|
||||
_baseATK = npc_type->ATK;
|
||||
_baseSTR = npc_type->STR;
|
||||
_baseSTA = npc_type->STA;
|
||||
_baseDEX = npc_type->DEX;
|
||||
_baseAGI = npc_type->AGI;
|
||||
_baseWIS = npc_type->WIS;
|
||||
_baseINT = npc_type->INT;
|
||||
_baseCHA = npc_type->CHA;
|
||||
_baseATK = npc_type->ATK;
|
||||
_baseMR = npc_type->MR;
|
||||
_baseFR = npc_type->FR;
|
||||
_baseDR = npc_type->DR;
|
||||
_basePR = npc_type->PR;
|
||||
_baseCR = npc_type->CR;
|
||||
_baseCorrup = npc_type->Corrup;
|
||||
|
||||
uint32 scalepercent = (int)(npc_type->scalerate * RuleI(Mercs, ScaleRate) / 100);
|
||||
|
||||
ScaleStats(scalepercent, setmax);
|
||||
|
||||
level = npc_type->level;
|
||||
max_dmg = (npc_type->max_dmg * npc_type->scalerate) / 100;
|
||||
min_dmg = (npc_type->min_dmg * npc_type->scalerate) / 100;
|
||||
_baseSTR = (npc_type->STR * npc_type->scalerate) / 100;
|
||||
_baseSTA = (npc_type->STA * npc_type->scalerate) / 100;
|
||||
_baseDEX = (npc_type->DEX * npc_type->scalerate) / 100;
|
||||
_baseAGI = (npc_type->AGI * npc_type->scalerate) / 100;
|
||||
_baseWIS = (npc_type->WIS * npc_type->scalerate) / 100;
|
||||
_baseINT = (npc_type->INT * npc_type->scalerate) / 100;
|
||||
_baseCHA = (npc_type->CHA * npc_type->scalerate) / 100;
|
||||
_baseATK = (npc_type->ATK * npc_type->scalerate) / 100;
|
||||
_baseMR = (npc_type->MR * npc_type->scalerate) / 100;
|
||||
_baseFR = (npc_type->FR * npc_type->scalerate) / 100;
|
||||
_baseDR = (npc_type->DR * npc_type->scalerate) / 100;
|
||||
_basePR = (npc_type->PR * npc_type->scalerate) / 100;
|
||||
_baseCR = (npc_type->CR * npc_type->scalerate) / 100;
|
||||
_baseCorrup = (npc_type->Corrup * npc_type->scalerate) / 100;
|
||||
_baseAC = (npc_type->AC * npc_type->scalerate) / 100;
|
||||
attack_speed = npc_type->attack_speed;
|
||||
attack_count = npc_type->attack_count;
|
||||
attack_delay = npc_type->attack_delay;
|
||||
spellscale = npc_type->spellscale;
|
||||
healscale = npc_type->healscale;
|
||||
|
||||
CalcBonuses();
|
||||
|
||||
CalcMaxEndurance();
|
||||
CalcMaxHP();
|
||||
CalcMaxMana();
|
||||
CalcMaxEndurance();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Merc::ScaleStats(int scalepercent, bool setmax) {
|
||||
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Scaling Mercenary Stats to %d Percent for %s.", scalepercent, GetName());
|
||||
|
||||
if (scalepercent <= 0)
|
||||
return;
|
||||
|
||||
float scalerate = (float)scalepercent / 100.0f;
|
||||
|
||||
if ((int)((float)base_hp * scalerate) > 1)
|
||||
{
|
||||
max_hp = (int)((float)base_hp * scalerate);
|
||||
base_hp = max_hp;
|
||||
if (setmax)
|
||||
cur_hp = max_hp;
|
||||
}
|
||||
|
||||
if (base_mana)
|
||||
{
|
||||
max_mana = (int)((float)base_mana * scalerate);
|
||||
base_mana = max_mana;
|
||||
if (setmax)
|
||||
cur_mana = max_mana;
|
||||
}
|
||||
|
||||
if (base_end)
|
||||
{
|
||||
max_end = (int)((float)base_end * scalerate);
|
||||
base_end = max_end;
|
||||
if (setmax)
|
||||
cur_end = max_end;
|
||||
}
|
||||
|
||||
if (_baseAC)
|
||||
{
|
||||
AC = (int)((float)_baseAC * scalerate);
|
||||
_baseAC = AC;
|
||||
}
|
||||
|
||||
if (_baseATK)
|
||||
{
|
||||
ATK = (int)((float)_baseATK * scalerate);
|
||||
_baseATK = ATK;
|
||||
}
|
||||
|
||||
if (_baseSTR)
|
||||
{
|
||||
STR = (int)((float)_baseSTR * scalerate);
|
||||
_baseSTR = STR;
|
||||
}
|
||||
if (_baseSTA)
|
||||
{
|
||||
STA = (int)((float)_baseSTA * scalerate);
|
||||
_baseSTA = STA;
|
||||
}
|
||||
if (_baseAGI)
|
||||
{
|
||||
AGI = (int)((float)_baseAGI * scalerate);
|
||||
_baseAGI = AGI;
|
||||
}
|
||||
if (_baseDEX)
|
||||
{
|
||||
DEX = (int)((float)_baseDEX * scalerate);
|
||||
_baseDEX = DEX;
|
||||
}
|
||||
if (_baseINT)
|
||||
{
|
||||
INT = (int)((float)_baseINT * scalerate);
|
||||
_baseINT = INT;
|
||||
}
|
||||
if (_baseWIS)
|
||||
{
|
||||
WIS = (int)((float)_baseWIS * scalerate);
|
||||
_baseWIS = WIS;
|
||||
}
|
||||
if (_baseCHA)
|
||||
{
|
||||
CHA = (int)((float)_baseCHA * scalerate);
|
||||
_baseCHA = CHA;
|
||||
}
|
||||
|
||||
if (_baseMR)
|
||||
{
|
||||
MR = (int)((float)_baseMR * scalerate);
|
||||
_baseMR = MR;
|
||||
}
|
||||
if (_baseCR)
|
||||
{
|
||||
CR = (int)((float)_baseCR * scalerate);
|
||||
_baseCR = CR;
|
||||
}
|
||||
if (_baseDR)
|
||||
{
|
||||
DR = (int)((float)_baseDR * scalerate);
|
||||
_baseDR = DR;
|
||||
}
|
||||
if (_baseFR)
|
||||
{
|
||||
FR = (int)((float)_baseFR * scalerate);
|
||||
_baseFR = FR;
|
||||
}
|
||||
if (_basePR)
|
||||
{
|
||||
PR = (int)((float)_basePR * scalerate);
|
||||
_basePR = PR;
|
||||
}
|
||||
if (_baseCorrup)
|
||||
{
|
||||
Corrup = (int)((float)_baseCorrup * scalerate);
|
||||
_baseCorrup = Corrup;
|
||||
}
|
||||
|
||||
if (max_dmg)
|
||||
{
|
||||
max_dmg = (int)((float)max_dmg * scalerate);
|
||||
}
|
||||
if (min_dmg)
|
||||
{
|
||||
min_dmg = (int)((float)min_dmg * scalerate);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Merc::UpdateMercAppearance() {
|
||||
// Copied from Bot Code:
|
||||
uint32 itemID = NO_ITEM;
|
||||
@@ -4938,7 +5072,7 @@ bool Merc::Spawn(Client *owner) {
|
||||
|
||||
SendPosition();
|
||||
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: Spawn.");
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Spawn Mercenary %s.", GetName());
|
||||
|
||||
//UpdateMercAppearance();
|
||||
|
||||
@@ -5084,7 +5218,8 @@ void Client::SendMercResponsePackets(uint32 ResponseType)
|
||||
SendMercMerchantResponsePacket(3);
|
||||
break;
|
||||
}
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: SendMercResponsePackets %i.", ResponseType);
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "SendMercResponsePackets %i for %s.", ResponseType, GetName());
|
||||
|
||||
}
|
||||
|
||||
void Client::UpdateMercTimer()
|
||||
@@ -5125,7 +5260,7 @@ void Client::UpdateMercTimer()
|
||||
SendMercResponsePackets(16);
|
||||
}
|
||||
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: UpdateMercTimer Complete.");
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "UpdateMercTimer Complete for %s.", GetName());
|
||||
|
||||
// Normal upkeep charge message
|
||||
//Message(7, "You have been charged a mercenary upkeep cost of %i plat, and %i gold and your mercenary upkeep cost timer has been reset to 15 minutes.", upkeep_plat, upkeep_gold, (int)(RuleI(Mercs, UpkeepIntervalMS) / 1000 / 60));
|
||||
@@ -5178,7 +5313,7 @@ bool Client::CheckCanHireMerc(Mob* merchant, uint32 template_id) {
|
||||
}
|
||||
}
|
||||
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: CheckCanHireMerc True.");
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "CheckCanHireMerc True for %s.", GetName());
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -5251,7 +5386,7 @@ bool Client::CheckCanSpawnMerc(uint32 template_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: CheckCanSpawnMerc True.");
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "CheckCanSpawnMerc True for %s.", GetName());
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -5273,7 +5408,7 @@ bool Client::CheckCanUnsuspendMerc() {
|
||||
return false;
|
||||
}
|
||||
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: CheckCanUnsuspendMerc True.");
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "CheckCanUnsuspendMerc True for %s.", GetName());
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -5288,7 +5423,7 @@ void Client::CheckMercSuspendTimer() {
|
||||
GetMercInfo().SuspendedTime = 0;
|
||||
SendMercResponsePackets(0);
|
||||
SendMercSuspendResponsePacket(GetMercInfo().SuspendedTime);
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: CheckMercSuspendTimer Ready.");
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "CheckMercSuspendTimer Ready for %s.", GetName());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5301,7 +5436,7 @@ void Client::SuspendMercCommand() {
|
||||
{
|
||||
if(!CheckCanUnsuspendMerc())
|
||||
{
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: SuspendMercCommand Unable to Unsuspend.");
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "SuspendMercCommand Unable to Unsuspend Merc for %s.", GetName());
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -5311,13 +5446,13 @@ void Client::SuspendMercCommand() {
|
||||
if(merc)
|
||||
{
|
||||
SpawnMerc(merc, true);
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: SuspendMercCommand Successful Unsuspend.");
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "SuspendMercCommand Successful Unsuspend for %s.", GetName());
|
||||
}
|
||||
else
|
||||
{
|
||||
//merc failed to spawn
|
||||
SendMercResponsePackets(3);
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: SuspendMercCommand Failed to Spawn Merc.");
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "SuspendMercCommand Failed to Spawn Merc for %s.", GetName());
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -5327,10 +5462,27 @@ void Client::SuspendMercCommand() {
|
||||
if(CurrentMerc && GetMercID())
|
||||
{
|
||||
CurrentMerc->Suspend();
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: SuspendMercCommand Successful Suspend.");
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "SuspendMercCommand Successful Suspend for %s.", GetName());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reset Merc Suspend State
|
||||
GetMercInfo().IsSuspended = true;
|
||||
//GetMercInfo().SuspendedTime = time(nullptr) + RuleI(Mercs, SuspendIntervalS);
|
||||
//GetMercInfo().MercTimerRemaining = GetMercTimer()->GetRemainingTime();
|
||||
//GetMercInfo().Stance = GetStance();
|
||||
GetMercTimer()->Disable();
|
||||
SendMercSuspendResponsePacket(GetMercInfo().SuspendedTime);
|
||||
SendMercTimer(nullptr);
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "SuspendMercCommand Failed to Get Merc to Suspend. Resetting Suspend State for %s.", GetName());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SpawnMercOnZone();
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "SuspendMercCommand Request Failed to Load Merc for %s. Trying SpawnMercOnZone.", GetName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5362,7 +5514,7 @@ void Client::SpawnMercOnZone() {
|
||||
{
|
||||
SpawnMerc(merc, false);
|
||||
}
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: SpawnMercOnZone Normal Merc.");
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "SpawnMercOnZone Normal Merc for %s.", GetName());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -5378,13 +5530,15 @@ void Client::SpawnMercOnZone() {
|
||||
// Send Mercenary Status/Timer packet
|
||||
SendMercTimer(GetMerc());
|
||||
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: SpawnMercOnZone Suspended Merc.");
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "SpawnMercOnZone Suspended Merc for %s.", GetName());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No Merc Hired
|
||||
SendClearMercInfo();
|
||||
// RoF+ displays a message from the following packet, which seems useless
|
||||
//SendClearMercInfo();
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "SpawnMercOnZone Failed to load Merc Info from the Database for %s.", GetName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5398,17 +5552,17 @@ void Client::SendMercTimer(Merc* merc) {
|
||||
if (!merc)
|
||||
{
|
||||
SendMercTimerPacket(NO_MERC_ID, MERC_STATE_SUSPENDED, GetMercInfo().SuspendedTime, GetMercInfo().MercTimerRemaining, RuleI(Mercs, SuspendIntervalMS));
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: SendMercTimer No Merc.");
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "SendMercTimer No Merc for %s.", GetName());
|
||||
}
|
||||
else if (merc->IsSuspended())
|
||||
{
|
||||
SendMercTimerPacket(NO_MERC_ID, MERC_STATE_SUSPENDED, GetMercInfo().SuspendedTime, GetMercInfo().MercTimerRemaining, RuleI(Mercs, SuspendIntervalMS));
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: SendMercTimer Suspended Merc.");
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "SendMercTimer Suspended Merc for %s.", GetName());
|
||||
}
|
||||
else
|
||||
{
|
||||
SendMercTimerPacket(merc->GetID(), MERC_STATE_NORMAL, NOT_SUSPENDED_TIME, GetMercInfo().MercTimerRemaining, RuleI(Mercs, SuspendIntervalMS));
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: SendMercTimer Normal Merc.");
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "SendMercTimer Normal Merc for %s.", GetName());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5430,7 +5584,7 @@ void Client::SpawnMerc(Merc* merc, bool setMaxStats) {
|
||||
merc->Unsuspend(setMaxStats);
|
||||
merc->SetStance(GetMercInfo().Stance);
|
||||
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: SpawnMerc Success.");
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "SpawnMerc Success for %s.", GetName());
|
||||
|
||||
return;
|
||||
|
||||
@@ -5459,7 +5613,7 @@ bool Merc::Suspend() {
|
||||
// Start the timer to send the packet that refreshes the Unsuspend Button
|
||||
mercOwner->GetPTimers().Start(pTimerMercSuspend, RuleI(Mercs, SuspendIntervalS));
|
||||
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: Suspend Complete.");
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Suspend Complete for %s.", mercOwner->GetName());
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -5545,12 +5699,12 @@ bool Client::DismissMerc(uint32 MercID) {
|
||||
bool Dismissed = true;
|
||||
if (!database.DeleteMerc(MercID))
|
||||
{
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: Dismiss Failed for MercID %i", MercID);
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Dismiss Failed Database Query for MercID: %i, Client: %s.", MercID, GetName());
|
||||
Dismissed = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: Dismiss Successful.");
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Dismiss Successful for %s.", GetName());
|
||||
}
|
||||
|
||||
if (GetMerc())
|
||||
@@ -5603,24 +5757,24 @@ bool Merc::RemoveMercFromGroup(Merc* merc, Group* group) {
|
||||
|
||||
if(merc && group)
|
||||
{
|
||||
uint32 groupID = group->GetID();
|
||||
if(merc->HasGroup())
|
||||
{
|
||||
if(!group->IsLeader(merc))
|
||||
{
|
||||
merc->SetFollowID(0);
|
||||
|
||||
if(group->DelMember(merc, true))
|
||||
if (group->GroupCount() <= 2 && merc->GetGroup() == group && ZoneLoaded)
|
||||
{
|
||||
group->DisbandGroup();
|
||||
}
|
||||
else if(group->DelMember(merc, true))
|
||||
{
|
||||
if(merc->GetMercCharacterID() != 0)
|
||||
{
|
||||
database.SetGroupID(merc->GetName(), 0, merc->GetMercCharacterID(), true);
|
||||
}
|
||||
}
|
||||
|
||||
if(group->GroupCount() <= 1 && ZoneLoaded)
|
||||
{
|
||||
group->DisbandGroup();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -5633,20 +5787,19 @@ bool Merc::RemoveMercFromGroup(Merc* merc, Group* group) {
|
||||
if(!group->members[i]->IsClient())
|
||||
continue;
|
||||
|
||||
group->members[i]->CastToClient()->LeaveGroup();
|
||||
}
|
||||
for(int i = 0; i < MAX_GROUP_MEMBERS; i++)
|
||||
{
|
||||
if(!group->members[i])
|
||||
continue;
|
||||
|
||||
if(!group->members[i]->IsMerc())
|
||||
continue;
|
||||
|
||||
group->members[i]->CastToMerc()->MercJoinClientGroup();
|
||||
Client *groupMember = group->members[i]->CastToClient();
|
||||
groupMember->LeaveGroup();
|
||||
if (groupMember->GetMerc())
|
||||
{
|
||||
groupMember->GetMerc()->MercJoinClientGroup();
|
||||
}
|
||||
}
|
||||
// Group should be removed by now, but just in case:
|
||||
group->DisbandGroup();
|
||||
Group *oldGroup = entity_list.GetGroupByID(groupID);
|
||||
if (oldGroup != nullptr)
|
||||
{
|
||||
oldGroup->DisbandGroup();
|
||||
}
|
||||
}
|
||||
|
||||
Result = true;
|
||||
@@ -5696,45 +5849,40 @@ bool Merc::MercJoinClientGroup() {
|
||||
|
||||
if(g->GetID() == 0)
|
||||
{
|
||||
|
||||
delete g;
|
||||
g = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(AddMercToGroup(this, g))
|
||||
if (AddMercToGroup(this, g))
|
||||
{
|
||||
entity_list.AddGroup(g, g->GetID());
|
||||
database.SetGroupLeaderName(g->GetID(), mercOwner->GetName());
|
||||
database.SetGroupID(mercOwner->GetName(), g->GetID(), mercOwner->CharacterID(), false);
|
||||
database.SetGroupID(this->GetName(), g->GetID(), mercOwner->CharacterID(), true);
|
||||
database.SetGroupLeaderName(g->GetID(), mercOwner->GetName());
|
||||
database.RefreshGroupFromDB(mercOwner);
|
||||
g->SaveGroupLeaderAA();
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: Mercenary joined new group.");
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary joined new group: %s (%s).", GetName(), mercOwner->GetName());
|
||||
}
|
||||
else
|
||||
{
|
||||
g->DisbandGroup();
|
||||
Suspend();
|
||||
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: Mercenary disbanded new group.");
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary disbanded new group: %s (%s).", GetName(), mercOwner->GetName());
|
||||
}
|
||||
|
||||
}
|
||||
else if (AddMercToGroup(this, mercOwner->GetGroup()))
|
||||
{
|
||||
// Group already exists
|
||||
database.SetGroupID(GetName(), mercOwner->GetGroup()->GetID(), mercOwner->CharacterID(), true);
|
||||
database.RefreshGroupFromDB(mercOwner);
|
||||
// Update members that are out of zone
|
||||
GetGroup()->SendGroupJoinOOZ(this);
|
||||
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: Mercenary joined existing group.");
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary %s joined existing group with %s.", GetName(), mercOwner->GetName());
|
||||
}
|
||||
else
|
||||
{
|
||||
Suspend();
|
||||
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: Mercenary failed to join the group - Suspending");
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary failed to join the group - Suspending %s for (%s).", GetName(), mercOwner->GetName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5785,7 +5933,7 @@ Merc* Client::GetMerc() {
|
||||
|
||||
if(GetMercID() == 0)
|
||||
{
|
||||
Log.Out(Logs::Detail, Logs::Mercenaries, "Mercenary Debug: GetMerc 0.");
|
||||
Log.Out(Logs::Detail, Logs::Mercenaries, "GetMerc - GetMercID: 0 for %s.", GetName());
|
||||
return (nullptr);
|
||||
}
|
||||
|
||||
@@ -5793,14 +5941,14 @@ Merc* Client::GetMerc() {
|
||||
if(tmp == nullptr)
|
||||
{
|
||||
SetMercID(0);
|
||||
Log.Out(Logs::Detail, Logs::Mercenaries, "Mercenary Debug: GetMerc No Merc.");
|
||||
Log.Out(Logs::Detail, Logs::Mercenaries, "GetMerc No Merc for %s.", GetName());
|
||||
return (nullptr);
|
||||
}
|
||||
|
||||
if(tmp->GetOwnerID() != GetID())
|
||||
{
|
||||
SetMercID(0);
|
||||
Log.Out(Logs::Detail, Logs::Mercenaries, "Mercenary Debug: GetMerc Owner Mismatch.");
|
||||
Log.Out(Logs::Detail, Logs::Mercenaries, "GetMerc Owner Mismatch - OwnerID: %d, ClientID: %d, Client: %s.", tmp->GetOwnerID(), GetID(), GetName());
|
||||
return (nullptr);
|
||||
}
|
||||
|
||||
@@ -5818,7 +5966,7 @@ uint8 Client::GetNumMercs() {
|
||||
numMercs++;
|
||||
}
|
||||
}
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: GetNumMercs %i.", numMercs);
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "GetNumMercs Number: %i for %s.", numMercs, GetName());
|
||||
|
||||
return numMercs;
|
||||
}
|
||||
@@ -5859,7 +6007,7 @@ void Client::SetMerc(Merc* newmerc) {
|
||||
GetMercInfo().Gender = 0;
|
||||
GetMercInfo().State = 0;
|
||||
memset(GetMercInfo().merc_name, 0, 64);
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: SetMerc No Merc.");
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "SetMerc No Merc for %s.", GetName());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -5876,7 +6024,7 @@ void Client::SetMerc(Merc* newmerc) {
|
||||
GetMercInfo().Gender = newmerc->GetGender();
|
||||
GetMercInfo().State = newmerc->IsSuspended() ? MERC_STATE_SUSPENDED : MERC_STATE_NORMAL;
|
||||
snprintf(GetMercInfo().merc_name, 64, "%s", newmerc->GetName());
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: SetMerc New Merc.");
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "SetMerc New Merc for %s.", GetName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5884,7 +6032,8 @@ void Client::UpdateMercLevel() {
|
||||
Merc* merc = GetMerc();
|
||||
if (merc)
|
||||
{
|
||||
merc->UpdateMercStats(this);
|
||||
merc->UpdateMercStats(this, false);
|
||||
merc->SendAppearancePacket(AT_WhoLevel, GetLevel(), true, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5896,7 +6045,7 @@ void Client::SendMercMerchantResponsePacket(int32 response_type) {
|
||||
MercenaryMerchantResponse_Struct* mmr = (MercenaryMerchantResponse_Struct*)outapp->pBuffer;
|
||||
mmr->ResponseType = response_type; // send specified response type
|
||||
FastQueuePacket(&outapp);
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: Sent SendMercMerchantResponsePacket %i.", response_type);
|
||||
Log.Out(Logs::Moderate, Logs::Mercenaries, "Sent SendMercMerchantResponsePacket ResponseType: %i, Client: %s.", response_type, GetName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5905,7 +6054,7 @@ void Client::SendMercenaryUnknownPacket(uint8 type) {
|
||||
EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryUnknown1, 1);
|
||||
outapp->WriteUInt8(type);
|
||||
FastQueuePacket(&outapp);
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: Sent SendMercenaryUnknownPacket %i.", type);
|
||||
Log.Out(Logs::Moderate, Logs::Mercenaries, "Sent SendMercenaryUnknownPacket Type: %i, Client: %s.", type, GetName());
|
||||
|
||||
}
|
||||
|
||||
@@ -5914,7 +6063,7 @@ void Client::SendMercenaryUnsuspendPacket(uint8 type) {
|
||||
EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryUnsuspendResponse, 1);
|
||||
outapp->WriteUInt8(type);
|
||||
FastQueuePacket(&outapp);
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: Sent SendMercenaryUnsuspendPacket %i.", type);
|
||||
Log.Out(Logs::Moderate, Logs::Mercenaries, "Sent SendMercenaryUnsuspendPacket Type: %i, Client: %s.", type, GetName());
|
||||
|
||||
}
|
||||
|
||||
@@ -5924,7 +6073,7 @@ void Client::SendMercSuspendResponsePacket(uint32 suspended_time) {
|
||||
SuspendMercenaryResponse_Struct* smr = (SuspendMercenaryResponse_Struct*)outapp->pBuffer;
|
||||
smr->SuspendTime = suspended_time; // Seen 0 (not suspended) or c9 c2 64 4f (suspended on Sat Mar 17 11:58:49 2012) - Unix Timestamp
|
||||
FastQueuePacket(&outapp);
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: Sent SendMercSuspendResponsePacket %i.", suspended_time);
|
||||
Log.Out(Logs::Moderate, Logs::Mercenaries, "Sent SendMercSuspendResponsePacket Time: %i, Client: %s.", suspended_time, GetName());
|
||||
|
||||
}
|
||||
|
||||
@@ -5939,7 +6088,7 @@ void Client::SendMercTimerPacket(int32 entity_id, int32 merc_state, int32 suspen
|
||||
mss->UpdateInterval = update_interval; // Seen 900000 - 15 minutes in ms
|
||||
mss->MercUnk01 = unk01; // Seen 180000 - 3 minutes in ms - Used for the unsuspend button refresh timer
|
||||
FastQueuePacket(&outapp);
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: Sent SendMercTimerPacket %i, %i, %i, %i, %i.", entity_id, merc_state, suspended_time, update_interval, unk01);
|
||||
Log.Out(Logs::Moderate, Logs::Mercenaries, "Sent SendMercTimerPacket EndID: %i, State: %i, SuspendTime: %i, Interval: %i, Unk1: %i, Client: %s.", entity_id, merc_state, suspended_time, update_interval, unk01, GetName());
|
||||
|
||||
}
|
||||
|
||||
@@ -5950,7 +6099,7 @@ void Client::SendMercAssignPacket(uint32 entityID, uint32 unk01, uint32 unk02) {
|
||||
mas->MercUnk01 = unk01;
|
||||
mas->MercUnk02 = unk02;
|
||||
FastQueuePacket(&outapp);
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: Sent SendMercAssignPacket %i, %i, %i.", entityID, unk01, unk02);
|
||||
Log.Out(Logs::Moderate, Logs::Mercenaries, "Sent SendMercAssignPacket EndID: %i, Unk1: %i, Unk2: %i, Client: %s.", entityID, unk01, unk02, GetName());
|
||||
}
|
||||
|
||||
void NPC::LoadMercTypes() {
|
||||
|
||||
+3
-1
@@ -137,7 +137,7 @@ public:
|
||||
virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
|
||||
static Merc* LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id, bool updateFromDB = false);
|
||||
void UpdateMercInfo(Client *c);
|
||||
void UpdateMercStats(Client *c);
|
||||
void UpdateMercStats(Client *c, bool setmax = false);
|
||||
void UpdateMercAppearance();
|
||||
virtual void UpdateEquipLightValue();
|
||||
void AddItem(uint8 slot, uint32 item_id);
|
||||
@@ -189,6 +189,7 @@ public:
|
||||
bool TryHide();
|
||||
|
||||
// stat functions
|
||||
virtual void ScaleStats(int scalepercent, bool setmax = false);
|
||||
virtual void CalcBonuses();
|
||||
int32 GetEndurance() const {return cur_end;} //This gets our current endurance
|
||||
inline virtual int32 GetAC() const { return AC; }
|
||||
@@ -347,6 +348,7 @@ private:
|
||||
|
||||
// Private "base stats" Members
|
||||
int32 base_mana;
|
||||
int32 base_end;
|
||||
int32 _baseAC;
|
||||
uint32 _baseSTR;
|
||||
uint32 _baseSTA;
|
||||
|
||||
+5
-5
@@ -2792,7 +2792,7 @@ void Mob::Say(const char *format, ...)
|
||||
}
|
||||
|
||||
//
|
||||
// solar: this is like the above, but the first parameter is a string id
|
||||
// this is like the above, but the first parameter is a string id
|
||||
//
|
||||
void Mob::Say_StringID(uint32 string_id, const char *message3, const char *message4, const char *message5, const char *message6, const char *message7, const char *message8, const char *message9)
|
||||
{
|
||||
@@ -3092,8 +3092,8 @@ float Mob::FindGroundZ(float new_x, float new_y, float z_offset)
|
||||
if (zone->zonemap != nullptr)
|
||||
{
|
||||
glm::vec3 me;
|
||||
me.x = m_Position.x;
|
||||
me.y = m_Position.y;
|
||||
me.x = new_x;
|
||||
me.y = new_y;
|
||||
me.z = m_Position.z + z_offset;
|
||||
glm::vec3 hit;
|
||||
float best_z = zone->zonemap->FindBestZ(me, &hit);
|
||||
@@ -3112,8 +3112,8 @@ float Mob::GetGroundZ(float new_x, float new_y, float z_offset)
|
||||
if (zone->zonemap != 0)
|
||||
{
|
||||
glm::vec3 me;
|
||||
me.x = m_Position.x;
|
||||
me.y = m_Position.y;
|
||||
me.x = new_x;
|
||||
me.y = new_y;
|
||||
me.z = m_Position.z+z_offset;
|
||||
glm::vec3 hit;
|
||||
float best_z = zone->zonemap->FindBestZ(me, &hit);
|
||||
|
||||
+11
-10
@@ -25,6 +25,7 @@
|
||||
#include "position.h"
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
char* strn0cpy(char* dest, const char* source, uint32 size);
|
||||
|
||||
@@ -122,7 +123,7 @@ public:
|
||||
|
||||
//Attack
|
||||
virtual void RogueBackstab(Mob* other, bool min_damage = false, int ReuseTime = 10);
|
||||
virtual void RogueAssassinate(Mob* other); // solar
|
||||
virtual void RogueAssassinate(Mob* other);
|
||||
float MobAngle(Mob *other = 0, float ourx = 0.0f, float oury = 0.0f) const;
|
||||
// greater than 90 is behind
|
||||
inline bool BehindMob(Mob *other = 0, float ourx = 0.0f, float oury = 0.0f) const
|
||||
@@ -577,7 +578,7 @@ public:
|
||||
void WakeTheDead(uint16 spell_id, Mob *target, uint32 duration);
|
||||
void Spin();
|
||||
void Kill();
|
||||
bool PassCharismaCheck(Mob* caster, Mob* spellTarget, uint16 spell_id);
|
||||
bool PassCharismaCheck(Mob* caster, uint16 spell_id);
|
||||
bool TryDeathSave();
|
||||
bool TryDivineSave();
|
||||
void DoBuffWearOffEffect(uint32 index);
|
||||
@@ -879,8 +880,8 @@ public:
|
||||
virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther) { return FACTION_INDIFFERENT; }
|
||||
|
||||
inline bool IsTrackable() const { return(trackable); }
|
||||
Timer* GetAIThinkTimer() { return AIthink_timer; }
|
||||
Timer* GetAIMovementTimer() { return AImovement_timer; }
|
||||
Timer* GetAIThinkTimer() { return AIthink_timer.get(); }
|
||||
Timer* GetAIMovementTimer() { return AImovement_timer.get(); }
|
||||
Timer GetAttackTimer() { return attack_timer; }
|
||||
Timer GetAttackDWTimer() { return attack_dw_timer; }
|
||||
inline bool IsFindable() { return findable; }
|
||||
@@ -1170,14 +1171,14 @@ protected:
|
||||
uint32 maxLastFightingDelayMoving;
|
||||
float pAggroRange;
|
||||
float pAssistRange;
|
||||
Timer* AIthink_timer;
|
||||
Timer* AImovement_timer;
|
||||
Timer* AItarget_check_timer;
|
||||
std::unique_ptr<Timer> AIthink_timer;
|
||||
std::unique_ptr<Timer> AImovement_timer;
|
||||
std::unique_ptr<Timer> AItarget_check_timer;
|
||||
bool movetimercompleted;
|
||||
bool permarooted;
|
||||
Timer* AIscanarea_timer;
|
||||
Timer* AIwalking_timer;
|
||||
Timer* AIfeignremember_timer;
|
||||
std::unique_ptr<Timer> AIscanarea_timer;
|
||||
std::unique_ptr<Timer> AIwalking_timer;
|
||||
std::unique_ptr<Timer> AIfeignremember_timer;
|
||||
uint32 pLastFightingDelayMoving;
|
||||
HateList hate_list;
|
||||
std::set<uint32> feign_memory_list;
|
||||
|
||||
+30
-30
@@ -422,14 +422,15 @@ bool EntityList::AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float
|
||||
return false;
|
||||
}
|
||||
|
||||
void Mob::AI_Init() {
|
||||
void Mob::AI_Init()
|
||||
{
|
||||
pAIControlled = false;
|
||||
AIthink_timer = 0;
|
||||
AIwalking_timer = 0;
|
||||
AImovement_timer = 0;
|
||||
AItarget_check_timer = 0;
|
||||
AIfeignremember_timer = nullptr;
|
||||
AIscanarea_timer = 0;
|
||||
AIthink_timer.reset(nullptr);
|
||||
AIwalking_timer.reset(nullptr);
|
||||
AImovement_timer.reset(nullptr);
|
||||
AItarget_check_timer.reset(nullptr);
|
||||
AIfeignremember_timer.reset(nullptr);
|
||||
AIscanarea_timer.reset(nullptr);
|
||||
minLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMin);
|
||||
maxLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMax);
|
||||
|
||||
@@ -441,10 +442,9 @@ void Mob::AI_Init() {
|
||||
pDontCureMeBefore = 0;
|
||||
}
|
||||
|
||||
void NPC::AI_Init() {
|
||||
Mob::AI_Init();
|
||||
|
||||
AIautocastspell_timer = 0;
|
||||
void NPC::AI_Init()
|
||||
{
|
||||
AIautocastspell_timer.reset(nullptr);
|
||||
casting_spell_AIindex = static_cast<uint8>(AIspells.size());
|
||||
|
||||
roambox_max_x = 0;
|
||||
@@ -458,8 +458,8 @@ void NPC::AI_Init() {
|
||||
roambox_delay = 2500;
|
||||
}
|
||||
|
||||
void Client::AI_Init() {
|
||||
Mob::AI_Init();
|
||||
void Client::AI_Init()
|
||||
{
|
||||
minLastFightingDelayMoving = CLIENT_LD_TIMEOUT;
|
||||
maxLastFightingDelayMoving = CLIENT_LD_TIMEOUT;
|
||||
}
|
||||
@@ -474,13 +474,13 @@ void Mob::AI_Start(uint32 iMoveDelay) {
|
||||
pLastFightingDelayMoving = 0;
|
||||
|
||||
pAIControlled = true;
|
||||
AIthink_timer = new Timer(AIthink_duration);
|
||||
AIthink_timer = std::unique_ptr<Timer>(new Timer(AIthink_duration));
|
||||
AIthink_timer->Trigger();
|
||||
AIwalking_timer = new Timer(0);
|
||||
AImovement_timer = new Timer(AImovement_duration);
|
||||
AItarget_check_timer = new Timer(AItarget_check_duration);
|
||||
AIfeignremember_timer = new Timer(AIfeignremember_delay);
|
||||
AIscanarea_timer = new Timer(AIscanarea_delay);
|
||||
AIwalking_timer = std::unique_ptr<Timer>(new Timer(0));
|
||||
AImovement_timer = std::unique_ptr<Timer>(new Timer(AImovement_duration));
|
||||
AItarget_check_timer = std::unique_ptr<Timer>(new Timer(AItarget_check_duration));
|
||||
AIfeignremember_timer = std::unique_ptr<Timer>(new Timer(AIfeignremember_delay));
|
||||
AIscanarea_timer = std::unique_ptr<Timer>(new Timer(AIscanarea_delay));
|
||||
#ifdef REVERSE_AGGRO
|
||||
if(IsNPC() && !CastToNPC()->WillAggroNPCs())
|
||||
AIscanarea_timer->Disable();
|
||||
@@ -516,10 +516,10 @@ void NPC::AI_Start(uint32 iMoveDelay) {
|
||||
return;
|
||||
|
||||
if (AIspells.size() == 0) {
|
||||
AIautocastspell_timer = new Timer(1000);
|
||||
AIautocastspell_timer = std::unique_ptr<Timer>(new Timer(1000));
|
||||
AIautocastspell_timer->Disable();
|
||||
} else {
|
||||
AIautocastspell_timer = new Timer(750);
|
||||
AIautocastspell_timer = std::unique_ptr<Timer>(new Timer(750));
|
||||
AIautocastspell_timer->Start(RandomTimer(0, 15000), false);
|
||||
}
|
||||
|
||||
@@ -540,19 +540,19 @@ void Mob::AI_Stop() {
|
||||
|
||||
pAIControlled = false;
|
||||
|
||||
safe_delete(AIthink_timer);
|
||||
safe_delete(AIwalking_timer);
|
||||
safe_delete(AImovement_timer);
|
||||
safe_delete(AItarget_check_timer);
|
||||
safe_delete(AIscanarea_timer);
|
||||
safe_delete(AIfeignremember_timer);
|
||||
AIthink_timer.reset(nullptr);
|
||||
AIwalking_timer.reset(nullptr);
|
||||
AImovement_timer.reset(nullptr);
|
||||
AItarget_check_timer.reset(nullptr);
|
||||
AIscanarea_timer.reset(nullptr);
|
||||
AIfeignremember_timer.reset(nullptr);
|
||||
|
||||
hate_list.WipeHateList();
|
||||
}
|
||||
|
||||
void NPC::AI_Stop() {
|
||||
Waypoints.clear();
|
||||
safe_delete(AIautocastspell_timer);
|
||||
AIautocastspell_timer.reset(nullptr);
|
||||
}
|
||||
|
||||
void Client::AI_Stop() {
|
||||
@@ -2657,7 +2657,7 @@ DBnpcspells_Struct* ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID) {
|
||||
npc_spells_cache = new DBnpcspells_Struct*[npc_spells_maxid+1];
|
||||
npc_spells_loadtried = new bool[npc_spells_maxid+1];
|
||||
for (uint32 i=0; i<=npc_spells_maxid; i++) {
|
||||
npc_spells_cache[i] = 0;
|
||||
npc_spells_cache[i] = nullptr;
|
||||
npc_spells_loadtried[i] = false;
|
||||
}
|
||||
}
|
||||
@@ -2795,7 +2795,7 @@ DBnpcspellseffects_Struct *ZoneDatabase::GetNPCSpellsEffects(uint32 iDBSpellsEff
|
||||
npc_spellseffects_cache = new DBnpcspellseffects_Struct *[npc_spellseffects_maxid + 1];
|
||||
npc_spellseffects_loadtried = new bool[npc_spellseffects_maxid + 1];
|
||||
for (uint32 i = 0; i <= npc_spellseffects_maxid; i++) {
|
||||
npc_spellseffects_cache[i] = 0;
|
||||
npc_spellseffects_cache[i] = nullptr;
|
||||
npc_spellseffects_loadtried[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -332,7 +332,7 @@ int main(int argc, char** argv) {
|
||||
Timer quest_timers(100);
|
||||
UpdateWindowTitle();
|
||||
bool worldwasconnected = worldserver.Connected();
|
||||
EQStream* eqss;
|
||||
std::shared_ptr<EQStream> eqss;
|
||||
EQStreamInterface *eqsi;
|
||||
uint8 IDLEZONEUPDATE = 200;
|
||||
uint8 ZONEUPDATE = 10;
|
||||
|
||||
+155
-186
@@ -250,8 +250,8 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, const glm::vec4& position, int if
|
||||
|
||||
npc_aggro = d->npc_aggro;
|
||||
|
||||
if(!IsMerc())
|
||||
AI_Start();
|
||||
AI_Init();
|
||||
AI_Start();
|
||||
|
||||
d_melee_texture1 = d->d_melee_texture1;
|
||||
d_melee_texture2 = d->d_melee_texture2;
|
||||
@@ -987,298 +987,267 @@ NPC* NPC::SpawnNPC(const char* spawncommand, const glm::vec4& position, Client*
|
||||
}
|
||||
}
|
||||
|
||||
uint32 ZoneDatabase::CreateNewNPCCommand(const char* zone, uint32 zone_version,Client *client, NPC* spawn, uint32 extra) {
|
||||
uint32 ZoneDatabase::CreateNewNPCCommand(const char *zone, uint32 zone_version, Client *client, NPC *spawn,
|
||||
uint32 extra)
|
||||
{
|
||||
uint32 npc_type_id = 0;
|
||||
|
||||
uint32 npc_type_id = 0;
|
||||
|
||||
if (extra && client && client->GetZoneID())
|
||||
{
|
||||
if (extra && client && client->GetZoneID()) {
|
||||
// Set an npc_type ID within the standard range for the current zone if possible (zone_id * 1000)
|
||||
int starting_npc_id = client->GetZoneID() * 1000;
|
||||
|
||||
std::string query = StringFormat("SELECT MAX(id) FROM npc_types WHERE id >= %i AND id < %i",
|
||||
starting_npc_id, starting_npc_id + 1000);
|
||||
auto results = QueryDatabase(query);
|
||||
starting_npc_id, starting_npc_id + 1000);
|
||||
auto results = QueryDatabase(query);
|
||||
if (results.Success()) {
|
||||
if (results.RowCount() != 0)
|
||||
{
|
||||
auto row = results.begin();
|
||||
npc_type_id = atoi(row[0]) + 1;
|
||||
// Prevent the npc_type id from exceeding the range for this zone
|
||||
if (npc_type_id >= (starting_npc_id + 1000))
|
||||
npc_type_id = 0;
|
||||
}
|
||||
else // No npc_type IDs set in this range yet
|
||||
npc_type_id = starting_npc_id;
|
||||
}
|
||||
}
|
||||
if (results.RowCount() != 0) {
|
||||
auto row = results.begin();
|
||||
npc_type_id = atoi(row[0]) + 1;
|
||||
// Prevent the npc_type id from exceeding the range for this zone
|
||||
if (npc_type_id >= (starting_npc_id + 1000))
|
||||
npc_type_id = 0;
|
||||
} else // No npc_type IDs set in this range yet
|
||||
npc_type_id = starting_npc_id;
|
||||
}
|
||||
}
|
||||
|
||||
char tmpstr[64];
|
||||
EntityList::RemoveNumbers(strn0cpy(tmpstr, spawn->GetName(), sizeof(tmpstr)));
|
||||
std::string query;
|
||||
if (npc_type_id)
|
||||
{
|
||||
query = StringFormat("INSERT INTO npc_types (id, name, level, race, class, hp, gender, "
|
||||
"texture, helmtexture, size, loottable_id, merchant_id, face, "
|
||||
"runspeed, prim_melee_type, sec_melee_type) "
|
||||
"VALUES(%i, \"%s\" , %i, %i, %i, %i, %i, %i, %i, %f, %i, %i, %i, %f, %i, %i)",
|
||||
npc_type_id, tmpstr, spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(),
|
||||
spawn->GetMaxHP(), spawn->GetGender(), spawn->GetTexture(),
|
||||
spawn->GetHelmTexture(), spawn->GetSize(), spawn->GetLoottableID(),
|
||||
spawn->MerchantType, 0, spawn->GetRunspeed(), 28, 28);
|
||||
auto results = QueryDatabase(query);
|
||||
if (npc_type_id) {
|
||||
query = StringFormat("INSERT INTO npc_types (id, name, level, race, class, hp, gender, "
|
||||
"texture, helmtexture, size, loottable_id, merchant_id, face, "
|
||||
"runspeed, prim_melee_type, sec_melee_type) "
|
||||
"VALUES(%i, \"%s\" , %i, %i, %i, %i, %i, %i, %i, %f, %i, %i, %i, %f, %i, %i)",
|
||||
npc_type_id, tmpstr, spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(),
|
||||
spawn->GetMaxHP(), spawn->GetGender(), spawn->GetTexture(),
|
||||
spawn->GetHelmTexture(), spawn->GetSize(), spawn->GetLoottableID(),
|
||||
spawn->MerchantType, 0, spawn->GetRunspeed(), 28, 28);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return false;
|
||||
}
|
||||
npc_type_id = results.LastInsertedID();
|
||||
} else {
|
||||
query = StringFormat("INSERT INTO npc_types (name, level, race, class, hp, gender, "
|
||||
"texture, helmtexture, size, loottable_id, merchant_id, face, "
|
||||
"runspeed, prim_melee_type, sec_melee_type) "
|
||||
"VALUES(\"%s\", %i, %i, %i, %i, %i, %i, %i, %f, %i, %i, %i, %f, %i, %i)",
|
||||
tmpstr, spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(), spawn->GetMaxHP(),
|
||||
spawn->GetGender(), spawn->GetTexture(), spawn->GetHelmTexture(), spawn->GetSize(),
|
||||
spawn->GetLoottableID(), spawn->MerchantType, 0, spawn->GetRunspeed(), 28, 28);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return false;
|
||||
}
|
||||
npc_type_id = results.LastInsertedID();
|
||||
}
|
||||
else
|
||||
{
|
||||
query = StringFormat("INSERT INTO npc_types (name, level, race, class, hp, gender, "
|
||||
"texture, helmtexture, size, loottable_id, merchant_id, face, "
|
||||
"runspeed, prim_melee_type, sec_melee_type) "
|
||||
"VALUES(\"%s\", %i, %i, %i, %i, %i, %i, %i, %f, %i, %i, %i, %f, %i, %i)",
|
||||
tmpstr, spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(),
|
||||
spawn->GetMaxHP(), spawn->GetGender(), spawn->GetTexture(),
|
||||
spawn->GetHelmTexture(), spawn->GetSize(), spawn->GetLoottableID(),
|
||||
spawn->MerchantType, 0, spawn->GetRunspeed(), 28, 28);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return false;
|
||||
}
|
||||
npc_type_id = results.LastInsertedID();
|
||||
}
|
||||
|
||||
if(client)
|
||||
|
||||
query = StringFormat("INSERT INTO spawngroup (id, name) VALUES(%i, '%s-%s')", 0, zone, spawn->GetName());
|
||||
auto results = QueryDatabase(query);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return false;
|
||||
}
|
||||
uint32 spawngroupid = results.LastInsertedID();
|
||||
uint32 spawngroupid = results.LastInsertedID();
|
||||
|
||||
if(client)
|
||||
|
||||
query = StringFormat("INSERT INTO spawn2 (zone, version, x, y, z, respawntime, heading, spawngroupID) "
|
||||
"VALUES('%s', %u, %f, %f, %f, %i, %f, %i)",
|
||||
zone, zone_version, spawn->GetX(), spawn->GetY(), spawn->GetZ(), 1200,
|
||||
spawn->GetHeading(), spawngroupid);
|
||||
results = QueryDatabase(query);
|
||||
query = StringFormat("INSERT INTO spawn2 (zone, version, x, y, z, respawntime, heading, spawngroupID) "
|
||||
"VALUES('%s', %u, %f, %f, %f, %i, %f, %i)",
|
||||
zone, zone_version, spawn->GetX(), spawn->GetY(), spawn->GetZ(), 1200, spawn->GetHeading(),
|
||||
spawngroupid);
|
||||
results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(client)
|
||||
|
||||
query = StringFormat("INSERT INTO spawnentry (spawngroupID, npcID, chance) VALUES(%i, %i, %i)",
|
||||
spawngroupid, npc_type_id, 100);
|
||||
results = QueryDatabase(query);
|
||||
query = StringFormat("INSERT INTO spawnentry (spawngroupID, npcID, chance) VALUES(%i, %i, %i)", spawngroupid,
|
||||
npc_type_id, 100);
|
||||
results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(client)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 ZoneDatabase::AddNewNPCSpawnGroupCommand(const char* zone, uint32 zone_version, Client *client, NPC* spawn, uint32 respawnTime) {
|
||||
uint32 last_insert_id = 0;
|
||||
uint32 ZoneDatabase::AddNewNPCSpawnGroupCommand(const char *zone, uint32 zone_version, Client *client, NPC *spawn,
|
||||
uint32 respawnTime)
|
||||
{
|
||||
uint32 last_insert_id = 0;
|
||||
|
||||
std::string query = StringFormat("INSERT INTO spawngroup (name) VALUES('%s%s%i')",
|
||||
zone, spawn->GetName(), Timer::GetCurrentTime());
|
||||
auto results = QueryDatabase(query);
|
||||
std::string query = StringFormat("INSERT INTO spawngroup (name) VALUES('%s%s%i')", zone, spawn->GetName(),
|
||||
Timer::GetCurrentTime());
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return 0;
|
||||
}
|
||||
last_insert_id = results.LastInsertedID();
|
||||
last_insert_id = results.LastInsertedID();
|
||||
|
||||
uint32 respawntime = 0;
|
||||
uint32 spawnid = 0;
|
||||
if (respawnTime)
|
||||
respawntime = respawnTime;
|
||||
else if(spawn->respawn2 && spawn->respawn2->RespawnTimer() != 0)
|
||||
respawntime = spawn->respawn2->RespawnTimer();
|
||||
else
|
||||
respawntime = 1200;
|
||||
uint32 respawntime = 0;
|
||||
uint32 spawnid = 0;
|
||||
if (respawnTime)
|
||||
respawntime = respawnTime;
|
||||
else if (spawn->respawn2 && spawn->respawn2->RespawnTimer() != 0)
|
||||
respawntime = spawn->respawn2->RespawnTimer();
|
||||
else
|
||||
respawntime = 1200;
|
||||
|
||||
query = StringFormat("INSERT INTO spawn2 (zone, version, x, y, z, respawntime, heading, spawngroupID) "
|
||||
"VALUES('%s', %u, %f, %f, %f, %i, %f, %i)",
|
||||
zone, zone_version, spawn->GetX(), spawn->GetY(), spawn->GetZ(), respawntime,
|
||||
spawn->GetHeading(), last_insert_id);
|
||||
results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return 0;
|
||||
}
|
||||
spawnid = results.LastInsertedID();
|
||||
query = StringFormat("INSERT INTO spawn2 (zone, version, x, y, z, respawntime, heading, spawngroupID) "
|
||||
"VALUES('%s', %u, %f, %f, %f, %i, %f, %i)",
|
||||
zone, zone_version, spawn->GetX(), spawn->GetY(), spawn->GetZ(), respawntime,
|
||||
spawn->GetHeading(), last_insert_id);
|
||||
results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return 0;
|
||||
}
|
||||
spawnid = results.LastInsertedID();
|
||||
|
||||
if(client)
|
||||
query = StringFormat("INSERT INTO spawnentry (spawngroupID, npcID, chance) VALUES(%i, %i, %i)", last_insert_id,
|
||||
spawn->GetNPCTypeID(), 100);
|
||||
results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
query = StringFormat("INSERT INTO spawnentry (spawngroupID, npcID, chance) VALUES(%i, %i, %i)",
|
||||
last_insert_id, spawn->GetNPCTypeID(), 100);
|
||||
results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(client)
|
||||
|
||||
return spawnid;
|
||||
return spawnid;
|
||||
}
|
||||
|
||||
uint32 ZoneDatabase::UpdateNPCTypeAppearance(Client *client, NPC* spawn) {
|
||||
|
||||
std::string query = StringFormat("UPDATE npc_types SET name = \"%s\", level = %i, race = %i, class = %i, "
|
||||
"hp = %i, gender = %i, texture = %i, helmtexture = %i, size = %i, "
|
||||
"loottable_id = %i, merchant_id = %i, face = %i, WHERE id = %i",
|
||||
spawn->GetName(), spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(),
|
||||
spawn->GetMaxHP(), spawn->GetGender(), spawn->GetTexture(),
|
||||
spawn->GetHelmTexture(), spawn->GetSize(), spawn->GetLoottableID(),
|
||||
spawn->MerchantType, spawn->GetNPCTypeID());
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success() && client)
|
||||
|
||||
return results.Success() == true? 1: 0;
|
||||
uint32 ZoneDatabase::UpdateNPCTypeAppearance(Client *client, NPC *spawn)
|
||||
{
|
||||
std::string query =
|
||||
StringFormat("UPDATE npc_types SET name = \"%s\", level = %i, race = %i, class = %i, "
|
||||
"hp = %i, gender = %i, texture = %i, helmtexture = %i, size = %i, "
|
||||
"loottable_id = %i, merchant_id = %i, face = %i, WHERE id = %i",
|
||||
spawn->GetName(), spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(), spawn->GetMaxHP(),
|
||||
spawn->GetGender(), spawn->GetTexture(), spawn->GetHelmTexture(), spawn->GetSize(),
|
||||
spawn->GetLoottableID(), spawn->MerchantType, spawn->GetNPCTypeID());
|
||||
auto results = QueryDatabase(query);
|
||||
return results.Success() == true ? 1 : 0;
|
||||
}
|
||||
|
||||
uint32 ZoneDatabase::DeleteSpawnLeaveInNPCTypeTable(const char* zone, Client *client, NPC* spawn) {
|
||||
uint32 ZoneDatabase::DeleteSpawnLeaveInNPCTypeTable(const char *zone, Client *client, NPC *spawn)
|
||||
{
|
||||
uint32 id = 0;
|
||||
uint32 spawngroupID = 0;
|
||||
|
||||
std::string query = StringFormat("SELECT id, spawngroupID FROM spawn2 WHERE "
|
||||
"zone='%s' AND spawngroupID=%i", zone, spawn->GetSp2());
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
"zone='%s' AND spawngroupID=%i",
|
||||
zone, spawn->GetSp2());
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return 0;
|
||||
|
||||
if (results.RowCount() == 0)
|
||||
return 0;
|
||||
if (results.RowCount() == 0)
|
||||
return 0;
|
||||
|
||||
auto row = results.begin();
|
||||
if (row[0])
|
||||
id = atoi(row[0]);
|
||||
id = atoi(row[0]);
|
||||
|
||||
if (row[1])
|
||||
spawngroupID = atoi(row[1]);
|
||||
spawngroupID = atoi(row[1]);
|
||||
|
||||
query = StringFormat("DELETE FROM spawn2 WHERE id = '%i'", id);
|
||||
results = QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM spawn2 WHERE id = '%i'", id);
|
||||
results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return 0;
|
||||
|
||||
if(client)
|
||||
|
||||
query = StringFormat("DELETE FROM spawngroup WHERE id = '%i'", spawngroupID);
|
||||
results = QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM spawngroup WHERE id = '%i'", spawngroupID);
|
||||
results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return 0;
|
||||
|
||||
if(client)
|
||||
|
||||
query = StringFormat("DELETE FROM spawnentry WHERE spawngroupID = '%i'", spawngroupID);
|
||||
results = QueryDatabase(query);
|
||||
query = StringFormat("DELETE FROM spawnentry WHERE spawngroupID = '%i'", spawngroupID);
|
||||
results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return 0;
|
||||
|
||||
if(client)
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32 ZoneDatabase::DeleteSpawnRemoveFromNPCTypeTable(const char* zone, uint32 zone_version, Client *client, NPC* spawn) {
|
||||
|
||||
uint32 ZoneDatabase::DeleteSpawnRemoveFromNPCTypeTable(const char *zone, uint32 zone_version, Client *client,
|
||||
NPC *spawn)
|
||||
{
|
||||
uint32 id = 0;
|
||||
uint32 spawngroupID = 0;
|
||||
|
||||
std::string query = StringFormat("SELECT id, spawngroupID FROM spawn2 WHERE zone = '%s' "
|
||||
"AND version = %u AND spawngroupID = %i",
|
||||
zone, zone_version, spawn->GetSp2());
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
"AND version = %u AND spawngroupID = %i",
|
||||
zone, zone_version, spawn->GetSp2());
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return 0;
|
||||
|
||||
if (results.RowCount() == 0)
|
||||
return 0;
|
||||
if (results.RowCount() == 0)
|
||||
return 0;
|
||||
|
||||
auto row = results.begin();
|
||||
|
||||
if (row[0])
|
||||
id = atoi(row[0]);
|
||||
id = atoi(row[0]);
|
||||
|
||||
if (row[1])
|
||||
spawngroupID = atoi(row[1]);
|
||||
spawngroupID = atoi(row[1]);
|
||||
|
||||
query = StringFormat("DELETE FROM spawn2 WHERE id = '%i'", id);
|
||||
results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return 0;
|
||||
|
||||
if(client)
|
||||
|
||||
query = StringFormat("DELETE FROM spawngroup WHERE id = '%i'", spawngroupID);
|
||||
query = StringFormat("DELETE FROM spawn2 WHERE id = '%i'", id);
|
||||
results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return 0;
|
||||
|
||||
if(client)
|
||||
|
||||
query = StringFormat("DELETE FROM spawnentry WHERE spawngroupID = '%i'", spawngroupID);
|
||||
query = StringFormat("DELETE FROM spawngroup WHERE id = '%i'", spawngroupID);
|
||||
results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return 0;
|
||||
|
||||
if(client)
|
||||
|
||||
query = StringFormat("DELETE FROM npc_types WHERE id = '%i'", spawn->GetNPCTypeID());
|
||||
query = StringFormat("DELETE FROM spawnentry WHERE spawngroupID = '%i'", spawngroupID);
|
||||
results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return 0;
|
||||
|
||||
if(client)
|
||||
query = StringFormat("DELETE FROM npc_types WHERE id = '%i'", spawn->GetNPCTypeID());
|
||||
results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32 ZoneDatabase::AddSpawnFromSpawnGroup(const char* zone, uint32 zone_version, Client *client, NPC* spawn, uint32 spawnGroupID) {
|
||||
|
||||
uint32 ZoneDatabase::AddSpawnFromSpawnGroup(const char *zone, uint32 zone_version, Client *client, NPC *spawn,
|
||||
uint32 spawnGroupID)
|
||||
{
|
||||
uint32 last_insert_id = 0;
|
||||
std::string query = StringFormat("INSERT INTO spawn2 (zone, version, x, y, z, respawntime, heading, spawngroupID) "
|
||||
"VALUES('%s', %u, %f, %f, %f, %i, %f, %i)",
|
||||
zone, zone_version, client->GetX(), client->GetY(), client->GetZ(),
|
||||
120, client->GetHeading(), spawnGroupID);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
std::string query =
|
||||
StringFormat("INSERT INTO spawn2 (zone, version, x, y, z, respawntime, heading, spawngroupID) "
|
||||
"VALUES('%s', %u, %f, %f, %f, %i, %f, %i)",
|
||||
zone, zone_version, client->GetX(), client->GetY(), client->GetZ(), 120, client->GetHeading(),
|
||||
spawnGroupID);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return 0;
|
||||
|
||||
if(client)
|
||||
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32 ZoneDatabase::AddNPCTypes(const char* zone, uint32 zone_version, Client *client, NPC* spawn, uint32 spawnGroupID) {
|
||||
|
||||
uint32 npc_type_id;
|
||||
uint32 ZoneDatabase::AddNPCTypes(const char *zone, uint32 zone_version, Client *client, NPC *spawn, uint32 spawnGroupID)
|
||||
{
|
||||
uint32 npc_type_id;
|
||||
char numberlessName[64];
|
||||
|
||||
EntityList::RemoveNumbers(strn0cpy(numberlessName, spawn->GetName(), sizeof(numberlessName)));
|
||||
std::string query = StringFormat("INSERT INTO npc_types (name, level, race, class, hp, gender, "
|
||||
"texture, helmtexture, size, loottable_id, merchant_id, face, "
|
||||
"runspeed, prim_melee_type, sec_melee_type) "
|
||||
"VALUES(\"%s\", %i, %i, %i, %i, %i, %i, %i, %f, %i, %i, %i, %f, %i, %i)",
|
||||
numberlessName, spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(),
|
||||
spawn->GetMaxHP(), spawn->GetGender(), spawn->GetTexture(),
|
||||
spawn->GetHelmTexture(), spawn->GetSize(), spawn->GetLoottableID(),
|
||||
spawn->MerchantType, 0, spawn->GetRunspeed(), 28, 28);
|
||||
auto results = QueryDatabase(query);
|
||||
std::string query =
|
||||
StringFormat("INSERT INTO npc_types (name, level, race, class, hp, gender, "
|
||||
"texture, helmtexture, size, loottable_id, merchant_id, face, "
|
||||
"runspeed, prim_melee_type, sec_melee_type) "
|
||||
"VALUES(\"%s\", %i, %i, %i, %i, %i, %i, %i, %f, %i, %i, %i, %f, %i, %i)",
|
||||
numberlessName, spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(), spawn->GetMaxHP(),
|
||||
spawn->GetGender(), spawn->GetTexture(), spawn->GetHelmTexture(), spawn->GetSize(),
|
||||
spawn->GetLoottableID(), spawn->MerchantType, 0, spawn->GetRunspeed(), 28, 28);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return 0;
|
||||
npc_type_id = results.LastInsertedID();
|
||||
npc_type_id = results.LastInsertedID();
|
||||
|
||||
if(client)
|
||||
|
||||
if(client)
|
||||
client->Message(0, "%s npc_type ID %i created successfully!", numberlessName, npc_type_id);
|
||||
if (client)
|
||||
client->Message(0, "%s npc_type ID %i created successfully!", numberlessName, npc_type_id);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
+2
-2
@@ -436,7 +436,7 @@ protected:
|
||||
|
||||
uint32 npc_spells_id;
|
||||
uint8 casting_spell_AIindex;
|
||||
Timer* AIautocastspell_timer;
|
||||
std::unique_ptr<Timer> AIautocastspell_timer;
|
||||
uint32* pDontCastBefore_casting_spell;
|
||||
std::vector<AISpells_Struct> AIspells;
|
||||
bool HasAISpell;
|
||||
@@ -444,7 +444,7 @@ protected:
|
||||
virtual bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0);
|
||||
AISpellsVar_Struct AISpellVar;
|
||||
int16 GetFocusEffect(focusType type, uint16 spell_id);
|
||||
|
||||
|
||||
uint32 npc_spells_effects_id;
|
||||
std::vector<AISpellsEffects_Struct> AIspellsEffects;
|
||||
bool HasAISpellEffects;
|
||||
|
||||
+8
-3
@@ -467,16 +467,21 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object)
|
||||
if (m_inst && sender) {
|
||||
// if there is a lore conflict, delete the offending item from the server inventory
|
||||
// the client updates itself and takes care of sending "duplicate lore item" messages
|
||||
if(sender->CheckLoreConflict(m_inst->GetItem())) {
|
||||
int16 loreslot = sender->GetInv().HasItem(m_inst->GetItem()->ID, 0, invWhereBank);
|
||||
auto item = m_inst->GetItem();
|
||||
if(sender->CheckLoreConflict(item)) {
|
||||
int16 loreslot = sender->GetInv().HasItem(item->ID, 0, invWhereBank);
|
||||
if (loreslot != INVALID_INDEX) // if the duplicate is in the bank, delete it.
|
||||
sender->DeleteItemInInventory(loreslot);
|
||||
else
|
||||
cursordelete = true; // otherwise, we delete the new one
|
||||
}
|
||||
|
||||
if (item->RecastDelay)
|
||||
m_inst->SetRecastTimestamp(
|
||||
database.GetItemRecastTimestamp(sender->CharacterID(), item->RecastType));
|
||||
|
||||
char buf[10];
|
||||
snprintf(buf, 9, "%u", m_inst->GetItem()->ID);
|
||||
snprintf(buf, 9, "%u", item->ID);
|
||||
buf[9] = '\0';
|
||||
std::vector<EQEmu::Any> args;
|
||||
args.push_back(m_inst);
|
||||
|
||||
@@ -663,7 +663,7 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime)
|
||||
DoAnim(animPiercing);
|
||||
}
|
||||
|
||||
// solar - assassinate [Kayen: No longer used for regular assassinate 6-29-14]
|
||||
// assassinate [No longer used for regular assassinate 6-29-14]
|
||||
void Mob::RogueAssassinate(Mob* other)
|
||||
{
|
||||
//can you dodge, parry, etc.. an assassinate??
|
||||
@@ -857,7 +857,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
|
||||
if (IsClient()){
|
||||
|
||||
_RangeWeapon = CastToClient()->m_inv[MainRange];
|
||||
if (_RangeWeapon && !_RangeWeapon->GetItem() && _RangeWeapon->GetItem()->ID == range_id)
|
||||
if (_RangeWeapon && _RangeWeapon->GetItem() && _RangeWeapon->GetItem()->ID == range_id)
|
||||
RangeWeapon = _RangeWeapon;
|
||||
|
||||
_Ammo = CastToClient()->m_inv[AmmoSlot];
|
||||
@@ -996,7 +996,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
|
||||
}
|
||||
|
||||
if (LaunchProjectile)
|
||||
return;//Shouldn't reach this point, but just in case.
|
||||
return;//Shouldn't reach this point durring initial launch phase, but just in case.
|
||||
|
||||
//Weapon Proc
|
||||
if(RangeWeapon && other && !other->HasDied())
|
||||
|
||||
@@ -134,7 +134,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
||||
if (spells[spell_id].EndurUpkeep > 0)
|
||||
SetEndurUpkeep(true);
|
||||
|
||||
if(IsClient() && CastToClient()->GetClientVersionBit() & BIT_UnderfootAndLater)
|
||||
if(IsClient() && CastToClient()->GetClientVersionBit() & BIT_UFAndLater)
|
||||
{
|
||||
EQApplicationPacket *outapp = MakeBuffsPacket(false);
|
||||
CastToClient()->FastQueuePacket(&outapp);
|
||||
@@ -3409,7 +3409,7 @@ void Mob::BuffProcess()
|
||||
{
|
||||
CastToClient()->SendBuffDurationPacket(buffs[buffs_i]);
|
||||
// Hack to get UF to play nicer, RoF seems fine without it
|
||||
if (CastToClient()->GetClientVersion() == ClientVersion::Und && buffs[buffs_i].numhits > 0)
|
||||
if (CastToClient()->GetClientVersion() == ClientVersion::UF && buffs[buffs_i].numhits > 0)
|
||||
CastToClient()->SendBuffNumHitPacket(buffs[buffs_i], buffs_i);
|
||||
buffs[buffs_i].UpdateClient = false;
|
||||
}
|
||||
@@ -3586,7 +3586,7 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste
|
||||
}
|
||||
|
||||
case SE_Charm: {
|
||||
if (!caster || !PassCharismaCheck(caster, this, spell_id)) {
|
||||
if (!caster || !PassCharismaCheck(caster, spell_id)) {
|
||||
BuffFadeByEffect(SE_Charm);
|
||||
}
|
||||
|
||||
@@ -4175,7 +4175,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
if(IsClient() && CastToClient()->GetClientVersionBit() & BIT_UnderfootAndLater)
|
||||
if(IsClient() && CastToClient()->GetClientVersionBit() & BIT_UFAndLater)
|
||||
{
|
||||
EQApplicationPacket *outapp = MakeBuffsPacket(false);
|
||||
CastToClient()->FastQueuePacket(&outapp);
|
||||
|
||||
+28
-11
@@ -1242,6 +1242,8 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot,
|
||||
{
|
||||
//Can we start the timer here? I don't see why not.
|
||||
CastToClient()->GetPTimers().Start((pTimerItemStart + recasttype), recastdelay);
|
||||
database.UpdateItemRecastTimestamps(CastToClient()->CharacterID(), recasttype,
|
||||
CastToClient()->GetPTimers().Get(pTimerItemStart + recasttype)->GetReadyTimestamp());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2023,6 +2025,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16
|
||||
//
|
||||
// Switch #2 - execute the spell
|
||||
//
|
||||
|
||||
switch(CastAction)
|
||||
{
|
||||
default:
|
||||
@@ -2146,6 +2149,15 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16
|
||||
// caster if they're not using TGB
|
||||
// NOTE: this will always hit the caster, plus the target's group so
|
||||
// it can affect up to 7 people if the targeted group is not our own
|
||||
|
||||
// Allow pets who cast group spells to affect the group.
|
||||
if (spell_target->IsPetOwnerClient()){
|
||||
Mob* owner = spell_target->GetOwner();
|
||||
|
||||
if (owner)
|
||||
spell_target = owner;
|
||||
}
|
||||
|
||||
if(spell_target->IsGrouped())
|
||||
{
|
||||
Group *target_group = entity_list.GetGroupByMob(spell_target);
|
||||
@@ -2270,11 +2282,15 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16
|
||||
{
|
||||
ItemInst *itm = CastToClient()->GetInv().GetItem(inventory_slot);
|
||||
if(itm && itm->GetItem()->RecastDelay > 0){
|
||||
CastToClient()->GetPTimers().Start((pTimerItemStart + itm->GetItem()->RecastType), itm->GetItem()->RecastDelay);
|
||||
auto recast_type = itm->GetItem()->RecastType;
|
||||
CastToClient()->GetPTimers().Start((pTimerItemStart + recast_type), itm->GetItem()->RecastDelay);
|
||||
database.UpdateItemRecastTimestamps(
|
||||
CastToClient()->CharacterID(), recast_type,
|
||||
CastToClient()->GetPTimers().Get(pTimerItemStart + recast_type)->GetReadyTimestamp());
|
||||
EQApplicationPacket *outapp = new EQApplicationPacket(OP_ItemRecastDelay, sizeof(ItemRecastDelay_Struct));
|
||||
ItemRecastDelay_Struct *ird = (ItemRecastDelay_Struct *)outapp->pBuffer;
|
||||
ird->recast_delay = itm->GetItem()->RecastDelay;
|
||||
ird->recast_type = itm->GetItem()->RecastType;
|
||||
ird->recast_type = recast_type;
|
||||
CastToClient()->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
@@ -3659,7 +3675,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r
|
||||
if(!IsHarmonySpell(spell_id))
|
||||
spelltar->AddToHateList(this, aggro);
|
||||
else
|
||||
if(!PassCharismaCheck(this, spelltar, spell_id))
|
||||
if(!spelltar->PassCharismaCheck(this, spell_id))
|
||||
spelltar->AddToHateList(this, aggro);
|
||||
}
|
||||
else{
|
||||
@@ -4388,7 +4404,7 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use
|
||||
level_mod += (2 * level_diff);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (CharismaCheck)
|
||||
{
|
||||
/*
|
||||
@@ -4402,7 +4418,7 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use
|
||||
*/
|
||||
int16 charisma = caster->GetCHA();
|
||||
|
||||
if (IsFear && (spells[spell_id].targettype != 10)){
|
||||
if (IsFear && (spells[spell_id].targettype != ST_Undead)){
|
||||
|
||||
if (charisma < 100)
|
||||
resist_modifier -= 20;
|
||||
@@ -4423,8 +4439,10 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use
|
||||
else
|
||||
resist_modifier += ((75 - charisma)/10) * 6; //Increase Resist Chance
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//Lull spells DO NOT use regular resists on initial cast, instead they use a flat +15 modifier. Live parses confirm this.
|
||||
//Regular resists are used when checking if mob will aggro off of a lull resist.
|
||||
if(!CharismaCheck && IsHarmonySpell(spell_id))
|
||||
@@ -4452,9 +4470,8 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use
|
||||
//Minimum resist chance should be caclulated factoring in the RuleI(Spells, CharmBreakCheckChance)
|
||||
if (CharmTick) {
|
||||
|
||||
int min_charmbreakchance = ((100/RuleI(Spells, CharmBreakCheckChance))/66 * 100)*2;
|
||||
|
||||
if (resist_chance < min_charmbreakchance)
|
||||
float min_charmbreakchance = ((100.0f/static_cast<float>(RuleI(Spells, CharmBreakCheckChance)))/66.0f * 100.0f)*2.0f;
|
||||
if (resist_chance < static_cast<int>(min_charmbreakchance))
|
||||
resist_chance = min_charmbreakchance;
|
||||
}
|
||||
|
||||
@@ -4462,9 +4479,9 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use
|
||||
//Minimum resist chance should be caclulated factoring in the RuleI(Spells, RootBreakCheckChance)
|
||||
if (IsRoot) {
|
||||
|
||||
int min_rootbreakchance = ((100/RuleI(Spells, RootBreakCheckChance))/22 * 100)*2;
|
||||
float min_rootbreakchance = ((100.0f/static_cast<float>(RuleI(Spells, RootBreakCheckChance)))/22.0f * 100.0f)*2.0f;
|
||||
|
||||
if (resist_chance < min_rootbreakchance)
|
||||
if (resist_chance < static_cast<int>(min_rootbreakchance))
|
||||
resist_chance = min_rootbreakchance;
|
||||
}
|
||||
|
||||
@@ -5248,7 +5265,7 @@ void Client::SendBuffDurationPacket(Buffs_Struct &buff)
|
||||
void Client::SendBuffNumHitPacket(Buffs_Struct &buff, int slot)
|
||||
{
|
||||
// UF+ use this packet
|
||||
if (GetClientVersion() < ClientVersion::Und)
|
||||
if (GetClientVersion() < ClientVersion::UF)
|
||||
return;
|
||||
EQApplicationPacket *outapp;
|
||||
outapp = new EQApplicationPacket(OP_BuffCreate, sizeof(BuffIcon_Struct) + sizeof(BuffIconEntry_Struct));
|
||||
|
||||
@@ -473,7 +473,7 @@ void WorldServer::Process() {
|
||||
if (ZoneLoaded) {
|
||||
SetZone(zone->GetZoneID(), zone->GetInstanceID());
|
||||
if (zst->zoneid == zone->GetZoneID()) {
|
||||
// This packet also doubles as "incomming client" notification, lets not shut down before they get here
|
||||
// This packet also doubles as "incoming client" notification, lets not shut down before they get here
|
||||
zone->StartShutdownTimer(AUTHENTICATION_TIMEOUT * 1000);
|
||||
}
|
||||
else {
|
||||
@@ -488,22 +488,19 @@ void WorldServer::Process() {
|
||||
if (!(Zone::Bootup(zst->zoneid, zst->instanceid, zst->makestatic))) {
|
||||
SendChannelMessage(0, 0, 10, 0, 0, "%s:%i Zone::Bootup failed: %s", net.GetZoneAddress(), net.GetZonePort(), database.GetZoneName(zst->zoneid));
|
||||
}
|
||||
// Moved annoucement to ZoneBootup()
|
||||
// else
|
||||
// SendEmoteMessage(0, 0, 15, "Zone bootup: %s", zone->GetLongName());
|
||||
break;
|
||||
}
|
||||
case ServerOP_ZoneIncClient: {
|
||||
if (pack->size != sizeof(ServerZoneIncommingClient_Struct)) {
|
||||
std::cout << "Wrong size on ServerOP_ZoneIncClient. Got: " << pack->size << ", Expected: " << sizeof(ServerZoneIncommingClient_Struct) << std::endl;
|
||||
if (pack->size != sizeof(ServerZoneIncomingClient_Struct)) {
|
||||
std::cout << "Wrong size on ServerOP_ZoneIncClient. Got: " << pack->size << ", Expected: " << sizeof(ServerZoneIncomingClient_Struct) << std::endl;
|
||||
break;
|
||||
}
|
||||
ServerZoneIncommingClient_Struct* szic = (ServerZoneIncommingClient_Struct*) pack->pBuffer;
|
||||
ServerZoneIncomingClient_Struct* szic = (ServerZoneIncomingClient_Struct*) pack->pBuffer;
|
||||
if (ZoneLoaded) {
|
||||
SetZone(zone->GetZoneID(), zone->GetInstanceID());
|
||||
if (szic->zoneid == zone->GetZoneID()) {
|
||||
zone->AddAuth(szic);
|
||||
// This packet also doubles as "incomming client" notification, lets not shut down before they get here
|
||||
// This packet also doubles as "incoming client" notification, lets not shut down before they get here
|
||||
zone->StartShutdownTimer(AUTHENTICATION_TIMEOUT * 1000);
|
||||
}
|
||||
}
|
||||
@@ -650,7 +647,7 @@ void WorldServer::Process() {
|
||||
case ServerOP_Petition: {
|
||||
std::cout << "Got Server Requested Petition List Refresh" << std::endl;
|
||||
ServerPetitionUpdate_Struct* sus = (ServerPetitionUpdate_Struct*) pack->pBuffer;
|
||||
// solar: this was typoed to = instead of ==, not that it acts any different now though..
|
||||
// this was typoed to = instead of ==, not that it acts any different now though..
|
||||
if (sus->status == 0) petition_list.ReadDatabase();
|
||||
else if (sus->status == 1) petition_list.ReadDatabase(); // Until I fix this to be better....
|
||||
break;
|
||||
|
||||
+2
-2
@@ -656,7 +656,7 @@ void Zone::LoadMercSpells(){
|
||||
merc_spells_list[classid].push_back(tempMercSpellEntry);
|
||||
}
|
||||
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary Debug: Loaded %i merc spells.", merc_spells_list[1].size() + merc_spells_list[2].size() + merc_spells_list[9].size() + merc_spells_list[12].size());
|
||||
Log.Out(Logs::General, Logs::Mercenaries, "Loaded %i merc spells.", merc_spells_list[1].size() + merc_spells_list[2].size() + merc_spells_list[9].size() + merc_spells_list[12].size());
|
||||
|
||||
}
|
||||
|
||||
@@ -1086,7 +1086,7 @@ bool Zone::SaveZoneCFG() {
|
||||
return database.SaveZoneCFG(GetZoneID(), GetInstanceVersion(), &newzone_data);
|
||||
}
|
||||
|
||||
void Zone::AddAuth(ServerZoneIncommingClient_Struct* szic) {
|
||||
void Zone::AddAuth(ServerZoneIncomingClient_Struct* szic) {
|
||||
ZoneClientAuth_Struct* zca = new ZoneClientAuth_Struct;
|
||||
memset(zca, 0, sizeof(ZoneClientAuth_Struct));
|
||||
zca->ip = szic->ip;
|
||||
|
||||
+2
-2
@@ -84,7 +84,7 @@ class PathManager;
|
||||
class WaterMap;
|
||||
extern EntityList entity_list;
|
||||
struct NPCType;
|
||||
struct ServerZoneIncommingClient_Struct;
|
||||
struct ServerZoneIncomingClient_Struct;
|
||||
|
||||
class Zone
|
||||
{
|
||||
@@ -149,7 +149,7 @@ public:
|
||||
void StartShutdownTimer(uint32 set_time = (RuleI(Zone, AutoShutdownDelay)));
|
||||
void ChangeWeather();
|
||||
bool HasWeather();
|
||||
void AddAuth(ServerZoneIncommingClient_Struct* szic);
|
||||
void AddAuth(ServerZoneIncomingClient_Struct* szic);
|
||||
void RemoveAuth(const char* iCharName);
|
||||
void ResetAuth();
|
||||
bool GetAuth(uint32 iIP, const char* iCharName, uint32* oWID = 0, uint32* oAccID = 0, uint32* oCharID = 0, int16* oStatus = 0, char* oLSKey = 0, bool* oTellsOff = 0);
|
||||
|
||||
+202
-127
@@ -1937,8 +1937,8 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) {
|
||||
return npc;
|
||||
}
|
||||
|
||||
const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 clientlevel) {
|
||||
|
||||
const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 clientlevel)
|
||||
{
|
||||
//need to save based on merc_npc_type & client level
|
||||
uint32 merc_type_id = id * 100 + clientlevel;
|
||||
|
||||
@@ -1963,7 +1963,7 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client
|
||||
"0 AS gender, "
|
||||
"m_armorinfo.texture, "
|
||||
"m_armorinfo.helmtexture, "
|
||||
"m_stats.attack_speed, "
|
||||
"m_stats.attack_delay, "
|
||||
"m_stats.STR, "
|
||||
"m_stats.STA, "
|
||||
"m_stats.DEX, "
|
||||
@@ -1996,6 +1996,7 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client
|
||||
"m_stats.AC, "
|
||||
"m_stats.ATK, "
|
||||
"m_stats.Accuracy, "
|
||||
"m_stats.statscale, "
|
||||
"m_stats.spellscale, "
|
||||
"m_stats.healscale "
|
||||
"FROM merc_stats m_stats "
|
||||
@@ -2014,125 +2015,125 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client
|
||||
"WHERE m_templates.merc_npc_type_id = %d AND m_stats.clientlevel = %d AND m_types.race_id = %d",
|
||||
id, clientlevel, raceid); //dual primary keys. one is ID, one is level.
|
||||
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return nullptr;
|
||||
}
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const NPCType *npc;
|
||||
const NPCType *npc;
|
||||
|
||||
// Process each row returned.
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
NPCType *tmpNPCType;
|
||||
tmpNPCType = new NPCType;
|
||||
memset (tmpNPCType, 0, sizeof *tmpNPCType);
|
||||
// Process each row returned.
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
NPCType *tmpNPCType;
|
||||
tmpNPCType = new NPCType;
|
||||
memset(tmpNPCType, 0, sizeof *tmpNPCType);
|
||||
|
||||
tmpNPCType->npc_id = atoi(row[0]);
|
||||
tmpNPCType->npc_id = atoi(row[0]);
|
||||
|
||||
strn0cpy(tmpNPCType->name, row[1], 50);
|
||||
strn0cpy(tmpNPCType->name, row[1], 50);
|
||||
|
||||
tmpNPCType->level = atoi(row[2]);
|
||||
tmpNPCType->race = atoi(row[3]);
|
||||
tmpNPCType->class_ = atoi(row[4]);
|
||||
tmpNPCType->max_hp = atoi(row[5]);
|
||||
tmpNPCType->cur_hp = tmpNPCType->max_hp;
|
||||
tmpNPCType->Mana = atoi(row[6]);
|
||||
tmpNPCType->gender = atoi(row[7]);
|
||||
tmpNPCType->texture = atoi(row[8]);
|
||||
tmpNPCType->helmtexture = atoi(row[9]);
|
||||
tmpNPCType->attack_speed = atof(row[10]);
|
||||
tmpNPCType->STR = atoi(row[11]);
|
||||
tmpNPCType->STA = atoi(row[12]);
|
||||
tmpNPCType->DEX = atoi(row[13]);
|
||||
tmpNPCType->AGI = atoi(row[14]);
|
||||
tmpNPCType->INT = atoi(row[15]);
|
||||
tmpNPCType->WIS = atoi(row[16]);
|
||||
tmpNPCType->CHA = atoi(row[17]);
|
||||
tmpNPCType->MR = atoi(row[18]);
|
||||
tmpNPCType->CR = atoi(row[19]);
|
||||
tmpNPCType->DR = atoi(row[20]);
|
||||
tmpNPCType->FR = atoi(row[21]);
|
||||
tmpNPCType->PR = atoi(row[22]);
|
||||
tmpNPCType->Corrup = atoi(row[23]);
|
||||
tmpNPCType->min_dmg = atoi(row[24]);
|
||||
tmpNPCType->max_dmg = atoi(row[25]);
|
||||
tmpNPCType->attack_count = atoi(row[26]);
|
||||
tmpNPCType->level = atoi(row[2]);
|
||||
tmpNPCType->race = atoi(row[3]);
|
||||
tmpNPCType->class_ = atoi(row[4]);
|
||||
tmpNPCType->max_hp = atoi(row[5]);
|
||||
tmpNPCType->cur_hp = tmpNPCType->max_hp;
|
||||
tmpNPCType->Mana = atoi(row[6]);
|
||||
tmpNPCType->gender = atoi(row[7]);
|
||||
tmpNPCType->texture = atoi(row[8]);
|
||||
tmpNPCType->helmtexture = atoi(row[9]);
|
||||
tmpNPCType->attack_delay = atoi(row[10]);
|
||||
tmpNPCType->STR = atoi(row[11]);
|
||||
tmpNPCType->STA = atoi(row[12]);
|
||||
tmpNPCType->DEX = atoi(row[13]);
|
||||
tmpNPCType->AGI = atoi(row[14]);
|
||||
tmpNPCType->INT = atoi(row[15]);
|
||||
tmpNPCType->WIS = atoi(row[16]);
|
||||
tmpNPCType->CHA = atoi(row[17]);
|
||||
tmpNPCType->MR = atoi(row[18]);
|
||||
tmpNPCType->CR = atoi(row[19]);
|
||||
tmpNPCType->DR = atoi(row[20]);
|
||||
tmpNPCType->FR = atoi(row[21]);
|
||||
tmpNPCType->PR = atoi(row[22]);
|
||||
tmpNPCType->Corrup = atoi(row[23]);
|
||||
tmpNPCType->min_dmg = atoi(row[24]);
|
||||
tmpNPCType->max_dmg = atoi(row[25]);
|
||||
tmpNPCType->attack_count = atoi(row[26]);
|
||||
|
||||
if (row[27] != nullptr)
|
||||
strn0cpy(tmpNPCType->special_abilities, row[27], 512);
|
||||
else
|
||||
tmpNPCType->special_abilities[0] = '\0';
|
||||
|
||||
tmpNPCType->d_melee_texture1 = atoi(row[28]);
|
||||
tmpNPCType->d_melee_texture2 = atoi(row[29]);
|
||||
tmpNPCType->prim_melee_type = atoi(row[30]);
|
||||
tmpNPCType->sec_melee_type = atoi(row[31]);
|
||||
tmpNPCType->runspeed= atof(row[32]);
|
||||
tmpNPCType->d_melee_texture1 = atoi(row[28]);
|
||||
tmpNPCType->d_melee_texture2 = atoi(row[29]);
|
||||
tmpNPCType->prim_melee_type = atoi(row[30]);
|
||||
tmpNPCType->sec_melee_type = atoi(row[31]);
|
||||
tmpNPCType->runspeed = atof(row[32]);
|
||||
|
||||
tmpNPCType->hp_regen = atoi(row[33]);
|
||||
tmpNPCType->mana_regen = atoi(row[34]);
|
||||
tmpNPCType->hp_regen = atoi(row[33]);
|
||||
tmpNPCType->mana_regen = atoi(row[34]);
|
||||
|
||||
tmpNPCType->aggroradius = RuleI(Mercs, AggroRadius);
|
||||
tmpNPCType->aggroradius = RuleI(Mercs, AggroRadius);
|
||||
|
||||
if (row[35] && strlen(row[35]))
|
||||
tmpNPCType->bodytype = (uint8)atoi(row[35]);
|
||||
else
|
||||
tmpNPCType->bodytype = 1;
|
||||
if (row[35] && strlen(row[35]))
|
||||
tmpNPCType->bodytype = (uint8)atoi(row[35]);
|
||||
else
|
||||
tmpNPCType->bodytype = 1;
|
||||
|
||||
uint32 armor_tint_id = atoi(row[36]);
|
||||
tmpNPCType->armor_tint[0] = (atoi(row[37]) & 0xFF) << 16;
|
||||
tmpNPCType->armor_tint[0] |= (atoi(row[38]) & 0xFF) << 8;
|
||||
tmpNPCType->armor_tint[0] |= (atoi(row[39]) & 0xFF);
|
||||
tmpNPCType->armor_tint[0] |= (tmpNPCType->armor_tint[0]) ? (0xFF << 24) : 0;
|
||||
uint32 armor_tint_id = atoi(row[36]);
|
||||
tmpNPCType->armor_tint[0] = (atoi(row[37]) & 0xFF) << 16;
|
||||
tmpNPCType->armor_tint[0] |= (atoi(row[38]) & 0xFF) << 8;
|
||||
tmpNPCType->armor_tint[0] |= (atoi(row[39]) & 0xFF);
|
||||
tmpNPCType->armor_tint[0] |= (tmpNPCType->armor_tint[0]) ? (0xFF << 24) : 0;
|
||||
|
||||
if (armor_tint_id == 0)
|
||||
for (int index = MaterialChest; index <= EmuConstants::MATERIAL_END; index++)
|
||||
tmpNPCType->armor_tint[index] = tmpNPCType->armor_tint[0];
|
||||
else if (tmpNPCType->armor_tint[0] == 0) {
|
||||
std::string armorTint_query = StringFormat("SELECT red1h, grn1h, blu1h, "
|
||||
"red2c, grn2c, blu2c, "
|
||||
"red3a, grn3a, blu3a, "
|
||||
"red4b, grn4b, blu4b, "
|
||||
"red5g, grn5g, blu5g, "
|
||||
"red6l, grn6l, blu6l, "
|
||||
"red7f, grn7f, blu7f, "
|
||||
"red8x, grn8x, blu8x, "
|
||||
"red9x, grn9x, blu9x "
|
||||
"FROM npc_types_tint WHERE id = %d",
|
||||
armor_tint_id);
|
||||
auto armorTint_results = QueryDatabase(armorTint_query);
|
||||
if (!results.Success() || results.RowCount() == 0)
|
||||
armor_tint_id = 0;
|
||||
else {
|
||||
auto armorTint_row = results.begin();
|
||||
if (armor_tint_id == 0)
|
||||
for (int index = MaterialChest; index <= EmuConstants::MATERIAL_END; index++)
|
||||
tmpNPCType->armor_tint[index] = tmpNPCType->armor_tint[0];
|
||||
else if (tmpNPCType->armor_tint[0] == 0) {
|
||||
std::string armorTint_query = StringFormat("SELECT red1h, grn1h, blu1h, "
|
||||
"red2c, grn2c, blu2c, "
|
||||
"red3a, grn3a, blu3a, "
|
||||
"red4b, grn4b, blu4b, "
|
||||
"red5g, grn5g, blu5g, "
|
||||
"red6l, grn6l, blu6l, "
|
||||
"red7f, grn7f, blu7f, "
|
||||
"red8x, grn8x, blu8x, "
|
||||
"red9x, grn9x, blu9x "
|
||||
"FROM npc_types_tint WHERE id = %d",
|
||||
armor_tint_id);
|
||||
auto armorTint_results = QueryDatabase(armorTint_query);
|
||||
if (!results.Success() || results.RowCount() == 0)
|
||||
armor_tint_id = 0;
|
||||
else {
|
||||
auto armorTint_row = results.begin();
|
||||
|
||||
for (int index = EmuConstants::MATERIAL_BEGIN; index <= EmuConstants::MATERIAL_END; index++) {
|
||||
tmpNPCType->armor_tint[index] = atoi(armorTint_row[index * 3]) << 16;
|
||||
tmpNPCType->armor_tint[index] |= atoi(armorTint_row[index * 3 + 1]) << 8;
|
||||
tmpNPCType->armor_tint[index] |= atoi(armorTint_row[index * 3 + 2]);
|
||||
tmpNPCType->armor_tint[index] |= (tmpNPCType->armor_tint[index]) ? (0xFF << 24) : 0;
|
||||
}
|
||||
}
|
||||
} else
|
||||
armor_tint_id = 0;
|
||||
for (int index = EmuConstants::MATERIAL_BEGIN; index <= EmuConstants::MATERIAL_END; index++) {
|
||||
tmpNPCType->armor_tint[index] = atoi(armorTint_row[index * 3]) << 16;
|
||||
tmpNPCType->armor_tint[index] |= atoi(armorTint_row[index * 3 + 1]) << 8;
|
||||
tmpNPCType->armor_tint[index] |= atoi(armorTint_row[index * 3 + 2]);
|
||||
tmpNPCType->armor_tint[index] |= (tmpNPCType->armor_tint[index]) ? (0xFF << 24) : 0;
|
||||
}
|
||||
}
|
||||
} else
|
||||
armor_tint_id = 0;
|
||||
|
||||
tmpNPCType->AC = atoi(row[40]);
|
||||
tmpNPCType->ATK = atoi(row[41]);
|
||||
tmpNPCType->accuracy_rating = atoi(row[42]);
|
||||
tmpNPCType->scalerate = RuleI(Mercs, ScaleRate);
|
||||
tmpNPCType->spellscale = atoi(row[43]);
|
||||
tmpNPCType->healscale = atoi(row[44]);
|
||||
tmpNPCType->AC = atoi(row[40]);
|
||||
tmpNPCType->ATK = atoi(row[41]);
|
||||
tmpNPCType->accuracy_rating = atoi(row[42]);
|
||||
tmpNPCType->scalerate = atoi(row[43]);
|
||||
tmpNPCType->spellscale = atoi(row[44]);
|
||||
tmpNPCType->healscale = atoi(row[45]);
|
||||
|
||||
// If Merc with duplicate NPC id already in table,
|
||||
// free item we attempted to add.
|
||||
// If Merc with duplicate NPC id already in table,
|
||||
// free item we attempted to add.
|
||||
if (zone->merctable.find(merc_type_id) != zone->merctable.end()) {
|
||||
delete tmpNPCType;
|
||||
return nullptr;
|
||||
}
|
||||
delete tmpNPCType;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
zone->merctable[merc_type_id] = tmpNPCType;
|
||||
npc = tmpNPCType;
|
||||
}
|
||||
npc = tmpNPCType;
|
||||
}
|
||||
|
||||
return npc;
|
||||
}
|
||||
@@ -2998,6 +2999,14 @@ void ZoneDatabase::RemoveTempFactions(Client *client) {
|
||||
QueryDatabase(query);
|
||||
}
|
||||
|
||||
void ZoneDatabase::UpdateItemRecastTimestamps(uint32 char_id, uint32 recast_type, uint32 timestamp)
|
||||
{
|
||||
std::string query =
|
||||
StringFormat("REPLACE INTO character_item_recast (id, recast_type, timestamp) VALUES (%u, %u, %u)", char_id,
|
||||
recast_type, timestamp);
|
||||
QueryDatabase(query);
|
||||
}
|
||||
|
||||
void ZoneDatabase::LoadPetInfo(Client *client) {
|
||||
|
||||
// Load current pet and suspended pet
|
||||
@@ -3413,38 +3422,102 @@ void ZoneDatabase::MarkCorpseAsRezzed(uint32 db_id) {
|
||||
|
||||
uint32 ZoneDatabase::SaveCharacterCorpse(uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, PlayerCorpse_Struct* dbpc, const glm::vec4& position) {
|
||||
/* Dump Basic Corpse Data */
|
||||
std::string query = StringFormat("INSERT INTO `character_corpses` "
|
||||
"SET `charname` = '%s', `zone_id` = %u, `instance_id` = %u, `charid` = %d,"
|
||||
"`x` = %1.1f, `y` = %1.1f, `z` = %1.1f, `heading` = %1.1f,"
|
||||
"`time_of_death` = NOW(), `is_buried` = 0, `is_locked` = %d,"
|
||||
"`exp` = %u, `size` = %f, `level` = %u, `race` = %u, `gender` = %u,"
|
||||
"`class` = %u, `deity` = %u, `texture` = %u, `helm_texture` = %u,"
|
||||
"`copper` = %u, `silver` = %u,`gold` = %u,`platinum` = %u,"
|
||||
"`hair_color` = %u, `beard_color` = %u, `eye_color_1` = %u,"
|
||||
"`eye_color_2` = %u, `hair_style` = %u, `face` = %u,"
|
||||
"`beard` = %u, `drakkin_heritage` = %u, `drakkin_tattoo` = %u,"
|
||||
"`drakkin_details` = %u, `wc_1` = %u, `wc_2` = %u,"
|
||||
"`wc_3` = %u, `wc_4` = %u, `wc_5` = %u, `wc_6` = %u,"
|
||||
"`wc_7` = %u,`wc_8` = %u,`wc_9` = %u",
|
||||
EscapeString(charname).c_str(), zoneid, instanceid, charid,
|
||||
position.x, position.y, position.z, position.w,
|
||||
dbpc->locked, dbpc->exp, dbpc->size, dbpc->level, dbpc->race,
|
||||
dbpc->gender, dbpc->class_, dbpc->deity, dbpc->texture,
|
||||
dbpc->helmtexture, dbpc->copper, dbpc->silver, dbpc->gold,
|
||||
dbpc->plat, dbpc->haircolor, dbpc->beardcolor, dbpc->eyecolor1,
|
||||
dbpc->eyecolor2, dbpc->hairstyle, dbpc->face, dbpc->beard,
|
||||
dbpc->drakkin_heritage, dbpc->drakkin_tattoo, dbpc->drakkin_details,
|
||||
dbpc->item_tint[0].color, dbpc->item_tint[1].color, dbpc->item_tint[2].color,
|
||||
dbpc->item_tint[3].color, dbpc->item_tint[4].color, dbpc->item_tint[5].color,
|
||||
dbpc->item_tint[6].color, dbpc->item_tint[7].color, dbpc->item_tint[8].color);
|
||||
std::string query = StringFormat(
|
||||
"INSERT INTO `character_corpses` "
|
||||
"SET `charname` = '%s', "
|
||||
"`zone_id` = %u, "
|
||||
"`instance_id` = %u, "
|
||||
"`charid` = %d, "
|
||||
"`x` = %1.1f, "
|
||||
"`y` = %1.1f, "
|
||||
"`z` = %1.1f, "
|
||||
"`heading` = %1.1f, "
|
||||
"`time_of_death` = NOW(), "
|
||||
"`is_buried` = 0, "
|
||||
"`is_locked` = %d, "
|
||||
"`exp` = %u, "
|
||||
"`size` = %f, "
|
||||
"`level` = %u, "
|
||||
"`race` = %u, "
|
||||
"`gender` = %u, "
|
||||
"`class` = %u, "
|
||||
"`deity` = %u, "
|
||||
"`texture` = %u, "
|
||||
"`helm_texture` = %u, "
|
||||
"`copper` = %u, "
|
||||
"`silver` = %u, "
|
||||
"`gold` = %u, "
|
||||
"`platinum` = %u, "
|
||||
"`hair_color` = %u, "
|
||||
"`beard_color` = %u, "
|
||||
"`eye_color_1` = %u, "
|
||||
"`eye_color_2` = %u, "
|
||||
"`hair_style` = %u, "
|
||||
"`face` = %u, "
|
||||
"`beard` = %u, "
|
||||
"`drakkin_heritage` = %u, "
|
||||
"`drakkin_tattoo` = %u, "
|
||||
"`drakkin_details` = %u, "
|
||||
"`wc_1` = %u, "
|
||||
"`wc_2` = %u, "
|
||||
"`wc_3` = %u, "
|
||||
"`wc_4` = %u, "
|
||||
"`wc_5` = %u, "
|
||||
"`wc_6` = %u, "
|
||||
"`wc_7` = %u, "
|
||||
"`wc_8` = %u, "
|
||||
"`wc_9` = %u ",
|
||||
EscapeString(charname).c_str(),
|
||||
zoneid,
|
||||
instanceid,
|
||||
charid,
|
||||
position.x,
|
||||
position.y,
|
||||
position.z,
|
||||
position.w,
|
||||
dbpc->locked,
|
||||
dbpc->exp,
|
||||
dbpc->size,
|
||||
dbpc->level,
|
||||
dbpc->race,
|
||||
dbpc->gender,
|
||||
dbpc->class_,
|
||||
dbpc->deity,
|
||||
dbpc->texture,
|
||||
dbpc->helmtexture,
|
||||
dbpc->copper,
|
||||
dbpc->silver,
|
||||
dbpc->gold,
|
||||
dbpc->plat,
|
||||
dbpc->haircolor,
|
||||
dbpc->beardcolor,
|
||||
dbpc->eyecolor1,
|
||||
dbpc->eyecolor2,
|
||||
dbpc->hairstyle,
|
||||
dbpc->face,
|
||||
dbpc->beard,
|
||||
dbpc->drakkin_heritage,
|
||||
dbpc->drakkin_tattoo,
|
||||
dbpc->drakkin_details,
|
||||
dbpc->item_tint[0].color,
|
||||
dbpc->item_tint[1].color,
|
||||
dbpc->item_tint[2].color,
|
||||
dbpc->item_tint[3].color,
|
||||
dbpc->item_tint[4].color,
|
||||
dbpc->item_tint[5].color,
|
||||
dbpc->item_tint[6].color,
|
||||
dbpc->item_tint[7].color,
|
||||
dbpc->item_tint[8].color
|
||||
);
|
||||
auto results = QueryDatabase(query);
|
||||
uint32 last_insert_id = results.LastInsertedID();
|
||||
|
||||
std::string corpse_items_query;
|
||||
/* Dump Items from Inventory */
|
||||
uint8 first_entry = 0;
|
||||
for (unsigned int i = 0; i < dbpc->itemcount; i++) {
|
||||
if (first_entry != 1){
|
||||
query = StringFormat("REPLACE INTO `character_corpse_items` \n"
|
||||
corpse_items_query = StringFormat("REPLACE INTO `character_corpse_items` \n"
|
||||
" (corpse_id, equip_slot, item_id, charges, aug_1, aug_2, aug_3, aug_4, aug_5, aug_6, attuned) \n"
|
||||
" VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n",
|
||||
last_insert_id,
|
||||
@@ -3462,7 +3535,7 @@ uint32 ZoneDatabase::SaveCharacterCorpse(uint32 charid, const char* charname, ui
|
||||
first_entry = 1;
|
||||
}
|
||||
else{
|
||||
query = query + StringFormat(", (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n",
|
||||
corpse_items_query = corpse_items_query + StringFormat(", (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n",
|
||||
last_insert_id,
|
||||
dbpc->items[i].equip_slot,
|
||||
dbpc->items[i].item_id,
|
||||
@@ -3477,7 +3550,9 @@ uint32 ZoneDatabase::SaveCharacterCorpse(uint32 charid, const char* charname, ui
|
||||
);
|
||||
}
|
||||
}
|
||||
auto sc_results = QueryDatabase(query);
|
||||
if (!corpse_items_query.empty())
|
||||
QueryDatabase(corpse_items_query);
|
||||
|
||||
return last_insert_id;
|
||||
}
|
||||
|
||||
|
||||
@@ -256,6 +256,7 @@ public:
|
||||
void LoadPetInfo(Client *c);
|
||||
void SavePetInfo(Client *c);
|
||||
void RemoveTempFactions(Client *c);
|
||||
void UpdateItemRecastTimestamps(uint32 char_id, uint32 recast_type, uint32 timestamp);
|
||||
|
||||
/* Character Data Loaders */
|
||||
bool LoadCharacterFactionValues(uint32 character_id, faction_map & val_list);
|
||||
|
||||
Reference in New Issue
Block a user