//::///////////////////////////////////////////////
//:: Meldshaping/Incarnum main include: Miscellaneous
//:: moi_inc_moifunc
//::///////////////////////////////////////////////
/** @file
    Defines various functions and other stuff that
    do something related to Meldshaping.

    Also acts as inclusion nexus for the general
    meldshaping includes. In other words, don't include
    them directly in your scripts, instead include this.

    @author Stratovarius
    @date   Created - 2019.12.28
*/
//:://////////////////////////////////////////////
//:://////////////////////////////////////////////

//////////////////////////////////////////////////
/*             Function prototypes              */
//////////////////////////////////////////////////

/**
 * Determines the given creature's Meldshaper level. 
 *
 * @param oMeldshaper    The creature whose Meldshaper level to determine
 * @param nSpecificClass The class to determine the creature's Meldshaper
 *                       level in.
 * @param nMeld          The meld to test, since Incarnum does level by meld
 *
 * @return               The Meldshaper level
 */
int GetMeldshaperLevel(object oMeldshaper, int nSpecificClass, int nMeld);

/**
 * Determines the given creature's highest unmodified Meldshaper level among its
 * Meldshaping classes.
 *
 * @param oMeldshaper Creature whose highest Meldshaper level to determine
 * @return          The highest unmodified Meldshaper level the creature can have
 */
int GetHighestMeldshaperLevel(object oMeldshaper);

/**
 * Determines whether a given class is a Incarnum-related class or not.
 *
 * @param nClass CLASS_TYPE_* of the class to test
 * @return       TRUE if the class is a Incarnum-related class, FALSE otherwise
 */
int GetIsIncarnumClass(int nClass);

/**
 * Calculates how many Meldshaper levels are gained by a given creature from
 * it's levels in prestige classes.
 *
 * @param oMeldshaper Creature to calculate added Meldshaper levels for
 * @return          The number of Meldshaper levels gained
 */
int GetIncarnumPRCLevels(object oMeldshaper);

/**
 * Determines which of the character's classes is their highest or first 
 * Meldshaping class, if any. This is the one which gains Meldshaper 
 * level raise benefits from prestige classes.
 *
 * @param oMeldshaper Creature whose classes to test
 * @return          CLASS_TYPE_* of the first Meldshaping class,
 *                  CLASS_TYPE_INVALID if the creature does not possess any.
 */
int GetPrimaryIncarnumClass(object oMeldshaper = OBJECT_SELF);

/**
 * Determines the position of a creature's first Meldshaping class, if any.
 *
 * @param oMeldshaper Creature whose classes to test
 * @return          The position of the first Meldshaping class {1, 2, 3} or 0 if
 *                  the creature possesses no levels in Meldshaping classes.
 */
int GetFirstIncarnumClassPosition(object oMeldshaper = OBJECT_SELF);

/**
 * Checks every second to see if temporary essentia has been lost
 *
 * @param oMeldshaper  The meldshaper
 */
void SpawnTempEssentiaChecker(object oMeldshaper);

/**
 * Returns total value of temporary essentia for the meldshaper
 *
 * @param oMeldshaper The meldshaper
 * 
 * @return        Total value of temporary essentia
 */
int GetTemporaryEssentia(object oMeldshaper);

/**
 * Essentia put into feats is locked away for 24 hours/until next rest
 *
 * @param oMeldshaper The meldshaper
 * 
 * @return        Total value of locked essentia
 */
int GetFeatLockedEssentia(object oMeldshaper);

/**
 * Total essentia a character has access to
 *
 * @param oMeldshaper The meldshaper
 * 
 * @return        Total value of essentia available
 */
int GetTotalEssentia(object oMeldshaper);

/**
 * Total essentia a character has access to, minus feat locked essentia
 *
 * @param oMeldshaper The meldshaper
 * 
 * @return        Total value of essentia available, minus feat locked essentia
 */
int GetTotalUsableEssentia(object oMeldshaper);

/**
 * Returns the slot associated to a given chakra
 *
 * @param nChakra Chakra constant
 * 
 * @return        Slot constant
 */
int ChakraToSlot(int nChakra);

/**
 * Returns the total binds the character can have for that class and level
 *
 * @param oMeldshaper The meldshaper 
 * @param nClass      The class to check
 * 
 * @return        Slot constant
 */
int GetMaxBindCount(object oMeldshaper, int nClass);

//////////////////////////////////////////////////
/*                  Includes                    */
//////////////////////////////////////////////////

#include "prc_inc_natweap"
#include "prc_inc_function"

//////////////////////////////////////////////////
/*             Function definitions             */
//////////////////////////////////////////////////

int GetMeldshaperLevel(object oMeldshaper, int nSpecificClass, int nMeld)
{
    int nLevel;

    //if (DEBUG) DoDebug("GetMeldshaperLevel: "+GetName(oMeldshaper)+" is a "+IntToString(nSpecificClass));

    if(GetIsIncarnumClass(nSpecificClass))
    {
        // Meldshaper level is class level + prestige
        nLevel = GetLevelByClass(nSpecificClass, oMeldshaper);
        if(nLevel)
        {
        	// Prevents people double-dipping prestige levels
            if (nSpecificClass == GetPrimaryIncarnumClass(oMeldshaper)) 
            {
            	nLevel += GetIncarnumPRCLevels(oMeldshaper);
            	nLevel += GetLevelByClass(CLASS_TYPE_NECROCARNATE, oMeldshaper); // Necrocarnate is here because it doesn't add to anything other than meldshaper level
            }	
            if (nSpecificClass == CLASS_TYPE_SOULBORN) nLevel /= 2;                   
        }   
    }
    
    //if(DEBUG) DoDebug("Meldshaper Level: " + IntToString(nLevel));
    // Being bound to the Totem Chakra increases the level by one.
	if (GetIsMeldBound(oMeldshaper, nMeld) == CHAKRA_TOTEM) nLevel++;
    return nLevel;
}

int GetIncarnumLevelForClass(int nSpecificClass, object oMeldshaper)
{
    int nLevel;

    //if (DEBUG) DoDebug("GetMeldshaperLevel: "+GetName(oMeldshaper)+" is a "+IntToString(nSpecificClass));

    if(GetIsIncarnumClass(nSpecificClass))
    {
        // Meldshaper level is class level + prestige
        nLevel = GetLevelByClass(nSpecificClass, oMeldshaper);
        if(nLevel)
        {
        	// Prevents people double-dipping prestige levels
            if (nSpecificClass == GetPrimaryIncarnumClass(oMeldshaper)) nLevel += GetIncarnumPRCLevels(oMeldshaper);                 
        }   
    }
    if(nSpecificClass == CLASS_TYPE_UMBRAL_DISCIPLE || nSpecificClass == CLASS_TYPE_INCANDESCENT_CHAMPION || nSpecificClass == CLASS_TYPE_NECROCARNATE)
    	nLevel = GetLevelByClass(nSpecificClass, oMeldshaper);
    
    //if(DEBUG) DoDebug("GetIncarnumLevelForClass: " + IntToString(nLevel));
    return nLevel;
}

int GetHighestMeldshaperLevel(object oMeldshaper)
{
    /**return PRCMax(PRCMax(GetClassByPosition(1, oMeldshaper) != CLASS_TYPE_INVALID ? GetMeldshaperLevel(oMeldshaper, GetClassByPosition(1, oMeldshaper), -1) : 0,
                   GetClassByPosition(2, oMeldshaper) != CLASS_TYPE_INVALID ? GetMeldshaperLevel(oMeldshaper, GetClassByPosition(2, oMeldshaper), -1) : 0
                   ),
               GetClassByPosition(3, oMeldshaper) != CLASS_TYPE_INVALID ? GetMeldshaperLevel(oMeldshaper, GetClassByPosition(3, oMeldshaper), -1) : 0
               );**/
               
	int nMax;
	int i;
    for(i = 1; i <= 8; i++)
    {
        int nClass = GetClassByPosition(i, oMeldshaper);
        int nTest = GetMeldshaperLevel(oMeldshaper, GetClassByPosition(i, oMeldshaper), -1);
		if (nTest > nMax)
			nMax = nTest;
    }	
    return nMax;
}

int GetIsIncarnumClass(int nClass)
{
    return nClass == CLASS_TYPE_INCARNATE
         || nClass == CLASS_TYPE_SOULBORN
         || nClass == CLASS_TYPE_TOTEMIST
         || nClass == CLASS_TYPE_SPINEMELD_WARRIOR;
}

int GetIncarnumPRCLevels(object oMeldshaper)
{
    int nLevel = GetLevelByClass(CLASS_TYPE_SAPPHIRE_HIERARCH, oMeldshaper);
    nLevel += GetLevelByClass(CLASS_TYPE_SOULCASTER, oMeldshaper);
    
    // These two don't add at 1st level
    if (GetLevelByClass(CLASS_TYPE_IRONSOUL_FORGEMASTER, oMeldshaper))
        nLevel += GetLevelByClass(CLASS_TYPE_IRONSOUL_FORGEMASTER, oMeldshaper) - 1;
    // Totem Rager    
	if (GetLevelByClass(CLASS_TYPE_TOTEM_RAGER, oMeldshaper) >= 6)
		nLevel += (GetLevelByClass(CLASS_TYPE_TOTEM_RAGER, oMeldshaper)) -2;
	else if (GetLevelByClass(CLASS_TYPE_TOTEM_RAGER, oMeldshaper))
		nLevel += (GetLevelByClass(CLASS_TYPE_TOTEM_RAGER, oMeldshaper)) -1;
	//This is an odd one	
	if (GetLevelByClass(CLASS_TYPE_WITCHBORN_BINDER, oMeldshaper))
	{
		nLevel += (GetLevelByClass(CLASS_TYPE_WITCHBORN_BINDER, oMeldshaper)+1)/2;
		
		if (GetLevelByClass(CLASS_TYPE_WITCHBORN_BINDER, oMeldshaper) >= 10) nLevel += 1;
	}	

    /*if (GetLevelByClass(CLASS_TYPE_MASTER_OF_SHADOW, oMeldshaper))
        nLevel += GetLevelByClass(CLASS_TYPE_MASTER_OF_SHADOW, oMeldshaper) - 1;        
*/
    return nLevel;
}

int GetPrimaryIncarnumClass(object oMeldshaper = OBJECT_SELF)
{
    int nClass = CLASS_TYPE_INVALID;

    if(GetPRCSwitch(PRC_CASTERLEVEL_FIRST_CLASS_RULE))
    {
        int nIncarnumPos = GetFirstIncarnumClassPosition(oMeldshaper);
        if (!nIncarnumPos) return CLASS_TYPE_INVALID; // no Blade Magic Meldshaping class

        nClass = GetClassByPosition(nIncarnumPos, oMeldshaper);
    }
    else
    {
        int nClassTest, nClassLvlTest, nMax, i;        
		for(i = 1; i <= 8; i++)
		{
			int nClassTest = GetClassByPosition(i, oMeldshaper);
			
			if(GetIsIncarnumClass(nClassTest)) 
				nClassLvlTest = GetLevelByClass(nClassTest, oMeldshaper);
			else 
				nClassLvlTest = 0; // Reset to 0 each iteration that isn't incarnum
				
			if (nClassLvlTest > nMax)
			{
				nMax = nClassLvlTest;
				nClass = nClassTest;
			}			
		}	        

        if(nMax == 0) //No Incarnum classes
            nClass = CLASS_TYPE_INVALID;
    }

    return nClass;
}

int GetFirstIncarnumClassPosition(object oMeldshaper = OBJECT_SELF)
{
	int i;        
	for(i = 1; i <= 8; i++)
	{
		if (GetIsIncarnumClass(GetClassByPosition(i, oMeldshaper)))
			return i;			
	}

    return 0;
}

string GetMeldFile(int nClass = -1)
{
	//string sFile;
	//if (nClass == CLASS_TYPE_INCARNATE) sFile = "cls_meld_incarn";
	
	return "soulmelds";
}

string GetMeldshapingClassFile(int nClass)
{
	string sFile;
	if (nClass == CLASS_TYPE_INCARNATE) sFile = "cls_mlkn_incarn";
	else if (nClass == CLASS_TYPE_SOULBORN) sFile = "cls_mlkn_soulbn";
	else if (nClass == CLASS_TYPE_TOTEMIST) sFile = "cls_mlkn_totem";
	else if (nClass == CLASS_TYPE_SPINEMELD_WARRIOR) sFile = "cls_mlkn_spnmld";
	else if (nClass == CLASS_TYPE_UMBRAL_DISCIPLE) sFile = "cls_mlkn_umbral";
	else if (nClass == CLASS_TYPE_INCANDESCENT_CHAMPION) sFile = "cls_mlkn_incand";
	else if (nClass == CLASS_TYPE_NECROCARNATE) sFile = "cls_mlkn_necrnm";
	
	return sFile;
}

