Permalink
Browse files

Implement a closer replica of summoning ritual

To fully implement all animations for vanilla and tbc, we need to
implement dummy channels, which only execute visual part and have
indefinite duration, send SMSG_CHANNEL_START and nothing else. This is
true for Souls ritual and also for summoning in vanilla
  • Loading branch information...
killerwife committed Feb 21, 2018
1 parent 325ddb3 commit 89fa2ccfccb6c5dfc867a56e4e53413808043899
Showing with 90 additions and 36 deletions.
  1. +76 −36 src/game/Entities/GameObject.cpp
  2. +14 −0 src/game/Entities/GameObject.h
@@ -75,6 +75,8 @@ GameObject::GameObject() : WorldObject(),
m_reStockTimer = 0;
m_rearmTimer = 0;
m_despawnTimer = 0;
m_delayedActionTimer = 0;
}
GameObject::~GameObject()
@@ -564,6 +566,17 @@ void GameObject::Update(uint32 update_diff, uint32 p_time)
}
}
if (m_delayedActionTimer)
{
if (m_delayedActionTimer <= update_diff)
{
m_delayedActionTimer = 0;
TriggerDelayedAction();
}
else
m_delayedActionTimer -= update_diff;
}
if (m_AI)
m_AI->UpdateAI(update_diff);
}
@@ -1519,6 +1532,9 @@ void GameObject::Use(Unit* user)
if (user->GetTypeId() != TYPEID_PLAYER)
return;
if (m_delayedActionTimer)
return;
Player* player = (Player*)user;
Unit* owner = GetOwner();
@@ -1537,9 +1553,6 @@ void GameObject::Use(Unit* user)
// expect owner to already be channeling, so if not...
if (!owner->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
return;
// in case summoning ritual caster is GO creator
spellCaster = owner;
}
else
{
@@ -1553,51 +1566,23 @@ void GameObject::Use(Unit* user)
else
return;
}
spellCaster = player;
}
AddUniqueUse(player);
if (info->summoningRitual.animSpell)
{
player->CastSpell(player, info->summoningRitual.animSpell, TRIGGERED_OLD_TRIGGERED);
// for this case, summoningRitual.spellId is always triggered
triggeredFlags = TRIGGERED_OLD_TRIGGERED;
}
player->CastSpell(player, info->summoningRitual.animSpell, TRIGGERED_NONE);
// full amount unique participants including original summoner, need more
if (GetUniqueUseCount() < info->summoningRitual.reqParticipants)
return;
// owner is first user for non-wild GO objects, if it offline value already set to current user
if (!GetOwnerGuid())
if (Player* firstUser = GetMap()->GetPlayer(m_firstUser))
spellCaster = firstUser;
spellId = info->summoningRitual.spellId;
if (spellId == 62330) // GO store nonexistent spell, replace by expected
spellId = 61993;
// spell have reagent and mana cost but it not expected use its
// it triggered spell in fact casted at currently channeled GO
triggeredFlags = TRIGGERED_OLD_TRIGGERED;
// finish owners spell
if (owner)
owner->FinishSpell(CURRENT_CHANNELED_SPELL);
// can be deleted now, if
if (!info->summoningRitual.ritualPersistent)
SetLootState(GO_JUST_DEACTIVATED);
// reset ritual for this GO
if (info->summoningRitualCustom.delay)
m_delayedActionTimer = info->summoningRitualCustom.delay;
else
ClearAllUsesData();
TriggerSummoningRitual();
// go to end function to spell casting
break;
return;
}
case GAMEOBJECT_TYPE_SPELLCASTER: // 22
{
@@ -2505,6 +2490,61 @@ void GameObject::SetInUse(bool use)
SetGoState(GO_STATE_READY);
}
void GameObject::TriggerSummoningRitual()
{
const GameObjectInfo* info = GetGOInfo();
Unit* owner = GetOwner();
Unit* caster = owner;
if (!owner)
{
if (Player* firstUser = GetMap()->GetPlayer(m_firstUser))
caster = firstUser;
}
else
// finish owners spell
owner->FinishSpell(CURRENT_CHANNELED_SPELL);
if (caster) // two caster checks to maintain order
{
for (GuidSet::const_iterator itr = m_UniqueUsers.begin(); itr != m_UniqueUsers.end(); ++itr)
{
if (*itr == caster->GetObjectGuid())
continue;
if (Player* pUnique = GetMap()->GetPlayer(*itr))
pUnique->FinishSpell(CURRENT_CHANNELED_SPELL);
}
}
// can be deleted now, if
if (!info->summoningRitual.ritualPersistent)
SetLootState(GO_JUST_DEACTIVATED);
// reset ritual for this GO
else
ClearAllUsesData();
uint32 spellId = info->summoningRitual.spellId;
if (spellId == 62330) // GO store nonexistent spell, replace by expected
spellId = 61993;
if (caster)
caster->CastSpell(sObjectMgr.GetPlayer(m_actionTarget), spellId, TRIGGERED_OLD_TRIGGERED, nullptr, nullptr, GetObjectGuid());
}
void GameObject::TriggerDelayedAction()
{
switch (GetGoType())
{
case GAMEOBJECT_TYPE_SUMMONING_RITUAL:
TriggerSummoningRitual();
break;
default:
break;
}
}
uint32 GameObject::GetScriptId() const
{
return ObjectMgr::GetGameObjectInfo(GetEntry())->ScriptId;
@@ -406,6 +406,12 @@ struct GameObjectInfo
uint32 triggerOn;
} trapCustom;
//18 GAMEOBJECT_TYPE_SUMMONING_RITUAL
struct
{
uint32 delay;
} summoningRitualCustom;
struct
{
uint32 data[1];
@@ -741,6 +747,7 @@ class GameObject : public WorldObject
m_UniqueUsers.clear();
}
void SetActionTarget(ObjectGuid guid) { m_actionTarget = guid; };
void AddUniqueUse(Player* player);
void AddUse() { ++m_useTimes; }
bool IsInUse() const { return m_isInUse; }
@@ -846,6 +853,13 @@ class GameObject : public WorldObject
time_t m_reStockTimer; // timer to refill the chest
time_t m_despawnTimer; // timer to despawn the chest if something changed in it
void TriggerSummoningRitual();
void TriggerDelayedAction();
uint32 m_delayedActionTimer; // used for delayed GO actions
ObjectGuid m_actionTarget; // used for setting target of Summoning rituals
std::unique_ptr<GameObjectAI> m_AI;
private:

0 comments on commit 89fa2cc

Please sign in to comment.