Implement extra bind points (secondary recall)

For SE_Gate, base2 is which bind to use (starting at 1)
For SE_BindAffinity, base1 is which bind to set (starting at 1)
For SE_GateCastersBindpoint, base1 is which bind to use (starting at 1)
    here was actually no spells that don't send to the main bind,
    but it uses a base1 of 1 which matches with SE_Gate
    This also doesn't break anything

The quest stuff for now hasn't been updated to be able to make use of the extra binds

There are a total of 5 bind points, with the 5th being your starting city
This commit is contained in:
Michael Cook (mackal) 2016-03-05 16:28:53 -05:00
parent 655d2d47ba
commit 9599501ace
17 changed files with 109 additions and 88 deletions

View File

@ -1,5 +1,13 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50) EQEMu Changelog (Started on Sept 24, 2003 15:50)
------------------------------------------------------- -------------------------------------------------------
== 03/05/2016 ==
mackal: Implement extra bind points (secondary recall)
For SE_Gate, base2 is which bind to use (starting at 1)
For SE_BindAffinity, base1 is which bind to set (starting at 1)
For SE_GateCastersBindpoint, base1 is which bind to use (starting at 1)
There was actually no spells that don't send to the main bind, but it uses a base1 of 1 which matches with SE_Gate
This also doesn't break anything
== 03/01/2016 == == 03/01/2016 ==
Uleat: Fix for LDoN treasure 'npcs' not leaving a corpse (please report any issues..) Uleat: Fix for LDoN treasure 'npcs' not leaving a corpse (please report any issues..)

View File

@ -636,11 +636,11 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe
); );
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
/* Save Bind Points */ /* Save Bind Points */
query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)"
" VALUES (%u, %u, %u, %f, %f, %f, %f, %i), " " VALUES (%u, %u, %u, %f, %f, %f, %f, %i), "
"(%u, %u, %u, %f, %f, %f, %f, %i)", "(%u, %u, %u, %f, %f, %f, %f, %i)",
character_id, pp->binds[0].zoneId, 0, pp->binds[0].x, pp->binds[0].y, pp->binds[0].z, pp->binds[0].heading, 0, character_id, pp->binds[0].zoneId, 0, pp->binds[0].x, pp->binds[0].y, pp->binds[0].z, pp->binds[0].heading, 0,
character_id, pp->binds[4].zoneId, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading, 1 character_id, pp->binds[4].zoneId, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading, 4
); results = QueryDatabase(query); ); results = QueryDatabase(query);
/* Save Skills */ /* Save Skills */

View File

@ -30,7 +30,7 @@
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/ */
#define CURRENT_BINARY_DATABASE_VERSION 9095 #define CURRENT_BINARY_DATABASE_VERSION 9096
#ifdef BOTS #ifdef BOTS
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9000 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9000
#else #else

View File

@ -349,6 +349,7 @@
9093|2015_12_21_items_updates_evoitem.sql|SHOW COLUMNS FROM `items` LIKE 'evoitem'|empty| 9093|2015_12_21_items_updates_evoitem.sql|SHOW COLUMNS FROM `items` LIKE 'evoitem'|empty|
9094|2015_12_29_quest_zone_events.sql|SELECT * FROM perl_event_export_settings WHERE event_description = 'EVENT_SPAWN_ZONE'|empty| 9094|2015_12_29_quest_zone_events.sql|SELECT * FROM perl_event_export_settings WHERE event_description = 'EVENT_SPAWN_ZONE'|empty|
9095|2016_01_08_command_find_aliases.sql|SELECT * FROM `command_settings` WHERE `command` LIKE 'findaliases'|empty| 9095|2016_01_08_command_find_aliases.sql|SELECT * FROM `command_settings` WHERE `command` LIKE 'findaliases'|empty|
9096|2016_03_05_secondary_recall.sql|SHOW COLUMNS FROM `character_bind` LIKE 'slot'|empty|
# Upgrade conditions: # Upgrade conditions:
# This won't be needed after this system is implemented, but it is used database that are not # This won't be needed after this system is implemented, but it is used database that are not

View File

@ -0,0 +1,6 @@
ALTER TABLE `character_bind` ADD `slot` int(4) AFTER `id`;
UPDATE `character_bind` SET `slot`='0' WHERE `is_home`=0;
UPDATE `character_bind` SET `slot`='4' WHERE `is_home`=1;
ALTER TABLE `character_bind` DROP PRIMARY KEY, ADD PRIMARY KEY(`id`, `slot`);
ALTER TABLE `character_bind` DROP COLUMN `is_home`;

