/*************************************************************************
* 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);
}
}
}
}