int GetMeldshapingClass(object oMeldshaper)
{
	int nClass = -1;
	// If there's levels in the class and haven't already done it
	if (GetLevelByClass(CLASS_TYPE_INCARNATE, oMeldshaper) && !GetLocalInt(oMeldshaper, "FirstMeldDone")) nClass = CLASS_TYPE_INCARNATE;
	else if (GetLevelByClass(CLASS_TYPE_SOULBORN, oMeldshaper) && !GetLocalInt(oMeldshaper, "SecondMeldDone")) nClass = CLASS_TYPE_SOULBORN;
	else if (GetLevelByClass(CLASS_TYPE_TOTEMIST, oMeldshaper) && !GetLocalInt(oMeldshaper, "ThirdMeldDone")) nClass = CLASS_TYPE_TOTEMIST;
	else if (GetLevelByClass(CLASS_TYPE_SPINEMELD_WARRIOR, oMeldshaper) && !GetLocalInt(oMeldshaper, "FourthMeldDone")) nClass = CLASS_TYPE_SPINEMELD_WARRIOR;
	//if (DEBUG) DoDebug("GetMeldshapingClass is "+IntToString(nClass));
	return nClass;
}

int GetMaxShapeSoulmeldCount(object oMeldshaper, int nClass)
{
	int nMax = StringToInt(Get2DACache(GetMeldshapingClassFile(nClass), "Soulmelds", GetIncarnumLevelForClass(nClass, oMeldshaper)-1));
	if (nClass == GetPrimaryIncarnumClass(oMeldshaper)) 
	{
		nMax += StringToInt(Get2DACache(GetMeldshapingClassFile(CLASS_TYPE_NECROCARNATE), "Soulmelds", GetLevelByClass(CLASS_TYPE_NECROCARNATE, oMeldshaper)));
    	int i;
    	for(i = FEAT_BONUS_SOULMELD_1; i <= FEAT_BONUS_SOULMELD_10; i++)
    	    if(GetHasFeat(i, oMeldshaper)) nMax++;
    }
    
	int nCon = GetAbilityScore(oMeldshaper, ABILITY_CONSTITUTION, TRUE)-10;
	if (GetHasFeat(FEAT_UNDEAD_MELDSHAPER, oMeldshaper)) nCon = GetAbilityScore(oMeldshaper, ABILITY_WISDOM, TRUE)-10;
	//Limited to Con score - 10 or class limit, whichever is less
	nMax = PRCMin(nMax, nCon);	
	
    //if (DEBUG) DoDebug("GetMaxShapeSoulmeldCount is "+IntToString(nMax));
    return nMax;
}

int GetTotalSoulmeldCount(object oMeldshaper)
{
	int nMax = GetMaxShapeSoulmeldCount(oMeldshaper, CLASS_TYPE_INCARNATE);	
		nMax += GetMaxShapeSoulmeldCount(oMeldshaper, CLASS_TYPE_SOULBORN);
		nMax += GetMaxShapeSoulmeldCount(oMeldshaper, CLASS_TYPE_TOTEMIST);
		nMax += GetMaxShapeSoulmeldCount(oMeldshaper, CLASS_TYPE_SPINEMELD_WARRIOR);
		nMax += GetMaxShapeSoulmeldCount(oMeldshaper, CLASS_TYPE_NECROCARNATE);
	
    //if (DEBUG) DoDebug("GetTotalSoulmeldCount is "+IntToString(nMax));
    return nMax;
}

int GetMaxBindCount(object oMeldshaper, int nClass)
{
	int nMax = StringToInt(Get2DACache(GetMeldshapingClassFile(nClass), "ChakraBinds", GetIncarnumLevelForClass(nClass, oMeldshaper)-1));
	if (nClass == GetPrimaryIncarnumClass(oMeldshaper)) 
	{
		nMax += StringToInt(Get2DACache(GetMeldshapingClassFile(CLASS_TYPE_NECROCARNATE), "ChakraBinds", GetLevelByClass(CLASS_TYPE_NECROCARNATE, oMeldshaper)));
	   	int i;
	   	for(i = FEAT_EXTRA_CHAKRA_BIND_1; i <= FEAT_EXTRA_CHAKRA_BIND_10; i++)
   	    	if(GetHasFeat(i, oMeldshaper)) nMax += 1;
   	}    
    //if (DEBUG) DoDebug("GetMaxBindCount is "+IntToString(nMax));
    return nMax;
}

void ShapeSoulmeld(object oMeldshaper, int nMeld)
{
	PRCRemoveSpellEffects(nMeld, oMeldshaper, oMeldshaper);
	GZPRCRemoveSpellEffects(nMeld, oMeldshaper, FALSE);
	ActionCastSpellOnSelf(nMeld);
	//if (DEBUG) DoDebug("Shaping Soulmeld "+IntToString(nMeld)+" on "+GetName(oMeldshaper));
}		

void MarkMeldShaped(object oMeldshaper, int nMeld, int nClass)
{
	//if (DEBUG) DoDebug("MarkMeldShaped nMeld is "+IntToString(nMeld));
	int nCont = TRUE;
	int nTest, i;
	while (nCont)
	{
		nTest = GetLocalInt(oMeldshaper, "ShapedMeld"+IntToString(nClass)+IntToString(i));
		//if (DEBUG) DoDebug("MarkMeldShaped nTest is "+IntToString(nTest));
		if (!nTest) // If it's blank
		{
			SetLocalInt(oMeldshaper, "ShapedMeld"+IntToString(nClass)+IntToString(i), nMeld);
			//if (DEBUG) DoDebug("MarkMeldShaped SetLocal");
			nCont = FALSE; // Break the loop
		}
		else
			i++; // Increment the counter to check
	}
}

void ClearMeldShapes(object oMeldshaper)
{
	object oSkin = GetPCSkin(oMeldshaper);
	ScrubPCSkin(oMeldshaper, oSkin);
	int i;
    for (i = 0; i <= 22; i++)
    {
		DeleteLocalInt(oMeldshaper, "ShapedMeld"+IntToString(CLASS_TYPE_INCARNATE)+IntToString(i));
		DeleteLocalInt(oMeldshaper, "ShapedMeld"+IntToString(CLASS_TYPE_SOULBORN)+IntToString(i));
		DeleteLocalInt(oMeldshaper, "ShapedMeld"+IntToString(CLASS_TYPE_TOTEMIST)+IntToString(i));
		DeleteLocalInt(oMeldshaper, "ShapedMeld"+IntToString(CLASS_TYPE_SPINEMELD_WARRIOR)+IntToString(i));
		DeleteLocalInt(oMeldshaper, "UsedMeld"+IntToString(CLASS_TYPE_SPINEMELD_WARRIOR)+IntToString(i));
		DeleteLocalInt(oMeldshaper, "UsedMeld"+IntToString(CLASS_TYPE_INCARNATE)+IntToString(i));
		DeleteLocalInt(oMeldshaper, "UsedMeld"+IntToString(CLASS_TYPE_SOULBORN)+IntToString(i));
		DeleteLocalInt(oMeldshaper, "UsedMeld"+IntToString(CLASS_TYPE_TOTEMIST)+IntToString(i));
		DeleteLocalInt(oMeldshaper, "BoundMeld"+IntToString(i));
		int nTest = GetLocalInt(oMeldshaper, "SpellInvestCheck"+IntToString(i));
    	if (nTest)
    		DeleteLocalInt(oMeldshaper, "SpellEssentia"+IntToString(nTest));
    	DeleteLocalInt(oMeldshaper, "SpellInvestCheck"+IntToString(i));	
    	DeleteLocalInt(oMeldshaper, "ExpandedSoulmeld"+IntToString(i));	
    	DeleteLocalInt(oMeldshaper, "UsedBladeMeld"+IntToString(i));	
    }
    for (i = 18700; i < 18799; i++)
    {
		DeleteLocalInt(oMeldshaper, "MeldEssentia"+IntToString(i));
    } 
    for (i = 8869; i < 8889; i++)
    {
		DeleteLocalInt(oMeldshaper, "FeatEssentia"+IntToString(i));
    }    
    DeleteLocalInt(oMeldshaper, "ArcaneFocusBound");
    if (GetLocalInt(oMeldshaper, "DiademPurelight")) 
    {
    	SetLocalInt(oMeldshaper, "PRCInLight", GetLocalInt(oMeldshaper, "PRCInLight")-1); 
    	DeleteLocalInt(oMeldshaper, "DiademPurelight");     
    }
    
    if (GetLocalInt(oMeldshaper, "PlanarChasubleLimit") > 7) 
    	DeleteLocalInt(oMeldshaper, "PlanarChasubleLimit");
    else
    	SetLocalInt(oMeldshaper, "PlanarChasubleLimit", GetLocalInt(oMeldshaper, "PlanarChasubleLimit")+1);
    
    DeleteLocalInt(oMeldshaper, "GorgonMaskLimit");
    DeleteLocalInt(oMeldshaper, "IncarnateAvatarSpeed");
    DeleteLocalInt(oMeldshaper, "LamiaBeltSpeed");
    DeleteLocalInt(oMeldshaper, "LifebondVestmentsTimer");
    DeleteLocalInt(oMeldshaper, "MidnightAugPower");
    DeleteLocalInt(oMeldshaper, "MeldEssentia18973"); // MELD_DUSKLING_SPEED
    DeleteLocalInt(oMeldshaper, "MeldEssentia18691"); // MELD_SPINE_ENHANCEMENT
    DeleteLocalInt(oMeldshaper, "MeldEssentia18687"); // MELD_IRONSOUL_SHIELD
    DeleteLocalInt(oMeldshaper, "MeldEssentia18685"); // MELD_IRONSOUL_ARMOR
    DeleteLocalInt(oMeldshaper, "MeldEssentia18683"); // MELD_IRONSOUL_WEAPON
    DeleteLocalInt(oMeldshaper, "MeldEssentia18681"); // MELD_UMBRAL_STEP  
    DeleteLocalInt(oMeldshaper, "MeldEssentia18679"); // MELD_UMBRAL_SHADOW
    DeleteLocalInt(oMeldshaper, "MeldEssentia18677"); // MELD_UMBRAL_SIGHT 
    DeleteLocalInt(oMeldshaper, "MeldEssentia18675"); // MELD_UMBRAL_SOUL  
    DeleteLocalInt(oMeldshaper, "MeldEssentia18673"); // MELD_UMBRAL_KISS  
    DeleteLocalInt(oMeldshaper, "MeldEssentia18670"); // MELD_INCANDESCENT_STRIKE
    DeleteLocalInt(oMeldshaper, "MeldEssentia18668"); // MELD_INCANDESCENT_HEAL       
    DeleteLocalInt(oMeldshaper, "MeldEssentia18666"); // MELD_INCANDESCENT_COUNTENANCE
    DeleteLocalInt(oMeldshaper, "MeldEssentia18663"); // MELD_INCANDESCENT_RAY        
    DeleteLocalInt(oMeldshaper, "MeldEssentia18659"); // MELD_INCANDESCENT_AURA    
    DeleteLocalInt(oMeldshaper, "MeldEssentia18634"); // MELD_WITCH_MELDSHIELD
    DeleteLocalInt(oMeldshaper, "MeldEssentia18636"); // MELD_WITCH_DISPEL    
    DeleteLocalInt(oMeldshaper, "MeldEssentia18638"); // MELD_WITCH_SHACKLES  
    DeleteLocalInt(oMeldshaper, "MeldEssentia18640"); // MELD_WITCH_ABROGATION
    DeleteLocalInt(oMeldshaper, "MeldEssentia18642"); // MELD_WITCH_SPIRITFLAY
    DeleteLocalInt(oMeldshaper, "MeldEssentia18644"); // MELD_WITCH_INTEGUMENT 
    DeleteLocalInt(oMeldshaper, "NecrocarnumCircletPen");
    DeleteLocalInt(oMeldshaper, "AstralVambraces");
    DeleteLocalInt(oMeldshaper, "TemporaryEssentia");
    DestroyObject(GetItemPossessedBy(oMeldshaper, "moi_incarnatewpn")); // Remove any weapons created by Incarnate Weapon
    
    // Clean up any the natural weapons that are lying around
    ClearNaturalWeapons(oMeldshaper);    
    // Nuke the creature weapons. If the normal form is supposed to have natural weapons, they'll get re-constructed
    if(GetIsObjectValid(GetItemInSlot(INVENTORY_SLOT_CWEAPON_R, oMeldshaper))) MyDestroyObject(GetItemInSlot(INVENTORY_SLOT_CWEAPON_R, oMeldshaper));
    if(GetIsObjectValid(GetItemInSlot(INVENTORY_SLOT_CWEAPON_L, oMeldshaper))) MyDestroyObject(GetItemInSlot(INVENTORY_SLOT_CWEAPON_L, oMeldshaper));
    if(GetIsObjectValid(GetItemInSlot(INVENTORY_SLOT_CWEAPON_B, oMeldshaper))) MyDestroyObject(GetItemInSlot(INVENTORY_SLOT_CWEAPON_B, oMeldshaper));    
    
    if (GetLocalInt(oMeldshaper, "ClearEventTotem")) ClearEventScriptList(oMeldshaper, EVENT_ITEM_ONHIT, TRUE, TRUE);   
} 