View File

@ -159,10 +159,10 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou
} }
/* Set Bind Point Data for any character that may possibly be missing it for any reason */ /* Set Bind Point Data for any character that may possibly be missing it for any reason */
cquery = StringFormat("SELECT `zone_id`, `instance_id`, `x`, `y`, `z`, `heading`, `is_home` FROM `character_bind` WHERE `id` = %i LIMIT 2", character_id); cquery = StringFormat("SELECT `zone_id`, `instance_id`, `x`, `y`, `z`, `heading`, `slot` FROM `character_bind` WHERE `id` = %i LIMIT 5", character_id);
auto results_bind = database.QueryDatabase(cquery); auto results_bind = database.QueryDatabase(cquery);
for (auto row_b = results_bind.begin(); row_b != results_bind.end(); ++row_b) { for (auto row_b = results_bind.begin(); row_b != results_bind.end(); ++row_b) {
if (row_b[6] && atoi(row_b[6]) == 1){ has_home = 1; } if (row_b[6] && atoi(row_b[6]) == 4){ has_home = 1; }
if (row_b[6] && atoi(row_b[6]) == 0){ has_bind = 1; } if (row_b[6] && atoi(row_b[6]) == 0){ has_bind = 1; }
} }
@ -189,14 +189,14 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou
pp.binds[0] = pp.binds[4]; pp.binds[0] = pp.binds[4];
/* If no home bind set, set it */ /* If no home bind set, set it */
if (has_home == 0) { if (has_home == 0) {
std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)"
" VALUES (%u, %u, %u, %f, %f, %f, %f, %i)", " VALUES (%u, %u, %u, %f, %f, %f, %f, %i)",
character_id, pp.binds[4].zoneId, 0, pp.binds[4].x, pp.binds[4].y, pp.binds[4].z, pp.binds[4].heading, 1); character_id, pp.binds[4].zoneId, 0, pp.binds[4].x, pp.binds[4].y, pp.binds[4].z, pp.binds[4].heading, 4);
auto results_bset = QueryDatabase(query); auto results_bset = QueryDatabase(query);
} }
/* If no regular bind set, set it */ /* If no regular bind set, set it */
if (has_bind == 0) { if (has_bind == 0) {
std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)"
" VALUES (%u, %u, %u, %f, %f, %f, %f, %i)", " VALUES (%u, %u, %u, %f, %f, %f, %f, %i)",
character_id, pp.binds[0].zoneId, 0, pp.binds[0].x, pp.binds[0].y, pp.binds[0].z, pp.binds[0].heading, 0); character_id, pp.binds[0].zoneId, 0, pp.binds[0].x, pp.binds[0].y, pp.binds[0].z, pp.binds[0].heading, 0);
auto results_bset = QueryDatabase(query); auto results_bset = QueryDatabase(query);
@ -285,7 +285,7 @@ int WorldDatabase::MoveCharacterToBind(int CharID, uint8 bindnum)
bindnum = 0; bindnum = 0;
} }
std::string query = StringFormat("SELECT zone_id, instance_id, x, y, z FROM character_bind WHERE id = %u AND is_home = %u LIMIT 1", CharID, bindnum == 4 ? 1 : 0); std::string query = StringFormat("SELECT zone_id, instance_id, x, y, z FROM character_bind WHERE id = %u AND slot = %u LIMIT 1", CharID, bindnum);
auto results = database.QueryDatabase(query); auto results = database.QueryDatabase(query);
if(!results.Success() || results.RowCount() == 0) { if(!results.Success() || results.RowCount() == 0) {
return 0; return 0;

View File

@ -587,10 +587,9 @@ bool Client::Save(uint8 iCommitNow) {
database.SaveCharacterCurrency(CharacterID(), &m_pp); database.SaveCharacterCurrency(CharacterID(), &m_pp);
/* Save Current Bind Points */ /* Save Current Bind Points */
auto regularBindPosition = glm::vec4(m_pp.binds[0].x, m_pp.binds[0].y, m_pp.binds[0].z, 0.0f); for (int i = 0; i < 5; i++)
auto homeBindPosition = glm::vec4(m_pp.binds[4].x, m_pp.binds[4].y, m_pp.binds[4].z, 0.0f); if (m_pp.binds[i].zoneId)
database.SaveCharacterBindPoint(CharacterID(), m_pp.binds[0].zoneId, m_pp.binds[0].instance_id, regularBindPosition, 0); /* Regular bind */ database.SaveCharacterBindPoint(CharacterID(), m_pp.binds[i], i);
database.SaveCharacterBindPoint(CharacterID(), m_pp.binds[4].zoneId, m_pp.binds[4].instance_id, homeBindPosition, 1); /* Home Bind */
/* Save Character Buffs */ /* Save Character Buffs */
database.SaveBuffs(this); database.SaveBuffs(this);

View File

@ -582,8 +582,8 @@ public:
void GoToBind(uint8 bindnum = 0); void GoToBind(uint8 bindnum = 0);
void GoToSafeCoords(uint16 zone_id, uint16 instance_id); void GoToSafeCoords(uint16 zone_id, uint16 instance_id);
void Gate(); void Gate(uint8 bindnum = 0);
void SetBindPoint(int to_zone = -1, int to_instance = 0, const glm::vec3& location = glm::vec3()); void SetBindPoint(int bind_num = 0, int to_zone = -1, int to_instance = 0, const glm::vec3& location = glm::vec3());
void SetStartZone(uint32 zoneid, float x = 0.0f, float y =0.0f, float z = 0.0f); void SetStartZone(uint32 zoneid, float x = 0.0f, float y =0.0f, float z = 0.0f);
uint32 GetStartZone(void); uint32 GetStartZone(void);
void MovePC(const char* zonename, float x, float y, float z, float heading, uint8 ignorerestrictions = 0, ZoneMode zm = ZoneSolicited); void MovePC(const char* zonename, float x, float y, float z, float heading, uint8 ignorerestrictions = 0, ZoneMode zm = ZoneSolicited);

View File

@ -232,27 +232,27 @@ void Lua_Client::SetBindPoint() {
void Lua_Client::SetBindPoint(int to_zone) { void Lua_Client::SetBindPoint(int to_zone) {
Lua_Safe_Call_Void(); Lua_Safe_Call_Void();
self->SetBindPoint(to_zone); self->SetBindPoint(0, to_zone);
} }
void Lua_Client::SetBindPoint(int to_zone, int to_instance) { void Lua_Client::SetBindPoint(int to_zone, int to_instance) {
Lua_Safe_Call_Void(); Lua_Safe_Call_Void();
self->SetBindPoint(to_zone, to_instance); self->SetBindPoint(0, to_zone, to_instance);
} }
void Lua_Client::SetBindPoint(int to_zone, int to_instance, float new_x) { void Lua_Client::SetBindPoint(int to_zone, int to_instance, float new_x) {
Lua_Safe_Call_Void(); Lua_Safe_Call_Void();
self->SetBindPoint(to_zone, to_instance, glm::vec3(new_x,0.0f,0.0f)); self->SetBindPoint(0, to_zone, to_instance, glm::vec3(new_x,0.0f,0.0f));
} }
void Lua_Client::SetBindPoint(int to_zone, int to_instance, float new_x, float new_y) { void Lua_Client::SetBindPoint(int to_zone, int to_instance, float new_x, float new_y) {
Lua_Safe_Call_Void(); Lua_Safe_Call_Void();
self->SetBindPoint(to_zone, to_instance, glm::vec3(new_x, new_y, 0.0f)); self->SetBindPoint(0, to_zone, to_instance, glm::vec3(new_x, new_y, 0.0f));
} }
void Lua_Client::SetBindPoint(int to_zone, int to_instance, float new_x, float new_y, float new_z) { void Lua_Client::SetBindPoint(int to_zone, int to_instance, float new_x, float new_y, float new_z) {
Lua_Safe_Call_Void(); Lua_Safe_Call_Void();
self->SetBindPoint(to_zone, to_instance, glm::vec3(new_x, new_y, new_z)); self->SetBindPoint(0, to_zone, to_instance, glm::vec3(new_x, new_y, new_z));
} }
float Lua_Client::GetBindX() { float Lua_Client::GetBindX() {

View File

@ -468,7 +468,7 @@ public:
inline bool IsMoving() const { return moving; } inline bool IsMoving() const { return moving; }
virtual void SetMoving(bool move) { moving = move; m_Delta = glm::vec4(); } virtual void SetMoving(bool move) { moving = move; m_Delta = glm::vec4(); }
virtual void GoToBind(uint8 bindnum = 0) { } virtual void GoToBind(uint8 bindnum = 0) { }
virtual void Gate(); virtual void Gate(uint8 bindnum = 0);
int GetWalkspeed() const { return(_GetWalkSpeed()); } int GetWalkspeed() const { return(_GetWalkSpeed()); }
int GetRunspeed() const { return(_GetRunSpeed()); } int GetRunspeed() const { return(_GetRunSpeed()); }
void SetCurrentSpeed(int in); void SetCurrentSpeed(int in);

View File

@ -165,7 +165,7 @@ public:
virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther); virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther);
void GoToBind(uint8 bindnum = 0) { GMMove(m_SpawnPoint.x, m_SpawnPoint.y, m_SpawnPoint.z, m_SpawnPoint.w); } void GoToBind(uint8 bindnum = 0) { GMMove(m_SpawnPoint.x, m_SpawnPoint.y, m_SpawnPoint.z, m_SpawnPoint.w); }
void Gate(); void Gate(uint8 bindnum = 0);
void GetPetState(SpellBuff_Struct *buffs, uint32 *items, char *name); void GetPetState(SpellBuff_Struct *buffs, uint32 *items, char *name);
void SetPetState(SpellBuff_Struct *buffs, uint32 *items); void SetPetState(SpellBuff_Struct *buffs, uint32 *items);

View File

@ -1072,7 +1072,7 @@ XS(XS_Client_SetBindPoint)
new_z = (float)SvNV(ST(5)); new_z = (float)SvNV(ST(5));
} }
THIS->SetBindPoint(to_zone, to_instance, glm::vec3(new_x, new_y, new_z)); THIS->SetBindPoint(0, to_zone, to_instance, glm::vec3(new_x, new_y, new_z));
} }
XSRETURN_EMPTY; XSRETURN_EMPTY;
} }

