#include "fcb_inc_prot"

//==========================================/
void switch_forge_enable(int enable)
//==========================================/
    {
    //enable/disable forge functions
    //ui_main_set_hidden_refresh(MAIN_FOLDER_INDEX_MAINMENU | n, !enable);
    //n defines which option to control:

    //1: Add item properties
    //2: Remove item properties
    //3: Set charge count

    //4: Duplicate item
    //5: Set name
    //6: Colored item names guide

    //Commented menues will NOT be turned off when the forge is disabled.
    ui_main_set_hidden_refresh(MAIN_FOLDER_INDEX_MAINMENU | 1, !enable);
    ui_main_set_hidden_refresh(MAIN_FOLDER_INDEX_MAINMENU | 2, !enable);
    ui_main_set_hidden_refresh(MAIN_FOLDER_INDEX_MAINMENU | 3, !enable);
    //ui_main_set_hidden_refresh(MAIN_FOLDER_INDEX_MAINMENU | 4, !enable);
    //ui_main_set_hidden_refresh(MAIN_FOLDER_INDEX_MAINMENU | 5, !enable);
    //ui_main_set_hidden_refresh(MAIN_FOLDER_INDEX_MAINMENU | 6, !enable);
    }

//==========================================/
void switch_ILR_enable(int enable)
//==========================================/
    {
    SetLocalInt(FCB_HOST, SW_ILR_ENABLE, enable);
    }

//==========================================/
void start_conversation(object user)
//==========================================/
    {
    AssignCommand(FCB_CV, ActionStartConversation(user, CV_MAIN, 1, 0));
    }

//==========================================/
int get_character_level(object user)
//==========================================/
    {
    int level = GetLevelByClass(GetClassByPosition(1, user), user);
    level += GetLevelByClass(GetClassByPosition(2, user), user);
    level += GetLevelByClass(GetClassByPosition(3, user), user);

    return level;
    }

//==========================================/
int get_item_cost(object item)
//==========================================/
    {
    int item_plot_flag = GetPlotFlag(item);
    SetPlotFlag(item, 0);
    int item_identified = GetIdentified(item);
    SetIdentified(item, 1);

    int cost = GetGoldPieceValue(item);

    SetPlotFlag(item, item_plot_flag);
    SetIdentified(item, item_identified);
    return cost;
    }

//::::::::::::::::::::::::::::::::::::::::::/
int item_level_search(int cost, int begin, int end)
//::::::::::::::::::::::::::::::::::::::::::/
    {
    int n = begin + (end - begin)/2;
    int max_single_item_value_0 = StringToInt(Get2DAString("itemvalue", "MAXSINGLEITEMVALUE", n-1));
    int max_single_item_value_1 = StringToInt(Get2DAString("itemvalue", "MAXSINGLEITEMVALUE", n));

    if(cost > max_single_item_value_0)
        {
        if(cost <= max_single_item_value_1)
            {
            return n;
            }
        else if(n >= ITEM_LEVEL_MAX-1)
            {
            return ITEM_LEVEL_MAX-1;
            }
        else
            {
            return item_level_search(cost, n+1, end);
            }
        }
    else if(n <= 0)
        {
        return 0;
        }
    else
        {
        return item_level_search(cost, begin, n-1);
        }
    }

//==========================================/
int get_item_level(object item)
//==========================================/
    {
    int cost = get_item_cost(item);

    return item_level_search(cost, 0, ITEM_LEVEL_MAX-1) + 1;
    }

//==========================================/
int get_item_level_by_cost(int cost)
//==========================================/
    {
    return item_level_search(cost, 0, ITEM_LEVEL_MAX-1) + 1;
    }

//==========================================/
object copy_item(object item, object target_inventory)
//==========================================/
    {
    object item_copy = CopyItem(item, target_inventory, 0);

    SetIdentified(item_copy, 1);
    return item_copy;
    }

//==========================================/
int get_item_stack_size(object item)
//==========================================/
    {
    return StringToInt(Get2DAString("baseitems", "ILRStackSize", GetBaseItemType(item)));
    }

//==========================================/
int give_gold(int gp_amount, object user)
//==========================================/
    {
    if(gp_amount >= 0)
        {
        GiveGoldToCreature(user, gp_amount);
        }
    else
        {
        if((GetGold(user) + gp_amount) >= 0)
            {
            TakeGoldFromCreature(-gp_amount, user, 1);
            }
        else
            {
            return 0;
            }
        }
    return 1;
    }