int GetShapedMeldsCount(object oMeldshaper)
{
	int i, nCount, nTest;
    for (i = 0; i <= 20; i++)
    {
		nTest = GetLocalInt(oMeldshaper, "ShapedMeld"+IntToString(CLASS_TYPE_INCARNATE)+IntToString(i));
		if (nTest) // If it's not blank
			nCount++;	
		nTest = GetLocalInt(oMeldshaper, "ShapedMeld"+IntToString(CLASS_TYPE_SOULBORN)+IntToString(i));
		if (nTest) // If it's not blank
			nCount++;	
		nTest = GetLocalInt(oMeldshaper, "ShapedMeld"+IntToString(CLASS_TYPE_TOTEMIST)+IntToString(i));
		if (nTest) // If it's not blank
			nCount++;	
		nTest = GetLocalInt(oMeldshaper, "ShapedMeld"+IntToString(CLASS_TYPE_SPINEMELD_WARRIOR)+IntToString(i));
		if (nTest) // If it's not blank
			nCount++;				
    }
    //if (DEBUG) DoDebug("GetTotalShapedMelds is "+IntToString(nCount));
    return nCount;
}

int GetTotalShapedMelds(object oMeldshaper, int nClass)
{
	int i, nCount, nTest;
    for (i = 0; i <= 20; i++)
    {
		nTest = GetLocalInt(oMeldshaper, "ShapedMeld"+IntToString(nClass)+IntToString(i));
		if (nTest) // If it's not blank
			nCount++;	
    }
    //if (DEBUG) DoDebug("GetTotalShapedMelds is "+IntToString(nCount));
    return nCount;
}

int CheckSplitChakra(object oMeldshaper, int nSlot)
{
	if (nSlot == INVENTORY_SLOT_HEAD  && GetHasFeat(FEAT_SPLIT_CHAKRA_CROWN    , oMeldshaper)) return TRUE;	
	if (nSlot == INVENTORY_SLOT_BOOTS && GetHasFeat(FEAT_SPLIT_CHAKRA_FEET     , oMeldshaper)) return TRUE;
	if (nSlot == INVENTORY_SLOT_ARMS  && GetHasFeat(FEAT_SPLIT_CHAKRA_HANDS    , oMeldshaper)) return TRUE;
	if (nSlot == INVENTORY_SLOT_ARMS  && GetHasFeat(FEAT_SPLIT_CHAKRA_ARMS     , oMeldshaper)) return TRUE;
	if (nSlot == INVENTORY_SLOT_HEAD  && GetHasFeat(FEAT_SPLIT_CHAKRA_BROW     , oMeldshaper)) return TRUE;
	if (nSlot == INVENTORY_SLOT_CLOAK && GetHasFeat(FEAT_SPLIT_CHAKRA_SHOULDERS, oMeldshaper)) return TRUE;
	if (nSlot == INVENTORY_SLOT_NECK  && GetHasFeat(FEAT_SPLIT_CHAKRA_THROAT   , oMeldshaper)) return TRUE;
	if (nSlot == INVENTORY_SLOT_BELT  && GetHasFeat(FEAT_SPLIT_CHAKRA_WAIST    , oMeldshaper)) return TRUE;
	if (nSlot == INVENTORY_SLOT_CHEST && GetHasFeat(FEAT_SPLIT_CHAKRA_HEART    , oMeldshaper)) return TRUE;	
	if (nSlot == INVENTORY_SLOT_CHEST && GetHasFeat(FEAT_SPLIT_CHAKRA_SOUL     , oMeldshaper)) return TRUE;
	
	return FALSE;	
}

void BindMeldToChakra(object oMeldshaper, int nMeld, int nChakra, int nClass)
{
	// Make sure it's not in use already, and that you have any binds to make
	if (!GetIsChakraBound(oMeldshaper, nChakra) && GetMaxBindCount(oMeldshaper, nClass))
	{
		//FloatingTextStringOnCreature("BindMeldToChakra: nMeld "+IntToString(nMeld)+" nChakra "+IntToString(nChakra), oMeldshaper);
		SetLocalInt(oMeldshaper, "BoundMeld"+IntToString(nChakra), nMeld);
		ShapeSoulmeld(oMeldshaper, nMeld);
		int nSlot = ChakraToSlot(DoubleChakraToChakra(nChakra)); // Can't have an item in a bound slot, unless Split Chakra
		if (!CheckSplitChakra(oMeldshaper, nSlot)) ForceUnequip(oMeldshaper, GetItemInSlot(nSlot, oMeldshaper), nSlot);
	}
}

int GetTotalBoundMelds(object oMeldshaper)
{
	int i, nCount, nTest;
    for (i = 0; i <= 22; i++)
    {
		nTest = GetLocalInt(oMeldshaper, "BoundMeld"+IntToString(i));
		if (nTest) // If it's not blank
			nCount++;	
    }
    //if (DEBUG) DoDebug("GetTotalBoundMelds is "+IntToString(nCount));
    return nCount;
}

int GetIsChakraUsed(object oMeldshaper, int nChakra, int nClass)
{
	int nTest = GetLocalInt(oMeldshaper, "UsedMeld"+IntToString(nClass)+IntToString(nChakra));
	
    //if (DEBUG) DoDebug("GetIsChakraUsed is "+IntToString(nTest));
    return nTest;
}

void SetChakraUsed(object oMeldshaper, int nMeld, int nChakra, int nClass)
{
	// This isn't the same as binding, but can only have one soulmeld in each chakra
	// Each class has its own limit on this, as per p20 of MoI
	if (!GetIsChakraUsed(oMeldshaper, nChakra, nClass))
	{
		SetLocalInt(oMeldshaper, "UsedMeld"+IntToString(nClass)+IntToString(nChakra), nMeld);
	}
}

int ChakraToSlot(int nChakra)
{
	if (nChakra == CHAKRA_CROWN    ) return INVENTORY_SLOT_HEAD;	
	if (nChakra == CHAKRA_FEET     ) return INVENTORY_SLOT_BOOTS;
	if (nChakra == CHAKRA_HANDS    ) return INVENTORY_SLOT_ARMS;
	if (nChakra == CHAKRA_ARMS     ) return INVENTORY_SLOT_ARMS;
	if (nChakra == CHAKRA_BROW     ) return INVENTORY_SLOT_HEAD;
	if (nChakra == CHAKRA_SHOULDERS) return INVENTORY_SLOT_CLOAK;
	if (nChakra == CHAKRA_THROAT   ) return INVENTORY_SLOT_NECK;
	if (nChakra == CHAKRA_WAIST    ) return INVENTORY_SLOT_BELT;
	if (nChakra == CHAKRA_HEART    ) return INVENTORY_SLOT_CHEST;	
	if (nChakra == CHAKRA_SOUL     ) return INVENTORY_SLOT_CHEST;
	if (nChakra == CHAKRA_TOTEM    ) return -1; // no slot associated
	
	return -1;
}	

void ChakraBindUnequip(object oMeldshaper, object oItem)
{    
    int nTest = FALSE;
    if (GetItemInSlot(INVENTORY_SLOT_HEAD, oMeldshaper) == oItem && (GetIsChakraBound(oMeldshaper, CHAKRA_CROWN) || GetIsChakraBound(oMeldshaper, CHAKRA_BROW))) nTest = INVENTORY_SLOT_HEAD + 1;
    else if (GetItemInSlot(INVENTORY_SLOT_BOOTS, oMeldshaper) == oItem && GetIsChakraBound(oMeldshaper, CHAKRA_FEET)) nTest = INVENTORY_SLOT_BOOTS + 1;
    else if (GetItemInSlot(INVENTORY_SLOT_ARMS, oMeldshaper) == oItem && (GetIsChakraBound(oMeldshaper, CHAKRA_ARMS) || GetIsChakraBound(oMeldshaper, CHAKRA_HANDS))) nTest = INVENTORY_SLOT_ARMS + 1;
    else if (GetItemInSlot(INVENTORY_SLOT_CLOAK, oMeldshaper) == oItem && GetIsChakraBound(oMeldshaper, CHAKRA_SHOULDERS)) nTest = INVENTORY_SLOT_CLOAK + 1;
    else if (GetItemInSlot(INVENTORY_SLOT_NECK, oMeldshaper) == oItem && GetIsChakraBound(oMeldshaper, CHAKRA_THROAT)) nTest = INVENTORY_SLOT_NECK + 1;
    else if (GetItemInSlot(INVENTORY_SLOT_BELT, oMeldshaper) == oItem && GetIsChakraBound(oMeldshaper, CHAKRA_WAIST)) nTest = INVENTORY_SLOT_BELT + 1;
    else if (GetItemInSlot(INVENTORY_SLOT_CHEST, oMeldshaper) == oItem && (GetIsChakraBound(oMeldshaper, CHAKRA_SOUL) || GetIsChakraBound(oMeldshaper, CHAKRA_HEART))) nTest = INVENTORY_SLOT_CHEST + 1;
	//if (DEBUG) DoDebug("ChakraBindUnequip is "+IntToString(nTest-1));
	if (nTest && !CheckSplitChakra(oMeldshaper, nTest-1) && GetIsItemPropertyValid(GetFirstItemProperty(oItem)) && oItem != GetItemInSlot(INVENTORY_SLOT_CWEAPON_B, oMeldshaper) && oItem != GetItemInSlot(INVENTORY_SLOT_CWEAPON_L, oMeldshaper) &&
		   oItem != GetItemInSlot(INVENTORY_SLOT_CWEAPON_R, oMeldshaper) && oItem != GetItemInSlot(INVENTORY_SLOT_CARMOUR, oMeldshaper)) // If it's bound you can't equip in that slot
	{
		nTest = nTest - 1;
		ForceUnequip(oMeldshaper, GetItemInSlot(nTest, oMeldshaper), nTest);
		FloatingTextStringOnCreature("You cannot equip a magical item when you have bound a meld to the same chakra!", oMeldshaper, FALSE);
	}
}

string ChakraToString(int nChakra)
{
	string sReturn = "";
	if (nChakra == CHAKRA_CROWN     || nChakra == CHAKRA_DOUBLE_CROWN    ) sReturn = "Crown";	
	if (nChakra == CHAKRA_FEET      || nChakra == CHAKRA_DOUBLE_FEET     ) sReturn = "Feet";
	if (nChakra == CHAKRA_HANDS     || nChakra == CHAKRA_DOUBLE_HANDS    ) sReturn = "Hands";
	if (nChakra == CHAKRA_ARMS      || nChakra == CHAKRA_DOUBLE_ARMS     ) sReturn = "Arms";
	if (nChakra == CHAKRA_BROW      || nChakra == CHAKRA_DOUBLE_BROW     ) sReturn = "Brow";
	if (nChakra == CHAKRA_SHOULDERS || nChakra == CHAKRA_DOUBLE_SHOULDERS) sReturn = "Shoulders";
	if (nChakra == CHAKRA_THROAT    || nChakra == CHAKRA_DOUBLE_THROAT   ) sReturn = "Throat";
	if (nChakra == CHAKRA_WAIST     || nChakra == CHAKRA_DOUBLE_WAIST    ) sReturn = "Waist";
	if (nChakra == CHAKRA_HEART     || nChakra == CHAKRA_DOUBLE_HEART    ) sReturn = "Heart";	
	if (nChakra == CHAKRA_SOUL      || nChakra == CHAKRA_DOUBLE_SOUL     ) sReturn = "Soul";
	if (nChakra == CHAKRA_TOTEM     || nChakra == CHAKRA_DOUBLE_TOTEM    ) sReturn = "Totem";
	
	//if (DEBUG) DoDebug("ChakraToString is "+IntToString(nChakra)+", Return is "+sReturn);
	return sReturn;
}

