void GlobalObject::_LoadTradeConditions(vt_script::ReadScriptDescriptor &script)
{
    if(!script.DoesTableExist("trade_conditions"))
        return;

    std::vector<uint32> temp;
    script.ReadTableKeys("trade_conditions", temp);

    if(temp.empty())
        return;

    script.OpenTable("trade_conditions");

    for(uint32 i = 0; i < temp.size(); ++i) {
        uint32 key = temp[i];
        uint32 quantity = script.ReadInt(key);

        // Set the trade price
        if (key == 0)
            _trade_price = quantity;
        else // Or the conditions.
            _trade_conditions.push_back(std::pair<uint32, uint32>(key, quantity));
    }

    script.CloseTable(); // trade_conditions

    return;
}
void GlobalObject::_LoadStatusEffects(vt_script::ReadScriptDescriptor &script)
{
    if(!script.DoesTableExist("status_effects"))
        return;

    std::vector<int32> status_effects;
    script.ReadTableKeys("status_effects", status_effects);

    if(status_effects.empty())
        return;

    script.OpenTable("status_effects");

    for(uint32 i = 0; i < status_effects.size(); ++i) {

        int32 key = status_effects[i];
        if(key <= GLOBAL_STATUS_INVALID || key >= GLOBAL_STATUS_TOTAL)
            continue;

        int32 intensity = script.ReadInt(key);
        // Note: The intensity of a status effect can only be positive
        if(intensity <= GLOBAL_INTENSITY_INVALID || intensity >= GLOBAL_INTENSITY_TOTAL)
            continue;

        _status_effects.push_back(std::pair<GLOBAL_STATUS, GLOBAL_INTENSITY>((GLOBAL_STATUS)key, (GLOBAL_INTENSITY)intensity));
    }
    // Make the effects be always presented in the same order.
    std::sort(_status_effects.begin(), _status_effects.end(), CompareStatusEffects);

    script.CloseTable(); // status_effects
}
void GlobalObject::_LoadElementalEffects(vt_script::ReadScriptDescriptor &script)
{
    if(!script.DoesTableExist("elemental_effects"))
        return;

    std::vector<int32> elemental_effects;
    script.ReadTableKeys("elemental_effects", elemental_effects);

    if(elemental_effects.empty())
        return;

    script.OpenTable("elemental_effects");

    for(uint32 i = 0; i < elemental_effects.size(); ++i) {

        int32 key = elemental_effects[i];
        if(key <= GLOBAL_ELEMENTAL_INVALID || key >= GLOBAL_ELEMENTAL_TOTAL)
            continue;

        int32 intensity = script.ReadInt(key);
        if(intensity <= GLOBAL_INTENSITY_INVALID || intensity >= GLOBAL_INTENSITY_TOTAL)
            continue;

        _elemental_effects.push_back(std::pair<GLOBAL_ELEMENTAL, GLOBAL_INTENSITY>((GLOBAL_ELEMENTAL)key, (GLOBAL_INTENSITY)intensity));
    }

    script.CloseTable(); // elemental_effects
}
void GlobalObject::_LoadEquipmentSkills(vt_script::ReadScriptDescriptor &script)
{
    _equipment_skills.clear();
    if(!script.DoesTableExist("equipment_skills"))
        return;

    script.ReadUIntVector("equipment_skills", _equipment_skills);
}
// A helper function reading a lua subtable of 4 float values.
Color ParticleEffect::_ReadColor(vt_script::ReadScriptDescriptor &particle_script,
                                 const std::string &param_name)
{
    std::vector<float> float_vec;
    particle_script.ReadFloatVector(param_name, float_vec);
    if(float_vec.size() < 4) {
        PRINT_WARNING << "Invalid color read in parameter: " << param_name
                      << " for file: " << particle_script.GetFilename() << std::endl;
        return Color();
    }
    Color new_color(float_vec[0], float_vec[1], float_vec[2], float_vec[3]);

    return new_color;
}
void GlobalObject::_LoadStatusEffects(vt_script::ReadScriptDescriptor &script)
{
    if(!script.DoesTableExist("status_effects"))
        return;

    std::vector<int32> status_effects;
    script.ReadTableKeys("status_effects", status_effects);

    if(status_effects.empty())
        return;

    script.OpenTable("status_effects");

    for(uint32 i = 0; i < status_effects.size(); ++i) {

        int32 key = status_effects[i];
        if(key <= GLOBAL_STATUS_INVALID || key >= GLOBAL_STATUS_TOTAL)
            continue;

        int32 intensity = script.ReadInt(key);
        // Note: The intensity of a status effect can only be positive
        if(intensity < GLOBAL_INTENSITY_NEUTRAL || intensity >= GLOBAL_INTENSITY_TOTAL)
            continue;

        // Check whether an opposite effect exists.
        bool effect_replaced = false;
        for (uint32 j = 0; j < _status_effects.size(); ++j) {
            GLOBAL_STATUS opposite_effect = GetOppositeStatusEffect((GLOBAL_STATUS) key);
            if (_status_effects[j].first != opposite_effect)
                continue;

            PRINT_WARNING << "The item (id:" << _id << ") has opposing passive status effects." << std::endl;
            effect_replaced = true;
            break;
        }

        if (effect_replaced)
            continue;

        _status_effects.push_back(std::pair<GLOBAL_STATUS, GLOBAL_INTENSITY>((GLOBAL_STATUS)key, (GLOBAL_INTENSITY)intensity));
    }

    script.CloseTable(); // status_effects
}
void GlobalObject::_LoadObjectData(vt_script::ReadScriptDescriptor &script)
{
    _name = MakeUnicodeString(script.ReadString("name"));
    _description = MakeUnicodeString(script.ReadString("description"));
    _price = script.ReadUInt("standard_price");
    _LoadTradeConditions(script);
    std::string icon_file = script.ReadString("icon");
    if (script.DoesBoolExist("key_item"))
        _is_key_item = script.ReadBool("key_item");
    if(!_icon_image.Load(icon_file)) {
        PRINT_WARNING << "failed to load icon image for item: " << _id << std::endl;

        // try a default icon in that case
        _icon_image.Load("img/icons/battle/default_special.png");
    }
}