diff --git a/changelog.txt b/changelog.txt index 3964d37b5..e3762b3dd 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,13 @@ 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 == Uleat: Fix for LDoN treasure 'npcs' not leaving a corpse (please report any issues..) diff --git a/common/database.cpp b/common/database.cpp index b8889fa06..cdafaa165 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -636,11 +636,11 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe ); auto results = QueryDatabase(query); /* 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), " "(%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[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); /* Save Skills */ diff --git a/common/version.h b/common/version.h index b1be73905..04bf9189c 100644 --- a/common/version.h +++ b/common/version.h @@ -30,7 +30,7 @@ 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 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9000 #else diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 31f3d2ccf..6f48f983e 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -349,6 +349,7 @@ 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| 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: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2016_03_05_secondary_recall.sql b/utils/sql/git/required/2016_03_05_secondary_recall.sql new file mode 100644 index 000000000..7b0f02754 --- /dev/null +++ b/utils/sql/git/required/2016_03_05_secondary_recall.sql @@ -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`; + diff --git a/world/worlddb.cpp b/world/worlddb.cpp index b09758888..357ab3c33 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -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 */ - 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); 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; } } @@ -189,14 +189,14 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou pp.binds[0] = pp.binds[4]; /* If no home bind set, set it */ 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)", - 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); } /* If no regular bind set, set it */ 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)", 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); @@ -285,7 +285,7 @@ int WorldDatabase::MoveCharacterToBind(int CharID, uint8 bindnum) 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); if(!results.Success() || results.RowCount() == 0) { return 0; diff --git a/zone/client.cpp b/zone/client.cpp index e24c24627..5a9724fa8 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -587,10 +587,9 @@ bool Client::Save(uint8 iCommitNow) { database.SaveCharacterCurrency(CharacterID(), &m_pp); /* 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); - auto homeBindPosition = glm::vec4(m_pp.binds[4].x, m_pp.binds[4].y, m_pp.binds[4].z, 0.0f); - database.SaveCharacterBindPoint(CharacterID(), m_pp.binds[0].zoneId, m_pp.binds[0].instance_id, regularBindPosition, 0); /* Regular bind */ - database.SaveCharacterBindPoint(CharacterID(), m_pp.binds[4].zoneId, m_pp.binds[4].instance_id, homeBindPosition, 1); /* Home Bind */ + for (int i = 0; i < 5; i++) + if (m_pp.binds[i].zoneId) + database.SaveCharacterBindPoint(CharacterID(), m_pp.binds[i], i); /* Save Character Buffs */ database.SaveBuffs(this); diff --git a/zone/client.h b/zone/client.h index b1d43c49c..f36422d3a 100644 --- a/zone/client.h +++ b/zone/client.h @@ -582,8 +582,8 @@ public: void GoToBind(uint8 bindnum = 0); void GoToSafeCoords(uint16 zone_id, uint16 instance_id); - void Gate(); - void SetBindPoint(int to_zone = -1, int to_instance = 0, const glm::vec3& location = glm::vec3()); + void Gate(uint8 bindnum = 0); + 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); uint32 GetStartZone(void); void MovePC(const char* zonename, float x, float y, float z, float heading, uint8 ignorerestrictions = 0, ZoneMode zm = ZoneSolicited); diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index d77b83c9f..3db1eabea 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -232,27 +232,27 @@ void Lua_Client::SetBindPoint() { void Lua_Client::SetBindPoint(int to_zone) { Lua_Safe_Call_Void(); - self->SetBindPoint(to_zone); + self->SetBindPoint(0, to_zone); } void Lua_Client::SetBindPoint(int to_zone, int to_instance) { 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) { 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) { 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) { 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() { diff --git a/zone/mob.h b/zone/mob.h index 554634006..11c11573f 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -468,7 +468,7 @@ public: inline bool IsMoving() const { return moving; } virtual void SetMoving(bool move) { moving = move; m_Delta = glm::vec4(); } virtual void GoToBind(uint8 bindnum = 0) { } - virtual void Gate(); + virtual void Gate(uint8 bindnum = 0); int GetWalkspeed() const { return(_GetWalkSpeed()); } int GetRunspeed() const { return(_GetRunSpeed()); } void SetCurrentSpeed(int in); diff --git a/zone/npc.h b/zone/npc.h index 327918c19..fe658aab2 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -165,7 +165,7 @@ public: 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 Gate(); + void Gate(uint8 bindnum = 0); void GetPetState(SpellBuff_Struct *buffs, uint32 *items, char *name); void SetPetState(SpellBuff_Struct *buffs, uint32 *items); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index d4c5f34d0..9c51b8a92 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -1072,7 +1072,7 @@ XS(XS_Client_SetBindPoint) 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; } diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index fa8788bbf..b16613e75 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -1565,7 +1565,7 @@ void QuestManager::ding() { void QuestManager::rebind(int zoneid, const glm::vec3& location) { QuestManagerCurrentQuestVars(); if(initiator && initiator->IsClient()) { - initiator->SetBindPoint(zoneid, 0, location); + initiator->SetBindPoint(0, zoneid, 0, location); } } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index d5006a52b..ca10259a1 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -499,7 +499,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove 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_Teleport2: { @@ -532,13 +532,16 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } if (effect == SE_GateCastersBindpoint && caster->IsClient()) - { //Shin: Teleport Bind uses caster's bind point - x = caster->CastToClient()->GetBindX(); - y = caster->CastToClient()->GetBindY(); - z = caster->CastToClient()->GetBindZ(); - heading = caster->CastToClient()->GetBindHeading(); + { // Teleport Bind uses caster's bind point + int index = spells[spell_id].base[i] - 1; + if (index < 0 || index > 4) + index = 0; + 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 - CastToClient()->MovePC(caster->CastToClient()->GetBindZoneID(), 0, x, y, z, heading); + CastToClient()->MovePC(caster->CastToClient()->GetBindZoneID(index), 0, x, y, z, heading); break; } @@ -917,7 +920,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if(caster->IsClient() && caster != this) caster->CastToClient()->QueuePacket(message_packet); - CastToClient()->SetBindPoint(); + CastToClient()->SetBindPoint(spells[spell_id].base[i] - 1); Save(); safe_delete(action_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) caster->CastToClient()->QueuePacket(message_packet); - CastToClient()->SetBindPoint(); + CastToClient()->SetBindPoint(spells[spell_id].base[i] - 1); Save(); safe_delete(action_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) caster->CastToClient()->QueuePacket(message_packet); - CastToClient()->SetBindPoint(); + CastToClient()->SetBindPoint(spells[spell_id].base[i] - 1); Save(); safe_delete(action_packet); safe_delete(message_packet); @@ -1012,7 +1015,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Gate: //TO DO: Add support for secondary and tertiary gate abilities (base2) + case SE_Gate: { #ifdef SPELL_EFFECT_SPAM 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(zone->random.Roll(effect_value)) - Gate(); + Gate(spells[spell_id].base2[i] - 1); else caster->Message_StringID(MT_SpellFailure,GATE_FAIL); } diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 591f8c3d3..e90e64af5 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1260,30 +1260,27 @@ bool ZoneDatabase::LoadCharacterPotions(uint32 character_id, PlayerProfile_Struc return true; } -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); +bool ZoneDatabase::LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct *pp) +{ + 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); + if (!results.RowCount()) // SHIT -- this actually isn't good + return true; + for (auto row = results.begin(); row != results.end(); ++row) { - - /* Is home bind */ - 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]); + int index = atoi(row[0]); + if (index < 0 || index > 4) continue; - } - /* Is regular bind point */ - pp->binds[0].zoneId = atoi(row[0]); - pp->binds[0].instance_id = atoi(row[1]); - pp->binds[0].x = atoi(row[2]); - pp->binds[0].y = atoi(row[3]); - pp->binds[0].z = atoi(row[4]); - pp->binds[0].heading = atoi(row[5]); + pp->binds[index].zoneId = atoi(row[1]); + pp->binds[index].instance_id = atoi(row[2]); + pp->binds[index].x = atoi(row[3]); + pp->binds[index].y = atoi(row[4]); + pp->binds[index].z = atoi(row[5]); + pp->binds[index].heading = atoi(row[6]); } return true; @@ -1295,19 +1292,23 @@ bool ZoneDatabase::SaveCharacterLanguage(uint32 character_id, uint32 lang_id, ui return true; } -bool ZoneDatabase::SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, const glm::vec4& position, uint8 is_home){ - if (zone_id <= 0) { - return false; - } - +bool ZoneDatabase::SaveCharacterBindPoint(uint32 character_id, const BindStruct &bind, uint32 bind_num) +{ /* Save Home Bind Point */ - std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" - " 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); - 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); + 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)", + 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); - if (!results.RowsAffected()) { - Log.Out(Logs::General, Logs::None, "ERROR Bind Home Save: %s. %s", results.ErrorMessage().c_str(), query.c_str()); - } + if (!results.RowsAffected()) + Log.Out(Logs::General, Logs::None, "ERROR Bind Home Save: %s. %s", results.ErrorMessage().c_str(), + query.c_str()); + return true; } diff --git a/zone/zonedb.h b/zone/zonedb.h index c4d26792d..b5e1d3509 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -277,7 +277,7 @@ public: bool LoadCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp); /* 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 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); diff --git a/zone/zoning.cpp b/zone/zoning.cpp index 5b60448ec..9c7ae87a4 100644 --- a/zone/zoning.cpp +++ b/zone/zoning.cpp @@ -707,37 +707,40 @@ void Client::GoToSafeCoords(uint16 zone_id, uint16 instance_id) { } -void Mob::Gate() { - GoToBind(); +void Mob::Gate(uint8 bindnum) { + GoToBind(bindnum); } -void Client::Gate() { - Mob::Gate(); +void Client::Gate(uint8 bindnum) { + Mob::Gate(bindnum); } -void NPC::Gate() { +void NPC::Gate(uint8 bindnum) { 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) { - m_pp.binds[0].zoneId = zone->GetZoneID(); - m_pp.binds[0].instance_id = (zone->GetInstanceID() != 0 && zone->IsInstancePersistent()) ? zone->GetInstanceID() : 0; - m_pp.binds[0].x = m_Position.x; - m_pp.binds[0].y = m_Position.y; - m_pp.binds[0].z = m_Position.z; + m_pp.binds[bind_num].zoneId = zone->GetZoneID(); + m_pp.binds[bind_num].instance_id = + (zone->GetInstanceID() != 0 && zone->IsInstancePersistent()) ? zone->GetInstanceID() : 0; + m_pp.binds[bind_num].x = m_Position.x; + 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 { - 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); + database.SaveCharacterBindPoint(this->CharacterID(), m_pp.binds[bind_num], bind_num); } void Client::GoToBind(uint8 bindnum) {