int GetCanBindChakra(object oMeldshaper, int nChakra)
{
	if (nChakra == CHAKRA_CROWN &&
	   (GetLevelByClass(CLASS_TYPE_INCARNATE, oMeldshaper) >= 2)) return TRUE;
	else if (nChakra == CHAKRA_FEET &&
	   (GetLevelByClass(CLASS_TYPE_INCARNATE, oMeldshaper) >= 4)) return TRUE;	
	else if (nChakra == CHAKRA_HANDS &&
	   (GetLevelByClass(CLASS_TYPE_INCARNATE, oMeldshaper) >= 4)) return TRUE;
	else if (nChakra == CHAKRA_ARMS &&
	   (GetLevelByClass(CLASS_TYPE_INCARNATE, oMeldshaper) >= 9)) return TRUE;	
	else if (nChakra == CHAKRA_BROW &&
	   (GetLevelByClass(CLASS_TYPE_INCARNATE, oMeldshaper) >= 9)) return TRUE;	
	else if (nChakra == CHAKRA_SHOULDERS &&
	   (GetLevelByClass(CLASS_TYPE_INCARNATE, oMeldshaper) >= 9)) return TRUE;	
	else if (nChakra == CHAKRA_THROAT &&
	   (GetLevelByClass(CLASS_TYPE_INCARNATE, oMeldshaper) >= 14)) return TRUE;	
	else if (nChakra == CHAKRA_WAIST &&
	   (GetLevelByClass(CLASS_TYPE_INCARNATE, oMeldshaper) >= 14)) return TRUE;	
	else if (nChakra == CHAKRA_HEART &&
	   (GetLevelByClass(CLASS_TYPE_INCARNATE, oMeldshaper) >= 16)) return TRUE;	
	else if (nChakra == CHAKRA_SOUL &&
	   (GetLevelByClass(CLASS_TYPE_INCARNATE, oMeldshaper) >= 19)) return TRUE;	
	   
	if (nChakra == CHAKRA_CROWN &&
	   (GetLevelByClass(CLASS_TYPE_SOULBORN, oMeldshaper) >= 8)) return TRUE;
	else if (nChakra == CHAKRA_FEET &&
	   (GetLevelByClass(CLASS_TYPE_SOULBORN, oMeldshaper) >= 8)) return TRUE;	
	else if (nChakra == CHAKRA_HANDS &&
	   (GetLevelByClass(CLASS_TYPE_SOULBORN, oMeldshaper) >= 8)) return TRUE;
	else if (nChakra == CHAKRA_ARMS &&
	   (GetLevelByClass(CLASS_TYPE_SOULBORN, oMeldshaper) >= 14)) return TRUE;	
	else if (nChakra == CHAKRA_BROW &&
	   (GetLevelByClass(CLASS_TYPE_SOULBORN, oMeldshaper) >= 14)) return TRUE;	
	else if (nChakra == CHAKRA_SHOULDERS &&
	   (GetLevelByClass(CLASS_TYPE_SOULBORN, oMeldshaper) >= 14)) return TRUE;	
	else if (nChakra == CHAKRA_THROAT &&
	   (GetLevelByClass(CLASS_TYPE_SOULBORN, oMeldshaper) >= 18)) return TRUE;	
	else if (nChakra == CHAKRA_WAIST &&
	   (GetLevelByClass(CLASS_TYPE_SOULBORN, oMeldshaper) >= 18)) return TRUE;	 
	   
	if (nChakra == CHAKRA_CROWN &&
	   (GetLevelByClass(CLASS_TYPE_TOTEMIST, oMeldshaper) >= 5)) return TRUE;
	else if (nChakra == CHAKRA_FEET &&
	   (GetLevelByClass(CLASS_TYPE_TOTEMIST, oMeldshaper) >= 5)) return TRUE;	
	else if (nChakra == CHAKRA_HANDS &&
	   (GetLevelByClass(CLASS_TYPE_TOTEMIST, oMeldshaper) >= 5)) return TRUE;
	else if (nChakra == CHAKRA_ARMS &&
	   (GetLevelByClass(CLASS_TYPE_TOTEMIST, oMeldshaper) >= 9)) return TRUE;	
	else if (nChakra == CHAKRA_BROW &&
	   (GetLevelByClass(CLASS_TYPE_TOTEMIST, oMeldshaper) >= 9)) return TRUE;	
	else if (nChakra == CHAKRA_SHOULDERS &&
	   (GetLevelByClass(CLASS_TYPE_TOTEMIST, oMeldshaper) >= 9)) return TRUE;	
	else if (nChakra == CHAKRA_THROAT &&
	   (GetLevelByClass(CLASS_TYPE_TOTEMIST, oMeldshaper) >= 14)) return TRUE;	
	else if (nChakra == CHAKRA_WAIST &&
	   (GetLevelByClass(CLASS_TYPE_TOTEMIST, oMeldshaper) >= 14)) return TRUE;	
	else if (nChakra == CHAKRA_HEART &&
	   (GetLevelByClass(CLASS_TYPE_TOTEMIST, oMeldshaper) >= 17)) return TRUE;	
	else if (nChakra == CHAKRA_TOTEM &&
	   (GetLevelByClass(CLASS_TYPE_TOTEMIST, oMeldshaper) >= 2)) return TRUE;	
	   
	if (nChakra == CHAKRA_ARMS &&
	   (GetLevelByClass(CLASS_TYPE_SPINEMELD_WARRIOR, oMeldshaper) >= 7)) return TRUE;	
	   
	if (nChakra == CHAKRA_CROWN &&
	   (GetLevelByClass(CLASS_TYPE_SOULCASTER, oMeldshaper) >= 3)) return TRUE;
	else if (nChakra == CHAKRA_FEET &&
	   (GetLevelByClass(CLASS_TYPE_SOULCASTER, oMeldshaper) >= 3)) return TRUE;	
	else if (nChakra == CHAKRA_HANDS &&
	   (GetLevelByClass(CLASS_TYPE_SOULCASTER, oMeldshaper) >= 3)) return TRUE;	   
	else if (nChakra == CHAKRA_ARMS &&
	   (GetLevelByClass(CLASS_TYPE_SOULCASTER, oMeldshaper) >= 8)) return TRUE;	
	else if (nChakra == CHAKRA_BROW &&
	   (GetLevelByClass(CLASS_TYPE_SOULCASTER, oMeldshaper) >= 8)) return TRUE;	
	else if (nChakra == CHAKRA_SHOULDERS &&
	   (GetLevelByClass(CLASS_TYPE_SOULCASTER, oMeldshaper) >= 8)) return TRUE;	

	if (nChakra == CHAKRA_ARMS &&
	   (GetLevelByClass(CLASS_TYPE_IRONSOUL_FORGEMASTER, oMeldshaper) >= 4)) return TRUE;
	else if (nChakra == CHAKRA_WAIST &&
	   (GetLevelByClass(CLASS_TYPE_IRONSOUL_FORGEMASTER, oMeldshaper) >= 6)) return TRUE;	
	else if (nChakra == CHAKRA_SHOULDERS &&
	   (GetLevelByClass(CLASS_TYPE_IRONSOUL_FORGEMASTER, oMeldshaper) >= 8)) return TRUE;	   
	else if (nChakra == CHAKRA_HEART &&
	   (GetLevelByClass(CLASS_TYPE_IRONSOUL_FORGEMASTER, oMeldshaper) >= 10)) return TRUE;	
	   
	if (nChakra == CHAKRA_CROWN &&
		(GetLevelByClass(CLASS_TYPE_TOTEM_RAGER, oMeldshaper) >=4)) return TRUE;
	else if (nChakra == CHAKRA_FEET &&
		(GetLevelByClass(CLASS_TYPE_TOTEM_RAGER, oMeldshaper) >=4)) return TRUE;   
	else if (nChakra == CHAKRA_HANDS &&
		(GetLevelByClass(CLASS_TYPE_TOTEM_RAGER, oMeldshaper) >=4)) return TRUE;	
	else if (nChakra == CHAKRA_ARMS &&
		(GetLevelByClass(CLASS_TYPE_TOTEM_RAGER, oMeldshaper) >=9)) return TRUE;
	else if (nChakra == CHAKRA_BROW &&
		(GetLevelByClass(CLASS_TYPE_TOTEM_RAGER, oMeldshaper) >=9)) return TRUE;
	else if (nChakra == CHAKRA_SHOULDERS &&
		(GetLevelByClass(CLASS_TYPE_TOTEM_RAGER, oMeldshaper) >=9)) return TRUE;
		
	if (nChakra == CHAKRA_ARMS &&
	   (GetLevelByClass(CLASS_TYPE_NECROCARNATE, oMeldshaper) >= 3)) return TRUE;	
	else if (nChakra == CHAKRA_BROW &&
	   (GetLevelByClass(CLASS_TYPE_NECROCARNATE, oMeldshaper) >= 3)) return TRUE;	
	else if (nChakra == CHAKRA_SHOULDERS &&
	   (GetLevelByClass(CLASS_TYPE_NECROCARNATE, oMeldshaper) >= 3)) return TRUE;	
	else if (nChakra == CHAKRA_THROAT &&
	   (GetLevelByClass(CLASS_TYPE_NECROCARNATE, oMeldshaper) >= 8)) return TRUE;	
	else if (nChakra == CHAKRA_WAIST &&
	   (GetLevelByClass(CLASS_TYPE_NECROCARNATE, oMeldshaper) >= 8)) return TRUE;	
	else if (nChakra == CHAKRA_HEART &&
	   (GetLevelByClass(CLASS_TYPE_NECROCARNATE, oMeldshaper) >= 11)) return TRUE;	
	else if (nChakra == CHAKRA_SOUL &&
	   (GetLevelByClass(CLASS_TYPE_NECROCARNATE, oMeldshaper) >= 13)) return TRUE;	
	   
	if (nChakra == CHAKRA_CROWN && GetHasFeat(FEAT_OPEN_LEAST_CHAKRA_CROWN, oMeldshaper)) return TRUE;
	else if (nChakra == CHAKRA_FEET      && GetHasFeat(FEAT_OPEN_LEAST_CHAKRA_FEET      , oMeldshaper)) return TRUE;
	else if (nChakra == CHAKRA_HANDS     && GetHasFeat(FEAT_OPEN_LEAST_CHAKRA_HANDS     , oMeldshaper)) return TRUE;
	else if (nChakra == CHAKRA_ARMS      && GetHasFeat(FEAT_OPEN_LESSER_CHAKRA_ARMS     , oMeldshaper)) return TRUE;
	else if (nChakra == CHAKRA_BROW      && GetHasFeat(FEAT_OPEN_LESSER_CHAKRA_BROW     , oMeldshaper)) return TRUE;
	else if (nChakra == CHAKRA_SHOULDERS && GetHasFeat(FEAT_OPEN_LESSER_CHAKRA_SHOULDERS, oMeldshaper)) return TRUE;
	else if (nChakra == CHAKRA_THROAT    && GetHasFeat(FEAT_OPEN_GREATER_CHAKRA_THROAT  , oMeldshaper)) return TRUE;
	else if (nChakra == CHAKRA_WAIST     && GetHasFeat(FEAT_OPEN_GREATER_CHAKRA_WAIST   , oMeldshaper)) return TRUE; 
	else if (nChakra == CHAKRA_HEART     && GetHasFeat(FEAT_OPEN_HEART_CHAKRA           , oMeldshaper)) return TRUE;
	else if (nChakra == CHAKRA_SOUL      && GetHasFeat(FEAT_OPEN_SOUL_CHAKRA            , oMeldshaper)) return TRUE;
	
	if (nChakra == CHAKRA_DOUBLE_CROWN && GetHasFeat(FEAT_DOUBLE_CHAKRA_CROWN, oMeldshaper)) return TRUE;
	else if (nChakra == CHAKRA_DOUBLE_FEET      && GetHasFeat(FEAT_DOUBLE_CHAKRA_FEET     , oMeldshaper)) return TRUE;
	else if (nChakra == CHAKRA_DOUBLE_HANDS     && GetHasFeat(FEAT_DOUBLE_CHAKRA_HANDS    , oMeldshaper)) return TRUE;
	else if (nChakra == CHAKRA_DOUBLE_ARMS      && GetHasFeat(FEAT_DOUBLE_CHAKRA_ARMS     , oMeldshaper)) return TRUE;
	else if (nChakra == CHAKRA_DOUBLE_BROW      && GetHasFeat(FEAT_DOUBLE_CHAKRA_BROW     , oMeldshaper)) return TRUE;
	else if (nChakra == CHAKRA_DOUBLE_SHOULDERS && GetHasFeat(FEAT_DOUBLE_CHAKRA_SHOULDERS, oMeldshaper)) return TRUE;
	else if (nChakra == CHAKRA_DOUBLE_THROAT    && GetHasFeat(FEAT_DOUBLE_CHAKRA_THROAT   , oMeldshaper)) return TRUE;
	else if (nChakra == CHAKRA_DOUBLE_WAIST     && GetHasFeat(FEAT_DOUBLE_CHAKRA_WAIST    , oMeldshaper)) return TRUE;
	else if (nChakra == CHAKRA_DOUBLE_HEART     && GetHasFeat(FEAT_DOUBLE_CHAKRA_HEART    , oMeldshaper)) return TRUE;
	else if (nChakra == CHAKRA_DOUBLE_SOUL      && GetHasFeat(FEAT_DOUBLE_CHAKRA_SOUL     , oMeldshaper)) return TRUE;	
	else if (nChakra == CHAKRA_DOUBLE_TOTEM     && GetHasFeat(FEAT_DOUBLE_CHAKRA_TOTEM    , oMeldshaper)) return TRUE;
	       
	return FALSE;   
}

