/************************************************************************* * StatCollection.cs * ----------------- * begin : Jan 24, 2007 * copyright : (C) The WCell Team * email : info@wcell.org *************************************************************************/ /************************************************************************* * * 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. * *************************************************************************/ using System; using System.Collections.Generic; using System.Linq; using System.Text; using WCell.Core; using Cell.Core; using WCell.RealmServer.Entities; namespace WCell.RealmServer.Stats { /// /// Manages the different categories of stat modification and allows calculators to be /// implemented as scripts for calculating totals. /// public class StatCollection { private Unit m_owner; private HashSet m_changeTracker; private Queue m_changes; private Dictionary> m_stats; private SpinWaitLock m_changeLock; private SpinWaitLock m_flagLock; /// /// Creates a object with the given as the owner. /// /// the that this collection belongs to public StatCollection(Unit unit) { m_owner = unit; m_changes = new Queue(); m_changeTracker = new HashSet(); m_stats = new Dictionary>(); Dictionary tempDict; for (int i = (int)StatCollectionType.Base; i < (int)StatCollectionType.End; i++) { tempDict = new Dictionary(); for (int j = (int)StatTypes.Base; j < (int)StatTypes.End; j++) { if ((StatCollectionType)i == StatCollectionType.Multiplicative) { tempDict.Add((StatTypes)j, 1.0); } else { tempDict.Add((StatTypes)j, 0.0); } } m_stats.Add((StatCollectionType)i, tempDict); } m_changeLock = new SpinWaitLock(); m_flagLock = new SpinWaitLock(); } /// /// Adds a given value to the existing value for a specific in a /// specific collection. /// /// the collection type /// the stat type /// the amount to add public void AddToStat(StatCollectionType collectionType, StatTypes statType, double value) { m_changeLock.Enter(); try { m_stats[collectionType][statType] = m_stats[collectionType][statType] + value; FlagChange(statType); } finally { m_changeLock.Exit(); } } /// /// Adds a given value to the existing value for a specific in a /// specific collection. /// /// the collection type /// the stat type /// the amount to add public void AddToStat(StatCollectionType collectionType, StatTypes statType, short value) { m_changeLock.Enter(); try { m_stats[collectionType][statType] = m_stats[collectionType][statType] + (double)value; FlagChange(statType); } finally { m_changeLock.Exit(); } } /// /// Adds a given value to the existing value for a specific in a /// specific collection. /// /// the collection type /// the stat type /// the amount to add public void AddToStat(StatCollectionType collectionType, StatTypes statType, int value) { m_changeLock.Enter(); try { m_stats[collectionType][statType] = m_stats[collectionType][statType] + (double)value; FlagChange(statType); } finally { m_changeLock.Exit(); } } /// /// Removes a given amount from the existing value for a specific in a /// specific collection. /// /// the collection type /// the stat type /// the amount to remove public void RemoveFromStat(StatCollectionType collectionType, StatTypes statType, double value) { m_changeLock.Enter(); try { m_stats[collectionType][statType] = m_stats[collectionType][statType] - value; } finally { m_changeLock.Exit(); } } /// /// Removes a given amount from the existing value for a specific in a /// specific collection. /// /// the collection type /// the stat type /// the amount to remove public void RemoveFromStat(StatCollectionType collectionType, StatTypes statType, short value) { m_changeLock.Enter(); try { m_stats[collectionType][statType] = m_stats[collectionType][statType] - (double)value; } finally { m_changeLock.Exit(); } } /// /// Removes a given amount from the existing value for a specific in a /// specific collection. /// /// the collection type /// the stat type /// the amount to remove public void RemoveFromStat(StatCollectionType collectionType, StatTypes statType, int value) { m_changeLock.Enter(); try { m_stats[collectionType][statType] = m_stats[collectionType][statType] - (double)value; } finally { m_changeLock.Exit(); } } /// /// Sets a specific value for a specific in a specific /// collection. /// /// the collection type /// the stat type /// the amount to set public void SetValue(StatCollectionType collectionType, StatTypes statType, double value) { m_changeLock.Enter(); try { m_stats[collectionType][statType] = value; } finally { m_changeLock.Exit(); } } /// /// Sets a specific value for a specific in a specific /// collection. /// /// the collection type /// the stat type /// the amount to set public void SetValue(StatCollectionType collectionType, StatTypes statType, short value) { m_changeLock.Enter(); try { m_stats[collectionType][statType] = (double)value; } finally { m_changeLock.Exit(); } } /// /// Sets a specific value for a specific in a specific /// collection. /// /// the collection type /// the stat type /// the amount to set public void SetValue(StatCollectionType collectionType, StatTypes statType, int value) { m_changeLock.Enter(); try { m_stats[collectionType][statType] = (double)value; } finally { m_changeLock.Exit(); } } /// /// Gets the value for a specific and a specific . /// /// the collection type /// the stat type /// the value for the given collection type/stat type public double GetStat(StatCollectionType collectionType, StatTypes statType) { m_changeLock.Enter(); try { return m_stats[collectionType][statType]; } finally { m_changeLock.Exit(); } } /// /// Gets the modified (total/final) value of a specific for the /// owner. /// /// the stat type /// the modified value for the given ; or /// if there was anexception when executing the calculator. public double GetModified(StatTypes statType) { m_changeLock.Enter(); try { double staticVal = (m_stats[StatCollectionType.BaseModifier][statType] + m_stats[StatCollectionType.PositiveModifier][statType] + m_stats[StatCollectionType.NegativeModifier][statType]); double posPercentMod = staticVal * m_stats[StatCollectionType.PositiveMultiplier][statType]; double negPercentMod = staticVal * m_stats[StatCollectionType.NegativeMultiplier][statType]; return staticVal + posPercentMod + negPercentMod; } finally { m_changeLock.Exit(); } } /// /// Manually flags a stat as changed. /// /// public void FlagChange(StatTypes statType) { m_flagLock.Enter(); try { StatChange change = new StatChange(statType); if (!m_changeTracker.Contains(change)) { m_changeTracker.Add(change); m_changes.Add(change); } } finally { m_flagLock.Exit(); } } /// /// Synchonizes all the pending stat changes with the owner . /// public void SynchronizeChanges() { if (m_changes.Count == 0) { return; } LinkedList changes; m_changeLock.Enter(); try { changes = new LinkedList(m_changes); } finally { m_flagLock.Exit(); } foreach (StatChange change in changes) { change.CommitChange(m_owner); } } } }