//
//  SuperTuxKart - a fun racing game with go-kart
//  Copyright (C) 2006-2015 SuperTuxKart-Team
//
//  This program is free software; you can redistribute it and/or
//  modify it under the terms of the GNU General Public License
//  as published by the Free Software Foundation; either version 3
//  of the License, or (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

#include "karts/abstract_characteristic.hpp"

#include "config/stk_config.hpp"
#include "utils/log.hpp"
#include "utils/interpolation_array.hpp"

#include <cmath>

AbstractCharacteristic::AbstractCharacteristic()
{
}

// ----------------------------------------------------------------------------
/** The process function should change the given value.
 *  The input and output argument is saved in value.
 *  is_set describes if the value is already set or if it's undefined.
 *  The function also has to set is_set if the state changed.
 */
void AbstractCharacteristic::process(CharacteristicType type, Value value,
                                     bool *is_set) const
{
    Log::warn("AbstractCharacteristic", "This type does not do anything");
}   // process

// ----------------------------------------------------------------------------
/** Returns the type of a given characteristic. */
AbstractCharacteristic::ValueType AbstractCharacteristic::getType(
    CharacteristicType type)
{
    switch (type)
    {
    case CHARACTERISTIC_COUNT:
        Log::fatal("AbstractCharacteristic::getType", "Can't get type of COUNT");
        break;
    // Script-generated content generated by tools/create_kart_properties.py getProp1
    // Please don't change the following tag. It will be automatically detected
    // by the script and replace the contained content.
    // To update the code, use tools/update_characteristics.py
    /* <characteristics-start getType> */
    case SUSPENSION_STIFFNESS:
        return TYPE_FLOAT;
    case SUSPENSION_REST:
        return TYPE_FLOAT;
    case SUSPENSION_TRAVEL:
        return TYPE_FLOAT;
    case SUSPENSION_EXP_SPRING_RESPONSE:
        return TYPE_BOOL;
    case SUSPENSION_MAX_FORCE:
        return TYPE_FLOAT;
    case STABILITY_ROLL_INFLUENCE:
        return TYPE_FLOAT;
    case STABILITY_CHASSIS_LINEAR_DAMPING:
        return TYPE_FLOAT;
    case STABILITY_CHASSIS_ANGULAR_DAMPING:
        return TYPE_FLOAT;
    case STABILITY_DOWNWARD_IMPULSE_FACTOR:
        return TYPE_FLOAT;
    case STABILITY_TRACK_CONNECTION_ACCEL:
        return TYPE_FLOAT;
    case STABILITY_ANGULAR_FACTOR:
        return TYPE_FLOAT_VECTOR;
    case STABILITY_SMOOTH_FLYING_IMPULSE:
        return TYPE_FLOAT;
    case TURN_RADIUS:
        return TYPE_INTERPOLATION_ARRAY;
    case TURN_TIME_RESET_STEER:
        return TYPE_FLOAT;
    case TURN_TIME_FULL_STEER:
        return TYPE_INTERPOLATION_ARRAY;
    case ENGINE_POWER:
        return TYPE_FLOAT;
    case ENGINE_MAX_SPEED:
        return TYPE_FLOAT;
    case ENGINE_GENERIC_MAX_SPEED:
        return TYPE_FLOAT;
    case ENGINE_BRAKE_FACTOR:
        return TYPE_FLOAT;
    case ENGINE_BRAKE_TIME_INCREASE:
        return TYPE_FLOAT;
    case ENGINE_MAX_SPEED_REVERSE_RATIO:
        return TYPE_FLOAT;
    case GEAR_SWITCH_RATIO:
        return TYPE_FLOAT_VECTOR;
    case GEAR_POWER_INCREASE:
        return TYPE_FLOAT_VECTOR;
    case MASS:
        return TYPE_FLOAT;
    case WHEELS_DAMPING_RELAXATION:
        return TYPE_FLOAT;
    case WHEELS_DAMPING_COMPRESSION:
        return TYPE_FLOAT;
    case JUMP_ANIMATION_TIME:
        return TYPE_FLOAT;
    case LEAN_MAX:
        return TYPE_FLOAT;
    case LEAN_SPEED:
        return TYPE_FLOAT;
    case ANVIL_DURATION:
        return TYPE_FLOAT;
    case ANVIL_WEIGHT:
        return TYPE_FLOAT;
    case ANVIL_SPEED_FACTOR:
        return TYPE_FLOAT;
    case PARACHUTE_FRICTION:
        return TYPE_FLOAT;
    case PARACHUTE_DURATION:
        return TYPE_FLOAT;
    case PARACHUTE_DURATION_OTHER:
        return TYPE_FLOAT;
    case PARACHUTE_DURATION_RANK_MULT:
        return TYPE_FLOAT;
    case PARACHUTE_DURATION_SPEED_MULT:
        return TYPE_FLOAT;
    case PARACHUTE_LBOUND_FRACTION:
        return TYPE_FLOAT;
    case PARACHUTE_UBOUND_FRACTION:
        return TYPE_FLOAT;
    case PARACHUTE_MAX_SPEED:
        return TYPE_FLOAT;
    case FRICTION_KART_FRICTION:
        return TYPE_FLOAT;
    case BUBBLEGUM_DURATION:
        return TYPE_FLOAT;
    case BUBBLEGUM_SPEED_FRACTION:
        return TYPE_FLOAT;
    case BUBBLEGUM_TORQUE:
        return TYPE_FLOAT;
    case BUBBLEGUM_FADE_IN_TIME:
        return TYPE_FLOAT;
    case BUBBLEGUM_SHIELD_DURATION:
        return TYPE_FLOAT;
    case ZIPPER_DURATION:
        return TYPE_FLOAT;
    case ZIPPER_FORCE:
        return TYPE_FLOAT;
    case ZIPPER_SPEED_GAIN:
        return TYPE_FLOAT;
    case ZIPPER_MAX_SPEED_INCREASE:
        return TYPE_FLOAT;
    case ZIPPER_FADE_OUT_TIME:
        return TYPE_FLOAT;
    case SWATTER_DURATION:
        return TYPE_FLOAT;
    case SWATTER_DISTANCE:
        return TYPE_FLOAT;
    case SWATTER_SQUASH_DURATION:
        return TYPE_FLOAT;
    case SWATTER_SQUASH_SLOWDOWN:
        return TYPE_FLOAT;
    case PLUNGER_BAND_MAX_LENGTH:
        return TYPE_FLOAT;
    case PLUNGER_BAND_FORCE:
        return TYPE_FLOAT;
    case PLUNGER_BAND_DURATION:
        return TYPE_FLOAT;
    case PLUNGER_BAND_SPEED_INCREASE:
        return TYPE_FLOAT;
    case PLUNGER_BAND_FADE_OUT_TIME:
        return TYPE_FLOAT;
    case PLUNGER_IN_FACE_TIME:
        return TYPE_FLOAT;
    case STARTUP_TIME:
        return TYPE_FLOAT_VECTOR;
    case STARTUP_BOOST:
        return TYPE_FLOAT_VECTOR;
    case RESCUE_DURATION:
        return TYPE_FLOAT;
    case RESCUE_VERT_OFFSET:
        return TYPE_FLOAT;
    case RESCUE_HEIGHT:
        return TYPE_FLOAT;
    case EXPLOSION_DURATION:
        return TYPE_FLOAT;
    case EXPLOSION_RADIUS:
        return TYPE_FLOAT;
    case EXPLOSION_INVULNERABILITY_TIME:
        return TYPE_FLOAT;
    case NITRO_DURATION:
        return TYPE_FLOAT;
    case NITRO_ENGINE_FORCE:
        return TYPE_FLOAT;
    case NITRO_ENGINE_MULT:
        return TYPE_FLOAT;
    case NITRO_CONSUMPTION:
        return TYPE_FLOAT;
    case NITRO_SMALL_CONTAINER:
        return TYPE_FLOAT;
    case NITRO_BIG_CONTAINER:
        return TYPE_FLOAT;
    case NITRO_MAX_SPEED_INCREASE:
        return TYPE_FLOAT;
    case NITRO_FADE_OUT_TIME:
        return TYPE_FLOAT;
    case NITRO_MAX:
        return TYPE_FLOAT;
    case SLIPSTREAM_DURATION_FACTOR:
        return TYPE_FLOAT;
    case SLIPSTREAM_BASE_SPEED:
        return TYPE_FLOAT;
    case SLIPSTREAM_LENGTH:
        return TYPE_FLOAT;
    case SLIPSTREAM_WIDTH:
        return TYPE_FLOAT;
    case SLIPSTREAM_INNER_FACTOR:
        return TYPE_FLOAT;
    case SLIPSTREAM_MIN_COLLECT_TIME:
        return TYPE_FLOAT;
    case SLIPSTREAM_MAX_COLLECT_TIME:
        return TYPE_FLOAT;
    case SLIPSTREAM_ADD_POWER:
        return TYPE_FLOAT;
    case SLIPSTREAM_MIN_SPEED:
        return TYPE_FLOAT;
    case SLIPSTREAM_MAX_SPEED_INCREASE:
        return TYPE_FLOAT;
    case SLIPSTREAM_FADE_OUT_TIME:
        return TYPE_FLOAT;
    case SKID_INCREASE:
        return TYPE_FLOAT;
    case SKID_DECREASE:
        return TYPE_FLOAT;
    case SKID_MAX:
        return TYPE_FLOAT;
    case SKID_TIME_TILL_MAX:
        return TYPE_FLOAT;
    case SKID_VISUAL:
        return TYPE_FLOAT;
    case SKID_VISUAL_TIME:
        return TYPE_FLOAT;
    case SKID_REVERT_VISUAL_TIME:
        return TYPE_FLOAT;
    case SKID_MIN_SPEED:
        return TYPE_FLOAT;
    case SKID_TIME_TILL_BONUS:
        return TYPE_FLOAT_VECTOR;
    case SKID_BONUS_SPEED:
        return TYPE_FLOAT_VECTOR;
    case SKID_BONUS_TIME:
        return TYPE_FLOAT_VECTOR;
    case SKID_BONUS_FORCE:
        return TYPE_FLOAT_VECTOR;
    case SKID_PHYSICAL_JUMP_TIME:
        return TYPE_FLOAT;
    case SKID_GRAPHICAL_JUMP_TIME:
        return TYPE_FLOAT;
    case SKID_POST_SKID_ROTATE_FACTOR:
        return TYPE_FLOAT;
    case SKID_REDUCE_TURN_MIN:
        return TYPE_FLOAT;
    case SKID_REDUCE_TURN_MAX:
        return TYPE_FLOAT;
    case SKID_ENABLED:
        return TYPE_BOOL;

    /* <characteristics-end getType> */
    }   // switch (type)
    Log::fatal("AbstractCharacteristic::getType", "Unknown type");
    return TYPE_FLOAT;
}   // getType