int GetMaxEssentiaCount(object oMeldshaper, int nClass)
{
	int nMax = StringToInt(Get2DACache(GetMeldshapingClassFile(nClass), "Essentia", GetIncarnumLevelForClass(nClass, oMeldshaper)-1));
    //if (DEBUG) DoDebug("GetMaxEssentiaCount is "+IntToString(nMax));
    return nMax;
}

void SpawnTempEssentiaChecker(object oMeldshaper)
{
	int nCur = GetTemporaryEssentia(oMeldshaper);
	int nPrv = GetLocalInt(oMeldshaper, "TempEssTest");
	int nRed = nPrv - nCur;
	// If we've lost some
	if (nPrv > nCur)
	{
		int i, nCount, nTest;
    	for (i = 18700; i < 18799; i++)
    	{
			nTest = GetLocalInt(oMeldshaper, "TempEssentiaAmount"+IntToString(i));
			if (nTest) // If it's not blank
			{
				//if (DEBUG) DoDebug("Found "+IntToString(nTest)+" Temp Essentia in Meld "+IntToString(i));
				// There's still some temp essentia left in the meld
				if (nTest > nRed)
				{
					int nChange = nTest-nRed;
					SetLocalInt(oMeldshaper, "TempEssentiaAmount"+IntToString(i), nChange);
					SetLocalInt(oMeldshaper, "MeldEssentia"+IntToString(i), GetEssentiaInvested(oMeldshaper, i)-nChange);
					ShapeSoulmeld(oMeldshaper, i);
					//if (DEBUG) DoDebug("Reducing Essentia in Meld "+IntToString(i)+" by "+IntToString(nChange));
				}
				else // Means the reduction is higher than the temp essentia ammount
				{
					// No more temp essentia here
					DeleteLocalInt(oMeldshaper, "TempEssentiaAmount"+IntToString(i));
					SetLocalInt(oMeldshaper, "MeldEssentia"+IntToString(i), GetEssentiaInvested(oMeldshaper, i)-nTest);
					ShapeSoulmeld(oMeldshaper, i);
					//if (DEBUG) DoDebug("Deleted Temp Essentia in Meld "+IntToString(i)+", total "+IntToString(nTest));
				}
				
				// Reduce the remaining amount of reduction by the amount we just used up
				nRed = nRed - nTest;
				//if (DEBUG) DoDebug("Remaining Temp Essentia to reduce "+IntToString(nRed));
				if (0 >= nRed) break; // End the loop if we're done
			}	
    	}	
	}
	// If we still have some left
	if (nCur > 0) 
	{
		SetLocalInt(oMeldshaper, "TempEssTest", nCur);
		DelayCommand(1.0, SpawnTempEssentiaChecker(oMeldshaper));
	}
	else 
		DeleteLocalInt(oMeldshaper, "TempEssTest");
}

void InvestEssentia(object oMeldshaper, int nMeld, int nEssentia)
{
	// Use up expanded soulmeld capacity
	if (nEssentia > 1000) 
	{
		nEssentia -= 1000;
		SetIsSoulmeldCapacityUsed(oMeldshaper, nMeld);
	}
	int nClass = GetMeldShapedClass(oMeldshaper, nMeld);
	// Special capacity of 1/2 class level
	if (nMeld == MELD_SPINE_ENHANCEMENT) nEssentia = PRCMin(nEssentia, (GetLevelByClass(CLASS_TYPE_SPINEMELD_WARRIOR, oMeldshaper)/2));
	else if (nEssentia > GetMaxEssentiaCapacity(oMeldshaper, nClass, nMeld)) nEssentia = GetMaxEssentiaCapacity(oMeldshaper, nClass, nMeld);
	// Can't invest more than you have
	if (nEssentia > GetTotalUsableEssentia(oMeldshaper)) nEssentia = GetTotalUsableEssentia(oMeldshaper);
	
	// All of this garbage to handle temporary essentia
	if (GetLocalInt(oMeldshaper, "InvestingTempEssentia"))
	{
		SetLocalInt(oMeldshaper, "TempEssentiaAmount"+IntToString(nMeld), nEssentia);
		SpawnTempEssentiaChecker(oMeldshaper);
		DeleteLocalInt(oMeldshaper, "InvestingTempEssentia");
	}
	
	FloatingTextStringOnCreature("Investing "+IntToString(nEssentia)+" essentia into "+GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nMeld))), oMeldshaper, FALSE);
	SetLocalInt(oMeldshaper, "MeldEssentia"+IntToString(nMeld), nEssentia);
	SetLocalInt(oMeldshaper, "EssentiaRound"+IntToString(nMeld), TRUE); // This is used by Melds that only trigger on the round that essentia is invested into it
	DelayCommand(6.0, DeleteLocalInt(oMeldshaper, "EssentiaRound"+IntToString(nMeld)));
}

int GetTotalEssentiaInvested(object oMeldshaper)
{
	int i, nCount, nTest;
    for (i = 18700; i < 18799; i++)
    {
		nTest = GetLocalInt(oMeldshaper, "MeldEssentia"+IntToString(i));
		if (nTest) // If it's not blank
			nCount += nTest;	
    }
    nCount += GetFeatLockedEssentia(oMeldshaper);
    nCount += GetLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_SPINE_ENHANCEMENT)); // MELD_SPINE_ENHANCEMENT
    nCount += GetLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_IRONSOUL_SHIELD)); // MELD_IRONSOUL_SHIELD
    nCount += GetLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_IRONSOUL_ARMOR)); // MELD_IRONSOUL_ARMOR
    nCount += GetLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_IRONSOUL_WEAPON)); // MELD_IRONSOUL_WEAPON
    nCount += GetLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_UMBRAL_STEP  )); // MELD_UMBRAL_STEP  
    nCount += GetLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_UMBRAL_SHADOW)); // MELD_UMBRAL_SHADOW
    nCount += GetLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_UMBRAL_SIGHT )); // MELD_UMBRAL_SIGHT 
    nCount += GetLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_UMBRAL_SOUL  )); // MELD_UMBRAL_SOUL  
    nCount += GetLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_UMBRAL_KISS  )); // MELD_UMBRAL_KISS  
    nCount += GetLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_DUSKLING_SPEED)); // MELD_DUSKLING_SPEED
    nCount += GetLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_INCANDESCENT_STRIKE)); // MELD_INCANDESCENT_STRIKE
    nCount += GetLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_INCANDESCENT_HEAL       )); // MELD_INCANDESCENT_HEAL       
    nCount += GetLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_INCANDESCENT_COUNTENANCE)); // MELD_INCANDESCENT_COUNTENANCE
    nCount += GetLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_INCANDESCENT_RAY        )); // MELD_INCANDESCENT_RAY        
    nCount += GetLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_INCANDESCENT_AURA       )); // MELD_INCANDESCENT_AURA       
    nCount += GetLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_WITCH_MELDSHIELD)); // MELD_WITCH_MELDSHIELD
    nCount += GetLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_WITCH_DISPEL    )); // MELD_WITCH_DISPEL    
    nCount += GetLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_WITCH_SHACKLES  )); // MELD_WITCH_SHACKLES  
    nCount += GetLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_WITCH_ABROGATION)); // MELD_WITCH_ABROGATION
    nCount += GetLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_WITCH_SPIRITFLAY)); // MELD_WITCH_SPIRITFLAY
    nCount += GetLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_WITCH_INTEGUMENT)); // MELD_WITCH_INTEGUMENT   
    //if (DEBUG) DoDebug("GetTotalEssentiaInvested is "+IntToString(nCount));
    return nCount;
}

int EssentiaIDToRealID(int nEssentiaID)
{
	int i, nReal, nTest;
    for (i = 1; i < 100; i++)
    {
		nTest = StringToInt(Get2DACache("soulmelds", "EssentiaID", i));
		if (nTest == nEssentiaID) // If it's been found
		{
			nReal = StringToInt(Get2DACache("soulmelds", "SpellID", i));	
			break;
		}	
    }
    
    if (nEssentiaID == 18690) nReal = MELD_SPINE_ENHANCEMENT;
    else if (nEssentiaID == 18686) nReal = MELD_IRONSOUL_SHIELD;
    else if (nEssentiaID == 18684) nReal = MELD_IRONSOUL_ARMOR;
    else if (nEssentiaID == 18682) nReal = MELD_IRONSOUL_WEAPON;
    else if (nEssentiaID == 18680) nReal = MELD_UMBRAL_STEP;
    else if (nEssentiaID == 18678) nReal = MELD_UMBRAL_SHADOW;
    else if (nEssentiaID == 18676) nReal = MELD_UMBRAL_SIGHT;
    else if (nEssentiaID == 18674) nReal = MELD_UMBRAL_SOUL;
    else if (nEssentiaID == 18672) nReal = MELD_UMBRAL_KISS;
    else if (nEssentiaID == 18669) nReal = MELD_INCANDESCENT_STRIKE;
    else if (nEssentiaID == 18667) nReal = MELD_INCANDESCENT_HEAL       ;
    else if (nEssentiaID == 18665) nReal = MELD_INCANDESCENT_COUNTENANCE;
    else if (nEssentiaID == 18662) nReal = MELD_INCANDESCENT_RAY        ;
    else if (nEssentiaID == 18661) nReal = MELD_INCANDESCENT_AURA       ;
    else if (nEssentiaID == 18633) nReal = MELD_WITCH_MELDSHIELD;
    else if (nEssentiaID == 18635) nReal = MELD_WITCH_DISPEL;    
    else if (nEssentiaID == 18637) nReal = MELD_WITCH_SHACKLES;
    else if (nEssentiaID == 18639) nReal = MELD_WITCH_ABROGATION;
    else if (nEssentiaID == 18641) nReal = MELD_WITCH_SPIRITFLAY;
    else if (nEssentiaID == 18643) nReal = MELD_WITCH_INTEGUMENT;    
    
    //if (DEBUG) DoDebug("EssentiaToRealID: nEssentiaID "+IntToString(nEssentiaID)+" nReal "+IntToString(nReal));
    return nReal; // Return the real spellID
}

void DrainEssentia(object oMeldshaper)
{
	//FloatingTextStringOnCreature("DrainEssentia", oMeldshaper);
	int i;
    for (i = 18700; i < 18799; i++)
    {
		DeleteLocalInt(oMeldshaper, "MeldEssentia"+IntToString(i));
    }  
    DeleteLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_DUSKLING_SPEED));
    DeleteLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_SPINE_ENHANCEMENT));
    DeleteLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_IRONSOUL_SHIELD));
    DeleteLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_IRONSOUL_ARMOR));
    DeleteLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_IRONSOUL_WEAPON));
    DeleteLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_UMBRAL_STEP  ));
    DeleteLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_UMBRAL_SHADOW));
    DeleteLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_UMBRAL_SIGHT ));
    DeleteLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_UMBRAL_SOUL  ));
    DeleteLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_UMBRAL_KISS  ));
    DeleteLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_INCANDESCENT_STRIKE));
    DeleteLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_INCANDESCENT_HEAL       ));
    DeleteLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_INCANDESCENT_COUNTENANCE));
    DeleteLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_INCANDESCENT_RAY        ));
    DeleteLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_INCANDESCENT_AURA       ));
    DeleteLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_WITCH_MELDSHIELD));
    DeleteLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_WITCH_DISPEL    ));
    DeleteLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_WITCH_SHACKLES  ));
    DeleteLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_WITCH_ABROGATION));
    DeleteLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_WITCH_SPIRITFLAY));
    DeleteLocalInt(oMeldshaper, "MeldEssentia"+IntToString(MELD_WITCH_INTEGUMENT));    
}

