mirror of
https://github.com/liyunfan1223/azerothcore-wotlk.git
synced 2026-08-08 15:58:04 +00:00
fix(Core/GameObject): Implement restock mechanic for non-consumable gameob… (#13950)
Core/GameObject: Implement restock mechanic for non-consumable gameobjects. Don't allow non-consumable goobers/chests to despawn on use. Source: TrinityCore. Fixes #13909
This commit is contained in:
@@ -52,6 +52,7 @@ GameObject::GameObject() : WorldObject(false), MovableMapObject(),
|
|||||||
m_respawnDelayTime = 300;
|
m_respawnDelayTime = 300;
|
||||||
m_despawnDelay = 0;
|
m_despawnDelay = 0;
|
||||||
m_despawnRespawnTime = 0s;
|
m_despawnRespawnTime = 0s;
|
||||||
|
m_restockTime = 0s;
|
||||||
m_lootState = GO_NOT_READY;
|
m_lootState = GO_NOT_READY;
|
||||||
m_spawnedByDefault = true;
|
m_spawnedByDefault = true;
|
||||||
m_allowModifyDestructibleBuilding = true;
|
m_allowModifyDestructibleBuilding = true;
|
||||||
@@ -585,6 +586,16 @@ void GameObject::Update(uint32 diff)
|
|||||||
spellCaster->CastSpell(spellCaster, spellId, triggered);
|
spellCaster->CastSpell(spellCaster, spellId, triggered);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
case GAMEOBJECT_TYPE_CHEST:
|
||||||
|
if (m_restockTime > GameTime::GetGameTime())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// If there is no restock timer, or if the restock timer passed, the chest becomes ready to loot
|
||||||
|
m_restockTime = 0s;
|
||||||
|
m_lootState = GO_READY;
|
||||||
|
AddToObjectUpdateIfNeeded();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
m_lootState = GO_READY; // for other GOis same switched without delay to GO_READY
|
m_lootState = GO_READY; // for other GOis same switched without delay to GO_READY
|
||||||
break;
|
break;
|
||||||
@@ -768,6 +779,14 @@ void GameObject::Update(uint32 diff)
|
|||||||
m_groupLootTimer -= diff;
|
m_groupLootTimer -= diff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Non-consumable chest was partially looted and restock time passed, restock all loot now
|
||||||
|
if (GetGOInfo()->chest.consumable == 0 && GameTime::GetGameTime() >= m_restockTime)
|
||||||
|
{
|
||||||
|
m_restockTime = 0s;
|
||||||
|
m_lootState = GO_READY;
|
||||||
|
AddToObjectUpdateIfNeeded();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case GAMEOBJECT_TYPE_TRAP:
|
case GAMEOBJECT_TYPE_TRAP:
|
||||||
{
|
{
|
||||||
@@ -826,21 +845,29 @@ void GameObject::Update(uint32 diff)
|
|||||||
|
|
||||||
loot.clear();
|
loot.clear();
|
||||||
|
|
||||||
//! If this is summoned by a spell with ie. SPELL_EFFECT_SUMMON_OBJECT_WILD, with or without owner, we check respawn criteria based on spell
|
// Do not delete chests or goobers that are not consumed on loot, while still allowing them to despawn when they expire if summoned
|
||||||
//! The GetOwnerGUID() check is mostly for compatibility with hacky scripts - 99% of the time summoning should be done trough spells.
|
bool isSummonedAndExpired = (GetOwner() || GetSpellId()) && m_respawnTime == 0;
|
||||||
if (GetSpellId() || GetOwnerGUID())
|
if ((GetGoType() == GAMEOBJECT_TYPE_CHEST || GetGoType() == GAMEOBJECT_TYPE_GOOBER) && !GetGOInfo()->IsDespawnAtAction() && !isSummonedAndExpired)
|
||||||
{
|
{
|
||||||
//Don't delete spell spawned chests, which are not consumed on loot
|
if (GetGoType() == GAMEOBJECT_TYPE_CHEST && GetGOInfo()->chest.chestRestockTime > 0)
|
||||||
if (m_respawnTime > 0 && GetGoType() == GAMEOBJECT_TYPE_CHEST && !GetGOInfo()->IsDespawnAtAction())
|
|
||||||
{
|
{
|
||||||
UpdateObjectVisibility();
|
// Start restock timer when the chest is fully looted
|
||||||
SetLootState(GO_READY);
|
m_restockTime = GameTime::GetGameTime() + Seconds(GetGOInfo()->chest.chestRestockTime);
|
||||||
|
SetLootState(GO_NOT_READY);
|
||||||
|
AddToObjectUpdateIfNeeded();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SetRespawnTime(0);
|
SetLootState(GO_READY);
|
||||||
Delete();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateObjectVisibility();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (GetOwnerGUID() || GetSpellId())
|
||||||
|
{
|
||||||
|
SetRespawnTime(0);
|
||||||
|
Delete();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2421,6 +2448,13 @@ void GameObject::SetLootState(LootState state, Unit* unit)
|
|||||||
|
|
||||||
AI()->OnStateChanged(state, unit);
|
AI()->OnStateChanged(state, unit);
|
||||||
sScriptMgr->OnGameObjectLootStateChanged(this, state, unit);
|
sScriptMgr->OnGameObjectLootStateChanged(this, state, unit);
|
||||||
|
|
||||||
|
// Start restock timer if the chest is partially looted or not looted at all
|
||||||
|
if (GetGoType() == GAMEOBJECT_TYPE_CHEST && state == GO_ACTIVATED && GetGOInfo()->chest.chestRestockTime > 0 && m_restockTime == 0s)
|
||||||
|
{
|
||||||
|
m_restockTime = GameTime::GetGameTime() + Seconds(GetGOInfo()->chest.chestRestockTime);
|
||||||
|
}
|
||||||
|
|
||||||
// pussywizard: lootState has nothing to do with collision, it depends entirely on GOState. Loot state is for timed close/open door and respawning, which then sets GOState
|
// pussywizard: lootState has nothing to do with collision, it depends entirely on GOState. Loot state is for timed close/open door and respawning, which then sets GOState
|
||||||
/*if (m_model)
|
/*if (m_model)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1071,9 +1071,10 @@ protected:
|
|||||||
uint32 m_respawnDelayTime; // (secs) if 0 then current GO state no dependent from timer
|
uint32 m_respawnDelayTime; // (secs) if 0 then current GO state no dependent from timer
|
||||||
uint32 m_despawnDelay;
|
uint32 m_despawnDelay;
|
||||||
Seconds m_despawnRespawnTime; // override respawn time after delayed despawn
|
Seconds m_despawnRespawnTime; // override respawn time after delayed despawn
|
||||||
|
Seconds m_restockTime;
|
||||||
LootState m_lootState;
|
LootState m_lootState;
|
||||||
bool m_spawnedByDefault;
|
bool m_spawnedByDefault;
|
||||||
uint32 m_cooldownTime; // used as internal reaction delay time store (not state change reaction).
|
uint32 m_cooldownTime; // used as internal reaction delay time store (not state change reaction).
|
||||||
// For traps this: spell casting cooldown, for doors/buttons: reset time.
|
// For traps this: spell casting cooldown, for doors/buttons: reset time.
|
||||||
std::unordered_map<ObjectGuid, int32> m_SkillupList;
|
std::unordered_map<ObjectGuid, int32> m_SkillupList;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user