// ----------------------------------------------------------------------------
/** Converts the enum value to a string. */
std::string AbstractCharacteristic::getName(CharacteristicType type)
{
    switch (type)
    {
    case CHARACTERISTIC_COUNT:
        return "CHARACTERISTIC_COUNT";
    // Script-generated content generated by tools/create_kart_properties.py getProp2
    // Please don't change the following tag. It will be automatically detected
    // by the script and replace the contained content.
    // To update the code, use tools/update_characteristics.py
    /* <characteristics-start getName> */
    case SUSPENSION_STIFFNESS:
        return "SUSPENSION_STIFFNESS";
    case SUSPENSION_REST:
        return "SUSPENSION_REST";
    case SUSPENSION_TRAVEL:
        return "SUSPENSION_TRAVEL";
    case SUSPENSION_EXP_SPRING_RESPONSE:
        return "SUSPENSION_EXP_SPRING_RESPONSE";
    case SUSPENSION_MAX_FORCE:
        return "SUSPENSION_MAX_FORCE";
    case STABILITY_ROLL_INFLUENCE:
        return "STABILITY_ROLL_INFLUENCE";
    case STABILITY_CHASSIS_LINEAR_DAMPING:
        return "STABILITY_CHASSIS_LINEAR_DAMPING";
    case STABILITY_CHASSIS_ANGULAR_DAMPING:
        return "STABILITY_CHASSIS_ANGULAR_DAMPING";
    case STABILITY_DOWNWARD_IMPULSE_FACTOR:
        return "STABILITY_DOWNWARD_IMPULSE_FACTOR";
    case STABILITY_TRACK_CONNECTION_ACCEL:
        return "STABILITY_TRACK_CONNECTION_ACCEL";
    case STABILITY_ANGULAR_FACTOR:
        return "STABILITY_ANGULAR_FACTOR";
    case STABILITY_SMOOTH_FLYING_IMPULSE:
        return "STABILITY_SMOOTH_FLYING_IMPULSE";
    case TURN_RADIUS:
        return "TURN_RADIUS";
    case TURN_TIME_RESET_STEER:
        return "TURN_TIME_RESET_STEER";
    case TURN_TIME_FULL_STEER:
        return "TURN_TIME_FULL_STEER";
    case ENGINE_POWER:
        return "ENGINE_POWER";
    case ENGINE_MAX_SPEED:
        return "ENGINE_MAX_SPEED";
    case ENGINE_GENERIC_MAX_SPEED:
        return "ENGINE_GENERIC_MAX_SPEED";
    case ENGINE_BRAKE_FACTOR:
        return "ENGINE_BRAKE_FACTOR";
    case ENGINE_BRAKE_TIME_INCREASE:
        return "ENGINE_BRAKE_TIME_INCREASE";
    case ENGINE_MAX_SPEED_REVERSE_RATIO:
        return "ENGINE_MAX_SPEED_REVERSE_RATIO";
    case GEAR_SWITCH_RATIO:
        return "GEAR_SWITCH_RATIO";
    case GEAR_POWER_INCREASE:
        return "GEAR_POWER_INCREASE";
    case MASS:
        return "MASS";
    case WHEELS_DAMPING_RELAXATION:
        return "WHEELS_DAMPING_RELAXATION";
    case WHEELS_DAMPING_COMPRESSION:
        return "WHEELS_DAMPING_COMPRESSION";
    case JUMP_ANIMATION_TIME:
        return "JUMP_ANIMATION_TIME";
    case LEAN_MAX:
        return "LEAN_MAX";
    case LEAN_SPEED:
        return "LEAN_SPEED";
    case ANVIL_DURATION:
        return "ANVIL_DURATION";
    case ANVIL_WEIGHT:
        return "ANVIL_WEIGHT";
    case ANVIL_SPEED_FACTOR:
        return "ANVIL_SPEED_FACTOR";
    case PARACHUTE_FRICTION:
        return "PARACHUTE_FRICTION";
    case PARACHUTE_DURATION:
        return "PARACHUTE_DURATION";
    case PARACHUTE_DURATION_OTHER:
        return "PARACHUTE_DURATION_OTHER";
    case PARACHUTE_DURATION_RANK_MULT:
        return "PARACHUTE_DURATION_RANK_MULT";
    case PARACHUTE_DURATION_SPEED_MULT:
        return "PARACHUTE_DURATION_SPEED_MULT";
    case PARACHUTE_LBOUND_FRACTION:
        return "PARACHUTE_LBOUND_FRACTION";
    case PARACHUTE_UBOUND_FRACTION:
        return "PARACHUTE_UBOUND_FRACTION";
    case PARACHUTE_MAX_SPEED:
        return "PARACHUTE_MAX_SPEED";
    case FRICTION_KART_FRICTION:
        return "FRICTION_KART_FRICTION";
    case BUBBLEGUM_DURATION:
        return "BUBBLEGUM_DURATION";
    case BUBBLEGUM_SPEED_FRACTION:
        return "BUBBLEGUM_SPEED_FRACTION";
    case BUBBLEGUM_TORQUE:
        return "BUBBLEGUM_TORQUE";
    case BUBBLEGUM_FADE_IN_TIME:
        return "BUBBLEGUM_FADE_IN_TIME";
    case BUBBLEGUM_SHIELD_DURATION:
        return "BUBBLEGUM_SHIELD_DURATION";
    case ZIPPER_DURATION:
        return "ZIPPER_DURATION";
    case ZIPPER_FORCE:
        return "ZIPPER_FORCE";
    case ZIPPER_SPEED_GAIN:
        return "ZIPPER_SPEED_GAIN";
    case ZIPPER_MAX_SPEED_INCREASE:
        return "ZIPPER_MAX_SPEED_INCREASE";
    case ZIPPER_FADE_OUT_TIME:
        return "ZIPPER_FADE_OUT_TIME";
    case SWATTER_DURATION:
        return "SWATTER_DURATION";
    case SWATTER_DISTANCE:
        return "SWATTER_DISTANCE";
    case SWATTER_SQUASH_DURATION:
        return "SWATTER_SQUASH_DURATION";
    case SWATTER_SQUASH_SLOWDOWN:
        return "SWATTER_SQUASH_SLOWDOWN";
    case PLUNGER_BAND_MAX_LENGTH:
        return "PLUNGER_BAND_MAX_LENGTH";
    case PLUNGER_BAND_FORCE:
        return "PLUNGER_BAND_FORCE";
    case PLUNGER_BAND_DURATION:
        return "PLUNGER_BAND_DURATION";
    case PLUNGER_BAND_SPEED_INCREASE:
        return "PLUNGER_BAND_SPEED_INCREASE";
    case PLUNGER_BAND_FADE_OUT_TIME:
        return "PLUNGER_BAND_FADE_OUT_TIME";
    case PLUNGER_IN_FACE_TIME:
        return "PLUNGER_IN_FACE_TIME";
    case STARTUP_TIME:
        return "STARTUP_TIME";
    case STARTUP_BOOST:
        return "STARTUP_BOOST";
    case RESCUE_DURATION:
        return "RESCUE_DURATION";
    case RESCUE_VERT_OFFSET:
        return "RESCUE_VERT_OFFSET";
    case RESCUE_HEIGHT:
        return "RESCUE_HEIGHT";
    case EXPLOSION_DURATION:
        return "EXPLOSION_DURATION";
    case EXPLOSION_RADIUS:
        return "EXPLOSION_RADIUS";
    case EXPLOSION_INVULNERABILITY_TIME:
        return "EXPLOSION_INVULNERABILITY_TIME";
    case NITRO_DURATION:
        return "NITRO_DURATION";
    case NITRO_ENGINE_FORCE:
        return "NITRO_ENGINE_FORCE";
    case NITRO_ENGINE_MULT:
        return "NITRO_ENGINE_MULT";
    case NITRO_CONSUMPTION:
        return "NITRO_CONSUMPTION";
    case NITRO_SMALL_CONTAINER:
        return "NITRO_SMALL_CONTAINER";
    case NITRO_BIG_CONTAINER:
        return "NITRO_BIG_CONTAINER";
    case NITRO_MAX_SPEED_INCREASE:
        return "NITRO_MAX_SPEED_INCREASE";
    case NITRO_FADE_OUT_TIME:
        return "NITRO_FADE_OUT_TIME";
    case NITRO_MAX:
        return "NITRO_MAX";
    case SLIPSTREAM_DURATION_FACTOR:
        return "SLIPSTREAM_DURATION_FACTOR";
    case SLIPSTREAM_BASE_SPEED:
        return "SLIPSTREAM_BASE_SPEED";
    case SLIPSTREAM_LENGTH:
        return "SLIPSTREAM_LENGTH";
    case SLIPSTREAM_WIDTH:
        return "SLIPSTREAM_WIDTH";
    case SLIPSTREAM_INNER_FACTOR:
        return "SLIPSTREAM_INNER_FACTOR";
    case SLIPSTREAM_MIN_COLLECT_TIME:
        return "SLIPSTREAM_MIN_COLLECT_TIME";
    case SLIPSTREAM_MAX_COLLECT_TIME:
        return "SLIPSTREAM_MAX_COLLECT_TIME";
    case SLIPSTREAM_ADD_POWER:
        return "SLIPSTREAM_ADD_POWER";
    case SLIPSTREAM_MIN_SPEED:
        return "SLIPSTREAM_MIN_SPEED";
    case SLIPSTREAM_MAX_SPEED_INCREASE:
        return "SLIPSTREAM_MAX_SPEED_INCREASE";
    case SLIPSTREAM_FADE_OUT_TIME:
        return "SLIPSTREAM_FADE_OUT_TIME";
    case SKID_INCREASE:
        return "SKID_INCREASE";
    case SKID_DECREASE:
        return "SKID_DECREASE";
    case SKID_MAX:
        return "SKID_MAX";
    case SKID_TIME_TILL_MAX:
        return "SKID_TIME_TILL_MAX";
    case SKID_VISUAL:
        return "SKID_VISUAL";
    case SKID_VISUAL_TIME:
        return "SKID_VISUAL_TIME";
    case SKID_REVERT_VISUAL_TIME:
        return "SKID_REVERT_VISUAL_TIME";
    case SKID_MIN_SPEED:
        return "SKID_MIN_SPEED";
    case SKID_TIME_TILL_BONUS:
        return "SKID_TIME_TILL_BONUS";
    case SKID_BONUS_SPEED:
        return "SKID_BONUS_SPEED";
    case SKID_BONUS_TIME:
        return "SKID_BONUS_TIME";
    case SKID_BONUS_FORCE:
        return "SKID_BONUS_FORCE";
    case SKID_PHYSICAL_JUMP_TIME:
        return "SKID_PHYSICAL_JUMP_TIME";
    case SKID_GRAPHICAL_JUMP_TIME:
        return "SKID_GRAPHICAL_JUMP_TIME";
    case SKID_POST_SKID_ROTATE_FACTOR:
        return "SKID_POST_SKID_ROTATE_FACTOR";
    case SKID_REDUCE_TURN_MIN:
        return "SKID_REDUCE_TURN_MIN";
    case SKID_REDUCE_TURN_MAX:
        return "SKID_REDUCE_TURN_MAX";
    case SKID_ENABLED:
        return "SKID_ENABLED";

    /* <characteristics-end getName> */
    }   // switch (type)
    Log::error("AbstractCharacteristic::getName", "Unknown type");
    return "Unknown type";
}   // getName

