[11443] Implement SPELL_AURA_MIRROR_IMAGE (247) and related receive/reply packets

Inspired by different patches posted in forum, thanks guys for the help it was :D

Signed-off-by: NoFantasy <nofantasy@nf.no>
This commit is contained in:
NoFantasy 2011-05-08 18:57:06 +02:00
parent d98b9b9670
commit 4c3b61d4f5
11 changed files with 160 additions and 6 deletions

View file

@ -1051,8 +1051,8 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
/*0x3FE*/ { "MSG_GUILD_BANK_MONEY_WITHDRAWN", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankMoneyWithdrawn },
/*0x3FF*/ { "MSG_GUILD_EVENT_LOG_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildEventLogQueryOpcode },
/*0x400*/ { "CMSG_MAELSTROM_RENAME_GUILD", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
/*0x401*/ { "CMSG_GET_MIRRORIMAGE_DATA", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
/*0x402*/ { "SMSG_MIRRORIMAGE_DATA", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x401*/ { "CMSG_GET_MIRRORIMAGE_DATA", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleGetMirrorimageData },
/*0x402*/ { "SMSG_MIRRORIMAGE_DATA", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x403*/ { "SMSG_FORCE_DISPLAY_UPDATE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x404*/ { "SMSG_SPELL_CHANCE_RESIST_PUSHBACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x405*/ { "CMSG_IGNORE_DIMINISHING_RETURNS_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },

View file

@ -9183,6 +9183,16 @@ Item* Player::GetItemByPos( uint8 bag, uint8 slot ) const
return NULL;
}
uint32 Player::GetItemDisplayIdInSlot(uint8 bag, uint8 slot) const
{
const Item* pItem = GetItemByPos(bag, slot);
if (!pItem)
return 0;
return pItem->GetProto()->DisplayInfoID;
}
Item* Player::GetWeaponForAttack(WeaponAttackType attackType, bool nonbroken, bool useable) const
{
uint8 slot;

View file

@ -1178,6 +1178,7 @@ class MANGOS_DLL_SPEC Player : public Unit
Item* GetItemByLimitedCategory(uint32 limitedCategory) const;
Item* GetItemByPos( uint16 pos ) const;
Item* GetItemByPos( uint8 bag, uint8 slot ) const;
uint32 GetItemDisplayIdInSlot(uint8 bag, uint8 slot) const;
Item* GetWeaponForAttack(WeaponAttackType attackType) const { return GetWeaponForAttack(attackType,false,false); }
Item* GetWeaponForAttack(WeaponAttackType attackType, bool nonbroken, bool useable) const;
Item* GetShield(bool useable = false) const;

View file

@ -5531,6 +5531,25 @@ SpellCastResult Spell::CheckCast(bool strict)
break;
}
case SPELL_AURA_MIRROR_IMAGE:
{
Unit* pTarget = m_targets.getUnitTarget();
if (!pTarget)
return SPELL_FAILED_BAD_TARGETS;
if (pTarget->GetTypeId() != TYPEID_UNIT) // Target must be creature
return SPELL_FAILED_BAD_TARGETS;
if (pTarget == m_caster) // Clone self can't be accepted
return SPELL_FAILED_BAD_TARGETS;
// It is assumed that target can not be cloned if already cloned by same or other clone auras
if (!pTarget->GetAurasByType(SPELL_AURA_MIRROR_IMAGE).empty())
return SPELL_FAILED_BAD_TARGETS;
break;
}
default:
break;
}

View file

@ -282,7 +282,7 @@ enum AuraType
SPELL_AURA_COMPREHEND_LANGUAGE = 244,
SPELL_AURA_MOD_DURATION_OF_MAGIC_EFFECTS = 245,
SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL = 246,
SPELL_AURA_247 = 247,
SPELL_AURA_MIRROR_IMAGE = 247,
SPELL_AURA_MOD_COMBAT_RESULT_CHANCE = 248,
SPELL_AURA_CONVERT_RUNE = 249,
SPELL_AURA_MOD_INCREASE_HEALTH_2 = 250,

View file

@ -297,7 +297,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
&Aura::HandleComprehendLanguage, //244 SPELL_AURA_COMPREHEND_LANGUAGE
&Aura::HandleNoImmediateEffect, //245 SPELL_AURA_MOD_DURATION_OF_MAGIC_EFFECTS implemented in Unit::CalculateAuraDuration
&Aura::HandleNoImmediateEffect, //246 SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL implemented in Unit::CalculateAuraDuration
&Aura::HandleNULL, //247 target to become a clone of the caster
&Aura::HandleAuraMirrorImage, //247 SPELL_AURA_MIRROR_IMAGE target to become a clone of the caster
&Aura::HandleNoImmediateEffect, //248 SPELL_AURA_MOD_COMBAT_RESULT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst
&Aura::HandleAuraConvertRune, //249 SPELL_AURA_CONVERT_RUNE
&Aura::HandleAuraModIncreaseHealth, //250 SPELL_AURA_MOD_INCREASE_HEALTH_2
@ -8032,6 +8032,44 @@ void Aura::HandleAuraOpenStable(bool apply, bool Real)
// client auto close stable dialog at !apply aura
}
void Aura::HandleAuraMirrorImage(bool apply, bool Real)
{
if (!Real)
return;
// Target of aura should always be creature (ref Spell::CheckCast)
Creature* pCreature = (Creature*)GetTarget();
// Caster can be player or creature, the unit who pCreature will become an clone of.
Unit* caster = GetCaster();
if (apply)
{
pCreature->SetByteValue(UNIT_FIELD_BYTES_0, 0, caster->getRace());
pCreature->SetByteValue(UNIT_FIELD_BYTES_0, 1, caster->getClass());
pCreature->SetByteValue(UNIT_FIELD_BYTES_0, 2, caster->getGender());
pCreature->SetByteValue(UNIT_FIELD_BYTES_0, 3, caster->getPowerType());
pCreature->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_CLONED);
pCreature->SetDisplayId(caster->GetNativeDisplayId());
}
else
{
const CreatureInfo* cinfo = pCreature->GetCreatureInfo();
const CreatureModelInfo* minfo = sObjectMgr.GetCreatureModelInfo(pCreature->GetNativeDisplayId());
pCreature->SetByteValue(UNIT_FIELD_BYTES_0, 0, 0);
pCreature->SetByteValue(UNIT_FIELD_BYTES_0, 1, cinfo->unit_class);
pCreature->SetByteValue(UNIT_FIELD_BYTES_0, 2, minfo->gender);
pCreature->SetByteValue(UNIT_FIELD_BYTES_0, 3, 0);
pCreature->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_CLONED);
pCreature->SetDisplayId(pCreature->GetNativeDisplayId());
}
}
void Aura::HandleAuraConvertRune(bool apply, bool Real)
{
if(!Real)

View file

@ -362,6 +362,7 @@ class MANGOS_DLL_SPEC Aura
void HandlePreventFleeing(bool apply, bool Real);
void HandleManaShield(bool apply, bool Real);
void HandleArenaPreparation(bool apply, bool Real);
void HandleAuraMirrorImage(bool apply, bool Real);
void HandleAuraConvertRune(bool apply, bool Real);
void HandleAuraIncreaseBaseHealthPercent(bool Apply, bool Real);
void HandleNoReagentUseAura(bool Apply, bool Real);

View file

@ -609,3 +609,87 @@ void WorldSession::HandleSpellClick( WorldPacket & recv_data )
}
}
}
void WorldSession::HandleGetMirrorimageData(WorldPacket& recv_data)
{
DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "WORLD: CMSG_GET_MIRRORIMAGE_DATA");
ObjectGuid guid;
recv_data >> guid;
Creature* pCreature = _player->GetMap()->GetAnyTypeCreature(guid);
if (!pCreature)
return;
Unit::AuraList const& images = pCreature->GetAurasByType(SPELL_AURA_MIRROR_IMAGE);
if (images.empty())
return;
Unit* pCaster = images.front()->GetCaster();
WorldPacket data(SMSG_MIRRORIMAGE_DATA, 68);
data << guid;
data << (uint32)pCreature->GetDisplayId();
data << (uint8)pCreature->getRace();
data << (uint8)pCreature->getGender();
data << (uint8)pCreature->getClass();
if (pCaster->GetTypeId() == TYPEID_PLAYER)
{
Player* pPlayer = (Player*)pCaster;
// skin, face, hair, haircolor
data << (uint8)pPlayer->GetByteValue(PLAYER_BYTES, 0);
data << (uint8)pPlayer->GetByteValue(PLAYER_BYTES, 1);
data << (uint8)pPlayer->GetByteValue(PLAYER_BYTES, 2);
data << (uint8)pPlayer->GetByteValue(PLAYER_BYTES, 3);
// facial hair
data << (uint8)pPlayer->GetByteValue(PLAYER_BYTES_2, 0);
// guild id
data << (uint32)pPlayer->GetGuildId();
if (pPlayer->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_HELM))
data << (uint32)0;
else
data << (uint32)pPlayer->GetItemDisplayIdInSlot(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_HEAD);
data << (uint32)pPlayer->GetItemDisplayIdInSlot(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_SHOULDERS);
data << (uint32)pPlayer->GetItemDisplayIdInSlot(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_BODY);
data << (uint32)pPlayer->GetItemDisplayIdInSlot(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_CHEST);
data << (uint32)pPlayer->GetItemDisplayIdInSlot(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_WAIST);
data << (uint32)pPlayer->GetItemDisplayIdInSlot(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_LEGS);
data << (uint32)pPlayer->GetItemDisplayIdInSlot(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_FEET);
data << (uint32)pPlayer->GetItemDisplayIdInSlot(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_WRISTS);
data << (uint32)pPlayer->GetItemDisplayIdInSlot(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_HANDS);
if (pPlayer->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_CLOAK))
data << (uint32)0;
else
data << (uint32)pPlayer->GetItemDisplayIdInSlot(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_BACK);
data << (uint32)pPlayer->GetItemDisplayIdInSlot(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_TABARD);
}
else
{
// No data when cloner is not player, data is taken from CreatureDisplayInfoExtraEntry by model already
data << (uint8)0;
data << (uint8)0;
data << (uint8)0;
data << (uint8)0;
data << (uint8)0;
data << (uint32)0;
for (int i = 0; i < 11; ++i)
data << (uint32)0;
}
SendPacket(&data);
}

