Core/Spells: Implemented personal summons
This commit is contained in:
@@ -37,7 +37,6 @@ namespace Game.Collision
|
||||
public abstract Vector3 GetPosition();
|
||||
public abstract float GetOrientation();
|
||||
public abstract float GetScale();
|
||||
public abstract void DebugVisualizeCorner(Vector3 corner);
|
||||
}
|
||||
|
||||
public class GameObjectModel : IModel
|
||||
@@ -196,7 +195,7 @@ namespace Game.Collision
|
||||
string magic = reader.ReadStringFromChars(8);
|
||||
if (magic != MapConst.VMapMagic)
|
||||
{
|
||||
Log.outError(LogFilter.Misc, $"File '{MapConst.GAMEOBJECT_MODELS}' has wrong header, expected {MapConst.VMapMagic}.");
|
||||
Log.outError(LogFilter.Misc, $"File '{filename}' has wrong header, expected {MapConst.VMapMagic}.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -56,11 +56,28 @@ namespace Game.Combat
|
||||
public void doAddThreat(Unit victim, float threat)
|
||||
{
|
||||
uint redirectThreadPct = victim.GetRedirectThreatPercent();
|
||||
Unit redirectTarget = victim.GetRedirectThreatTarget();
|
||||
|
||||
// If victim is personnal spawn, redirect all aggro to summoner
|
||||
TempSummon tempSummonVictim = victim.ToTempSummon();
|
||||
if (tempSummonVictim)
|
||||
{
|
||||
if (tempSummonVictim.IsVisibleBySummonerOnly())
|
||||
{
|
||||
// Personnal Spawns from same summoner can aggro each other
|
||||
if (!GetOwner().ToTempSummon() ||
|
||||
!GetOwner().ToTempSummon().IsVisibleBySummonerOnly() ||
|
||||
tempSummonVictim.GetSummonerGUID() != GetOwner().ToTempSummon().GetSummonerGUID())
|
||||
{
|
||||
redirectThreadPct = 100;
|
||||
redirectTarget = tempSummonVictim.GetSummoner();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// must check > 0.0f, otherwise dead loop
|
||||
if (threat > 0.0f && redirectThreadPct != 0)
|
||||
{
|
||||
Unit redirectTarget = victim.GetRedirectThreatTarget();
|
||||
if (redirectTarget != null)
|
||||
{
|
||||
float redirectThreat = MathFunctions.CalculatePct(threat, redirectThreadPct);
|
||||
|
||||
@@ -548,7 +548,7 @@ namespace Game.DataStorage
|
||||
public sealed class SummonPropertiesRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint Flags;
|
||||
public SummonPropFlags Flags;
|
||||
public SummonCategory Control;
|
||||
public ushort Faction;
|
||||
public SummonType Title;
|
||||
|
||||
@@ -1719,8 +1719,19 @@ namespace Game.Entities
|
||||
WorldObject viewpoint = this;
|
||||
Player player = ToPlayer();
|
||||
if (player != null)
|
||||
{
|
||||
viewpoint = player.GetViewpoint();
|
||||
|
||||
Creature creature = obj.ToCreature();
|
||||
if (creature)
|
||||
{
|
||||
TempSummon tempSummon = creature.ToTempSummon();
|
||||
if (tempSummon)
|
||||
if (tempSummon.IsVisibleBySummonerOnly() && GetGUID() != tempSummon.GetSummonerGUID())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (viewpoint == null)
|
||||
viewpoint = this;
|
||||
|
||||
@@ -1990,7 +2001,7 @@ namespace Game.Entities
|
||||
return null;
|
||||
}
|
||||
|
||||
public TempSummon SummonCreature(uint id, float x, float y, float z, float ang = 0, TempSummonType spwtype = TempSummonType.ManualDespawn, uint despwtime = 0)
|
||||
public TempSummon SummonCreature(uint id, float x, float y, float z, float ang = 0, TempSummonType spwtype = TempSummonType.ManualDespawn, uint despwtime = 0, bool visibleBySummonerOnly = false)
|
||||
{
|
||||
if (x == 0.0f && y == 0.0f && z == 0.0f)
|
||||
{
|
||||
@@ -1999,15 +2010,15 @@ namespace Game.Entities
|
||||
}
|
||||
Position pos = new Position();
|
||||
pos.Relocate(x, y, z, ang);
|
||||
return SummonCreature(id, pos, spwtype, despwtime, 0);
|
||||
return SummonCreature(id, pos, spwtype, despwtime, 0, visibleBySummonerOnly);
|
||||
}
|
||||
|
||||
public TempSummon SummonCreature(uint entry, Position pos, TempSummonType spwtype = TempSummonType.ManualDespawn, uint duration = 0, uint vehId = 0)
|
||||
public TempSummon SummonCreature(uint entry, Position pos, TempSummonType spwtype = TempSummonType.ManualDespawn, uint duration = 0, uint vehId = 0, bool visibleBySummonerOnly = false)
|
||||
{
|
||||
Map map = GetMap();
|
||||
if (map != null)
|
||||
{
|
||||
TempSummon summon = map.SummonCreature(entry, pos, null, duration, isTypeMask(TypeMask.Unit) ? ToUnit() : null);
|
||||
TempSummon summon = map.SummonCreature(entry, pos, null, duration, ToUnit(), 0, vehId, visibleBySummonerOnly);
|
||||
if (summon != null)
|
||||
{
|
||||
summon.SetTempSummonType(spwtype);
|
||||
|
||||
@@ -1716,7 +1716,8 @@ namespace Game.Entities
|
||||
|
||||
void CastAllObtainSpells()
|
||||
{
|
||||
for (byte slot = InventorySlots.ItemStart; slot < InventorySlots.ItemEnd; ++slot)
|
||||
int inventoryEnd = InventorySlots.ItemStart + GetInventorySlotCount();
|
||||
for (byte slot = InventorySlots.ItemStart; slot < inventoryEnd; ++slot)
|
||||
{
|
||||
Item item = GetItemByPos(InventorySlots.Bag0, slot);
|
||||
if (item)
|
||||
|
||||
@@ -4501,6 +4501,9 @@ namespace Game.Entities
|
||||
// update visibility
|
||||
UpdateObjectVisibility();
|
||||
|
||||
// recast lost by death auras of any items held in the inventory
|
||||
CastAllObtainSpells();
|
||||
|
||||
if (!applySickness)
|
||||
return;
|
||||
|
||||
|
||||
@@ -296,11 +296,15 @@ namespace Game.Entities
|
||||
|
||||
public uint GetTimer() { return m_timer; }
|
||||
|
||||
public void SetVisibleBySummonerOnly(bool visibleBySummonerOnly) { m_visibleBySummonerOnly = visibleBySummonerOnly; }
|
||||
public bool IsVisibleBySummonerOnly() { return m_visibleBySummonerOnly; }
|
||||
|
||||
public SummonPropertiesRecord m_Properties;
|
||||
TempSummonType m_type;
|
||||
uint m_timer;
|
||||
uint m_lifetime;
|
||||
ObjectGuid m_summonerGUID;
|
||||
bool m_visibleBySummonerOnly;
|
||||
}
|
||||
|
||||
public class Minion : TempSummon
|
||||
|
||||
@@ -3294,7 +3294,7 @@ namespace Game.Maps
|
||||
}
|
||||
}
|
||||
|
||||
public TempSummon SummonCreature(uint entry, Position pos, SummonPropertiesRecord properties = null, uint duration = 0, Unit summoner = null, uint spellId = 0, uint vehId = 0)
|
||||
public TempSummon SummonCreature(uint entry, Position pos, SummonPropertiesRecord properties = null, uint duration = 0, Unit summoner = null, uint spellId = 0, uint vehId = 0, bool visibleBySummonerOnly = false)
|
||||
{
|
||||
var mask = UnitTypeMask.Summon;
|
||||
if (properties != null)
|
||||
@@ -3333,7 +3333,7 @@ namespace Game.Maps
|
||||
mask = UnitTypeMask.Minion;
|
||||
break;
|
||||
default:
|
||||
if (Convert.ToBoolean(properties.Flags & 512)) // Mirror Image, Summon Gargoyle
|
||||
if (Convert.ToBoolean(properties.Flags & SummonPropFlags.Unk10)) // Mirror Image, Summon Gargoyle
|
||||
mask = UnitTypeMask.Guardian;
|
||||
break;
|
||||
}
|
||||
@@ -3374,10 +3374,10 @@ namespace Game.Maps
|
||||
PhasingHandler.InheritPhaseShift(summon, summoner);
|
||||
|
||||
summon.SetUInt32Value(UnitFields.CreatedBySpell, spellId);
|
||||
|
||||
summon.SetHomePosition(pos);
|
||||
|
||||
summon.InitStats(duration);
|
||||
summon.SetVisibleBySummonerOnly(visibleBySummonerOnly);
|
||||
|
||||
AddToMap(summon.ToCreature());
|
||||
summon.InitSummon();
|
||||
|
||||
|
||||
@@ -1710,6 +1710,8 @@ namespace Game.Spells
|
||||
if (m_originalCaster == null)
|
||||
return;
|
||||
|
||||
bool personalSpawn = (properties.Flags & SummonPropFlags.PersonalSpawn) != 0;
|
||||
|
||||
int duration = m_spellInfo.CalcDuration(m_originalCaster);
|
||||
|
||||
TempSummon summon = null;
|
||||
@@ -1750,7 +1752,7 @@ namespace Game.Spells
|
||||
case SummonCategory.Wild:
|
||||
case SummonCategory.Ally:
|
||||
case SummonCategory.Unk:
|
||||
if (Convert.ToBoolean(properties.Flags & 512))
|
||||
if (Convert.ToBoolean(properties.Flags & SummonPropFlags.Unk10))
|
||||
{
|
||||
SummonGuardian(effIndex, entry, properties, numSummons);
|
||||
break;
|
||||
@@ -1771,7 +1773,7 @@ namespace Game.Spells
|
||||
case SummonType.LightWell:
|
||||
case SummonType.Totem:
|
||||
{
|
||||
summon = m_caster.GetMap().SummonCreature(entry, destTarget, properties, (uint)duration, m_originalCaster, m_spellInfo.Id);
|
||||
summon = m_caster.GetMap().SummonCreature(entry, destTarget, properties, (uint)duration, m_originalCaster, m_spellInfo.Id, 0, personalSpawn);
|
||||
if (summon == null || !summon.IsTotem())
|
||||
return;
|
||||
|
||||
@@ -1784,7 +1786,7 @@ namespace Game.Spells
|
||||
}
|
||||
case SummonType.Minipet:
|
||||
{
|
||||
summon = m_caster.GetMap().SummonCreature(entry, destTarget, properties, (uint)duration, m_originalCaster, m_spellInfo.Id);
|
||||
summon = m_caster.GetMap().SummonCreature(entry, destTarget, properties, (uint)duration, m_originalCaster, m_spellInfo.Id, 0, personalSpawn);
|
||||
if (summon == null || !summon.HasUnitTypeMask(UnitTypeMask.Minion))
|
||||
return;
|
||||
|
||||
@@ -1811,7 +1813,7 @@ namespace Game.Spells
|
||||
// randomize position for multiple summons
|
||||
m_caster.GetRandomPoint(destTarget, radius, out pos);
|
||||
|
||||
summon = m_originalCaster.SummonCreature(entry, pos, summonType, (uint)duration);
|
||||
summon = m_originalCaster.SummonCreature(entry, pos, summonType, (uint)duration, 0, personalSpawn);
|
||||
if (summon == null)
|
||||
continue;
|
||||
|
||||
@@ -1832,7 +1834,7 @@ namespace Game.Spells
|
||||
SummonGuardian(effIndex, entry, properties, numSummons);
|
||||
break;
|
||||
case SummonCategory.Puppet:
|
||||
summon = m_caster.GetMap().SummonCreature(entry, destTarget, properties, (uint)duration, m_originalCaster, m_spellInfo.Id);
|
||||
summon = m_caster.GetMap().SummonCreature(entry, destTarget, properties, (uint)duration, m_originalCaster, m_spellInfo.Id, 0, personalSpawn);
|
||||
break;
|
||||
case SummonCategory.Vehicle:
|
||||
// Summoning spells (usually triggered by npc_spellclick) that spawn a vehicle and that cause the clicker
|
||||
|
||||
Reference in New Issue
Block a user