// Script-generated content generated by tools/create_kart_properties.py defs
// Please don't change the following tag. It will be automatically detected
// by the script and replace the contained content.
// To update the code, use tools/update_characteristics.py
/* <characteristics-start acgetter> */
// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSuspensionStiffness() const
{
    float result;
    bool is_set = false;
    process(SUSPENSION_STIFFNESS, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SUSPENSION_STIFFNESS).c_str());
    return result;
}  // getSuspensionStiffness

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSuspensionRest() const
{
    float result;
    bool is_set = false;
    process(SUSPENSION_REST, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SUSPENSION_REST).c_str());
    return result;
}  // getSuspensionRest

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSuspensionTravel() const
{
    float result;
    bool is_set = false;
    process(SUSPENSION_TRAVEL, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SUSPENSION_TRAVEL).c_str());
    return result;
}  // getSuspensionTravel

// ----------------------------------------------------------------------------
bool AbstractCharacteristic::getSuspensionExpSpringResponse() const
{
    bool result;
    bool is_set = false;
    process(SUSPENSION_EXP_SPRING_RESPONSE, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SUSPENSION_EXP_SPRING_RESPONSE).c_str());
    return result;
}  // getSuspensionExpSpringResponse

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSuspensionMaxForce() const
{
    float result;
    bool is_set = false;
    process(SUSPENSION_MAX_FORCE, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SUSPENSION_MAX_FORCE).c_str());
    return result;
}  // getSuspensionMaxForce

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getStabilityRollInfluence() const
{
    float result;
    bool is_set = false;
    process(STABILITY_ROLL_INFLUENCE, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(STABILITY_ROLL_INFLUENCE).c_str());
    return result;
}  // getStabilityRollInfluence

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getStabilityChassisLinearDamping() const
{
    float result;
    bool is_set = false;
    process(STABILITY_CHASSIS_LINEAR_DAMPING, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(STABILITY_CHASSIS_LINEAR_DAMPING).c_str());
    return result;
}  // getStabilityChassisLinearDamping

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getStabilityChassisAngularDamping() const
{
    float result;
    bool is_set = false;
    process(STABILITY_CHASSIS_ANGULAR_DAMPING, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(STABILITY_CHASSIS_ANGULAR_DAMPING).c_str());
    return result;
}  // getStabilityChassisAngularDamping

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getStabilityDownwardImpulseFactor() const
{
    float result;
    bool is_set = false;
    process(STABILITY_DOWNWARD_IMPULSE_FACTOR, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(STABILITY_DOWNWARD_IMPULSE_FACTOR).c_str());
    return result;
}  // getStabilityDownwardImpulseFactor

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getStabilityTrackConnectionAccel() const
{
    float result;
    bool is_set = false;
    process(STABILITY_TRACK_CONNECTION_ACCEL, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(STABILITY_TRACK_CONNECTION_ACCEL).c_str());
    return result;
}  // getStabilityTrackConnectionAccel

