//::///////////////////////////////////////////////
//:: Name  oai_inc_weapstat
//:://////////////////////////////////////////////
/*
    Routines to get weapon stats
    Implements an on demand cache for weapon stats from 2DA to local variables

    Cache Table is "OAI_CWS_" prefix to variable name (can be chanhed below)
    Uses "OAI_CWS_Category" as the index to determine if cache values are loaded
    (so "OAI_CWS_Category0" would hold the Category of a short sword)
    Loads all variables (tracked) for the requested base item type from the
    baseitems.2da per when first required.
    Nb! So far only get Int values (through need, will impliment strings later if required)
*/
//:://////////////////////////////////////////////
//:: Created By: David Kelly
//:: Created On: 26-Dec-2005
//:://////////////////////////////////////////////

const string OAI_CACHEPREFIX = "OAI_CSW_";  // Prefix for cahce variables
const int OAI_CACHENULL = -99;  // Value which means has no value (caution, CAN NOT BE zero)

// Tracked variables
const string OAI_STAT_CATEGORY      = "Category";
const string OAI_STAT_WEAPONSIZE    = "WeaponSize";
const string OAI_STAT_WEAPONTYPE    = "WeaponType";
const string OAI_STAT_BASEAMMO      = "BaseAmmo";
const string OAI_STAT_MAXDAMAGE     = "MaxDamage";
const string OAI_STAT_REQFEAT       = "ReqFeat";

// Fixed flags for Feat Mask
// Bit mask: 1E,2M,4S,8D,16Mo,32R,64MU,128Elf,256C
const int OAI_MASK_EXOTIC   = 0x0001;
const int OAI_MASK_MARTIAL  = 0x0002;
const int OAI_MASK_SIMPLE   = 0x0004;
const int OAI_MASK_DRUID    = 0x0008;
const int OAI_MASK_MONK     = 0x0010;
const int OAI_MASK_ROGUE    = 0x0020;
const int OAI_MASK_MU       = 0x0040;
const int OAI_MASK_ELF      = 0x0080;
const int OAI_MASK_CREATURE = 0x0100;

struct OAIWeapon
{
    int nBaseType;      // Weapons BaseType
    int nCategory;      // 1 melee, 2 bows, 3 shield, 6 ammo, 7 thrown
    int nWeaponSize;    // 1 tiny, 2 small, 3 medium, 4 large
    int nWeaponType;    // 1 pierce, 2 crush, 3 slash, 4 slash/pierce
    int nBaseAmmo;      // nBaseType of ammo (self for thrown)
    int nMaxDamage;     // Maximum damage not counting criticals
    int nReqFeat;       // 1 Exotic, 2 martial, 4 simple, 8 druid, 16 monk,
                        // 32 rogue, 64 MU, 128 elf, 256 creature (as Bit Mask)
};

// Routine to get weapon stats structure for given weapon
struct OAIWeapon OAI_GetWeaponStats(object oItem);

// Gets required weapon stat, from cache if available
// if not chache will be loaded first and then used
int OAI_GetWeaponStat(object oItem, string sStat);

// Converts 2DA Feat reference to Feat Bit Mask value
int OAI_FeatToMask(string sFeat);

// Generate the FeatMask for the given creature
int OAI_GetFeatMask(object oMon);

int OAI_GetFeatMask(object oMon)
{
    int class, pos, mask = 0;

    if (GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE))
        mask += OAI_MASK_SIMPLE;
    if (GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL))
        mask += OAI_MASK_MARTIAL;
    if (GetHasFeat(FEAT_WEAPON_PROFICIENCY_EXOTIC))
        mask += OAI_MASK_EXOTIC;

    for (pos = 1; pos <= 3; pos++)
        switch (GetClassByPosition(pos, oMon))
        {
            case CLASS_TYPE_DRUID: mask += OAI_MASK_DRUID; break;
            case CLASS_TYPE_MONK: mask += OAI_MASK_MONK; break;
            case CLASS_TYPE_ROGUE: mask += OAI_MASK_ROGUE; break;
            case CLASS_TYPE_SORCERER:
            case CLASS_TYPE_WIZARD:
                mask += OAI_MASK_MU; break;
        }

    if (GetRacialType(oMon) == RACIAL_TYPE_ELF)
        mask += OAI_MASK_ELF;

    return mask;
}

/*
 * If using 2DA references
 */
