Merge git://github.com/EQEmu/Server into Development

This commit is contained in:
KayenEQ
2014-09-22 17:50:35 -04:00
79 changed files with 4242 additions and 4209 deletions
-2
View File
@@ -119,7 +119,6 @@ SET(zone_sources
zone_logsys.cpp
zone_config.cpp
zonedb.cpp
zonedbasync.cpp
zoning.cpp
)
@@ -207,7 +206,6 @@ SET(zone_headers
zone.h
zone_config.h
zonedb.h
zonedbasync.h
zonedump.h
)
+29 -14
View File
@@ -18,6 +18,8 @@ Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net)
// Test 1
#include <iostream>
#include "../common/debug.h"
#include "aa.h"
#include "mob.h"
@@ -300,7 +302,7 @@ void Client::ActivateAA(aaID activate){
return;
}
} else {
if(!CastSpell(caa->spell_id, target_id, 10, -1, -1, 0, -1, AATimerID + pTimerAAStart, timer_base, 1)) {
if (!CastSpell(caa->spell_id, target_id, USE_ITEM_SPELL_SLOT, -1, -1, 0, -1, AATimerID + pTimerAAStart, timer_base, 1)) {
//Reset on failed cast
SendAATimer(AATimerID, 0, 0xFFFFFF);
Message_StringID(15,ABILITY_FAILED);
@@ -316,13 +318,14 @@ void Client::ActivateAA(aaID activate){
}
}
// Check if AA is expendable
if (aas_send[activate - activate_val]->special_category == 7)
{
if (aas_send[activate - activate_val]->special_category == 7) {
// Add the AA cost to the extended profile to track overall total
m_epp.expended_aa += aas_send[activate]->cost;
SetAA(activate, 0);
Save();
SaveAA(); /* Save Character AA */
SendAA(activate);
SendAATable();
}
@@ -525,7 +528,7 @@ void Client::HandleAAAction(aaID activate) {
//cast the spell, if we have one
if(IsValidSpell(spell_id)) {
int aatid = GetAATimerID(activate);
if(!CastSpell(spell_id, target_id , 10, -1, -1, 0, -1, pTimerAAStart + aatid , CalcAAReuseTimer(caa), 1)) {
if (!CastSpell(spell_id, target_id, USE_ITEM_SPELL_SLOT, -1, -1, 0, -1, pTimerAAStart + aatid, CalcAAReuseTimer(caa), 1)) {
SendAATimer(aatid, 0, 0xFFFFFF);
Message_StringID(15,ABILITY_FAILED);
p_timers.Clear(&database, pTimerAAStart + aatid);
@@ -1035,8 +1038,7 @@ void Client::BuyAA(AA_Action* action)
uint32 real_cost;
std::map<uint32, AALevelCost_Struct>::iterator RequiredLevel = AARequiredLevelAndCost.find(action->ability);
if(RequiredLevel != AARequiredLevelAndCost.end())
{
if(RequiredLevel != AARequiredLevelAndCost.end()) {
real_cost = RequiredLevel->second.Cost;
}
else
@@ -1049,7 +1051,11 @@ void Client::BuyAA(AA_Action* action)
m_pp.aapoints -= real_cost;
Save();
/* Do Player Profile rank calculations and set player profile */
SaveAA();
/* Save to Database to avoid having to write the whole AA array to the profile, only write changes*/
// database.SaveCharacterAA(this->CharacterID(), aa2->id, (cur_level + 1));
if ((RuleB(AA, Stacking) && (GetClientVersionBit() >= 4) && (aa2->hotkey_sid == 4294967295u))
&& ((aa2->max_level == (cur_level + 1)) && aa2->sof_next_id)){
SendAA(aa2->id);
@@ -1060,8 +1066,10 @@ void Client::BuyAA(AA_Action* action)
SendAATable();
//we are building these messages ourself instead of using the stringID to work around patch discrepencies
//these are AA_GAIN_ABILITY (410) & AA_IMPROVE (411), respectively, in both Titanium & SoF. not sure about 6.2
/*
We are building these messages ourself instead of using the stringID to work around patch discrepencies
these are AA_GAIN_ABILITY (410) & AA_IMPROVE (411), respectively, in both Titanium & SoF. not sure about 6.2
*/
/* Initial purchase of an AA ability */
if (cur_level < 1){
@@ -1084,8 +1092,6 @@ void Client::BuyAA(AA_Action* action)
}
}
SendAAStats();
CalcBonuses();
@@ -1514,11 +1520,15 @@ bool ZoneDatabase::LoadAAEffects2() {
return true;
}
void Client::ResetAA(){
RefundAA();
uint32 i;
for(i=0;i<MAX_PP_AA_ARRAY;i++){
aa[i]->AA = 0;
aa[i]->value = 0;
m_pp.aa_array[MAX_PP_AA_ARRAY].AA = 0;
m_pp.aa_array[MAX_PP_AA_ARRAY].value = 0;
}
std::map<uint32,uint8>::iterator itr;
for(itr=aa_points.begin();itr!=aa_points.end();++itr)
aa_points[itr->first] = 0;
@@ -1530,6 +1540,12 @@ void Client::ResetAA(){
m_pp.raid_leadership_points = 0;
m_pp.group_leadership_exp = 0;
m_pp.raid_leadership_exp = 0;
database.DeleteCharacterAAs(this->CharacterID());
SaveAA();
SendAATable();
database.DeleteCharacterLeadershipAAs(this->CharacterID());
Kick();
}
int Client::GroupLeadershipAAHealthEnhancement()
@@ -1818,8 +1834,7 @@ void ZoneDatabase::LoadAAs(SendAA_Struct **load){
}
AALevelCost_Struct aalcs;
for (auto row = results.begin(); row != results.end(); ++row)
{
for (auto row = results.begin(); row != results.end(); ++row) {
aalcs.Level = atoi(row[1]);
aalcs.Cost = atoi(row[2]);
AARequiredLevelAndCost[atoi(row[0])] = aalcs;
+2 -2
View File
@@ -311,11 +311,11 @@ public:
virtual float GetAOERange(uint16 spell_id);
virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100);
virtual void DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caster_level, Mob* caster = 0);
virtual bool CastSpell(uint16 spell_id, uint16 target_id, uint16 slot = 10, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, int16 *resist_adjust = nullptr);
virtual bool CastSpell(uint16 spell_id, uint16 target_id, uint16 slot = USE_ITEM_SPELL_SLOT, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, int16 *resist_adjust = nullptr);
virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar);
virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster);
virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction);
virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot = 10, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF);
virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot = USE_ITEM_SPELL_SLOT, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF);
// Bot Action Command Methods
bool MesmerizeTarget(Mob* target);
+107 -167
View File
@@ -73,8 +73,6 @@ extern uint32 numclients;
extern PetitionList petition_list;
bool commandlogged;
char entirecommand[255];
extern DBAsyncFinishedQueue MTdbafq;
extern DBAsync *dbasync;
Client::Client(EQStreamInterface* ieqs)
: Mob("No name", // name
@@ -479,60 +477,23 @@ void Client::ReportConnectingState() {
};
}
bool Client::Save(uint8 iCommitNow) {
#if 0
// Orig. Offset: 344 / 0x00000000
// Length: 36 / 0x00000024
unsigned char rawData[36] =
{
0x0D, 0x30, 0xE1, 0x30, 0x1E, 0x10, 0x22, 0x10, 0x20, 0x10, 0x21, 0x10, 0x1C, 0x20, 0x1F, 0x10,
0x7C, 0x10, 0x68, 0x10, 0x51, 0x10, 0x78, 0x10, 0xBD, 0x10, 0xD2, 0x10, 0xCD, 0x10, 0xD1, 0x10,
0x01, 0x10, 0x6D, 0x10
} ;
for (int tmp = 0;tmp <=35;tmp++){
m_pp.unknown0256[89+tmp] = rawData[tmp];
}
#endif
if(!ClientDataLoaded())
return false;
m_pp.x = x_pos;
m_pp.y = y_pos;
m_pp.z = z_pos;
m_pp.guildrank=guildrank;
m_pp.heading = heading;
// Temp Hack for signed values until we get the root of the problem changed over to signed...
if (m_pp.copper < 0) { m_pp.copper = 0; }
if (m_pp.silver < 0) { m_pp.silver = 0; }
if (m_pp.gold < 0) { m_pp.gold = 0; }
if (m_pp.platinum < 0) { m_pp.platinum = 0; }
if (m_pp.copper_bank < 0) { m_pp.copper_bank = 0; }
if (m_pp.silver_bank < 0) { m_pp.silver_bank = 0; }
if (m_pp.gold_bank < 0) { m_pp.gold_bank = 0; }
if (m_pp.platinum_bank < 0) { m_pp.platinum_bank = 0; }
int spentpoints=0;
for(int a=0;a < MAX_PP_AA_ARRAY;a++) {
bool Client::SaveAA(){
int first_entry = 0;
std::string rquery;
/* Save Player AA */
int spentpoints = 0;
for (int a = 0; a < MAX_PP_AA_ARRAY; a++) {
uint32 points = aa[a]->value;
if(points > HIGHEST_AA_VALUE) // Unifying this
{
if (points > HIGHEST_AA_VALUE) {
aa[a]->value = HIGHEST_AA_VALUE;
points = HIGHEST_AA_VALUE;
}
if (points > 0)
{
SendAA_Struct* curAA = zone->FindAA(aa[a]->AA-aa[a]->value+1);
if(curAA)
{
for (int rank=0; rank<points; rank++)
{
std::map<uint32, AALevelCost_Struct>::iterator RequiredLevel = AARequiredLevelAndCost.find(aa[a]->AA-aa[a]->value + 1 + rank);
if(RequiredLevel != AARequiredLevelAndCost.end())
{
if (points > 0) {
SendAA_Struct* curAA = zone->FindAA(aa[a]->AA - aa[a]->value + 1);
if (curAA) {
for (int rank = 0; rank<points; rank++) {
std::map<uint32, AALevelCost_Struct>::iterator RequiredLevel = AARequiredLevelAndCost.find(aa[a]->AA - aa[a]->value + 1 + rank);
if (RequiredLevel != AARequiredLevelAndCost.end()) {
spentpoints += RequiredLevel->second.Cost;
}
else
@@ -541,42 +502,61 @@ bool Client::Save(uint8 iCommitNow) {
}
}
}
m_pp.aapoints_spent = spentpoints + m_epp.expended_aa;
if (GetHP() <= 0) {
m_pp.cur_hp = GetMaxHP();
for (int a = 0; a < MAX_PP_AA_ARRAY; a++) {
if (aa[a]->AA > 0 && aa[a]->value){
if (first_entry != 1){
rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, slot, aa_id, aa_value)"
" VALUES (%u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value);
first_entry = 1;
}
rquery = rquery + StringFormat(", (%u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value);
}
}
else
m_pp.cur_hp = GetHP();
auto results = database.QueryDatabase(rquery);
return true;
}
bool Client::Save(uint8 iCommitNow) {
if(!ClientDataLoaded())
return false;
/* Wrote current basics to PP for saves */
m_pp.x = x_pos;
m_pp.y = y_pos;
m_pp.z = z_pos;
m_pp.guildrank = guildrank;
m_pp.heading = heading;
/* Mana and HP */
if (GetHP() <= 0) { m_pp.cur_hp = GetMaxHP(); }
else { m_pp.cur_hp = GetHP(); }
m_pp.mana = cur_mana;
m_pp.endurance = cur_end;
/* Save Character Currency */
database.SaveCharacterCurrency(this->CharacterID(), &m_pp);
/* Save Current Bind Points : Sets Instance to 0 because it is currently not implemented */
database.SaveCharacterBindPoint(this->CharacterID(), m_pp.binds[0].zoneId, 0, m_pp.binds[0].x, m_pp.binds[0].y, m_pp.binds[0].z, 0, 0); /* Regular bind */
database.SaveCharacterBindPoint(this->CharacterID(), m_pp.binds[4].zoneId, 0, m_pp.binds[4].x, m_pp.binds[4].y, m_pp.binds[4].z, 0, 1); /* Home Bind */
/* Save Character Buffs */
database.SaveBuffs(this);
/* Total Time Played */
TotalSecondsPlayed += (time(nullptr) - m_pp.lastlogin);
m_pp.timePlayedMin = (TotalSecondsPlayed / 60);
m_pp.RestTimer = rest_timer.GetRemainingTime() / 1000;
if(GetMercInfo().MercTimerRemaining > RuleI(Mercs, UpkeepIntervalMS))
GetMercInfo().MercTimerRemaining = RuleI(Mercs, UpkeepIntervalMS);
if(GetMercTimer()->Enabled()) {
GetMercInfo().MercTimerRemaining = GetMercTimer()->GetRemainingTime();
}
if (GetMerc() && !dead) {
} else {
memset(&m_mercinfo, 0, sizeof(struct MercInfo));
}
/* Save Mercs */
if (GetMercInfo().MercTimerRemaining > RuleI(Mercs, UpkeepIntervalMS)){ GetMercInfo().MercTimerRemaining = RuleI(Mercs, UpkeepIntervalMS); }
if (GetMercTimer()->Enabled()) { GetMercInfo().MercTimerRemaining = GetMercTimer()->GetRemainingTime(); }
if (GetMerc() && !dead) { }
else { memset(&m_mercinfo, 0, sizeof(struct MercInfo)); }
m_pp.lastlogin = time(nullptr);
if (pQueuedSaveWorkID) {
dbasync->CancelWork(pQueuedSaveWorkID);
pQueuedSaveWorkID = 0;
}
if (GetPet() && !GetPet()->IsFamiliar() && GetPet()->CastToNPC()->GetPetSpellID() && !dead) {
NPC *pet = GetPet()->CastToNPC();
@@ -591,58 +571,19 @@ bool Client::Save(uint8 iCommitNow) {
}
database.SavePetInfo(this);
if(tribute_timer.Enabled()) {
m_pp.tribute_time_remaining = tribute_timer.GetRemainingTime();
} else {
m_pp.tribute_time_remaining = 0xFFFFFFFF;
m_pp.tribute_active = 0;
}
if(tribute_timer.Enabled()) { m_pp.tribute_time_remaining = tribute_timer.GetRemainingTime(); }
else { m_pp.tribute_time_remaining = 0xFFFFFFFF; m_pp.tribute_active = 0; }
p_timers.Store(&database);
// printf("Dumping inventory on save:\n");
// m_inv.dumpEntireInventory();
SaveTaskState();
if (iCommitNow <= 1) {
char* query = 0;
uint32_breakdown workpt;
workpt.b4() = DBA_b4_Entity;
workpt.w2_3() = GetID();
workpt.b1() = DBA_b1_Entity_Client_Save;
DBAsyncWork* dbaw = new DBAsyncWork(&database, &MTdbafq, workpt, DBAsync::Write, 0xFFFFFFFF);
dbaw->AddQuery(iCommitNow == 0 ? true : false, &query, database.SetPlayerProfile_MQ(&query, account_id, character_id, &m_pp, &m_inv, &m_epp, 0, 0, MaxXTargets), false);
if (iCommitNow == 0){
pQueuedSaveWorkID = dbasync->AddWork(&dbaw, 2500);
}
else {
dbasync->AddWork(&dbaw, 0);
SaveBackup();
}
safe_delete_array(query);
return true;
}
else if (database.SetPlayerProfile(account_id, character_id, &m_pp, &m_inv, &m_epp, 0, 0, MaxXTargets)) {
SaveBackup();
}
else {
std::cerr << "Failed to update player profile" << std::endl;
return false;
}
/* Mirror Character Data */
database.StoreCharacterLookup(this->CharacterID());
database.SaveCharacterTribute(this->CharacterID(), &m_pp);
SaveTaskState(); /* Save Character Task */
database.SaveCharacterData(this->CharacterID(), this->AccountID(), &m_pp, &m_epp); /* Save Character Data */
return true;
}
void Client::SaveBackup() {
if (!RunLoops)
return;
char* query = 0;
DBAsyncWork* dbaw = new DBAsyncWork(&database, &DBAsyncCB_CharacterBackup, this->CharacterID(), DBAsync::Read);
dbaw->AddQuery(0, &query, MakeAnyLenString(&query, "Select id, UNIX_TIMESTAMP()-UNIX_TIMESTAMP(ts) as age from character_backup where charid=%u and backupreason=0 order by ts asc", this->CharacterID()), true);
dbasync->AddWork(&dbaw, 0);
}
CLIENTPACKET::CLIENTPACKET()
@@ -1406,12 +1347,14 @@ bool Client::UpdateLDoNPoints(int32 points, uint32 theme)
void Client::SetSkill(SkillUseTypes skillid, uint16 value) {
if (skillid > HIGHEST_SKILL)
return;
m_pp.skills[skillid] = value; // We need to be able to #setskill 254 and 255 to reset skills
return;
m_pp.skills[skillid] = value; // We need to be able to #setskill 254 and 255 to reset skills
database.SaveCharacterSkill(this->CharacterID(), skillid, value);
EQApplicationPacket* outapp = new EQApplicationPacket(OP_SkillUpdate, sizeof(SkillUpdate_Struct));
SkillUpdate_Struct* skill = (SkillUpdate_Struct*)outapp->pBuffer;
skill->skillId=skillid;
skill->skillId=skillid;
skill->value=value;
QueuePacket(outapp);
safe_delete(outapp);
@@ -1427,10 +1370,12 @@ void Client::IncreaseLanguageSkill(int skill_id, int value) {
if (m_pp.languages[skill_id] > 100) //Lang skill above max
m_pp.languages[skill_id] = 100;
database.SaveCharacterLanguage(this->CharacterID(), skill_id, m_pp.languages[skill_id]);
EQApplicationPacket* outapp = new EQApplicationPacket(OP_SkillUpdate, sizeof(SkillUpdate_Struct));
SkillUpdate_Struct* skill = (SkillUpdate_Struct*)outapp->pBuffer;
skill->skillId = 100 + skill_id;
skill->value = m_pp.languages[skill_id];
skill->value = m_pp.languages[skill_id];
QueuePacket(outapp);
safe_delete(outapp);
@@ -2115,7 +2060,7 @@ bool Client::TakeMoneyFromPP(uint64 copper, bool updateclient) {
m_pp.copper = copperpp;
if(updateclient)
SendMoneyUpdate();
Save();
SaveCurrency();
return true;
}
silver -= copper;
@@ -2130,7 +2075,7 @@ bool Client::TakeMoneyFromPP(uint64 copper, bool updateclient) {
m_pp.copper += (silver-(m_pp.silver*10));
if(updateclient)
SendMoneyUpdate();
Save();
SaveCurrency();
return true;
}
@@ -2150,7 +2095,7 @@ bool Client::TakeMoneyFromPP(uint64 copper, bool updateclient) {
m_pp.copper += coppertest;
if(updateclient)
SendMoneyUpdate();
Save();
SaveCurrency();
return true;
}
@@ -2168,7 +2113,7 @@ bool Client::TakeMoneyFromPP(uint64 copper, bool updateclient) {
if(updateclient)
SendMoneyUpdate();
RecalcWeight();
Save();
SaveCurrency();
return true;
}
}
@@ -2178,32 +2123,27 @@ void Client::AddMoneyToPP(uint64 copper, bool updateclient){
uint64 tmp2;
tmp = copper;
// Add Amount of Platinum
/* Add Amount of Platinum */
tmp2 = tmp/1000;
int32 new_val = m_pp.platinum + tmp2;
if(new_val < 0) {
m_pp.platinum = 0;
} else {
m_pp.platinum = m_pp.platinum + tmp2;
}
if(new_val < 0) { m_pp.platinum = 0; }
else { m_pp.platinum = m_pp.platinum + tmp2; }
tmp-=tmp2*1000;
//if (updateclient)
// SendClientMoneyUpdate(3,tmp2);
// Add Amount of Gold
/* Add Amount of Gold */
tmp2 = tmp/100;
new_val = m_pp.gold + tmp2;
if(new_val < 0) {
m_pp.gold = 0;
} else {
m_pp.gold = m_pp.gold + tmp2;
}
if(new_val < 0) { m_pp.gold = 0; }
else { m_pp.gold = m_pp.gold + tmp2; }
tmp-=tmp2*100;
//if (updateclient)
// SendClientMoneyUpdate(2,tmp2);
// Add Amount of Silver
/* Add Amount of Silver */
tmp2 = tmp/10;
new_val = m_pp.silver + tmp2;
if(new_val < 0) {
@@ -2234,13 +2174,12 @@ void Client::AddMoneyToPP(uint64 copper, bool updateclient){
RecalcWeight();
Save();
SaveCurrency();
LogFile->write(EQEMuLog::Debug, "Client::AddMoneyToPP() %s should have: plat:%i gold:%i silver:%i copper:%i", GetName(), m_pp.platinum, m_pp.gold, m_pp.silver, m_pp.copper);
}
void Client::AddMoneyToPP(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, bool updateclient){
void Client::EVENT_ITEM_ScriptStopReturn(){
/* Set a timestamp in an entity variable for plugin check_handin.pl in return_items
This will stopgap players from items being returned if global_npc.pl has a catch all return_items
*/
@@ -2249,6 +2188,10 @@ void Client::AddMoneyToPP(uint32 copper, uint32 silver, uint32 gold, uint32 plat
gettimeofday(&read_time, 0);
sprintf(buffer, "%li.%li \n", read_time.tv_sec, read_time.tv_usec);
this->SetEntityVariable("Stop_Return", buffer);
}
void Client::AddMoneyToPP(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, bool updateclient){
this->EVENT_ITEM_ScriptStopReturn();
int32 new_value = m_pp.platinum + platinum;
if(new_value >= 0 && new_value > m_pp.platinum)
@@ -2270,7 +2213,7 @@ void Client::AddMoneyToPP(uint32 copper, uint32 silver, uint32 gold, uint32 plat
SendMoneyUpdate();
RecalcWeight();
Save();
SaveCurrency();
#if (EQDEBUG>=5)
LogFile->write(EQEMuLog::Debug, "Client::AddMoneyToPP() %s should have: plat:%i gold:%i silver:%i copper:%i",
@@ -2807,11 +2750,6 @@ void Client::SetMaterial(int16 in_slot, uint32 item_id) {
m_pp.item_material[MaterialArms] = item->Material;
else if (in_slot==MainWrist1)
m_pp.item_material[MaterialWrist] = item->Material;
/*
// non-live behavior
else if (in_slot==SLOT_BRACER02)
m_pp.item_material[MaterialWrist] = item->Material;
*/
else if (in_slot==MainHands)
m_pp.item_material[MaterialHands] = item->Material;
else if (in_slot==MainLegs)
@@ -3134,10 +3072,19 @@ void Client::FilteredMessage_StringID(Mob *sender, uint32 type, eqFilterType fil
safe_delete(outapp);
}
void Client::Tell_StringID(uint32 string_id, const char *who, const char *message)
{
char string_id_str[10];
snprintf(string_id_str, 10, "%d", string_id);
Message_StringID(MT_TellEcho, TELL_QUEUED_MESSAGE, who, string_id_str, message);
}
void Client::SetTint(int16 in_slot, uint32 color) {
Color_Struct new_color;
new_color.color = color;
SetTint(in_slot, new_color);
database.SaveCharacterMaterialColor(this->CharacterID(), in_slot, color);
}
// Still need to reconcile bracer01 versus bracer02
@@ -3165,6 +3112,8 @@ void Client::SetTint(int16 in_slot, Color_Struct& color) {
m_pp.item_tint[MaterialLegs].color=color.color;
else if (in_slot==MainFeet)
m_pp.item_tint[MaterialFeet].color=color.color;
database.SaveCharacterMaterialColor(this->CharacterID(), in_slot, color.color);
}
void Client::SetHideMe(bool flag)
@@ -3199,6 +3148,7 @@ void Client::SetLanguageSkill(int langid, int value)
value = 100; //Max lang value
m_pp.languages[langid] = value;
database.SaveCharacterLanguage(this->CharacterID(), langid, value);
EQApplicationPacket* outapp = new EQApplicationPacket(OP_SkillUpdate, sizeof(SkillUpdate_Struct));
SkillUpdate_Struct* skill = (SkillUpdate_Struct*)outapp->pBuffer;
@@ -4270,7 +4220,6 @@ void Client::VoiceMacroReceived(uint32 Type, char *Target, uint32 MacroNumber) {
}
void Client::ClearGroupAAs() {
for(unsigned int i = 0; i < MAX_GROUP_LEADERSHIP_AA_ARRAY; i++)
m_pp.leader_abilities.ranks[i] = 0;
@@ -4280,28 +4229,18 @@ void Client::ClearGroupAAs() {
m_pp.raid_leadership_exp = 0;
Save();
database.SaveCharacterLeadershipAA(this->CharacterID(), &m_pp);
}
void Client::UpdateGroupAAs(int32 points, uint32 type) {
switch(type)
{
case 0:
{
m_pp.group_leadership_points += points;
break;
}
case 1:
{
m_pp.raid_leadership_points += points;
break;
}
switch(type) {
case 0: { m_pp.group_leadership_points += points; break; }
case 1: { m_pp.raid_leadership_points += points; break; }
}
SendLeadershipEXPUpdate();
}
bool Client::IsLeadershipEXPOn()
{
bool Client::IsLeadershipEXPOn() {
if(!m_pp.leadAAActive)
return false;
@@ -5718,7 +5657,7 @@ void Client::AddCrystals(uint32 Radiant, uint32 Ebon)
m_pp.currentEbonCrystals += Ebon;
m_pp.careerEbonCrystals += Ebon;
Save();
SaveCurrency();
SendCrystalCounts();
}
@@ -8024,7 +7963,7 @@ void Client::RefundAA() {
for(int j = 0; j < cur; j++) {
m_pp.aapoints += curaa->cost + (curaa->cost_inc * j);
refunded = true;
}
}
}
else
{
@@ -8036,8 +7975,9 @@ void Client::RefundAA() {
}
if(refunded) {
SaveAA();
Save();
Kick();
// Kick();
}
}
+11 -11
View File
@@ -37,6 +37,7 @@ class Client;
#include "../common/item_struct.h"
#include "../common/clientversions.h"
#include "common.h"
#include "zonedb.h"
#include "errno.h"
#include "mob.h"
@@ -102,11 +103,6 @@ enum { //scribing argument to MemorizeSpell
memSpellSpellbar = 3
};
#define USE_ITEM_SPELL_SLOT 10
#define POTION_BELT_SPELL_SLOT 11
#define DISCIPLINE_SPELL_SLOT 10
#define ABILITY_SPELL_SLOT 9
//Modes for the zoning state of the client.
typedef enum {
ZoneToSafeCoords, // Always send ZonePlayerToBind_Struct to client: Succor/Evac
@@ -240,8 +236,6 @@ public:
bool KeyRingCheck(uint32 item_id);
void KeyRingList();
virtual bool IsClient() const { return true; }
virtual void DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw);
bool FinishConnState2(DBAsyncWork* dbaw);
void CompleteConnect();
bool TryStacking(ItemInst* item, uint8 type = ItemPacketTrade, bool try_worn = true, bool try_cursor = true);
void SendTraderPacket(Client* trader, uint32 Unknown72 = 51);
@@ -260,6 +254,7 @@ public:
const char *message5 = nullptr, const char *message6 = nullptr,
const char *message7 = nullptr, const char *message8 = nullptr,
const char *message9 = nullptr);
void Tell_StringID(uint32 string_id, const char *who, const char *message);
void SendBazaarResults(uint32 trader_id,uint32 class_,uint32 race,uint32 stat,uint32 slot,uint32 type,char name[64],uint32 minprice,uint32 maxprice);
void SendTraderItem(uint32 item_id,uint16 quantity);
uint16 FindTraderItem(int32 SerialNumber,uint16 Quantity);
@@ -315,6 +310,10 @@ public:
bool Save(uint8 iCommitNow); // 0 = delayed, 1=async now, 2=sync now
void SaveBackup();
/* New PP Save Functions */
bool SaveCurrency(){ return database.SaveCharacterCurrency(this->CharacterID(), &m_pp); }
bool SaveAA();
inline bool ClientDataLoaded() const { return client_data_loaded; }
inline bool Connected() const { return (client_state == CLIENT_CONNECTED); }
inline bool InZone() const { return (client_state == CLIENT_CONNECTED || client_state == CLIENT_LINKDEAD); }
@@ -657,14 +656,14 @@ public:
void OnDisconnect(bool hard_disconnect);
uint16 GetSkillPoints() {return m_pp.points;}
void SetSkillPoints(int inp) {m_pp.points = inp;}
uint16 GetSkillPoints() { return m_pp.points;}
void SetSkillPoints(int inp) { m_pp.points = inp;}
void IncreaseSkill(int skill_id, int value = 1) { if (skill_id <= HIGHEST_SKILL) { m_pp.skills[skill_id] += value; } }
void IncreaseLanguageSkill(int skill_id, int value = 1);
virtual uint16 GetSkill(SkillUseTypes skill_id) const { if (skill_id <= HIGHEST_SKILL) { return((itembonuses.skillmod[skill_id] > 0)? m_pp.skills[skill_id]*(100 + itembonuses.skillmod[skill_id])/100 : m_pp.skills[skill_id]); } return 0; }
virtual uint16 GetSkill(SkillUseTypes skill_id) const { if (skill_id <= HIGHEST_SKILL) { return((itembonuses.skillmod[skill_id] > 0) ? m_pp.skills[skill_id] * (100 + itembonuses.skillmod[skill_id]) / 100 : m_pp.skills[skill_id]); } return 0; }
uint32 GetRawSkill(SkillUseTypes skill_id) const { if (skill_id <= HIGHEST_SKILL) { return(m_pp.skills[skill_id]); } return 0; }
bool HasSkill(SkillUseTypes skill_id) const;
bool HasSkill(SkillUseTypes skill_id) const;
bool CanHaveSkill(SkillUseTypes skill_id) const;
void SetSkill(SkillUseTypes skill_num, uint16 value);
void AddSkill(SkillUseTypes skillid, uint16 value);
@@ -785,6 +784,7 @@ public:
int16 acmod();
// Item methods
void EVENT_ITEM_ScriptStopReturn();
uint32 NukeItem(uint32 itemnum, uint8 where_to_check =
(invWhereWorn | invWherePersonal | invWhereBank | invWhereSharedBank | invWhereTrading | invWhereCursor));
void SetTint(int16 slot_id, uint32 color);
+2 -3
View File
@@ -33,14 +33,12 @@ void ClientLogs::subscribe(EQEMuLog::LogIDs id, Client *c) {
if(c == nullptr)
return;
//make sure they arnt allready subscribed.
std::vector<Client *>::iterator cur,end;
cur = entries[id].begin();
end = entries[id].end();
for(; cur != end; ++cur) {
if(*cur == c) {
printf("%s was allready subscribed to %d\n", c->GetName(), id);
printf("%s was already subscribed to %d\n", c->GetName(), id);
return;
}
}
@@ -100,6 +98,7 @@ void ClientLogs::msg(EQEMuLog::LogIDs id, const char *buf) {
for(; cur != end; ++cur) {
if(!(*cur)->InZone())
continue;
(*cur)->Message(CLIENT_LOG_CHANNEL, buf);
}
}
+552 -693
View File
File diff suppressed because it is too large Load Diff
+9 -3
View File
@@ -1547,7 +1547,12 @@ void Client::OPMoveCoin(const EQApplicationPacket* app)
if (from_bucket == &m_pp.platinum_shared)
amount_to_add = 0 - amount_to_take;
database.SetSharedPlatinum(AccountID(),amount_to_add);
database.SetSharedPlatinum(AccountID(),amount_to_add);
}
}
else{
if (to_bucket == &m_pp.platinum_shared || from_bucket == &m_pp.platinum_shared){
this->Message(13, "::: WARNING! ::: SHARED BANK IS DISABLED AND YOUR PLATINUM WILL BE DESTROYED IF YOU PUT IT HERE");
}
}
}
@@ -1580,7 +1585,7 @@ void Client::OPMoveCoin(const EQApplicationPacket* app)
safe_delete(outapp);
}
Save();
SaveCurrency();
}
void Client::OPGMTraining(const EQApplicationPacket *app)
@@ -1715,6 +1720,7 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app)
}
uint16 skilllevel = GetRawSkill(skill);
if(skilllevel == 0) {
//this is a new skill..
uint16 t_level = SkillTrainLevel(skill, GetClass());
@@ -1724,7 +1730,7 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app)
}
SetSkill(skill, t_level);
} else {
} else {
switch(skill) {
case SkillBrewing:
case SkillMakePoison:
+83 -230
View File
@@ -149,7 +149,7 @@ Access Levels:
int command_init(void) {
if
(
command_add("resetaa","- Resets a Player's AA in their profile.",200,command_resetaa) ||
command_add("resetaa","- Resets a Player's AA in their profile and refunds spent AA's to unspent, disconnects player.",200,command_resetaa) ||
command_add("qtest","- QueryServ testing command.",255,command_qtest) ||
command_add("bind","- Sets your targets bind spot to their current location",200,command_bind) ||
command_add("sendop","[opcode] - LE's Private test command, leave it alone",200,command_sendop) ||
@@ -225,7 +225,6 @@ int command_init(void) {
command_add("worldshutdown","- Shut down world and all zones",200,command_worldshutdown) ||
command_add("sendzonespawns","- Refresh spawn list for all clients in zone",150,command_sendzonespawns) ||
command_add("dbspawn2","[spawngroup] [respawn] [variance] - Spawn an NPC from a predefined row in the spawn2 table",100,command_dbspawn2) ||
command_add("copychar","[character name] [new character] [new account id] - Create a copy of a character",100,command_copychar) ||
command_add("shutdown","- Shut this zone process down",150,command_shutdown) ||
command_add("delacct","[accountname] - Delete an account",150,command_delacct) ||
command_add("setpass","[accountname] [password] - Set local password for accountname",150,command_setpass) ||
@@ -258,12 +257,11 @@ int command_init(void) {
command_add("dbspawn",nullptr,0,command_npctypespawn) ||
command_add("heal","- Completely heal your target",10,command_heal) ||
command_add("appearance","[type] [value] - Send an appearance packet for you or your target",150,command_appearance) ||
command_add("charbackup","[list/restore] - Query or restore character backups",150,command_charbackup) ||
command_add("nukeitem","[itemid] - Remove itemid from your player target's inventory",150,command_nukeitem) ||
command_add("peekinv","[worn/cursor/inv/bank/trade/trib/all] - Print out contents of your player target's inventory",100,command_peekinv) ||
command_add("findnpctype","[search criteria] - Search database NPC types",100,command_findnpctype) ||
command_add("findzone","[search criteria] - Search database zones",100,command_findzone) ||
command_add("fz",nullptr,100,command_findzone) ||
command_add("fz",nullptr,100, command_findzone) ||
command_add("viewnpctype","[npctype id] - Show info about an npctype",100,command_viewnpctype) ||
command_add("reloadstatic","- Reload Static Zone Data",150,command_reloadstatic) ||
command_add("reloadquest"," - Clear quest cache (any argument causes it to also stop all timers)",150,command_reloadqst) ||
@@ -333,8 +331,6 @@ int command_init(void) {
command_add("guilds",nullptr,0,command_guild) ||
command_add("zonestatus","- Show connected zoneservers, synonymous with /servers",150,command_zonestatus) ||
command_add("manaburn","- Use AA Wizard class skill manaburn on target",10,command_manaburn) ||
command_add("viewmessage","[id] - View messages in your tell queue",100,command_viewmessage) ||
command_add("viewmessages",nullptr,0,command_viewmessage) ||
command_add("doanim","[animnum] [type] - Send an EmoteAnim for you or your target",50,command_doanim) ||
command_add("randomfeatures","- Temporarily randomizes the Facial Features of your target",80,command_randomfeatures) ||
command_add("rf",nullptr,80,command_randomfeatures) ||
@@ -407,7 +403,6 @@ int command_init(void) {
command_add("guildapprove","[guildapproveid] - Approve a guild with specified ID (guild creator receives the id)",0,command_guildapprove) ||
command_add("guildlist","[guildapproveid] - Lists character names who have approved the guild specified by the approve id",0,command_guildlist) ||
command_add("altactivate", "[argument] - activates alternate advancement abilities, use altactivate help for more information", 0, command_altactivate) ||
command_add("refundaa", "- Refunds your target's AA points, will disconnect them in the process as well.", 100, command_refundaa) ||
#ifdef BOTS
command_add("bot","- Type \"#bot help\" to the see the list of available commands for bots.", 0, command_bot) ||
@@ -2158,8 +2153,8 @@ void command_worldshutdown(Client *c, const Seperator *sep)
uint32 interval=0;
if (worldserver.Connected()) {
if(sep->IsNumber(1) && sep->IsNumber(2) && ((time=atoi(sep->arg[1]))>0) && ((interval=atoi(sep->arg[2]))>0)) {
worldserver.SendEmoteMessage(0,0,15,"<SYSTEMWIDE MESSAGE>:SYSTEM MSG:World coming down in %i seconds, everyone log out before this time.",time);
c->Message(0, "Sending shutdown packet now, World will shutdown in: %i Seconds with an interval of: %i",time,interval);
worldserver.SendEmoteMessage(0,0,15,"<SYSTEMWIDE MESSAGE>:SYSTEM MSG:World coming down in %i minutes, everyone log out before this time.", (time / 60 ));
c->Message(0, "Sending shutdown packet now, World will shutdown in: %i minutes with an interval of: %i seconds", (time / 60), interval);
ServerPacket* pack = new ServerPacket(ServerOP_ShutdownAll,sizeof(WorldShutDown_Struct));
WorldShutDown_Struct* wsd = (WorldShutDown_Struct*)pack->pBuffer;
wsd->time=time*1000;
@@ -2228,28 +2223,6 @@ void command_dbspawn2(Client *c, const Seperator *sep)
}
}
void command_copychar(Client *c, const Seperator *sep)
{
if(sep->arg[1][0]==0 || sep->arg[2][0] == 0 || sep->arg[3][0] == 0)
c->Message(0, "Usage: #copychar [character name] [new character] [new account id]");
//CheckUsedName.... TRUE=No Char, FALSE=Char/Error
//If there is no source...
else if (database.CheckUsedName((char*)sep->arg[1])) {
c->Message(0, "Source character not found!");
}
else {
//If there is a name is not used....
if (database.CheckUsedName((char*) sep->arg[2])) {
if (!database.CopyCharacter((char*) sep->arg[1], (char*) sep->arg[2], atoi(sep->arg[3])))
c->Message(0, "Character copy operation failed!");
else
c->Message(0, "Character copy complete.");
}
else
c->Message(0, "Target character already exists!");
}
}
void command_shutdown(Client *c, const Seperator *sep)
{
CatchSignal(2);
@@ -2424,8 +2397,8 @@ void command_showskills(Client *c, const Seperator *sep)
c->Message(0, "Skills for %s", t->GetName());
for (SkillUseTypes i=Skill1HBlunt; i <= HIGHEST_SKILL; i=(SkillUseTypes)(i+1))
c->Message(0, "Skill [%d] is at [%d]", i, t->GetSkill(i));
}
c->Message(0, "Skill [%d] is at [%d] - %u", i, t->GetSkill(i), t->GetRawSkill(i));
}
void command_findspell(Client *c, const Seperator *sep)
{
@@ -2492,14 +2465,14 @@ void command_castspell(Client *c, const Seperator *sep)
else
if (c->GetTarget() == 0)
if(c->Admin() >= commandInstacast)
c->SpellFinished(spellid, 0, 10, 0, -1, spells[spellid].ResistDiff);
c->SpellFinished(spellid, 0, USE_ITEM_SPELL_SLOT, 0, -1, spells[spellid].ResistDiff);
else
c->CastSpell(spellid, 0, 10, 0);
c->CastSpell(spellid, 0, USE_ITEM_SPELL_SLOT, 0);
else
if(c->Admin() >= commandInstacast)
c->SpellFinished(spellid, c->GetTarget(), 10, 0, -1, spells[spellid].ResistDiff);
else
c->CastSpell(spellid, c->GetTarget()->GetID(), 10, 0);
c->CastSpell(spellid, c->GetTarget()->GetID(), USE_ITEM_SPELL_SLOT, 0);
}
}
@@ -2791,85 +2764,6 @@ void command_appearance(Client *c, const Seperator *sep)
}
}
void command_charbackup(Client *c, const Seperator *sep)
{
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES* result;
MYSQL_ROW row;
if (strcasecmp(sep->arg[1], "list") == 0) {
uint32 charid = 0;
if (sep->IsNumber(2))
charid = atoi(sep->arg[2]);
else
database.GetAccountIDByChar(sep->arg[2], &charid);
if (charid) {
if (database.RunQuery(query, MakeAnyLenString(&query,
"Select id, backupreason, charid, account_id, zoneid, DATE_FORMAT(ts, '%%m/%%d/%%Y %%H:%%i:%%s') "
" from character_backup where charid=%u", charid), errbuf, &result)) {
safe_delete(query);
uint32 x = 0;
while ((row = mysql_fetch_row(result))) {
c->Message(0, " %u: %s, %s (%u), reason=%u", atoi(row[0]), row[5], database.GetZoneName(atoi(row[4])), atoi(row[4]), atoi(row[1]));
x++;
}
c->Message(0, " %u backups found.", x);
mysql_free_result(result);
}
else {
c->Message(13, "Query error: '%s' %s", query, errbuf);
safe_delete(query);
}
}
else
c->Message(0, "Usage: #charbackup list [char name/id]");
}
else if (strcasecmp(sep->arg[1], "restore") == 0) {
uint32 charid = 0;
if (sep->IsNumber(2))
charid = atoi(sep->arg[2]);
else
database.GetAccountIDByChar(sep->arg[2], &charid);
if (charid && sep->IsNumber(3)) {
uint32 cbid = atoi(sep->arg[3]);
if (database.RunQuery(query, MakeAnyLenString(&query,
"Insert into character_backup (backupreason, charid, account_id, name, profile, level, class, x, y, z, zoneid, alt_adv) "
" select 1, id, account_id, name, profile, level, class, x, y, z, zoneid, alt_adv from character_ where id=%u", charid), errbuf)) {
if (database.RunQuery(query, MakeAnyLenString(&query,
"update character_ inner join character_backup on character_.id = character_backup.charid "
" set character_.name = character_backup.name, "
" character_.profile = character_backup.profile, "
" character_.level = character_backup.level, "
" character_.class = character_backup.class, "
" character_.x = character_backup.x, "
" character_.y = character_backup.y, "
" character_.z = character_backup.z, "
" character_.zoneid = character_backup.zoneid "
" where character_backup.charid=%u and character_backup.id=%u", charid, cbid), errbuf)) {
safe_delete(query);
c->Message(0, "Character restored.");
}
else {
c->Message(13, "Query error: '%s' %s", query, errbuf);
safe_delete(query);
}
}
else {
c->Message(13, "Query error: '%s' %s", query, errbuf);
safe_delete(query);
}
}
else
c->Message(0, "Usage: #charbackup list [char name/id]");
}
else {
c->Message(0, "#charbackup sub-commands:");
c->Message(0, " list [char name/id]");
c->Message(0, " restore [char name/id] [backup#]");
}
}
void command_nukeitem(Client *c, const Seperator *sep)
{
int numitems, itemid;
@@ -5294,53 +5188,6 @@ void command_manaburn(Client *c, const Seperator *sep)
}
}
void command_viewmessage(Client *c, const Seperator *sep)
{
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if(sep->arg[1][0]==0)
{
if (database.RunQuery(query, MakeAnyLenString(&query, "SELECT id,date,receiver,sender,message from tellque where receiver='%s'",c->GetName()), errbuf, &result))
{
if (mysql_num_rows(result)>0)
{
c->Message(0,"You have messages waiting for you to view.");
c->Message(0,"Type #Viewmessage <Message ID> to view the message.");
c->Message(0," ID , Message Sent Date, Message Sender");
while ((row = mysql_fetch_row(result)))
c->Message(0,"ID: %s Sent Date: %s Sender: %s ",row[0],row[1],row[3]);
}
else
c->Message(0,"You have no new messages");
mysql_free_result(result);
}
safe_delete_array(query);
}
else
{
if (database.RunQuery(query, MakeAnyLenString(&query, "SELECT id,date,receiver,sender,message from tellque where id=%s",sep->argplus[1]), errbuf, &result))
{
if (mysql_num_rows(result)==1)
{
row = mysql_fetch_row(result);
mysql_free_result(result);
if (strcasecmp((const char *) c->GetName(), (const char *) row[2]) == 0)
{
c->Message(15,"ID: %s,Sent Date: %s,Sender: %s,Message: %s",row[0],row[1],row[3],row[4]);
database.RunQuery(query, MakeAnyLenString(&query, "Delete from tellque where id=%s",row[0]), errbuf);
}
else
c->Message(13,"Invalid Message Number, check the number and try again.");
}
else
c->Message(13,"Invalid Message Number, check the number and try again.");
}
safe_delete_array(query);
}
}
void command_doanim(Client *c, const Seperator *sep)
{
if (!sep->IsNumber(1))
@@ -6274,13 +6121,13 @@ void command_setcrystals(Client *c, const Seperator *sep)
{
t->SetRadiantCrystals(atoi(sep->arg[2]));
t->SendCrystalCounts();
t->Save();
t->SaveCurrency();
}
else if(!strcasecmp(sep->arg[1], "ebon"))
{
t->SetEbonCrystals(atoi(sep->arg[2]));
t->SendCrystalCounts();
t->Save();
t->SaveCurrency();
}
else
{
@@ -6307,36 +6154,49 @@ void command_stun(Client *c, const Seperator *sep)
c->Message(0, "Usage: #stun [duration]");
}
void command_ban(Client *c, const Seperator *sep)
{
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if(sep->arg[1][0] == 0)
if(sep->arg[1][0] == 0 || sep->arg[2][0] == 0)
{
c->Message(0, "Usage: #ban [charname]");
c->Message(0, "Usage: #ban <charname> <message>");
}
else
{
database.RunQuery(query, MakeAnyLenString(&query, "SELECT account_id from character_ where name = '%s'", sep->arg[1]), errbuf, &result);
if(query)
{
safe_delete_array(query);
auto account_id = database.GetAccountIDByChar(sep->arg[1]);
std::string message;
int i = 2;
while(1) {
if(sep->arg[i][0] == 0) {
break;
}
if(message.length() > 0) {
message.push_back(' ');
}
message += sep->arg[i];
++i;
}
if(mysql_num_rows(result))
{
row = mysql_fetch_row(result);
database.RunQuery(query, MakeAnyLenString(&query, "UPDATE account set status = -2 where id = %i", atoi(row[0])), errbuf, 0);
c->Message(13,"Account number %i with the character %s has been banned.", atoi(row[0]), sep->arg[1]);
if(message.length() == 0) {
c->Message(0, "Usage: #ban <charname> <message>");
return;
}
ServerPacket* pack = new ServerPacket(ServerOP_FlagUpdate, 6);
*((uint32*) pack->pBuffer) = atoi(row[0]);
*((int16*) &pack->pBuffer[4]) = -2;
worldserver.SendPacket(pack);
safe_delete(pack);
if(account_id > 0)
{
database.RunQuery(query, MakeAnyLenString(&query, "UPDATE account set status = -2, ban_reason = '%s' where id = %i", EscapeString(message).c_str(), account_id), errbuf, 0);
c->Message(13, "Account number %i with the character %s has been banned with message: \"%s\"", account_id, sep->arg[1], message.c_str());
ServerPacket pack(ServerOP_FlagUpdate, 6);
*((uint32*)&pack.pBuffer[0]) = account_id;
*((int16*)&pack.pBuffer[4]) = -2;
worldserver.SendPacket(&pack);
Client *client = nullptr;
client = entity_list.GetClientByName(sep->arg[1]);
@@ -6346,25 +6206,20 @@ void command_ban(Client *c, const Seperator *sep)
}
else
{
ServerPacket* pack = new ServerPacket(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct));
ServerKickPlayer_Struct* skp = (ServerKickPlayer_Struct*) pack->pBuffer;
ServerPacket pack(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct));
ServerKickPlayer_Struct* skp = (ServerKickPlayer_Struct*)pack.pBuffer;
strcpy(skp->adminname, c->GetName());
strcpy(skp->name, sep->arg[1]);
skp->adminrank = c->Admin();
worldserver.SendPacket(pack);
safe_delete(pack);
worldserver.SendPacket(&pack);
}
mysql_free_result(result);
}
else
{
c->Message(13,"Character does not exist.");
}
if(query)
{
safe_delete_array(query);
c->Message(13, "Character does not exist.");
}
safe_delete_array(query);
}
}
@@ -6374,7 +6229,7 @@ void command_suspend(Client *c, const Seperator *sep)
char *query = nullptr;
if((sep->arg[1][0] == 0) || (sep->arg[2][0] == 0))
c->Message(0, "Usage: #suspend <charname> <days> (Specify 0 days to lift the suspension immediately)");
c->Message(0, "Usage: #suspend <charname> <days>(Specify 0 days to lift the suspension immediately) <message>");
else
{
int Duration = atoi(sep->arg[2]);
@@ -6382,22 +6237,40 @@ void command_suspend(Client *c, const Seperator *sep)
if(Duration < 0)
Duration = 0;
char *EscName = new char[strlen(sep->arg[1]) * 2 + 1];
std::string message;
if(Duration > 0) {
int i = 3;
while(1) {
if(sep->arg[i][0] == 0) {
break;
}
database.DoEscapeString(EscName, sep->arg[1], strlen(sep->arg[1]));
if(message.length() > 0) {
message.push_back(' ');
}
message += sep->arg[i];
++i;
}
if(message.length() == 0) {
c->Message(0, "Usage: #suspend <charname> <days>(Specify 0 days to lift the suspension immediately) <message>");
return;
}
}
int AccountID;
if((AccountID = database.GetAccountIDByChar(EscName)) > 0)
if((AccountID = database.GetAccountIDByChar(sep->arg[1])) > 0)
{
database.RunQuery(query, MakeAnyLenString(&query, "UPDATE `account` SET `suspendeduntil` = DATE_ADD(NOW(), INTERVAL %i DAY)"
" WHERE `id` = %i", Duration, AccountID), errbuf, 0);
database.RunQuery(query, MakeAnyLenString(&query, "UPDATE `account` SET `suspendeduntil` = DATE_ADD(NOW(), INTERVAL %i DAY), "
"suspend_reason = '%s' WHERE `id` = %i", Duration, EscapeString(message).c_str(), AccountID), errbuf, 0);
if(Duration)
c->Message(13,"Account number %i with the character %s has been temporarily suspended for %i day(s).", AccountID, sep->arg[1],
Duration);
c->Message(13, "Account number %i with the character %s has been temporarily suspended for %i day(s) with the message: \"%s\"", AccountID, sep->arg[1],
Duration, message.c_str());
else
c->Message(13,"Account number %i with the character %s is no longer suspended.", AccountID, sep->arg[1]);
c->Message(13, "Account number %i with the character %s is no longer suspended.", AccountID, sep->arg[1]);
safe_delete_array(query);
@@ -6407,22 +6280,20 @@ void command_suspend(Client *c, const Seperator *sep)
BannedClient->WorldKick();
else
{
ServerPacket* pack = new ServerPacket(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct));
ServerKickPlayer_Struct* sks = (ServerKickPlayer_Struct*) pack->pBuffer;
ServerPacket pack(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct));
ServerKickPlayer_Struct* sks = (ServerKickPlayer_Struct*)pack.pBuffer;
strn0cpy(sks->adminname, c->GetName(), sizeof(sks->adminname));
strn0cpy(sks->name, sep->arg[1], sizeof(sks->name));
sks->adminrank = c->Admin();
worldserver.SendPacket(pack);
safe_delete(pack);
worldserver.SendPacket(&pack);
}
} else
c->Message(13,"Character does not exist.");
safe_delete_array(EscName);
}
else {
c->Message(13, "Character does not exist.");
}
}
}
@@ -8662,25 +8533,6 @@ void command_altactivate(Client *c, const Seperator *sep){
}
}
void command_refundaa(Client *c, const Seperator *sep){
Client* refundee = nullptr;
if(c) {
if(c->GetTarget()){
if(c->GetTarget()->IsClient())
refundee = c->GetTarget()->CastToClient();
else
c->Message(0, "Your target must be a client.");
}
else{
c->Message(0, "You must have a target selected.");
}
if(refundee) {
refundee->RefundAA();
}
}
}
void command_traindisc(Client *c, const Seperator *sep)
{
uint8 max_level, min_level;
@@ -8736,6 +8588,7 @@ void command_traindisc(Client *c, const Seperator *sep)
break; //continue the 1st loop
} else if(t->GetPP().disciplines.values[r] == 0) {
t->GetPP().disciplines.values[r] = curspell;
database.SaveCharacterDisc(c->CharacterID(), r, curspell);
t->SendDisciplineUpdate();
t->Message(0, "You have learned a new discipline!");
count++; //success counter
-3
View File
@@ -125,7 +125,6 @@ void command_worldshutdown(Client *c, const Seperator *sep);
void command_sendzonespawns(Client *c, const Seperator *sep);
void command_zsave(Client *c, const Seperator *sep);
void command_dbspawn2(Client *c, const Seperator *sep);
void command_copychar(Client *c, const Seperator *sep);
void command_shutdown(Client *c, const Seperator *sep);
void command_delacct(Client *c, const Seperator *sep);
void command_setpass(Client *c, const Seperator *sep);
@@ -151,7 +150,6 @@ void command_texture(Client *c, const Seperator *sep);
void command_npctypespawn(Client *c, const Seperator *sep);
void command_heal(Client *c, const Seperator *sep);
void command_appearance(Client *c, const Seperator *sep);
void command_charbackup(Client *c, const Seperator *sep);
void command_nukeitem(Client *c, const Seperator *sep);
void command_peekinv(Client *c, const Seperator *sep);
void command_findnpctype(Client *c, const Seperator *sep);
@@ -217,7 +215,6 @@ void command_guild(Client *c, const Seperator *sep);
bool helper_guild_edit(Client *c, uint32 dbid, uint32 eqid, uint8 rank, const char* what, const char* value);
void command_zonestatus(Client *c, const Seperator *sep);
void command_manaburn(Client *c, const Seperator *sep);
void command_viewmessage(Client *c, const Seperator *sep);
void command_doanim(Client *c, const Seperator *sep);
void command_randomfeatures(Client *c, const Seperator *sep);
void command_face(Client *c, const Seperator *sep);
+4
View File
@@ -17,6 +17,10 @@
#define _NPCPET(x) (x && x->IsNPC() && x->CastToMob()->GetOwner() && x->CastToMob()->GetOwner()->IsNPC())
#define _BECOMENPCPET(x) (x && x->CastToMob()->GetOwner() && x->CastToMob()->GetOwner()->IsClient() && x->CastToMob()->GetOwner()->CastToClient()->IsBecomeNPC())
#define USE_ITEM_SPELL_SLOT 10
#define POTION_BELT_SPELL_SLOT 11
#define DISCIPLINE_SPELL_SLOT 10
#define ABILITY_SPELL_SLOT 9
//LOS Parameters:
#define HEAD_POSITION 0.9f //ratio of GetSize() where NPCs see from
+1 -2
View File
@@ -971,8 +971,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
}
RemoveCash();
Save();
client->Save();
Save();
}
outapp->priority = 6;
+1 -4
View File
@@ -606,6 +606,7 @@ bool Client::TrainDiscipline(uint32 itemid) {
return(false);
} else if(m_pp.disciplines.values[r] == 0) {
m_pp.disciplines.values[r] = spell_id;
database.SaveCharacterDisc(this->CharacterID(), r, spell_id);
SendDisciplineUpdate();
Message(0, "You have learned a new discipline!");
return(true);
@@ -616,13 +617,9 @@ bool Client::TrainDiscipline(uint32 itemid) {
}
void Client::SendDisciplineUpdate() {
//this dosent seem to work right now
EQApplicationPacket app(OP_DisciplineUpdate, sizeof(Disciplines_Struct));
Disciplines_Struct *d = (Disciplines_Struct*)app.pBuffer;
//dunno why I dont just send the one from m_pp
memcpy(d, &m_pp.disciplines, sizeof(m_pp.disciplines));
QueuePacket(&app);
}
+38 -1
View File
@@ -3402,6 +3402,41 @@ XS(XS__qs_player_event)
XSRETURN_EMPTY;
}
XS(XS__crosszonesetentityvariablebynpctypeid);
XS(XS__crosszonesetentityvariablebynpctypeid)
{
dXSARGS;
if (items != 3)
Perl_croak(aTHX_ "Usage: crosszonesetentityvariablebynpctypeid(npctype_id, id, m_var)");
if (items == 3) {
uint32 npctype_id = (uint32)SvIV(ST(0));
const char *id = (const char *)SvPV_nolen(ST(1));
const char *m_var = (const char *)SvPV_nolen(ST(2));
quest_manager.CrossZoneSetEntityVariableByNPCTypeID(npctype_id, id, m_var);
}
XSRETURN_EMPTY;
}
XS(XS__crosszonesignalnpcbynpctypeid);
XS(XS__crosszonesignalnpcbynpctypeid)
{
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: crosszonesignalnpcbynpctypeid(npctype_id, data)");
if (items == 2) {
uint32 npctype_id = (uint32)SvIV(ST(0));
uint32 data = (uint32)SvIV(ST(1));
quest_manager.CrossZoneSignalNPCByNPCTypeID(npctype_id, data);
}
XSRETURN_EMPTY;
}
/*
This is the callback perl will look for to setup the
quest package's XSUBs
@@ -3624,7 +3659,9 @@ EXTERN_C XS(boot_quest)
newXS(strcpy(buf, "disablerecipe"), XS__disablerecipe, file);
newXS(strcpy(buf, "clear_npctype_cache"), XS__clear_npctype_cache, file);
newXS(strcpy(buf, "qs_send_query"), XS__qs_send_query, file);
newXS(strcpy(buf, "qs_player_event"), XS__qs_player_event, file);
newXS(strcpy(buf, "qs_player_event"), XS__qs_player_event, file);
newXS(strcpy(buf, "crosszonesetentityvariablebynpctypeid"), XS__crosszonesetentityvariablebynpctypeid, file);
newXS(strcpy(buf, "crosszonesignalnpcbynpctypeid"), XS__crosszonesignalnpcbynpctypeid, file);
XSRETURN_YES;
}
+1 -4
View File
@@ -40,7 +40,6 @@
#include "../common/spdat.h"
#include "../common/features.h"
#include "string_ids.h"
#include "../common/dbasync.h"
#include "guild_mgr.h"
#include "raids.h"
#include "quest_parser_collection.h"
@@ -57,7 +56,6 @@ extern WorldServer worldserver;
extern NetConnection net;
extern uint32 numclients;
extern PetitionList petition_list;
extern DBAsync *dbasync;
extern char errorname[32];
extern uint16 adverrornum;
@@ -65,12 +63,11 @@ extern uint16 adverrornum;
Entity::Entity()
{
id = 0;
pDBAsyncWorkID = 0;
}
Entity::~Entity()
{
dbasync->CancelWork(pDBAsyncWorkID);
}
Client *Entity::CastToClient()
+1 -3
View File
@@ -28,7 +28,6 @@
#include "zonedb.h"
#include "zonedump.h"
#include "zonedbasync.h"
#include "qglobals.h"
class EQApplicationPacket;
@@ -53,7 +52,7 @@ class Bot;
class BotRaids;
#endif
extern EntityList entity_list;
extern EntityList entity_list;
class Entity
{
@@ -100,7 +99,6 @@ public:
inline const uint16& GetID() const { return id; }
virtual const char* GetName() { return ""; }
virtual void DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) { pDBAsyncWorkID = 0; }
bool CheckCoordLosNoZLeaps(float cur_x, float cur_y, float cur_z, float trg_x, float trg_y, float trg_z, float perwalk=1);
#ifdef BOTS
+1 -8
View File
@@ -51,14 +51,7 @@ static uint32 MaxBankedRaidLeadershipPoints(int Level)
void Client::AddEXP(uint32 in_add_exp, uint8 conlevel, bool resexp) {
/* Set a timestamp in an entity variable for plugin check_handin.pl in return_items
This will stopgap players from items being returned if global_npc.pl has a catch all return_items
*/
struct timeval read_time;
char buffer[50];
gettimeofday(&read_time, 0);
sprintf(buffer, "%li.%li \n", read_time.tv_sec, read_time.tv_usec);
this->SetEntityVariable("Stop_Return", buffer);
this->EVENT_ITEM_ScriptStopReturn();
uint32 add_exp = in_add_exp;
-53
View File
@@ -24,59 +24,6 @@
#include "client.h"
#include "entity.h"
/*
CREATE TABLE guilds (
id MEDIUMINT UNSIGNED NOT NULL,
name VARCHAR(32) NOT NULL,
leader int NOT NULL,
minstatus SMALLINT NOT NULL,
tribute INT UNSIGNED NOT NULL,
motd TEXT NOT NULL DEFAULT '',
PRIMARY KEY(id),
UNIQUE KEY(name),
UNIQUE KEY(leader)
);
CREATE TABLE guild_ranks (
guild_id MEDIUMINT UNSIGNED NOT NULL,
rank TINYINT UNSIGNED NOT NULL,
title VARCHAR(128) NOT NULL,
can_hear TINYINT UNSIGNED NOT NULL,
can_speak TINYINT UNSIGNED NOT NULL,
can_invite TINYINT UNSIGNED NOT NULL,
can_remove TINYINT UNSIGNED NOT NULL,
can_promote TINYINT UNSIGNED NOT NULL,
can_demote TINYINT UNSIGNED NOT NULL,
can_motd TINYINT UNSIGNED NOT NULL,
can_warpeace TINYINT UNSIGNED NOT NULL,
PRIMARY KEY(guild_id,rank)
);
# guild1 < guild2 by definition.
CREATE TABLE guild_relations (
guild1 MEDIUMINT UNSIGNED NOT NULL,
guild2 MEDIUMINT UNSIGNED NOT NULL,
relation TINYINT NOT NULL,
PRIMARY KEY(guild1, guild1)
);
CREATE TABLE guild_members (
char_id INT NOT NULL,
guild_id MEDIUMINT UNSIGNED NOT NULL,
rank TINYINT UNSIGNED NOT NULL,
tribute_enable TINYINT UNSIGNED NOT NULL DEFAULT 0,
total_tribute INT UNSIGNED NOT NULL DEFAULT 0,
last_tribute INT UNSIGNED NOT NULL DEFAULT 0,
banker TINYINT UNSIGNED NOT NULL DEFAULT 0,
public_note TEXT NOT NULL DEFAULT '',
PRIMARY KEY(char_id)
);
*/
ZoneGuildManager guild_mgr;
GuildBankManager *GuildBanks;
+10 -20
View File
@@ -200,14 +200,7 @@ bool Client::CheckLoreConflict(const Item_Struct* item) {
}
bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, bool attuned, uint16 to_slot) {
/* Set a timestamp in an entity variable for plugin check_handin.pl in return_items
This will stopgap players from items being returned if global_npc.pl has a catch all return_items
*/
struct timeval read_time;
char buffer[50];
gettimeofday(&read_time, 0);
sprintf(buffer, "%li.%li \n", read_time.tv_sec, read_time.tv_usec);
this->SetEntityVariable("Recieved_Item", buffer);
this->EVENT_ITEM_ScriptStopReturn();
// TODO: update calling methods and script apis to handle a failure return
@@ -1877,7 +1870,9 @@ void Client::DyeArmor(DyeStruct* dye){
uint8 slot2=SlotConvert(i);
ItemInst* inst = this->m_inv.GetItem(slot2);
if(inst){
inst->SetColor((dye->dye[i].rgb.red*65536)+(dye->dye[i].rgb.green*256)+(dye->dye[i].rgb.blue));
uint32 armor_color = (dye->dye[i].rgb.red * 65536) + (dye->dye[i].rgb.green * 256) + (dye->dye[i].rgb.blue);
inst->SetColor(armor_color);
database.SaveCharacterMaterialColor(this->CharacterID(), i, armor_color);
database.SaveInventory(CharacterID(),inst,slot2);
if(dye->dye[i].rgb.use_tint)
m_pp.item_tint[i].rgb.use_tint = 0xFF;
@@ -1898,7 +1893,7 @@ void Client::DyeArmor(DyeStruct* dye){
EQApplicationPacket* outapp=new EQApplicationPacket(OP_Dye,0);
QueuePacket(outapp);
safe_delete(outapp);
Save();
}
/*bool Client::DecreaseByItemType(uint32 type, uint8 amt) {
@@ -2417,10 +2412,8 @@ void Client::CreateBandolier(const EQApplicationPacket *app) {
_log(INVENTORY__BANDOLIER, "Char: %s Creating Bandolier Set %i, Set Name: %s", GetName(), bs->number, bs->name);
strcpy(m_pp.bandoliers[bs->number].name, bs->name);
const ItemInst* InvItem;
const Item_Struct *BaseItem;
const ItemInst* InvItem;
const Item_Struct *BaseItem;
int16 WeaponSlot;
for(int BandolierSlot = bandolierMainHand; BandolierSlot <= bandolierAmmo; BandolierSlot++) {
@@ -2431,6 +2424,7 @@ void Client::CreateBandolier(const EQApplicationPacket *app) {
_log(INVENTORY__BANDOLIER, "Char: %s adding item %s to slot %i", GetName(),BaseItem->Name, WeaponSlot);
m_pp.bandoliers[bs->number].items[BandolierSlot].item_id = BaseItem->ID;
m_pp.bandoliers[bs->number].items[BandolierSlot].icon = BaseItem->Icon;
database.SaveCharacterBandolier(this->CharacterID(), bs->number, BandolierSlot, m_pp.bandoliers[bs->number].items[BandolierSlot].item_id, m_pp.bandoliers[bs->number].items[BandolierSlot].icon, bs->name);
}
else {
_log(INVENTORY__BANDOLIER, "Char: %s no item in slot %i", GetName(), WeaponSlot);
@@ -2438,21 +2432,17 @@ void Client::CreateBandolier(const EQApplicationPacket *app) {
m_pp.bandoliers[bs->number].items[BandolierSlot].icon = 0;
}
}
Save();
}
void Client::RemoveBandolier(const EQApplicationPacket *app) {
// Delete bandolier with the specified number
BandolierDelete_Struct *bds = (BandolierDelete_Struct*)app->pBuffer;
_log(INVENTORY__BANDOLIER, "Char: %s removing set", GetName(), bds->number);
memset(m_pp.bandoliers[bds->number].name, 0, 32);
for(int i = bandolierMainHand; i <= bandolierAmmo; i++) {
m_pp.bandoliers[bds->number].items[i].item_id = 0;
m_pp.bandoliers[bds->number].items[i].icon = 0;
m_pp.bandoliers[bds->number].items[i].icon = 0;
}
Save();
database.DeleteCharacterBandolier(this->CharacterID(), bds->number);
}
void Client::SetBandolier(const EQApplicationPacket *app) {
+1
View File
@@ -1932,6 +1932,7 @@ void Mob::SetZone(uint32 zone_id, uint32 instance_id)
{
CastToClient()->GetPP().zone_id = zone_id;
CastToClient()->GetPP().zoneInstance = instance_id;
CastToClient()->Save();
}
Save();
}
+1 -1
View File
@@ -205,7 +205,7 @@ public:
void SendSpellBarEnable(uint16 spellid);
void ZeroCastingVars();
virtual void SpellProcess();
virtual bool CastSpell(uint16 spell_id, uint16 target_id, uint16 slot = 10, int32 casttime = -1,
virtual bool CastSpell(uint16 spell_id, uint16 target_id, uint16 slot = USE_ITEM_SPELL_SLOT, int32 casttime = -1,
int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF,
uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, uint32 type = 0, int16 *resist_adjust = nullptr);
virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot = 10, int32 casttime = -1,
-10
View File
@@ -97,8 +97,6 @@ extern Zone* zone;
EQStreamFactory eqsf(ZoneStream);
npcDecayTimes_Struct npcCorpseDecayTimes[100];
TitleManager title_manager;
DBAsyncFinishedQueue MTdbafq;
DBAsync *dbasync = nullptr;
QueryServ *QServ = 0;
TaskManager *taskmanager = 0;
QuestParserCollection *parse = 0;
@@ -168,8 +166,6 @@ int main(int argc, char** argv) {
_log(ZONE__INIT_ERR, "Cannot continue without a database connection.");
return 1;
}
dbasync = new DBAsync(&database);
dbasync->AddFQ(&MTdbafq);
guild_mgr.SetDatabase(&database);
GuildBanks = nullptr;
@@ -444,10 +440,6 @@ int main(int argc, char** argv) {
}
}
DBAsyncWork* dbaw = 0;
while ((dbaw = MTdbafq.Pop())) {
DispatchFinishedDBAsync(dbaw);
}
if (InterserverTimer.Check()) {
InterserverTimer.Start();
database.ping();
@@ -507,8 +499,6 @@ int main(int argc, char** argv) {
//Fix for Linux world server problem.
eqsf.Close();
worldserver.Disconnect();
dbasync->CommitWrites();
dbasync->StopThread();
safe_delete(taskmanager);
command_deinit();
safe_delete(parse);
+30
View File
@@ -5072,6 +5072,35 @@ XS(XS_Client_UpdateTaskActivity)
XSRETURN_EMPTY;
}
XS(XS_Client_GetTaskActivityDoneCount); /* prototype to pass -Wmissing-prototypes */
XS(XS_Client_GetTaskActivityDoneCount)
{
dXSARGS;
if (items != 3)
Perl_croak(aTHX_ "Usage: Client::GetTaskActivityDoneCount(THIS, TaskID, ActivityID)");
{
Client * THIS;
int RETVAL;
int TaskID = (int)SvIV(ST(1));
int ActivityID = (int)SvIV(ST(2));
dXSTARG;
if (sv_derived_from(ST(0), "Client")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(Client *, tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type Client");
if (THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetTaskActivityDoneCountFromTaskID(TaskID, ActivityID);
XSprePUSH; PUSHi((IV)RETVAL);
}
XSRETURN(1);
}
XS(XS_Client_AssignTask); /* prototype to pass -Wmissing-prototypes */
XS(XS_Client_AssignTask)
{
@@ -6199,6 +6228,7 @@ XS(boot_Client)
newXSproto(strcpy(buf, "IsTaskCompleted"), XS_Client_IsTaskCompleted, file, "$$");
newXSproto(strcpy(buf, "IsTaskActive"), XS_Client_IsTaskActive, file, "$$");
newXSproto(strcpy(buf, "IsTaskActivityActive"), XS_Client_IsTaskActivityActive, file, "$$$");
newXSproto(strcpy(buf, "GetTaskActivityDoneCount"), XS_Client_GetTaskActivityDoneCount, file, "$$$");
newXSproto(strcpy(buf, "GetCorpseCount"), XS_Client_GetCorpseCount, file, "$");
newXSproto(strcpy(buf, "GetCorpseID"), XS_Client_GetCorpseID, file, "$$");
newXSproto(strcpy(buf, "GetCorpseItemAt"), XS_Client_GetCorpseItemAt, file, "$$$");
+32 -9
View File
@@ -946,7 +946,7 @@ uint16 QuestManager::traindiscs(uint8 max_level, uint8 min_level) {
uint16 count;
uint16 curspell;
uint16 Char_ID = initiator->CharacterID();
uint32 Char_ID = initiator->CharacterID();
bool SpellGlobalRule = RuleB(Spells, EnableSpellGlobals);
bool SpellGlobalCheckResult = 0;
@@ -960,7 +960,7 @@ uint16 QuestManager::traindiscs(uint8 max_level, uint8 min_level) {
spells[curspell].skill != 52 &&
( !RuleB(Spells, UseCHAScribeHack) || spells[curspell].effectid[EFFECT_COUNT - 1] != 10 )
)
{
{
if(IsDiscipline(curspell)){
//we may want to come up with a function like Client::GetNextAvailableSpellBookSlot() to help speed this up a little
for(uint32 r = 0; r < MAX_PP_DISCIPLINES; r++) {
@@ -974,18 +974,20 @@ uint16 QuestManager::traindiscs(uint8 max_level, uint8 min_level) {
SpellGlobalCheckResult = initiator->SpellGlobalCheck(curspell, Char_ID);
if (SpellGlobalCheckResult) {
initiator->GetPP().disciplines.values[r] = curspell;
database.SaveCharacterDisc(Char_ID, r, curspell);
initiator->SendDisciplineUpdate();
initiator->Message(0, "You have learned a new discipline!");
count++; //success counter
}
break; //continue the 1st loop
break; //continue the 1st loop
}
else {
initiator->GetPP().disciplines.values[r] = curspell;
initiator->SendDisciplineUpdate();
initiator->Message(0, "You have learned a new discipline!");
count++; //success counter
break; //continue the 1st loop
initiator->GetPP().disciplines.values[r] = curspell;
database.SaveCharacterDisc(Char_ID, r, curspell);
initiator->SendDisciplineUpdate();
initiator->Message(0, "You have learned a new discipline!");
count++; //success counter
break; //continue the 1st loop
}
} //if we get to this point, there's already a discipline in this slot, so we skip it
}
@@ -2949,6 +2951,15 @@ const char* QuestManager::GetZoneLongName(const char *zone) {
return ln.c_str();
}
void QuestManager::CrossZoneSignalNPCByNPCTypeID(uint32 npctype_id, uint32 data){
ServerPacket* pack = new ServerPacket(ServerOP_CZSignalNPC, sizeof(CZNPCSignal_Struct));
CZNPCSignal_Struct* CZSN = (CZNPCSignal_Struct*)pack->pBuffer;
CZSN->npctype_id = npctype_id;
CZSN->data = data;
worldserver.SendPacket(pack);
safe_delete(pack);
}
void QuestManager::CrossZoneSignalPlayerByCharID(int charid, uint32 data){
ServerPacket* pack = new ServerPacket(ServerOP_CZSignalClient, sizeof(CZClientSignal_Struct));
CZClientSignal_Struct* CZSC = (CZClientSignal_Struct*) pack->pBuffer;
@@ -2966,7 +2977,7 @@ void QuestManager::CrossZoneSignalPlayerByName(const char *CharName, uint32 data
CZSC->data = data;
worldserver.SendPacket(pack);
safe_delete(pack);
}
}
void QuestManager::CrossZoneMessagePlayerByName(uint32 Type, const char *CharName, const char *Message){
uint32 message_len = strlen(CharName) + 1;
@@ -2976,6 +2987,18 @@ void QuestManager::CrossZoneMessagePlayerByName(uint32 Type, const char *CharNam
CZSC->Type = Type;
strn0cpy(CZSC->CharName, CharName, 64);
strn0cpy(CZSC->Message, Message, 512);
worldserver.SendPacket(pack);
safe_delete(pack);
}
void QuestManager::CrossZoneSetEntityVariableByNPCTypeID(uint32 npctype_id, const char *id, const char *m_var){
uint32 message_len = strlen(id) + 1;
uint32 message_len2 = strlen(m_var) + 1;
ServerPacket* pack = new ServerPacket(ServerOP_CZSetEntityVariableByNPCTypeID, sizeof(CZSetEntVarByNPCTypeID_Struct) + message_len + message_len2);
CZSetEntVarByNPCTypeID_Struct* CZSNBYNID = (CZSetEntVarByNPCTypeID_Struct*)pack->pBuffer;
CZSNBYNID->npctype_id = npctype_id;
strn0cpy(CZSNBYNID->id, id, 256);
strn0cpy(CZSNBYNID->m_var, m_var, 256);
worldserver.SendPacket(pack);
safe_delete(pack);
}
+3 -1
View File
@@ -239,8 +239,10 @@ public:
uint16 CreateDoor( const char* model, float x, float y, float z, float heading, uint8 opentype, uint16 size);
int32 GetZoneID(const char *zone);
const char *GetZoneLongName(const char *zone);
void CrossZoneSignalPlayerByCharID(int charid, uint32 data);
void CrossZoneSignalPlayerByCharID(int charid, uint32 data);
void CrossZoneSignalNPCByNPCTypeID(uint32 npctype_id, uint32 data);
void CrossZoneSignalPlayerByName(const char *CharName, uint32 data);
void CrossZoneSetEntityVariableByNPCTypeID(uint32 npctype_id, const char *id, const char *m_var);
void CrossZoneMessagePlayerByName(uint32 Type, const char *CharName, const char *Message);
bool EnableRecipe(uint32 recipe_id);
bool DisableRecipe(uint32 recipe_id);
+16 -15
View File
@@ -5598,28 +5598,29 @@ void Mob::CheckNumHitsRemaining(uint8 type, uint32 buff_slot, uint16 spell_id)
}
//for some stupid reason SK procs return theirs one base off...
uint16 Mob::GetProcID(uint16 spell_id, uint8 effect_index) {
uint16 Mob::GetProcID(uint16 spell_id, uint8 effect_index)
{
if (!RuleB(Spells, SHDProcIDOffByOne)) // UF+ spell files
return spells[spell_id].base[effect_index];
// We should actually just be checking if the mob is SHD, but to not force
// custom servers to create new spells, we will still do this
bool sk = false;
bool other = false;
for(int x = 0; x < 16; x++)
{
if(x == 4){
if(spells[spell_id].classes[4] < 255)
for (int x = 0; x < 16; x++) {
if (x == 4) {
if (spells[spell_id].classes[4] < 255)
sk = true;
}
else{
if(spells[spell_id].classes[x] < 255)
} else {
if (spells[spell_id].classes[x] < 255)
other = true;
}
}
if(sk && !other)
{
return(spells[spell_id].base[effect_index] + 1);
}
else{
return(spells[spell_id].base[effect_index]);
}
if (sk && !other)
return spells[spell_id].base[effect_index] + 1;
else
return spells[spell_id].base[effect_index];
}
bool Mob::TryDivineSave()
+9 -2
View File
@@ -4841,6 +4841,8 @@ void Client::MemSpell(uint16 spell_id, int slot, bool update_client)
m_pp.mem_spells[slot] = spell_id;
mlog(CLIENT__SPELLS, "Spell %d memorized into slot %d", spell_id, slot);
database.SaveCharacterMemorizedSpell(this->CharacterID(), m_pp.mem_spells[slot], slot);
if(update_client)
{
MemorizeSpell(slot, spell_id, memSpellMemorize);
@@ -4855,6 +4857,8 @@ void Client::UnmemSpell(int slot, bool update_client)
mlog(CLIENT__SPELLS, "Spell %d forgotten from slot %d", m_pp.mem_spells[slot], slot);
m_pp.mem_spells[slot] = 0xFFFFFFFF;
database.DeleteCharacterMemorizedSpell(this->CharacterID(), m_pp.mem_spells[slot], slot);
if(update_client)
{
MemorizeSpell(slot, m_pp.mem_spells[slot], memSpellForget);
@@ -4882,6 +4886,7 @@ void Client::ScribeSpell(uint16 spell_id, int slot, bool update_client)
}
m_pp.spell_book[slot] = spell_id;
database.SaveCharacterSpell(this->CharacterID(), spell_id, slot);
mlog(CLIENT__SPELLS, "Spell %d scribed into spell book slot %d", spell_id, slot);
if(update_client)
@@ -4897,7 +4902,8 @@ void Client::UnscribeSpell(int slot, bool update_client)
mlog(CLIENT__SPELLS, "Spell %d erased from spell book slot %d", m_pp.spell_book[slot], slot);
m_pp.spell_book[slot] = 0xFFFFFFFF;
database.DeleteCharacterSpell(this->CharacterID(), m_pp.spell_book[slot], slot);
if(update_client)
{
EQApplicationPacket* outapp = new EQApplicationPacket(OP_DeleteSpell, sizeof(DeleteSpell_Struct));
@@ -4925,8 +4931,9 @@ void Client::UntrainDisc(int slot, bool update_client)
if(slot >= MAX_PP_DISCIPLINES || slot < 0)
return;
mlog(CLIENT__SPELLS, "Discipline %d untrained from slot %d", m_pp.disciplines.values[slot], slot);
mlog(CLIENT__SPELLS, "Discipline %d untrained from slot %d", m_pp.disciplines.values[slot], slot);
m_pp.disciplines.values[slot] = 0;
database.DeleteCharacterDisc(this->CharacterID(), slot);
if(update_client)
{
+4
View File
@@ -249,6 +249,8 @@
#define PLAYER_CHARMED 1461 //You lose control of yourself!
#define TRADER_BUSY 1468 //That Trader is currently with a customer. Please wait until their transaction is finished.
#define SENSE_CORPSE_DIRECTION 1563 //You sense a corpse in this direction.
#define QUEUED_TELL 2458 //[queued]
#define QUEUE_TELL_FULL 2459 //[zoing and queue is full]
#define SUSPEND_MINION_UNSUSPEND 3267 //%1 tells you, 'I live again...'
#define SUSPEND_MINION_SUSPEND 3268 //%1 tells you, 'By your command, master.'
#define ONLY_SUMMONED_PETS 3269 //3269 This effect only works with summoned pets.
@@ -269,6 +271,8 @@
#define CORPSEDRAG_STOP 4066 //You stop dragging the corpse.
#define TARGET_TOO_CLOSE 4602 //You are too close to your target. Get farther away.
#define WHOALL_NO_RESULTS 5029 //There are no players in EverQuest that match those who filters.
#define TELL_QUEUED_MESSAGE 5045 //You told %1 '%T2. %3'
#define TOLD_NOT_ONLINE 5046 //%1 is not online at this time.
#define PETITION_NO_DELETE 5053 //You do not have a petition in the queue.
#define PETITION_DELETED 5054 //Your petition was successfully deleted.
#define GAIN_RAIDEXP 5085 //You gained raid experience!
+2 -9
View File
@@ -913,14 +913,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st
if(!tradingWith->IsMoving())
tradingWith->FaceTarget(this);
/* Set a timestamp in an entity variable for plugin check_handin.pl in return_items
This will stopgap players from items being returned if global_npc.pl has a catch all return_items
*/
struct timeval read_time;
char buffer[50];
gettimeofday(&read_time, 0);
sprintf(buffer, "%li.%li \n", read_time.tv_sec, read_time.tv_usec);
this->SetEntityVariable("Stop_Return", buffer);
this->EVENT_ITEM_ScriptStopReturn();
}
}
@@ -938,7 +931,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st
parse->AddVar(temp1, temp2);
snprintf(temp1, 100, "platinum.%d", tradingWith->GetNPCTypeID());
snprintf(temp2, 100, "%u", trade->pp);
parse->AddVar(temp1, temp2);
parse->AddVar(temp1, temp2);
if(tradingWith->GetAppearance() != eaDead) {
tradingWith->FaceTarget(this);
+6 -4
View File
@@ -254,8 +254,10 @@ int32 Client::TributeItem(uint32 slot, uint32 quantity) {
return(0);
}
//make sure they have enough of them
//and remove it from inventory
/*
Make sure they have enough of them
and remove it from inventory
*/
if(inst->IsStackable()) {
if(inst->GetCharges() < (int32)quantity) //dont have enough....
return(0);
@@ -267,7 +269,7 @@ int32 Client::TributeItem(uint32 slot, uint32 quantity) {
pts *= quantity;
//add the tribute value in points
/* Add the tribute value in points */
AddTributePoints(pts);
return(pts);
}
@@ -279,7 +281,7 @@ int32 Client::TributeMoney(uint32 platinum) {
return(0);
}
//add the tribute value in points
/* Add the tribute value in points */
AddTributePoints(platinum);
return(platinum);
}
+50 -9
View File
@@ -168,18 +168,24 @@ void WorldServer::Process() {
break;
}
case ServerOP_ChannelMessage: {
if (!ZoneLoaded) break;
if (!ZoneLoaded)
break;
ServerChannelMessage_Struct* scm = (ServerChannelMessage_Struct*) pack->pBuffer;
if (scm->deliverto[0] == 0) {
entity_list.ChannelMessageFromWorld(scm->from, scm->to, scm->chan_num, scm->guilddbid, scm->language, scm->message);
}
else {
Client* client;
client = entity_list.GetClientByName(scm->deliverto);
if (client != 0) {
} else {
Client* client = entity_list.GetClientByName(scm->deliverto);
if (client) {
if (client->Connected()) {
client->ChannelMessageSend(scm->from, scm->to, scm->chan_num, scm->language, scm->message);
if (!scm->noreply && scm->chan_num!=2) { //dont echo on group chat
if (scm->queued == 1) // tell was queued
client->Tell_StringID(QUEUED_TELL, scm->to, scm->message);
else if (scm->queued == 2) // tell queue was full
client->Tell_StringID(QUEUE_TELL_FULL, scm->to, scm->message);
else if (scm->queued == 3) // person was offline
client->Message_StringID(MT_TellEcho, TOLD_NOT_ONLINE, scm->to);
else // normal stuff
client->ChannelMessageSend(scm->from, scm->to, scm->chan_num, scm->language, scm->message);
if (!scm->noreply && scm->chan_num != 2) { //dont echo on group chat
// if it's a tell, echo back so it shows up
scm->noreply = true;
scm->chan_num = 14;
@@ -322,7 +328,7 @@ void WorldServer::Process() {
entity->CastToMob()->SetZone(ztz->requested_zone_id, ztz->requested_instance_id);
if(ztz->ignorerestrictions == 3)
if(ztz->ignorerestrictions == 3)
entity->CastToClient()->GoToSafeCoords(ztz->requested_zone_id, ztz->requested_instance_id);
}
@@ -1777,6 +1783,24 @@ void WorldServer::Process() {
break;
}
case ServerOP_CZSetEntityVariableByNPCTypeID:
{
CZSetEntVarByNPCTypeID_Struct* CZM = (CZSetEntVarByNPCTypeID_Struct*)pack->pBuffer;
NPC* n = entity_list.GetNPCByNPCTypeID(CZM->npctype_id);
if (n != 0) {
n->SetEntityVariable(CZM->id, CZM->m_var);
}
break;
}
case ServerOP_CZSignalNPC:
{
CZNPCSignal_Struct* CZCN = (CZNPCSignal_Struct*)pack->pBuffer;
NPC* n = entity_list.GetNPCByNPCTypeID(CZCN->npctype_id);
if (n != 0) {
n->SignalNPC(CZCN->data);
}
break;
}
case ServerOP_CZSignalClient:
{
CZClientSignal_Struct* CZCS = (CZClientSignal_Struct*) pack->pBuffer;
@@ -1856,6 +1880,7 @@ bool WorldServer::SendChannelMessage(Client* from, const char* to, uint8 chan_nu
scm->chan_num = chan_num;
scm->guilddbid = guilddbid;
scm->language = language;
scm->queued = 0;
strcpy(scm->message, buffer);
pack->Deflate();
@@ -2180,3 +2205,19 @@ void WorldServer::HandleLFPMatches(ServerPacket *pack) {
safe_delete(outapp);
}
}
void WorldServer::RequestTellQueue(const char *who)
{
if (!who)
return;
ServerPacket* pack = new ServerPacket(ServerOP_RequestTellQueue, sizeof(ServerRequestTellQueue_Struct));
ServerRequestTellQueue_Struct* rtq = (ServerRequestTellQueue_Struct*) pack->pBuffer;
strn0cpy(rtq->name, who, sizeof(rtq->name));
SendPacket(pack);
safe_delete(pack);
return;
}
+2
View File
@@ -57,6 +57,8 @@ public:
void HandleLFGMatches(ServerPacket *pack);
void HandleLFPMatches(ServerPacket *pack);
void RequestTellQueue(const char *who);
private:
virtual void OnConnected();
+51 -120
View File
@@ -77,8 +77,6 @@ extern bool staticzone;
Zone* zone = 0;
volatile bool ZoneLoaded = false;
extern QuestParserCollection* parse;
extern DBAsyncFinishedQueue MTdbafq;
extern DBAsync *dbasync;
bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) {
const char* zonename = database.GetZoneName(iZoneID);
@@ -105,7 +103,7 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) {
}
zone->zonemap = Map::LoadMapFile(zone->map_name);
zone->watermap = WaterMap::LoadWaterMapfile(zone->map_name);
zone->pathing = PathManager::LoadPathFile(zone->map_name);
zone->pathing = PathManager::LoadPathFile(zone->map_name);
char tmp[10];
if (database.GetVariable("loglevel",tmp, 9)) {
@@ -401,40 +399,33 @@ uint32 Zone::GetTempMerchantQuantity(uint32 NPCID, uint32 Slot) {
void Zone::LoadTempMerchantData(){
LogFile->write(EQEMuLog::Status, "Loading Temporary Merchant Lists...");
char* query = 0;
uint32_breakdown workpt;
workpt.b4() = DBA_b4_Zone;
workpt.w2_3() = 0;
workpt.b1() = DBA_b1_Zone_MerchantListsTemp;
DBAsyncWork* dbaw = new DBAsyncWork(&database, &MTdbafq, workpt, DBAsync::Read);
dbaw->AddQuery(1, &query, MakeAnyLenString(&query,
"select ml.npcid,ml.slot,ml.itemid,ml.charges "
"from "
" merchantlist_temp ml, "
" spawnentry se, "
" spawn2 s2 "
"where "
" ml.npcid=se.npcid "
" and se.spawngroupid=s2.spawngroupid "
" and s2.zone='%s' and s2.version=%u", GetShortName(), GetInstanceVersion()));
if (!(pQueuedMerchantsWorkID = dbasync->AddWork(&dbaw))) {
safe_delete(dbaw);
LogFile->write(EQEMuLog::Error, "dbasync->AddWork() failed adding merchant list query");
std::string query = StringFormat(
"SELECT "
"ml.npcid, "
"ml.slot, "
"ml.charges, "
"ml.itemid "
"FROM "
"merchantlist_temp ml, "
"spawnentry se, "
"spawn2 s2 "
"WHERE "
"ml.npcid = se.npcid "
"AND se.spawngroupid = s2.spawngroupid "
"AND s2.zone = '%s' AND s2.version = %i", GetShortName(), GetInstanceVersion());
auto results = database.QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in LoadTempMerchantData query '%s' %s", query.c_str(), results.ErrorMessage().c_str());
return;
}
}
void Zone::LoadTempMerchantData_result(MYSQL_RES* result) {
MYSQL_ROW row;
std::map<uint32,std::list<TempMerchantList> >::iterator cur;
std::map<uint32, std::list<TempMerchantList> >::iterator cur;
uint32 npcid = 0;
while((row = mysql_fetch_row(result))) {
for (auto row = results.begin(); row != results.end(); ++row) {
TempMerchantList ml;
ml.npcid = atoul(row[0]);
if(npcid != ml.npcid){
if (npcid != ml.npcid){
cur = tmpmerchanttable.find(ml.npcid);
if(cur == tmpmerchanttable.end()) {
if (cur == tmpmerchanttable.end()) {
std::list<TempMerchantList> empty;
tmpmerchanttable[ml.npcid] = empty;
cur = tmpmerchanttable.find(ml.npcid);
@@ -447,9 +438,9 @@ void Zone::LoadTempMerchantData_result(MYSQL_RES* result) {
ml.origslot = ml.slot;
cur->second.push_back(ml);
}
pQueuedMerchantsWorkID = 0;
}
//there should prolly be a temp counterpart of this...
void Zone::LoadNewMerchantData(uint32 merchantid){
std::list<MerchantList> merlist;
@@ -476,16 +467,35 @@ void Zone::LoadNewMerchantData(uint32 merchantid){
merchanttable[merchantid] = merlist;
}
void Zone::LoadMerchantData_result(MYSQL_RES* result) {
MYSQL_ROW row;
std::map<uint32,std::list<MerchantList> >::iterator cur;
void Zone::GetMerchantDataForZoneLoad(){
LogFile->write(EQEMuLog::Status, "Loading Merchant Lists...");
std::string query = StringFormat(
"SELECT "
"ml.merchantid, "
"ml.slot, "
"ml.item, "
"ml.faction_required, "
"ml.level_required, "
"ml.alt_currency_cost, "
"ml.classes_required, "
"ml.probability "
"FROM "
"merchantlist AS ml, "
"npc_types AS nt, "
"spawnentry AS se, "
"spawn2 AS s2 "
"WHERE nt.merchant_id = ml.merchantid AND nt.id = se.npcid "
"AND se.spawngroupid = s2.spawngroupid AND s2.zone = '%s' AND s2.version = %i ", GetShortName(), GetInstanceVersion());
auto results = database.QueryDatabase(query);
std::map<uint32, std::list<MerchantList> >::iterator cur;
uint32 npcid = 0;
while((row = mysql_fetch_row(result))) {
if (results.RowCount() == 0){ LogFile->write(EQEMuLog::Error, "Error in loading Merchant Data for zone"); return; }
for (auto row = results.begin(); row != results.end(); ++row) {
MerchantList ml;
ml.id = atoul(row[0]);
if(npcid != ml.id){
if (npcid != ml.id){
cur = merchanttable.find(ml.id);
if(cur == merchanttable.end()) {
if (cur == merchanttable.end()) {
std::list<MerchantList> empty;
merchanttable[ml.id] = empty;
cur = merchanttable.find(ml.id);
@@ -495,15 +505,15 @@ void Zone::LoadMerchantData_result(MYSQL_RES* result) {
std::list<MerchantList>::iterator iter = cur->second.begin();
bool found = false;
while(iter != cur->second.end()) {
if((*iter).item == ml.id) {
while (iter != cur->second.end()) {
if ((*iter).item == ml.id) {
found = true;
break;
}
++iter;
}
if(found) {
if (found) {
continue;
}
@@ -516,28 +526,7 @@ void Zone::LoadMerchantData_result(MYSQL_RES* result) {
ml.probability = atoul(row[7]);
cur->second.push_back(ml);
}
}
void Zone::GetMerchantDataForZoneLoad(){
LogFile->write(EQEMuLog::Status, "Loading Merchant Lists...");
char* query = 0;
uint32_breakdown workpt;
workpt.b4() = DBA_b4_Zone;
workpt.w2_3() = 0;
workpt.b1() = DBA_b1_Zone_MerchantLists;
DBAsyncWork* dbaw = new DBAsyncWork(&database, &MTdbafq, workpt, DBAsync::Read);
dbaw->AddQuery(1, &query, MakeAnyLenString(&query,
"select ml.merchantid,ml.slot,ml.item,ml.faction_required,ml.level_required,ml.alt_currency_cost,ml.classes_required,ml.probability "
"from merchantlist ml, npc_types nt, spawnentry se, spawn2 s2 "
"where nt.merchant_id=ml.merchantid and nt.id=se.npcid "
"and se.spawngroupid=s2.spawngroupid and s2.zone='%s' and s2.version=%u "
//"group by ml.merchantid,slot order by merchantid,slot asc" //this made the query use a temp table/filesort (very slow)... so we handle unsorted data on our end.
, GetShortName(), GetInstanceVersion()));
if (!(pQueuedMerchantsWorkID = dbasync->AddWork(&dbaw))) {
safe_delete(dbaw);
LogFile->write(EQEMuLog::Error,"dbasync->AddWork() failed adding merchant list query");
return;
}
}
void Zone::LoadMercTemplates(){
@@ -665,61 +654,6 @@ void Zone::LoadMercSpells(){
}
void Zone::DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) {
// LogFile->write(EQEMuLog::Debug, "Zone work complete...");
switch (workpt_b1) {
case DBA_b1_Zone_MerchantLists: {
char errbuf[MYSQL_ERRMSG_SIZE];
MYSQL_RES* result = 0;
DBAsyncQuery* dbaq = dbaw->PopAnswer();
if(dbaq == nullptr) {
LogFile->write(EQEMuLog::Error, "nullptr answer provided for async merchant list load.");
break;
}
if(!dbaq->GetAnswer(errbuf, &result)) {
LogFile->write(EQEMuLog::Error, "Zone::DBAWComplete(): Unable to get results for merchant lists");
break;
}
if(dbaq->QPT() != 1) {
LogFile->write(EQEMuLog::Error, "Zone::DBAWComplete(): Invalid query part for merchant lists");
break;
}
LoadMerchantData_result(result);
pQueuedMerchantsWorkID = 0;
break;
}
case DBA_b1_Zone_MerchantListsTemp: {
char errbuf[MYSQL_ERRMSG_SIZE];
MYSQL_RES* result = 0;
DBAsyncQuery* dbaq = dbaw->PopAnswer();
if(dbaq == nullptr) {
LogFile->write(EQEMuLog::Error, "nullptr answer provided for async temp merchant list load.");
break;
}
if(!dbaq->GetAnswer(errbuf, &result)) {
LogFile->write(EQEMuLog::Error, "Zone::DBAWComplete(): Unable to get results for temp merchant lists");
break;
}
if(dbaq->QPT() != 1) {
LogFile->write(EQEMuLog::Error, "Zone::DBAWComplete(): Invalid query part for temp merchant lists");
break;
}
LoadTempMerchantData_result(result);
pQueuedMerchantsWorkID = 0;
break;
}
default: {
LogFile->write(EQEMuLog::Error, "Zone::DBAWComplete(): Unknown workpt_b1");
break;
}
}
}
bool Zone::IsLoaded() {
return ZoneLoaded;
}
@@ -772,7 +706,6 @@ void Zone::Shutdown(bool quite)
zone->ResetAuth();
safe_delete(zone);
dbasync->CommitWrites();
entity_list.ClearAreas();
parse->ReloadQuests(true);
UpdateWindowTitle();
@@ -911,8 +844,6 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name)
}
Zone::~Zone() {
if(pQueuedMerchantsWorkID != 0)
dbasync->CancelWork(pQueuedMerchantsWorkID);
spawn2_list.Clear();
safe_delete(zonemap);
safe_delete(watermap);
-3
View File
@@ -166,7 +166,6 @@ public:
void SetStaticZone(bool sz) { staticzone = sz; }
inline bool IsStaticZone() { return staticzone; }
inline void GotCurTime(bool time) { gottime = time; }
void DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw);
void SpawnConditionChanged(const SpawnCondition &c, int16 old_value);
@@ -174,8 +173,6 @@ public:
void LoadNewMerchantData(uint32 merchantid);
void LoadTempMerchantData();
uint32 GetTempMerchantQuantity(uint32 NPCID, uint32 Slot);
void LoadTempMerchantData_result(MYSQL_RES* result);
void LoadMerchantData_result(MYSQL_RES* result);
int SaveTempItem(uint32 merchantid, uint32 npcid, uint32 item, int32 charges, bool sold=false);
void LoadMercTemplates();
void LoadMercSpells();
+905 -160
View File
File diff suppressed because it is too large Load Diff
+76 -96
View File
@@ -6,6 +6,8 @@
#include "../common/loottable.h"
#include "zonedump.h"
#include "../common/faction.h"
#include <limits>
//#include "doors.h"
struct wplist {
@@ -212,9 +214,7 @@ public:
ZoneDatabase(const char* host, const char* user, const char* passwd, const char* database,uint32 port);
virtual ~ZoneDatabase();
/*
* Objects and World Containers
*/
/* Objects and World Containers */
void LoadWorldContainer(uint32 parentid, ItemInst* container);
void SaveWorldContainer(uint32 zone_id, uint32 parent_id, const ItemInst* container);
void DeleteWorldContainer(uint32 parent_id,uint32 zone_id);
@@ -223,10 +223,7 @@ public:
void DeleteObject(uint32 id);
Ground_Spawns* LoadGroundSpawns(uint32 zone_id, int16 version, Ground_Spawns* gs);
/*
* Traders
*/
/* Traders */
void SaveTraderItem(uint32 char_id,uint32 itemid,uint32 uniqueid, int32 charges,uint32 itemcost,uint8 slot);
void UpdateTraderItemCharges(int char_id, uint32 ItemInstID, int32 charges);
void UpdateTraderItemPrice(int CharID, uint32 ItemID, uint32 Charges, uint32 NewPrice);
@@ -236,38 +233,66 @@ public:
Trader_Struct* LoadTraderItem(uint32 char_id);
TraderCharges_Struct* LoadTraderItemWithCharges(uint32 char_id);
// Buyer/Barter
//
/* Buyer/Barter */
void AddBuyLine(uint32 CharID, uint32 BuySlot, uint32 ItemID, const char *ItemName, uint32 Quantity, uint32 Price);
void RemoveBuyLine(uint32 CharID, uint32 BuySlot);
void DeleteBuyLines(uint32 CharID);
void UpdateBuyLine(uint32 CharID, uint32 BuySlot, uint32 Quantity);
/*
* General Character Related Stuff
*/
void StoreCharacterLookup(uint32 char_id);
bool GetAccountInfoForLogin_result(MYSQL_RES* result, int16* admin = 0, char* account_name = 0,
uint32* lsaccountid = 0, uint8* gmspeed = 0, bool* revoked = 0, bool* gmhideme = nullptr,
uint32* account_creation = 0);
bool GetCharacterInfoForLogin_result(MYSQL_RES* result, uint32* character_id = 0, char* current_zone = 0,
PlayerProfile_Struct* pp = 0, Inventory* inv = 0, ExtendedProfile_Struct *ext = 0, uint32* pplen = 0,
uint32* guilddbid = 0, uint8* guildrank = 0, uint8 *class_= 0, uint8 *level = 0, bool *LFP = 0,
bool *LFG = 0, uint8 *NumXTargets = 0, uint8* firstlogon = 0);
/* General Character Related Stuff */
bool SetServerFilters(char* name, ServerSideFilters_Struct *ssfs);
uint32 GetServerFilters(char* name, ServerSideFilters_Struct *ssfs);
void SaveBuffs(Client *c);
void LoadBuffs(Client *c);
void LoadPetInfo(Client *c);
void SavePetInfo(Client *c);
void RemoveTempFactions(Client *c);
/*
* Character Inventory
*/
/* Character Data Loaders */
bool LoadCharacterFactionValues(uint32 character_id, faction_map & val_list);
bool LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterDisciplines(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterSkills(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterData(uint32 character_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp);
bool LoadCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterMaterialColor(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterBandolier(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterPotions(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp);
/* Character Data Saves */
bool SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, float x, float y, float z, float heading, uint8 is_home);
bool SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp);
bool SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp);
bool SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level);
bool SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
bool SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
bool SaveCharacterMaterialColor(uint32 character_id, uint32 slot_id, uint32 color);
bool SaveCharacterSkill(uint32 character_id, uint32 skill_id, uint32 value);
bool SaveCharacterLanguage(uint32 character_id, uint32 lang_id, uint32 value);
bool SaveCharacterDisc(uint32 character_id, uint32 slot_id, uint32 disc_id);
bool SaveCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp);
bool SaveCharacterBandolier(uint32 character_id, uint8 bandolier_id, uint8 bandolier_slot, uint32 item_id, uint32 icon, const char* bandolier_name);
bool SaveCharacterPotionBelt(uint32 character_id, uint8 potion_id, uint32 item_id, uint32 icon);
bool SaveCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp);
/* Character Data Deletes */
bool DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
bool DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
bool DeleteCharacterDisc(uint32 character_id, uint32 slot_id);
bool DeleteCharacterBandolier(uint32 character_id, uint32 band_id);
bool DeleteCharacterLeadershipAAs(uint32 character_id);
bool DeleteCharacterAAs(uint32 character_id);
/* Character Inventory */
bool NoRentExpired(const char* name);
/*
* Corpses
*/
/* Corpses */
bool GetDecayTimes(npcDecayTimes_Struct* npcCorpseDecayTimes);
uint32 CreatePlayerCorpse(uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, uchar* data, uint32 datasize, float x, float y, float z, float heading);
bool CreatePlayerCorpseBackup(uint32 dbid, uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, uchar* data, uint32 datasize, float x, float y, float z, float heading);
@@ -293,21 +318,15 @@ public:
uint32 GetPlayerCorpseItemAt(uint32 corpse_id, uint16 slotid);
uint32 GetPlayerCorpseTimeLeft(uint8 corpse, uint8 type);
/*
* Faction
*/
/* Faction */
bool GetNPCFactionList(uint32 npcfaction_id, int32* faction_id, int32* value, uint8* temp, int32* primary_faction = 0);
bool GetFactionData(FactionMods* fd, uint32 class_mod, uint32 race_mod, uint32 deity_mod, int32 faction_id); //rembrant, needed for factions Dec, 16 2001
bool GetFactionName(int32 faction_id, char* name, uint32 buflen); // rembrant, needed for factions Dec, 16 2001
bool GetFactionIdsForNPC(uint32 nfl_id, std::list<struct NPCFaction*> *faction_list, int32* primary_faction = 0); // neotokyo: improve faction handling
bool SetCharacterFactionLevel(uint32 char_id, int32 faction_id, int32 value, uint8 temp, faction_map &val_list); // rembrant, needed for factions Dec, 16 2001
bool LoadFactionData();
bool LoadFactionValues(uint32 char_id, faction_map & val_list);
bool LoadFactionValues_result(MYSQL_RES* result, faction_map & val_list);
/*
* AAs
*/
/* AAs */
bool LoadAAEffects();
bool LoadAAEffects2();
bool LoadSwarmSpells();
@@ -319,9 +338,7 @@ public:
uint32 CountAAEffects();
void FillAAEffects(SendAA_Struct* aa_struct);
/*
* Zone related
*/
/* Zone related */
bool GetZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct *data, bool &can_bind, bool &can_combat, bool &can_levitate, bool &can_castoutdoor, bool &is_city, bool &is_hotzone, bool &allow_mercs, uint8 &zone_type, int &ruleset, char **map_filename);
bool SaveZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct* zd);
bool LoadStaticZonePoints(LinkedList<ZonePoint*>* zone_point_list,const char* zonename, uint32 version);
@@ -329,9 +346,7 @@ public:
uint8 GetUseCFGSafeCoords();
int getZoneShutDownDelay(uint32 zoneID, uint32 version);
/*
* Spawns and Spawn Points
*/
/* Spawns and Spawn Points */
bool LoadSpawnGroups(const char* zone_name, uint16 version, SpawnGroupList* spawn_group_list);
bool LoadSpawnGroupsByID(int spawngroupid, SpawnGroupList* spawn_group_list);
bool PopulateZoneSpawnList(uint32 zoneid, LinkedList<Spawn2*> &spawn2_list, int16 version, uint32 repopdelay = 0);
@@ -341,9 +356,7 @@ public:
uint32 GetSpawnTimeLeft(uint32 id, uint16 instance_id);
void UpdateSpawn2Status(uint32 id, uint8 new_status);
/*
* Grids/Paths
*/
/* Grids/Paths */
uint32 GetFreeGrid(uint16 zoneid);
void DeleteGrid(Client *c, uint32 sg2, uint32 grid_num, bool grid_too,uint16 zoneid);
void DeleteWaypoint(Client *c, uint32 grid_num, uint32 wp_num,uint16 zoneid);
@@ -359,9 +372,7 @@ public:
int GetHighestGrid(uint32 zoneid);
int GetHighestWaypoint(uint32 zoneid, uint32 gridid);
/*
* NPCs
*/
/* NPCs */
const NPCType* GetNPCType(uint32 id);
uint32 NPCSpawnDB(uint8 command, const char* zone, uint32 zone_version, Client *c, NPC* spawn = 0, uint32 extra = 0); // 0 = Create 1 = Add; 2 = Update; 3 = Remove; 4 = Delete
bool SetSpecialAttkFlag(uint8 id, const char* flag);
@@ -375,9 +386,7 @@ public:
DBnpcspells_Struct* GetNPCSpells(uint32 iDBSpellsID);
DBnpcspellseffects_Struct* GetNPCSpellsEffects(uint32 iDBSpellsEffectsID);
/*
* Mercs
*/
/* Mercs */
const NPCType* GetMercType(uint32 id, uint16 raceid, uint32 clientlevel);
void LoadMercEquipment(Merc *merc);
void SaveMercBuffs(Merc *merc);
@@ -389,9 +398,7 @@ public:
//void LoadMercTypesForMercMerchant(NPC *merchant);
//void LoadMercsForMercMerchant(NPC *merchant);
/*
* Petitions
*/
/* Petitions */
void UpdateBug(BugStruct* bug);
void UpdateBug(PetitionBug_Struct* bug);
void DeletePetitionFromDB(Petition* wpet);
@@ -399,16 +406,11 @@ public:
void InsertPetitionToDB(Petition* wpet);
void RefreshPetitionsFromDB();
/*
* Merchants
*/
/* Merchants */
void SaveMerchantTemp(uint32 npcid, uint32 slot, uint32 item, uint32 charges);
void DeleteMerchantTemp(uint32 npcid, uint32 slot);
/*
* Tradeskills
*/
/* Tradeskills */
bool GetTradeRecipe(const ItemInst* container, uint8 c_type, uint32 some_id, uint32 char_id, DBTradeskillRecipe_Struct *spec);
bool GetTradeRecipe(uint32 recipe_id, uint8 c_type, uint32 some_id, uint32 char_id, DBTradeskillRecipe_Struct *spec);
uint32 GetZoneForage(uint32 ZoneID, uint8 skill); /* for foraging */
@@ -417,14 +419,10 @@ public:
bool EnableRecipe(uint32 recipe_id);
bool DisableRecipe(uint32 recipe_id);
/*
* Tribute
*/
/* Tribute */
bool LoadTributes();
/*
* Doors
*/
/* Doors */
bool DoorIsOpen(uint8 door_id,const char* zone_name);
void SetDoorPlace(uint8 value,uint8 door_id,const char* zone_name);
bool LoadDoors(int32 iDoorCount, Door *into, const char *zone_name, int16 version);
@@ -437,64 +435,46 @@ public:
int32 GetDoorsDBCountPlusOne(const char *zone_name, int16 version);
void InsertDoor(uint32 did, uint16 ddoorid, const char* ddoor_name, float dxpos, float dypos, float dzpos, float dheading, uint8 dopentype, uint16 dguildid, uint32 dlockpick, uint32 dkeyitem, uint8 ddoor_param, uint8 dinvert, int dincline, uint16 dsize);
/*
* Blocked Spells
*/
/* Blocked Spells */
int32 GetBlockedSpellsCount(uint32 zoneid);
bool LoadBlockedSpells(int32 blockedSpellsCount, ZoneSpellsBlocked* into, uint32 zoneid);
/*
* Traps
*/
/* Traps */
bool LoadTraps(const char* zonename, int16 version);
char* GetTrapMessage(uint32 trap_id);
/*
* Time
*/
/* Time */
uint32 GetZoneTZ(uint32 zoneid, uint32 version);
bool SetZoneTZ(uint32 zoneid, uint32 version, uint32 tz);
/*
* Group
*/
/* Group */
void RefreshGroupFromDB(Client *c);
uint8 GroupCount(uint32 groupid);
/*
* Raid
*/
/* Raid */
uint8 RaidGroupCount(uint32 raidid, uint32 groupid);
/*
* Instancing
*/
/* Instancing */
void ListAllInstances(Client* c, uint32 charid);
/*
* QGlobals
*/
/* QGlobals */
void QGlobalPurge();
/*
* Alternate Currency
*/
/* Alternate Currency */
void LoadAltCurrencyValues(uint32 char_id, std::map<uint32, uint32> &currency);
void UpdateAltCurrencyValue(uint32 char_id, uint32 currency_id, uint32 value);
/*
* Misc stuff.
* PLEASE DO NOT ADD TO THIS COLLECTION OF CRAP UNLESS YOUR METHOD
* REALLY HAS NO BETTER SECTION
* Misc stuff.
* PLEASE DO NOT ADD TO THIS COLLECTION OF CRAP UNLESS YOUR METHOD
* REALLY HAS NO BETTER SECTION
*/
bool logevents(const char* accountname,uint32 accountid,uint8 status,const char* charname,const char* target, const char* descriptiontype, const char* description,int event_nid);
void GetEventLogs(const char* name,char* target,uint32 account_id=0,uint8 eventid=0,char* detail=0,char* timestamp=0, CharacterEventLog_Struct* cel=0);
uint32 GetKarma(uint32 acct_id);
void UpdateKarma(uint32 acct_id, uint32 amount);
/*
* Things which really dont belong here...
*/
/* Things which really dont belong here... */
int16 CommandRequirement(const char* commandname);
protected:
-127
View File
@@ -1,127 +0,0 @@
#include "../common/debug.h"
#include <iostream>
#include "entity.h"
#include "masterentity.h"
#include "../common/string_util.h"
#include "../common/breakdowns.h"
#include <stdlib.h>
extern EntityList entity_list;
void DispatchFinishedDBAsync(DBAsyncWork* dbaw) {
uint32_breakdown workpt;
workpt = dbaw->WPT();
switch (workpt.b4()) {
/* case DBA_b4_Main: {
switch (workpt.i24_1()) {
case DBA_i24_1_Main_LoadVariables: {
char errbuf[MYSQL_ERRMSG_SIZE];
MYSQL_RES* result;
DBAsyncQuery* dbaq = dbaw->PopAnswer();
if (dbaq->GetAnswer(errbuf, result))
database.LoadVariables_result(result);
else
std::cout << "Async DB.LoadVariables() failed: '" << errbuf << "'" << std::endl;
break;
}
default: {
std::cout << "Error: DispatchFinishedDBAsync(): Unknown workpt.b4" << std::endl;
break;
}
}
}*/
case DBA_b4_Zone: {
if(zone == nullptr)
break;
zone->DBAWComplete(workpt.b1(), dbaw);
break;
}
case DBA_b4_Entity: {
Entity* entity = entity_list.GetID(workpt.w2_3());
if (!entity)
break;
entity->DBAWComplete(workpt.b1(), dbaw);
break;
}
default: {
std::cout << "Error: DispatchFinishedDBAsync(): Unknown workpt.b4: " << (int) workpt.b4() << ", workpt=" << workpt << std::endl;
break;
}
}
safe_delete(dbaw);
}
#define MAX_TO_DELETE 10
#define MAX_BACKUPS 5
bool DBAsyncCB_CharacterBackup(DBAsyncWork* iWork) { // return true means delete data
char errbuf[MYSQL_ERRMSG_SIZE] = "dbaq == 0";
MYSQL_RES* result = 0;
MYSQL_ROW row;
char* query = 0;
uint32 i;
uint8 ToDeleteIndex = 0;
uint32 ToDelete[MAX_TO_DELETE];
memset(ToDelete, 0, sizeof(ToDelete));
uint32 BackupAges[MAX_BACKUPS]; // must be sorted, highest value in lowest index
memset(BackupAges, 0, sizeof(BackupAges));
bool FoundBackup[MAX_BACKUPS];
memset(FoundBackup, 0, sizeof(FoundBackup));
BackupAges[0] = 86400;
BackupAges[1] = 3600;
DBAsyncQuery* dbaq = iWork->PopAnswer();
if (dbaq && dbaq->GetAnswer(errbuf, &result)) {
while ((row = mysql_fetch_row(result))) {
for (i=0; i<MAX_BACKUPS; i++) {
if (BackupAges[i] == 0 || (uint32)atoi(row[1]) > BackupAges[i])
i = MAX_BACKUPS;
else if (!FoundBackup[i]) {
FoundBackup[i] = true;
break;
}
}
if (i >= MAX_BACKUPS)
ToDelete[ToDeleteIndex++] = atoi(row[0]);
if (ToDeleteIndex >= MAX_TO_DELETE)
break;
}
if (ToDelete[0]) {
uint32 len = 0, size = 0;
AppendAnyLenString(&query, &size, &len, "Delete from character_backup where id=%u", ToDelete[0]);
for (uint8 i=1; i<ToDeleteIndex; i++) {
AppendAnyLenString(&query, &size, &len, " or id=%u", ToDelete[i]);
}
if (!database.RunQuery(query, len, errbuf)) {
LogFile->write(EQEMuLog::Error, "Error in DBAsyncCB_CharacterBackup query2 '%s' %s", query, errbuf);
safe_delete_array(query);
return true;
}
safe_delete_array(query);
}
bool needtoinsert = false;
for (i=0; i<MAX_BACKUPS; i++) {
if (BackupAges[i] != 0 && !FoundBackup[i])
needtoinsert = true;
}
if (needtoinsert) {
if (!database.RunQuery(query, MakeAnyLenString(&query,
"Insert Delayed into character_backup (charid, account_id, name, profile, level, class, x, y, z, zoneid) "
"select id, account_id, name, profile, level, class, x, y, z, zoneid "
"from character_ where id=%u", iWork->WPT()), errbuf)) {
std::cout << "Error in DBAsyncCB_CharacterBackup query3 '" << query << "' " << errbuf << std::endl;
safe_delete_array(query);
return true;
}
safe_delete_array(query);
}
}
else {
// std::cout << "Error in DBAsyncCB_CharacterBackup query1 '" << query << "' " << errbuf << std::endl;
safe_delete_array(query);
return true;
}
return true;
}
-22
View File
@@ -1,22 +0,0 @@
#ifndef ZONEDBASYNC_H
#define ZONEDBASYNC_H
#include "../common/dbasync.h"
void DispatchFinishedDBAsync(DBAsyncWork* iDBAW);
bool DBAsyncCB_CharacterBackup(DBAsyncWork* iWork);
#define DBA_b4_Main 1
#define DBA_b4_Worldserver 2
#define DBA_b4_Zone 3
#define DBA_b4_Entity 4
#define DBA_b1_Entity_SeeQPT 0
#define DBA_b1_Entity_Client_InfoForLogin 1
#define DBA_b1_Entity_Client_Save 2
#define DBA_b1_Entity_Client_Backup 3
#define DBA_b1_Entity_Corpse_Backup 4
#define DBA_b1_Zone_MerchantLists 5
#define DBA_b1_Zone_MerchantListsTemp 6
#endif
+2 -1
View File
@@ -354,7 +354,7 @@ void Client::DoZoneSuccess(ZoneChange_Struct *zc, uint16 zone_id, uint32 instanc
m_pp.zoneInstance = instance_id;
//Force a save so its waiting for them when they zone
Save(2);
Save(2);
if (zone_id == zone->GetZoneID() && instance_id == zone->GetInstanceID()) {
// No need to ask worldserver if we're zoning to ourselves (most
@@ -704,6 +704,7 @@ void Client::SetBindPoint(int to_zone, float new_x, float new_y, float new_z) {
m_pp.binds[0].y = new_y;
m_pp.binds[0].z = new_z;
}
database.SaveCharacterBindPoint(this->CharacterID(), m_pp.binds[0].zoneId, 0, m_pp.binds[0].x, m_pp.binds[0].y, m_pp.binds[0].z, 0, 0);
}
void Client::GoToBind(uint8 bindnum) {