// ----------------------------------------------------------------------------
std::vector<float> AbstractCharacteristic::getStabilityAngularFactor() const
{
    std::vector<float> result;
    bool is_set = false;
    process(STABILITY_ANGULAR_FACTOR, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(STABILITY_ANGULAR_FACTOR).c_str());
    return result;
}  // getStabilityAngularFactor

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getStabilitySmoothFlyingImpulse() const
{
    float result;
    bool is_set = false;
    process(STABILITY_SMOOTH_FLYING_IMPULSE, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(STABILITY_SMOOTH_FLYING_IMPULSE).c_str());
    return result;
}  // getStabilitySmoothFlyingImpulse

// ----------------------------------------------------------------------------
InterpolationArray AbstractCharacteristic::getTurnRadius() const
{
    InterpolationArray result;
    bool is_set = false;
    process(TURN_RADIUS, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(TURN_RADIUS).c_str());
    return result;
}  // getTurnRadius

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getTurnTimeResetSteer() const
{
    float result;
    bool is_set = false;
    process(TURN_TIME_RESET_STEER, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(TURN_TIME_RESET_STEER).c_str());
    return result;
}  // getTurnTimeResetSteer

// ----------------------------------------------------------------------------
InterpolationArray AbstractCharacteristic::getTurnTimeFullSteer() const
{
    InterpolationArray result;
    bool is_set = false;
    process(TURN_TIME_FULL_STEER, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(TURN_TIME_FULL_STEER).c_str());
    return result;
}  // getTurnTimeFullSteer

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getEnginePower() const
{
    float result;
    bool is_set = false;
    process(ENGINE_POWER, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(ENGINE_POWER).c_str());
    return result;
}  // getEnginePower

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getEngineMaxSpeed() const
{
    float result;
    bool is_set = false;
    process(ENGINE_MAX_SPEED, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(ENGINE_MAX_SPEED).c_str());
    return result;
}  // getEngineMaxSpeed

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getEngineGenericMaxSpeed() const
{
    float result;
    bool is_set = false;
    process(ENGINE_GENERIC_MAX_SPEED, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(ENGINE_GENERIC_MAX_SPEED).c_str());
    return result;
}  // getEngineGenericMaxSpeed

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getEngineBrakeFactor() const
{
    float result;
    bool is_set = false;
    process(ENGINE_BRAKE_FACTOR, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(ENGINE_BRAKE_FACTOR).c_str());
    return result;
}  // getEngineBrakeFactor

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getEngineBrakeTimeIncrease() const
{
    float result;
    bool is_set = false;
    process(ENGINE_BRAKE_TIME_INCREASE, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(ENGINE_BRAKE_TIME_INCREASE).c_str());
    return result;
}  // getEngineBrakeTimeIncrease

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getEngineMaxSpeedReverseRatio() const
{
    float result;
    bool is_set = false;
    process(ENGINE_MAX_SPEED_REVERSE_RATIO, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(ENGINE_MAX_SPEED_REVERSE_RATIO).c_str());
    return result;
}  // getEngineMaxSpeedReverseRatio

