diff options
| author | Shauren <shauren.trinity@gmail.com> | 2013-06-15 15:16:36 +0200 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2013-06-15 15:16:36 +0200 |
| commit | fa75fe78bd76e910ab7dfc614bc75f3ce43f9793 (patch) | |
| tree | c58fbf5ca08da0f9726b8045d42a774aaf1fc576 /src/server/game/Entities/Unit | |
| parent | a8a5239aad6f0396948978bdeae0979e7a8dfa97 (diff) | |
Core/Objects
* Split BuildValuesUpdate into separate virtual methods for every object type that does something special with update fields
* Removed _SetCreateBits/_SetUpdateBits to halve the amount of checks if field needs to be sent
Diffstat (limited to 'src/server/game/Entities/Unit')
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 174 | ||||
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 2 |
2 files changed, 176 insertions, 0 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index c10bffbbe92..e274c40e336 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -17549,3 +17549,177 @@ void Unit::ReleaseFocus(Spell const* focusSpell) if (focusSpell->GetSpellInfo()->AttributesEx5 & SPELL_ATTR5_DONT_TURN_DURING_CAST) ClearUnitState(UNIT_STATE_ROTATING); } + +void Unit::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target) const +{ + if (!target) + return; + + ByteBuffer fieldBuffer; + + UpdateMask updateMask; + updateMask.SetCount(m_valuesCount); + + uint32* flags = UnitUpdateFieldFlags; + uint32 visibleFlag = UF_FLAG_PUBLIC; + + if (target == this) + visibleFlag |= UF_FLAG_PRIVATE; + + Player* plr = GetCharmerOrOwnerPlayerOrPlayerItself(); + if (GetOwnerGUID() == target->GetGUID()) + visibleFlag |= UF_FLAG_OWNER; + + if (HasFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_SPECIALINFO)) + if (HasAuraTypeWithCaster(SPELL_AURA_EMPATHY, target->GetGUID())) + visibleFlag |= UF_FLAG_SPECIAL_INFO; + + if (plr && plr->IsInSameRaidWith(target)) + visibleFlag |= UF_FLAG_PARTY_MEMBER; + + Creature const* creature = ToCreature(); + for (uint16 index = 0; index < m_valuesCount; ++index) + { + if (_fieldNotifyFlags & flags[index] || + ((flags[index] & visibleFlag) & UF_FLAG_SPECIAL_INFO) || + ((updateType == UPDATETYPE_VALUES ? _changesMask.GetBit(index) : m_uint32Values[index]) && (flags[index] & visibleFlag)) || + (index == UNIT_FIELD_AURASTATE && HasFlag(UNIT_FIELD_AURASTATE, PER_CASTER_AURA_STATE_MASK))) + { + updateMask.SetBit(index); + + if (index == UNIT_NPC_FLAGS) + { + uint32 appendValue = m_uint32Values[UNIT_NPC_FLAGS]; + + if (creature) + if (!target->CanSeeSpellClickOn(creature)) + appendValue &= ~UNIT_NPC_FLAG_SPELLCLICK; + + fieldBuffer << uint32(appendValue); + } + else if (index == UNIT_FIELD_AURASTATE) + { + // Check per caster aura states to not enable using a spell in client if specified aura is not by target + fieldBuffer << BuildAuraStateUpdateForTarget(target); + } + // FIXME: Some values at server stored in float format but must be sent to client in uint32 format + else if (index >= UNIT_FIELD_BASEATTACKTIME && index <= UNIT_FIELD_RANGEDATTACKTIME) + { + // convert from float to uint32 and send + fieldBuffer << uint32(m_floatValues[index] < 0 ? 0 : m_floatValues[index]); + } + // there are some float values which may be negative or can't get negative due to other checks + else if ((index >= UNIT_FIELD_NEGSTAT0 && index <= UNIT_FIELD_NEGSTAT4) || + (index >= UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE && index <= (UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE + 6)) || + (index >= UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE && index <= (UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE + 6)) || + (index >= UNIT_FIELD_POSSTAT0 && index <= UNIT_FIELD_POSSTAT4)) + { + fieldBuffer << uint32(m_floatValues[index]); + } + // Gamemasters should be always able to select units - remove not selectable flag + else if (index == UNIT_FIELD_FLAGS) + { + uint32 appendValue = m_uint32Values[UNIT_FIELD_FLAGS]; + if (target->IsGameMaster()) + appendValue &= ~UNIT_FLAG_NOT_SELECTABLE; + + fieldBuffer << uint32(appendValue); + } + // use modelid_a if not gm, _h if gm for CREATURE_FLAG_EXTRA_TRIGGER creatures + else if (index == UNIT_FIELD_DISPLAYID) + { + uint32 displayId = m_uint32Values[UNIT_FIELD_DISPLAYID]; + if (creature) + { + CreatureTemplate const* cinfo = creature->GetCreatureTemplate(); + + // this also applies for transform auras + if (SpellInfo const* transform = sSpellMgr->GetSpellInfo(getTransForm())) + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + if (transform->Effects[i].IsAura(SPELL_AURA_TRANSFORM)) + if (CreatureTemplate const* transformInfo = sObjectMgr->GetCreatureTemplate(transform->Effects[i].MiscValue)) + { + cinfo = transformInfo; + break; + } + + if (cinfo->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER) + { + if (target->IsGameMaster()) + { + if (cinfo->Modelid1) + displayId = cinfo->Modelid1; // Modelid1 is a visible model for gms + else + displayId = 17519; // world visible trigger's model + } + else + { + if (cinfo->Modelid2) + displayId = cinfo->Modelid2; // Modelid2 is an invisible model for players + else + displayId = 11686; // world invisible trigger's model + } + } + } + + fieldBuffer << uint32(displayId); + } + // hide lootable animation for unallowed players + else if (index == UNIT_DYNAMIC_FLAGS) + { + uint32 dynamicFlags = m_uint32Values[UNIT_DYNAMIC_FLAGS] & ~(UNIT_DYNFLAG_TAPPED | UNIT_DYNFLAG_TAPPED_BY_PLAYER); + + if (creature) + { + if (creature->hasLootRecipient()) + { + dynamicFlags |= UNIT_DYNFLAG_TAPPED; + if (creature->isTappedBy(target)) + dynamicFlags |= UNIT_DYNFLAG_TAPPED_BY_PLAYER; + } + + if (!target->isAllowedToLoot(creature)) + dynamicFlags &= ~UNIT_DYNFLAG_LOOTABLE; + } + + // unit UNIT_DYNFLAG_TRACK_UNIT should only be sent to caster of SPELL_AURA_MOD_STALKED auras + if (dynamicFlags & UNIT_DYNFLAG_TRACK_UNIT) + if (!HasAuraTypeWithCaster(SPELL_AURA_MOD_STALKED, target->GetGUID())) + dynamicFlags &= ~UNIT_DYNFLAG_TRACK_UNIT; + + fieldBuffer << dynamicFlags; + } + // FG: pretend that OTHER players in own group are friendly ("blue") + else if (index == UNIT_FIELD_BYTES_2 || index == UNIT_FIELD_FACTIONTEMPLATE) + { + if (IsControlledByPlayer() && target != this && sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && IsInRaidWith(target)) + { + FactionTemplateEntry const* ft1 = GetFactionTemplateEntry(); + FactionTemplateEntry const* ft2 = target->GetFactionTemplateEntry(); + if (ft1 && ft2 && !ft1->IsFriendlyTo(*ft2)) + { + if (index == UNIT_FIELD_BYTES_2) + // Allow targetting opposite faction in party when enabled in config + fieldBuffer << (m_uint32Values[UNIT_FIELD_BYTES_2] & ((UNIT_BYTE2_FLAG_SANCTUARY /*| UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5*/) << 8)); // this flag is at uint8 offset 1 !! + else + // pretend that all other HOSTILE players have own faction, to allow follow, heal, rezz (trade wont work) + fieldBuffer << uint32(target->getFaction()); + } + else + fieldBuffer << m_uint32Values[index]; + } + else + fieldBuffer << m_uint32Values[index]; + } + else + { + // send in current format (float as float, uint32 as uint32) + fieldBuffer << m_uint32Values[index]; + } + } + } + + *data << uint8(updateMask.GetBlockCount()); + updateMask.AppendToPacket(data); + data->append(fieldBuffer); +} diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index da954fc9e40..04950cfdcbd 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -2149,6 +2149,8 @@ class Unit : public WorldObject protected: explicit Unit (bool isWorldObject); + void BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, Player* target) const; + UnitAI* i_AI, *i_disabledAI; void _UpdateSpells(uint32 time); |
