From 4a051e2443963ccdc3d62c93a3671c76e3c1aafd Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 1 Mar 2010 12:52:59 +0300 Subject: [PATCH] [9496] HomeBind fixes. * Use area id instead zone id for home bind zone info as expected. This will for example proper show capital name in area himebinding for capital; tavern. * Clarify that player create zone in fact is area (subzone) * Implement SPELL_EFFECT_BIND for normal homebinding. Also support spell target position mode used in 53823/53821 spells * Add Spell::EffectEmpty for mark spell effects that used but not expect any code in handler. Example weapon spells that used just as known spell markers for client. Original patch idea inspirit by Sadikum patch suggestion. --- src/game/NPCHandler.cpp | 32 ++------------------ src/game/ObjectMgr.cpp | 4 +-- src/game/Player.cpp | 25 ++++++++-------- src/game/Player.h | 6 ++-- src/game/Spell.cpp | 1 + src/game/Spell.h | 2 ++ src/game/SpellEffects.cpp | 63 ++++++++++++++++++++++++++++++++++++++- src/game/SpellMgr.cpp | 47 ++++++++++++++++++----------- src/shared/revision_nr.h | 2 +- 9 files changed, 116 insertions(+), 66 deletions(-) diff --git a/src/game/NPCHandler.cpp b/src/game/NPCHandler.cpp index 6d7deb85a..cfdf7fa81 100644 --- a/src/game/NPCHandler.cpp +++ b/src/game/NPCHandler.cpp @@ -425,38 +425,12 @@ void WorldSession::SendBindPoint(Creature *npc) if(GetPlayer()->GetMap()->Instanceable()) return; - uint32 bindspell = 3286; - uint32 zone_id = _player->GetZoneId(); - - _player->SetHomebindToCurrentPos(); - // send spell for bind 3286 bind magic - npc->CastSpell(_player, bindspell, true); + npc->CastSpell(_player, 3286, true); // Bind WorldPacket data( SMSG_TRAINER_BUY_SUCCEEDED, (8+4)); - data << npc->GetGUID(); - data << bindspell; - SendPacket( &data ); - - // binding - data.Initialize( SMSG_BINDPOINTUPDATE, (4+4+4+4+4) ); - data << float(_player->GetPositionX()); - data << float(_player->GetPositionY()); - data << float(_player->GetPositionZ()); - data << uint32(_player->GetMapId()); - data << uint32(zone_id); - SendPacket( &data ); - - DEBUG_LOG("New Home Position X is %f",_player->GetPositionX()); - DEBUG_LOG("New Home Position Y is %f",_player->GetPositionY()); - DEBUG_LOG("New Home Position Z is %f",_player->GetPositionZ()); - DEBUG_LOG("New Home MapId is %u",_player->GetMapId()); - DEBUG_LOG("New Home ZoneId is %u",zone_id); - - // zone update - data.Initialize( SMSG_PLAYERBOUND, 8+4 ); - data << uint64(_player->GetGUID()); - data << uint32(zone_id); + data << uint64(npc->GetGUID()); + data << uint32(3286); // Bind SendPacket( &data ); _player->PlayerTalkClass->CloseGossip(); diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index b88796107..b1540da6f 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -2333,7 +2333,7 @@ void ObjectMgr::LoadPlayerInfo() uint32 current_race = fields[0].GetUInt32(); uint32 current_class = fields[1].GetUInt32(); uint32 mapId = fields[2].GetUInt32(); - uint32 zoneId = fields[3].GetUInt32(); + uint32 areaId = fields[3].GetUInt32(); float positionX = fields[4].GetFloat(); float positionY = fields[5].GetFloat(); float positionZ = fields[6].GetFloat(); @@ -2379,7 +2379,7 @@ void ObjectMgr::LoadPlayerInfo() PlayerInfo* pInfo = &playerInfo[current_race][current_class]; pInfo->mapId = mapId; - pInfo->zoneId = zoneId; + pInfo->areaId = areaId; pInfo->positionX = positionX; pInfo->positionY = positionY; pInfo->positionZ = positionZ; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 03eb0e888..65d63ce2c 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -16095,7 +16095,7 @@ bool Player::_LoadHomeBind(QueryResult *result) { Field *fields = result->Fetch(); m_homebindMapId = fields[0].GetUInt32(); - m_homebindZoneId = fields[1].GetUInt16(); + m_homebindAreaId = fields[1].GetUInt16(); m_homebindX = fields[2].GetFloat(); m_homebindY = fields[3].GetFloat(); m_homebindZ = fields[4].GetFloat(); @@ -16116,16 +16116,16 @@ bool Player::_LoadHomeBind(QueryResult *result) if(!ok) { m_homebindMapId = info->mapId; - m_homebindZoneId = info->zoneId; + m_homebindAreaId = info->areaId; m_homebindX = info->positionX; m_homebindY = info->positionY; m_homebindZ = info->positionZ; - CharacterDatabase.PExecute("INSERT INTO character_homebind (guid,map,zone,position_x,position_y,position_z) VALUES ('%u', '%u', '%u', '%f', '%f', '%f')", GetGUIDLow(), m_homebindMapId, (uint32)m_homebindZoneId, m_homebindX, m_homebindY, m_homebindZ); + CharacterDatabase.PExecute("INSERT INTO character_homebind (guid,map,zone,position_x,position_y,position_z) VALUES ('%u', '%u', '%u', '%f', '%f', '%f')", GetGUIDLow(), m_homebindMapId, (uint32)m_homebindAreaId, m_homebindX, m_homebindY, m_homebindZ); } DEBUG_LOG("Setting player home position: mapid is: %u, zoneid is %u, X is %f, Y is %f, Z is %f", - m_homebindMapId, m_homebindZoneId, m_homebindX, m_homebindY, m_homebindZ); + m_homebindMapId, m_homebindAreaId, m_homebindX, m_homebindY, m_homebindZ); return true; } @@ -18901,7 +18901,7 @@ void Player::SendInitialPacketsBeforeAddToMap() WorldPacket data(SMSG_BINDPOINTUPDATE, 5*4); data << m_homebindX << m_homebindY << m_homebindZ; data << (uint32) m_homebindMapId; - data << (uint32) m_homebindZoneId; + data << (uint32) m_homebindAreaId; GetSession()->SendPacket(&data); // SMSG_SET_PROFICIENCY @@ -21549,16 +21549,17 @@ bool Player::IsImmunedToSpellEffect(SpellEntry const* spellInfo, SpellEffectInde return Unit::IsImmunedToSpellEffect(spellInfo, index); } -void Player::SetHomebindToCurrentPos() +void Player::SetHomebindToLocation(WorldLocation const& loc, uint32 area_id) { - m_homebindMapId = GetMapId(); - m_homebindZoneId = GetZoneId(); - m_homebindX = GetPositionX(); - m_homebindY = GetPositionY(); - m_homebindZ = GetPositionZ(); + m_homebindMapId = loc.mapid; + m_homebindAreaId = area_id; + m_homebindX = loc.coord_x; + m_homebindY = loc.coord_y; + m_homebindZ = loc.coord_z; // update sql homebind CharacterDatabase.PExecute("UPDATE character_homebind SET map = '%u', zone = '%u', position_x = '%f', position_y = '%f', position_z = '%f' WHERE guid = '%u'", - m_homebindMapId, m_homebindZoneId, m_homebindX, m_homebindY, m_homebindZ, GetGUIDLow()); + m_homebindMapId, m_homebindAreaId, m_homebindX, m_homebindY, m_homebindZ, GetGUIDLow()); } + diff --git a/src/game/Player.h b/src/game/Player.h index f35e614d6..b2ff7f219 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -289,7 +289,7 @@ struct PlayerInfo } uint32 mapId; - uint32 zoneId; + uint32 areaId; float positionX; float positionY; float positionZ; @@ -2168,7 +2168,7 @@ class MANGOS_DLL_SPEC Player : public Unit float m_recallO; void SaveRecallPosition(); - void SetHomebindToCurrentPos(); + void SetHomebindToLocation(WorldLocation const& loc, uint32 area_id); void RelocateToHomebind() { SetLocationMapId(m_homebindMapId); Relocate(m_homebindX, m_homebindY, m_homebindZ); } bool TeleportToHomebind(uint32 options = 0) { return TeleportTo(m_homebindMapId, m_homebindX, m_homebindY, m_homebindZ, GetOrientation(), options); } @@ -2533,7 +2533,7 @@ class MANGOS_DLL_SPEC Player : public Unit // Homebind coordinates uint32 m_homebindMapId; - uint16 m_homebindZoneId; + uint16 m_homebindAreaId; float m_homebindX; float m_homebindY; float m_homebindZ; diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index d879e918e..0eada1763 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -2258,6 +2258,7 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList& } break; } + case SPELL_EFFECT_BIND: case SPELL_EFFECT_RESURRECT: case SPELL_EFFECT_PARRY: case SPELL_EFFECT_BLOCK: diff --git a/src/game/Spell.h b/src/game/Spell.h index ca93d5d36..7612ff084 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -217,6 +217,7 @@ class Spell friend void Unit::SetCurrentCastedSpell( Spell * pSpell ); public: + void EffectEmpty(SpellEffectIndex eff_idx); void EffectNULL(SpellEffectIndex eff_idx); void EffectUnused(SpellEffectIndex eff_idx); void EffectDistract(SpellEffectIndex eff_idx); @@ -231,6 +232,7 @@ class Spell void EffectPowerBurn(SpellEffectIndex eff_idx); void EffectPowerDrain(SpellEffectIndex eff_idx); void EffectHeal(SpellEffectIndex eff_idx); + void EffectBind(SpellEffectIndex eff_idx); void EffectHealthLeech(SpellEffectIndex eff_idx); void EffectQuestComplete(SpellEffectIndex eff_idx); void EffectCreateItem(SpellEffectIndex eff_idx); diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 1d9bb3c64..6401d9b47 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -68,7 +68,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectPowerDrain, // 8 SPELL_EFFECT_POWER_DRAIN &Spell::EffectHealthLeech, // 9 SPELL_EFFECT_HEALTH_LEECH &Spell::EffectHeal, // 10 SPELL_EFFECT_HEAL - &Spell::EffectNULL, // 11 SPELL_EFFECT_BIND + &Spell::EffectBind, // 11 SPELL_EFFECT_BIND &Spell::EffectNULL, // 12 SPELL_EFFECT_PORTAL &Spell::EffectUnused, // 13 SPELL_EFFECT_RITUAL_BASE unused &Spell::EffectUnused, // 14 SPELL_EFFECT_RITUAL_SPECIALIZE unused @@ -222,6 +222,11 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectActivateSpec, //162 SPELL_EFFECT_TALENT_SPEC_SELECT activate primary/secondary spec }; +void Spell::EffectEmpty(SpellEffectIndex /*eff_idx*/) +{ + // NOT NEED ANY IMPLEMENTATION CODE, EFFECT POSISBLE USED AS MARKER OR CLIENT INFORM +} + void Spell::EffectNULL(SpellEffectIndex /*eff_idx*/) { sLog.outDebug("WORLD: Spell Effect DUMMY"); @@ -7372,3 +7377,59 @@ void Spell::EffectActivateSpec(SpellEffectIndex /*eff_idx*/) ((Player*)unitTarget)->ActivateSpec(spec); } + +void Spell::EffectBind(SpellEffectIndex eff_idx) +{ + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + Player* player = (Player*)unitTarget; + + uint32 area_id; + WorldLocation loc; + if (m_spellInfo->EffectImplicitTargetA[eff_idx] == TARGET_TABLE_X_Y_Z_COORDINATES || + m_spellInfo->EffectImplicitTargetB[eff_idx] == TARGET_TABLE_X_Y_Z_COORDINATES) + { + SpellTargetPosition const* st = sSpellMgr.GetSpellTargetPosition(m_spellInfo->Id); + if (!st) + { + sLog.outError( "Spell::EffectBind - unknown Teleport coordinates for spell ID %u", m_spellInfo->Id ); + return; + } + + loc.mapid = st->target_mapId; + loc.coord_x = st->target_X; + loc.coord_y = st->target_Y; + loc.coord_z = st->target_Y; + loc.orientation = st->target_Orientation; + area_id = sMapMgr.GetAreaId(loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z); + } + else + { + player->GetPosition(loc); + area_id = player->GetAreaId(); + } + + player->SetHomebindToLocation(loc,area_id); + + // binding + WorldPacket data( SMSG_BINDPOINTUPDATE, (4+4+4+4+4) ); + data << float(loc.coord_x); + data << float(loc.coord_y); + data << float(loc.coord_z); + data << uint32(loc.mapid); + data << uint32(area_id); + player->SendDirectMessage( &data ); + + DEBUG_LOG("New Home Position X is %f", loc.coord_x); + DEBUG_LOG("New Home Position Y is %f", loc.coord_y); + DEBUG_LOG("New Home Position Z is %f", loc.coord_z); + DEBUG_LOG("New Home MapId is %u", loc.mapid); + DEBUG_LOG("New Home AreaId is %u", area_id); + + // zone update + data.Initialize(SMSG_PLAYERBOUND, 8+4); + data << uint64(player->GetGUID()); + data << uint32(area_id); + player->SendMessageToSet( &data, true ); +} diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index f804f6ca4..6914982e1 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -795,7 +795,7 @@ void SpellMgr::LoadSpellTargetPositions() // 0 1 2 3 4 5 QueryResult *result = WorldDatabase.Query("SELECT id, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM spell_target_position"); - if( !result ) + if (!result) { barGoLink bar( 1 ); @@ -807,7 +807,7 @@ void SpellMgr::LoadSpellTargetPositions() return; } - barGoLink bar( (int)result->GetRowCount() ); + barGoLink bar((int)result->GetRowCount()); do { @@ -825,8 +825,21 @@ void SpellMgr::LoadSpellTargetPositions() st.target_Z = fields[4].GetFloat(); st.target_Orientation = fields[5].GetFloat(); + MapEntry const* mapEntry = sMapStore.LookupEntry(st.target_mapId); + if (!mapEntry) + { + sLog.outErrorDb("Spell (ID:%u) target map (ID: %u) does not exist in `Map.dbc`.",Spell_ID,st.target_mapId); + continue; + } + + if (st.target_X==0 && st.target_Y==0 && st.target_Z==0) + { + sLog.outErrorDb("Spell (ID:%u) target coordinates not provided.",Spell_ID); + continue; + } + SpellEntry const* spellInfo = sSpellStore.LookupEntry(Spell_ID); - if(!spellInfo) + if (!spellInfo) { sLog.outErrorDb("Spell (ID:%u) listed in `spell_target_position` does not exist.",Spell_ID); continue; @@ -835,31 +848,29 @@ void SpellMgr::LoadSpellTargetPositions() bool found = false; for(int i = 0; i < MAX_EFFECT_INDEX; ++i) { - if( spellInfo->EffectImplicitTargetA[i]==TARGET_TABLE_X_Y_Z_COORDINATES || spellInfo->EffectImplicitTargetB[i]==TARGET_TABLE_X_Y_Z_COORDINATES ) + if (spellInfo->EffectImplicitTargetA[i]==TARGET_TABLE_X_Y_Z_COORDINATES || spellInfo->EffectImplicitTargetB[i]==TARGET_TABLE_X_Y_Z_COORDINATES) { + // additional requirements + if (spellInfo->Effect[i]==SPELL_EFFECT_BIND && spellInfo->EffectMiscValue[i]) + { + uint32 zone_id = sMapMgr.GetAreaId(st.target_mapId, st.target_X, st.target_Y, st.target_Z); + if (zone_id != spellInfo->EffectMiscValue[i]) + { + sLog.outErrorDb("Spell (Id: %u) listed in `spell_target_position` expected point to zone %u bit point to zone %u.",Spell_ID, spellInfo->EffectMiscValue[i], zone_id); + break; + } + } + found = true; break; } } - if(!found) + if (!found) { sLog.outErrorDb("Spell (Id: %u) listed in `spell_target_position` does not have target TARGET_TABLE_X_Y_Z_COORDINATES (17).",Spell_ID); continue; } - MapEntry const* mapEntry = sMapStore.LookupEntry(st.target_mapId); - if(!mapEntry) - { - sLog.outErrorDb("Spell (ID:%u) target map (ID: %u) does not exist in `Map.dbc`.",Spell_ID,st.target_mapId); - continue; - } - - if(st.target_X==0 && st.target_Y==0 && st.target_Z==0) - { - sLog.outErrorDb("Spell (ID:%u) target coordinates not provided.",Spell_ID); - continue; - } - mSpellTargetPositions[Spell_ID] = st; ++count; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index b1a55749b..3831476d2 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "9495" + #define REVISION_NR "9496" #endif // __REVISION_NR_H__