List <GarrAbilityRecord> GetClassSpecAbilities(GarrFollowerRecord follower, uint faction) { List <GarrAbilityRecord> abilities = new List <GarrAbilityRecord>(); uint classSpecId; switch (faction) { case GarrisonFactionIndex.Horde: classSpecId = follower.HordeGarrClassSpecID; break; case GarrisonFactionIndex.Alliance: classSpecId = follower.AllianceGarrClassSpecID; break; default: return(abilities); } if (!CliDB.GarrClassSpecStorage.ContainsKey(classSpecId)) { return(abilities); } var garrAbility = _garrisonFollowerClassSpecAbilities.LookupByKey(classSpecId); if (!garrAbility.Empty()) { abilities = garrAbility; } return(abilities); }
public void AddFollower(uint garrFollowerId) { GarrisonAddFollowerResult addFollowerResult = new(); addFollowerResult.GarrTypeID = GetGarrisonType(); GarrFollowerRecord followerEntry = CliDB.GarrFollowerStorage.LookupByKey(garrFollowerId); if (_followerIds.Contains(garrFollowerId) || followerEntry == null) { addFollowerResult.Result = GarrisonError.FollowerExists; _owner.SendPacket(addFollowerResult); return; } _followerIds.Add(garrFollowerId); ulong dbId = Global.GarrisonMgr.GenerateFollowerDbId(); Follower follower = new(); follower.PacketInfo.DbID = dbId; follower.PacketInfo.GarrFollowerID = garrFollowerId; follower.PacketInfo.Quality = (uint)followerEntry.Quality; // TODO: handle magic upgrades follower.PacketInfo.FollowerLevel = followerEntry.FollowerLevel; follower.PacketInfo.ItemLevelWeapon = followerEntry.ItemLevelWeapon; follower.PacketInfo.ItemLevelArmor = followerEntry.ItemLevelArmor; follower.PacketInfo.Xp = 0; follower.PacketInfo.CurrentBuildingID = 0; follower.PacketInfo.CurrentMissionID = 0; follower.PacketInfo.AbilityID = Global.GarrisonMgr.RollFollowerAbilities(garrFollowerId, followerEntry, follower.PacketInfo.Quality, GetFaction(), true); follower.PacketInfo.FollowerStatus = 0; _followers[dbId] = follower; addFollowerResult.Follower = follower.PacketInfo; _owner.SendPacket(addFollowerResult); _owner.UpdateCriteria(CriteriaType.RecruitGarrisonFollower, follower.PacketInfo.DbID); }
//todo check this method, might be slow..... public List <GarrAbilityRecord> RollFollowerAbilities(uint garrFollowerId, GarrFollowerRecord follower, uint quality, uint faction, bool initial) { Cypher.Assert(faction < 2); bool hasForcedExclusiveTrait = false; List <GarrAbilityRecord> result = new List <GarrAbilityRecord>(); uint[] slots = { AbilitiesForQuality[quality, 0], AbilitiesForQuality[quality, 1] }; GarrAbilities garrAbilities = null; var abilities = _garrisonFollowerAbilities[faction].LookupByKey(garrFollowerId); if (abilities != null) { garrAbilities = abilities; } List <GarrAbilityRecord> abilityList = new List <GarrAbilityRecord>(); List <GarrAbilityRecord> forcedAbilities = new List <GarrAbilityRecord>(); List <GarrAbilityRecord> traitList = new List <GarrAbilityRecord>(); List <GarrAbilityRecord> forcedTraits = new List <GarrAbilityRecord>(); if (garrAbilities != null) { foreach (GarrAbilityRecord ability in garrAbilities.Counters) { if (ability.Flags.HasAnyFlag(GarrisonAbilityFlags.HordeOnly) && faction != GarrisonFactionIndex.Horde) { continue; } else if (ability.Flags.HasAnyFlag(GarrisonAbilityFlags.AllianceOnly) && faction != GarrisonFactionIndex.Alliance) { continue; } if (ability.Flags.HasAnyFlag(GarrisonAbilityFlags.CannotRemove)) { forcedAbilities.Add(ability); } else { abilityList.Add(ability); } } foreach (GarrAbilityRecord ability in garrAbilities.Traits) { if (ability.Flags.HasAnyFlag(GarrisonAbilityFlags.HordeOnly) && faction != GarrisonFactionIndex.Horde) { continue; } else if (ability.Flags.HasAnyFlag(GarrisonAbilityFlags.AllianceOnly) && faction != GarrisonFactionIndex.Alliance) { continue; } if (ability.Flags.HasAnyFlag(GarrisonAbilityFlags.CannotRemove)) { forcedTraits.Add(ability); } else { traitList.Add(ability); } } } abilityList.RandomResize((uint)Math.Max(0, slots[0] - forcedAbilities.Count)); traitList.RandomResize((uint)Math.Max(0, slots[1] - forcedTraits.Count)); // Add abilities specified in GarrFollowerXAbility.db2 before generic classspec ones on follower creation if (initial) { forcedAbilities.AddRange(abilityList); forcedTraits.AddRange(traitList); } forcedAbilities.Sort(); abilityList.Sort(); forcedTraits.Sort(); traitList.Sort(); // check if we have a trait from exclusive category foreach (GarrAbilityRecord ability in forcedTraits) { if (ability.Flags.HasAnyFlag(GarrisonAbilityFlags.Exclusive)) { hasForcedExclusiveTrait = true; break; } } if (slots[0] > forcedAbilities.Count + abilityList.Count) { List <GarrAbilityRecord> classSpecAbilities = GetClassSpecAbilities(follower, faction); IEnumerable <GarrAbilityRecord> classSpecAbilitiesTemp = classSpecAbilities.Except(forcedAbilities); abilityList = classSpecAbilitiesTemp.Union(abilityList).ToList(); abilityList.RandomResize((uint)Math.Max(0, slots[0] - forcedAbilities.Count)); } if (slots[1] > forcedTraits.Count + traitList.Count) { List <GarrAbilityRecord> genericTraitsTemp = new List <GarrAbilityRecord>(); foreach (GarrAbilityRecord ability in _garrisonFollowerRandomTraits) { if (ability.Flags.HasAnyFlag(GarrisonAbilityFlags.HordeOnly) && faction != GarrisonFactionIndex.Horde) { continue; } else if (ability.Flags.HasAnyFlag(GarrisonAbilityFlags.AllianceOnly) && faction != GarrisonFactionIndex.Alliance) { continue; } // forced exclusive trait exists, skip other ones entirely if (hasForcedExclusiveTrait && ability.Flags.HasAnyFlag(GarrisonAbilityFlags.Exclusive)) { continue; } genericTraitsTemp.Add(ability); } List <GarrAbilityRecord> genericTraits = genericTraitsTemp.Except(forcedTraits).ToList(); genericTraits.AddRange(traitList); genericTraits.Sort((GarrAbilityRecord a1, GarrAbilityRecord a2) => { int e1 = (int)(a1.Flags & GarrisonAbilityFlags.Exclusive); int e2 = (int)(a2.Flags & GarrisonAbilityFlags.Exclusive); if (e1 != e2) { return(e1.CompareTo(e2)); } return(a1.Id.CompareTo(a2.Id)); }); genericTraits = genericTraits.Distinct().ToList(); int firstExclusive = 0; int total = genericTraits.Count; for (var i = 0; i < total; ++i, ++firstExclusive) { if (genericTraits[i].Flags.HasAnyFlag(GarrisonAbilityFlags.Exclusive)) { break; } } while (traitList.Count < Math.Max(0, slots[1] - forcedTraits.Count) && total != 0) { var garrAbility = genericTraits[RandomHelper.IRand(0, total-- - 1)]; if (garrAbility.Flags.HasAnyFlag(GarrisonAbilityFlags.Exclusive)) { total = firstExclusive; // selected exclusive trait - no other can be selected now } else { --firstExclusive; } traitList.Add(garrAbility); genericTraits.Remove(garrAbility); } } result.AddRange(forcedAbilities); result.AddRange(abilityList); result.AddRange(forcedTraits); result.AddRange(traitList); return(result); }