void WipeMelds(object oMeldshaper)
{
	//FloatingTextStringOnCreature("WipeMelds", oMeldshaper);
	int i;
    for (i = 18700; i < 18799; i++)
    {
		PRCRemoveSpellEffects(i, oMeldshaper, oMeldshaper);
		GZPRCRemoveSpellEffects(i, oMeldshaper, FALSE);
    }
    PRCRemoveSpellEffects(MELD_DUSKLING_SPEED, oMeldshaper, oMeldshaper);
    GZPRCRemoveSpellEffects(MELD_DUSKLING_SPEED, oMeldshaper, FALSE);
    PRCRemoveSpellEffects(MELD_SPINE_ENHANCEMENT, oMeldshaper, oMeldshaper);
    GZPRCRemoveSpellEffects(MELD_SPINE_ENHANCEMENT, oMeldshaper, FALSE);    
    PRCRemoveSpellEffects(MELD_IRONSOUL_SHIELD, oMeldshaper, oMeldshaper);
    GZPRCRemoveSpellEffects(MELD_IRONSOUL_SHIELD, oMeldshaper, FALSE);  
    PRCRemoveSpellEffects(MELD_IRONSOUL_ARMOR, oMeldshaper, oMeldshaper);
    GZPRCRemoveSpellEffects(MELD_IRONSOUL_ARMOR, oMeldshaper, FALSE);  
    PRCRemoveSpellEffects(MELD_IRONSOUL_WEAPON, oMeldshaper, oMeldshaper);
    GZPRCRemoveSpellEffects(MELD_IRONSOUL_WEAPON, oMeldshaper, FALSE);          
    PRCRemoveSpellEffects(MELD_UMBRAL_STEP, oMeldshaper, oMeldshaper);
    GZPRCRemoveSpellEffects(MELD_UMBRAL_STEP, oMeldshaper, FALSE);      
    PRCRemoveSpellEffects(MELD_UMBRAL_SHADOW, oMeldshaper, oMeldshaper);
    GZPRCRemoveSpellEffects(MELD_UMBRAL_SHADOW, oMeldshaper, FALSE);      
    PRCRemoveSpellEffects(MELD_UMBRAL_SIGHT, oMeldshaper, oMeldshaper);
    GZPRCRemoveSpellEffects(MELD_UMBRAL_SIGHT, oMeldshaper, FALSE);      
    PRCRemoveSpellEffects(MELD_UMBRAL_SOUL, oMeldshaper, oMeldshaper);
    GZPRCRemoveSpellEffects(MELD_UMBRAL_SOUL, oMeldshaper, FALSE);      
    PRCRemoveSpellEffects(MELD_UMBRAL_KISS, oMeldshaper, oMeldshaper);
    GZPRCRemoveSpellEffects(MELD_UMBRAL_KISS, oMeldshaper, FALSE);          
    PRCRemoveSpellEffects(MELD_INCANDESCENT_STRIKE, oMeldshaper, oMeldshaper);
    GZPRCRemoveSpellEffects(MELD_INCANDESCENT_STRIKE, oMeldshaper, FALSE); 
    PRCRemoveSpellEffects(MELD_WITCH_MELDSHIELD, oMeldshaper, oMeldshaper);
    GZPRCRemoveSpellEffects(MELD_WITCH_MELDSHIELD, oMeldshaper, FALSE);     
    for (i = 18647; i < 18657; i++)
    {
		PRCRemoveSpellEffects(i, oMeldshaper, oMeldshaper);
		GZPRCRemoveSpellEffects(i, oMeldshaper, FALSE);
    }    
}

void ReshapeMelds(object oMeldshaper)
{
	// Check each class and run the loop
	if (GetLevelByClass(CLASS_TYPE_INCARNATE, oMeldshaper))
	{
		int i, nTest;
    	for (i = 0; i <= 20; i++)
    	{
			nTest = GetLocalInt(oMeldshaper, "ShapedMeld"+IntToString(CLASS_TYPE_INCARNATE)+IntToString(i));
			if (nTest) // If it's not blank, recast it
			{
				//FloatingTextStringOnCreature("ReshapeMelds: CLASS_TYPE_INCARNATE nTest "+IntToString(nTest), oMeldshaper);
				ActionCastSpellOnSelf(nTest);
			}	
    	}
    }
	if (GetLevelByClass(CLASS_TYPE_SOULBORN, oMeldshaper))
	{
		int i, nTest;
    	for (i = 0; i <= 20; i++)
    	{
			nTest = GetLocalInt(oMeldshaper, "ShapedMeld"+IntToString(CLASS_TYPE_SOULBORN)+IntToString(i));
			if (nTest) // If it's not blank, recast it
			{
				//FloatingTextStringOnCreature("ReshapeMelds: CLASS_TYPE_SOULBORN nTest "+IntToString(nTest), oMeldshaper);
				ActionCastSpellOnSelf(nTest);
			}	
    	}
    }
	if (GetLevelByClass(CLASS_TYPE_TOTEMIST, oMeldshaper))
	{
		int i, nTest;
    	for (i = 0; i <= 20; i++)
    	{
			nTest = GetLocalInt(oMeldshaper, "ShapedMeld"+IntToString(CLASS_TYPE_TOTEMIST)+IntToString(i));
			if (nTest) // If it's not blank, recast it
			{
				//FloatingTextStringOnCreature("ReshapeMelds: CLASS_TYPE_TOTEMIST nTest "+IntToString(nTest), oMeldshaper);
				ActionCastSpellOnSelf(nTest);
			}	
    	}
    }    
	if (GetLevelByClass(CLASS_TYPE_SPINEMELD_WARRIOR, oMeldshaper))
	{
		ActionCastSpellOnSelf(MELD_SPINE_ENHANCEMENT);
		int i, nTest;
    	for (i = 0; i <= 20; i++)
    	{
			nTest = GetLocalInt(oMeldshaper, "ShapedMeld"+IntToString(CLASS_TYPE_SPINEMELD_WARRIOR)+IntToString(i));
			if (nTest) // If it's not blank, recast it
			{
				//FloatingTextStringOnCreature("ReshapeMelds: CLASS_TYPE_TOTEMIST nTest "+IntToString(nTest), oMeldshaper);
				ActionCastSpellOnSelf(nTest);
			}	
    	}
    }     
    int nIron = GetLevelByClass(CLASS_TYPE_IRONSOUL_FORGEMASTER, oMeldshaper);
	if (nIron)
	{
		ActionCastSpellOnSelf(MELD_IRONSOUL_SHIELD);
		if (nIron >= 5) ActionCastSpellOnSelf(MELD_IRONSOUL_ARMOR);
		if (nIron >= 9) ActionCastSpellOnSelf(MELD_IRONSOUL_WEAPON);		
	}
    int nUmbral = GetLevelByClass(CLASS_TYPE_UMBRAL_DISCIPLE, oMeldshaper);
	if (nUmbral)
	{
		ActionCastSpellOnSelf(MELD_UMBRAL_STEP);
		if (nUmbral >= 3) ActionCastSpellOnSelf(MELD_UMBRAL_SHADOW);
		if (nUmbral >= 7) ActionCastSpellOnSelf(MELD_UMBRAL_SIGHT);		
		if (nUmbral >= 9) ActionCastSpellOnSelf(MELD_UMBRAL_SOUL);
		if (nUmbral >= 10) ActionCastSpellOnSelf(MELD_UMBRAL_KISS);
	}	
    int nIncand = GetLevelByClass(CLASS_TYPE_INCANDESCENT_CHAMPION, oMeldshaper);
	if (nIncand)
	{
		ActionCastSpellOnSelf(MELD_INCANDESCENT_STRIKE);
	}	
	if(GetLevelByClass(CLASS_TYPE_WITCHBORN_BINDER, oMeldshaper)) ActionCastSpellOnSelf(MELD_WITCH_MELDSHIELD);
    if (GetRacialType(oMeldshaper) == RACIAL_TYPE_DUSKLING) ActionCastSpellOnSelf(MELD_DUSKLING_SPEED);
}

int EssentiaToD4(int nEssentia)
{
	if (nEssentia == 1    )   return IP_CONST_DAMAGEBONUS_1d4;	
	else if (nEssentia == 2)  return IP_CONST_DAMAGEBONUS_2d4;
	else if (nEssentia == 3)  return IP_CONST_DAMAGEBONUS_3d4;
	else if (nEssentia == 4)  return IP_CONST_DAMAGEBONUS_4d4;
	else if (nEssentia == 5)  return IP_CONST_DAMAGEBONUS_5d4;
	else if (nEssentia == 6)  return IP_CONST_DAMAGEBONUS_6d4;
	else if (nEssentia == 7)  return IP_CONST_DAMAGEBONUS_7d4;
	else if (nEssentia == 8)  return IP_CONST_DAMAGEBONUS_8d4;
	else if (nEssentia == 9)  return IP_CONST_DAMAGEBONUS_9d4;	
	else if (nEssentia >= 10) return IP_CONST_DAMAGEBONUS_10d4;
	
	return -1;
}

int IncarnateAlignment(object oMeldshaper)
{
	int nReturn = FALSE;
	
	if (GetAlignmentLawChaos(oMeldshaper) == ALIGNMENT_LAWFUL && GetAlignmentGoodEvil(oMeldshaper) == ALIGNMENT_NEUTRAL)
	{
		nReturn = TRUE;
	}
	else if (GetAlignmentLawChaos(oMeldshaper) == ALIGNMENT_CHAOTIC && GetAlignmentGoodEvil(oMeldshaper) == ALIGNMENT_NEUTRAL)
	{
		nReturn = TRUE;
	}	
	else if (GetAlignmentLawChaos(oMeldshaper) == ALIGNMENT_NEUTRAL && GetAlignmentGoodEvil(oMeldshaper) == ALIGNMENT_GOOD)
	{
		nReturn = TRUE;
	}
	else if (GetAlignmentLawChaos(oMeldshaper) == ALIGNMENT_NEUTRAL && GetAlignmentGoodEvil(oMeldshaper) == ALIGNMENT_EVIL)
	{
		nReturn = TRUE;
	}
	
	return nReturn;
}

int GetOpposition(object oMeldshaper, object oTarget)
{
	int nReturn = FALSE;
	if (GetAlignmentLawChaos(oMeldshaper) == ALIGNMENT_LAWFUL && GetAlignmentGoodEvil(oMeldshaper) == ALIGNMENT_GOOD && (GetAlignmentGoodEvil(oTarget) == ALIGNMENT_EVIL || GetAlignmentLawChaos(oTarget) == ALIGNMENT_CHAOTIC))
		nReturn = TRUE;
	if (GetAlignmentLawChaos(oMeldshaper) == ALIGNMENT_LAWFUL && GetAlignmentGoodEvil(oMeldshaper) == ALIGNMENT_EVIL && (GetAlignmentGoodEvil(oTarget) == ALIGNMENT_GOOD || GetAlignmentLawChaos(oTarget) == ALIGNMENT_CHAOTIC))
		nReturn = TRUE;
	if (GetAlignmentLawChaos(oMeldshaper) == ALIGNMENT_CHAOTIC && GetAlignmentGoodEvil(oMeldshaper) == ALIGNMENT_GOOD && (GetAlignmentGoodEvil(oTarget) == ALIGNMENT_EVIL || GetAlignmentLawChaos(oTarget) == ALIGNMENT_LAWFUL))
		nReturn = TRUE;
	if (GetAlignmentLawChaos(oMeldshaper) == ALIGNMENT_CHAOTIC && GetAlignmentGoodEvil(oMeldshaper) == ALIGNMENT_EVIL && (GetAlignmentGoodEvil(oTarget) == ALIGNMENT_GOOD || GetAlignmentLawChaos(oTarget) == ALIGNMENT_LAWFUL))
		nReturn = TRUE;	
		
	return nReturn;	
}

void SetTemporaryEssentia(object oMeldshaper, int nEssentia)
{
	//if (DEBUG) DoDebug("Set Temporary Essentia from "+IntToString(GetLocalInt(oMeldshaper, "TemporaryEssentia"))+" to "+IntToString(GetLocalInt(oMeldshaper, "TemporaryEssentia")+nEssentia));
	SetLocalInt(oMeldshaper, "TemporaryEssentia", GetLocalInt(oMeldshaper, "TemporaryEssentia")+nEssentia);
}

int GetTemporaryEssentia(object oMeldshaper)
{
	return GetLocalInt(oMeldshaper, "TemporaryEssentia");
}

int GetMaxEssentiaCapacityFeat(object oMeldshaper)
{
	int nMax = 1; // Always can invest one
	int nHD = GetHitDice(oMeldshaper);
	if (nHD >= 61) nMax = 8;
	else if (nHD >= 51) nMax = 7;
	else if (nHD >= 41) nMax = 6;
	else if (nHD >= 31) nMax = 5;	
	else if (nHD >= 18) nMax = 4;
	else if (nHD >= 12) nMax = 3;
	else if (nHD >= 6) nMax = 2;
	
	if (GetLocalInt(oMeldshaper, "DivineSoultouch")) nMax += 1;
	if (GetLocalInt(oMeldshaper, "IncandescentOverload")) nMax += PRCMax(GetAbilityModifier(ABILITY_CHARISMA, oMeldshaper), 1);
	if (GetHasFeat(FEAT_IMPROVED_ESSENTIA_CAPACITY, oMeldshaper)) nMax += 1;
	
	// Don't allow more than they have
	if (nMax > GetTotalUsableEssentia(oMeldshaper)) nMax = GetTotalUsableEssentia(oMeldshaper);

	if(DEBUG) DoDebug("GetMaxEssentiaCapacityFeat: nHD "+IntToString(nHD)+" nMax "+IntToString(nMax));
	return nMax;
}

