ace/Source/ACE.DatLoader/Entity/SpellBase.cs
Mag-nus 390961ca70
More profiling based improvements (#1091)
* Landblock LoadMeshes summary improved

* Landblock CellLandblock/LandblockInfo get only (set in ctor)

* Fix LScape get_landblock thread safety

* Fix EnchantmentManager Surpass (retval)

* Only create the WorldObject.ObjectGuid once

We don't need to instantinate a new ObjetGuid per get of the property.

* castclass (cast) is faster than isinst (as), also fix double enumeration

* Streamline Attributes and Vitals

They are fixed and set in SetEphemeralValues, called by the ctor.

They do not need the additional layer that Skills do.

* BiotaPropertiesEnchatmentRegistry direct access fixes (Use extensions instead)

* Another BiotaPropertiesEnchantmentRegistry -> Extension fix

* Initial EnchantmentManagerWithCaching

* Added the remaining functions to the cache

* DelayManager using the wrong Min. woops...

Min() was the linq version that enumerates the whole collection. Min is the built in fast version for the SortedSet

* Fix PortalDatDatabase properties

They should only be set once, not executing the getter on every request.

Furthermore, SpellBase was referencing the static DatManager via the Unpack command to construct SpellWords. A dat file type should not be referencing the static datmanager. Instead, we use the GetSPellWords that takes the reference to DatManager to generate the same result.

* Cleanup loadalllandblocks status output

* Improve LoadAllLandblocks comments
2018-11-14 20:52:13 -06:00

160 lines
6.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Collections.Generic;
using System.IO;
using ACE.DatLoader.FileTypes;
using ACE.Entity.Enum;
namespace ACE.DatLoader.Entity
{
public class SpellBase : IUnpackable
{
public string Name { get; private set; }
public string Desc { get; private set; }
public MagicSchool School { get; private set; }
public uint Icon { get; private set; }
public uint Category { get; private set; } // All related levels of the same spell. Same category spells will not stack. (Strength Self I & Strength Self II)
public uint Bitfield { get; private set; }
public uint BaseMana { get; private set; } // Mana Cost
public float BaseRangeConstant { get; private set; }
public float BaseRangeMod { get; private set; }
public uint Power { get; private set; } // Used to determine which spell in the catgory is the strongest.
public float SpellEconomyMod { get; private set; } // A legacy of a bygone era
public uint FormulaVersion { get; private set; }
public float ComponentLoss { get; private set; } // Burn rate
public SpellType MetaSpellType { get; private set; }
public uint MetaSpellId { get; private set; } // Just the spell id again
// Only on EnchantmentSpell/FellowshipEnchantmentSpells
public double Duration { get; private set; }
public float DegradeModifier { get; private set; } // Unknown what this does
public float DegradeLimit { get; private set; } // Unknown what this does
public double PortalLifetime { get; private set; } // Only for PortalSummon_SpellType
public List<uint> Formula { get; private set; } // UInt Values correspond to the SpellComponentsTable
public uint CasterEffect { get; private set; } // effect that playes on the caster of the casted spell (e.g. for buffs, protects, etc)
public uint TargetEffect { get; private set; } // effect that playes on the target of the casted spell (e.g. for debuffs, vulns, etc)
public uint FizzleEffect { get; private set; } // is always zero. All spells have the same fizzle effect.
public double RecoveryInterval { get; private set; } // is always zero
public float RecoveryAmount { get; private set; } // is always zero
public uint DisplayOrder { get; private set; } // for soring in the spell list in the client UI
public uint NonComponentTargetType { get; private set; } // Unknown what this does
public uint ManaMod { get; private set; } // Additional mana cost per target (e.g. "Incantation of Acid Bane" Mana Cost = 80 + 14 per target)
public SpellBase()
{
}
public SpellBase(uint power, double duration, float degradeModifier, float degradeLimit)
{
Power = power;
Duration = duration;
DegradeModifier = degradeModifier;
DegradeLimit = degradeLimit;
}
public void Unpack(BinaryReader reader)
{
Name = reader.ReadObfuscatedString();
reader.AlignBoundary();
Desc = reader.ReadObfuscatedString();
reader.AlignBoundary();
School = (MagicSchool)reader.ReadUInt32();
Icon = reader.ReadUInt32();
Category = reader.ReadUInt32();
Bitfield = reader.ReadUInt32();
BaseMana = reader.ReadUInt32();
BaseRangeConstant = reader.ReadSingle();
BaseRangeMod = reader.ReadSingle();
Power = reader.ReadUInt32();
SpellEconomyMod = reader.ReadSingle();
FormulaVersion = reader.ReadUInt32();
ComponentLoss = reader.ReadSingle();
MetaSpellType = (SpellType)reader.ReadUInt32();
MetaSpellId = reader.ReadUInt32();
switch (MetaSpellType)
{
case SpellType.Enchantment:
case SpellType.FellowEnchantment:
Duration = reader.ReadDouble();
DegradeModifier = reader.ReadSingle();
DegradeLimit = reader.ReadSingle();
break;
case SpellType.PortalSummon:
PortalLifetime = reader.ReadDouble();
break;
}
// Components : Load them first, then decrypt them. More efficient to hash all at once.
List<uint> rawComps = new List<uint>();
for (uint j = 0; j < 8; j++)
{
uint comp = reader.ReadUInt32();
// We will only add the comp if it is valid
if (comp > 0)
rawComps.Add(comp);
}
// Get the decryped component values
Formula = DecryptFormula(rawComps, Name, Desc);
CasterEffect = reader.ReadUInt32();
TargetEffect = reader.ReadUInt32();
FizzleEffect = reader.ReadUInt32();
RecoveryInterval = reader.ReadDouble();
RecoveryAmount = reader.ReadSingle();
DisplayOrder = reader.ReadUInt32();
NonComponentTargetType = reader.ReadUInt32();
ManaMod = reader.ReadUInt32();
}
private const uint HIGHEST_COMP_ID = 198; // "Essence of Kemeroi", for Void Spells -- not actually ever in game!
/// <summary>
/// Does the math based on the crypto keys (name and description) for the spell formula.
/// </summary>
private static List<uint> DecryptFormula(List<uint> rawComps, string name, string desc)
{
List<uint> comps = new List<uint>();
// uint testDescHash = ComputeHash(" 200");
uint nameHash = SpellTable.ComputeHash(name);
uint descHash = SpellTable.ComputeHash(desc);
uint key = (nameHash % 0x12107680) + (descHash % 0xBEADCF45);
for (int i = 0; i < rawComps.Count; i++)
{
uint comp = (rawComps[i] - key);
// This seems to correct issues with certain spells with extended characters.
if (comp > HIGHEST_COMP_ID) // highest comp ID is 198 - "Essence of Kemeroi", for Void Spells
comp = comp & 0xFF;
comps.Add(comp);
}
return comps;
}
private string spellWords;
/// <summary>
/// Not technically part of this function, but saves numerous looks later.
/// </summary>
public string GetSpellWords(SpellComponentsTable comps)
{
if (spellWords != null)
return spellWords;
spellWords = SpellComponentsTable.GetSpellWords(comps, Formula);
return spellWords;
}
}
}