[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.
This commit is contained in:
VladimirMangos 2010-03-01 12:52:59 +03:00
parent aa13458b69
commit 4a051e2443
9 changed files with 116 additions and 66 deletions

View file

@ -425,38 +425,12 @@ void WorldSession::SendBindPoint(Creature *npc)
if(GetPlayer()->GetMap()->Instanceable()) if(GetPlayer()->GetMap()->Instanceable())
return; return;
uint32 bindspell = 3286;
uint32 zone_id = _player->GetZoneId();
_player->SetHomebindToCurrentPos();
// send spell for bind 3286 bind magic // 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)); WorldPacket data( SMSG_TRAINER_BUY_SUCCEEDED, (8+4));
data << npc->GetGUID(); data << uint64(npc->GetGUID());
data << bindspell; data << uint32(3286); // Bind
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);
SendPacket( &data ); SendPacket( &data );
_player->PlayerTalkClass->CloseGossip(); _player->PlayerTalkClass->CloseGossip();

View file

@ -2333,7 +2333,7 @@ void ObjectMgr::LoadPlayerInfo()
uint32 current_race = fields[0].GetUInt32(); uint32 current_race = fields[0].GetUInt32();
uint32 current_class = fields[1].GetUInt32(); uint32 current_class = fields[1].GetUInt32();
uint32 mapId = fields[2].GetUInt32(); uint32 mapId = fields[2].GetUInt32();
uint32 zoneId = fields[3].GetUInt32(); uint32 areaId = fields[3].GetUInt32();
float positionX = fields[4].GetFloat(); float positionX = fields[4].GetFloat();
float positionY = fields[5].GetFloat(); float positionY = fields[5].GetFloat();
float positionZ = fields[6].GetFloat(); float positionZ = fields[6].GetFloat();
@ -2379,7 +2379,7 @@ void ObjectMgr::LoadPlayerInfo()
PlayerInfo* pInfo = &playerInfo[current_race][current_class]; PlayerInfo* pInfo = &playerInfo[current_race][current_class];
pInfo->mapId = mapId; pInfo->mapId = mapId;
pInfo->zoneId = zoneId; pInfo->areaId = areaId;
pInfo->positionX = positionX; pInfo->positionX = positionX;
pInfo->positionY = positionY; pInfo->positionY = positionY;
pInfo->positionZ = positionZ; pInfo->positionZ = positionZ;

View file

@ -16095,7 +16095,7 @@ bool Player::_LoadHomeBind(QueryResult *result)
{ {
Field *fields = result->Fetch(); Field *fields = result->Fetch();
m_homebindMapId = fields[0].GetUInt32(); m_homebindMapId = fields[0].GetUInt32();
m_homebindZoneId = fields[1].GetUInt16(); m_homebindAreaId = fields[1].GetUInt16();
m_homebindX = fields[2].GetFloat(); m_homebindX = fields[2].GetFloat();
m_homebindY = fields[3].GetFloat(); m_homebindY = fields[3].GetFloat();
m_homebindZ = fields[4].GetFloat(); m_homebindZ = fields[4].GetFloat();
@ -16116,16 +16116,16 @@ bool Player::_LoadHomeBind(QueryResult *result)
if(!ok) if(!ok)
{ {
m_homebindMapId = info->mapId; m_homebindMapId = info->mapId;
m_homebindZoneId = info->zoneId; m_homebindAreaId = info->areaId;
m_homebindX = info->positionX; m_homebindX = info->positionX;
m_homebindY = info->positionY; m_homebindY = info->positionY;
m_homebindZ = info->positionZ; 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", 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; return true;
} }
@ -18901,7 +18901,7 @@ void Player::SendInitialPacketsBeforeAddToMap()
WorldPacket data(SMSG_BINDPOINTUPDATE, 5*4); WorldPacket data(SMSG_BINDPOINTUPDATE, 5*4);
data << m_homebindX << m_homebindY << m_homebindZ; data << m_homebindX << m_homebindY << m_homebindZ;
data << (uint32) m_homebindMapId; data << (uint32) m_homebindMapId;
data << (uint32) m_homebindZoneId; data << (uint32) m_homebindAreaId;
GetSession()->SendPacket(&data); GetSession()->SendPacket(&data);
// SMSG_SET_PROFICIENCY // SMSG_SET_PROFICIENCY
@ -21549,16 +21549,17 @@ bool Player::IsImmunedToSpellEffect(SpellEntry const* spellInfo, SpellEffectInde
return Unit::IsImmunedToSpellEffect(spellInfo, index); return Unit::IsImmunedToSpellEffect(spellInfo, index);
} }
void Player::SetHomebindToCurrentPos() void Player::SetHomebindToLocation(WorldLocation const& loc, uint32 area_id)
{ {
m_homebindMapId = GetMapId(); m_homebindMapId = loc.mapid;
m_homebindZoneId = GetZoneId(); m_homebindAreaId = area_id;
m_homebindX = GetPositionX(); m_homebindX = loc.coord_x;
m_homebindY = GetPositionY(); m_homebindY = loc.coord_y;
m_homebindZ = GetPositionZ(); m_homebindZ = loc.coord_z;
// update sql homebind // 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'", 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());
} }

View file

@ -289,7 +289,7 @@ struct PlayerInfo
} }
uint32 mapId; uint32 mapId;
uint32 zoneId; uint32 areaId;
float positionX; float positionX;
float positionY; float positionY;
float positionZ; float positionZ;
@ -2168,7 +2168,7 @@ class MANGOS_DLL_SPEC Player : public Unit
float m_recallO; float m_recallO;
void SaveRecallPosition(); void SaveRecallPosition();
void SetHomebindToCurrentPos(); void SetHomebindToLocation(WorldLocation const& loc, uint32 area_id);
void RelocateToHomebind() { SetLocationMapId(m_homebindMapId); Relocate(m_homebindX, m_homebindY, m_homebindZ); } 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); } 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 // Homebind coordinates
uint32 m_homebindMapId; uint32 m_homebindMapId;
uint16 m_homebindZoneId; uint16 m_homebindAreaId;
float m_homebindX; float m_homebindX;
float m_homebindY; float m_homebindY;
float m_homebindZ; float m_homebindZ;