View File

@ -1565,7 +1565,7 @@ void QuestManager::ding() {
void QuestManager::rebind(int zoneid, const glm::vec3& location) { void QuestManager::rebind(int zoneid, const glm::vec3& location) {
QuestManagerCurrentQuestVars(); QuestManagerCurrentQuestVars();
if(initiator && initiator->IsClient()) { if(initiator && initiator->IsClient()) {
initiator->SetBindPoint(zoneid, 0, location); initiator->SetBindPoint(0, zoneid, 0, location);
} }
} }

View File

@ -499,7 +499,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
break; break;
} }
case SE_GateCastersBindpoint: //Shin: Used on Teleport Bind. case SE_GateCastersBindpoint: // Used on Teleport Bind.
case SE_Teleport: // gates, rings, circles, etc case SE_Teleport: // gates, rings, circles, etc
case SE_Teleport2: case SE_Teleport2:
{ {
@ -532,13 +532,16 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
} }
if (effect == SE_GateCastersBindpoint && caster->IsClient()) if (effect == SE_GateCastersBindpoint && caster->IsClient())
{ //Shin: Teleport Bind uses caster's bind point { // Teleport Bind uses caster's bind point
x = caster->CastToClient()->GetBindX(); int index = spells[spell_id].base[i] - 1;
y = caster->CastToClient()->GetBindY(); if (index < 0 || index > 4)
z = caster->CastToClient()->GetBindZ(); index = 0;
heading = caster->CastToClient()->GetBindHeading(); x = caster->CastToClient()->GetBindX(index);
y = caster->CastToClient()->GetBindY(index);
z = caster->CastToClient()->GetBindZ(index);
heading = caster->CastToClient()->GetBindHeading(index);
//target_zone = caster->CastToClient()->GetBindZoneId(); target_zone doesn't work due to const char //target_zone = caster->CastToClient()->GetBindZoneId(); target_zone doesn't work due to const char
CastToClient()->MovePC(caster->CastToClient()->GetBindZoneID(), 0, x, y, z, heading); CastToClient()->MovePC(caster->CastToClient()->GetBindZoneID(index), 0, x, y, z, heading);
break; break;
} }
@ -917,7 +920,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
if(caster->IsClient() && caster != this) if(caster->IsClient() && caster != this)
caster->CastToClient()->QueuePacket(message_packet); caster->CastToClient()->QueuePacket(message_packet);
CastToClient()->SetBindPoint(); CastToClient()->SetBindPoint(spells[spell_id].base[i] - 1);
Save(); Save();
safe_delete(action_packet); safe_delete(action_packet);
safe_delete(message_packet); safe_delete(message_packet);
@ -966,7 +969,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
if(caster->IsClient() && caster != this) if(caster->IsClient() && caster != this)
caster->CastToClient()->QueuePacket(message_packet); caster->CastToClient()->QueuePacket(message_packet);
CastToClient()->SetBindPoint(); CastToClient()->SetBindPoint(spells[spell_id].base[i] - 1);
Save(); Save();
safe_delete(action_packet); safe_delete(action_packet);
safe_delete(message_packet); safe_delete(message_packet);
@ -1002,7 +1005,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
if(caster->IsClient() && caster != this) if(caster->IsClient() && caster != this)
caster->CastToClient()->QueuePacket(message_packet); caster->CastToClient()->QueuePacket(message_packet);
CastToClient()->SetBindPoint(); CastToClient()->SetBindPoint(spells[spell_id].base[i] - 1);
Save(); Save();
safe_delete(action_packet); safe_delete(action_packet);
safe_delete(message_packet); safe_delete(message_packet);
@ -1012,7 +1015,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
break; break;
} }
case SE_Gate: //TO DO: Add support for secondary and tertiary gate abilities (base2) case SE_Gate:
{ {
#ifdef SPELL_EFFECT_SPAM #ifdef SPELL_EFFECT_SPAM
snprintf(effect_desc, _EDLEN, "Gate"); snprintf(effect_desc, _EDLEN, "Gate");
@ -1020,7 +1023,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
if(!spellbonuses.AntiGate){ if(!spellbonuses.AntiGate){
if(zone->random.Roll(effect_value)) if(zone->random.Roll(effect_value))
Gate(); Gate(spells[spell_id].base2[i] - 1);
else else
caster->Message_StringID(MT_SpellFailure,GATE_FAIL); caster->Message_StringID(MT_SpellFailure,GATE_FAIL);
} }

View File

@ -1260,30 +1260,27 @@ bool ZoneDatabase::LoadCharacterPotions(uint32 character_id, PlayerProfile_Struc
return true; return true;
} }
bool ZoneDatabase::LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp){ bool ZoneDatabase::LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct *pp)
std::string query = StringFormat("SELECT `zone_id`, `instance_id`, `x`, `y`, `z`, `heading`, `is_home` FROM `character_bind` WHERE `id` = %u LIMIT 2", character_id); {
std::string query = StringFormat("SELECT `slot`, `zone_id`, `instance_id`, `x`, `y`, `z`, `heading` FROM "
"`character_bind` WHERE `id` = %u LIMIT 5",
character_id);
auto results = database.QueryDatabase(query); auto results = database.QueryDatabase(query);
if (!results.RowCount()) // SHIT -- this actually isn't good
return true;
for (auto row = results.begin(); row != results.end(); ++row) { for (auto row = results.begin(); row != results.end(); ++row) {
int index = atoi(row[0]);
/* Is home bind */ if (index < 0 || index > 4)
if (atoi(row[6]) == 1){
pp->binds[4].zoneId = atoi(row[0]);
pp->binds[4].instance_id = atoi(row[1]);
pp->binds[4].x = atoi(row[2]);
pp->binds[4].y = atoi(row[3]);
pp->binds[4].z = atoi(row[4]);
pp->binds[4].heading = atoi(row[5]);
continue; continue;
}
/* Is regular bind point */ pp->binds[index].zoneId = atoi(row[1]);
pp->binds[0].zoneId = atoi(row[0]); pp->binds[index].instance_id = atoi(row[2]);
pp->binds[0].instance_id = atoi(row[1]); pp->binds[index].x = atoi(row[3]);
pp->binds[0].x = atoi(row[2]); pp->binds[index].y = atoi(row[4]);
pp->binds[0].y = atoi(row[3]); pp->binds[index].z = atoi(row[5]);
pp->binds[0].z = atoi(row[4]); pp->binds[index].heading = atoi(row[6]);
pp->binds[0].heading = atoi(row[5]);
} }
return true; return true;
@ -1295,19 +1292,23 @@ bool ZoneDatabase::SaveCharacterLanguage(uint32 character_id, uint32 lang_id, ui
return true; return true;
} }
bool ZoneDatabase::SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, const glm::vec4& position, uint8 is_home){ bool ZoneDatabase::SaveCharacterBindPoint(uint32 character_id, const BindStruct &bind, uint32 bind_num)
if (zone_id <= 0) { {
return false;
}
/* Save Home Bind Point */ /* Save Home Bind Point */
std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" std::string query =
" VALUES (%u, %u, %u, %f, %f, %f, %f, %i)", character_id, zone_id, instance_id, position.x, position.y, position.z, position.w, is_home); StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot) VALUES (%u, "
Log.Out(Logs::General, Logs::None, "ZoneDatabase::SaveCharacterBindPoint for character ID: %i zone_id: %u instance_id: %u position: %s ishome: %u", character_id, zone_id, instance_id, to_string(position).c_str(), is_home); "%u, %u, %f, %f, %f, %f, %i)",
character_id, bind.zoneId, bind.instance_id, bind.x, bind.y, bind.z, bind.heading, bind_num);
Log.Out(Logs::General, Logs::None, "ZoneDatabase::SaveCharacterBindPoint for character ID: %i zone_id: %u "
"instance_id: %u position: %f %f %f %f bind_num: %u",
character_id, bind.zoneId, bind.instance_id, bind.x, bind.y, bind.z, bind.heading, bind_num);
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.RowsAffected()) { if (!results.RowsAffected())
Log.Out(Logs::General, Logs::None, "ERROR Bind Home Save: %s. %s", results.ErrorMessage().c_str(), query.c_str()); Log.Out(Logs::General, Logs::None, "ERROR Bind Home Save: %s. %s", results.ErrorMessage().c_str(),
} query.c_str());
return true; return true;
} }