void SapphireSmiteUses(object oMeldshaper, int nEssentia)
{
	int i;

    for (i = 1; i <= nEssentia; i++)
    {
		IncrementRemainingFeatUses(oMeldshaper, FEAT_SMITE_GOOD_ALIGN); // Fist of Raziel
		IncrementRemainingFeatUses(oMeldshaper, FEAT_SMITE_EVIL); // Paladin
		IncrementRemainingFeatUses(oMeldshaper, FEAT_SMITE_GOOD); // Blackguard
		IncrementRemainingFeatUses(oMeldshaper, FEAT_KIAI_SMITE); // CW Samurai		
		IncrementRemainingFeatUses(oMeldshaper, FEAT_CRUSADER_SMITE); // Crusader
		IncrementRemainingFeatUses(oMeldshaper, FEAT_SMITE_UNDEAD); // Soldier of Light
		IncrementRemainingFeatUses(oMeldshaper, FEAT_SHADOWBANE_SMITE); // Shadowbane
		IncrementRemainingFeatUses(oMeldshaper, FEAT_KILLOREN_ASPECT_D); // Killoren
		IncrementRemainingFeatUses(oMeldshaper, FEAT_SMITE_OPPOSITION); // Soulborn
		IncrementRemainingFeatUses(oMeldshaper, FEAT_CULTIST_SMITE_MAGE); // Cultist of the Shattered Peak
    }
}

void AzureEnmity(object oMeldshaper, int nEssentia)
{
	effect eLink = EffectLinkEffects(EffectSkillIncrease(SKILL_BLUFF, nEssentia), EffectSkillIncrease(SKILL_LISTEN, nEssentia));
	       eLink = EffectLinkEffects(eLink, EffectSkillIncrease(SKILL_SENSE_MOTIVE, nEssentia));
	       eLink = EffectLinkEffects(eLink, EffectSkillIncrease(SKILL_SPOT, nEssentia));
	       eLink = EffectLinkEffects(eLink, EffectDamageIncrease(IPGetDamageBonusConstantFromNumber(nEssentia), DAMAGE_TYPE_BASE_WEAPON));

    if(GetHasFeat(FEAT_FAVORED_ENEMY_ABERRATION, oMeldshaper))
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, SupernaturalEffect(VersusRacialTypeEffect(eLink, RACIAL_TYPE_ABERRATION)), oMeldshaper, 9999.0);
    if(GetHasFeat(FEAT_FAVORED_ENEMY_ANIMAL, oMeldshaper))
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, SupernaturalEffect(VersusRacialTypeEffect(eLink, RACIAL_TYPE_ANIMAL)), oMeldshaper, 9999.0);
    if(GetHasFeat(FEAT_FAVORED_ENEMY_BEAST, oMeldshaper))
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, SupernaturalEffect(VersusRacialTypeEffect(eLink, RACIAL_TYPE_BEAST)), oMeldshaper, 9999.0);
    if(GetHasFeat(FEAT_FAVORED_ENEMY_CONSTRUCT, oMeldshaper))
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, SupernaturalEffect(VersusRacialTypeEffect(eLink, RACIAL_TYPE_CONSTRUCT)), oMeldshaper, 9999.0);
    if(GetHasFeat(FEAT_FAVORED_ENEMY_DRAGON, oMeldshaper))
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, SupernaturalEffect(VersusRacialTypeEffect(eLink, RACIAL_TYPE_DRAGON)), oMeldshaper, 9999.0);
    if(GetHasFeat(FEAT_FAVORED_ENEMY_DWARF, oMeldshaper))
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, SupernaturalEffect(VersusRacialTypeEffect(eLink, RACIAL_TYPE_DWARF)), oMeldshaper, 9999.0);
    if(GetHasFeat(FEAT_FAVORED_ENEMY_ELEMENTAL, oMeldshaper))
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, SupernaturalEffect(VersusRacialTypeEffect(eLink, RACIAL_TYPE_ELEMENTAL)), oMeldshaper, 9999.0);
    if(GetHasFeat(FEAT_FAVORED_ENEMY_ELF, oMeldshaper))
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, SupernaturalEffect(VersusRacialTypeEffect(eLink, RACIAL_TYPE_ELF)), oMeldshaper, 9999.0);
    if(GetHasFeat(FEAT_FAVORED_ENEMY_FEY, oMeldshaper))
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, SupernaturalEffect(VersusRacialTypeEffect(eLink, RACIAL_TYPE_FEY)), oMeldshaper, 9999.0);
    if(GetHasFeat(FEAT_FAVORED_ENEMY_GIANT, oMeldshaper))
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, SupernaturalEffect(VersusRacialTypeEffect(eLink, RACIAL_TYPE_GIANT)), oMeldshaper, 9999.0);
    if(GetHasFeat(FEAT_FAVORED_ENEMY_GNOME, oMeldshaper))
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, SupernaturalEffect(VersusRacialTypeEffect(eLink, RACIAL_TYPE_GNOME)), oMeldshaper, 9999.0);
    if(GetHasFeat(FEAT_FAVORED_ENEMY_GOBLINOID, oMeldshaper))
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, SupernaturalEffect(VersusRacialTypeEffect(eLink, RACIAL_TYPE_HUMANOID_GOBLINOID)), oMeldshaper, 9999.0);
    if(GetHasFeat(FEAT_FAVORED_ENEMY_HALFELF, oMeldshaper))
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, SupernaturalEffect(VersusRacialTypeEffect(eLink, RACIAL_TYPE_HALFELF)), oMeldshaper, 9999.0);
    if(GetHasFeat(FEAT_FAVORED_ENEMY_HALFLING, oMeldshaper))
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, SupernaturalEffect(VersusRacialTypeEffect(eLink, RACIAL_TYPE_HALFLING)), oMeldshaper, 9999.0);
    if(GetHasFeat(FEAT_FAVORED_ENEMY_HALFORC, oMeldshaper))
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, SupernaturalEffect(VersusRacialTypeEffect(eLink, RACIAL_TYPE_HALFORC)), oMeldshaper, 9999.0);
    if(GetHasFeat(FEAT_FAVORED_ENEMY_HUMAN, oMeldshaper))
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, SupernaturalEffect(VersusRacialTypeEffect(eLink, RACIAL_TYPE_HUMAN)), oMeldshaper, 9999.0);
    if(GetHasFeat(FEAT_FAVORED_ENEMY_MAGICAL_BEAST, oMeldshaper))
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, SupernaturalEffect(VersusRacialTypeEffect(eLink, RACIAL_TYPE_MAGICAL_BEAST)), oMeldshaper, 9999.0);
    if(GetHasFeat(FEAT_FAVORED_ENEMY_MONSTROUS, oMeldshaper))
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, SupernaturalEffect(VersusRacialTypeEffect(eLink, RACIAL_TYPE_HUMANOID_MONSTROUS)), oMeldshaper, 9999.0);
    if(GetHasFeat(RACIAL_TYPE_HUMANOID_ORC, oMeldshaper))
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, SupernaturalEffect(VersusRacialTypeEffect(eLink, RACIAL_TYPE_HUMANOID_ORC)), oMeldshaper, 9999.0);
    if(GetHasFeat(FEAT_FAVORED_ENEMY_OUTSIDER, oMeldshaper))
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, SupernaturalEffect(VersusRacialTypeEffect(eLink, RACIAL_TYPE_OUTSIDER)), oMeldshaper, 9999.0);
    if(GetHasFeat(FEAT_FAVORED_ENEMY_REPTILIAN, oMeldshaper))
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, SupernaturalEffect(VersusRacialTypeEffect(eLink, RACIAL_TYPE_HUMANOID_REPTILIAN)), oMeldshaper, 9999.0);
    if(GetHasFeat(FEAT_FAVORED_ENEMY_SHAPECHANGER, oMeldshaper))
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, SupernaturalEffect(VersusRacialTypeEffect(eLink, RACIAL_TYPE_SHAPECHANGER)), oMeldshaper, 9999.0);
    if(GetHasFeat(FEAT_FAVORED_ENEMY_UNDEAD, oMeldshaper))
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, SupernaturalEffect(VersusRacialTypeEffect(eLink, RACIAL_TYPE_UNDEAD)), oMeldshaper, 9999.0);
    if(GetHasFeat(FEAT_FAVORED_ENEMY_VERMIN, oMeldshaper))
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, SupernaturalEffect(VersusRacialTypeEffect(eLink, RACIAL_TYPE_VERMIN)), oMeldshaper, 9999.0);
}

void DoFeatBonus(object oMeldshaper, int nFeat, int nEssentia)
{
	effect eLink;
	if (nFeat == FEAT_CERULEAN_FORTITUDE) eLink = EffectSavingThrowIncrease(SAVING_THROW_FORT, nEssentia);
	else if (nFeat == FEAT_CERULEAN_REFLEXES) eLink = EffectSavingThrowIncrease(SAVING_THROW_REFLEX, nEssentia);
	else if (nFeat == FEAT_CERULEAN_WILL) eLink = EffectSavingThrowIncrease(SAVING_THROW_WILL, nEssentia);
	else if (nFeat == FEAT_AZURE_TALENT) ExecuteScript("moi_ft_aztalent", oMeldshaper);
	else if (nFeat == FEAT_AZURE_TOUGHNESS) eLink = EffectTemporaryHitpoints(3*nEssentia);
	else if (nFeat == FEAT_HEALING_SOUL) FeatUsePerDay(oMeldshaper, FEAT_HEALING_SOUL, -1, 0, nEssentia);
	else if (nFeat == FEAT_SAPPHIRE_SMITE) SapphireSmiteUses(oMeldshaper, nEssentia);
	else if (nFeat == FEAT_AZURE_ENMITY) AzureEnmity(oMeldshaper, nEssentia);
	
	ApplyEffectToObject(DURATION_TYPE_TEMPORARY, SupernaturalEffect(eLink), oMeldshaper, 9999.0);
}

void InvestEssentiaFeat(object oMeldshaper, int nFeat, int nEssentia)
{
	// Jump out if there's no feat
	if (!GetHasFeat(nFeat, oMeldshaper)) return;
	
	int nMax = GetMaxEssentiaCapacityFeat(oMeldshaper);
	
	// Bonuses to specific feat caps
	if (nFeat == FEAT_COBALT_RAGE && GetLevelByClass(CLASS_TYPE_TOTEM_RAGER, oMeldshaper)) nMax++;
	
	// No breaking the rules
	if (nEssentia > nMax) nEssentia = nMax;
	// Can't invest more than you have
	if (nEssentia > GetTotalUsableEssentia(oMeldshaper)) nEssentia = GetTotalUsableEssentia(oMeldshaper);	
	
	FloatingTextStringOnCreature("Investing "+IntToString(nEssentia)+" essentia into "+GetStringByStrRef(StringToInt(Get2DACache("feat", "FEAT", nFeat))), oMeldshaper);
	DoFeatBonus(oMeldshaper, nFeat, nEssentia);
	SetLocalInt(oMeldshaper, "FeatEssentia"+IntToString(nFeat), nEssentia);
}

void DoClassBonus(object oMeldshaper, int nFeat, int nEssentia)
{

}

void InvestEssentiaClass(object oMeldshaper, int nFeat, int nEssentia)
{
	// Jump out if there's no feat
	if (!GetHasFeat(nFeat, oMeldshaper)) return;
	
	// No breaking the rules
	if (nEssentia > GetMaxEssentiaCapacityFeat(oMeldshaper)) nEssentia = GetMaxEssentiaCapacityFeat(oMeldshaper);
	// Can't invest more than you have
	if (nEssentia > GetTotalUsableEssentia(oMeldshaper)) nEssentia = GetTotalUsableEssentia(oMeldshaper);	
	
	FloatingTextStringOnCreature("Investing "+IntToString(nEssentia)+" essentia into "+GetStringByStrRef(StringToInt(Get2DACache("feat", "FEAT", nFeat))), oMeldshaper);
	DoClassBonus(oMeldshaper, nFeat, nEssentia);
	SetLocalInt(oMeldshaper, "ClassEssentia"+IntToString(nFeat), nEssentia);
}