int OAI_FeatToMask(string sFeat)
{
    int nFeat = StringToInt(sFeat);
    int nMask;

    switch (nFeat)
    {
        case  44: nMask = OAI_MASK_EXOTIC; break;   // Exotic
        case  45: nMask = OAI_MASK_MARTIAL; break;  // Martial
        case  46: nMask = OAI_MASK_SIMPLE; break;   // Simple
        case  48: nMask = OAI_MASK_DRUID; break;    // Druid
        case  49: nMask = OAI_MASK_MONK; break;     // Monk
        case  50: nMask = OAI_MASK_ROGUE; break;    // Rogue
        case  51: nMask = OAI_MASK_ELF; break;      // MU
        case 255: nMask = OAI_MASK_CREATURE; break; // Creature
        default: nMask = 0;
    }

    return nMask;
}

int OAI_GetWeaponStat(object oItem, string sStat)
{
    object oMod = GetModule();
    int nBaseType = GetBaseItemType(oItem);
    string sBaseType = IntToString(nBaseType);
    int nValue = GetLocalInt(oMod, OAI_CACHEPREFIX + OAI_STAT_CATEGORY + sBaseType);

    // Values not loaded yet
    if (nValue == 0)
    {
        int nLoop;

        // Load Cache
        nValue = StringToInt(Get2DAString("baseitems", "Category", nBaseType));
        if (nValue == 0)
            nValue = OAI_CACHENULL;     // NOT ALLOWED to be zero
        SetLocalInt(oMod, OAI_CACHEPREFIX + OAI_STAT_CATEGORY + sBaseType, nValue);

        // Weapon Size and Type and AMmotype are straight forward
        nValue = StringToInt(Get2DAString("baseitems", "WeaponSize", nBaseType));
        if (nValue)
            SetLocalInt(oMod, OAI_CACHEPREFIX + OAI_STAT_WEAPONSIZE + sBaseType, nValue);
        nValue = StringToInt(Get2DAString("baseitems", "WeaponType", nBaseType));
        if (nValue)
            SetLocalInt(oMod, OAI_CACHEPREFIX + OAI_STAT_WEAPONTYPE + sBaseType, nValue);
        nValue = StringToInt(Get2DAString("baseitems", "RangedWeapon", nBaseType));
        if (nValue)
            SetLocalInt(oMod, OAI_CACHEPREFIX + OAI_STAT_BASEAMMO + sBaseType, nValue);

        // Max Damge is a calculation
        nValue = StringToInt(Get2DAString("baseitems", "NumDice", nBaseType)) *
                 StringToInt(Get2DAString("baseitems", "DieToRoll", nBaseType));
        if (nValue)
            SetLocalInt(oMod, OAI_CACHEPREFIX + OAI_STAT_MAXDAMAGE + sBaseType, nValue);

        // Feats are mapped onto the bit mask values and stored as a single number
        nValue = 0;
        for (nLoop = 0; nLoop <= 4; nLoop++)
            nValue += OAI_FeatToMask(Get2DAString("baseitems", "ReqFeat" + IntToString(nLoop), nBaseType));
        if (nValue)
            SetLocalInt(oMod, OAI_CACHEPREFIX + OAI_STAT_REQFEAT + sBaseType, nValue);
    }

    // Return required result
    return GetLocalInt(oMod, OAI_CACHEPREFIX + sStat + sBaseType);
}

struct OAIWeapon OAI_GetWeaponStats(object oItem)
{
    object oMod = GetModule();
    struct OAIWeapon ow;
    string sBT;

    ow.nBaseType = GetBaseItemType(oItem);
    ow.nCategory = OAI_GetWeaponStat(oItem, OAI_STAT_CATEGORY); // Force cache to load if necessary
    sBT = IntToString(ow.nBaseType);
    ow.nWeaponSize = GetLocalInt(oMod, OAI_CACHEPREFIX + OAI_STAT_WEAPONSIZE + sBT);
    ow.nWeaponType = GetLocalInt(oMod, OAI_CACHEPREFIX + OAI_STAT_WEAPONTYPE + sBT);
    ow.nBaseAmmo = GetLocalInt(oMod, OAI_CACHEPREFIX + OAI_STAT_BASEAMMO + sBT);
    ow.nMaxDamage = GetLocalInt(oMod, OAI_CACHEPREFIX + OAI_STAT_MAXDAMAGE + sBT);
    ow.nReqFeat = GetLocalInt(oMod, OAI_CACHEPREFIX + OAI_STAT_REQFEAT + sBT);

    return ow;
}

//void main(){}