View File

@ -277,7 +277,7 @@ public:
bool LoadCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp); bool LoadCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp);
/* Character Data Saves */ /* Character Data Saves */
bool SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, const glm::vec4& position, uint8 is_home); bool SaveCharacterBindPoint(uint32 character_id, const BindStruct &bind, uint32 bind_num);
bool SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp); bool SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp);
bool SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp); 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, uint32 charges); bool SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level, uint32 charges);

View File

@ -707,37 +707,40 @@ void Client::GoToSafeCoords(uint16 zone_id, uint16 instance_id) {
} }
void Mob::Gate() { void Mob::Gate(uint8 bindnum) {
GoToBind(); GoToBind(bindnum);
} }
void Client::Gate() { void Client::Gate(uint8 bindnum) {
Mob::Gate(); Mob::Gate(bindnum);
} }
void NPC::Gate() { void NPC::Gate(uint8 bindnum) {
entity_list.MessageClose_StringID(this, true, 200, MT_Spells, GATES, GetCleanName()); entity_list.MessageClose_StringID(this, true, 200, MT_Spells, GATES, GetCleanName());
Mob::Gate(); Mob::Gate(bindnum);
} }
void Client::SetBindPoint(int to_zone, int to_instance, const glm::vec3& location) { void Client::SetBindPoint(int bind_num, int to_zone, int to_instance, const glm::vec3 &location)
{
if (bind_num < 0 || bind_num >= 4)
bind_num = 0;
if (to_zone == -1) { if (to_zone == -1) {
m_pp.binds[0].zoneId = zone->GetZoneID(); m_pp.binds[bind_num].zoneId = zone->GetZoneID();
m_pp.binds[0].instance_id = (zone->GetInstanceID() != 0 && zone->IsInstancePersistent()) ? zone->GetInstanceID() : 0; m_pp.binds[bind_num].instance_id =
m_pp.binds[0].x = m_Position.x; (zone->GetInstanceID() != 0 && zone->IsInstancePersistent()) ? zone->GetInstanceID() : 0;
m_pp.binds[0].y = m_Position.y; m_pp.binds[bind_num].x = m_Position.x;
m_pp.binds[0].z = m_Position.z; m_pp.binds[bind_num].y = m_Position.y;
m_pp.binds[bind_num].z = m_Position.z;
} else {
m_pp.binds[bind_num].zoneId = to_zone;
m_pp.binds[bind_num].instance_id = to_instance;
m_pp.binds[bind_num].x = location.x;
m_pp.binds[bind_num].y = location.y;
m_pp.binds[bind_num].z = location.z;
} }
else { database.SaveCharacterBindPoint(this->CharacterID(), m_pp.binds[bind_num], bind_num);
m_pp.binds[0].zoneId = to_zone;
m_pp.binds[0].instance_id = to_instance;
m_pp.binds[0].x = location.x;
m_pp.binds[0].y = location.y;
m_pp.binds[0].z = location.z;
}
auto regularBindPoint = glm::vec4(m_pp.binds[0].x, m_pp.binds[0].y, m_pp.binds[0].z, 0.0f);
database.SaveCharacterBindPoint(this->CharacterID(), m_pp.binds[0].zoneId, m_pp.binds[0].instance_id, regularBindPoint, 0);
} }
void Client::GoToBind(uint8 bindnum) { void Client::GoToBind(uint8 bindnum) {