void InvestEssentiaSpell(object oMeldshaper, int nFeat, int nEssentia)
{
	FloatingTextStringOnCreature("Investing "+IntToString(nEssentia)+" essentia into "+GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nFeat))), oMeldshaper);
	SetLocalInt(oMeldshaper, "SpellEssentia"+IntToString(nFeat), nEssentia);
	if (!GetLocalInt(oMeldshaper, "SpellInvestCheck1")) SetLocalInt(oMeldshaper, "SpellInvestCheck1", nFeat);
	else if (!GetLocalInt(oMeldshaper, "SpellInvestCheck2")) SetLocalInt(oMeldshaper, "SpellInvestCheck2", nFeat);
	else if (!GetLocalInt(oMeldshaper, "SpellInvestCheck3")) SetLocalInt(oMeldshaper, "SpellInvestCheck3", nFeat);
	else if (!GetLocalInt(oMeldshaper, "SpellInvestCheck4")) SetLocalInt(oMeldshaper, "SpellInvestCheck4", nFeat);
	else if (!GetLocalInt(oMeldshaper, "SpellInvestCheck5")) SetLocalInt(oMeldshaper, "SpellInvestCheck5", nFeat);
	else if (!GetLocalInt(oMeldshaper, "SpellInvestCheck6")) SetLocalInt(oMeldshaper, "SpellInvestCheck6", nFeat);
	else if (!GetLocalInt(oMeldshaper, "SpellInvestCheck7")) SetLocalInt(oMeldshaper, "SpellInvestCheck7", nFeat);
	else if (!GetLocalInt(oMeldshaper, "SpellInvestCheck8")) SetLocalInt(oMeldshaper, "SpellInvestCheck8", nFeat);
	else if (!GetLocalInt(oMeldshaper, "SpellInvestCheck9")) SetLocalInt(oMeldshaper, "SpellInvestCheck9", nFeat);
	else if (!GetLocalInt(oMeldshaper, "SpellInvestCheck10")) SetLocalInt(oMeldshaper, "SpellInvestCheck10", nFeat);
}

int GetFeatLockedEssentia(object oMeldshaper)
{
	int nTotal, i, nTest;
    for (i = 8869; i < 8889; i++)
    {
		nTest = GetLocalInt(oMeldshaper, "FeatEssentia"+IntToString(i));
		if (nTest) // If it's not blank
			nTotal += nTest;	
    } 
    for (i = 0; i < 11; i++)
    {
		nTest = GetLocalInt(oMeldshaper, "SpellInvestCheck"+IntToString(i));
		if (nTest) // If it's not blank
			nTotal += GetLocalInt(oMeldshaper, "SpellEssentia"+IntToString(nTest));	
    }     
    //if (DEBUG) DoDebug("GetFeatLockedEssentia return value "+IntToString(nTotal));
    return nTotal;
}

int IncarnumFeats(object oMeldshaper)
{
	int nEssentia;
	
	if (GetHasFeat(FEAT_AZURE_ENMITY, oMeldshaper)) nEssentia += 1;
	if (GetHasFeat(FEAT_CERULEAN_FORTITUDE, oMeldshaper)) nEssentia += 1;
	if (GetHasFeat(FEAT_CERULEAN_REFLEXES, oMeldshaper)) nEssentia += 1;
	if (GetHasFeat(FEAT_CERULEAN_WILL, oMeldshaper)) nEssentia += 1;
	if (GetHasFeat(FEAT_AZURE_TALENT, oMeldshaper)) nEssentia += 1;
	if (GetHasFeat(FEAT_AZURE_TOUCH, oMeldshaper)) nEssentia += 1;
	if (GetHasFeat(FEAT_AZURE_TOUGHNESS, oMeldshaper)) nEssentia += 1;
	if (GetHasFeat(FEAT_AZURE_TURNING, oMeldshaper)) nEssentia += 1;
	if (GetHasFeat(FEAT_AZURE_WILD_SHAPE, oMeldshaper)) nEssentia += 1;
	if (GetHasFeat(FEAT_COBALT_CHARGE, oMeldshaper)) nEssentia += 1;
	if (GetHasFeat(FEAT_COBALT_EXPERTISE, oMeldshaper)) nEssentia += 1;
	if (GetHasFeat(FEAT_COBALT_POWER, oMeldshaper)) nEssentia += 1;
	if (GetHasFeat(FEAT_COBALT_RAGE, oMeldshaper)) nEssentia += 1;
	if (GetHasFeat(FEAT_HEALING_SOUL, oMeldshaper)) nEssentia += 1;
	if (GetHasFeat(FEAT_INCARNUM_SPELLSHAPING, oMeldshaper)) nEssentia += 1;
	if (GetHasFeat(FEAT_INDIGO_STRIKE, oMeldshaper)) nEssentia += 1;
	if (GetHasFeat(FEAT_MIDNIGHT_AUGMENTATION, oMeldshaper)) nEssentia += 1;
	if (GetHasFeat(FEAT_MIDNIGHT_DODGE, oMeldshaper)) nEssentia += 1;
	if (GetHasFeat(FEAT_MIDNIGHT_METAMAGIC, oMeldshaper)) nEssentia += 1;
	if (GetHasFeat(FEAT_PSYCARNUM_BLADE, oMeldshaper)) nEssentia += 1;
	if (GetHasFeat(FEAT_SAPPHIRE_SMITE, oMeldshaper)) nEssentia += 1;
	if (GetHasFeat(FEAT_SOULTOUCHED_SPELLCASTING, oMeldshaper)) nEssentia += 1;
	if (GetHasFeat(FEAT_BONUS_ESSENTIA, oMeldshaper)) 
	{	
		nEssentia += 1;
		if(GetIsIncarnumUser(oMeldshaper))
			nEssentia += 1; // Yes, this is correct
	}		
	if (GetRacialType(oMeldshaper) == RACIAL_TYPE_DUSKLING) nEssentia += 1;
	if (GetRacialType(oMeldshaper) == RACIAL_TYPE_AZURIN) nEssentia += 1;

   	int i;
   	for(i = FEAT_EPIC_ESSENTIA_1; i <= FEAT_EPIC_ESSENTIA_6; i++)
   	    if(GetHasFeat(i, oMeldshaper)) nEssentia += 3;
	
	//if (DEBUG) DoDebug("IncarnumFeats return value "+IntToString(nEssentia));
	return nEssentia;
}

void AddNecrocarnumEssentia(object oMeldshaper, int nEssentia)
{
	int nNecrocarnum = GetLocalInt(oMeldshaper, "NecrocarnumEssentia");
	SetLocalInt(oMeldshaper, "NecrocarnumEssentia", nNecrocarnum+nEssentia);
	// It lasts for 24 hours, then remove it back out
	DelayCommand(HoursToSeconds(24), SetLocalInt(oMeldshaper, "NecrocarnumEssentia", GetLocalInt(oMeldshaper, "NecrocarnumEssentia")-nEssentia));
}

int GetTotalEssentia(object oMeldshaper)
{
	int nEssentia;
	
	if (GetLevelByClass(CLASS_TYPE_INCARNATE, oMeldshaper)) nEssentia += GetMaxEssentiaCount(oMeldshaper, CLASS_TYPE_INCARNATE);
	if (GetLevelByClass(CLASS_TYPE_SOULBORN, oMeldshaper))  nEssentia += GetMaxEssentiaCount(oMeldshaper, CLASS_TYPE_SOULBORN);
	if (GetLevelByClass(CLASS_TYPE_TOTEMIST, oMeldshaper))  nEssentia += GetMaxEssentiaCount(oMeldshaper, CLASS_TYPE_TOTEMIST);
	if (GetLevelByClass(CLASS_TYPE_SPINEMELD_WARRIOR, oMeldshaper))  nEssentia += GetMaxEssentiaCount(oMeldshaper, CLASS_TYPE_SPINEMELD_WARRIOR);
	if (GetLevelByClass(CLASS_TYPE_UMBRAL_DISCIPLE, oMeldshaper))  nEssentia += GetMaxEssentiaCount(oMeldshaper, CLASS_TYPE_UMBRAL_DISCIPLE);
	if (GetLevelByClass(CLASS_TYPE_NECROCARNATE, oMeldshaper)) nEssentia += GetLocalInt(oMeldshaper, "NecrocarnumEssentia");
	if (GetLevelByClass(CLASS_TYPE_WITCHBORN_BINDER, oMeldshaper) >= 2) nEssentia += 1;
	if (GetLevelByClass(CLASS_TYPE_WITCHBORN_BINDER, oMeldshaper) >= 6) nEssentia += 1;
	if (GetLevelByClass(CLASS_TYPE_INCANDESCENT_CHAMPION, oMeldshaper))  nEssentia += GetMaxEssentiaCount(oMeldshaper, CLASS_TYPE_INCANDESCENT_CHAMPION);
	
	nEssentia += IncarnumFeats(oMeldshaper);
	//if (DEBUG) DoDebug("GetTotalEssentia return value "+IntToString(nEssentia));
	return nEssentia;
}

int GetTotalUsableEssentia(object oMeldshaper)
{
	return GetTotalEssentia(oMeldshaper) - GetFeatLockedEssentia(oMeldshaper);
}

int GetIncarnumFeats(object oMeldshaper)
{
	int nTotal, i;
    for (i = 8868; i < 8910; i++)
    {
		if (GetHasFeat(i, oMeldshaper)) 
			nTotal += 1;	
    }  
    //if (DEBUG) DoDebug("GetIncarnumFeats return value "+IntToString(nTotal));
    return nTotal;
}

int GetIsBlademeldUsed(object oMeldshaper, int nChakra)
{
	int nTest = GetLocalInt(oMeldshaper, "UsedBladeMeld"+IntToString(nChakra));
	
    //if (DEBUG) DoDebug("GetIsBlademeldUsed is "+IntToString(nTest));
    return nTest;
}

void SetBlademeldUsed(object oMeldshaper, int nChakra)
{
	if (!GetIsBlademeldUsed(oMeldshaper, nChakra))
	{
		SetLocalInt(oMeldshaper, "UsedBladeMeld"+IntToString(nChakra), nChakra);
	}
}

string GetBlademeldDesc(int nChakra)
{
	string sString;
	if (nChakra == CHAKRA_CROWN    ) sString = "You gain a +4 bonus on disarm checks and on Sense Motive";
	if (nChakra == CHAKRA_FEET     ) sString = "You gain a +2 bonus on Initiative";
	if (nChakra == CHAKRA_HANDS    ) sString = "You gain a +1 bonus on damage";
	if (nChakra == CHAKRA_ARMS     ) sString = "You gain a +2 bonus on attack rolls";
	if (nChakra == CHAKRA_BROW     ) sString = "You gain the Blind-Fight feat";
	if (nChakra == CHAKRA_SHOULDERS) sString = "You gain immunity to criticals but not sneak attacks";
	if (nChakra == CHAKRA_THROAT   ) sString = "At will as a standard action, each enemy within 60 feet who can hear you shout must save or become shaken for 1 round (Will DC 10 + incarnum blade level + Con modifier).";
	if (nChakra == CHAKRA_WAIST    ) sString = "You gain a +10 bonus on checks made to avoid being bull rushed, grappled, tripped, or overrun. You also gain Uncanny Dodge";
	if (nChakra == CHAKRA_HEART    ) sString = "You gain temporary hit points equal to twice your character level (maximum +40)";
	if (nChakra == CHAKRA_SOUL     ) sString = "You break DR up to +3, and deal 1d6 damage to creatures of one opposed alignment";
    
	return sString;
}

int ChakraToBlademeld(int nChakra)
{
	int nMeld;
	if (nChakra == CHAKRA_CROWN    ) nMeld = MELD_BLADEMELD_CROWN;    
	if (nChakra == CHAKRA_FEET     ) nMeld = MELD_BLADEMELD_FEET;     
	if (nChakra == CHAKRA_HANDS    ) nMeld = MELD_BLADEMELD_HANDS;    
	if (nChakra == CHAKRA_ARMS     ) nMeld = MELD_BLADEMELD_ARMS;     
	if (nChakra == CHAKRA_BROW     ) nMeld = MELD_BLADEMELD_BROW;     
	if (nChakra == CHAKRA_SHOULDERS) nMeld = MELD_BLADEMELD_SHOULDERS;
	if (nChakra == CHAKRA_THROAT   ) nMeld = MELD_BLADEMELD_THROAT;   
	if (nChakra == CHAKRA_WAIST    ) nMeld = MELD_BLADEMELD_WAIST;    
	if (nChakra == CHAKRA_HEART    ) nMeld = MELD_BLADEMELD_HEART;    
	if (nChakra == CHAKRA_SOUL     ) nMeld = MELD_BLADEMELD_SOUL;     
    
	return nMeld;
}