View file

@ -2258,6 +2258,7 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList&
} }
break; break;
} }
case SPELL_EFFECT_BIND:
case SPELL_EFFECT_RESURRECT: case SPELL_EFFECT_RESURRECT:
case SPELL_EFFECT_PARRY: case SPELL_EFFECT_PARRY:
case SPELL_EFFECT_BLOCK: case SPELL_EFFECT_BLOCK:

View file

@ -217,6 +217,7 @@ class Spell
friend void Unit::SetCurrentCastedSpell( Spell * pSpell ); friend void Unit::SetCurrentCastedSpell( Spell * pSpell );
public: public:
void EffectEmpty(SpellEffectIndex eff_idx);
void EffectNULL(SpellEffectIndex eff_idx); void EffectNULL(SpellEffectIndex eff_idx);
void EffectUnused(SpellEffectIndex eff_idx); void EffectUnused(SpellEffectIndex eff_idx);
void EffectDistract(SpellEffectIndex eff_idx); void EffectDistract(SpellEffectIndex eff_idx);
@ -231,6 +232,7 @@ class Spell
void EffectPowerBurn(SpellEffectIndex eff_idx); void EffectPowerBurn(SpellEffectIndex eff_idx);
void EffectPowerDrain(SpellEffectIndex eff_idx); void EffectPowerDrain(SpellEffectIndex eff_idx);
void EffectHeal(SpellEffectIndex eff_idx); void EffectHeal(SpellEffectIndex eff_idx);
void EffectBind(SpellEffectIndex eff_idx);
void EffectHealthLeech(SpellEffectIndex eff_idx); void EffectHealthLeech(SpellEffectIndex eff_idx);
void EffectQuestComplete(SpellEffectIndex eff_idx); void EffectQuestComplete(SpellEffectIndex eff_idx);
void EffectCreateItem(SpellEffectIndex eff_idx); void EffectCreateItem(SpellEffectIndex eff_idx);

View file

@ -68,7 +68,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectPowerDrain, // 8 SPELL_EFFECT_POWER_DRAIN &Spell::EffectPowerDrain, // 8 SPELL_EFFECT_POWER_DRAIN
&Spell::EffectHealthLeech, // 9 SPELL_EFFECT_HEALTH_LEECH &Spell::EffectHealthLeech, // 9 SPELL_EFFECT_HEALTH_LEECH
&Spell::EffectHeal, // 10 SPELL_EFFECT_HEAL &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::EffectNULL, // 12 SPELL_EFFECT_PORTAL
&Spell::EffectUnused, // 13 SPELL_EFFECT_RITUAL_BASE unused &Spell::EffectUnused, // 13 SPELL_EFFECT_RITUAL_BASE unused
&Spell::EffectUnused, // 14 SPELL_EFFECT_RITUAL_SPECIALIZE 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 &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*/) void Spell::EffectNULL(SpellEffectIndex /*eff_idx*/)
{ {
sLog.outDebug("WORLD: Spell Effect DUMMY"); sLog.outDebug("WORLD: Spell Effect DUMMY");
@ -7372,3 +7377,59 @@ void Spell::EffectActivateSpec(SpellEffectIndex /*eff_idx*/)
((Player*)unitTarget)->ActivateSpec(spec); ((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 );
}

View file

@ -795,7 +795,7 @@ void SpellMgr::LoadSpellTargetPositions()
// 0 1 2 3 4 5 // 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"); 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 ); barGoLink bar( 1 );
@ -807,7 +807,7 @@ void SpellMgr::LoadSpellTargetPositions()
return; return;
} }
barGoLink bar( (int)result->GetRowCount() ); barGoLink bar((int)result->GetRowCount());
do do
{ {
@ -825,8 +825,21 @@ void SpellMgr::LoadSpellTargetPositions()
st.target_Z = fields[4].GetFloat(); st.target_Z = fields[4].GetFloat();
st.target_Orientation = fields[5].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); 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); sLog.outErrorDb("Spell (ID:%u) listed in `spell_target_position` does not exist.",Spell_ID);
continue; continue;
@ -835,31 +848,29 @@ void SpellMgr::LoadSpellTargetPositions()
bool found = false; bool found = false;
for(int i = 0; i < MAX_EFFECT_INDEX; ++i) 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; found = true;
break; 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); sLog.outErrorDb("Spell (Id: %u) listed in `spell_target_position` does not have target TARGET_TABLE_X_Y_Z_COORDINATES (17).",Spell_ID);
continue; 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; mSpellTargetPositions[Spell_ID] = st;
++count; ++count;

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "9495" #define REVISION_NR "9496"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__