mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-21 01:37:37 +01:00
Core/Garrison: dropped Garrison implementation
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
DROP TABLE IF EXISTS `character_garrison`;
|
||||
DROP TABLE IF EXISTS `character_garrison_blueprints`;
|
||||
DROP TABLE IF EXISTS `character_garrison_buildings`;
|
||||
DROP TABLE IF EXISTS `character_garrison_follower_abilities`;
|
||||
DROP TABLE IF EXISTS `character_garrison_followers`;
|
||||
@@ -697,23 +697,6 @@ void CharacterDatabaseConnection::DoPrepareStatements()
|
||||
PrepareStatement(CHAR_UPD_QUEST_TRACK_COMPLETE_TIME, "UPDATE quest_tracker SET quest_complete_time = NOW() WHERE id = ? AND character_guid = ? ORDER BY quest_accept_time DESC LIMIT 1", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_QUEST_TRACK_ABANDON_TIME, "UPDATE quest_tracker SET quest_abandon_time = NOW() WHERE id = ? AND character_guid = ? ORDER BY quest_accept_time DESC LIMIT 1", CONNECTION_ASYNC);
|
||||
|
||||
// Garrison
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_GARRISON, "SELECT siteLevelId, followerActivationsRemainingToday FROM character_garrison WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHARACTER_GARRISON, "INSERT INTO character_garrison (guid, siteLevelId, followerActivationsRemainingToday) VALUES (?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHARACTER_GARRISON, "DELETE FROM character_garrison WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_CHARACTER_GARRISON_FOLLOWER_ACTIVATIONS, "UPDATE character_garrison SET followerActivationsRemainingToday = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_GARRISON_BLUEPRINTS, "SELECT buildingId FROM character_garrison_blueprints WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHARACTER_GARRISON_BLUEPRINTS, "INSERT INTO character_garrison_blueprints (guid, buildingId) VALUES (?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_BLUEPRINTS, "DELETE FROM character_garrison_blueprints WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_GARRISON_BUILDINGS, "SELECT plotInstanceId, buildingId, timeBuilt, active FROM character_garrison_buildings WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHARACTER_GARRISON_BUILDINGS, "INSERT INTO character_garrison_buildings (guid, plotInstanceId, buildingId, timeBuilt, active) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_BUILDINGS, "DELETE FROM character_garrison_buildings WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_GARRISON_FOLLOWERS, "SELECT dbId, followerId, quality, level, itemLevelWeapon, itemLevelArmor, xp, currentBuilding, currentMission, status FROM character_garrison_followers WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHARACTER_GARRISON_FOLLOWERS, "INSERT INTO character_garrison_followers (dbId, guid, followerId, quality, level, itemLevelWeapon, itemLevelArmor, xp, currentBuilding, currentMission, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_FOLLOWERS, "DELETE gfab, gf FROM character_garrison_follower_abilities gfab INNER JOIN character_garrison_followers gf ON gfab.dbId = gf.dbId WHERE gf.guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_GARRISON_FOLLOWER_ABILITIES, "SELECT gfab.dbId, gfab.abilityId FROM character_garrison_follower_abilities gfab INNER JOIN character_garrison_followers gf ON gfab.dbId = gf.dbId WHERE guid = ? ORDER BY gfab.slot", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHARACTER_GARRISON_FOLLOWER_ABILITIES, "INSERT INTO character_garrison_follower_abilities (dbId, abilityId, slot) VALUES (?, ?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
// Black Market
|
||||
PrepareStatement(CHAR_SEL_BLACKMARKET_AUCTIONS, "SELECT marketId, currentBid, time, numBids, bidder FROM blackmarket_auctions", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_DEL_BLACKMARKET_AUCTIONS, "DELETE FROM blackmarket_auctions WHERE marketId = ?", CONNECTION_ASYNC);
|
||||
|
||||
@@ -573,22 +573,6 @@ enum CharacterDatabaseStatements : uint32
|
||||
CHAR_UPD_QUEST_TRACK_COMPLETE_TIME,
|
||||
CHAR_UPD_QUEST_TRACK_ABANDON_TIME,
|
||||
|
||||
CHAR_SEL_CHARACTER_GARRISON,
|
||||
CHAR_INS_CHARACTER_GARRISON,
|
||||
CHAR_DEL_CHARACTER_GARRISON,
|
||||
CHAR_UPD_CHARACTER_GARRISON_FOLLOWER_ACTIVATIONS,
|
||||
CHAR_SEL_CHARACTER_GARRISON_BLUEPRINTS,
|
||||
CHAR_INS_CHARACTER_GARRISON_BLUEPRINTS,
|
||||
CHAR_DEL_CHARACTER_GARRISON_BLUEPRINTS,
|
||||
CHAR_SEL_CHARACTER_GARRISON_BUILDINGS,
|
||||
CHAR_INS_CHARACTER_GARRISON_BUILDINGS,
|
||||
CHAR_DEL_CHARACTER_GARRISON_BUILDINGS,
|
||||
CHAR_SEL_CHARACTER_GARRISON_FOLLOWERS,
|
||||
CHAR_INS_CHARACTER_GARRISON_FOLLOWERS,
|
||||
CHAR_DEL_CHARACTER_GARRISON_FOLLOWERS,
|
||||
CHAR_SEL_CHARACTER_GARRISON_FOLLOWER_ABILITIES,
|
||||
CHAR_INS_CHARACTER_GARRISON_FOLLOWER_ABILITIES,
|
||||
|
||||
CHAR_SEL_BLACKMARKET_AUCTIONS,
|
||||
CHAR_DEL_BLACKMARKET_AUCTIONS,
|
||||
CHAR_UPD_BLACKMARKET_AUCTIONS,
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#include "DisableMgr.h"
|
||||
#include "GameEventMgr.h"
|
||||
#include "GameTime.h"
|
||||
#include "Garrison.h"
|
||||
#include "Group.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "Item.h"
|
||||
@@ -2347,334 +2346,31 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
|
||||
return false;
|
||||
break;
|
||||
case ModifierTreeType::GarrisonTierEqualOrGreaterThan: // 126
|
||||
{
|
||||
Garrison const* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison || garrison->GetType() != GarrisonType(secondaryAsset) || garrison->GetSiteLevel()->GarrLevel < reqValue)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType::GarrisonFollowersWithLevelEqualOrGreaterThan: // 127
|
||||
{
|
||||
Garrison const* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison)
|
||||
return false;
|
||||
uint32 followerCount = garrison->CountFollowers([secondaryAsset, tertiaryAsset](Garrison::Follower const& follower)
|
||||
{
|
||||
GarrFollowerEntry const* garrFollower = sGarrFollowerStore.AssertEntry(follower.PacketInfo.GarrFollowerID);
|
||||
return garrFollower->GarrFollowerTypeID == tertiaryAsset && follower.PacketInfo.FollowerLevel >= secondaryAsset;
|
||||
});
|
||||
if (followerCount < reqValue)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType::GarrisonFollowersWithQualityEqualOrGreaterThan: // 128
|
||||
{
|
||||
Garrison const* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison)
|
||||
return false;
|
||||
uint32 followerCount = garrison->CountFollowers([secondaryAsset, tertiaryAsset](Garrison::Follower const& follower)
|
||||
{
|
||||
GarrFollowerEntry const* garrFollower = sGarrFollowerStore.AssertEntry(follower.PacketInfo.GarrFollowerID);
|
||||
return garrFollower->GarrFollowerTypeID == tertiaryAsset && follower.PacketInfo.Quality >= secondaryAsset;
|
||||
});
|
||||
if (followerCount < reqValue)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType::GarrisonFollowerWithAbilityAtLevelEqualOrGreaterThan: // 129
|
||||
{
|
||||
Garrison const* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison)
|
||||
return false;
|
||||
uint32 followerCount = garrison->CountFollowers([reqValue, secondaryAsset, tertiaryAsset](Garrison::Follower const& follower)
|
||||
{
|
||||
GarrFollowerEntry const* garrFollower = sGarrFollowerStore.AssertEntry(follower.PacketInfo.GarrFollowerID);
|
||||
return garrFollower->GarrFollowerTypeID == tertiaryAsset && follower.PacketInfo.FollowerLevel >= reqValue && follower.HasAbility(secondaryAsset);
|
||||
});
|
||||
if (followerCount < 1)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType::GarrisonFollowerWithTraitAtLevelEqualOrGreaterThan: // 130
|
||||
{
|
||||
Garrison const* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison)
|
||||
return false;
|
||||
GarrAbilityEntry const* traitEntry = sGarrAbilityStore.LookupEntry(secondaryAsset);
|
||||
if (!traitEntry || !(traitEntry->Flags & GARRISON_ABILITY_FLAG_TRAIT))
|
||||
return false;
|
||||
uint32 followerCount = garrison->CountFollowers([reqValue, secondaryAsset, tertiaryAsset](Garrison::Follower const& follower)
|
||||
{
|
||||
GarrFollowerEntry const* garrFollower = sGarrFollowerStore.AssertEntry(follower.PacketInfo.GarrFollowerID);
|
||||
return garrFollower->GarrFollowerTypeID == tertiaryAsset && follower.PacketInfo.FollowerLevel >= reqValue && follower.HasAbility(secondaryAsset);
|
||||
});
|
||||
if (followerCount < 1)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType::GarrisonFollowerWithAbilityAssignedToBuilding: // 131
|
||||
{
|
||||
Garrison const* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
|
||||
return false;
|
||||
uint32 followerCount = garrison->CountFollowers([reqValue, secondaryAsset](Garrison::Follower const& follower)
|
||||
{
|
||||
GarrBuildingEntry const* followerBuilding = sGarrBuildingStore.LookupEntry(follower.PacketInfo.CurrentBuildingID);
|
||||
if (!followerBuilding)
|
||||
return false;
|
||||
return followerBuilding->BuildingType == int32(secondaryAsset) && follower.HasAbility(reqValue);;
|
||||
});
|
||||
if (followerCount < 1)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType::GarrisonFollowerWithTraitAssignedToBuilding: // 132
|
||||
{
|
||||
Garrison const* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
|
||||
return false;
|
||||
GarrAbilityEntry const* traitEntry = sGarrAbilityStore.LookupEntry(reqValue);
|
||||
if (!traitEntry || !(traitEntry->Flags & GARRISON_ABILITY_FLAG_TRAIT))
|
||||
return false;
|
||||
uint32 followerCount = garrison->CountFollowers([reqValue, secondaryAsset](Garrison::Follower const& follower)
|
||||
{
|
||||
GarrBuildingEntry const* followerBuilding = sGarrBuildingStore.LookupEntry(follower.PacketInfo.CurrentBuildingID);
|
||||
if (!followerBuilding)
|
||||
return false;
|
||||
return followerBuilding->BuildingType == int32(secondaryAsset) && follower.HasAbility(reqValue);;
|
||||
});
|
||||
if (followerCount < 1)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType::GarrisonFollowerWithLevelAssignedToBuilding: // 133
|
||||
{
|
||||
Garrison const* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
|
||||
return false;
|
||||
uint32 followerCount = garrison->CountFollowers([reqValue, secondaryAsset](Garrison::Follower const& follower)
|
||||
{
|
||||
if (follower.PacketInfo.FollowerLevel < reqValue)
|
||||
return false;
|
||||
GarrBuildingEntry const* followerBuilding = sGarrBuildingStore.LookupEntry(follower.PacketInfo.CurrentBuildingID);
|
||||
if (!followerBuilding)
|
||||
return false;
|
||||
return followerBuilding->BuildingType == int32(secondaryAsset);
|
||||
});
|
||||
if (followerCount < 1)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType::GarrisonBuildingWithLevelEqualOrGreaterThan: // 134
|
||||
{
|
||||
Garrison* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
|
||||
return false;
|
||||
for (Garrison::Plot const* plot : garrison->GetPlots())
|
||||
{
|
||||
if (!plot->BuildingInfo.PacketInfo)
|
||||
continue;
|
||||
|
||||
GarrBuildingEntry const* building = sGarrBuildingStore.LookupEntry(plot->BuildingInfo.PacketInfo->GarrBuildingID);
|
||||
if (!building || building->UpgradeLevel < reqValue || building->BuildingType != int32(secondaryAsset))
|
||||
continue;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case ModifierTreeType::HasBlueprintForGarrisonBuilding: // 135
|
||||
{
|
||||
Garrison const* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison || garrison->GetType() != GarrisonType(secondaryAsset))
|
||||
return false;
|
||||
if (!garrison->HasBlueprint(reqValue))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType::HasGarrisonBuildingSpecialization: // 136
|
||||
return false; // OBSOLETE
|
||||
case ModifierTreeType::AllGarrisonPlotsAreFull: // 137
|
||||
{
|
||||
Garrison* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison || garrison->GetType() != GarrisonType(reqValue))
|
||||
return false;
|
||||
for (Garrison::Plot const* plot : garrison->GetPlots())
|
||||
if (!plot->BuildingInfo.PacketInfo)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType::PlayerIsInOwnGarrison: // 138
|
||||
if (!referencePlayer->GetMap()->IsGarrison() || referencePlayer->GetMap()->GetInstanceId() != referencePlayer->GetGUID().GetCounter())
|
||||
return false;
|
||||
break;
|
||||
case ModifierTreeType::GarrisonShipmentOfTypeIsPending: // 139 NYI
|
||||
return false;
|
||||
case ModifierTreeType::GarrisonBuildingIsUnderConstruction: // 140
|
||||
{
|
||||
GarrBuildingEntry const* building = sGarrBuildingStore.LookupEntry(reqValue);
|
||||
if (!building)
|
||||
return false;
|
||||
Garrison* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
|
||||
return false;
|
||||
for (Garrison::Plot const* plot : garrison->GetPlots())
|
||||
{
|
||||
if (!plot->BuildingInfo.PacketInfo || plot->BuildingInfo.PacketInfo->GarrBuildingID != reqValue)
|
||||
continue;
|
||||
|
||||
return !plot->BuildingInfo.PacketInfo->Active;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case ModifierTreeType::GarrisonMissionHasBeenCompleted: // 141 NYI
|
||||
return false;
|
||||
case ModifierTreeType::GarrisonBuildingLevelEqual: // 142
|
||||
{
|
||||
Garrison* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
|
||||
return false;
|
||||
for (Garrison::Plot const* plot : garrison->GetPlots())
|
||||
{
|
||||
if (!plot->BuildingInfo.PacketInfo)
|
||||
continue;
|
||||
|
||||
GarrBuildingEntry const* building = sGarrBuildingStore.LookupEntry(plot->BuildingInfo.PacketInfo->GarrBuildingID);
|
||||
if (!building || building->UpgradeLevel != secondaryAsset || building->BuildingType != int32(reqValue))
|
||||
continue;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case ModifierTreeType::GarrisonFollowerHasAbility: // 143
|
||||
{
|
||||
Garrison const* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison || garrison->GetType() != GarrisonType(secondaryAsset))
|
||||
return false;
|
||||
if (miscValue1)
|
||||
{
|
||||
Garrison::Follower const* follower = garrison->GetFollower(miscValue1);
|
||||
if (!follower)
|
||||
return false;
|
||||
if (!follower->HasAbility(reqValue))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 followerCount = garrison->CountFollowers([reqValue](Garrison::Follower const& follower)
|
||||
{
|
||||
return follower.HasAbility(reqValue);
|
||||
});
|
||||
if (followerCount < 1)
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType::GarrisonFollowerHasTrait: // 144
|
||||
{
|
||||
GarrAbilityEntry const* traitEntry = sGarrAbilityStore.LookupEntry(reqValue);
|
||||
if (!traitEntry || !(traitEntry->Flags & GARRISON_ABILITY_FLAG_TRAIT))
|
||||
return false;
|
||||
Garrison const* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison || garrison->GetType() != GarrisonType(secondaryAsset))
|
||||
return false;
|
||||
if (miscValue1)
|
||||
{
|
||||
Garrison::Follower const* follower = garrison->GetFollower(miscValue1);
|
||||
if (!follower || !follower->HasAbility(reqValue))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 followerCount = garrison->CountFollowers([reqValue](Garrison::Follower const& follower)
|
||||
{
|
||||
return follower.HasAbility(reqValue);
|
||||
});
|
||||
if (followerCount < 1)
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType::GarrisonFollowerQualityEqual: // 145
|
||||
{
|
||||
Garrison const* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison || garrison->GetType() != GARRISON_TYPE_GARRISON)
|
||||
return false;
|
||||
if (miscValue1)
|
||||
{
|
||||
Garrison::Follower const* follower = garrison->GetFollower(miscValue1);
|
||||
if (!follower || follower->PacketInfo.Quality < reqValue)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 followerCount = garrison->CountFollowers([reqValue](Garrison::Follower const& follower)
|
||||
{
|
||||
return follower.PacketInfo.Quality >= reqValue;
|
||||
});
|
||||
if (followerCount < 1)
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType::GarrisonFollowerLevelEqual: // 146
|
||||
{
|
||||
Garrison const* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison || garrison->GetType() != GarrisonType(secondaryAsset))
|
||||
return false;
|
||||
if (miscValue1)
|
||||
{
|
||||
Garrison::Follower const* follower = garrison->GetFollower(miscValue1);
|
||||
if (!follower || follower->PacketInfo.FollowerLevel != reqValue)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 followerCount = garrison->CountFollowers([reqValue](Garrison::Follower const& follower)
|
||||
{
|
||||
return follower.PacketInfo.FollowerLevel == reqValue;
|
||||
});
|
||||
if (followerCount < 1)
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType::GarrisonMissionIsRare: // 147 NYI
|
||||
case ModifierTreeType::GarrisonMissionIsElite: // 148 NYI
|
||||
return false;
|
||||
case ModifierTreeType::CurrentGarrisonBuildingLevelEqual: // 149
|
||||
{
|
||||
if (!miscValue1)
|
||||
return false;
|
||||
Garrison* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison)
|
||||
return false;
|
||||
for (Garrison::Plot const* plot : garrison->GetPlots())
|
||||
{
|
||||
if (!plot->BuildingInfo.PacketInfo || plot->BuildingInfo.PacketInfo->GarrBuildingID != miscValue1)
|
||||
continue;
|
||||
|
||||
GarrBuildingEntry const* building = sGarrBuildingStore.LookupEntry(plot->BuildingInfo.PacketInfo->GarrBuildingID);
|
||||
if (!building || building->UpgradeLevel != reqValue)
|
||||
continue;
|
||||
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType::GarrisonPlotInstanceHasBuildingThatIsReadyToActivate: // 150
|
||||
{
|
||||
Garrison* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison)
|
||||
return false;
|
||||
Garrison::Plot const* plot = garrison->GetPlot(reqValue);
|
||||
if (!plot)
|
||||
return false;
|
||||
if (!plot->BuildingInfo.CanActivate() || !plot->BuildingInfo.PacketInfo || plot->BuildingInfo.PacketInfo->Active)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
case ModifierTreeType::BattlePetTeamWithSpeciesEqualOrGreaterThan: // 151
|
||||
{
|
||||
uint32 count = 0;
|
||||
@@ -2710,20 +2406,8 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType::HasGarrisonBuildingActiveSpecialization: // 156
|
||||
return false; // OBSOLETE
|
||||
case ModifierTreeType::HasGarrisonFollower: // 157
|
||||
{
|
||||
Garrison const* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison)
|
||||
return false;
|
||||
uint32 followerCount = garrison->CountFollowers([reqValue](Garrison::Follower const& follower)
|
||||
{
|
||||
return follower.PacketInfo.GarrFollowerID == reqValue;
|
||||
});
|
||||
if (followerCount < 1)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
case ModifierTreeType::PlayerQuestObjectiveProgressEqual: // 158
|
||||
{
|
||||
QuestObjective const* objective = sObjectMgr->GetQuestObjective(reqValue);
|
||||
@@ -2755,58 +2439,11 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
|
||||
return false;
|
||||
break;
|
||||
case ModifierTreeType::AllGarrisonPlotsFilledWithBuildingsWithLevelEqualOrGreater: // 166
|
||||
{
|
||||
Garrison* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison || garrison->GetType() != GarrisonType(reqValue))
|
||||
return false;
|
||||
for (Garrison::Plot const* plot : garrison->GetPlots())
|
||||
{
|
||||
if (!plot->BuildingInfo.PacketInfo)
|
||||
return false;
|
||||
GarrBuildingEntry const* building = sGarrBuildingStore.LookupEntry(plot->BuildingInfo.PacketInfo->GarrBuildingID);
|
||||
if (!building || building->UpgradeLevel != reqValue)
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType::GarrisonMissionType: // 167 NYI
|
||||
return false;
|
||||
case ModifierTreeType::GarrisonFollowerItemLevelEqualOrGreaterThan: // 168
|
||||
{
|
||||
if (!miscValue1)
|
||||
return false;
|
||||
Garrison const* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison)
|
||||
return false;
|
||||
uint32 followerCount = garrison->CountFollowers([miscValue1, reqValue](Garrison::Follower const& follower)
|
||||
{
|
||||
return follower.PacketInfo.GarrFollowerID == miscValue1 && follower.GetItemLevel() >= reqValue;
|
||||
});
|
||||
if (followerCount < 1)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType::GarrisonFollowerCountWithItemLevelEqualOrGreaterThan: // 169
|
||||
{
|
||||
Garrison const* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison)
|
||||
return false;
|
||||
uint32 followerCount = garrison->CountFollowers([secondaryAsset, tertiaryAsset](Garrison::Follower const& follower)
|
||||
{
|
||||
GarrFollowerEntry const* garrFollower = sGarrFollowerStore.AssertEntry(follower.PacketInfo.GarrFollowerID);
|
||||
return garrFollower->GarrFollowerTypeID == tertiaryAsset && follower.GetItemLevel() >= secondaryAsset;
|
||||
});
|
||||
if (followerCount < reqValue)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType::GarrisonTierEqual: // 170
|
||||
{
|
||||
Garrison const* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison || garrison->GetType() != GarrisonType(secondaryAsset) || garrison->GetSiteLevel()->GarrLevel != reqValue)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
case ModifierTreeType::InstancePlayerCountEqual: // 171
|
||||
if (referencePlayer->GetMap()->GetPlayers().getSize() != reqValue)
|
||||
return false;
|
||||
@@ -2829,70 +2466,12 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType::GarrisonFollowerCountWithLevelEqualOrGreaterThan: // 175
|
||||
{
|
||||
Garrison const* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
|
||||
return false;
|
||||
uint32 followerCount = garrison->CountFollowers([secondaryAsset, tertiaryAsset](Garrison::Follower const& follower)
|
||||
{
|
||||
GarrFollowerEntry const* garrFollower = sGarrFollowerStore.AssertEntry(follower.PacketInfo.GarrFollowerID);
|
||||
return garrFollower->GarrFollowerTypeID == tertiaryAsset && follower.PacketInfo.FollowerLevel == secondaryAsset;
|
||||
});
|
||||
if (followerCount < reqValue)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType::GarrisonFollowerIsInBuilding: // 176
|
||||
{
|
||||
Garrison const* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison)
|
||||
return false;
|
||||
uint32 followerCount = garrison->CountFollowers([reqValue, secondaryAsset](Garrison::Follower const& follower)
|
||||
{
|
||||
return follower.PacketInfo.GarrFollowerID == reqValue && follower.PacketInfo.CurrentBuildingID == secondaryAsset;
|
||||
});
|
||||
if (followerCount < 1)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType::GarrisonMissionCountLessThan: // 177 NYI
|
||||
return false;
|
||||
case ModifierTreeType::GarrisonPlotInstanceCountEqualOrGreaterThan: // 178
|
||||
{
|
||||
Garrison* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison || garrison->GetType() != GarrisonType(reqValue))
|
||||
return false;
|
||||
uint32 plotCount = 0;
|
||||
for (Garrison::Plot const* plot : garrison->GetPlots())
|
||||
{
|
||||
GarrPlotInstanceEntry const* garrPlotInstance = sGarrPlotInstanceStore.LookupEntry(plot->PacketInfo.GarrPlotInstanceID);
|
||||
if (!garrPlotInstance || garrPlotInstance->GarrPlotID != secondaryAsset)
|
||||
continue;
|
||||
++plotCount;
|
||||
}
|
||||
if (plotCount < reqValue)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType::CurrencySource: // 179 NYI
|
||||
return false;
|
||||
case ModifierTreeType::PlayerIsInNotOwnGarrison: // 180
|
||||
if (!referencePlayer->GetMap()->IsGarrison() || referencePlayer->GetMap()->GetInstanceId() == referencePlayer->GetGUID().GetCounter())
|
||||
return false;
|
||||
break;
|
||||
case ModifierTreeType::HasActiveGarrisonFollower: // 181
|
||||
{
|
||||
Garrison const* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison)
|
||||
return false;
|
||||
uint32 followerCount = garrison->CountFollowers([reqValue](Garrison::Follower const& follower)
|
||||
{
|
||||
return follower.PacketInfo.GarrFollowerID == reqValue && !(follower.PacketInfo.FollowerStatus & FOLLOWER_STATUS_INACTIVE);
|
||||
});
|
||||
if (followerCount < 1)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType::PlayerDailyRandomValueMod_X_Equals: // 182 NYI
|
||||
return false;
|
||||
case ModifierTreeType::PlayerHasMount: // 183
|
||||
@@ -2909,43 +2488,9 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
|
||||
return false;
|
||||
}
|
||||
case ModifierTreeType::GarrisonFollowerCountWithInactiveWithItemLevelEqualOrGreaterThan: // 184
|
||||
{
|
||||
Garrison const* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison)
|
||||
return false;
|
||||
uint32 followerCount = garrison->CountFollowers([secondaryAsset, tertiaryAsset](Garrison::Follower const& follower)
|
||||
{
|
||||
GarrFollowerEntry const* garrFollower = sGarrFollowerStore.LookupEntry(follower.PacketInfo.GarrFollowerID);
|
||||
if (!garrFollower)
|
||||
return false;
|
||||
return follower.GetItemLevel() >= secondaryAsset && garrFollower->GarrFollowerTypeID == tertiaryAsset;
|
||||
});
|
||||
if (followerCount < reqValue)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType::GarrisonFollowerIsOnAMission: // 185
|
||||
{
|
||||
Garrison const* garrison = referencePlayer->GetGarrison();
|
||||
if (!garrison)
|
||||
return false;
|
||||
uint32 followerCount = garrison->CountFollowers([reqValue](Garrison::Follower const& follower)
|
||||
{
|
||||
return follower.PacketInfo.GarrFollowerID == reqValue && follower.PacketInfo.CurrentMissionID != 0;
|
||||
});
|
||||
if (followerCount < 1)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType::GarrisonMissionCountInSetLessThan: // 186 NYI
|
||||
return false;
|
||||
case ModifierTreeType::GarrisonFollowerType: // 187
|
||||
{
|
||||
GarrFollowerEntry const* garrFollower = sGarrFollowerStore.LookupEntry(miscValue1);
|
||||
if (!garrFollower || garrFollower->GarrFollowerTypeID != int32(reqValue))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType::PlayerUsedBoostLessThanHoursAgoRealTime: // 188 NYI
|
||||
case ModifierTreeType::PlayerUsedBoostLessThanHoursAgoGameTime: // 189 NYI
|
||||
return false;
|
||||
|
||||
@@ -55,8 +55,6 @@
|
||||
#include "GameEventMgr.h"
|
||||
#include "GameEventSender.h"
|
||||
#include "GameObjectAI.h"
|
||||
#include "Garrison.h"
|
||||
#include "GarrisonMgr.h"
|
||||
#include "GitRevision.h"
|
||||
#include "GossipDef.h"
|
||||
#include "GridNotifiers.h"
|
||||
@@ -4254,8 +4252,6 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
|
||||
|
||||
Corpse::DeleteFromDB(playerguid, trans);
|
||||
|
||||
Garrison::DeleteFromDB(guid, trans);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_TRAIT_ENTRIES_BY_CHAR);
|
||||
stmt->setUInt64(0, guid);
|
||||
trans->Append(stmt);
|
||||
@@ -7005,7 +7001,6 @@ void Player::ModifyCurrency(uint32 id, int32 amount, CurrencyGainSource gainSour
|
||||
bool isGainOnRefund = [&]() -> bool
|
||||
{
|
||||
if (gainSource == CurrencyGainSource::ItemRefund ||
|
||||
gainSource == CurrencyGainSource::GarrisonBuildingRefund ||
|
||||
gainSource == CurrencyGainSource::PlayerTraitRefund)
|
||||
return true;
|
||||
|
||||
@@ -17720,14 +17715,6 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
|
||||
|
||||
_LoadCUFProfiles(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_CUF_PROFILES));
|
||||
|
||||
std::unique_ptr<Garrison> garrison = std::make_unique<Garrison>(this);
|
||||
if (garrison->LoadFromDB(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON),
|
||||
holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_BLUEPRINTS),
|
||||
holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_BUILDINGS),
|
||||
holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWERS),
|
||||
holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWER_ABILITIES)))
|
||||
_garrison = std::move(garrison);
|
||||
|
||||
_InitHonorLevelOnLoadFromDB(fields.honor, fields.honorLevel);
|
||||
|
||||
_restMgr->LoadRestBonus(REST_TYPE_HONOR, fields.honorRestState, fields.honorRestBonus);
|
||||
@@ -19483,8 +19470,6 @@ void Player::SaveToDB(LoginDatabaseTransaction loginTransaction, CharacterDataba
|
||||
_SaveInstanceTimeRestrictions(trans);
|
||||
_SaveCurrency(trans);
|
||||
_SaveCUFProfiles(trans);
|
||||
if (_garrison)
|
||||
_garrison->SaveToDB(trans);
|
||||
|
||||
// check if stats should only be saved on logout
|
||||
// save stats can be out of transaction
|
||||
@@ -23490,9 +23475,6 @@ void Player::SendInitialPacketsAfterAddToMap()
|
||||
|
||||
PhasingHandler::OnMapChange(this);
|
||||
|
||||
if (_garrison)
|
||||
_garrison->SendRemoteInfo();
|
||||
|
||||
UpdateItemLevelAreaBasedScaling();
|
||||
|
||||
if (!GetPlayerSharingQuest().IsEmpty())
|
||||
@@ -23967,9 +23949,6 @@ void Player::DailyReset()
|
||||
m_DailyQuestChanged = false;
|
||||
m_lastDailyQuestTime = 0;
|
||||
|
||||
if (_garrison)
|
||||
_garrison->ResetFollowerActivationLimit();
|
||||
|
||||
FailCriteria(CriteriaFailEvent::DailyQuestsCleared, 0);
|
||||
}
|
||||
|
||||
@@ -27941,22 +27920,6 @@ VoidStorageItem* Player::GetVoidStorageItem(uint64 id, uint8& slot) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Player::CreateGarrison(uint32 garrSiteId)
|
||||
{
|
||||
std::unique_ptr<Garrison> garrison(new Garrison(this));
|
||||
if (garrison->Create(garrSiteId))
|
||||
_garrison = std::move(garrison);
|
||||
}
|
||||
|
||||
void Player::DeleteGarrison()
|
||||
{
|
||||
if (_garrison)
|
||||
{
|
||||
_garrison->Delete();
|
||||
_garrison.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void Player::SendMovementSetCollisionHeight(float height, WorldPackets::Movement::UpdateCollisionHeightReason reason)
|
||||
{
|
||||
WorldPackets::Movement::MoveSetCollisionHeight setCollisionHeight;
|
||||
|
||||
@@ -71,7 +71,6 @@ class Channel;
|
||||
class CinematicMgr;
|
||||
class Creature;
|
||||
class DynamicObject;
|
||||
class Garrison;
|
||||
class Group;
|
||||
class Guild;
|
||||
class Item;
|
||||
@@ -876,11 +875,6 @@ enum PlayerLoginQueryIndex
|
||||
PLAYER_LOGIN_QUERY_LOAD_CUF_PROFILES,
|
||||
PLAYER_LOGIN_QUERY_LOAD_CORPSE_LOCATION,
|
||||
PLAYER_LOGIN_QUERY_LOAD_PET_SLOTS,
|
||||
PLAYER_LOGIN_QUERY_LOAD_GARRISON,
|
||||
PLAYER_LOGIN_QUERY_LOAD_GARRISON_BLUEPRINTS,
|
||||
PLAYER_LOGIN_QUERY_LOAD_GARRISON_BUILDINGS,
|
||||
PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWERS,
|
||||
PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWER_ABILITIES,
|
||||
PLAYER_LOGIN_QUERY_LOAD_TRAIT_ENTRIES,
|
||||
PLAYER_LOGIN_QUERY_LOAD_TRAIT_CONFIGS,
|
||||
MAX_PLAYER_LOGIN_QUERY
|
||||
@@ -2644,10 +2638,6 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
|
||||
bool IsReagentBankUnlocked() const { return HasPlayerFlagEx(PLAYER_FLAGS_EX_REAGENT_BANK_UNLOCKED); }
|
||||
void UnlockReagentBank() { SetPlayerFlagEx(PLAYER_FLAGS_EX_REAGENT_BANK_UNLOCKED); }
|
||||
|
||||
void CreateGarrison(uint32 garrSiteId);
|
||||
void DeleteGarrison();
|
||||
Garrison* GetGarrison() const { return _garrison.get(); }
|
||||
|
||||
bool IsAdvancedCombatLoggingEnabled() const { return _advancedCombatLoggingEnabled; }
|
||||
void SetAdvancedCombatLogging(bool enabled) { _advancedCombatLoggingEnabled = enabled; }
|
||||
|
||||
@@ -3128,8 +3118,6 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
|
||||
|
||||
uint32 _activeCheats;
|
||||
|
||||
std::unique_ptr<Garrison> _garrison;
|
||||
|
||||
bool _advancedCombatLoggingEnabled;
|
||||
|
||||
// variables to save health and mana before duel and restore them after duel
|
||||
|
||||
@@ -1,858 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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 2 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/>.
|
||||
*/
|
||||
|
||||
#include "Garrison.h"
|
||||
#include "Creature.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "DB2Stores.h"
|
||||
#include "GameObject.h"
|
||||
#include "GameTime.h"
|
||||
#include "GarrisonMgr.h"
|
||||
#include "Log.h"
|
||||
#include "Map.h"
|
||||
#include "MapManager.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "PhasingHandler.h"
|
||||
#include "Player.h"
|
||||
#include "VehicleDefines.h"
|
||||
|
||||
Garrison::Garrison(Player* owner) : _owner(owner), _siteLevel(nullptr), _followerActivationsRemainingToday(1)
|
||||
{
|
||||
}
|
||||
|
||||
bool Garrison::LoadFromDB(PreparedQueryResult garrison, PreparedQueryResult blueprints, PreparedQueryResult buildings,
|
||||
PreparedQueryResult followers, PreparedQueryResult abilities)
|
||||
{
|
||||
if (!garrison)
|
||||
return false;
|
||||
|
||||
Field* fields = garrison->Fetch();
|
||||
_siteLevel = sGarrSiteLevelStore.LookupEntry(fields[0].GetUInt32());
|
||||
_followerActivationsRemainingToday = fields[1].GetUInt32();
|
||||
if (!_siteLevel)
|
||||
return false;
|
||||
|
||||
InitializePlots();
|
||||
|
||||
if (blueprints)
|
||||
{
|
||||
do
|
||||
{
|
||||
fields = blueprints->Fetch();
|
||||
if (GarrBuildingEntry const* building = sGarrBuildingStore.LookupEntry(fields[0].GetUInt32()))
|
||||
_knownBuildings.insert(building->ID);
|
||||
|
||||
} while (blueprints->NextRow());
|
||||
}
|
||||
|
||||
if (buildings)
|
||||
{
|
||||
do
|
||||
{
|
||||
fields = buildings->Fetch();
|
||||
uint32 plotInstanceId = fields[0].GetUInt32();
|
||||
uint32 buildingId = fields[1].GetUInt32();
|
||||
time_t timeBuilt = fields[2].GetInt64();
|
||||
bool active = fields[3].GetBool();
|
||||
|
||||
Plot* plot = GetPlot(plotInstanceId);
|
||||
if (!plot)
|
||||
continue;
|
||||
|
||||
if (!sGarrBuildingStore.LookupEntry(buildingId))
|
||||
continue;
|
||||
|
||||
plot->BuildingInfo.PacketInfo.emplace();
|
||||
plot->BuildingInfo.PacketInfo->GarrPlotInstanceID = plotInstanceId;
|
||||
plot->BuildingInfo.PacketInfo->GarrBuildingID = buildingId;
|
||||
plot->BuildingInfo.PacketInfo->TimeBuilt = timeBuilt;
|
||||
plot->BuildingInfo.PacketInfo->Active = active;
|
||||
|
||||
} while (buildings->NextRow());
|
||||
}
|
||||
|
||||
// 0 1 2 3 4 5 6 7 8 9
|
||||
// SELECT dbId, followerId, quality, level, itemLevelWeapon, itemLevelArmor, xp, currentBuilding, currentMission, status FROM character_garrison_followers WHERE guid = ?
|
||||
if (followers)
|
||||
{
|
||||
do
|
||||
{
|
||||
fields = followers->Fetch();
|
||||
|
||||
uint64 dbId = fields[0].GetUInt64();
|
||||
uint32 followerId = fields[1].GetUInt32();
|
||||
if (!sGarrFollowerStore.LookupEntry(followerId))
|
||||
continue;
|
||||
|
||||
_followerIds.insert(followerId);
|
||||
Follower& follower = _followers[dbId];
|
||||
follower.PacketInfo.DbID = dbId;
|
||||
follower.PacketInfo.GarrFollowerID = followerId;
|
||||
follower.PacketInfo.Quality = fields[2].GetUInt32();
|
||||
follower.PacketInfo.FollowerLevel = fields[3].GetUInt32();
|
||||
follower.PacketInfo.ItemLevelWeapon = fields[4].GetUInt32();
|
||||
follower.PacketInfo.ItemLevelArmor = fields[5].GetUInt32();
|
||||
follower.PacketInfo.Xp = fields[6].GetUInt32();
|
||||
follower.PacketInfo.CurrentBuildingID = fields[7].GetUInt32();
|
||||
follower.PacketInfo.CurrentMissionID = fields[8].GetUInt32();
|
||||
follower.PacketInfo.FollowerStatus = fields[9].GetUInt32();
|
||||
if (!sGarrBuildingStore.LookupEntry(follower.PacketInfo.CurrentBuildingID))
|
||||
follower.PacketInfo.CurrentBuildingID = 0;
|
||||
|
||||
//if (!sGarrMissionStore.LookupEntry(follower.PacketInfo.CurrentMissionID))
|
||||
// follower.PacketInfo.CurrentMissionID = 0;
|
||||
|
||||
} while (followers->NextRow());
|
||||
|
||||
if (abilities)
|
||||
{
|
||||
do
|
||||
{
|
||||
fields = abilities->Fetch();
|
||||
uint64 dbId = fields[0].GetUInt64();
|
||||
GarrAbilityEntry const* ability = sGarrAbilityStore.LookupEntry(fields[1].GetUInt32());
|
||||
|
||||
if (!ability)
|
||||
continue;
|
||||
|
||||
auto itr = _followers.find(dbId);
|
||||
if (itr == _followers.end())
|
||||
continue;
|
||||
|
||||
itr->second.PacketInfo.AbilityID.push_back(ability);
|
||||
} while (abilities->NextRow());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Garrison::SaveToDB(CharacterDatabaseTransaction trans)
|
||||
{
|
||||
DeleteFromDB(_owner->GetGUID().GetCounter(), trans);
|
||||
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_GARRISON);
|
||||
stmt->setUInt64(0, _owner->GetGUID().GetCounter());
|
||||
stmt->setUInt32(1, _siteLevel->ID);
|
||||
stmt->setUInt32(2, _followerActivationsRemainingToday);
|
||||
trans->Append(stmt);
|
||||
|
||||
for (uint32 building : _knownBuildings)
|
||||
{
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_GARRISON_BLUEPRINTS);
|
||||
stmt->setUInt64(0, _owner->GetGUID().GetCounter());
|
||||
stmt->setUInt32(1, building);
|
||||
trans->Append(stmt);
|
||||
}
|
||||
|
||||
for (auto const& p : _plots)
|
||||
{
|
||||
Plot const& plot = p.second;
|
||||
if (plot.BuildingInfo.PacketInfo)
|
||||
{
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_GARRISON_BUILDINGS);
|
||||
stmt->setUInt64(0, _owner->GetGUID().GetCounter());
|
||||
stmt->setUInt32(1, plot.BuildingInfo.PacketInfo->GarrPlotInstanceID);
|
||||
stmt->setUInt32(2, plot.BuildingInfo.PacketInfo->GarrBuildingID);
|
||||
stmt->setInt64(3, plot.BuildingInfo.PacketInfo->TimeBuilt);
|
||||
stmt->setBool(4, plot.BuildingInfo.PacketInfo->Active);
|
||||
trans->Append(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto const& p : _followers)
|
||||
{
|
||||
Follower const& follower = p.second;
|
||||
uint8 index = 0;
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_GARRISON_FOLLOWERS);
|
||||
stmt->setUInt64(index++, follower.PacketInfo.DbID);
|
||||
stmt->setUInt64(index++, _owner->GetGUID().GetCounter());
|
||||
stmt->setUInt32(index++, follower.PacketInfo.GarrFollowerID);
|
||||
stmt->setUInt32(index++, follower.PacketInfo.Quality);
|
||||
stmt->setUInt32(index++, follower.PacketInfo.FollowerLevel);
|
||||
stmt->setUInt32(index++, follower.PacketInfo.ItemLevelWeapon);
|
||||
stmt->setUInt32(index++, follower.PacketInfo.ItemLevelArmor);
|
||||
stmt->setUInt32(index++, follower.PacketInfo.Xp);
|
||||
stmt->setUInt32(index++, follower.PacketInfo.CurrentBuildingID);
|
||||
stmt->setUInt32(index++, follower.PacketInfo.CurrentMissionID);
|
||||
stmt->setUInt32(index++, follower.PacketInfo.FollowerStatus);
|
||||
trans->Append(stmt);
|
||||
|
||||
uint8 slot = 0;
|
||||
for (GarrAbilityEntry const* ability : follower.PacketInfo.AbilityID)
|
||||
{
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_GARRISON_FOLLOWER_ABILITIES);
|
||||
stmt->setUInt64(0, follower.PacketInfo.DbID);
|
||||
stmt->setUInt32(1, ability->ID);
|
||||
stmt->setUInt8(2, slot++);
|
||||
trans->Append(stmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Garrison::DeleteFromDB(ObjectGuid::LowType ownerGuid, CharacterDatabaseTransaction trans)
|
||||
{
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_GARRISON);
|
||||
stmt->setUInt64(0, ownerGuid);
|
||||
trans->Append(stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_GARRISON_BLUEPRINTS);
|
||||
stmt->setUInt64(0, ownerGuid);
|
||||
trans->Append(stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_GARRISON_BUILDINGS);
|
||||
stmt->setUInt64(0, ownerGuid);
|
||||
trans->Append(stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_GARRISON_FOLLOWERS);
|
||||
stmt->setUInt64(0, ownerGuid);
|
||||
trans->Append(stmt);
|
||||
}
|
||||
|
||||
bool Garrison::Create(uint32 garrSiteId)
|
||||
{
|
||||
GarrSiteLevelEntry const* siteLevel = sGarrisonMgr.GetGarrSiteLevelEntry(garrSiteId, 1);
|
||||
if (!siteLevel)
|
||||
return false;
|
||||
|
||||
_siteLevel = siteLevel;
|
||||
|
||||
InitializePlots();
|
||||
|
||||
WorldPackets::Garrison::GarrisonCreateResult garrisonCreateResult;
|
||||
garrisonCreateResult.GarrSiteLevelID = _siteLevel->ID;
|
||||
_owner->SendDirectMessage(garrisonCreateResult.Write());
|
||||
PhasingHandler::OnConditionChange(_owner);
|
||||
SendRemoteInfo();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Garrison::Delete()
|
||||
{
|
||||
CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
|
||||
DeleteFromDB(_owner->GetGUID().GetCounter(), trans);
|
||||
CharacterDatabase.CommitTransaction(trans);
|
||||
|
||||
WorldPackets::Garrison::GarrisonDeleteResult garrisonDelete;
|
||||
garrisonDelete.Result = GARRISON_SUCCESS;
|
||||
garrisonDelete.GarrSiteID = _siteLevel->GarrSiteID;
|
||||
_owner->SendDirectMessage(garrisonDelete.Write());
|
||||
}
|
||||
|
||||
void Garrison::InitializePlots()
|
||||
{
|
||||
if (std::vector<GarrSiteLevelPlotInstEntry const*> const* plots = sGarrisonMgr.GetGarrPlotInstForSiteLevel(_siteLevel->ID))
|
||||
{
|
||||
for (std::size_t i = 0; i < plots->size(); ++i)
|
||||
{
|
||||
uint32 garrPlotInstanceId = plots->at(i)->GarrPlotInstanceID;
|
||||
GarrPlotInstanceEntry const* plotInstance = sGarrPlotInstanceStore.LookupEntry(garrPlotInstanceId);
|
||||
GameObjectsEntry const* gameObject = sGarrisonMgr.GetPlotGameObject(_siteLevel->MapID, garrPlotInstanceId);
|
||||
if (!plotInstance || !gameObject)
|
||||
continue;
|
||||
|
||||
GarrPlotEntry const* plot = sGarrPlotStore.LookupEntry(plotInstance->GarrPlotID);
|
||||
if (!plot)
|
||||
continue;
|
||||
|
||||
Plot& plotInfo = _plots[garrPlotInstanceId];
|
||||
plotInfo.PacketInfo.GarrPlotInstanceID = garrPlotInstanceId;
|
||||
plotInfo.PacketInfo.PlotPos = Position(gameObject->Pos.X, gameObject->Pos.Y, gameObject->Pos.Z, 2 * std::acos(gameObject->Rot[3]));
|
||||
plotInfo.PacketInfo.PlotType = plot->PlotType;
|
||||
plotInfo.Rotation = QuaternionData(gameObject->Rot[0], gameObject->Rot[1], gameObject->Rot[2], gameObject->Rot[3]);
|
||||
plotInfo.EmptyGameObjectId = gameObject->ID;
|
||||
plotInfo.GarrSiteLevelPlotInstId = plots->at(i)->ID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Garrison::Upgrade()
|
||||
{
|
||||
}
|
||||
|
||||
void Garrison::Enter() const
|
||||
{
|
||||
if (MapEntry const* map = sMapStore.LookupEntry(_siteLevel->MapID))
|
||||
{
|
||||
if (int32(_owner->GetMapId()) == map->ParentMapID)
|
||||
{
|
||||
WorldLocation loc(_siteLevel->MapID);
|
||||
loc.Relocate(_owner);
|
||||
_owner->TeleportTo(loc, TELE_TO_SEAMLESS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Garrison::Leave() const
|
||||
{
|
||||
if (MapEntry const* map = sMapStore.LookupEntry(_siteLevel->MapID))
|
||||
{
|
||||
if (_owner->GetMapId() == _siteLevel->MapID)
|
||||
{
|
||||
WorldLocation loc(map->ParentMapID);
|
||||
loc.Relocate(_owner);
|
||||
_owner->TeleportTo(loc, TELE_TO_SEAMLESS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GarrisonFactionIndex Garrison::GetFaction() const
|
||||
{
|
||||
return _owner->GetTeam() == HORDE ? GARRISON_FACTION_INDEX_HORDE : GARRISON_FACTION_INDEX_ALLIANCE;
|
||||
}
|
||||
|
||||
std::vector<Garrison::Plot*> Garrison::GetPlots()
|
||||
{
|
||||
std::vector<Plot*> plots;
|
||||
plots.reserve(_plots.size());
|
||||
for (auto& p : _plots)
|
||||
plots.push_back(&p.second);
|
||||
|
||||
return plots;
|
||||
}
|
||||
|
||||
Garrison::Plot* Garrison::GetPlot(uint32 garrPlotInstanceId)
|
||||
{
|
||||
auto itr = _plots.find(garrPlotInstanceId);
|
||||
if (itr != _plots.end())
|
||||
return &itr->second;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Garrison::Plot const* Garrison::GetPlot(uint32 garrPlotInstanceId) const
|
||||
{
|
||||
auto itr = _plots.find(garrPlotInstanceId);
|
||||
if (itr != _plots.end())
|
||||
return &itr->second;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Garrison::LearnBlueprint(uint32 garrBuildingId)
|
||||
{
|
||||
WorldPackets::Garrison::GarrisonLearnBlueprintResult learnBlueprintResult;
|
||||
learnBlueprintResult.GarrTypeID = GetType();
|
||||
learnBlueprintResult.BuildingID = garrBuildingId;
|
||||
learnBlueprintResult.Result = GARRISON_SUCCESS;
|
||||
|
||||
if (!sGarrBuildingStore.LookupEntry(garrBuildingId))
|
||||
learnBlueprintResult.Result = GARRISON_ERROR_INVALID_BUILDINGID;
|
||||
else if (HasBlueprint(garrBuildingId))
|
||||
learnBlueprintResult.Result = GARRISON_ERROR_BLUEPRINT_EXISTS;
|
||||
else
|
||||
_knownBuildings.insert(garrBuildingId);
|
||||
|
||||
_owner->SendDirectMessage(learnBlueprintResult.Write());
|
||||
}
|
||||
|
||||
void Garrison::UnlearnBlueprint(uint32 garrBuildingId)
|
||||
{
|
||||
WorldPackets::Garrison::GarrisonUnlearnBlueprintResult unlearnBlueprintResult;
|
||||
unlearnBlueprintResult.GarrTypeID = GetType();
|
||||
unlearnBlueprintResult.BuildingID = garrBuildingId;
|
||||
unlearnBlueprintResult.Result = GARRISON_SUCCESS;
|
||||
|
||||
if (!sGarrBuildingStore.LookupEntry(garrBuildingId))
|
||||
unlearnBlueprintResult.Result = GARRISON_ERROR_INVALID_BUILDINGID;
|
||||
else if (!HasBlueprint(garrBuildingId))
|
||||
unlearnBlueprintResult.Result = GARRISON_ERROR_REQUIRES_BLUEPRINT;
|
||||
else
|
||||
_knownBuildings.erase(garrBuildingId);
|
||||
|
||||
_owner->SendDirectMessage(unlearnBlueprintResult.Write());
|
||||
}
|
||||
|
||||
void Garrison::PlaceBuilding(uint32 garrPlotInstanceId, uint32 garrBuildingId)
|
||||
{
|
||||
WorldPackets::Garrison::GarrisonPlaceBuildingResult placeBuildingResult;
|
||||
placeBuildingResult.GarrTypeID = GetType();
|
||||
placeBuildingResult.Result = CheckBuildingPlacement(garrPlotInstanceId, garrBuildingId);
|
||||
if (placeBuildingResult.Result == GARRISON_SUCCESS)
|
||||
{
|
||||
placeBuildingResult.BuildingInfo.GarrPlotInstanceID = garrPlotInstanceId;
|
||||
placeBuildingResult.BuildingInfo.GarrBuildingID = garrBuildingId;
|
||||
placeBuildingResult.BuildingInfo.TimeBuilt = GameTime::GetGameTime();
|
||||
|
||||
Plot* plot = GetPlot(garrPlotInstanceId);
|
||||
uint32 oldBuildingId = 0;
|
||||
Map* map = FindMap();
|
||||
GarrBuildingEntry const* building = sGarrBuildingStore.AssertEntry(garrBuildingId);
|
||||
if (map)
|
||||
plot->DeleteGameObject(map);
|
||||
|
||||
if (plot->BuildingInfo.PacketInfo)
|
||||
{
|
||||
oldBuildingId = plot->BuildingInfo.PacketInfo->GarrBuildingID;
|
||||
if (sGarrBuildingStore.AssertEntry(oldBuildingId)->BuildingType != building->BuildingType)
|
||||
plot->ClearBuildingInfo(GetType(), _owner);
|
||||
}
|
||||
|
||||
plot->SetBuildingInfo(placeBuildingResult.BuildingInfo, _owner);
|
||||
if (map)
|
||||
if (GameObject* go = plot->CreateGameObject(map, GetFaction()))
|
||||
map->AddToMap(go);
|
||||
|
||||
_owner->RemoveCurrency(building->CurrencyTypeID, building->CurrencyQty, CurrencyDestroyReason::Garrison);
|
||||
_owner->ModifyMoney(-building->GoldCost * GOLD, false);
|
||||
|
||||
if (oldBuildingId)
|
||||
{
|
||||
WorldPackets::Garrison::GarrisonBuildingRemoved buildingRemoved;
|
||||
buildingRemoved.GarrTypeID = GetType();
|
||||
buildingRemoved.Result = GARRISON_SUCCESS;
|
||||
buildingRemoved.GarrPlotInstanceID = garrPlotInstanceId;
|
||||
buildingRemoved.GarrBuildingID = oldBuildingId;
|
||||
_owner->SendDirectMessage(buildingRemoved.Write());
|
||||
}
|
||||
|
||||
_owner->UpdateCriteria(CriteriaType::PlaceGarrisonBuilding, garrBuildingId);
|
||||
}
|
||||
|
||||
_owner->SendDirectMessage(placeBuildingResult.Write());
|
||||
}
|
||||
|
||||
void Garrison::CancelBuildingConstruction(uint32 garrPlotInstanceId)
|
||||
{
|
||||
WorldPackets::Garrison::GarrisonBuildingRemoved buildingRemoved;
|
||||
buildingRemoved.GarrTypeID = GetType();
|
||||
buildingRemoved.Result = CheckBuildingRemoval(garrPlotInstanceId);
|
||||
if (buildingRemoved.Result == GARRISON_SUCCESS)
|
||||
{
|
||||
Plot* plot = GetPlot(garrPlotInstanceId);
|
||||
|
||||
buildingRemoved.GarrPlotInstanceID = garrPlotInstanceId;
|
||||
buildingRemoved.GarrBuildingID = plot->BuildingInfo.PacketInfo->GarrBuildingID;
|
||||
|
||||
Map* map = FindMap();
|
||||
if (map)
|
||||
plot->DeleteGameObject(map);
|
||||
|
||||
plot->ClearBuildingInfo(GetType(), _owner);
|
||||
_owner->SendDirectMessage(buildingRemoved.Write());
|
||||
|
||||
GarrBuildingEntry const* constructing = sGarrBuildingStore.AssertEntry(buildingRemoved.GarrBuildingID);
|
||||
// Refund construction/upgrade cost
|
||||
_owner->AddCurrency(constructing->CurrencyTypeID, constructing->CurrencyQty, CurrencyGainSource::GarrisonBuildingRefund);
|
||||
_owner->ModifyMoney(constructing->GoldCost * GOLD, false);
|
||||
|
||||
if (constructing->UpgradeLevel > 1)
|
||||
{
|
||||
// Restore previous level building
|
||||
uint32 restored = sGarrisonMgr.GetPreviousLevelBuildingId(constructing->BuildingType, constructing->UpgradeLevel);
|
||||
ASSERT(restored);
|
||||
|
||||
WorldPackets::Garrison::GarrisonPlaceBuildingResult placeBuildingResult;
|
||||
placeBuildingResult.GarrTypeID = GetType();
|
||||
placeBuildingResult.Result = GARRISON_SUCCESS;
|
||||
placeBuildingResult.BuildingInfo.GarrPlotInstanceID = garrPlotInstanceId;
|
||||
placeBuildingResult.BuildingInfo.GarrBuildingID = restored;
|
||||
placeBuildingResult.BuildingInfo.TimeBuilt = GameTime::GetGameTime();
|
||||
placeBuildingResult.BuildingInfo.Active = true;
|
||||
|
||||
plot->SetBuildingInfo(placeBuildingResult.BuildingInfo, _owner);
|
||||
_owner->SendDirectMessage(placeBuildingResult.Write());
|
||||
}
|
||||
|
||||
if (map)
|
||||
if (GameObject* go = plot->CreateGameObject(map, GetFaction()))
|
||||
map->AddToMap(go);
|
||||
}
|
||||
else
|
||||
_owner->SendDirectMessage(buildingRemoved.Write());
|
||||
}
|
||||
|
||||
void Garrison::ActivateBuilding(uint32 garrPlotInstanceId)
|
||||
{
|
||||
if (Plot* plot = GetPlot(garrPlotInstanceId))
|
||||
{
|
||||
if (plot->BuildingInfo.CanActivate() && plot->BuildingInfo.PacketInfo && !plot->BuildingInfo.PacketInfo->Active)
|
||||
{
|
||||
plot->BuildingInfo.PacketInfo->Active = true;
|
||||
if (Map* map = FindMap())
|
||||
{
|
||||
plot->DeleteGameObject(map);
|
||||
if (GameObject* go = plot->CreateGameObject(map, GetFaction()))
|
||||
map->AddToMap(go);
|
||||
}
|
||||
|
||||
WorldPackets::Garrison::GarrisonBuildingActivated buildingActivated;
|
||||
buildingActivated.GarrPlotInstanceID = garrPlotInstanceId;
|
||||
_owner->SendDirectMessage(buildingActivated.Write());
|
||||
|
||||
_owner->UpdateCriteria(CriteriaType::ActivateAnyGarrisonBuilding, plot->BuildingInfo.PacketInfo->GarrBuildingID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Garrison::AddFollower(uint32 garrFollowerId)
|
||||
{
|
||||
WorldPackets::Garrison::GarrisonAddFollowerResult addFollowerResult;
|
||||
addFollowerResult.GarrTypeID = GetType();
|
||||
GarrFollowerEntry const* followerEntry = sGarrFollowerStore.LookupEntry(garrFollowerId);
|
||||
if (_followerIds.count(garrFollowerId) || !followerEntry)
|
||||
{
|
||||
addFollowerResult.Result = GARRISON_ERROR_FOLLOWER_EXISTS;
|
||||
_owner->SendDirectMessage(addFollowerResult.Write());
|
||||
return;
|
||||
}
|
||||
|
||||
_followerIds.insert(garrFollowerId);
|
||||
uint64 dbId = sGarrisonMgr.GenerateFollowerDbId();
|
||||
Follower& follower = _followers[dbId];
|
||||
follower.PacketInfo.DbID = dbId;
|
||||
follower.PacketInfo.GarrFollowerID = garrFollowerId;
|
||||
follower.PacketInfo.Quality = 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 = sGarrisonMgr.RollFollowerAbilities(garrFollowerId, followerEntry, follower.PacketInfo.Quality, GetFaction(), true);
|
||||
follower.PacketInfo.FollowerStatus = 0;
|
||||
|
||||
addFollowerResult.Follower = follower.PacketInfo;
|
||||
_owner->SendDirectMessage(addFollowerResult.Write());
|
||||
|
||||
_owner->UpdateCriteria(CriteriaType::RecruitGarrisonFollower, follower.PacketInfo.DbID);
|
||||
}
|
||||
|
||||
Garrison::Follower const* Garrison::GetFollower(uint64 dbId) const
|
||||
{
|
||||
auto itr = _followers.find(dbId);
|
||||
if (itr != _followers.end())
|
||||
return &itr->second;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Garrison::SendInfo()
|
||||
{
|
||||
WorldPackets::Garrison::GetGarrisonInfoResult garrisonInfo;
|
||||
garrisonInfo.FactionIndex = GetFaction();
|
||||
garrisonInfo.Garrisons.emplace_back();
|
||||
|
||||
WorldPackets::Garrison::GarrisonInfo& garrison = garrisonInfo.Garrisons.back();
|
||||
garrison.GarrTypeID = GetType();
|
||||
garrison.GarrSiteID = _siteLevel->GarrSiteID;
|
||||
garrison.GarrSiteLevelID = _siteLevel->ID;
|
||||
garrison.NumFollowerActivationsRemaining = _followerActivationsRemainingToday;
|
||||
for (auto& p : _plots)
|
||||
{
|
||||
Plot& plot = p.second;
|
||||
garrison.Plots.push_back(&plot.PacketInfo);
|
||||
if (plot.BuildingInfo.PacketInfo)
|
||||
garrison.Buildings.push_back(&*plot.BuildingInfo.PacketInfo);
|
||||
}
|
||||
|
||||
for (auto const& p : _followers)
|
||||
garrison.Followers.push_back(&p.second.PacketInfo);
|
||||
|
||||
_owner->SendDirectMessage(garrisonInfo.Write());
|
||||
}
|
||||
|
||||
void Garrison::SendRemoteInfo() const
|
||||
{
|
||||
MapEntry const* garrisonMap = sMapStore.LookupEntry(_siteLevel->MapID);
|
||||
if (!garrisonMap || int32(_owner->GetMapId()) != garrisonMap->ParentMapID)
|
||||
return;
|
||||
|
||||
WorldPackets::Garrison::GarrisonRemoteInfo remoteInfo;
|
||||
remoteInfo.Sites.resize(1);
|
||||
|
||||
WorldPackets::Garrison::GarrisonRemoteSiteInfo& remoteSiteInfo = remoteInfo.Sites[0];
|
||||
remoteSiteInfo.GarrSiteLevelID = _siteLevel->ID;
|
||||
for (auto const& p : _plots)
|
||||
if (p.second.BuildingInfo.PacketInfo)
|
||||
remoteSiteInfo.Buildings.emplace_back(p.first, p.second.BuildingInfo.PacketInfo->GarrBuildingID);
|
||||
|
||||
_owner->SendDirectMessage(remoteInfo.Write());
|
||||
}
|
||||
|
||||
void Garrison::SendBlueprintAndSpecializationData()
|
||||
{
|
||||
WorldPackets::Garrison::GarrisonRequestBlueprintAndSpecializationDataResult data;
|
||||
data.GarrTypeID = GetType();
|
||||
data.BlueprintsKnown = &_knownBuildings;
|
||||
_owner->SendDirectMessage(data.Write());
|
||||
}
|
||||
|
||||
void Garrison::SendMapData(Player* receiver) const
|
||||
{
|
||||
WorldPackets::Garrison::GarrisonMapDataResponse mapData;
|
||||
mapData.Buildings.reserve(_plots.size());
|
||||
|
||||
for (auto const& p : _plots)
|
||||
{
|
||||
Plot const& plot = p.second;
|
||||
if (plot.BuildingInfo.PacketInfo)
|
||||
if (uint32 garrBuildingPlotInstId = sGarrisonMgr.GetGarrBuildingPlotInst(plot.BuildingInfo.PacketInfo->GarrBuildingID, plot.GarrSiteLevelPlotInstId))
|
||||
mapData.Buildings.emplace_back(garrBuildingPlotInstId, plot.PacketInfo.PlotPos.Pos);
|
||||
}
|
||||
|
||||
receiver->SendDirectMessage(mapData.Write());
|
||||
}
|
||||
|
||||
Map* Garrison::FindMap() const
|
||||
{
|
||||
return sMapMgr->FindMap(_siteLevel->MapID, _owner->GetGUID().GetCounter());
|
||||
}
|
||||
|
||||
GarrisonError Garrison::CheckBuildingPlacement(uint32 garrPlotInstanceId, uint32 garrBuildingId) const
|
||||
{
|
||||
GarrPlotInstanceEntry const* plotInstance = sGarrPlotInstanceStore.LookupEntry(garrPlotInstanceId);
|
||||
Plot const* plot = GetPlot(garrPlotInstanceId);
|
||||
if (!plotInstance || !plot)
|
||||
return GARRISON_ERROR_INVALID_PLOT_INSTANCEID;
|
||||
|
||||
GarrBuildingEntry const* building = sGarrBuildingStore.LookupEntry(garrBuildingId);
|
||||
if (!building)
|
||||
return GARRISON_ERROR_INVALID_BUILDINGID;
|
||||
|
||||
if (!sGarrisonMgr.IsPlotMatchingBuilding(plotInstance->GarrPlotID, garrBuildingId))
|
||||
return GARRISON_ERROR_INVALID_PLOT_BUILDING;
|
||||
|
||||
// Cannot place buldings of higher level than garrison level
|
||||
if (building->UpgradeLevel > _siteLevel->MaxBuildingLevel)
|
||||
return GARRISON_ERROR_INVALID_BUILDINGID;
|
||||
|
||||
if (building->Flags & GARRISON_BUILDING_FLAG_NEEDS_PLAN)
|
||||
{
|
||||
if (!HasBlueprint(garrBuildingId))
|
||||
return GARRISON_ERROR_REQUIRES_BLUEPRINT;
|
||||
}
|
||||
else // Building is built as a quest reward
|
||||
return GARRISON_ERROR_INVALID_BUILDINGID;
|
||||
|
||||
// Check all plots to find if we already have this building
|
||||
GarrBuildingEntry const* existingBuilding;
|
||||
for (auto const& p : _plots)
|
||||
{
|
||||
if (p.second.BuildingInfo.PacketInfo)
|
||||
{
|
||||
existingBuilding = sGarrBuildingStore.AssertEntry(p.second.BuildingInfo.PacketInfo->GarrBuildingID);
|
||||
if (existingBuilding->BuildingType == building->BuildingType)
|
||||
if (p.first != garrPlotInstanceId || existingBuilding->UpgradeLevel + 1 != building->UpgradeLevel) // check if its an upgrade in same plot
|
||||
return GARRISON_ERROR_BUILDING_EXISTS;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_owner->HasCurrency(building->CurrencyTypeID, building->CurrencyQty))
|
||||
return GARRISON_ERROR_NOT_ENOUGH_CURRENCY;
|
||||
|
||||
if (!_owner->HasEnoughMoney(uint64(building->GoldCost) * GOLD))
|
||||
return GARRISON_ERROR_NOT_ENOUGH_GOLD;
|
||||
|
||||
// New building cannot replace another building currently under construction
|
||||
if (plot->BuildingInfo.PacketInfo)
|
||||
if (!plot->BuildingInfo.PacketInfo->Active)
|
||||
return GARRISON_ERROR_NO_BUILDING;
|
||||
|
||||
return GARRISON_SUCCESS;
|
||||
}
|
||||
|
||||
GarrisonError Garrison::CheckBuildingRemoval(uint32 garrPlotInstanceId) const
|
||||
{
|
||||
Plot const* plot = GetPlot(garrPlotInstanceId);
|
||||
if (!plot)
|
||||
return GARRISON_ERROR_INVALID_PLOT_INSTANCEID;
|
||||
|
||||
if (!plot->BuildingInfo.PacketInfo)
|
||||
return GARRISON_ERROR_NO_BUILDING;
|
||||
|
||||
if (plot->BuildingInfo.CanActivate())
|
||||
return GARRISON_ERROR_BUILDING_EXISTS;
|
||||
|
||||
return GARRISON_SUCCESS;
|
||||
}
|
||||
|
||||
template<class T, void(T::*SecondaryRelocate)(float,float,float,float)>
|
||||
T* BuildingSpawnHelper(GameObject* building, ObjectGuid::LowType spawnId, Map* map)
|
||||
{
|
||||
T* spawn = new T();
|
||||
if (!spawn->LoadFromDB(spawnId, map, false, false))
|
||||
{
|
||||
delete spawn;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
float x = spawn->GetPositionX();
|
||||
float y = spawn->GetPositionY();
|
||||
float z = spawn->GetPositionZ();
|
||||
float o = spawn->GetOrientation();
|
||||
TransportBase::CalculatePassengerPosition(x, y, z, &o, building->GetPositionX(), building->GetPositionY(), building->GetPositionZ(), building->GetOrientation());
|
||||
|
||||
spawn->Relocate(x, y, z, o);
|
||||
(spawn->*SecondaryRelocate)(x, y, z, o);
|
||||
|
||||
if (!spawn->IsPositionValid())
|
||||
{
|
||||
delete spawn;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!map->AddToMap(spawn))
|
||||
{
|
||||
delete spawn;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return spawn;
|
||||
}
|
||||
|
||||
GameObject* Garrison::Plot::CreateGameObject(Map* map, GarrisonFactionIndex faction)
|
||||
{
|
||||
uint32 entry = EmptyGameObjectId;
|
||||
if (BuildingInfo.PacketInfo)
|
||||
{
|
||||
GarrPlotInstanceEntry const* plotInstance = sGarrPlotInstanceStore.AssertEntry(PacketInfo.GarrPlotInstanceID);
|
||||
GarrPlotEntry const* plot = sGarrPlotStore.AssertEntry(plotInstance->GarrPlotID);
|
||||
GarrBuildingEntry const* building = sGarrBuildingStore.AssertEntry(BuildingInfo.PacketInfo->GarrBuildingID);
|
||||
entry = faction == GARRISON_FACTION_INDEX_HORDE ? plot->HordeConstructObjID : plot->AllianceConstructObjID;
|
||||
if (BuildingInfo.PacketInfo->Active || !entry)
|
||||
entry = faction == GARRISON_FACTION_INDEX_HORDE ? building->HordeGameObjectID : building->AllianceGameObjectID;
|
||||
}
|
||||
|
||||
if (!sObjectMgr->GetGameObjectTemplate(entry))
|
||||
{
|
||||
TC_LOG_ERROR("garrison", "Garrison attempted to spawn gameobject whose template doesn't exist ({})", entry);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GameObject* building = GameObject::CreateGameObject(entry, map, PacketInfo.PlotPos.Pos, Rotation, 255, GO_STATE_READY);
|
||||
if (!building)
|
||||
return nullptr;
|
||||
|
||||
if (BuildingInfo.CanActivate() && BuildingInfo.PacketInfo && !BuildingInfo.PacketInfo->Active)
|
||||
{
|
||||
if (FinalizeGarrisonPlotGOInfo const* finalizeInfo = sGarrisonMgr.GetPlotFinalizeGOInfo(PacketInfo.GarrPlotInstanceID))
|
||||
{
|
||||
Position const& pos2 = finalizeInfo->FactionInfo[faction].Pos;
|
||||
if (GameObject* finalizer = GameObject::CreateGameObject(finalizeInfo->FactionInfo[faction].GameObjectId, map, pos2, QuaternionData::fromEulerAnglesZYX(pos2.GetOrientation(), 0.0f, 0.0f), 255, GO_STATE_READY))
|
||||
{
|
||||
// set some spell id to make the object delete itself after use
|
||||
finalizer->SetSpellId(finalizer->GetGOInfo()->goober.spell);
|
||||
finalizer->SetRespawnTime(0);
|
||||
|
||||
if (uint16 animKit = finalizeInfo->FactionInfo[faction].AnimKitId)
|
||||
finalizer->SetAnimKitId(animKit, false);
|
||||
|
||||
map->AddToMap(finalizer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (building->GetGoType() == GAMEOBJECT_TYPE_GARRISON_BUILDING && building->GetGOInfo()->garrisonBuilding.SpawnMap)
|
||||
{
|
||||
if (CellObjectGuidsMap const* cells = sObjectMgr->GetMapObjectGuids(building->GetGOInfo()->garrisonBuilding.SpawnMap, map->GetDifficultyID()))
|
||||
{
|
||||
for (auto const& [cellId, guids] : *cells)
|
||||
{
|
||||
for (ObjectGuid::LowType spawnId : guids.gameobjects)
|
||||
if (GameObject* spawn = BuildingSpawnHelper<GameObject, &GameObject::RelocateStationaryPosition>(building, spawnId, map))
|
||||
BuildingInfo.Spawns.insert(spawn->GetGUID());
|
||||
|
||||
for (ObjectGuid::LowType spawnId : guids.creatures)
|
||||
if (Creature* spawn = BuildingSpawnHelper<Creature, &Creature::SetHomePosition>(building, spawnId, map))
|
||||
BuildingInfo.Spawns.insert(spawn->GetGUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BuildingInfo.Guid = building->GetGUID();
|
||||
return building;
|
||||
}
|
||||
|
||||
void Garrison::Plot::DeleteGameObject(Map* map)
|
||||
{
|
||||
if (BuildingInfo.Guid.IsEmpty())
|
||||
return;
|
||||
|
||||
for (ObjectGuid const& guid : BuildingInfo.Spawns)
|
||||
{
|
||||
WorldObject* object = nullptr;
|
||||
switch (guid.GetHigh())
|
||||
{
|
||||
case HighGuid::Creature:
|
||||
object = map->GetCreature(guid);
|
||||
break;
|
||||
case HighGuid::GameObject:
|
||||
object = map->GetGameObject(guid);
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (object)
|
||||
object->AddObjectToRemoveList();
|
||||
}
|
||||
|
||||
BuildingInfo.Spawns.clear();
|
||||
|
||||
if (GameObject* oldBuilding = map->GetGameObject(BuildingInfo.Guid))
|
||||
oldBuilding->Delete();
|
||||
|
||||
BuildingInfo.Guid.Clear();
|
||||
}
|
||||
|
||||
void Garrison::Plot::ClearBuildingInfo(GarrisonType garrisonType, Player* owner)
|
||||
{
|
||||
WorldPackets::Garrison::GarrisonPlotPlaced plotPlaced;
|
||||
plotPlaced.GarrTypeID = garrisonType;
|
||||
plotPlaced.PlotInfo = &PacketInfo;
|
||||
owner->SendDirectMessage(plotPlaced.Write());
|
||||
|
||||
BuildingInfo.PacketInfo.reset();
|
||||
}
|
||||
|
||||
void Garrison::Plot::SetBuildingInfo(WorldPackets::Garrison::GarrisonBuildingInfo const& buildingInfo, Player* owner)
|
||||
{
|
||||
if (!BuildingInfo.PacketInfo)
|
||||
{
|
||||
WorldPackets::Garrison::GarrisonPlotRemoved plotRemoved;
|
||||
plotRemoved.GarrPlotInstanceID = PacketInfo.GarrPlotInstanceID;
|
||||
owner->SendDirectMessage(plotRemoved.Write());
|
||||
}
|
||||
|
||||
BuildingInfo.PacketInfo = buildingInfo;
|
||||
}
|
||||
|
||||
bool Garrison::Building::CanActivate() const
|
||||
{
|
||||
if (PacketInfo)
|
||||
{
|
||||
GarrBuildingEntry const* building = sGarrBuildingStore.AssertEntry(PacketInfo->GarrBuildingID);
|
||||
if (PacketInfo->TimeBuilt + building->BuildSeconds <= GameTime::GetGameTime())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 Garrison::Follower::GetItemLevel() const
|
||||
{
|
||||
return (PacketInfo.ItemLevelWeapon + PacketInfo.ItemLevelArmor) / 2;
|
||||
}
|
||||
|
||||
bool Garrison::Follower::HasAbility(uint32 garrAbilityId) const
|
||||
{
|
||||
return std::find_if(PacketInfo.AbilityID.begin(), PacketInfo.AbilityID.end(), [garrAbilityId](GarrAbilityEntry const* garrAbility)
|
||||
{
|
||||
return garrAbility->ID == garrAbilityId;
|
||||
}) != PacketInfo.AbilityID.end();
|
||||
}
|
||||
@@ -1,284 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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 2 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/>.
|
||||
*/
|
||||
|
||||
#ifndef Garrison_h__
|
||||
#define Garrison_h__
|
||||
|
||||
#include "Define.h"
|
||||
#include "DatabaseEnvFwd.h"
|
||||
#include "GarrisonPackets.h"
|
||||
#include "Optional.h"
|
||||
#include "QuaternionData.h"
|
||||
#include <unordered_map>
|
||||
|
||||
class GameObject;
|
||||
class Map;
|
||||
class Player;
|
||||
struct GarrSiteLevelEntry;
|
||||
|
||||
enum GarrisonType
|
||||
{
|
||||
GARRISON_TYPE_GARRISON = 2,
|
||||
GARRISON_TYPE_CLASS_ORDER = 3,
|
||||
GARRISON_TYPE_WAR_CAMPAIGN = 9,
|
||||
GARRISON_TYPE_COVENANT = 111
|
||||
};
|
||||
|
||||
enum GarrisonFactionIndex
|
||||
{
|
||||
GARRISON_FACTION_INDEX_HORDE = 0,
|
||||
GARRISON_FACTION_INDEX_ALLIANCE = 1
|
||||
};
|
||||
|
||||
enum GarrisonBuildingFlags
|
||||
{
|
||||
GARRISON_BUILDING_FLAG_NEEDS_PLAN = 0x1
|
||||
};
|
||||
|
||||
enum GarrisonFollowerFlags
|
||||
{
|
||||
GARRISON_FOLLOWER_FLAG_UNIQUE = 0x1
|
||||
};
|
||||
|
||||
enum GarrisonFollowerType
|
||||
{
|
||||
FOLLOWER_TYPE_GARRISON = 1,
|
||||
FOLLOWER_TYPE_SHIPYARD = 2,
|
||||
FOLLOWER_TYPE_CLASS_ORDER = 4,
|
||||
FOLLOWER_TYPE_WAR_CAMPAIGN = 11,
|
||||
FOLLOWER_TYPE_COVENANT = 123
|
||||
};
|
||||
|
||||
enum GarrisonAbilityFlags
|
||||
{
|
||||
GARRISON_ABILITY_FLAG_TRAIT = 0x0001,
|
||||
GARRISON_ABILITY_CANNOT_ROLL = 0x0002,
|
||||
GARRISON_ABILITY_HORDE_ONLY = 0x0004,
|
||||
GARRISON_ABILITY_ALLIANCE_ONLY = 0x0008,
|
||||
GARRISON_ABILITY_FLAG_CANNOT_REMOVE = 0x0010,
|
||||
GARRISON_ABILITY_FLAG_EXCLUSIVE = 0x0020,
|
||||
GARRISON_ABILITY_FLAG_SINGLE_MISSION_DURATION = 0x0040,
|
||||
GARRISON_ABILITY_FLAG_ACTIVE_ONLY_ON_ZONE_SUPPORT = 0x0080,
|
||||
GARRISON_ABILITY_FLAG_APPLY_TO_FIRST_MISSION = 0x0100,
|
||||
GARRISON_ABILITY_FLAG_IS_SPECIALIZATION = 0x0200,
|
||||
GARRISON_ABILITY_FLAG_IS_EMPTY_SLOT = 0x0400
|
||||
};
|
||||
|
||||
enum GarrisonError
|
||||
{
|
||||
GARRISON_SUCCESS = 0,
|
||||
GARRISON_ERROR_NO_GARRISON = 1,
|
||||
GARRISON_ERROR_GARRISON_EXISTS = 2,
|
||||
GARRISON_ERROR_GARRISON_SAME_TYPE_EXISTS = 3,
|
||||
GARRISON_ERROR_INVALID_GARRISON = 4,
|
||||
GARRISON_ERROR_INVALID_GARRISON_LEVEL = 5,
|
||||
GARRISON_ERROR_GARRISON_LEVEL_UNCHANGED = 6,
|
||||
GARRISON_ERROR_NOT_IN_GARRISON = 7,
|
||||
GARRISON_ERROR_NO_BUILDING = 8,
|
||||
GARRISON_ERROR_BUILDING_EXISTS = 9,
|
||||
GARRISON_ERROR_INVALID_PLOT_INSTANCEID = 10,
|
||||
GARRISON_ERROR_INVALID_BUILDINGID = 11,
|
||||
GARRISON_ERROR_INVALID_UPGRADE_LEVEL = 12,
|
||||
GARRISON_ERROR_UPGRADE_LEVEL_EXCEEDS_GARRISON_LEVEL = 13,
|
||||
GARRISON_ERROR_PLOTS_NOT_FULL = 14,
|
||||
GARRISON_ERROR_INVALID_SITE_ID = 15,
|
||||
GARRISON_ERROR_INVALID_PLOT_BUILDING = 16,
|
||||
GARRISON_ERROR_INVALID_FACTION = 17,
|
||||
GARRISON_ERROR_INVALID_SPECIALIZATION = 18,
|
||||
GARRISON_ERROR_SPECIALIZATION_EXISTS = 19,
|
||||
GARRISON_ERROR_SPECIALIZATION_ON_COOLDOWN = 20,
|
||||
GARRISON_ERROR_BLUEPRINT_EXISTS = 21,
|
||||
GARRISON_ERROR_REQUIRES_BLUEPRINT = 22,
|
||||
GARRISON_ERROR_INVALID_DOODAD_SET_ID = 23,
|
||||
GARRISON_ERROR_BUILDING_TYPE_EXISTS = 24,
|
||||
GARRISON_ERROR_BUILDING_NOT_ACTIVE = 25,
|
||||
GARRISON_ERROR_CONSTRUCTION_COMPLETE = 26,
|
||||
GARRISON_ERROR_FOLLOWER_EXISTS = 27,
|
||||
GARRISON_ERROR_INVALID_FOLLOWER = 28,
|
||||
GARRISON_ERROR_FOLLOWER_ALREADY_ON_MISSION = 29,
|
||||
GARRISON_ERROR_FOLLOWER_IN_BUILDING = 30,
|
||||
GARRISON_ERROR_FOLLOWER_INVALID_FOR_BUILDING = 31,
|
||||
GARRISON_ERROR_INVALID_FOLLOWER_LEVEL = 32,
|
||||
GARRISON_ERROR_MISSION_EXISTS = 33,
|
||||
GARRISON_ERROR_INVALID_MISSION = 34,
|
||||
GARRISON_ERROR_INVALID_MISSION_TIME = 35,
|
||||
GARRISON_ERROR_INVALID_MISSION_REWARD_INDEX = 36,
|
||||
GARRISON_ERROR_MISSION_NOT_OFFERED = 37,
|
||||
GARRISON_ERROR_ALREADY_ON_MISSION = 38,
|
||||
GARRISON_ERROR_MISSION_SIZE_INVALID = 39,
|
||||
GARRISON_ERROR_FOLLOWER_SOFT_CAP_EXCEEDED = 40,
|
||||
GARRISON_ERROR_NOT_ON_MISSION = 41,
|
||||
GARRISON_ERROR_ALREADY_COMPLETED_MISSION = 42,
|
||||
GARRISON_ERROR_MISSION_NOT_COMPLETE = 43,
|
||||
GARRISON_ERROR_MISSION_REWARDS_PENDING = 44,
|
||||
GARRISON_ERROR_MISSION_EXPIRED = 45,
|
||||
GARRISON_ERROR_NOT_ENOUGH_CURRENCY = 46,
|
||||
GARRISON_ERROR_NOT_ENOUGH_GOLD = 47,
|
||||
GARRISON_ERROR_BUILDING_MISSING = 48,
|
||||
GARRISON_ERROR_NO_ARCHITECT = 49,
|
||||
GARRISON_ERROR_ARCHITECT_NOT_AVAILABLE = 50,
|
||||
GARRISON_ERROR_NO_MISSION_NPC = 51,
|
||||
GARRISON_ERROR_MISSION_NPC_NOT_AVAILABLE = 52,
|
||||
GARRISON_ERROR_INTERNAL_ERROR = 53,
|
||||
GARRISON_ERROR_INVALID_STATIC_TABLE_VALUE = 54,
|
||||
GARRISON_ERROR_INVALID_ITEM_LEVEL = 55,
|
||||
GARRISON_ERROR_INVALID_AVAILABLE_RECRUIT = 56,
|
||||
GARRISON_ERROR_FOLLOWER_ALREADY_RECRUITED = 57,
|
||||
GARRISON_ERROR_RECRUITMENT_GENERATION_IN_PROGRESS = 58,
|
||||
GARRISON_ERROR_RECRUITMENT_ON_COOLDOWN = 59,
|
||||
GARRISON_ERROR_RECRUIT_BLOCKED_BY_GENERATION = 60,
|
||||
GARRISON_ERROR_RECRUITMENT_NPC_NOT_AVAILABLE = 61,
|
||||
GARRISON_ERROR_INVALID_FOLLOWER_QUALITY = 62,
|
||||
GARRISON_ERROR_PROXY_NOT_OK = 63,
|
||||
GARRISON_ERROR_RECALL_PORTAL_USED_LESS_THAN_24_HOURS_AGO = 64,
|
||||
GARRISON_ERROR_ON_REMOVE_BUILDING_SPELL_FAILED = 65,
|
||||
GARRISON_ERROR_OPERATION_NOT_SUPPORTED = 66,
|
||||
GARRISON_ERROR_FOLLOWER_FATIGUED = 67,
|
||||
GARRISON_ERROR_UPGRADE_CONDITION_FAILED = 68,
|
||||
GARRISON_ERROR_FOLLOWER_INACTIVE = 69,
|
||||
GARRISON_ERROR_FOLLOWER_ACTIVE = 70,
|
||||
GARRISON_ERROR_FOLLOWER_ACTIVATION_UNAVAILABLE = 71,
|
||||
GARRISON_ERROR_FOLLOWER_TYPE_MISMATCH = 72,
|
||||
GARRISON_ERROR_INVALID_GARRISON_TYPE = 73,
|
||||
GARRISON_ERROR_MISSION_START_CONDITION_FAILED = 74,
|
||||
GARRISON_ERROR_INVALID_FOLLOWER_ABILITY = 75,
|
||||
GARRISON_ERROR_INVALID_MISSION_BONUS_ABILITY = 76,
|
||||
GARRISON_ERROR_HIGHER_BUILDING_TYPE_EXISTS = 77,
|
||||
GARRISON_ERROR_AT_FOLLOWER_HARD_CAP = 78,
|
||||
GARRISON_ERROR_FOLLOWER_CANNOT_GAIN_XP = 79,
|
||||
GARRISON_ERROR_NO_OP = 80,
|
||||
GARRISON_ERROR_AT_CLASS_SPEC_CAP = 81,
|
||||
GARRISON_ERROR_MISSION_REQUIRES_100_TO_START = 82,
|
||||
GARRISON_ERROR_MISSION_MISSING_REQUIRED_FOLLOWER = 83,
|
||||
GARRISON_ERROR_INVALID_TALENT = 84,
|
||||
GARRISON_ERROR_ALREADY_RESEARCHING_TALENT = 85,
|
||||
GARRISON_ERROR_FAILED_CONDITION = 86,
|
||||
GARRISON_ERROR_INVALID_TIER = 87,
|
||||
GARRISON_ERROR_INVALID_CLASS = 88
|
||||
};
|
||||
|
||||
enum GarrisonFollowerStatus
|
||||
{
|
||||
FOLLOWER_STATUS_FAVORITE = 0x01,
|
||||
FOLLOWER_STATUS_EXHAUSTED = 0x02,
|
||||
FOLLOWER_STATUS_INACTIVE = 0x04,
|
||||
FOLLOWER_STATUS_TROOP = 0x08,
|
||||
FOLLOWER_STATUS_NO_XP_GAIN = 0x10
|
||||
};
|
||||
|
||||
class TC_GAME_API Garrison
|
||||
{
|
||||
public:
|
||||
struct Building
|
||||
{
|
||||
bool CanActivate() const;
|
||||
|
||||
ObjectGuid Guid;
|
||||
std::unordered_set<ObjectGuid> Spawns;
|
||||
Optional<WorldPackets::Garrison::GarrisonBuildingInfo> PacketInfo;
|
||||
};
|
||||
|
||||
struct Plot
|
||||
{
|
||||
GameObject* CreateGameObject(Map* map, GarrisonFactionIndex faction);
|
||||
void DeleteGameObject(Map* map);
|
||||
void ClearBuildingInfo(GarrisonType garrisonType, Player* owner);
|
||||
void SetBuildingInfo(WorldPackets::Garrison::GarrisonBuildingInfo const& buildingInfo, Player* owner);
|
||||
|
||||
WorldPackets::Garrison::GarrisonPlotInfo PacketInfo;
|
||||
QuaternionData Rotation;
|
||||
uint32 EmptyGameObjectId = 0;
|
||||
uint32 GarrSiteLevelPlotInstId = 0;
|
||||
Building BuildingInfo;
|
||||
};
|
||||
|
||||
struct Follower
|
||||
{
|
||||
uint32 GetItemLevel() const;
|
||||
bool HasAbility(uint32 garrAbilityId) const;
|
||||
|
||||
WorldPackets::Garrison::GarrisonFollower PacketInfo;
|
||||
};
|
||||
|
||||
explicit Garrison(Player* owner);
|
||||
|
||||
bool LoadFromDB(PreparedQueryResult garrison, PreparedQueryResult blueprints, PreparedQueryResult buildings,
|
||||
PreparedQueryResult followers, PreparedQueryResult abilities);
|
||||
void SaveToDB(CharacterDatabaseTransaction trans);
|
||||
static void DeleteFromDB(ObjectGuid::LowType ownerGuid, CharacterDatabaseTransaction trans);
|
||||
|
||||
bool Create(uint32 garrSiteId);
|
||||
void Delete();
|
||||
void Upgrade();
|
||||
|
||||
void Enter() const;
|
||||
void Leave() const;
|
||||
|
||||
GarrisonFactionIndex GetFaction() const;
|
||||
GarrisonType GetType() const { return GARRISON_TYPE_GARRISON; }
|
||||
GarrSiteLevelEntry const* GetSiteLevel() const { return _siteLevel; }
|
||||
|
||||
// Plots
|
||||
std::vector<Plot*> GetPlots();
|
||||
Plot* GetPlot(uint32 garrPlotInstanceId);
|
||||
Plot const* GetPlot(uint32 garrPlotInstanceId) const;
|
||||
|
||||
// Buildings
|
||||
void LearnBlueprint(uint32 garrBuildingId);
|
||||
void UnlearnBlueprint(uint32 garrBuildingId);
|
||||
bool HasBlueprint(uint32 garrBuildingId) const { return _knownBuildings.find(garrBuildingId) != _knownBuildings.end(); }
|
||||
void PlaceBuilding(uint32 garrPlotInstanceId, uint32 garrBuildingId);
|
||||
void CancelBuildingConstruction(uint32 garrPlotInstanceId);
|
||||
void ActivateBuilding(uint32 garrPlotInstanceId);
|
||||
|
||||
// Followers
|
||||
void AddFollower(uint32 garrFollowerId);
|
||||
Follower const* GetFollower(uint64 dbId) const;
|
||||
template<typename Predicate>
|
||||
uint32 CountFollowers(Predicate&& predicate) const
|
||||
{
|
||||
uint32 count = 0;
|
||||
for (auto itr = _followers.begin(); itr != _followers.end(); ++itr)
|
||||
if (predicate(itr->second))
|
||||
++count;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void SendInfo();
|
||||
void SendRemoteInfo() const;
|
||||
void SendBlueprintAndSpecializationData();
|
||||
void SendMapData(Player* receiver) const;
|
||||
|
||||
void ResetFollowerActivationLimit() { _followerActivationsRemainingToday = 1; }
|
||||
|
||||
private:
|
||||
Map* FindMap() const;
|
||||
void InitializePlots();
|
||||
GarrisonError CheckBuildingPlacement(uint32 garrPlotInstanceId, uint32 garrBuildingId) const;
|
||||
GarrisonError CheckBuildingRemoval(uint32 garrPlotInstanceId) const;
|
||||
Player* _owner;
|
||||
GarrSiteLevelEntry const* _siteLevel;
|
||||
uint32 _followerActivationsRemainingToday;
|
||||
|
||||
std::unordered_map<uint32 /*garrPlotInstanceId*/, Plot> _plots;
|
||||
std::unordered_set<uint32 /*garrBuildingId*/> _knownBuildings;
|
||||
std::unordered_map<uint64 /*dbId*/, Follower> _followers;
|
||||
std::unordered_set<uint32> _followerIds;
|
||||
};
|
||||
|
||||
#endif // Garrison_h__
|
||||
@@ -1,146 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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 2 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/>.
|
||||
*/
|
||||
|
||||
#include "GarrisonMap.h"
|
||||
#include "DBCEnums.h"
|
||||
#include "GameObject.h"
|
||||
#include "Garrison.h"
|
||||
#include "Log.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "ObjectGridLoader.h"
|
||||
#include "Player.h"
|
||||
#include "World.h"
|
||||
|
||||
class GarrisonGridLoader
|
||||
{
|
||||
public:
|
||||
GarrisonGridLoader(NGridType* grid, GarrisonMap* map, Cell const& cell)
|
||||
: i_cell(cell), i_grid(grid), i_map(map), i_garrison(map->GetGarrison()), i_gameObjects(0), i_creatures(0)
|
||||
{ }
|
||||
|
||||
void Visit(GameObjectMapType& m);
|
||||
void Visit(CreatureMapType& m);
|
||||
|
||||
void LoadN();
|
||||
|
||||
template<class T> static void SetObjectCell(T* obj, CellCoord const& cellCoord);
|
||||
template<class T> void Visit(GridRefManager<T>& /*m*/) { }
|
||||
|
||||
private:
|
||||
Cell i_cell;
|
||||
NGridType* i_grid;
|
||||
GarrisonMap* i_map;
|
||||
Garrison* i_garrison;
|
||||
uint32 i_gameObjects;
|
||||
uint32 i_creatures;
|
||||
};
|
||||
|
||||
void GarrisonGridLoader::LoadN()
|
||||
{
|
||||
if (i_garrison)
|
||||
{
|
||||
i_cell.data.Part.cell_y = 0;
|
||||
for (uint32 x = 0; x < MAX_NUMBER_OF_CELLS; ++x)
|
||||
{
|
||||
i_cell.data.Part.cell_x = x;
|
||||
for (uint32 y = 0; y < MAX_NUMBER_OF_CELLS; ++y)
|
||||
{
|
||||
i_cell.data.Part.cell_y = y;
|
||||
|
||||
//Load creatures and game objects
|
||||
TypeContainerVisitor<GarrisonGridLoader, GridTypeMapContainer> visitor(*this);
|
||||
i_grid->VisitGrid(x, y, visitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TC_LOG_DEBUG("maps", "{} GameObjects and {} Creatures loaded for grid {} on map {}", i_gameObjects, i_creatures, i_grid->GetGridId(), i_map->GetId());
|
||||
}
|
||||
|
||||
void GarrisonGridLoader::Visit(GameObjectMapType& m)
|
||||
{
|
||||
std::vector<Garrison::Plot*> plots = i_garrison->GetPlots();
|
||||
if (!plots.empty())
|
||||
{
|
||||
CellCoord cellCoord = i_cell.GetCellCoord();
|
||||
for (Garrison::Plot* plot : plots)
|
||||
{
|
||||
Position const& spawn = plot->PacketInfo.PlotPos.Pos;
|
||||
if (cellCoord != Trinity::ComputeCellCoord(spawn.GetPositionX(), spawn.GetPositionY()))
|
||||
continue;
|
||||
|
||||
GameObject* go = plot->CreateGameObject(i_map, i_garrison->GetFaction());
|
||||
if (!go)
|
||||
continue;
|
||||
|
||||
go->AddToGrid(m);
|
||||
ObjectGridLoader::SetObjectCell(go, cellCoord);
|
||||
go->AddToWorld();
|
||||
++i_gameObjects;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GarrisonGridLoader::Visit(CreatureMapType& /*m*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
GarrisonMap::GarrisonMap(uint32 id, time_t expiry, uint32 instanceId, ObjectGuid const& owner)
|
||||
: Map(id, expiry, instanceId, DIFFICULTY_NORMAL), _owner(owner), _loadingPlayer(nullptr)
|
||||
{
|
||||
GarrisonMap::InitVisibilityDistance();
|
||||
}
|
||||
|
||||
void GarrisonMap::LoadGridObjects(NGridType* grid, Cell const& cell)
|
||||
{
|
||||
Map::LoadGridObjects(grid, cell);
|
||||
|
||||
GarrisonGridLoader loader(grid, this, cell);
|
||||
loader.LoadN();
|
||||
}
|
||||
|
||||
Garrison* GarrisonMap::GetGarrison()
|
||||
{
|
||||
if (_loadingPlayer)
|
||||
return _loadingPlayer->GetGarrison();
|
||||
|
||||
if (Player* owner = ObjectAccessor::FindConnectedPlayer(_owner))
|
||||
return owner->GetGarrison();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void GarrisonMap::InitVisibilityDistance()
|
||||
{
|
||||
//init visibility distance for instances
|
||||
m_VisibleDistance = World::GetMaxVisibleDistanceInInstances();
|
||||
m_VisibilityNotifyPeriod = World::GetVisibilityNotifyPeriodInInstances();
|
||||
}
|
||||
|
||||
bool GarrisonMap::AddPlayerToMap(Player* player, bool initPlayer /*= true*/)
|
||||
{
|
||||
if (player->GetGUID() == _owner)
|
||||
_loadingPlayer = player;
|
||||
|
||||
bool result = Map::AddPlayerToMap(player, initPlayer);
|
||||
|
||||
if (player->GetGUID() == _owner)
|
||||
_loadingPlayer = nullptr;
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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 2 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/>.
|
||||
*/
|
||||
|
||||
#ifndef GarrisonMap_h__
|
||||
#define GarrisonMap_h__
|
||||
|
||||
#include "Map.h"
|
||||
|
||||
class Garrison;
|
||||
class Player;
|
||||
|
||||
class TC_GAME_API GarrisonMap : public Map
|
||||
{
|
||||
public:
|
||||
GarrisonMap(uint32 id, time_t, uint32 instanceId, ObjectGuid const& owner);
|
||||
|
||||
void LoadGridObjects(NGridType* grid, Cell const& cell) override;
|
||||
Garrison* GetGarrison();
|
||||
|
||||
void InitVisibilityDistance() override;
|
||||
|
||||
bool AddPlayerToMap(Player* player, bool initPlayer = true) override;
|
||||
|
||||
private:
|
||||
ObjectGuid _owner;
|
||||
Player* _loadingPlayer; ///< @workaround Player is not registered in ObjectAccessor during login
|
||||
};
|
||||
|
||||
#endif // GarrisonMap_h__
|
||||
@@ -1,463 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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 2 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/>.
|
||||
*/
|
||||
|
||||
#include "GarrisonMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "DB2Stores.h"
|
||||
#include "Garrison.h"
|
||||
#include "Log.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "Random.h"
|
||||
#include "Timer.h"
|
||||
#include "World.h"
|
||||
|
||||
GarrisonMgr& GarrisonMgr::Instance()
|
||||
{
|
||||
static GarrisonMgr instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void GarrisonMgr::Initialize()
|
||||
{
|
||||
for (GarrSiteLevelPlotInstEntry const* siteLevelPlotInst : sGarrSiteLevelPlotInstStore)
|
||||
_garrisonPlotInstBySiteLevel[siteLevelPlotInst->GarrSiteLevelID].push_back(siteLevelPlotInst);
|
||||
|
||||
for (GameObjectsEntry const* gameObject : sGameObjectsStore)
|
||||
if (gameObject->TypeID == GAMEOBJECT_TYPE_GARRISON_PLOT)
|
||||
_garrisonPlots[gameObject->OwnerID][gameObject->PropValue[0]] = gameObject;
|
||||
|
||||
for (GarrPlotBuildingEntry const* plotBuilding : sGarrPlotBuildingStore)
|
||||
_garrisonBuildingsByPlot[plotBuilding->GarrPlotID].insert(plotBuilding->GarrBuildingID);
|
||||
|
||||
for (GarrBuildingPlotInstEntry const* buildingPlotInst : sGarrBuildingPlotInstStore)
|
||||
_garrisonBuildingPlotInstances[std::make_pair(buildingPlotInst->GarrBuildingID, buildingPlotInst->GarrSiteLevelPlotInstID)] = buildingPlotInst->ID;
|
||||
|
||||
for (GarrBuildingEntry const* building : sGarrBuildingStore)
|
||||
_garrisonBuildingsByType[building->BuildingType].push_back(building->ID);
|
||||
|
||||
for (GarrFollowerXAbilityEntry const* followerAbility : sGarrFollowerXAbilityStore)
|
||||
{
|
||||
if (GarrAbilityEntry const* ability = sGarrAbilityStore.LookupEntry(followerAbility->GarrAbilityID))
|
||||
{
|
||||
if (ability->GarrFollowerTypeID != FOLLOWER_TYPE_GARRISON)
|
||||
continue;
|
||||
|
||||
if (!(ability->Flags & GARRISON_ABILITY_CANNOT_ROLL) && ability->Flags & GARRISON_ABILITY_FLAG_TRAIT)
|
||||
_garrisonFollowerRandomTraits.insert(ability);
|
||||
|
||||
if (followerAbility->FactionIndex < 2)
|
||||
{
|
||||
if (ability->Flags & GARRISON_ABILITY_FLAG_TRAIT)
|
||||
_garrisonFollowerAbilities[followerAbility->FactionIndex][followerAbility->GarrFollowerID].Traits.insert(ability);
|
||||
else
|
||||
_garrisonFollowerAbilities[followerAbility->FactionIndex][followerAbility->GarrFollowerID].Counters.insert(ability);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InitializeDbIdSequences();
|
||||
LoadPlotFinalizeGOInfo();
|
||||
LoadFollowerClassSpecAbilities();
|
||||
}
|
||||
|
||||
GarrSiteLevelEntry const* GarrisonMgr::GetGarrSiteLevelEntry(uint32 garrSiteId, uint32 level) const
|
||||
{
|
||||
for (GarrSiteLevelEntry const* siteLevel : sGarrSiteLevelStore)
|
||||
if (siteLevel->GarrSiteID == garrSiteId && siteLevel->GarrLevel == level)
|
||||
return siteLevel;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<GarrSiteLevelPlotInstEntry const*> const* GarrisonMgr::GetGarrPlotInstForSiteLevel(uint32 garrSiteLevelId) const
|
||||
{
|
||||
auto itr = _garrisonPlotInstBySiteLevel.find(garrSiteLevelId);
|
||||
if (itr != _garrisonPlotInstBySiteLevel.end())
|
||||
return &itr->second;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GameObjectsEntry const* GarrisonMgr::GetPlotGameObject(uint32 mapId, uint32 garrPlotInstanceId) const
|
||||
{
|
||||
auto mapItr = _garrisonPlots.find(mapId);
|
||||
if (mapItr != _garrisonPlots.end())
|
||||
{
|
||||
auto plotItr = mapItr->second.find(garrPlotInstanceId);
|
||||
if (plotItr != mapItr->second.end())
|
||||
return plotItr->second;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool GarrisonMgr::IsPlotMatchingBuilding(uint32 garrPlotId, uint32 garrBuildingId) const
|
||||
{
|
||||
auto plotItr = _garrisonBuildingsByPlot.find(garrPlotId);
|
||||
if (plotItr != _garrisonBuildingsByPlot.end())
|
||||
return plotItr->second.count(garrBuildingId) > 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 GarrisonMgr::GetGarrBuildingPlotInst(uint32 garrBuildingId, uint32 garrSiteLevelPlotInstId) const
|
||||
{
|
||||
auto itr = _garrisonBuildingPlotInstances.find(std::make_pair(garrBuildingId, garrSiteLevelPlotInstId));
|
||||
if (itr != _garrisonBuildingPlotInstances.end())
|
||||
return itr->second;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 GarrisonMgr::GetPreviousLevelBuildingId(uint32 buildingType, uint32 currentLevel) const
|
||||
{
|
||||
auto itr = _garrisonBuildingsByType.find(buildingType);
|
||||
if (itr != _garrisonBuildingsByType.end())
|
||||
for (uint32 buildingId : itr->second)
|
||||
if (sGarrBuildingStore.AssertEntry(buildingId)->UpgradeLevel == currentLevel - 1)
|
||||
return buildingId;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FinalizeGarrisonPlotGOInfo const* GarrisonMgr::GetPlotFinalizeGOInfo(uint32 garrPlotInstanceID) const
|
||||
{
|
||||
auto itr = _finalizePlotGOInfo.find(garrPlotInstanceID);
|
||||
if (itr != _finalizePlotGOInfo.end())
|
||||
return &itr->second;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint64 GarrisonMgr::GenerateFollowerDbId()
|
||||
{
|
||||
if (_followerDbIdGenerator >= std::numeric_limits<uint64>::max())
|
||||
{
|
||||
TC_LOG_ERROR("misc", "Garrison follower db id overflow! Can't continue, shutting down server. ");
|
||||
World::StopNow(ERROR_EXIT_CODE);
|
||||
}
|
||||
|
||||
return _followerDbIdGenerator++;
|
||||
}
|
||||
|
||||
uint32 const AbilitiesForQuality[][2] =
|
||||
{
|
||||
// Counters, Traits
|
||||
{ 0, 0 },
|
||||
{ 1, 0 },
|
||||
{ 1, 1 }, // Uncommon
|
||||
{ 1, 2 }, // Rare
|
||||
{ 2, 3 }, // Epic
|
||||
{ 2, 3 } // Legendary
|
||||
};
|
||||
|
||||
std::list<GarrAbilityEntry const*> GarrisonMgr::RollFollowerAbilities(uint32 garrFollowerId, GarrFollowerEntry const* follower, uint32 quality, uint32 faction, bool initial) const
|
||||
{
|
||||
ASSERT(faction < 2);
|
||||
|
||||
bool hasForcedExclusiveTrait = false;
|
||||
std::list<GarrAbilityEntry const*> result;
|
||||
uint32 slots[2] = { AbilitiesForQuality[quality][0], AbilitiesForQuality[quality][1] };
|
||||
|
||||
GarrAbilities const* abilities = nullptr;
|
||||
auto itr = _garrisonFollowerAbilities[faction].find(garrFollowerId);
|
||||
if (itr != _garrisonFollowerAbilities[faction].end())
|
||||
abilities = &itr->second;
|
||||
|
||||
std::list<GarrAbilityEntry const*> abilityList, forcedAbilities, traitList, forcedTraits;
|
||||
if (abilities)
|
||||
{
|
||||
for (GarrAbilityEntry const* ability : abilities->Counters)
|
||||
{
|
||||
if (ability->Flags & GARRISON_ABILITY_HORDE_ONLY && faction != GARRISON_FACTION_INDEX_HORDE)
|
||||
continue;
|
||||
else if (ability->Flags & GARRISON_ABILITY_ALLIANCE_ONLY && faction != GARRISON_FACTION_INDEX_ALLIANCE)
|
||||
continue;
|
||||
|
||||
if (ability->Flags & GARRISON_ABILITY_FLAG_CANNOT_REMOVE)
|
||||
forcedAbilities.push_back(ability);
|
||||
else
|
||||
abilityList.push_back(ability);
|
||||
}
|
||||
|
||||
for (GarrAbilityEntry const* ability : abilities->Traits)
|
||||
{
|
||||
if (ability->Flags & GARRISON_ABILITY_HORDE_ONLY && faction != GARRISON_FACTION_INDEX_HORDE)
|
||||
continue;
|
||||
else if (ability->Flags & GARRISON_ABILITY_ALLIANCE_ONLY && faction != GARRISON_FACTION_INDEX_ALLIANCE)
|
||||
continue;
|
||||
|
||||
if (ability->Flags & GARRISON_ABILITY_FLAG_CANNOT_REMOVE)
|
||||
forcedTraits.push_back(ability);
|
||||
else
|
||||
traitList.push_back(ability);
|
||||
}
|
||||
}
|
||||
|
||||
Trinity::Containers::RandomResize(abilityList, std::max<int32>(0, slots[0] - forcedAbilities.size()));
|
||||
Trinity::Containers::RandomResize(traitList, std::max<int32>(0, slots[1] - forcedTraits.size()));
|
||||
|
||||
// Add abilities specified in GarrFollowerXAbility.db2 before generic classspec ones on follower creation
|
||||
if (initial)
|
||||
{
|
||||
forcedAbilities.splice(forcedAbilities.end(), abilityList);
|
||||
forcedTraits.splice(forcedTraits.end(), traitList);
|
||||
}
|
||||
|
||||
forcedAbilities.sort();
|
||||
abilityList.sort();
|
||||
forcedTraits.sort();
|
||||
traitList.sort();
|
||||
|
||||
// check if we have a trait from exclusive category
|
||||
for (GarrAbilityEntry const* ability : forcedTraits)
|
||||
{
|
||||
if (ability->Flags & GARRISON_ABILITY_FLAG_EXCLUSIVE)
|
||||
{
|
||||
hasForcedExclusiveTrait = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (slots[0] > forcedAbilities.size() + abilityList.size())
|
||||
{
|
||||
std::list<GarrAbilityEntry const*> classSpecAbilities = GetClassSpecAbilities(follower, faction);
|
||||
std::list<GarrAbilityEntry const*> classSpecAbilitiesTemp, classSpecAbilitiesTemp2;
|
||||
classSpecAbilitiesTemp2.swap(abilityList);
|
||||
std::set_difference(classSpecAbilities.begin(), classSpecAbilities.end(), forcedAbilities.begin(), forcedAbilities.end(), std::back_inserter(classSpecAbilitiesTemp));
|
||||
std::set_union(classSpecAbilitiesTemp.begin(), classSpecAbilitiesTemp.end(), classSpecAbilitiesTemp2.begin(), classSpecAbilitiesTemp2.end(), std::back_inserter(abilityList));
|
||||
|
||||
Trinity::Containers::RandomResize(abilityList, std::max<int32>(0, slots[0] - forcedAbilities.size()));
|
||||
}
|
||||
|
||||
if (slots[1] > forcedTraits.size() + traitList.size())
|
||||
{
|
||||
std::list<GarrAbilityEntry const*> genericTraits, genericTraitsTemp;
|
||||
for (GarrAbilityEntry const* ability : _garrisonFollowerRandomTraits)
|
||||
{
|
||||
if (ability->Flags & GARRISON_ABILITY_HORDE_ONLY && faction != GARRISON_FACTION_INDEX_HORDE)
|
||||
continue;
|
||||
else if (ability->Flags & GARRISON_ABILITY_ALLIANCE_ONLY && faction != GARRISON_FACTION_INDEX_ALLIANCE)
|
||||
continue;
|
||||
|
||||
// forced exclusive trait exists, skip other ones entirely
|
||||
if (hasForcedExclusiveTrait && ability->Flags & GARRISON_ABILITY_FLAG_EXCLUSIVE)
|
||||
continue;
|
||||
|
||||
genericTraitsTemp.push_back(ability);
|
||||
}
|
||||
|
||||
std::set_difference(genericTraitsTemp.begin(), genericTraitsTemp.end(), forcedTraits.begin(), forcedTraits.end(), std::back_inserter(genericTraits));
|
||||
genericTraits.splice(genericTraits.begin(), traitList);
|
||||
// "split" the list into two parts [nonexclusive, exclusive] to make selection later easier
|
||||
genericTraits.sort([](GarrAbilityEntry const* a1, GarrAbilityEntry const* a2)
|
||||
{
|
||||
uint32 e1 = a1->Flags & GARRISON_ABILITY_FLAG_EXCLUSIVE;
|
||||
uint32 e2 = a2->Flags & GARRISON_ABILITY_FLAG_EXCLUSIVE;
|
||||
if (e1 != e2)
|
||||
return e1 < e2;
|
||||
|
||||
return a1->ID < a2->ID;
|
||||
});
|
||||
genericTraits.unique();
|
||||
|
||||
std::size_t firstExclusive = 0, total = genericTraits.size();
|
||||
for (auto genericTraitItr = genericTraits.begin(); genericTraitItr != genericTraits.end(); ++genericTraitItr, ++firstExclusive)
|
||||
if ((*genericTraitItr)->Flags & GARRISON_ABILITY_FLAG_EXCLUSIVE)
|
||||
break;
|
||||
|
||||
while (traitList.size() < size_t(std::max<int32>(0, slots[1] - forcedTraits.size())) && total)
|
||||
{
|
||||
auto genericTraitItr = genericTraits.begin();
|
||||
std::advance(genericTraitItr, urand(0, total-- - 1));
|
||||
if ((*genericTraitItr)->Flags & GARRISON_ABILITY_FLAG_EXCLUSIVE)
|
||||
total = firstExclusive; // selected exclusive trait - no other can be selected now
|
||||
else
|
||||
--firstExclusive;
|
||||
|
||||
traitList.push_back(*genericTraitItr);
|
||||
genericTraits.erase(genericTraitItr);
|
||||
}
|
||||
}
|
||||
|
||||
result.splice(result.end(), forcedAbilities);
|
||||
result.splice(result.end(), abilityList);
|
||||
result.splice(result.end(), forcedTraits);
|
||||
result.splice(result.end(), traitList);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::list<GarrAbilityEntry const*> GarrisonMgr::GetClassSpecAbilities(GarrFollowerEntry const* follower, uint32 faction) const
|
||||
{
|
||||
std::list<GarrAbilityEntry const*> abilities;
|
||||
uint32 classSpecId;
|
||||
switch (faction)
|
||||
{
|
||||
case GARRISON_FACTION_INDEX_HORDE:
|
||||
classSpecId = follower->HordeGarrClassSpecID;
|
||||
break;
|
||||
case GARRISON_FACTION_INDEX_ALLIANCE:
|
||||
classSpecId = follower->AllianceGarrClassSpecID;
|
||||
break;
|
||||
default:
|
||||
return abilities;
|
||||
}
|
||||
|
||||
if (!sGarrClassSpecStore.LookupEntry(classSpecId))
|
||||
return abilities;
|
||||
|
||||
auto itr = _garrisonFollowerClassSpecAbilities.find(classSpecId);
|
||||
if (itr != _garrisonFollowerClassSpecAbilities.end())
|
||||
abilities = itr->second;
|
||||
|
||||
return abilities;
|
||||
}
|
||||
|
||||
void GarrisonMgr::InitializeDbIdSequences()
|
||||
{
|
||||
if (QueryResult result = CharacterDatabase.Query("SELECT MAX(dbId) FROM character_garrison_followers"))
|
||||
_followerDbIdGenerator = (*result)[0].GetUInt64() + 1;
|
||||
}
|
||||
|
||||
void GarrisonMgr::LoadPlotFinalizeGOInfo()
|
||||
{
|
||||
// 0 1 2 3 4 5 6
|
||||
QueryResult result = WorldDatabase.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)
|
||||
{
|
||||
TC_LOG_INFO("server.loading", ">> Loaded 0 garrison follower class spec abilities. DB table `garrison_plot_finalize_info` is empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 msTime = getMSTime();
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
uint32 garrPlotInstanceId = fields[0].GetUInt32();
|
||||
uint32 hordeGameObjectId = fields[1].GetUInt32();
|
||||
uint32 allianceGameObjectId = fields[7].GetUInt32();
|
||||
uint16 hordeAnimKitId = fields[6].GetUInt16();
|
||||
uint16 allianceAnimKitId = fields[12].GetUInt16();
|
||||
|
||||
if (!sGarrPlotInstanceStore.LookupEntry(garrPlotInstanceId))
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "Non-existing GarrPlotInstance.db2 entry {} was referenced in `garrison_plot_finalize_info`.", garrPlotInstanceId);
|
||||
continue;
|
||||
}
|
||||
|
||||
GameObjectTemplate const* goTemplate = sObjectMgr->GetGameObjectTemplate(hordeGameObjectId);
|
||||
if (!goTemplate)
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "Non-existing gameobject_template entry {} was referenced in `garrison_plot_finalize_info`.`hordeGameObjectId` for garrPlotInstanceId {}.",
|
||||
hordeGameObjectId, garrPlotInstanceId);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (goTemplate->type != GAMEOBJECT_TYPE_GOOBER)
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "Invalid gameobject type {} (entry {}) was referenced in `garrison_plot_finalize_info`.`hordeGameObjectId` for garrPlotInstanceId {}.",
|
||||
goTemplate->type, hordeGameObjectId, garrPlotInstanceId);
|
||||
continue;
|
||||
}
|
||||
|
||||
goTemplate = sObjectMgr->GetGameObjectTemplate(allianceGameObjectId);
|
||||
if (!goTemplate)
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "Non-existing gameobject_template entry {} was referenced in `garrison_plot_finalize_info`.`allianceGameObjectId` for garrPlotInstanceId {}.",
|
||||
allianceGameObjectId, garrPlotInstanceId);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (goTemplate->type != GAMEOBJECT_TYPE_GOOBER)
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "Invalid gameobject type {} (entry {}) was referenced in `garrison_plot_finalize_info`.`allianceGameObjectId` for garrPlotInstanceId {}.",
|
||||
goTemplate->type, allianceGameObjectId, garrPlotInstanceId);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hordeAnimKitId && !sAnimKitStore.LookupEntry(hordeAnimKitId))
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "Non-existing AnimKit.dbc entry {} was referenced in `garrison_plot_finalize_info`.`hordeAnimKitId` for garrPlotInstanceId {}.",
|
||||
hordeAnimKitId, garrPlotInstanceId);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (allianceAnimKitId && !sAnimKitStore.LookupEntry(allianceAnimKitId))
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "Non-existing AnimKit.dbc entry {} was referenced in `garrison_plot_finalize_info`.`allianceAnimKitId` for garrPlotInstanceId {}.",
|
||||
allianceAnimKitId, garrPlotInstanceId);
|
||||
continue;
|
||||
}
|
||||
|
||||
FinalizeGarrisonPlotGOInfo& info = _finalizePlotGOInfo[garrPlotInstanceId];
|
||||
info.FactionInfo[GARRISON_FACTION_INDEX_HORDE].GameObjectId = hordeGameObjectId;
|
||||
info.FactionInfo[GARRISON_FACTION_INDEX_HORDE].Pos.Relocate(fields[2].GetFloat(), fields[3].GetFloat(), fields[4].GetFloat(), fields[5].GetFloat());
|
||||
info.FactionInfo[GARRISON_FACTION_INDEX_HORDE].AnimKitId = hordeAnimKitId;
|
||||
|
||||
info.FactionInfo[GARRISON_FACTION_INDEX_ALLIANCE].GameObjectId = allianceGameObjectId;
|
||||
info.FactionInfo[GARRISON_FACTION_INDEX_ALLIANCE].Pos.Relocate(fields[8].GetFloat(), fields[9].GetFloat(), fields[10].GetFloat(), fields[11].GetFloat());
|
||||
info.FactionInfo[GARRISON_FACTION_INDEX_ALLIANCE].AnimKitId = allianceAnimKitId;
|
||||
|
||||
} while (result->NextRow());
|
||||
|
||||
TC_LOG_INFO("server.loading", ">> Loaded {} garrison plot finalize entries in {}.", uint32(_finalizePlotGOInfo.size()), GetMSTimeDiffToNow(msTime));
|
||||
}
|
||||
|
||||
void GarrisonMgr::LoadFollowerClassSpecAbilities()
|
||||
{
|
||||
QueryResult result = WorldDatabase.Query("SELECT classSpecId, abilityId FROM garrison_follower_class_spec_abilities");
|
||||
if (!result)
|
||||
{
|
||||
TC_LOG_INFO("server.loading", ">> Loaded 0 garrison follower class spec abilities. DB table `garrison_follower_class_spec_abilities` is empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 msTime = getMSTime();
|
||||
uint32 count = 0;
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
uint32 classSpecId = fields[0].GetUInt32();
|
||||
uint32 abilityId = fields[1].GetUInt32();
|
||||
|
||||
if (!sGarrClassSpecStore.LookupEntry(classSpecId))
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "Non-existing GarrClassSpec.db2 entry {} was referenced in `garrison_follower_class_spec_abilities` by row ({}, {}).", classSpecId, classSpecId, abilityId);
|
||||
continue;
|
||||
}
|
||||
|
||||
GarrAbilityEntry const* ability = sGarrAbilityStore.LookupEntry(abilityId);
|
||||
if (!ability)
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "Non-existing GarrAbility.db2 entry {} was referenced in `garrison_follower_class_spec_abilities` by row ({}, {}).", abilityId, classSpecId, abilityId);
|
||||
continue;
|
||||
}
|
||||
|
||||
_garrisonFollowerClassSpecAbilities[classSpecId].push_back(ability);
|
||||
++count;
|
||||
|
||||
} while (result->NextRow());
|
||||
|
||||
for (auto& pair : _garrisonFollowerClassSpecAbilities)
|
||||
pair.second.sort();
|
||||
|
||||
TC_LOG_INFO("server.loading", ">> Loaded {} garrison follower class spec abilities in {}.", count, GetMSTimeDiffToNow(msTime));
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* 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 2 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/>.
|
||||
*/
|
||||
|
||||
#ifndef GarrisonMgr_h__
|
||||
#define GarrisonMgr_h__
|
||||
|
||||
#include "Define.h"
|
||||
#include "Hash.h"
|
||||
#include "Position.h"
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
struct GameObjectsEntry;
|
||||
struct GarrAbilityEntry;
|
||||
struct GarrFollowerEntry;
|
||||
struct GarrSiteLevelEntry;
|
||||
struct GarrSiteLevelPlotInstEntry;
|
||||
|
||||
struct FinalizeGarrisonPlotGOInfo
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 GameObjectId;
|
||||
Position Pos;
|
||||
uint16 AnimKitId;
|
||||
} FactionInfo[2];
|
||||
};
|
||||
|
||||
struct GarrAbilities
|
||||
{
|
||||
std::unordered_set<GarrAbilityEntry const*> Counters;
|
||||
std::unordered_set<GarrAbilityEntry const*> Traits;
|
||||
};
|
||||
|
||||
class TC_GAME_API GarrisonMgr
|
||||
{
|
||||
public:
|
||||
static GarrisonMgr& Instance();
|
||||
|
||||
void Initialize();
|
||||
|
||||
GarrSiteLevelEntry const* GetGarrSiteLevelEntry(uint32 garrSiteId, uint32 level) const;
|
||||
std::vector<GarrSiteLevelPlotInstEntry const*> const* GetGarrPlotInstForSiteLevel(uint32 garrSiteLevelId) const;
|
||||
GameObjectsEntry const* GetPlotGameObject(uint32 mapId, uint32 garrPlotInstanceId) const;
|
||||
bool IsPlotMatchingBuilding(uint32 garrPlotId, uint32 garrBuildingId) const;
|
||||
uint32 GetGarrBuildingPlotInst(uint32 garrBuildingId, uint32 garrSiteLevelPlotInstId) const;
|
||||
uint32 GetPreviousLevelBuildingId(uint32 buildingType, uint32 currentLevel) const;
|
||||
FinalizeGarrisonPlotGOInfo const* GetPlotFinalizeGOInfo(uint32 garrPlotInstanceID) const;
|
||||
uint64 GenerateFollowerDbId();
|
||||
std::list<GarrAbilityEntry const*> RollFollowerAbilities(uint32 garrFollowerId, GarrFollowerEntry const* follower, uint32 quality, uint32 faction, bool initial) const;
|
||||
std::list<GarrAbilityEntry const*> GetClassSpecAbilities(GarrFollowerEntry const* follower, uint32 faction) const;
|
||||
|
||||
private:
|
||||
void InitializeDbIdSequences();
|
||||
void LoadPlotFinalizeGOInfo();
|
||||
void LoadFollowerClassSpecAbilities();
|
||||
|
||||
std::unordered_map<uint32 /*garrSiteId*/, std::vector<GarrSiteLevelPlotInstEntry const*>> _garrisonPlotInstBySiteLevel;
|
||||
std::unordered_map<uint32 /*mapId*/, std::unordered_map<uint32 /*garrPlotId*/, GameObjectsEntry const*>> _garrisonPlots;
|
||||
std::unordered_map<uint32 /*garrPlotId*/, std::unordered_set<uint32/*garrBuildingId*/>> _garrisonBuildingsByPlot;
|
||||
std::unordered_map<std::pair<uint32 /*garrBuildingId*/, uint32 /*garrSiteLevelPlotInstId*/>, uint32 /*garrBuildingPlotInstId*/> _garrisonBuildingPlotInstances;
|
||||
std::unordered_map<uint32 /*buildingType*/, std::vector<uint32>> _garrisonBuildingsByType;
|
||||
std::unordered_map<uint32 /*garrPlotInstanceId*/, FinalizeGarrisonPlotGOInfo> _finalizePlotGOInfo;
|
||||
std::unordered_map<uint32 /*garrFollowerId*/, GarrAbilities> _garrisonFollowerAbilities[2];
|
||||
std::unordered_map<uint32 /*classSpecId*/, std::list<GarrAbilityEntry const*>> _garrisonFollowerClassSpecAbilities;
|
||||
std::set<GarrAbilityEntry const*> _garrisonFollowerRandomTraits;
|
||||
|
||||
uint64 _followerDbIdGenerator = UI64LIT(1);
|
||||
};
|
||||
|
||||
#define sGarrisonMgr GarrisonMgr::Instance()
|
||||
|
||||
#endif // GarrisonMgr_h__
|
||||
@@ -268,26 +268,6 @@ bool LoginQueryHolder::Initialize()
|
||||
stmt->setUInt64(0, lowGuid);
|
||||
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_PET_SLOTS, stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_GARRISON);
|
||||
stmt->setUInt64(0, lowGuid);
|
||||
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_GARRISON, stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_GARRISON_BLUEPRINTS);
|
||||
stmt->setUInt64(0, lowGuid);
|
||||
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_GARRISON_BLUEPRINTS, stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_GARRISON_BUILDINGS);
|
||||
stmt->setUInt64(0, lowGuid);
|
||||
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_GARRISON_BUILDINGS, stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_GARRISON_FOLLOWERS);
|
||||
stmt->setUInt64(0, lowGuid);
|
||||
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWERS, stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_GARRISON_FOLLOWER_ABILITIES);
|
||||
stmt->setUInt64(0, lowGuid);
|
||||
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWER_ABILITIES, stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_TRAIT_ENTRIES);
|
||||
stmt->setUInt64(0, lowGuid);
|
||||
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_TRAIT_ENTRIES, stmt);
|
||||
|
||||
@@ -16,42 +16,29 @@
|
||||
*/
|
||||
|
||||
#include "WorldSession.h"
|
||||
#include "Garrison.h"
|
||||
#include "GarrisonPackets.h"
|
||||
#include "Player.h"
|
||||
|
||||
void WorldSession::HandleGetGarrisonInfo(WorldPackets::Garrison::GetGarrisonInfo& /*getGarrisonInfo*/)
|
||||
{
|
||||
if (Garrison* garrison = _player->GetGarrison())
|
||||
garrison->SendInfo();
|
||||
}
|
||||
|
||||
void WorldSession::HandleGarrisonPurchaseBuilding(WorldPackets::Garrison::GarrisonPurchaseBuilding& garrisonPurchaseBuilding)
|
||||
{
|
||||
if (!_player->GetNPCIfCanInteractWith(garrisonPurchaseBuilding.NpcGUID, UNIT_NPC_FLAG_NONE, UNIT_NPC_FLAG_2_GARRISON_ARCHITECT))
|
||||
return;
|
||||
|
||||
if (Garrison* garrison = _player->GetGarrison())
|
||||
garrison->PlaceBuilding(garrisonPurchaseBuilding.PlotInstanceID, garrisonPurchaseBuilding.BuildingID);
|
||||
}
|
||||
|
||||
void WorldSession::HandleGarrisonCancelConstruction(WorldPackets::Garrison::GarrisonCancelConstruction& garrisonCancelConstruction)
|
||||
{
|
||||
if (!_player->GetNPCIfCanInteractWith(garrisonCancelConstruction.NpcGUID, UNIT_NPC_FLAG_NONE, UNIT_NPC_FLAG_2_GARRISON_ARCHITECT))
|
||||
return;
|
||||
|
||||
if (Garrison* garrison = _player->GetGarrison())
|
||||
garrison->CancelBuildingConstruction(garrisonCancelConstruction.PlotInstanceID);
|
||||
}
|
||||
|
||||
void WorldSession::HandleGarrisonRequestBlueprintAndSpecializationData(WorldPackets::Garrison::GarrisonRequestBlueprintAndSpecializationData& /*garrisonRequestBlueprintAndSpecializationData*/)
|
||||
{
|
||||
if (Garrison* garrison = _player->GetGarrison())
|
||||
garrison->SendBlueprintAndSpecializationData();
|
||||
}
|
||||
|
||||
void WorldSession::HandleGarrisonGetMapData(WorldPackets::Garrison::GarrisonGetMapData& /*garrisonGetMapData*/)
|
||||
{
|
||||
if (Garrison* garrison = _player->GetGarrison())
|
||||
garrison->SendMapData(_player);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include "DB2Stores.h"
|
||||
#include "FlightPathMovementGenerator.h"
|
||||
#include "GameTime.h"
|
||||
#include "Garrison.h"
|
||||
#include "InstanceLockMgr.h"
|
||||
#include "InstancePackets.h"
|
||||
#include "Log.h"
|
||||
@@ -154,11 +153,7 @@ void WorldSession::HandleMoveWorldportAck()
|
||||
if (!seamlessTeleport)
|
||||
player->SendInitialPacketsAfterAddToMap();
|
||||
else
|
||||
{
|
||||
player->UpdateVisibilityForPlayer();
|
||||
if (Garrison* garrison = player->GetGarrison())
|
||||
garrison->SendRemoteInfo();
|
||||
}
|
||||
|
||||
// flight fast teleport case
|
||||
if (player->IsInFlight())
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "Containers.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "DB2Stores.h"
|
||||
#include "GarrisonMap.h"
|
||||
#include "Group.h"
|
||||
#include "InstanceLockMgr.h"
|
||||
#include "Log.h"
|
||||
@@ -129,13 +128,6 @@ BattlegroundMap* MapManager::CreateBattleground(uint32 mapId, uint32 instanceId,
|
||||
return map;
|
||||
}
|
||||
|
||||
GarrisonMap* MapManager::CreateGarrison(uint32 mapId, uint32 instanceId, Player* owner)
|
||||
{
|
||||
GarrisonMap* map = new GarrisonMap(mapId, i_gridCleanUpDelay, instanceId, owner->GetGUID());
|
||||
ASSERT(map->IsGarrison());
|
||||
return map;
|
||||
}
|
||||
|
||||
/*
|
||||
- return the right instance for the object, based on its InstanceId
|
||||
- create the instance if it's not created already
|
||||
@@ -223,13 +215,6 @@ Map* MapManager::CreateMap(uint32 mapId, Player* player)
|
||||
player->SetRecentInstance(mapId, newInstanceId);
|
||||
}
|
||||
}
|
||||
else if (entry->IsGarrison())
|
||||
{
|
||||
newInstanceId = player->GetGUID().GetCounter();
|
||||
map = FindMap_i(mapId, newInstanceId);
|
||||
if (!map)
|
||||
map = CreateGarrison(mapId, newInstanceId, player);
|
||||
}
|
||||
else
|
||||
{
|
||||
newInstanceId = 0;
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
|
||||
class Battleground;
|
||||
class BattlegroundMap;
|
||||
class GarrisonMap;
|
||||
class Group;
|
||||
class InstanceLock;
|
||||
class InstanceMap;
|
||||
@@ -140,7 +139,6 @@ class TC_GAME_API MapManager
|
||||
Map* CreateWorldMap(uint32 mapId, uint32 instanceId);
|
||||
InstanceMap* CreateInstance(uint32 mapId, uint32 instanceId, InstanceLock* instanceLock, Difficulty difficulty, TeamId team, Group* group);
|
||||
BattlegroundMap* CreateBattleground(uint32 mapId, uint32 instanceId, Battleground* bg);
|
||||
GarrisonMap* CreateGarrison(uint32 mapId, uint32 instanceId, Player* owner);
|
||||
|
||||
bool DestroyMap(Map* map);
|
||||
|
||||
|
||||
@@ -383,13 +383,9 @@ class TC_GAME_API Spell
|
||||
void EffectCreateAreaTrigger();
|
||||
void EffectRemoveTalent();
|
||||
void EffectDestroyItem();
|
||||
void EffectLearnGarrisonBuilding();
|
||||
void EffectRemoveAuraBySpellLabel();
|
||||
void EffectCreateGarrison();
|
||||
void EffectCreateConversation();
|
||||
void EffectCancelConversation();
|
||||
void EffectAddGarrisonFollower();
|
||||
void EffectActivateGarrisonBuilding();
|
||||
void EffectGrantBattlePetLevel();
|
||||
void EffectGiveExperience();
|
||||
void EffectGiveRestedExperience();
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
#include "GameObject.h"
|
||||
#include "GameObjectAI.h"
|
||||
#include "GameTime.h"
|
||||
#include "Garrison.h"
|
||||
#include "GossipDef.h"
|
||||
#include "GridNotifiers.h"
|
||||
#include "GridNotifiersImpl.h"
|
||||
@@ -295,21 +294,21 @@ NonDefaultConstructible<SpellEffectHandlerFn> SpellEffectHandlers[TOTAL_SPELL_EF
|
||||
&Spell::EffectNULL, //207 SPELL_EFFECT_LAUNCH_QUEST_TASK
|
||||
&Spell::EffectNULL, //208 SPELL_EFFECT_SET_REPUTATION
|
||||
&Spell::EffectUnused, //209 SPELL_EFFECT_209
|
||||
&Spell::EffectLearnGarrisonBuilding, //210 SPELL_EFFECT_LEARN_GARRISON_BUILDING
|
||||
&Spell::EffectNULL, //210 SPELL_EFFECT_LEARN_GARRISON_BUILDING
|
||||
&Spell::EffectNULL, //211 SPELL_EFFECT_LEARN_GARRISON_SPECIALIZATION
|
||||
&Spell::EffectRemoveAuraBySpellLabel, //212 SPELL_EFFECT_REMOVE_AURA_BY_SPELL_LABEL
|
||||
&Spell::EffectJumpDest, //213 SPELL_EFFECT_JUMP_DEST_2
|
||||
&Spell::EffectCreateGarrison, //214 SPELL_EFFECT_CREATE_GARRISON
|
||||
&Spell::EffectNULL, //214 SPELL_EFFECT_CREATE_GARRISON
|
||||
&Spell::EffectNULL, //215 SPELL_EFFECT_UPGRADE_CHARACTER_SPELLS
|
||||
&Spell::EffectNULL, //216 SPELL_EFFECT_CREATE_SHIPMENT
|
||||
&Spell::EffectNULL, //217 SPELL_EFFECT_UPGRADE_GARRISON
|
||||
&Spell::EffectNULL, //218 SPELL_EFFECT_218
|
||||
&Spell::EffectCreateConversation, //219 SPELL_EFFECT_CREATE_CONVERSATION
|
||||
&Spell::EffectAddGarrisonFollower, //220 SPELL_EFFECT_ADD_GARRISON_FOLLOWER
|
||||
&Spell::EffectNULL, //220 SPELL_EFFECT_ADD_GARRISON_FOLLOWER
|
||||
&Spell::EffectNULL, //221 SPELL_EFFECT_ADD_GARRISON_MISSION
|
||||
&Spell::EffectCreateHeirloomItem, //222 SPELL_EFFECT_CREATE_HEIRLOOM_ITEM
|
||||
&Spell::EffectNULL, //223 SPELL_EFFECT_CHANGE_ITEM_BONUSES
|
||||
&Spell::EffectActivateGarrisonBuilding, //224 SPELL_EFFECT_ACTIVATE_GARRISON_BUILDING
|
||||
&Spell::EffectNULL, //224 SPELL_EFFECT_ACTIVATE_GARRISON_BUILDING
|
||||
&Spell::EffectGrantBattlePetLevel, //225 SPELL_EFFECT_GRANT_BATTLEPET_LEVEL
|
||||
&Spell::EffectNULL, //226 SPELL_EFFECT_TRIGGER_ACTION_SET
|
||||
&Spell::EffectNULL, //227 SPELL_EFFECT_TELEPORT_TO_LFG_DUNGEON
|
||||
@@ -5361,17 +5360,6 @@ void Spell::EffectDestroyItem()
|
||||
player->DestroyItem(item->GetBagSlot(), item->GetSlot(), true);
|
||||
}
|
||||
|
||||
void Spell::EffectLearnGarrisonBuilding()
|
||||
{
|
||||
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
|
||||
return;
|
||||
|
||||
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
if (Garrison* garrison = unitTarget->ToPlayer()->GetGarrison())
|
||||
garrison->LearnBlueprint(effectInfo->MiscValue);
|
||||
}
|
||||
|
||||
void Spell::EffectRemoveAuraBySpellLabel()
|
||||
{
|
||||
@@ -5387,17 +5375,6 @@ void Spell::EffectRemoveAuraBySpellLabel()
|
||||
});
|
||||
}
|
||||
|
||||
void Spell::EffectCreateGarrison()
|
||||
{
|
||||
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
|
||||
return;
|
||||
|
||||
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
unitTarget->ToPlayer()->CreateGarrison(effectInfo->MiscValue);
|
||||
}
|
||||
|
||||
void Spell::EffectCreateConversation()
|
||||
{
|
||||
if (effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH)
|
||||
@@ -5430,18 +5407,6 @@ void Spell::EffectCancelConversation()
|
||||
}
|
||||
}
|
||||
|
||||
void Spell::EffectAddGarrisonFollower()
|
||||
{
|
||||
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
|
||||
return;
|
||||
|
||||
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
if (Garrison* garrison = unitTarget->ToPlayer()->GetGarrison())
|
||||
garrison->AddFollower(effectInfo->MiscValue);
|
||||
}
|
||||
|
||||
void Spell::EffectCreateHeirloomItem()
|
||||
{
|
||||
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
|
||||
@@ -5459,18 +5424,6 @@ void Spell::EffectCreateHeirloomItem()
|
||||
ExecuteLogEffectCreateItem(SpellEffectName(effectInfo->Effect), m_misc.Raw.Data[0]);
|
||||
}
|
||||
|
||||
void Spell::EffectActivateGarrisonBuilding()
|
||||
{
|
||||
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
|
||||
return;
|
||||
|
||||
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
if (Garrison* garrison = unitTarget->ToPlayer()->GetGarrison())
|
||||
garrison->ActivateBuilding(effectInfo->MiscValue);
|
||||
}
|
||||
|
||||
void Spell::EffectGrantBattlePetLevel()
|
||||
{
|
||||
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
|
||||
|
||||
@@ -54,7 +54,6 @@
|
||||
#include "GameObjectModel.h"
|
||||
#include "GameTables.h"
|
||||
#include "GameTime.h"
|
||||
#include "GarrisonMgr.h"
|
||||
#include "GitRevision.h"
|
||||
#include "GridNotifiersImpl.h"
|
||||
#include "GroupMgr.h"
|
||||
@@ -2325,9 +2324,6 @@ void World::SetInitialWorldSettings()
|
||||
/*TC_LOG_INFO("server.loading", "Loading GM surveys...");
|
||||
sSupportMgr->LoadSurveys();*/
|
||||
|
||||
TC_LOG_INFO("server.loading", "Loading garrison info...");
|
||||
sGarrisonMgr.Initialize();
|
||||
|
||||
///- Handle outdated emails (delete/return)
|
||||
TC_LOG_INFO("server.loading", "Returning old mails...");
|
||||
sObjectMgr->ReturnOrDeleteOldMails(false);
|
||||
@@ -3511,10 +3507,6 @@ void World::DailyReset()
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_RESET_CHARACTER_QUESTSTATUS_DAILY);
|
||||
CharacterDatabase.Execute(stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHARACTER_GARRISON_FOLLOWER_ACTIVATIONS);
|
||||
stmt->setUInt32(0, 1);
|
||||
CharacterDatabase.Execute(stmt);
|
||||
|
||||
// reset all quest status in memory
|
||||
for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
|
||||
if (Player* player = itr->second->GetPlayer())
|
||||
|
||||
Reference in New Issue
Block a user