// ----------------------------------------------------------------------------
std::vector<float> AbstractCharacteristic::getGearSwitchRatio() const
{
    std::vector<float> result;
    bool is_set = false;
    process(GEAR_SWITCH_RATIO, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(GEAR_SWITCH_RATIO).c_str());
    return result;
}  // getGearSwitchRatio

// ----------------------------------------------------------------------------
std::vector<float> AbstractCharacteristic::getGearPowerIncrease() const
{
    std::vector<float> result;
    bool is_set = false;
    process(GEAR_POWER_INCREASE, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(GEAR_POWER_INCREASE).c_str());
    return result;
}  // getGearPowerIncrease

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getMass() const
{
    float result;
    bool is_set = false;
    process(MASS, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(MASS).c_str());
    return result;
}  // getMass

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getWheelsDampingRelaxation() const
{
    float result;
    bool is_set = false;
    process(WHEELS_DAMPING_RELAXATION, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(WHEELS_DAMPING_RELAXATION).c_str());
    return result;
}  // getWheelsDampingRelaxation

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getWheelsDampingCompression() const
{
    float result;
    bool is_set = false;
    process(WHEELS_DAMPING_COMPRESSION, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(WHEELS_DAMPING_COMPRESSION).c_str());
    return result;
}  // getWheelsDampingCompression

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getJumpAnimationTime() const
{
    float result;
    bool is_set = false;
    process(JUMP_ANIMATION_TIME, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(JUMP_ANIMATION_TIME).c_str());
    return result;
}  // getJumpAnimationTime

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getLeanMax() const
{
    float result;
    bool is_set = false;
    process(LEAN_MAX, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(LEAN_MAX).c_str());
    return result;
}  // getLeanMax

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getLeanSpeed() const
{
    float result;
    bool is_set = false;
    process(LEAN_SPEED, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(LEAN_SPEED).c_str());
    return result;
}  // getLeanSpeed

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getAnvilDuration() const
{
    float result;
    bool is_set = false;
    process(ANVIL_DURATION, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(ANVIL_DURATION).c_str());
    return result;
}  // getAnvilDuration

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getAnvilWeight() const
{
    float result;
    bool is_set = false;
    process(ANVIL_WEIGHT, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(ANVIL_WEIGHT).c_str());
    return result;
}  // getAnvilWeight

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getAnvilSpeedFactor() const
{
    float result;
    bool is_set = false;
    process(ANVIL_SPEED_FACTOR, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(ANVIL_SPEED_FACTOR).c_str());
    return result;
}  // getAnvilSpeedFactor

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getParachuteFriction() const
{
    float result;
    bool is_set = false;
    process(PARACHUTE_FRICTION, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(PARACHUTE_FRICTION).c_str());
    return result;
}  // getParachuteFriction

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getParachuteDuration() const
{
    float result;
    bool is_set = false;
    process(PARACHUTE_DURATION, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(PARACHUTE_DURATION).c_str());
    return result;
}  // getParachuteDuration

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getParachuteDurationOther() const
{
    float result;
    bool is_set = false;
    process(PARACHUTE_DURATION_OTHER, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(PARACHUTE_DURATION_OTHER).c_str());
    return result;
}  // getParachuteDurationOther

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getParachuteDurationRankMult() const
{
    float result;
    bool is_set = false;
    process(PARACHUTE_DURATION_RANK_MULT, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(PARACHUTE_DURATION_RANK_MULT).c_str());
    return result;
}  // getParachuteDurationRankMult

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getParachuteDurationSpeedMult() const
{
    float result;
    bool is_set = false;
    process(PARACHUTE_DURATION_SPEED_MULT, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(PARACHUTE_DURATION_SPEED_MULT).c_str());
    return result;
}  // getParachuteDurationSpeedMult

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getParachuteLboundFraction() const
{
    float result;
    bool is_set = false;
    process(PARACHUTE_LBOUND_FRACTION, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(PARACHUTE_LBOUND_FRACTION).c_str());
    return result;
}  // getParachuteLboundFraction

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getParachuteUboundFraction() const
{
    float result;
    bool is_set = false;
    process(PARACHUTE_UBOUND_FRACTION, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(PARACHUTE_UBOUND_FRACTION).c_str());
    return result;
}  // getParachuteUboundFraction

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getParachuteMaxSpeed() const
{
    float result;
    bool is_set = false;
    process(PARACHUTE_MAX_SPEED, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(PARACHUTE_MAX_SPEED).c_str());
    return result;
}  // getParachuteMaxSpeed

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getFrictionKartFriction() const
{
    float result;
    bool is_set = false;
    process(FRICTION_KART_FRICTION, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(FRICTION_KART_FRICTION).c_str());
    return result;
}  // getFrictionKartFriction

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getBubblegumDuration() const
{
    float result;
    bool is_set = false;
    process(BUBBLEGUM_DURATION, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(BUBBLEGUM_DURATION).c_str());
    return result;
}  // getBubblegumDuration

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getBubblegumSpeedFraction() const
{
    float result;
    bool is_set = false;
    process(BUBBLEGUM_SPEED_FRACTION, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(BUBBLEGUM_SPEED_FRACTION).c_str());
    return result;
}  // getBubblegumSpeedFraction

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getBubblegumTorque() const
{
    float result;
    bool is_set = false;
    process(BUBBLEGUM_TORQUE, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(BUBBLEGUM_TORQUE).c_str());
    return result;
}  // getBubblegumTorque

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getBubblegumFadeInTime() const
{
    float result;
    bool is_set = false;
    process(BUBBLEGUM_FADE_IN_TIME, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(BUBBLEGUM_FADE_IN_TIME).c_str());
    return result;
}  // getBubblegumFadeInTime

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getBubblegumShieldDuration() const
{
    float result;
    bool is_set = false;
    process(BUBBLEGUM_SHIELD_DURATION, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(BUBBLEGUM_SHIELD_DURATION).c_str());
    return result;
}  // getBubblegumShieldDuration

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getZipperDuration() const
{
    float result;
    bool is_set = false;
    process(ZIPPER_DURATION, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(ZIPPER_DURATION).c_str());
    return result;
}  // getZipperDuration

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getZipperForce() const
{
    float result;
    bool is_set = false;
    process(ZIPPER_FORCE, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(ZIPPER_FORCE).c_str());
    return result;
}  // getZipperForce

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getZipperSpeedGain() const
{
    float result;
    bool is_set = false;
    process(ZIPPER_SPEED_GAIN, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(ZIPPER_SPEED_GAIN).c_str());
    return result;
}  // getZipperSpeedGain

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getZipperMaxSpeedIncrease() const
{
    float result;
    bool is_set = false;
    process(ZIPPER_MAX_SPEED_INCREASE, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(ZIPPER_MAX_SPEED_INCREASE).c_str());
    return result;
}  // getZipperMaxSpeedIncrease

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getZipperFadeOutTime() const
{
    float result;
    bool is_set = false;
    process(ZIPPER_FADE_OUT_TIME, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(ZIPPER_FADE_OUT_TIME).c_str());
    return result;
}  // getZipperFadeOutTime

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSwatterDuration() const
{
    float result;
    bool is_set = false;
    process(SWATTER_DURATION, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SWATTER_DURATION).c_str());
    return result;
}  // getSwatterDuration

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSwatterDistance() const
{
    float result;
    bool is_set = false;
    process(SWATTER_DISTANCE, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SWATTER_DISTANCE).c_str());
    return result;
}  // getSwatterDistance

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSwatterSquashDuration() const
{
    float result;
    bool is_set = false;
    process(SWATTER_SQUASH_DURATION, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SWATTER_SQUASH_DURATION).c_str());
    return result;
}  // getSwatterSquashDuration

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSwatterSquashSlowdown() const
{
    float result;
    bool is_set = false;
    process(SWATTER_SQUASH_SLOWDOWN, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SWATTER_SQUASH_SLOWDOWN).c_str());
    return result;
}  // getSwatterSquashSlowdown

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getPlungerBandMaxLength() const
{
    float result;
    bool is_set = false;
    process(PLUNGER_BAND_MAX_LENGTH, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(PLUNGER_BAND_MAX_LENGTH).c_str());
    return result;
}  // getPlungerBandMaxLength

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getPlungerBandForce() const
{
    float result;
    bool is_set = false;
    process(PLUNGER_BAND_FORCE, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(PLUNGER_BAND_FORCE).c_str());
    return result;
}  // getPlungerBandForce

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getPlungerBandDuration() const
{
    float result;
    bool is_set = false;
    process(PLUNGER_BAND_DURATION, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(PLUNGER_BAND_DURATION).c_str());
    return result;
}  // getPlungerBandDuration

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getPlungerBandSpeedIncrease() const
{
    float result;
    bool is_set = false;
    process(PLUNGER_BAND_SPEED_INCREASE, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(PLUNGER_BAND_SPEED_INCREASE).c_str());
    return result;
}  // getPlungerBandSpeedIncrease

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getPlungerBandFadeOutTime() const
{
    float result;
    bool is_set = false;
    process(PLUNGER_BAND_FADE_OUT_TIME, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(PLUNGER_BAND_FADE_OUT_TIME).c_str());
    return result;
}  // getPlungerBandFadeOutTime

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getPlungerInFaceTime() const
{
    float result;
    bool is_set = false;
    process(PLUNGER_IN_FACE_TIME, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(PLUNGER_IN_FACE_TIME).c_str());
    return result;
}  // getPlungerInFaceTime