//==========================================/
int iprp_to_param(itemproperty iprp)
//==========================================/
    {
    int itempropdef_row = FILTER_IPRP_TYPE & GetItemPropertyType(iprp);
    int subtype_row = FILTER_IPRP_SUB; //all 1s
    int cost_row = FILTER_IPRP_COST; //all 1s
    int param1_row = FILTER_IPRP_PARAM1 & GetItemPropertyParam1Value(iprp);

    //subtype exists
    string subtype_resref = Get2DAString("itempropdef", "SubTypeResRef", itempropdef_row);
    if(subtype_resref != "")
        {
        subtype_row &= GetItemPropertySubType(iprp);
        }

    //cost exists
    int costtable_row = GetItemPropertyCostTable(iprp);
    if(costtable_row > 0)
        {
        cost_row &= GetItemPropertyCostTableValue(iprp);
        }

    int param = (itempropdef_row << BITLEN_IPRP_SUB) | subtype_row;
    param = (param << BITLEN_IPRP_COST) | cost_row;
    param = (param << BITLEN_IPRP_PARAM1) | param1_row;

    return param;
    }

//==========================================/
itemproperty param_to_iprp(int param)
//==========================================/
    {
    int param0 = 0;
    int param1 = 0;
    int param2 = 0;
    int param3 = 0;

    //----------------------------------------//
    //7 bits
    int param1_row = FILTER_IPRP_PARAM1 & param;
    param >>>= BITLEN_IPRP_PARAM1;

    //8 bits
    int cost_row = FILTER_IPRP_COST & param;
    param >>>= BITLEN_IPRP_COST;

    //10 bits
    int subtype_row = FILTER_IPRP_SUB & param;
    param >>>= BITLEN_IPRP_SUB;

    //7 bits type
    param0 = FILTER_IPRP_TYPE & param;

    //----------------------------------------//
    //subtype exists
    if(subtype_row != FILTER_IPRP_SUB)
        {
        param1 = subtype_row;

        if(cost_row != FILTER_IPRP_COST)
            {
            param2 = cost_row;
            param3 = param1_row;
            }
        else
            {
            param2 = param1_row;
            }
        }
    else
        {
        if(cost_row != FILTER_IPRP_COST)
            {
            param1 = cost_row;
            param2 = param1_row;
            }
        }

    return convert_iprp(param0, param1, param2, param3);
    }

