From 2949a2514c431b484f250e55832be2dc2eeedb17 Mon Sep 17 00:00:00 2001 From: hondacrx Date: Thu, 4 Mar 2021 12:00:39 -0500 Subject: [PATCH] Core/Creatures: Implemented extra flag to use offhand attacks Port From (https://github.com/TrinityCore/TrinityCore/commit/2a51edc5bcebe40c114e37ef3b24da6c8f095892) --- Source/Framework/Constants/CreatureConst.cs | 22 ++++++------ Source/Game/Entities/Creature/Creature.cs | 38 ++++++++++++--------- Source/Game/Entities/Unit/Unit.Combat.cs | 4 +-- 3 files changed, 34 insertions(+), 30 deletions(-) diff --git a/Source/Framework/Constants/CreatureConst.cs b/Source/Framework/Constants/CreatureConst.cs index 5ab0bdfc6..f2cd193c6 100644 --- a/Source/Framework/Constants/CreatureConst.cs +++ b/Source/Framework/Constants/CreatureConst.cs @@ -209,9 +209,9 @@ namespace Framework.Constants NoTaunt = 0x100, // Creature Is Immune To Taunt Auras And Effect Attack Me NoMoveFlagsUpdate = 0x200, // Creature won't update movement flags GhostVisibility = 0x400, // creature will be only visible for dead players - Unused11 = 0x00000800, - Unused12 = 0x00001000, - Unused13 = 0x00002000, + UseOffhandAttack = 0x800, // creature will use offhand attacks + Unused12 = 0x1000, + Unused13 = 0x2000, Worldevent = 0x4000, // Custom Flag For World Event Creatures (Left Room For Merging) Guard = 0x8000, // Creature Is Guard Unused16 = 0x00010000, @@ -220,21 +220,21 @@ namespace Framework.Constants TauntDiminish = 0x80000, // Taunt Is A Subject To Diminishing Returns On This Creautre AllDiminish = 0x100000, // Creature Is Subject To All Diminishing Returns As Player Are NoPlayerDamageReq = 0x200000, // creature does not need to take player damage for kill credit - Unused22 = 0x00400000, - Unused23 = 0x00800000, - Unused24 = 0x01000000, - Unused25 = 0x02000000, - Unused26 = 0x04000000, - Unused27 = 0x08000000, + Unused22 = 0x400000, + Unused23 = 0x800000, + Unused24 = 0x1000000, + Unused25 = 0x2000000, + Unused26 = 0x4000000, + Unused27 = 0x8000000, DungeonBoss = 0x10000000, // Creature Is A Dungeon Boss (Set Dynamically, Do Not Add In Db) IgnorePathfinding = 0x20000000, // creature ignore pathfinding ImmunityKnockback = 0x40000000, // creature is immune to knockback effects Unused31 = 0x80000000, // Masks - AllUnused = (Unused11 | Unused12 | Unused13 | Unused16 | Unused22 | Unused23 | Unused24 | Unused25 | Unused26 | Unused27 | Unused31), + AllUnused = (Unused12 | Unused13 | Unused16 | Unused22 | Unused23 | Unused24 | Unused25 | Unused26 | Unused27 | Unused31), - DBAllowed = (0xFFFFFFFF & ~(AllUnused | CreatureFlagsExtra.DungeonBoss)) + DBAllowed = (0xFFFFFFFF & ~(AllUnused | DungeonBoss)) } public enum CreatureType diff --git a/Source/Game/Entities/Creature/Creature.cs b/Source/Game/Entities/Creature/Creature.cs index 79abcab11..cb78cd491 100644 --- a/Source/Game/Entities/Creature/Creature.cs +++ b/Source/Game/Entities/Creature/Creature.cs @@ -234,9 +234,9 @@ namespace Game.Entities } // get difficulty 1 mode entry - CreatureTemplate cinfo = null; + CreatureTemplate cInfo = null; DifficultyRecord difficultyEntry = CliDB.DifficultyStorage.LookupByKey(GetMap().GetDifficultyID()); - while (cinfo == null && difficultyEntry != null) + while (cInfo == null && difficultyEntry != null) { int idx = CreatureTemplate.DifficultyIDToDifficultyEntryIndex(difficultyEntry.Id); if (idx == -1) @@ -244,7 +244,7 @@ namespace Game.Entities if (normalInfo.DifficultyEntry[idx] != 0) { - cinfo = Global.ObjectMgr.GetCreatureTemplate(normalInfo.DifficultyEntry[idx]); + cInfo = Global.ObjectMgr.GetCreatureTemplate(normalInfo.DifficultyEntry[idx]); break; } @@ -254,29 +254,29 @@ namespace Game.Entities difficultyEntry = CliDB.DifficultyStorage.LookupByKey(difficultyEntry.FallbackDifficultyID); } - if (cinfo == null) - cinfo = normalInfo; + if (cInfo == null) + cInfo = normalInfo; // Initialize loot duplicate count depending on raid difficulty if (GetMap().Is25ManRaid()) loot.maxDuplicates = 3; SetEntry(entry); // normal entry always - m_creatureInfo = cinfo; // map mode related always + m_creatureInfo = cInfo; // map mode related always // equal to player Race field, but creature does not have race SetRace(0); - SetClass((Class)cinfo.UnitClass); + SetClass((Class)cInfo.UnitClass); // Cancel load if no model defined - if (cinfo.GetFirstValidModel() == null) + if (cInfo.GetFirstValidModel() == null) { Log.outError(LogFilter.Sql, "Creature (Entry: {0}) has no model defined in table `creature_template`, can't load. ", entry); return false; } - CreatureModel model = ObjectManager.ChooseDisplayId(cinfo, data); - CreatureModelInfo minfo = Global.ObjectMgr.GetCreatureModelRandomGender(ref model, cinfo); + CreatureModel model = ObjectManager.ChooseDisplayId(cInfo, data); + CreatureModelInfo minfo = Global.ObjectMgr.GetCreatureModelRandomGender(ref model, cInfo); if (minfo == null) // Cancel load if no model defined { Log.outError(LogFilter.Sql, "Creature (Entry: {0}) has invalid model {1} defined in table `creature_template`, can't load.", entry, model.CreatureDisplayID); @@ -289,9 +289,9 @@ namespace Game.Entities // Load creature equipment if (data == null || data.equipmentId == 0) LoadEquipment(); // use default equipment (if available) - else if(data != null && data.equipmentId != 0) // override, 0 means no equipment + else { - m_originalEquipmentId = (sbyte)data.equipmentId; + m_originalEquipmentId = data.equipmentId; LoadEquipment(data.equipmentId); } @@ -304,17 +304,19 @@ namespace Game.Entities SetModHasteRegen(1.0f); SetModTimeRate(1.0f); - SetSpeedRate(UnitMoveType.Walk, cinfo.SpeedWalk); - SetSpeedRate(UnitMoveType.Run, cinfo.SpeedRun); + SetSpeedRate(UnitMoveType.Walk, cInfo.SpeedWalk); + SetSpeedRate(UnitMoveType.Run, cInfo.SpeedRun); SetSpeedRate(UnitMoveType.Swim, 1.0f); // using 1.0 rate SetSpeedRate(UnitMoveType.Flight, 1.0f); // using 1.0 rate - SetObjectScale(cinfo.Scale); + SetObjectScale(cInfo.Scale); - SetHoverHeight(cinfo.HoverHeight); + SetHoverHeight(cInfo.HoverHeight); + + SetCanDualWield(cInfo.FlagsExtra.HasAnyFlag(CreatureFlagsExtra.UseOffhandAttack)); // checked at loading - DefaultMovementType = (MovementGeneratorType)(data != null ? data.movementType : cinfo.MovementType); + DefaultMovementType = (MovementGeneratorType)(data != null ? data.movementType : cInfo.MovementType); if (m_respawnradius == 0 && DefaultMovementType == MovementGeneratorType.Random) DefaultMovementType = MovementGeneratorType.Idle; @@ -362,6 +364,8 @@ namespace Game.Entities SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.StateAnimID), Global.DB2Mgr.GetEmptyAnimStateID()); + SetCanDualWield(cInfo.FlagsExtra.HasAnyFlag(CreatureFlagsExtra.UseOffhandAttack)); + SetBaseAttackTime(WeaponAttackType.BaseAttack, cInfo.BaseAttackTime); SetBaseAttackTime(WeaponAttackType.OffAttack, cInfo.BaseAttackTime); SetBaseAttackTime(WeaponAttackType.RangedAttack, cInfo.RangeAttackTime); diff --git a/Source/Game/Entities/Unit/Unit.Combat.cs b/Source/Game/Entities/Unit/Unit.Combat.cs index 7a2102f50..c7114b2d7 100644 --- a/Source/Game/Entities/Unit/Unit.Combat.cs +++ b/Source/Game/Entities/Unit/Unit.Combat.cs @@ -467,9 +467,9 @@ namespace Game.Entities SetEmoteState(Emote.OneshotNone); } - // delay offhand weapon attack to next attack time + // delay offhand weapon attack by 50% of the base attack time if (HaveOffhandWeapon() && GetTypeId() != TypeId.Player) - ResetAttackTimer(WeaponAttackType.OffAttack); + SetAttackTimer(WeaponAttackType.OffAttack, Math.Max(GetAttackTimer(WeaponAttackType.OffAttack), GetAttackTimer(WeaponAttackType.BaseAttack) + MathFunctions.CalculatePct(GetBaseAttackTime(WeaponAttackType.BaseAttack), 50))); if (meleeAttack) SendMeleeAttackStart(victim);