Ported .Net Core commits:
hondacrx: - Initial commit: Switch to .Net Core 2.0 - Fix build and removed not needed files Fabi: - Updated solution platforms. - Changed folder structure. - Change library target framework to netstandard2.0. - Updated solution platforms again... - Removed windows specific kernel32 function usage (Ctrl-C handler).
This commit is contained in:
@@ -0,0 +1,502 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2017 CypherCore <http://github.com/CypherCore>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.Database;
|
||||
using Game.DataStorage;
|
||||
using Game.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Linq;
|
||||
|
||||
namespace Game.Garrisons
|
||||
{
|
||||
public class GarrisonManager : Singleton<GarrisonManager>
|
||||
{
|
||||
GarrisonManager() { }
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
foreach (GarrSiteLevelPlotInstRecord siteLevelPlotInst in CliDB.GarrSiteLevelPlotInstStorage.Values)
|
||||
_garrisonPlotInstBySiteLevel.Add(siteLevelPlotInst.GarrSiteLevelID, siteLevelPlotInst);
|
||||
|
||||
foreach (GameObjectsRecord gameObject in CliDB.GameObjectsStorage.Values)
|
||||
{
|
||||
if (gameObject.Type == GameObjectTypes.GarrisonPlot)
|
||||
{
|
||||
if (!_garrisonPlots.ContainsKey(gameObject.MapID))
|
||||
_garrisonPlots[gameObject.MapID] = new Dictionary<uint, GameObjectsRecord>();
|
||||
|
||||
_garrisonPlots[gameObject.MapID][(uint)gameObject.Data[0]] = gameObject;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (GarrPlotBuildingRecord plotBuilding in CliDB.GarrPlotBuildingStorage.Values)
|
||||
_garrisonBuildingsByPlot.Add(plotBuilding.GarrPlotID, plotBuilding.GarrBuildingID);
|
||||
|
||||
foreach (GarrBuildingPlotInstRecord buildingPlotInst in CliDB.GarrBuildingPlotInstStorage.Values)
|
||||
_garrisonBuildingPlotInstances[MathFunctions.MakePair64(buildingPlotInst.GarrBuildingID, buildingPlotInst.GarrSiteLevelPlotInstID)] = buildingPlotInst.Id;
|
||||
|
||||
foreach (GarrBuildingRecord building in CliDB.GarrBuildingStorage.Values)
|
||||
_garrisonBuildingsByType.Add(building.Type, building.Id);
|
||||
|
||||
for (var i = 0; i < 2; ++i)
|
||||
_garrisonFollowerAbilities[i] = new Dictionary<uint, GarrAbilities>();
|
||||
|
||||
foreach (GarrFollowerXAbilityRecord followerAbility in CliDB.GarrFollowerXAbilityStorage.Values)
|
||||
{
|
||||
GarrAbilityRecord ability = CliDB.GarrAbilityStorage.LookupByKey(followerAbility.GarrAbilityID);
|
||||
if (ability != null)
|
||||
{
|
||||
if (ability.FollowerTypeID != (uint)GarrisonFollowerType.Garrison)
|
||||
continue;
|
||||
|
||||
if (!ability.Flags.HasAnyFlag(GarrisonAbilityFlags.CannotRoll) && ability.Flags.HasAnyFlag(GarrisonAbilityFlags.Trait))
|
||||
_garrisonFollowerRandomTraits.Add(ability);
|
||||
|
||||
if (followerAbility.FactionIndex < 2)
|
||||
{
|
||||
var dic = _garrisonFollowerAbilities[followerAbility.FactionIndex];
|
||||
|
||||
if (!dic.ContainsKey(followerAbility.GarrFollowerID))
|
||||
dic[followerAbility.GarrFollowerID] = new GarrAbilities();
|
||||
|
||||
if (ability.Flags.HasAnyFlag(GarrisonAbilityFlags.Trait))
|
||||
dic[followerAbility.GarrFollowerID].Traits.Add(ability);
|
||||
else
|
||||
dic[followerAbility.GarrFollowerID].Counters.Add(ability);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InitializeDbIdSequences();
|
||||
LoadPlotFinalizeGOInfo();
|
||||
LoadFollowerClassSpecAbilities();
|
||||
}
|
||||
|
||||
public GarrSiteLevelRecord GetGarrSiteLevelEntry(uint garrSiteId, uint level)
|
||||
{
|
||||
foreach (GarrSiteLevelRecord siteLevel in CliDB.GarrSiteLevelStorage.Values)
|
||||
if (siteLevel.SiteID == garrSiteId && siteLevel.Level == level)
|
||||
return siteLevel;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<GarrSiteLevelPlotInstRecord> GetGarrPlotInstForSiteLevel(uint garrSiteLevelId)
|
||||
{
|
||||
return _garrisonPlotInstBySiteLevel.LookupByKey(garrSiteLevelId);
|
||||
}
|
||||
|
||||
public GameObjectsRecord GetPlotGameObject(uint mapId, uint garrPlotInstanceId)
|
||||
{
|
||||
var pair = _garrisonPlots.LookupByKey(mapId);
|
||||
if (pair != null)
|
||||
{
|
||||
var gameobjectsRecord = pair.LookupByKey(garrPlotInstanceId);
|
||||
if (gameobjectsRecord != null)
|
||||
return gameobjectsRecord;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool IsPlotMatchingBuilding(uint garrPlotId, uint garrBuildingId)
|
||||
{
|
||||
var plotList = _garrisonBuildingsByPlot.LookupByKey(garrPlotId);
|
||||
if (!plotList.Empty())
|
||||
return plotList.Contains(garrBuildingId);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public uint GetGarrBuildingPlotInst(uint garrBuildingId, uint garrSiteLevelPlotInstId)
|
||||
{
|
||||
return _garrisonBuildingPlotInstances.LookupByKey(MathFunctions.MakePair64(garrBuildingId, garrSiteLevelPlotInstId));
|
||||
}
|
||||
|
||||
public uint GetPreviousLevelBuilding(uint buildingType, uint currentLevel)
|
||||
{
|
||||
var list = _garrisonBuildingsByType.LookupByKey(buildingType);
|
||||
if (!list.Empty())
|
||||
{
|
||||
foreach (uint buildingId in list)
|
||||
if (CliDB.GarrBuildingStorage.LookupByKey(buildingId).Level == currentLevel - 1)
|
||||
return buildingId;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public FinalizeGarrisonPlotGOInfo GetPlotFinalizeGOInfo(uint garrPlotInstanceID)
|
||||
{
|
||||
return _finalizePlotGOInfo.LookupByKey(garrPlotInstanceID);
|
||||
}
|
||||
|
||||
public ulong GenerateFollowerDbId()
|
||||
{
|
||||
if (_followerDbIdGenerator >= ulong.MaxValue)
|
||||
{
|
||||
Log.outFatal(LogFilter.Server, "Garrison follower db id overflow! Can't continue, shutting down server. ");
|
||||
Global.WorldMgr.StopNow();
|
||||
}
|
||||
|
||||
return _followerDbIdGenerator++;
|
||||
}
|
||||
|
||||
// Counters, Traits
|
||||
uint[,] AbilitiesForQuality =
|
||||
{
|
||||
{ 0, 0 },
|
||||
{ 1, 0 },
|
||||
{ 1, 1 }, // Uncommon
|
||||
{ 1, 2 }, // Rare
|
||||
{ 2, 3 }, // Epic
|
||||
{ 2, 3 } // Legendary
|
||||
};
|
||||
|
||||
//todo check this method, might be slow.....
|
||||
public List<GarrAbilityRecord> RollFollowerAbilities(uint garrFollowerId, GarrFollowerRecord follower, uint quality, uint faction, bool initial)
|
||||
{
|
||||
Contract.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);
|
||||
List<GarrAbilityRecord> classSpecAbilitiesTemp = classSpecAbilities.Except(forcedAbilities).ToList();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void InitializeDbIdSequences()
|
||||
{
|
||||
SQLResult result = DB.Characters.Query("SELECT MAX(dbId) FROM character_garrison_followers");
|
||||
if (!result.IsEmpty())
|
||||
_followerDbIdGenerator = result.Read<ulong>(0) + 1;
|
||||
}
|
||||
|
||||
void LoadPlotFinalizeGOInfo()
|
||||
{
|
||||
// 0 1 2 3 4 5 6
|
||||
SQLResult result = DB.World.Query("SELECT garrPlotInstanceId, hordeGameObjectId, hordeX, hordeY, hordeZ, hordeO, hordeAnimKitId, " +
|
||||
// 7 8 9 10 11 12
|
||||
"allianceGameObjectId, allianceX, allianceY, allianceZ, allianceO, allianceAnimKitId FROM garrison_plot_finalize_info");
|
||||
|
||||
if (result.IsEmpty())
|
||||
{
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loaded 0 garrison follower class spec abilities. DB table `garrison_plot_finalize_info` is empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
uint msTime = Time.GetMSTime();
|
||||
do
|
||||
{
|
||||
uint garrPlotInstanceId = result.Read<uint>(0);
|
||||
uint hordeGameObjectId = result.Read<uint>(1);
|
||||
uint allianceGameObjectId = result.Read<uint>(7);
|
||||
ushort hordeAnimKitId = result.Read<ushort>(6);
|
||||
ushort allianceAnimKitId = result.Read<ushort>(12);
|
||||
|
||||
if (!CliDB.GarrPlotInstanceStorage.ContainsKey(garrPlotInstanceId))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Non-existing GarrPlotInstance.db2 entry {0} was referenced in `garrison_plot_finalize_info`.", garrPlotInstanceId);
|
||||
continue;
|
||||
}
|
||||
|
||||
GameObjectTemplate goTemplate = Global.ObjectMgr.GetGameObjectTemplate(hordeGameObjectId);
|
||||
if (goTemplate == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Non-existing gameobject_template entry {0} was referenced in `garrison_plot_finalize_info`.`hordeGameObjectId` for garrPlotInstanceId {1}.",
|
||||
hordeGameObjectId, garrPlotInstanceId);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (goTemplate.type != GameObjectTypes.Goober)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Invalid gameobject type {0} (entry {1}) was referenced in `garrison_plot_finalize_info`.`hordeGameObjectId` for garrPlotInstanceId {2}.",
|
||||
goTemplate.type, hordeGameObjectId, garrPlotInstanceId);
|
||||
continue;
|
||||
}
|
||||
|
||||
goTemplate = Global.ObjectMgr.GetGameObjectTemplate(allianceGameObjectId);
|
||||
if (goTemplate == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Non-existing gameobject_template entry {0} was referenced in `garrison_plot_finalize_info`.`allianceGameObjectId` for garrPlotInstanceId {1}.",
|
||||
allianceGameObjectId, garrPlotInstanceId);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (goTemplate.type != GameObjectTypes.Goober)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Invalid gameobject type {0} (entry {1}) was referenced in `garrison_plot_finalize_info`.`allianceGameObjectId` for garrPlotInstanceId {2}.",
|
||||
goTemplate.type, allianceGameObjectId, garrPlotInstanceId);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hordeAnimKitId != 0 && !CliDB.AnimKitStorage.ContainsKey(hordeAnimKitId))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Non-existing AnimKit.dbc entry {0} was referenced in `garrison_plot_finalize_info`.`hordeAnimKitId` for garrPlotInstanceId {1}.",
|
||||
hordeAnimKitId, garrPlotInstanceId);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (allianceAnimKitId != 0 && !CliDB.AnimKitStorage.ContainsKey(allianceAnimKitId))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Non-existing AnimKit.dbc entry {0} was referenced in `garrison_plot_finalize_info`.`allianceAnimKitId` for garrPlotInstanceId {1}.",
|
||||
allianceAnimKitId, garrPlotInstanceId);
|
||||
continue;
|
||||
}
|
||||
|
||||
FinalizeGarrisonPlotGOInfo info = new FinalizeGarrisonPlotGOInfo();
|
||||
info.factionInfo[GarrisonFactionIndex.Horde].GameObjectId = hordeGameObjectId;
|
||||
info.factionInfo[GarrisonFactionIndex.Horde].Pos.Relocate(result.Read<float>(2), result.Read<float>(3), result.Read<float>(4), result.Read<float>(5));
|
||||
info.factionInfo[GarrisonFactionIndex.Horde].AnimKitId = hordeAnimKitId;
|
||||
|
||||
info.factionInfo[GarrisonFactionIndex.Alliance].GameObjectId = allianceGameObjectId;
|
||||
info.factionInfo[GarrisonFactionIndex.Alliance].Pos.Relocate(result.Read<float>(8), result.Read<float>(9), result.Read<float>(10), result.Read<float>(11));
|
||||
info.factionInfo[GarrisonFactionIndex.Alliance].AnimKitId = allianceAnimKitId;
|
||||
|
||||
_finalizePlotGOInfo[garrPlotInstanceId] = info;
|
||||
|
||||
} while (result.NextRow());
|
||||
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} garrison plot finalize entries in {1}.", _finalizePlotGOInfo.Count, Time.GetMSTimeDiffToNow(msTime));
|
||||
}
|
||||
|
||||
void LoadFollowerClassSpecAbilities()
|
||||
{
|
||||
SQLResult result = DB.World.Query("SELECT classSpecId, abilityId FROM garrison_follower_class_spec_abilities");
|
||||
if (result.IsEmpty())
|
||||
{
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loaded 0 garrison follower class spec abilities. DB table `garrison_follower_class_spec_abilities` is empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
uint msTime = Time.GetMSTime();
|
||||
uint count = 0;
|
||||
do
|
||||
{
|
||||
uint classSpecId = result.Read<uint>(0);
|
||||
uint abilityId = result.Read<uint>(1);
|
||||
|
||||
if (!CliDB.GarrClassSpecStorage.ContainsKey(classSpecId))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Non-existing GarrClassSpec.db2 entry {0} was referenced in `garrison_follower_class_spec_abilities` by row ({1}, {2}).", classSpecId, classSpecId, abilityId);
|
||||
continue;
|
||||
}
|
||||
|
||||
GarrAbilityRecord ability = CliDB.GarrAbilityStorage.LookupByKey(abilityId);
|
||||
if (ability == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Non-existing GarrAbility.db2 entry {0} was referenced in `garrison_follower_class_spec_abilities` by row ({1}, {2}).", abilityId, classSpecId, abilityId);
|
||||
continue;
|
||||
}
|
||||
|
||||
_garrisonFollowerClassSpecAbilities.Add(classSpecId, ability);
|
||||
++count;
|
||||
|
||||
} while (result.NextRow());
|
||||
|
||||
//foreach (var key in _garrisonFollowerClassSpecAbilities.Keys)
|
||||
//_garrisonFollowerClassSpecAbilities[key].Sort();
|
||||
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} garrison follower class spec abilities in {1}.", count, Time.GetMSTimeDiffToNow(msTime));
|
||||
}
|
||||
|
||||
MultiMap<uint, GarrSiteLevelPlotInstRecord> _garrisonPlotInstBySiteLevel = new MultiMap<uint, GarrSiteLevelPlotInstRecord>();
|
||||
Dictionary<uint, Dictionary<uint, GameObjectsRecord>> _garrisonPlots = new Dictionary<uint, Dictionary<uint, GameObjectsRecord>>();
|
||||
MultiMap<uint, uint> _garrisonBuildingsByPlot = new MultiMap<uint, uint>();
|
||||
Dictionary<ulong, uint> _garrisonBuildingPlotInstances = new Dictionary<ulong, uint>();
|
||||
MultiMap<uint, uint> _garrisonBuildingsByType = new MultiMap<uint, uint>();
|
||||
Dictionary<uint, FinalizeGarrisonPlotGOInfo> _finalizePlotGOInfo = new Dictionary<uint, FinalizeGarrisonPlotGOInfo>();
|
||||
Dictionary<uint, GarrAbilities>[] _garrisonFollowerAbilities = new Dictionary<uint, GarrAbilities>[2];
|
||||
MultiMap<uint, GarrAbilityRecord> _garrisonFollowerClassSpecAbilities = new MultiMap<uint, GarrAbilityRecord>();
|
||||
List<GarrAbilityRecord> _garrisonFollowerRandomTraits = new List<GarrAbilityRecord>();
|
||||
|
||||
ulong _followerDbIdGenerator = 1;
|
||||
}
|
||||
|
||||
class GarrAbilities
|
||||
{
|
||||
public List<GarrAbilityRecord> Counters = new List<GarrAbilityRecord>();
|
||||
public List<GarrAbilityRecord> Traits = new List<GarrAbilityRecord>();
|
||||
}
|
||||
|
||||
public class FinalizeGarrisonPlotGOInfo
|
||||
{
|
||||
public FactionInfo[] factionInfo = new FactionInfo[2];
|
||||
|
||||
public struct FactionInfo
|
||||
{
|
||||
public uint GameObjectId;
|
||||
public Position Pos;
|
||||
public ushort AnimKitId;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2017 CypherCore <http://github.com/CypherCore>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Game.Entities;
|
||||
using Game.Maps;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Game.Garrisons
|
||||
{
|
||||
class GarrisonMap : Map
|
||||
{
|
||||
public GarrisonMap(uint id, long expiry, uint instanceId, Map parent, ObjectGuid owner)
|
||||
: base(id, expiry, instanceId, Difficulty.Normal, parent)
|
||||
{
|
||||
_owner = owner;
|
||||
InitVisibilityDistance();
|
||||
}
|
||||
|
||||
public override void LoadGridObjects(Grid grid, Cell cell)
|
||||
{
|
||||
base.LoadGridObjects(grid, cell);
|
||||
|
||||
GarrisonGridLoader loader = new GarrisonGridLoader(grid, this, cell);
|
||||
loader.LoadN();
|
||||
}
|
||||
|
||||
public Garrison GetGarrison()
|
||||
{
|
||||
if (_loadingPlayer)
|
||||
return _loadingPlayer.GetGarrison();
|
||||
|
||||
Player owner = Global.ObjAccessor.FindConnectedPlayer(_owner);
|
||||
if (owner)
|
||||
return owner.GetGarrison();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override void InitVisibilityDistance()
|
||||
{
|
||||
//init visibility distance for instances
|
||||
m_VisibleDistance = Global.WorldMgr.GetMaxVisibleDistanceInBGArenas();
|
||||
m_VisibilityNotifyPeriod = Global.WorldMgr.GetVisibilityNotifyPeriodInBGArenas();
|
||||
}
|
||||
|
||||
public override bool AddPlayerToMap(Player player, bool initPlayer = true)
|
||||
{
|
||||
if (player.GetGUID() == _owner)
|
||||
_loadingPlayer = player;
|
||||
|
||||
bool result = base.AddPlayerToMap(player, initPlayer);
|
||||
|
||||
if (player.GetGUID() == _owner)
|
||||
_loadingPlayer = null;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ObjectGuid _owner;
|
||||
Player _loadingPlayer; // @workaround Player is not registered in ObjectAccessor during login
|
||||
}
|
||||
|
||||
class GarrisonGridLoader : Notifier
|
||||
{
|
||||
public GarrisonGridLoader(Grid grid, GarrisonMap map, Cell cell)
|
||||
{
|
||||
i_cell = cell;
|
||||
i_grid = grid;
|
||||
i_map = map;
|
||||
i_garrison = map.GetGarrison();
|
||||
}
|
||||
|
||||
public void LoadN()
|
||||
{
|
||||
if (i_garrison != null)
|
||||
{
|
||||
i_cell.data.cell_y = 0;
|
||||
for (uint x = 0; x < MapConst.MaxCells; ++x)
|
||||
{
|
||||
i_cell.data.cell_x = x;
|
||||
for (uint y = 0; y < MapConst.MaxCells; ++y)
|
||||
{
|
||||
i_cell.data.cell_y = y;
|
||||
|
||||
//Load creatures and game objects
|
||||
var visitor = new Visitor(this, GridMapTypeMask.AllGrid);
|
||||
i_grid.VisitGrid(x, y, visitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Log.outDebug(LogFilter.Maps, "{0} GameObjects and {1} Creatures loaded for grid {2} on map {3}", i_gameObjects, i_creatures, i_grid.GetGridId(), i_map.GetId());
|
||||
}
|
||||
|
||||
public override void Visit(ICollection<WorldObject> objs)
|
||||
{
|
||||
List<Garrison.Plot> plots = i_garrison.GetPlots().ToList();
|
||||
if (!plots.Empty())
|
||||
{
|
||||
CellCoord cellCoord = i_cell.GetCellCoord();
|
||||
foreach (Garrison.Plot plot in plots)
|
||||
{
|
||||
Position spawn = plot.PacketInfo.PlotPos;
|
||||
if (cellCoord != GridDefines.ComputeCellCoord(spawn.GetPositionX(), spawn.GetPositionY()))
|
||||
continue;
|
||||
|
||||
GameObject go = plot.CreateGameObject(i_map, i_garrison.GetFaction());
|
||||
if (!go)
|
||||
continue;
|
||||
|
||||
var cell = new Cell(cellCoord);
|
||||
i_map.AddToGrid(go, cell);
|
||||
go.AddToWorld();
|
||||
++i_gameObjects;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Cell i_cell;
|
||||
Grid i_grid;
|
||||
GarrisonMap i_map;
|
||||
Garrison i_garrison;
|
||||
uint i_gameObjects;
|
||||
uint i_creatures;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,864 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2017 CypherCore <http://github.com/CypherCore>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.Database;
|
||||
using Framework.Dynamic;
|
||||
using Framework.GameMath;
|
||||
using Game.DataStorage;
|
||||
using Game.Entities;
|
||||
using Game.Maps;
|
||||
using Game.Network.Packets;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.Contracts;
|
||||
|
||||
namespace Game.Garrisons
|
||||
{
|
||||
public class Garrison
|
||||
{
|
||||
public Garrison(Player owner)
|
||||
{
|
||||
_owner = owner;
|
||||
_followerActivationsRemainingToday = 1;
|
||||
}
|
||||
|
||||
public bool LoadFromDB(SQLResult garrison, SQLResult blueprints, SQLResult buildings, SQLResult followers, SQLResult abilities)
|
||||
{
|
||||
if (garrison.IsEmpty())
|
||||
return false;
|
||||
|
||||
_siteLevel = CliDB.GarrSiteLevelStorage.LookupByKey(garrison.Read<uint>(0));
|
||||
_followerActivationsRemainingToday = garrison.Read<uint>(1);
|
||||
if (_siteLevel == null)
|
||||
return false;
|
||||
|
||||
InitializePlots();
|
||||
|
||||
if (!blueprints.IsEmpty())
|
||||
{
|
||||
do
|
||||
{
|
||||
GarrBuildingRecord building = CliDB.GarrBuildingStorage.LookupByKey(blueprints.Read<uint>(0));
|
||||
if (building != null)
|
||||
_knownBuildings.Add(building.Id);
|
||||
|
||||
} while (blueprints.NextRow());
|
||||
}
|
||||
|
||||
if (!buildings.IsEmpty())
|
||||
{
|
||||
do
|
||||
{
|
||||
uint plotInstanceId = buildings.Read<uint>(0);
|
||||
uint buildingId = buildings.Read<uint>(1);
|
||||
ulong timeBuilt = buildings.Read<ulong>(2);
|
||||
bool active = buildings.Read<bool>(3);
|
||||
|
||||
|
||||
Plot plot = GetPlot(plotInstanceId);
|
||||
if (plot == null)
|
||||
continue;
|
||||
|
||||
if (!CliDB.GarrBuildingStorage.ContainsKey(buildingId))
|
||||
continue;
|
||||
|
||||
plot.BuildingInfo.PacketInfo.HasValue = true;
|
||||
plot.BuildingInfo.PacketInfo.Value.GarrPlotInstanceID = plotInstanceId;
|
||||
plot.BuildingInfo.PacketInfo.Value.GarrBuildingID = buildingId;
|
||||
plot.BuildingInfo.PacketInfo.Value.TimeBuilt = (long)timeBuilt;
|
||||
plot.BuildingInfo.PacketInfo.Value.Active = active;
|
||||
|
||||
} while (buildings.NextRow());
|
||||
}
|
||||
|
||||
if (!followers.IsEmpty())
|
||||
{
|
||||
do
|
||||
{
|
||||
ulong dbId = followers.Read<ulong>(0);
|
||||
uint followerId = followers.Read<uint>(1);
|
||||
if (!CliDB.GarrFollowerStorage.ContainsKey(followerId))
|
||||
continue;
|
||||
|
||||
_followerIds.Add(followerId);
|
||||
|
||||
var follower = new Follower();
|
||||
follower.PacketInfo.DbID = dbId;
|
||||
follower.PacketInfo.GarrFollowerID = followerId;
|
||||
follower.PacketInfo.Quality = followers.Read<uint>(2);
|
||||
follower.PacketInfo.FollowerLevel = followers.Read<uint>(3);
|
||||
follower.PacketInfo.ItemLevelWeapon = followers.Read<uint>(4);
|
||||
follower.PacketInfo.ItemLevelArmor = followers.Read<uint>(5);
|
||||
follower.PacketInfo.Xp = followers.Read<uint>(6);
|
||||
follower.PacketInfo.CurrentBuildingID = followers.Read<uint>(7);
|
||||
follower.PacketInfo.CurrentMissionID = followers.Read<uint>(8);
|
||||
follower.PacketInfo.FollowerStatus = followers.Read<uint>(9);
|
||||
if (!CliDB.GarrBuildingStorage.ContainsKey(follower.PacketInfo.CurrentBuildingID))
|
||||
follower.PacketInfo.CurrentBuildingID = 0;
|
||||
|
||||
//if (!sGarrMissionStore.LookupEntry(follower.PacketInfo.CurrentMissionID))
|
||||
// follower.PacketInfo.CurrentMissionID = 0;
|
||||
_followers[followerId] = follower;
|
||||
|
||||
} while (followers.NextRow());
|
||||
|
||||
if (!abilities.IsEmpty())
|
||||
{
|
||||
do
|
||||
{
|
||||
ulong dbId = abilities.Read<ulong>(0);
|
||||
GarrAbilityRecord ability = CliDB.GarrAbilityStorage.LookupByKey(abilities.Read<uint>(1));
|
||||
|
||||
if (ability == null)
|
||||
continue;
|
||||
|
||||
var garrisonFollower = _followers.LookupByKey(dbId);
|
||||
if (garrisonFollower == null)
|
||||
continue;
|
||||
|
||||
garrisonFollower.PacketInfo.AbilityID.Add(ability);
|
||||
} while (abilities.NextRow());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SaveToDB(SQLTransaction trans)
|
||||
{
|
||||
DeleteFromDB(_owner.GetGUID().GetCounter(), trans);
|
||||
|
||||
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_CHARACTER_GARRISON);
|
||||
stmt.AddValue(0, _owner.GetGUID().GetCounter());
|
||||
stmt.AddValue(1, _siteLevel.Id);
|
||||
stmt.AddValue(2, _followerActivationsRemainingToday);
|
||||
trans.Append(stmt);
|
||||
|
||||
foreach (uint building in _knownBuildings)
|
||||
{
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_CHARACTER_GARRISON_BLUEPRINTS);
|
||||
stmt.AddValue(0, _owner.GetGUID().GetCounter());
|
||||
stmt.AddValue(1, building);
|
||||
trans.Append(stmt);
|
||||
}
|
||||
|
||||
foreach (var plot in _plots.Values)
|
||||
{
|
||||
if (plot.BuildingInfo.PacketInfo.HasValue)
|
||||
{
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_CHARACTER_GARRISON_BUILDINGS);
|
||||
stmt.AddValue(0, _owner.GetGUID().GetCounter());
|
||||
stmt.AddValue(1, plot.BuildingInfo.PacketInfo.Value.GarrPlotInstanceID);
|
||||
stmt.AddValue(2, plot.BuildingInfo.PacketInfo.Value.GarrBuildingID);
|
||||
stmt.AddValue(3, plot.BuildingInfo.PacketInfo.Value.TimeBuilt);
|
||||
stmt.AddValue(4, plot.BuildingInfo.PacketInfo.Value.Active);
|
||||
trans.Append(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var follower in _followers.Values)
|
||||
{
|
||||
byte index = 0;
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_CHARACTER_GARRISON_FOLLOWERS);
|
||||
stmt.AddValue(index++, follower.PacketInfo.DbID);
|
||||
stmt.AddValue(index++, _owner.GetGUID().GetCounter());
|
||||
stmt.AddValue(index++, follower.PacketInfo.GarrFollowerID);
|
||||
stmt.AddValue(index++, follower.PacketInfo.Quality);
|
||||
stmt.AddValue(index++, follower.PacketInfo.FollowerLevel);
|
||||
stmt.AddValue(index++, follower.PacketInfo.ItemLevelWeapon);
|
||||
stmt.AddValue(index++, follower.PacketInfo.ItemLevelArmor);
|
||||
stmt.AddValue(index++, follower.PacketInfo.Xp);
|
||||
stmt.AddValue(index++, follower.PacketInfo.CurrentBuildingID);
|
||||
stmt.AddValue(index++, follower.PacketInfo.CurrentMissionID);
|
||||
stmt.AddValue(index++, follower.PacketInfo.FollowerStatus);
|
||||
trans.Append(stmt);
|
||||
|
||||
byte slot = 0;
|
||||
foreach (GarrAbilityRecord ability in follower.PacketInfo.AbilityID)
|
||||
{
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_CHARACTER_GARRISON_FOLLOWER_ABILITIES);
|
||||
stmt.AddValue(0, follower.PacketInfo.DbID);
|
||||
stmt.AddValue(1, ability.Id);
|
||||
stmt.AddValue(2, slot++);
|
||||
trans.Append(stmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void DeleteFromDB(ulong ownerGuid, SQLTransaction trans)
|
||||
{
|
||||
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_CHARACTER_GARRISON);
|
||||
stmt.AddValue(0, ownerGuid);
|
||||
trans.Append(stmt);
|
||||
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_CHARACTER_GARRISON_BLUEPRINTS);
|
||||
stmt.AddValue(0, ownerGuid);
|
||||
trans.Append(stmt);
|
||||
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_CHARACTER_GARRISON_BUILDINGS);
|
||||
stmt.AddValue(0, ownerGuid);
|
||||
trans.Append(stmt);
|
||||
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_CHARACTER_GARRISON_FOLLOWERS);
|
||||
stmt.AddValue(0, ownerGuid);
|
||||
trans.Append(stmt);
|
||||
}
|
||||
|
||||
public bool Create(uint garrSiteId)
|
||||
{
|
||||
GarrSiteLevelRecord siteLevel = Global.GarrisonMgr.GetGarrSiteLevelEntry(garrSiteId, 1);
|
||||
if (siteLevel == null)
|
||||
return false;
|
||||
|
||||
_siteLevel = siteLevel;
|
||||
|
||||
InitializePlots();
|
||||
|
||||
GarrisonCreateResult garrisonCreateResult = new GarrisonCreateResult();
|
||||
garrisonCreateResult.GarrSiteLevelID = _siteLevel.Id;
|
||||
_owner.SendPacket(garrisonCreateResult);
|
||||
_owner.SendUpdatePhasing();
|
||||
SendRemoteInfo();
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Delete()
|
||||
{
|
||||
SQLTransaction trans = new SQLTransaction();
|
||||
DeleteFromDB(_owner.GetGUID().GetCounter(), trans);
|
||||
DB.Characters.CommitTransaction(trans);
|
||||
|
||||
GarrisonDeleteResult garrisonDelete = new GarrisonDeleteResult();
|
||||
garrisonDelete.Result = GarrisonError.Success;
|
||||
garrisonDelete.GarrSiteID = _siteLevel.SiteID;
|
||||
_owner.SendPacket(garrisonDelete);
|
||||
}
|
||||
|
||||
void InitializePlots()
|
||||
{
|
||||
var plots = Global.GarrisonMgr.GetGarrPlotInstForSiteLevel(_siteLevel.Id);
|
||||
|
||||
for (var i = 0; i < plots.Count; ++i)
|
||||
{
|
||||
uint garrPlotInstanceId = plots[i].GarrPlotInstanceID;
|
||||
GarrPlotInstanceRecord plotInstance = CliDB.GarrPlotInstanceStorage.LookupByKey(garrPlotInstanceId);
|
||||
GameObjectsRecord gameObject = Global.GarrisonMgr.GetPlotGameObject(_siteLevel.MapID, garrPlotInstanceId);
|
||||
if (plotInstance == null || gameObject == null)
|
||||
continue;
|
||||
|
||||
GarrPlotRecord plot = CliDB.GarrPlotStorage.LookupByKey(plotInstance.GarrPlotID);
|
||||
if (plot == null)
|
||||
continue;
|
||||
|
||||
Plot plotInfo = _plots[garrPlotInstanceId];
|
||||
plotInfo.PacketInfo.GarrPlotInstanceID = garrPlotInstanceId;
|
||||
plotInfo.PacketInfo.PlotPos.Relocate(gameObject.Position.X, gameObject.Position.Y, gameObject.Position.Z, 2 * (float)Math.Acos(gameObject.RotationW));
|
||||
plotInfo.PacketInfo.PlotType = plot.PlotType;
|
||||
plotInfo.EmptyGameObjectId = gameObject.Id;
|
||||
plotInfo.GarrSiteLevelPlotInstId = plots[i].Id;
|
||||
}
|
||||
}
|
||||
|
||||
void Upgrade()
|
||||
{
|
||||
}
|
||||
|
||||
void Enter()
|
||||
{
|
||||
WorldLocation loc = new WorldLocation(_siteLevel.MapID);
|
||||
loc.Relocate(_owner);
|
||||
_owner.TeleportTo(loc, TeleportToOptions.Seamless);
|
||||
}
|
||||
|
||||
void Leave()
|
||||
{
|
||||
MapRecord map = CliDB.MapStorage.LookupByKey(_siteLevel.MapID);
|
||||
if (map != null)
|
||||
{
|
||||
WorldLocation loc = new WorldLocation((uint)map.ParentMapID);
|
||||
loc.Relocate(_owner);
|
||||
_owner.TeleportTo(loc, TeleportToOptions.Seamless);
|
||||
}
|
||||
}
|
||||
|
||||
public uint GetFaction()
|
||||
{
|
||||
return _owner.GetTeam() == Team.Horde ? GarrisonFactionIndex.Horde : GarrisonFactionIndex.Alliance;
|
||||
}
|
||||
|
||||
public ICollection<Plot> GetPlots()
|
||||
{
|
||||
return _plots.Values;
|
||||
}
|
||||
|
||||
Plot GetPlot(uint garrPlotInstanceId)
|
||||
{
|
||||
return _plots.LookupByKey(garrPlotInstanceId);
|
||||
}
|
||||
|
||||
public void LearnBlueprint(uint garrBuildingId)
|
||||
{
|
||||
GarrisonLearnBlueprintResult learnBlueprintResult = new GarrisonLearnBlueprintResult();
|
||||
learnBlueprintResult.GarrTypeID = GarrisonType.Garrison;
|
||||
learnBlueprintResult.BuildingID = garrBuildingId;
|
||||
learnBlueprintResult.Result = GarrisonError.Success;
|
||||
|
||||
if (!CliDB.GarrBuildingStorage.ContainsKey(garrBuildingId))
|
||||
learnBlueprintResult.Result = GarrisonError.InvalidBuildingId;
|
||||
else if (_knownBuildings.Contains(garrBuildingId))
|
||||
learnBlueprintResult.Result = GarrisonError.BlueprintExists;
|
||||
else
|
||||
_knownBuildings.Add(garrBuildingId);
|
||||
|
||||
_owner.SendPacket(learnBlueprintResult);
|
||||
}
|
||||
|
||||
void UnlearnBlueprint(uint garrBuildingId)
|
||||
{
|
||||
GarrisonUnlearnBlueprintResult unlearnBlueprintResult = new GarrisonUnlearnBlueprintResult();
|
||||
unlearnBlueprintResult.GarrTypeID = GarrisonType.Garrison;
|
||||
unlearnBlueprintResult.BuildingID = garrBuildingId;
|
||||
unlearnBlueprintResult.Result = GarrisonError.Success;
|
||||
|
||||
if (!CliDB.GarrBuildingStorage.ContainsKey(garrBuildingId))
|
||||
unlearnBlueprintResult.Result = GarrisonError.InvalidBuildingId;
|
||||
else if (!_knownBuildings.Contains(garrBuildingId))
|
||||
unlearnBlueprintResult.Result = GarrisonError.RequiresBlueprint;
|
||||
else
|
||||
_knownBuildings.Remove(garrBuildingId);
|
||||
|
||||
_owner.SendPacket(unlearnBlueprintResult);
|
||||
}
|
||||
|
||||
public void PlaceBuilding(uint garrPlotInstanceId, uint garrBuildingId)
|
||||
{
|
||||
GarrisonPlaceBuildingResult placeBuildingResult = new GarrisonPlaceBuildingResult();
|
||||
placeBuildingResult.GarrTypeID = GarrisonType.Garrison;
|
||||
placeBuildingResult.Result = CheckBuildingPlacement(garrPlotInstanceId, garrBuildingId);
|
||||
if (placeBuildingResult.Result == GarrisonError.Success)
|
||||
{
|
||||
placeBuildingResult.BuildingInfo.GarrPlotInstanceID = garrPlotInstanceId;
|
||||
placeBuildingResult.BuildingInfo.GarrBuildingID = garrBuildingId;
|
||||
placeBuildingResult.BuildingInfo.TimeBuilt = Time.UnixTime;
|
||||
|
||||
Plot plot = GetPlot(garrPlotInstanceId);
|
||||
uint oldBuildingId = 0;
|
||||
Map map = FindMap();
|
||||
GarrBuildingRecord building = CliDB.GarrBuildingStorage.LookupByKey(garrBuildingId);
|
||||
if (map)
|
||||
plot.DeleteGameObject(map);
|
||||
|
||||
if (plot.BuildingInfo.PacketInfo.HasValue)
|
||||
{
|
||||
oldBuildingId = plot.BuildingInfo.PacketInfo.Value.GarrBuildingID;
|
||||
if (CliDB.GarrBuildingStorage.LookupByKey(oldBuildingId).Type != building.Type)
|
||||
plot.ClearBuildingInfo(_owner);
|
||||
}
|
||||
|
||||
plot.SetBuildingInfo(placeBuildingResult.BuildingInfo, _owner);
|
||||
if (map)
|
||||
{
|
||||
GameObject go = plot.CreateGameObject(map, GetFaction());
|
||||
if (go)
|
||||
map.AddToMap(go);
|
||||
}
|
||||
|
||||
_owner.ModifyCurrency((CurrencyTypes)building.CostCurrencyID, -building.CostCurrencyAmount, false, true);
|
||||
_owner.ModifyMoney(-building.CostMoney * MoneyConstants.Gold, false);
|
||||
|
||||
if (oldBuildingId != 0)
|
||||
{
|
||||
GarrisonBuildingRemoved buildingRemoved = new GarrisonBuildingRemoved();
|
||||
buildingRemoved.GarrTypeID = GarrisonType.Garrison;
|
||||
buildingRemoved.Result = GarrisonError.Success;
|
||||
buildingRemoved.GarrPlotInstanceID = garrPlotInstanceId;
|
||||
buildingRemoved.GarrBuildingID = oldBuildingId;
|
||||
_owner.SendPacket(buildingRemoved);
|
||||
}
|
||||
|
||||
_owner.UpdateCriteria(CriteriaTypes.PlaceGarrisonBuilding, garrBuildingId);
|
||||
}
|
||||
|
||||
_owner.SendPacket(placeBuildingResult);
|
||||
}
|
||||
|
||||
public void CancelBuildingConstruction(uint garrPlotInstanceId)
|
||||
{
|
||||
GarrisonBuildingRemoved buildingRemoved = new GarrisonBuildingRemoved();
|
||||
buildingRemoved.GarrTypeID = GarrisonType.Garrison;
|
||||
buildingRemoved.Result = CheckBuildingRemoval(garrPlotInstanceId);
|
||||
if (buildingRemoved.Result == GarrisonError.Success)
|
||||
{
|
||||
Plot plot = GetPlot(garrPlotInstanceId);
|
||||
|
||||
buildingRemoved.GarrPlotInstanceID = garrPlotInstanceId;
|
||||
buildingRemoved.GarrBuildingID = plot.BuildingInfo.PacketInfo.Value.GarrBuildingID;
|
||||
|
||||
Map map = FindMap();
|
||||
if (map)
|
||||
plot.DeleteGameObject(map);
|
||||
|
||||
plot.ClearBuildingInfo(_owner);
|
||||
_owner.SendPacket(buildingRemoved);
|
||||
|
||||
GarrBuildingRecord constructing = CliDB.GarrBuildingStorage.LookupByKey(buildingRemoved.GarrBuildingID);
|
||||
// Refund construction/upgrade cost
|
||||
_owner.ModifyCurrency((CurrencyTypes)constructing.CostCurrencyID, constructing.CostCurrencyAmount, false, true);
|
||||
_owner.ModifyMoney(constructing.CostMoney * MoneyConstants.Gold, false);
|
||||
|
||||
if (constructing.Level > 1)
|
||||
{
|
||||
// Restore previous level building
|
||||
uint restored = Global.GarrisonMgr.GetPreviousLevelBuilding(constructing.Type, constructing.Level);
|
||||
Contract.Assert(restored != 0);
|
||||
|
||||
GarrisonPlaceBuildingResult placeBuildingResult = new GarrisonPlaceBuildingResult();
|
||||
placeBuildingResult.GarrTypeID = GarrisonType.Garrison;
|
||||
placeBuildingResult.Result = GarrisonError.Success;
|
||||
placeBuildingResult.BuildingInfo.GarrPlotInstanceID = garrPlotInstanceId;
|
||||
placeBuildingResult.BuildingInfo.GarrBuildingID = restored;
|
||||
placeBuildingResult.BuildingInfo.TimeBuilt = Time.UnixTime;
|
||||
placeBuildingResult.BuildingInfo.Active = true;
|
||||
|
||||
plot.SetBuildingInfo(placeBuildingResult.BuildingInfo, _owner);
|
||||
_owner.SendPacket(placeBuildingResult);
|
||||
}
|
||||
|
||||
if (map)
|
||||
{
|
||||
GameObject go = plot.CreateGameObject(map, GetFaction());
|
||||
if (go)
|
||||
map.AddToMap(go);
|
||||
}
|
||||
}
|
||||
else
|
||||
_owner.SendPacket(buildingRemoved);
|
||||
}
|
||||
|
||||
public void ActivateBuilding(uint garrPlotInstanceId)
|
||||
{
|
||||
Plot plot = GetPlot(garrPlotInstanceId);
|
||||
if (plot != null)
|
||||
{
|
||||
if (plot.BuildingInfo.CanActivate() && plot.BuildingInfo.PacketInfo.HasValue && !plot.BuildingInfo.PacketInfo.Value.Active)
|
||||
{
|
||||
plot.BuildingInfo.PacketInfo.Value.Active = true;
|
||||
Map map = FindMap();
|
||||
if (map)
|
||||
{
|
||||
plot.DeleteGameObject(map);
|
||||
GameObject go = plot.CreateGameObject(map, GetFaction());
|
||||
if (go)
|
||||
map.AddToMap(go);
|
||||
}
|
||||
|
||||
GarrisonBuildingActivated buildingActivated = new GarrisonBuildingActivated();
|
||||
buildingActivated.GarrPlotInstanceID = garrPlotInstanceId;
|
||||
_owner.SendPacket(buildingActivated);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AddFollower(uint garrFollowerId)
|
||||
{
|
||||
GarrisonAddFollowerResult addFollowerResult = new GarrisonAddFollowerResult();
|
||||
addFollowerResult.GarrTypeID = GarrisonType.Garrison;
|
||||
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();
|
||||
follower.PacketInfo.DbID = dbId;
|
||||
follower.PacketInfo.GarrFollowerID = garrFollowerId;
|
||||
follower.PacketInfo.Quality = followerEntry.Quality; // TODO: handle magic upgrades
|
||||
follower.PacketInfo.FollowerLevel = followerEntry.Level;
|
||||
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(CriteriaTypes.RecruitGarrisonFollower, follower.PacketInfo.DbID);
|
||||
}
|
||||
|
||||
public Follower GetFollower(ulong dbId)
|
||||
{
|
||||
return _followers.LookupByKey(dbId);
|
||||
}
|
||||
|
||||
public void SendInfo()
|
||||
{
|
||||
GetGarrisonInfoResult garrisonInfo = new GetGarrisonInfoResult();
|
||||
garrisonInfo.FactionIndex = GetFaction();
|
||||
|
||||
GarrisonInfo garrison = new GarrisonInfo();
|
||||
garrison.GarrTypeID = GarrisonType.Garrison;
|
||||
garrison.GarrSiteID = _siteLevel.SiteID;
|
||||
garrison.GarrSiteLevelID = _siteLevel.Id;
|
||||
garrison.NumFollowerActivationsRemaining = _followerActivationsRemainingToday;
|
||||
foreach (var plot in _plots.Values)
|
||||
{
|
||||
garrison.Plots.Add(plot.PacketInfo);
|
||||
if (plot.BuildingInfo.PacketInfo.HasValue)
|
||||
garrison.Buildings.Add(plot.BuildingInfo.PacketInfo.Value);
|
||||
}
|
||||
|
||||
foreach (var follower in _followers.Values)
|
||||
garrison.Followers.Add(follower.PacketInfo);
|
||||
|
||||
garrisonInfo.Garrisons.Add(garrison);
|
||||
|
||||
_owner.SendPacket(garrisonInfo);
|
||||
}
|
||||
|
||||
public void SendRemoteInfo()
|
||||
{
|
||||
MapRecord garrisonMap = CliDB.MapStorage.LookupByKey(_siteLevel.MapID);
|
||||
if (garrisonMap == null || _owner.GetMapId() != garrisonMap.ParentMapID)
|
||||
return;
|
||||
|
||||
GarrisonRemoteInfo remoteInfo = new GarrisonRemoteInfo();
|
||||
|
||||
GarrisonRemoteSiteInfo remoteSiteInfo = new GarrisonRemoteSiteInfo();
|
||||
remoteSiteInfo.GarrSiteLevelID = _siteLevel.Id;
|
||||
foreach (var p in _plots)
|
||||
if (p.Value.BuildingInfo.PacketInfo.HasValue)
|
||||
remoteSiteInfo.Buildings.Add(new GarrisonRemoteBuildingInfo(p.Key, p.Value.BuildingInfo.PacketInfo.Value.GarrBuildingID));
|
||||
|
||||
remoteInfo.Sites.Add(remoteSiteInfo);
|
||||
_owner.SendPacket(remoteInfo);
|
||||
}
|
||||
|
||||
public void SendBlueprintAndSpecializationData()
|
||||
{
|
||||
GarrisonRequestBlueprintAndSpecializationDataResult data = new GarrisonRequestBlueprintAndSpecializationDataResult();
|
||||
data.GarrTypeID = GarrisonType.Garrison;
|
||||
data.BlueprintsKnown = _knownBuildings;
|
||||
_owner.SendPacket(data);
|
||||
}
|
||||
|
||||
public void SendBuildingLandmarks(Player receiver)
|
||||
{
|
||||
GarrisonBuildingLandmarks buildingLandmarks = new GarrisonBuildingLandmarks();
|
||||
|
||||
foreach (var plot in _plots.Values)
|
||||
{
|
||||
if (plot.BuildingInfo.PacketInfo.HasValue)
|
||||
{
|
||||
uint garrBuildingPlotInstId = Global.GarrisonMgr.GetGarrBuildingPlotInst(plot.BuildingInfo.PacketInfo.Value.GarrBuildingID, plot.GarrSiteLevelPlotInstId);
|
||||
if (garrBuildingPlotInstId != 0)
|
||||
buildingLandmarks.Landmarks.Add(new GarrisonBuildingLandmark(garrBuildingPlotInstId, plot.PacketInfo.PlotPos));
|
||||
}
|
||||
}
|
||||
|
||||
receiver.SendPacket(buildingLandmarks);
|
||||
}
|
||||
|
||||
Map FindMap()
|
||||
{
|
||||
return Global.MapMgr.FindMap(_siteLevel.MapID, (uint)_owner.GetGUID().GetCounter());
|
||||
}
|
||||
|
||||
GarrisonError CheckBuildingPlacement(uint garrPlotInstanceId, uint garrBuildingId)
|
||||
{
|
||||
GarrPlotInstanceRecord plotInstance = CliDB.GarrPlotInstanceStorage.LookupByKey(garrPlotInstanceId);
|
||||
Plot plot = GetPlot(garrPlotInstanceId);
|
||||
if (plotInstance == null || plot == null)
|
||||
return GarrisonError.InvalidPlotInstanceId;
|
||||
|
||||
GarrBuildingRecord building = CliDB.GarrBuildingStorage.LookupByKey(garrBuildingId);
|
||||
if (building == null)
|
||||
return GarrisonError.InvalidBuildingId;
|
||||
|
||||
if (!Global.GarrisonMgr.IsPlotMatchingBuilding(plotInstance.GarrPlotID, garrBuildingId))
|
||||
return GarrisonError.InvalidPlotBuilding;
|
||||
|
||||
// Cannot place buldings of higher level than garrison level
|
||||
if (building.Level > _siteLevel.Level)
|
||||
return GarrisonError.InvalidBuildingId;
|
||||
|
||||
if (building.Flags.HasAnyFlag(GarrisonBuildingFlags.NeedsPlan))
|
||||
{
|
||||
if (!_knownBuildings.Contains(garrBuildingId))
|
||||
return GarrisonError.RequiresBlueprint;
|
||||
}
|
||||
else // Building is built as a quest reward
|
||||
return GarrisonError.InvalidBuildingId;
|
||||
|
||||
// Check all plots to find if we already have this building
|
||||
GarrBuildingRecord existingBuilding;
|
||||
foreach (var p in _plots)
|
||||
{
|
||||
if (p.Value.BuildingInfo.PacketInfo.HasValue)
|
||||
{
|
||||
existingBuilding = CliDB.GarrBuildingStorage.LookupByKey(p.Value.BuildingInfo.PacketInfo.Value.GarrBuildingID);
|
||||
if (existingBuilding.Type == building.Type)
|
||||
if (p.Key != garrPlotInstanceId || existingBuilding.Level + 1 != building.Level) // check if its an upgrade in same plot
|
||||
return GarrisonError.BuildingExists;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_owner.HasCurrency(building.CostCurrencyID, (uint)building.CostCurrencyAmount))
|
||||
return GarrisonError.NotEnoughCurrency;
|
||||
|
||||
if (!_owner.HasEnoughMoney(building.CostMoney * MoneyConstants.Gold))
|
||||
return GarrisonError.NotEnoughGold;
|
||||
|
||||
// New building cannot replace another building currently under construction
|
||||
if (plot.BuildingInfo.PacketInfo.HasValue)
|
||||
if (!plot.BuildingInfo.PacketInfo.Value.Active)
|
||||
return GarrisonError.NoBuilding;
|
||||
|
||||
return GarrisonError.Success;
|
||||
}
|
||||
|
||||
GarrisonError CheckBuildingRemoval(uint garrPlotInstanceId)
|
||||
{
|
||||
Plot plot = GetPlot(garrPlotInstanceId);
|
||||
if (plot == null)
|
||||
return GarrisonError.InvalidPlotInstanceId;
|
||||
|
||||
if (!plot.BuildingInfo.PacketInfo.HasValue)
|
||||
return GarrisonError.NoBuilding;
|
||||
|
||||
if (plot.BuildingInfo.CanActivate())
|
||||
return GarrisonError.BuildingExists;
|
||||
|
||||
return GarrisonError.Success;
|
||||
}
|
||||
|
||||
public void ResetFollowerActivationLimit() { _followerActivationsRemainingToday = 1; }
|
||||
|
||||
Player _owner;
|
||||
GarrSiteLevelRecord _siteLevel;
|
||||
uint _followerActivationsRemainingToday;
|
||||
|
||||
Dictionary<uint, Plot> _plots = new Dictionary<uint, Plot>();
|
||||
List<uint> _knownBuildings = new List<uint>();
|
||||
Dictionary<ulong, Follower> _followers = new Dictionary<ulong, Follower>();
|
||||
List<uint> _followerIds = new List<uint>();
|
||||
|
||||
public class Building
|
||||
{
|
||||
public bool CanActivate()
|
||||
{
|
||||
if (PacketInfo.HasValue)
|
||||
{
|
||||
GarrBuildingRecord building = CliDB.GarrBuildingStorage.LookupByKey(PacketInfo.Value.GarrBuildingID);
|
||||
if (PacketInfo.Value.TimeBuilt + building.BuildDuration <= Time.UnixTime)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public ObjectGuid Guid;
|
||||
public List<ObjectGuid> Spawns = new List<ObjectGuid>();
|
||||
public Optional<GarrisonBuildingInfo> PacketInfo;
|
||||
}
|
||||
|
||||
public class Plot
|
||||
{
|
||||
public GameObject CreateGameObject(Map map, uint faction)
|
||||
{
|
||||
uint entry = EmptyGameObjectId;
|
||||
if (BuildingInfo.PacketInfo.HasValue)
|
||||
{
|
||||
GarrPlotInstanceRecord plotInstance = CliDB.GarrPlotInstanceStorage.LookupByKey(PacketInfo.GarrPlotInstanceID);
|
||||
GarrPlotRecord plot = CliDB.GarrPlotStorage.LookupByKey(plotInstance.GarrPlotID);
|
||||
GarrBuildingRecord building = CliDB.GarrBuildingStorage.LookupByKey(BuildingInfo.PacketInfo.Value.GarrBuildingID);
|
||||
|
||||
entry = faction == GarrisonFactionIndex.Horde ? plot.HordeConstructionGameObjectID : plot.AllianceConstructionGameObjectID;
|
||||
if (BuildingInfo.PacketInfo.Value.Active || entry == 0)
|
||||
entry = faction == GarrisonFactionIndex.Horde ? building.HordeGameObjectID : building.AllianceGameObjectID;
|
||||
}
|
||||
|
||||
if (Global.ObjectMgr.GetGameObjectTemplate(entry) == null)
|
||||
{
|
||||
Log.outError(LogFilter.Garrison, "Garrison attempted to spawn gameobject whose template doesn't exist ({0})", entry);
|
||||
return null;
|
||||
}
|
||||
|
||||
Position pos = PacketInfo.PlotPos;
|
||||
GameObject go = new GameObject();
|
||||
if (!go.Create(entry, map, 0, pos, Quaternion.WAxis, 255, GameObjectState.Active))
|
||||
return null;
|
||||
|
||||
if (BuildingInfo.CanActivate() && BuildingInfo.PacketInfo.HasValue && !BuildingInfo.PacketInfo.Value.Active)
|
||||
{
|
||||
FinalizeGarrisonPlotGOInfo finalizeInfo = Global.GarrisonMgr.GetPlotFinalizeGOInfo(PacketInfo.GarrPlotInstanceID);
|
||||
if (finalizeInfo != null)
|
||||
{
|
||||
Position pos2 = finalizeInfo.factionInfo[faction].Pos;
|
||||
GameObject finalizer = new GameObject();
|
||||
if (finalizer.Create(finalizeInfo.factionInfo[faction].GameObjectId, map, 0, pos2, Quaternion.WAxis, 255, GameObjectState.Ready))
|
||||
{
|
||||
// set some spell id to make the object delete itself after use
|
||||
finalizer.SetSpellId(finalizer.GetGoInfo().Goober.spell);
|
||||
finalizer.SetRespawnTime(0);
|
||||
|
||||
ushort animKit = finalizeInfo.factionInfo[faction].AnimKitId;
|
||||
if (animKit != 0)
|
||||
finalizer.SetAnimKitId(animKit, false);
|
||||
|
||||
map.AddToMap(finalizer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (go.GetGoType() == GameObjectTypes.GarrisonBuilding && go.GetGoInfo().garrisonBuilding.SpawnMap != 0)
|
||||
{
|
||||
foreach (var cellGuids in Global.ObjectMgr.GetMapObjectGuids((uint)go.GetGoInfo().garrisonBuilding.SpawnMap, (byte)map.GetSpawnMode()))
|
||||
{
|
||||
foreach (var spawnId in cellGuids.Value.creatures)
|
||||
{
|
||||
Creature spawn = BuildingSpawnHelper<Creature>(go, spawnId, map);
|
||||
if (spawn)
|
||||
BuildingInfo.Spawns.Add(spawn.GetGUID());
|
||||
}
|
||||
|
||||
foreach (var spawnId in cellGuids.Value.gameobjects)
|
||||
{
|
||||
GameObject spawn = BuildingSpawnHelper<GameObject>(go, spawnId, map);
|
||||
if (spawn)
|
||||
BuildingInfo.Spawns.Add(spawn.GetGUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BuildingInfo.Guid = go.GetGUID();
|
||||
return go;
|
||||
}
|
||||
|
||||
public void DeleteGameObject(Map map)
|
||||
{
|
||||
if (BuildingInfo.Guid.IsEmpty())
|
||||
return;
|
||||
|
||||
foreach (var guid in BuildingInfo.Spawns)
|
||||
{
|
||||
WorldObject obj = null;
|
||||
switch (guid.GetHigh())
|
||||
{
|
||||
case HighGuid.Creature:
|
||||
obj = map.GetCreature(guid);
|
||||
break;
|
||||
case HighGuid.GameObject:
|
||||
obj = map.GetGameObject(guid);
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (obj)
|
||||
obj.AddObjectToRemoveList();
|
||||
}
|
||||
|
||||
BuildingInfo.Spawns.Clear();
|
||||
|
||||
GameObject oldBuilding = map.GetGameObject(BuildingInfo.Guid);
|
||||
if (oldBuilding)
|
||||
oldBuilding.Delete();
|
||||
|
||||
BuildingInfo.Guid.Clear();
|
||||
}
|
||||
|
||||
public void ClearBuildingInfo(Player owner)
|
||||
{
|
||||
GarrisonPlotPlaced plotPlaced = new GarrisonPlotPlaced();
|
||||
plotPlaced.GarrTypeID = GarrisonType.Garrison;
|
||||
plotPlaced.PlotInfo = PacketInfo;
|
||||
owner.SendPacket(plotPlaced);
|
||||
|
||||
BuildingInfo.PacketInfo.Clear();
|
||||
}
|
||||
|
||||
public void SetBuildingInfo(GarrisonBuildingInfo buildingInfo, Player owner)
|
||||
{
|
||||
if (!BuildingInfo.PacketInfo.HasValue)
|
||||
{
|
||||
GarrisonPlotRemoved plotRemoved = new GarrisonPlotRemoved();
|
||||
plotRemoved.GarrPlotInstanceID = PacketInfo.GarrPlotInstanceID;
|
||||
owner.SendPacket(plotRemoved);
|
||||
}
|
||||
|
||||
BuildingInfo.PacketInfo.Set(buildingInfo);
|
||||
}
|
||||
|
||||
T BuildingSpawnHelper<T>(GameObject building, ulong spawnId, Map map) where T : WorldObject, new()
|
||||
{
|
||||
T spawn = new T();
|
||||
if (!spawn.LoadFromDB(spawnId, map))
|
||||
return null;
|
||||
|
||||
float x = spawn.GetPositionX();
|
||||
float y = spawn.GetPositionY();
|
||||
float z = spawn.GetPositionZ();
|
||||
float o = spawn.GetOrientation();
|
||||
TransportPosHelper.CalculatePassengerPosition(ref x, ref y, ref z, ref o, building.GetPositionX(), building.GetPositionY(), building.GetPositionZ(), building.GetOrientation());
|
||||
|
||||
spawn.Relocate(x, y, z, o);
|
||||
switch (spawn.GetTypeId())
|
||||
{
|
||||
case TypeId.Unit:
|
||||
spawn.ToCreature().SetHomePosition(x, y, z, o);
|
||||
break;
|
||||
case TypeId.GameObject:
|
||||
spawn.ToGameObject().RelocateStationaryPosition(x, y, z, o);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!spawn.IsPositionValid())
|
||||
return null;
|
||||
|
||||
if (!map.AddToMap(spawn))
|
||||
return null;
|
||||
|
||||
return spawn;
|
||||
}
|
||||
|
||||
public GarrisonPlotInfo PacketInfo;
|
||||
public uint EmptyGameObjectId;
|
||||
public uint GarrSiteLevelPlotInstId;
|
||||
public Building BuildingInfo;
|
||||
}
|
||||
|
||||
public class Follower
|
||||
{
|
||||
public uint GetItemLevel()
|
||||
{
|
||||
return (PacketInfo.ItemLevelWeapon + PacketInfo.ItemLevelArmor) / 2;
|
||||
}
|
||||
|
||||
public GarrisonFollower PacketInfo = new GarrisonFollower();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user