//==========================================/
itemproperty convert_iprp(int param0, int param1, int param2, int param3)
//==========================================/
    {
    switch(param0)
        {
        case 0:  return ItemPropertyAbilityBonus(param1, param2);
        case 1:  return ItemPropertyACBonus(param1);
        case 2:  return ItemPropertyACBonusVsAlign(param1, param2);
        case 3:  return ItemPropertyACBonusVsDmgType(param1, param2);
        case 4:  return ItemPropertyACBonusVsRace(param1, param2);
        case 5:  return ItemPropertyACBonusVsSAlign(param1, param2);
        case 6:  return ItemPropertyEnhancementBonus(param1);
        case 7:  return ItemPropertyEnhancementBonusVsAlign(param1, param2);
        case 8:  return ItemPropertyEnhancementBonusVsRace(param1, param2);
        case 9:  return ItemPropertyEnhancementBonusVsSAlign(param1, param2);
        case 10: return ItemPropertyEnhancementPenalty(param1);
        case 11: return ItemPropertyWeightReduction(param1);
        case 12: return ItemPropertyBonusFeat(param1);
        case 13: return ItemPropertyBonusLevelSpell(param1, param2);
        //case 14: return
        case 15: return ItemPropertyCastSpell(param1, param2);
        case 16: return ItemPropertyDamageBonus(param1, param2);
        case 17: return ItemPropertyDamageBonusVsAlign(param1, param3, param2); //special index shift
        case 18: return ItemPropertyDamageBonusVsRace(param1, param3, param2);  //special index shift
        case 19: return ItemPropertyDamageBonusVsSAlign(param1, param3, param2); //special index shift
        case 20: return ItemPropertyDamageImmunity(param1, param2);
        case 21: return ItemPropertyDamagePenalty(param1);
        case 22: return ItemPropertyDamageReduction(param1, param2);
        case 23: return ItemPropertyDamageResistance(param1, param2);
        case 24: return ItemPropertyDamageVulnerability(param1, param2);
        //case 25: return
        case 26: return ItemPropertyDarkvision();
        case 27: return ItemPropertyDecreaseAbility(param1, param2);
        case 28: return ItemPropertyDecreaseAC(param1, param2);
        case 29: return ItemPropertyDecreaseSkill(param1, param2);
        //case 30: return
        //case 31: return
        case 32: return ItemPropertyContainerReducedWeight(param1);
        case 33: return ItemPropertyExtraMeleeDamageType(param1);
        case 34: return ItemPropertyExtraRangeDamageType(param1);
        case 35: return ItemPropertyHaste();
        case 36: return ItemPropertyHolyAvenger();
        case 37: return ItemPropertyImmunityMisc(param1);
        case 38: return ItemPropertyImprovedEvasion();
        case 39: return ItemPropertyBonusSpellResistance(param1);
        case 40: return ItemPropertyBonusSavingThrowVsX(param1, param2);
        case 41: return ItemPropertyBonusSavingThrow(param1, param2);
        //case 42: return
        case 43: return ItemPropertyKeen();
        case 44: return ItemPropertyLight(param1, param2); //special index shift*
        case 45: return ItemPropertyMaxRangeStrengthMod(param1);
        //case 46: return
        case 47: return ItemPropertyNoDamage();
        case 48: return ItemPropertyOnHitProps(param1, param2 + (param1 == IP_CONST_ONHIT_LEVELDRAIN), param3); //special index shift
        case 49: return ItemPropertyReducedSavingThrowVsX(param1, param2);
        case 50: return ItemPropertyReducedSavingThrow(param1, param2);
        case 51: return ItemPropertyRegeneration(param1);
        case 52: return ItemPropertySkillBonus(param1, param2);
        case 53: return ItemPropertySpellImmunitySpecific(param1);
        case 54: return ItemPropertySpellImmunitySchool(param1);
        case 55: return ItemPropertyThievesTools(param1);
        case 56: return ItemPropertyAttackBonus(param1);
        case 57: return ItemPropertyAttackBonusVsAlign(param1, param2);
        case 58: return ItemPropertyAttackBonusVsRace(param1, param2);
        case 59: return ItemPropertyAttackBonusVsSAlign(param1, param2);
        case 60: return ItemPropertyAttackPenalty(param1);
        case 61: return ItemPropertyUnlimitedAmmo(param2);
        case 62: return ItemPropertyLimitUseByAlign(param1);
        case 63: return ItemPropertyLimitUseByClass(param1);
        case 64: return ItemPropertyLimitUseByRace(param1);
        case 65: return ItemPropertyLimitUseBySAlign(param1);
        //case 66: return
        case 67: return ItemPropertyVampiricRegeneration(param1);
        //case 68: return
        //case 69: return
        case 70: return ItemPropertyTrap(param1, param2);
        case 71: return ItemPropertyTrueSeeing();
        case 72: return ItemPropertyOnMonsterHitProperties(param1, param2);
        case 73: return ItemPropertyTurnResistance(param1);
        case 74: return ItemPropertyMassiveCritical(param1);
        case 75: return ItemPropertyFreeAction();
        //case 76: return
        case 77: return ItemPropertyMonsterDamage(param1);
        case 78: return ItemPropertyImmunityToSpellLevel(param1); //special index shift*
        case 79: return ItemPropertySpecialWalk(param1);
        case 80: return ItemPropertyHealersKit(param1);
        case 81: return ItemPropertyWeightIncrease(param1);
        case 82: return ItemPropertyOnHitCastSpell(param1, param2+1); //special index shift
        case 83: return ItemPropertyVisualEffect(param1);
        case 84: return ItemPropertyArcaneSpellFailure(param1);
        }
    itemproperty ipRet;
    return ipRet;
    }

//==========================================/
int get_item_inventory_slot(object item, object user)
//==========================================/
    {
    int n = 0;
    while(n < NUM_INVENTORY_SLOTS)
        {
        if(GetItemInSlot(n, user) == item)
            {
            return n;
            }
        n++;
        }

    return -1;
    }

//==========================================/
void equip_item(object item, int equip_slot, object user)
//==========================================/
    {
    effect immobilize = ExtraordinaryEffect(EffectCutsceneImmobilize());
    ApplyEffectToObject(DURATION_TYPE_PERMANENT, immobilize, user);

    //----------------------------------------//
    AssignCommand(user, ActionEquipItem(item, equip_slot));
    RemoveEffect(user, immobilize);
    }

//==========================================/
void disp_delayed_msg(object user, string msg)
//==========================================/
    {
    DelayCommand(INFO_MSG_DELAY, SendMessageToPC(user, c_hlt2(msg)));
    }

//==========================================/
void visual_effect()
//==========================================/
    {
    ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(MOD_VISUAL_EFFECT), EXT_PLACEABLE);
    }

//==========================================/
void clear_script_param()
//==========================================/
    {
    SetLocalInt(FCB_HOST, SCRIPT_PARAM, (~FILTER_F100) & GetLocalInt(FCB_HOST, SCRIPT_PARAM));
    }