// ----------------------------------------------------------------------------
std::vector<float> AbstractCharacteristic::getStartupTime() const
{
    std::vector<float> result;
    bool is_set = false;
    process(STARTUP_TIME, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(STARTUP_TIME).c_str());
    return result;
}  // getStartupTime

// ----------------------------------------------------------------------------
std::vector<float> AbstractCharacteristic::getStartupBoost() const
{
    std::vector<float> result;
    bool is_set = false;
    process(STARTUP_BOOST, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(STARTUP_BOOST).c_str());
    return result;
}  // getStartupBoost

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getRescueDuration() const
{
    float result;
    bool is_set = false;
    process(RESCUE_DURATION, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(RESCUE_DURATION).c_str());
    return result;
}  // getRescueDuration

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getRescueVertOffset() const
{
    float result;
    bool is_set = false;
    process(RESCUE_VERT_OFFSET, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(RESCUE_VERT_OFFSET).c_str());
    return result;
}  // getRescueVertOffset

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getRescueHeight() const
{
    float result;
    bool is_set = false;
    process(RESCUE_HEIGHT, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(RESCUE_HEIGHT).c_str());
    return result;
}  // getRescueHeight

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getExplosionDuration() const
{
    float result;
    bool is_set = false;
    process(EXPLOSION_DURATION, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(EXPLOSION_DURATION).c_str());
    return result;
}  // getExplosionDuration

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getExplosionRadius() const
{
    float result;
    bool is_set = false;
    process(EXPLOSION_RADIUS, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(EXPLOSION_RADIUS).c_str());
    return result;
}  // getExplosionRadius

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getExplosionInvulnerabilityTime() const
{
    float result;
    bool is_set = false;
    process(EXPLOSION_INVULNERABILITY_TIME, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(EXPLOSION_INVULNERABILITY_TIME).c_str());
    return result;
}  // getExplosionInvulnerabilityTime

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getNitroDuration() const
{
    float result;
    bool is_set = false;
    process(NITRO_DURATION, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(NITRO_DURATION).c_str());
    return result;
}  // getNitroDuration

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getNitroEngineForce() const
{
    float result;
    bool is_set = false;
    process(NITRO_ENGINE_FORCE, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(NITRO_ENGINE_FORCE).c_str());
    return result;
}  // getNitroEngineForce

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getNitroEngineMult() const
{
    float result;
    bool is_set = false;
    process(NITRO_ENGINE_MULT, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(NITRO_ENGINE_MULT).c_str());
    return result;
}  // getNitroEngineMult

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getNitroConsumption() const
{
    float result;
    bool is_set = false;
    process(NITRO_CONSUMPTION, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(NITRO_CONSUMPTION).c_str());
    return result;
}  // getNitroConsumption

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getNitroSmallContainer() const
{
    float result;
    bool is_set = false;
    process(NITRO_SMALL_CONTAINER, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(NITRO_SMALL_CONTAINER).c_str());
    return result;
}  // getNitroSmallContainer

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getNitroBigContainer() const
{
    float result;
    bool is_set = false;
    process(NITRO_BIG_CONTAINER, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(NITRO_BIG_CONTAINER).c_str());
    return result;
}  // getNitroBigContainer

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getNitroMaxSpeedIncrease() const
{
    float result;
    bool is_set = false;
    process(NITRO_MAX_SPEED_INCREASE, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(NITRO_MAX_SPEED_INCREASE).c_str());
    return result;
}  // getNitroMaxSpeedIncrease

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getNitroFadeOutTime() const
{
    float result;
    bool is_set = false;
    process(NITRO_FADE_OUT_TIME, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(NITRO_FADE_OUT_TIME).c_str());
    return result;
}  // getNitroFadeOutTime

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getNitroMax() const
{
    float result;
    bool is_set = false;
    process(NITRO_MAX, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(NITRO_MAX).c_str());
    return result;
}  // getNitroMax

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSlipstreamDurationFactor() const
{
    float result;
    bool is_set = false;
    process(SLIPSTREAM_DURATION_FACTOR, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SLIPSTREAM_DURATION_FACTOR).c_str());
    return result;
}  // getSlipstreamDurationFactor

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSlipstreamBaseSpeed() const
{
    float result;
    bool is_set = false;
    process(SLIPSTREAM_BASE_SPEED, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SLIPSTREAM_BASE_SPEED).c_str());
    return result;
}  // getSlipstreamBaseSpeed

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSlipstreamLength() const
{
    float result;
    bool is_set = false;
    process(SLIPSTREAM_LENGTH, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SLIPSTREAM_LENGTH).c_str());
    return result;
}  // getSlipstreamLength

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSlipstreamWidth() const
{
    float result;
    bool is_set = false;
    process(SLIPSTREAM_WIDTH, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SLIPSTREAM_WIDTH).c_str());
    return result;
}  // getSlipstreamWidth

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSlipstreamInnerFactor() const
{
    float result;
    bool is_set = false;
    process(SLIPSTREAM_INNER_FACTOR, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SLIPSTREAM_INNER_FACTOR).c_str());
    return result;
}  // getSlipstreamInnerFactor

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSlipstreamMinCollectTime() const
{
    float result;
    bool is_set = false;
    process(SLIPSTREAM_MIN_COLLECT_TIME, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SLIPSTREAM_MIN_COLLECT_TIME).c_str());
    return result;
}  // getSlipstreamMinCollectTime

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSlipstreamMaxCollectTime() const
{
    float result;
    bool is_set = false;
    process(SLIPSTREAM_MAX_COLLECT_TIME, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SLIPSTREAM_MAX_COLLECT_TIME).c_str());
    return result;
}  // getSlipstreamMaxCollectTime

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSlipstreamAddPower() const
{
    float result;
    bool is_set = false;
    process(SLIPSTREAM_ADD_POWER, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SLIPSTREAM_ADD_POWER).c_str());
    return result;
}  // getSlipstreamAddPower

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSlipstreamMinSpeed() const
{
    float result;
    bool is_set = false;
    process(SLIPSTREAM_MIN_SPEED, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SLIPSTREAM_MIN_SPEED).c_str());
    return result;
}  // getSlipstreamMinSpeed

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSlipstreamMaxSpeedIncrease() const
{
    float result;
    bool is_set = false;
    process(SLIPSTREAM_MAX_SPEED_INCREASE, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SLIPSTREAM_MAX_SPEED_INCREASE).c_str());
    return result;
}  // getSlipstreamMaxSpeedIncrease

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSlipstreamFadeOutTime() const
{
    float result;
    bool is_set = false;
    process(SLIPSTREAM_FADE_OUT_TIME, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SLIPSTREAM_FADE_OUT_TIME).c_str());
    return result;
}  // getSlipstreamFadeOutTime

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSkidIncrease() const
{
    float result;
    bool is_set = false;
    process(SKID_INCREASE, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SKID_INCREASE).c_str());
    return result;
}  // getSkidIncrease

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSkidDecrease() const
{
    float result;
    bool is_set = false;
    process(SKID_DECREASE, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SKID_DECREASE).c_str());
    return result;
}  // getSkidDecrease

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSkidMax() const
{
    float result;
    bool is_set = false;
    process(SKID_MAX, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SKID_MAX).c_str());
    return result;
}  // getSkidMax

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSkidTimeTillMax() const
{
    float result;
    bool is_set = false;
    process(SKID_TIME_TILL_MAX, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SKID_TIME_TILL_MAX).c_str());
    return result;
}  // getSkidTimeTillMax

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSkidVisual() const
{
    float result;
    bool is_set = false;
    process(SKID_VISUAL, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SKID_VISUAL).c_str());
    return result;
}  // getSkidVisual

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSkidVisualTime() const
{
    float result;
    bool is_set = false;
    process(SKID_VISUAL_TIME, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SKID_VISUAL_TIME).c_str());
    return result;
}  // getSkidVisualTime

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSkidRevertVisualTime() const
{
    float result;
    bool is_set = false;
    process(SKID_REVERT_VISUAL_TIME, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SKID_REVERT_VISUAL_TIME).c_str());
    return result;
}  // getSkidRevertVisualTime

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSkidMinSpeed() const
{
    float result;
    bool is_set = false;
    process(SKID_MIN_SPEED, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SKID_MIN_SPEED).c_str());
    return result;
}  // getSkidMinSpeed