View file

@ -547,7 +547,7 @@ enum UnitFlags2
UNIT_FLAG2_UNK1 = 0x00000002, // Hides body and body armor. Weapons and shoulder and head armor still visible
UNIT_FLAG2_UNK2 = 0x00000004,
UNIT_FLAG2_COMPREHEND_LANG = 0x00000008,
UNIT_FLAG2_UNK4 = 0x00000010,
UNIT_FLAG2_CLONED = 0x00000010, // Used in SPELL_AURA_MIRROR_IMAGE
UNIT_FLAG2_UNK5 = 0x00000020,
UNIT_FLAG2_FORCE_MOVE = 0x00000040,
UNIT_FLAG2_DISARM_OFFHAND = 0x00000080, // also shield case

View file

@ -840,6 +840,7 @@ class MANGOS_DLL_SPEC WorldSession
void HandleCalendarGetNumPending(WorldPacket& recv_data);
void HandleSpellClick(WorldPacket& recv_data);
void HandleGetMirrorimageData(WorldPacket& recv_data);
void HandleAlterAppearanceOpcode(WorldPacket& recv_data);
void HandleRemoveGlyphOpcode(WorldPacket& recv_data);
void HandleCharCustomizeOpcode(WorldPacket& recv_data);

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "11442"
#define REVISION_NR "11443"
#endif // __REVISION_NR_H__