/*
* The Mana Server
* Copyright (C) 2004-2010 The Mana World Development Team
*
* This file is part of The Mana Server.
*
* The Mana Server 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
* any later version.
*
* The Mana Server is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with The Mana Server. If not, see .
*/
#ifndef ATTRIBUTE_H
#define ATTRIBUTE_H
#include "common/defines.h"
#include "attributemanager.h"
#include
#include
class AttributeModifierState
{
public:
AttributeModifierState(unsigned short duration,
double value,
unsigned id)
: mDuration(duration)
, mValue(value)
, mId(id)
{}
bool tick() { return mDuration ? !--mDuration : false; }
private:
/** Number of ticks (0 means permanent, e.g. equipment). */
unsigned short mDuration;
const double mValue; /**< Positive or negative amount. */
/**
* Special purpose variable used to identify this effect to
* dispells or similar. Exact usage depends on the effect,
* origin, etc.
*/
const unsigned mId;
friend bool durationCompare(const AttributeModifierState*,
const AttributeModifierState*);
friend class AttributeModifiersEffect;
};
class AttributeModifiersEffect
{
public:
AttributeModifiersEffect(StackableType stackableType,
ModifierEffectType effectType);
~AttributeModifiersEffect();
/**
* Recalculates the value for this level.
* @returns True if the value changed, false if it did not change.
* Note that this will not change values at a higher level, nor the
* overall modified value for this attribute.
* If this returns true, the cached values for *all* modifiers of a
* higher level must be recalculated, as well as the final
*/
bool add(unsigned short duration, double value,
double prevLayerValue, int level);
/**
* remove() - as with Attribute::remove().
*/
bool remove(double value, unsigned id, bool fullCheck);
/**
* Performs the necessary modifications to mMod when the states change.
* @param value The value to alter. This is only used in stackable
* types, as the effect can be simply inverted there.
* For non stackable types (and stackable multiplicative types
* where the value is zero), mMod must be recalculated from all
* current modifiers.
* @note This /negates/ the effect of value.
* @note A parameter should always be provided when stackable.
*/
void updateMod(double value = 0);
/**
* Performs the necessary modifications to mCacheVal when the states
* change.
*/
bool recalculateModifiedValue(double newPrevLayerValue);
double getCachedModifiedValue() const { return mCacheVal; }
bool tick();
/**
* clearMods() - removes all modifications present in this layer.
* This only really makes sense when all other layers are being reset too.
* @param baseValue the value to reset to - typically an Attribute's mBase
*/
void clearMods(double baseValue);
private:
/** List of all modifications present at this level */
std::list mStates;
/**
* Stores the value that results from mStates. This takes into
* account all previous layers.
*/
double mCacheVal;
/**
* Stores the effective modifying value from mStates. This defaults to
* 0 for additive modifiers and 1 for multiplicative modifiers.
*/
double mMod;
const StackableType mStackableType;
const ModifierEffectType mEffectType;
};
/**
* Represents some attribute of a being. Is has a base value and a modified
* value, subject to modifiers that can be added and removed.
*/
class Attribute
{
public:
Attribute()
: mBase(0)
, mMinValue(0)
, mMaxValue(0)
{throw;} // DEBUG; Find improper constructions
Attribute(const AttributeManager::AttributeInfo &info);
~Attribute();
void setBase(double base);
double getBase() const { return mBase; }
double getModifiedAttribute() const
{ return mMods.empty() ? mBase :
(*mMods.rbegin())->getCachedModifiedValue(); }
/*
* add() and remove() are the standard functions used to add and
* remove modifiers while keeping track of the modifier state.
*/
/**
* @param duration The amount of time before the modifier expires
* naturally.
* When set to 0, the effect does not expire.
* @param value The value to be applied as the modifier.
* @param layer The id of the layer with which this modifier is to be
* applied to.
* @param id Used to identify this effect.
* @return Whether the modified attribute value was changed.
*/
bool add(unsigned short duration, double value, unsigned layer, int id = 0);
/**
* @param value The value of the modifier to be removed.
* - When 0, id is used exclusively to identify modifiers.
* @param layer The id of the layer which contains the modifier to be removed.
* @param id Used to identify this effect.
* - When 0, only the first match will be removed.
* - When non-0, all modifiers matching this id and other
* parameters will be removed.
* @param fullcheck Whether to perform a check for all modifiers,
* or only those that are otherwise permanent (ie. duration of 0)
* @returns Whether the modified attribute value was changed.
*/
bool remove(double value, unsigned layer, int id, bool fullcheck);
/**
* clearMods() removes *all* modifications present in this Attribute (!)
*/
void clearMods();
/**
* tick() processes all timers associated with modifiers for this attribute.
*/
bool tick();
private:
/**
* Checks the min and max permitted values for the given base value
* and return the adjusted value.
*/
double checkBounds(double baseValue) const;
double mBase; // The attribute base value
double mMinValue; // The min authorized base and derived attribute value
double mMaxValue; // The max authorized base and derived attribute value
std::vector mMods;
};
#endif // ATTRIBUTE_H