// ----------------------------------------------------------------------------
std::vector<float> AbstractCharacteristic::getSkidTimeTillBonus() const
{
    std::vector<float> result;
    bool is_set = false;
    process(SKID_TIME_TILL_BONUS, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SKID_TIME_TILL_BONUS).c_str());
    return result;
}  // getSkidTimeTillBonus

// ----------------------------------------------------------------------------
std::vector<float> AbstractCharacteristic::getSkidBonusSpeed() const
{
    std::vector<float> result;
    bool is_set = false;
    process(SKID_BONUS_SPEED, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SKID_BONUS_SPEED).c_str());
    return result;
}  // getSkidBonusSpeed

// ----------------------------------------------------------------------------
std::vector<float> AbstractCharacteristic::getSkidBonusTime() const
{
    std::vector<float> result;
    bool is_set = false;
    process(SKID_BONUS_TIME, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SKID_BONUS_TIME).c_str());
    return result;
}  // getSkidBonusTime

// ----------------------------------------------------------------------------
std::vector<float> AbstractCharacteristic::getSkidBonusForce() const
{
    std::vector<float> result;
    bool is_set = false;
    process(SKID_BONUS_FORCE, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SKID_BONUS_FORCE).c_str());
    return result;
}  // getSkidBonusForce

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSkidPhysicalJumpTime() const
{
    float result;
    bool is_set = false;
    process(SKID_PHYSICAL_JUMP_TIME, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SKID_PHYSICAL_JUMP_TIME).c_str());
    return result;
}  // getSkidPhysicalJumpTime

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSkidGraphicalJumpTime() const
{
    float result;
    bool is_set = false;
    process(SKID_GRAPHICAL_JUMP_TIME, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SKID_GRAPHICAL_JUMP_TIME).c_str());
    return result;
}  // getSkidGraphicalJumpTime

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSkidPostSkidRotateFactor() const
{
    float result;
    bool is_set = false;
    process(SKID_POST_SKID_ROTATE_FACTOR, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SKID_POST_SKID_ROTATE_FACTOR).c_str());
    return result;
}  // getSkidPostSkidRotateFactor

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSkidReduceTurnMin() const
{
    float result;
    bool is_set = false;
    process(SKID_REDUCE_TURN_MIN, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SKID_REDUCE_TURN_MIN).c_str());
    return result;
}  // getSkidReduceTurnMin

// ----------------------------------------------------------------------------
float AbstractCharacteristic::getSkidReduceTurnMax() const
{
    float result;
    bool is_set = false;
    process(SKID_REDUCE_TURN_MAX, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SKID_REDUCE_TURN_MAX).c_str());
    return result;
}  // getSkidReduceTurnMax

// ----------------------------------------------------------------------------
bool AbstractCharacteristic::getSkidEnabled() const
{
    bool result;
    bool is_set = false;
    process(SKID_ENABLED, &result, &is_set);
    if (!is_set)
        Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
                    getName(SKID_ENABLED).c_str());
    return result;
}  // getSkidEnabled


/* <characteristics-end acgetter> */
