#include "MW4Headers.hpp" #include "AI_UserConstants.hpp" using namespace MW4AI; UserConstants* UserConstants::m_Instance = 0; UserConstants::UserConstants() : m_RefCount(0) , m_Resource("ai\\ai.constants") , m_LastPage(0) { Verify(m_Resource.DoesResourceExist()); m_Resource.LoadData(); m_NotationFile.Assimilate(new Stuff::NotationFile(&m_Resource)); const std::string friendly_fire_building_cheat("Friendly Fire Building Cheat"); const std::string mood_entropy("Mood Entropy"); const std::string mood_multipliers("Mood Modifiers"); const std::string missed_shot_modifiers("Missed Shot Modifiers"); const std::string speed_definitions("Speed Definitions"); const std::string tonnage_definitions("Tonnage Definitions"); const std::string distance_definitions("Distance Definitions"); const std::string to_hit_modifiers("To-Hit Modifiers"); const std::string elite_levels("Elite Levels"); const std::string evasion_characteristics("Evasion Characteristics"); const std::string lancemates("Lancemates"); const std::string firing("Firing"); const std::string tactics("Tactics"); const std::string tactic_selection("Tactic Selection"); const std::string ai_slope ("AI Slope"); const std::string ai_movecost ("AI Movement Costs"); const std::string objective ("Objective"); const std::string skills ("Skills"); const std::string piloting ("Piloting"); const std::string ejecting("Ejecting"); const std::string difficulty ("Difficulty"); const std::string collision ("Collision"); const std::string joystick ("Joystick"); const std::string salvage ("Salvage"); const std::string mouse ("Mouse"); {for (int i = ID_FIRST; i <= ID_LAST; ++i) { switch ((ID)i) { #define ENTRY(itemname,blockname) case itemname: { LookUpValue(blockname,#itemname,(int)itemname); break; } ENTRY(entropy_regeneration_at_0, mood_entropy); ENTRY(entropy_regeneration_at_100, mood_entropy); ENTRY(building_ff_multiplier, friendly_fire_building_cheat); ENTRY(shutdown, mood_multipliers); ENTRY(internal_armor_breached, mood_multipliers); ENTRY(fall_down, mood_multipliers); ENTRY(first_arm_hit, mood_multipliers); ENTRY(second_arm_hit, mood_multipliers); ENTRY(first_leg_hit, mood_multipliers); ENTRY(mood_squad_dead_unit_multiplier, mood_multipliers); ENTRY(interval_multiplier_desperate, mood_multipliers); ENTRY(interval_multiplier_defensive, mood_multipliers); ENTRY(interval_multiplier_neutral, mood_multipliers); ENTRY(interval_multiplier_aggressive, mood_multipliers); ENTRY(interval_multiplier_brutal, mood_multipliers); ENTRY(skew_at_0, missed_shot_modifiers); ENTRY(skew_at_100, missed_shot_modifiers); ENTRY(skew_inc_at_0, missed_shot_modifiers); ENTRY(skew_inc_at_100, missed_shot_modifiers); ENTRY(speed_stopped, speed_definitions); ENTRY(speed_slow, speed_definitions); ENTRY(speed_medium, speed_definitions); ENTRY(speed_fast, speed_definitions); ENTRY(speed_maximum, speed_definitions); ENTRY(mech_tiny, tonnage_definitions); ENTRY(mech_small, tonnage_definitions); ENTRY(mech_medium, tonnage_definitions); ENTRY(mech_large, tonnage_definitions); ENTRY(mech_huge, tonnage_definitions); ENTRY(distance_adjacent, distance_definitions); ENTRY(distance_near, distance_definitions); ENTRY(distance_medium, distance_definitions); ENTRY(distance_far, distance_definitions); ENTRY(distance_very_far, distance_definitions); ENTRY(if_crouched, to_hit_modifiers); ENTRY(if_tiny, to_hit_modifiers); ENTRY(if_small, to_hit_modifiers); ENTRY(if_medium_size, to_hit_modifiers); ENTRY(if_large, to_hit_modifiers); ENTRY(if_huge, to_hit_modifiers); ENTRY(if_stopped, to_hit_modifiers); ENTRY(if_slow, to_hit_modifiers); ENTRY(if_medium_speed, to_hit_modifiers); ENTRY(if_fast, to_hit_modifiers); ENTRY(if_maximum, to_hit_modifiers); ENTRY(if_shooter_stopped, to_hit_modifiers); ENTRY(if_shooter_slow, to_hit_modifiers); ENTRY(if_shooter_medium, to_hit_modifiers); ENTRY(if_shooter_fast, to_hit_modifiers); ENTRY(if_shooter_maximum, to_hit_modifiers); ENTRY(if_adjacent, to_hit_modifiers); ENTRY(if_near, to_hit_modifiers); ENTRY(if_medium_range, to_hit_modifiers); ENTRY(if_far, to_hit_modifiers); ENTRY(if_very_far, to_hit_modifiers); ENTRY(if_firing_with_one_arm, to_hit_modifiers); ENTRY(if_turning, to_hit_modifiers); ENTRY(if_bearing_90, to_hit_modifiers); ENTRY(min_evade_when_missiles_shot_at_me, elite_levels); ENTRY(max_evade_when_missiles_shot_at_me, elite_levels); ENTRY(min_evade_when_targeted, elite_levels); ENTRY(max_evade_when_targeted, elite_levels); ENTRY(min_evade_by_jumping, elite_levels); ENTRY(max_evade_by_jumping, elite_levels); ENTRY(min_evade_by_throttle_override, elite_levels); ENTRY(max_evade_by_throttle_override, elite_levels); ENTRY(min_evade_by_crouching, elite_levels); ENTRY(max_evade_by_crouching, elite_levels); ENTRY(min_jump_if_rushed, elite_levels); ENTRY(max_jump_if_rushed, elite_levels); ENTRY(min_opportunity_fire, elite_levels); ENTRY(max_opportunity_fire, elite_levels); ENTRY(min_look_left_or_right, elite_levels); ENTRY(max_look_left_or_right, elite_levels); ENTRY(min_look_time_at_0, elite_levels); ENTRY(min_look_time_at_100, elite_levels); ENTRY(min_dont_use_limited_ammo_vs_non_mechs, elite_levels); ENTRY(max_dont_use_limited_ammo_vs_non_mechs, elite_levels); ENTRY(min_vulnerable_leg_hiding, elite_levels); ENTRY(max_vulnerable_leg_hiding, elite_levels); ENTRY(min_mood_vulnerable_leg_hiding, elite_levels); ENTRY(max_mood_vulnerable_leg_hiding, elite_levels); ENTRY(switch_to_random_component_picking, elite_levels); ENTRY(switch_to_most_damaged_component_picking, elite_levels); ENTRY(min_prefer_water, elite_levels); ENTRY(max_prefer_water, elite_levels); ENTRY(min_throttle_override, elite_levels); ENTRY(torso_twist_multiplier_at_0, elite_levels); ENTRY(torso_twist_use_full_multiplier, elite_levels); ENTRY(jump_wait_time_at_0, evasion_characteristics); ENTRY(jump_wait_time_at_100, evasion_characteristics); ENTRY(evade_focus_time_at_0, evasion_characteristics); ENTRY(evade_focus_time_at_100, evasion_characteristics); ENTRY(lancemate_can_attack_radius, lancemates); ENTRY(max_lancemate_distance_from_leader, lancemates); ENTRY(max_defend_distance_from_target, tactics); ENTRY(jump_and_shoot_hover_height_min, tactics); ENTRY(jump_and_shoot_hover_height_max, tactics); ENTRY(max_fire_cheat_angle, firing); ENTRY(max_airplane_fire_cheat_angle, firing); ENTRY(max_turret_fire_cheat_angle, firing); ENTRY(min_tactic_time, tactic_selection); ENTRY(min_elite_joust, tactic_selection); ENTRY(max_elite_joust, tactic_selection); ENTRY(min_mood_joust, tactic_selection); ENTRY(max_mood_joust, tactic_selection); ENTRY(min_elite_rush, tactic_selection); ENTRY(max_elite_rush, tactic_selection); ENTRY(min_mood_rush, tactic_selection); ENTRY(max_mood_rush, tactic_selection); ENTRY(min_elite_hitandrun, tactic_selection); ENTRY(max_elite_hitandrun, tactic_selection); ENTRY(min_mood_hitandrun, tactic_selection); ENTRY(max_mood_hitandrun, tactic_selection); ENTRY(min_elite_rear, tactic_selection); ENTRY(max_elite_rear, tactic_selection); ENTRY(min_mood_rear, tactic_selection); ENTRY(max_mood_rear, tactic_selection); ENTRY(min_elite_circle, tactic_selection); ENTRY(max_elite_circle, tactic_selection); ENTRY(min_mood_circle, tactic_selection); ENTRY(max_mood_circle, tactic_selection); ENTRY(min_elite_retreat, tactic_selection); ENTRY(max_elite_retreat, tactic_selection); ENTRY(min_mood_retreat, tactic_selection); ENTRY(max_mood_retreat, tactic_selection); ENTRY(min_elite_dfa, tactic_selection); ENTRY(max_elite_dfa, tactic_selection); ENTRY(min_mood_dfa, tactic_selection); ENTRY(max_mood_dfa, tactic_selection); ENTRY(leg_up_slope, ai_slope); ENTRY(leg_down_slope, ai_slope); ENTRY(track_up_slope, ai_slope); ENTRY(track_down_slope, ai_slope); ENTRY(wheel_up_slope, ai_slope); ENTRY(wheel_down_slope, ai_slope); ENTRY(hover_up_slope, ai_slope); ENTRY(hover_down_slope, ai_slope); ENTRY(leg_dirt_cost, ai_movecost); ENTRY(leg_rock_cost, ai_movecost); ENTRY(leg_steel_cost, ai_movecost); ENTRY(leg_blacktop_cost, ai_movecost); ENTRY(leg_glass_cost, ai_movecost); ENTRY(leg_brick_cost, ai_movecost); ENTRY(leg_grass_cost, ai_movecost); ENTRY(leg_wood_cost, ai_movecost); ENTRY(leg_tree_cost, ai_movecost); ENTRY(leg_swamp_cost, ai_movecost); ENTRY(leg_concrete_cost, ai_movecost); ENTRY(leg_rough_cost, ai_movecost); ENTRY(leg_snow_cost, ai_movecost); ENTRY(leg_underbrush_cost, ai_movecost); ENTRY(leg_shallowwater_cost, ai_movecost); ENTRY(leg_midwater_cost, ai_movecost); ENTRY(leg_oceanicwater_cost, ai_movecost); ENTRY(leg_desert_cost, ai_movecost); ENTRY(leg_flatswamp_cost, ai_movecost); ENTRY(leg_thickswamp_cost, ai_movecost); // MSL 5.03 Lava ENTRY(leg_crackedlava_cost, ai_movecost); ENTRY(leg_openlava_cost, ai_movecost); ENTRY(track_dirt_cost, ai_movecost); ENTRY(track_rock_cost, ai_movecost); ENTRY(track_steel_cost, ai_movecost); ENTRY(track_blacktop_cost, ai_movecost); ENTRY(track_glass_cost, ai_movecost); ENTRY(track_brick_cost, ai_movecost); ENTRY(track_grass_cost, ai_movecost); ENTRY(track_wood_cost, ai_movecost); ENTRY(track_tree_cost, ai_movecost); ENTRY(track_swamp_cost, ai_movecost); ENTRY(track_concrete_cost, ai_movecost); ENTRY(track_rough_cost, ai_movecost); ENTRY(track_snow_cost, ai_movecost); ENTRY(track_underbrush_cost, ai_movecost); ENTRY(track_shallowwater_cost,ai_movecost); ENTRY(track_midwater_cost, ai_movecost); ENTRY(track_oceanicwater_cost,ai_movecost); ENTRY(track_desert_cost, ai_movecost); ENTRY(track_flatswamp_cost, ai_movecost); ENTRY(track_thickswamp_cost, ai_movecost); // MSL 5.03 Lava ENTRY(track_crackedlava_cost, ai_movecost); ENTRY(track_openlava_cost, ai_movecost); ENTRY(wheel_dirt_cost, ai_movecost); ENTRY(wheel_rock_cost, ai_movecost); ENTRY(wheel_steel_cost, ai_movecost); ENTRY(wheel_blacktop_cost, ai_movecost); ENTRY(wheel_glass_cost, ai_movecost); ENTRY(wheel_brick_cost, ai_movecost); ENTRY(wheel_grass_cost, ai_movecost); ENTRY(wheel_wood_cost, ai_movecost); ENTRY(wheel_tree_cost, ai_movecost); ENTRY(wheel_swamp_cost, ai_movecost); ENTRY(wheel_concrete_cost, ai_movecost); ENTRY(wheel_rough_cost, ai_movecost); ENTRY(wheel_snow_cost, ai_movecost); ENTRY(wheel_underbrush_cost, ai_movecost); ENTRY(wheel_shallowwater_cost,ai_movecost); ENTRY(wheel_midwater_cost, ai_movecost); ENTRY(wheel_oceanicwater_cost,ai_movecost); ENTRY(wheel_desert_cost, ai_movecost); ENTRY(wheel_flatswamp_cost, ai_movecost); ENTRY(wheel_thickswamp_cost, ai_movecost); // MSL 5.03 Lava ENTRY(wheel_crackedlava_cost, ai_movecost); ENTRY(wheel_openlava_cost, ai_movecost); ENTRY(hover_dirt_cost, ai_movecost); ENTRY(hover_rock_cost, ai_movecost); ENTRY(hover_steel_cost, ai_movecost); ENTRY(hover_blacktop_cost, ai_movecost); ENTRY(hover_glass_cost, ai_movecost); ENTRY(hover_brick_cost, ai_movecost); ENTRY(hover_grass_cost, ai_movecost); ENTRY(hover_wood_cost, ai_movecost); ENTRY(hover_tree_cost, ai_movecost); ENTRY(hover_swamp_cost, ai_movecost); ENTRY(hover_concrete_cost, ai_movecost); ENTRY(hover_rough_cost, ai_movecost); ENTRY(hover_snow_cost, ai_movecost); ENTRY(hover_underbrush_cost, ai_movecost); ENTRY(hover_shallowwater_cost,ai_movecost); ENTRY(hover_midwater_cost, ai_movecost); ENTRY(hover_oceanicwater_cost,ai_movecost); ENTRY(hover_desert_cost, ai_movecost); ENTRY(hover_flatswamp_cost, ai_movecost); ENTRY(hover_thickswamp_cost, ai_movecost); // MSL 5.03 Lava ENTRY(hover_crackedlava_cost, ai_movecost); ENTRY(hover_openlava_cost, ai_movecost); ENTRY(objective_display_time, objective); ENTRY(default_pilot, skills); ENTRY(default_gunnery, skills); ENTRY(default_elite, skills); ENTRY(default_minheat, skills); ENTRY(default_maxheat, skills); ENTRY(default_sensor, skills); ENTRY(default_blind, skills); ENTRY(default_longrange, skills); ENTRY(default_shortrange, skills); ENTRY(default_addpilot, skills); ENTRY(default_addgunnery, skills); ENTRY(default_addelite, skills); ENTRY(max_skill_add, skills); ENTRY(max_fog_dist_to_use_blind_skill, skills); ENTRY(damage_amount, piloting); ENTRY(fall_damage_minus, piloting); ENTRY(fall_splash_multiplier, piloting); ENTRY(min_fall_timer, piloting); ENTRY(damage_mod, piloting); ENTRY(low_water_mod, piloting); ENTRY(mid_water_mod, piloting); ENTRY(concrete_mod, piloting); ENTRY(gimped_mod, piloting); ENTRY(double_damage_mod, piloting); ENTRY(moving_fast_mod, piloting); ENTRY(jump_recover_mod, piloting); ENTRY(max_water_jump, piloting); ENTRY(flying_turn_rate, piloting); ENTRY(eject_chance_for_non_lancemate, ejecting); ENTRY(eject_chance_for_lancemate, ejecting); ENTRY(eject_chance_ok_when_ejected, ejecting); ENTRY(eject_chance_injured_when_ejected, ejecting); ENTRY(friend_easy_gunnery_mod, difficulty); ENTRY(friend_medium_gunnery_mod, difficulty); ENTRY(friend_hard_gunnery_mod, difficulty); ENTRY(friend_impossible_gunnery_mod, difficulty); ENTRY(enemy_easy_gunnery_mod, difficulty); ENTRY(enemy_medium_gunnery_mod, difficulty); ENTRY(enemy_hard_gunnery_mod, difficulty); ENTRY(enemy_impossible_gunnery_mod, difficulty); ENTRY(neutral_easy_gunnery_mod, difficulty); ENTRY(neutral_medium_gunnery_mod, difficulty); ENTRY(neutral_hard_gunnery_mod, difficulty); ENTRY(neutral_impossible_gunnery_mod, difficulty); ENTRY(collision_mech_light_damage, collision); ENTRY(collision_mech_light_slowdown, collision); ENTRY(collision_mech_light_mech_speed, collision); ENTRY(collision_mech_light_building_speed, collision); ENTRY(collision_mech_medium_tonage, collision); ENTRY(collision_mech_medium_damage, collision); ENTRY(collision_mech_medium_slowdown, collision); ENTRY(collision_mech_medium_mech_speed, collision); ENTRY(collision_mech_medium_building_speed, collision); ENTRY(collision_mech_heavy_tonage, collision); ENTRY(collision_mech_heavy_damage, collision); ENTRY(collision_mech_heavy_slowdown, collision); ENTRY(collision_mech_heavy_mech_speed, collision); ENTRY(collision_mech_heavy_building_speed, collision); ENTRY(collision_dfa_speed, collision); ENTRY(collision_dfa_damage_given, collision); ENTRY(collision_dfa_damage_taken, collision); ENTRY(collision_tank_slowdown, collision); ENTRY(throttle_center, joystick); ENTRY(throttle_dead_low, joystick); ENTRY(throttle_dead_high, joystick); ENTRY(chance_salvage, salvage); ENTRY(mouse_min_change, mouse); ENTRY(mouse_interia_mult, mouse); ENTRY(mouse_max_mouse, mouse); default: { Verify(!"Should never get here."); } #undef ENTRY } }} for (int i = ID_MOVE_COST_START;i <= ID_MOVE_COST_LAST;++i) { if (m_Value[i] <= -100) m_Value[i] = FLT_MAX; } } UserConstants::~UserConstants() { } Stuff::Scalar UserConstants::Get(ID id) const { Verify(id >= ID_FIRST); Verify(id <= ID_LAST); return (m_Value[(int)id]); } void UserConstants::LookUpValue(const std::string& header_name, const std::string& item_name, int value_index) { Verify(m_NotationFile.GetPointer() != 0); Stuff::Page* page = 0; if ((m_LastPage != 0) && (stricmp(header_name.c_str(),m_LastPage->GetName()) == 0)) { page = m_LastPage; } else { page = m_NotationFile->FindPage(header_name.c_str()); if (page == 0) { Verify(!"Item not found. Make sure you have the latest CONTENT\\AI\\AI.CONSTANTS file."); m_Value[value_index] = 0; return; } m_LastPage = page; } Stuff::Note* note = page->FindNote(item_name.c_str()); m_Value[value_index] = 0; if (note == 0) { Verify(!"Item not found."); } else { note->GetEntry(&(m_Value[value_index])); } } void UserConstants::IncrementRefCount() { if (m_Instance == 0) { m_Instance = new UserConstants(); } ++m_Instance->m_RefCount; } void UserConstants::DecrementRefCount() { Verify(m_Instance != 0); Verify(m_Instance->m_RefCount > 0); --(m_Instance->m_RefCount); if (m_Instance->m_RefCount == 0) { delete m_Instance; m_Instance = 0; } } UserConstants* UserConstants::Instance() { return (m_Instance); } Stuff::Scalar UserConstants::GetMultiplier_Tonnage(Stuff::Scalar tonnage) const { return (FindCategorizedValue(tonnage,mech_tiny,mech_huge,if_tiny)); } Stuff::Scalar UserConstants::GetMultiplier_CrouchState(bool fCrouched) const { if (fCrouched == true) { return (Get(if_crouched)); } return (1.0f); } Stuff::Scalar UserConstants::GetMultiplier_Speed(Stuff::Scalar kph) const { return (FindCategorizedValue(kph,speed_stopped,speed_maximum,if_stopped)); } Stuff::Scalar UserConstants::GetMultiplier_ShooterSpeed(Stuff::Scalar kph) const { return (FindCategorizedValue(kph,speed_stopped,speed_maximum,if_shooter_stopped)); } Stuff::Scalar UserConstants::GetMultiplier_Distance(Stuff::Scalar distance) const { return (FindCategorizedValue(distance,distance_adjacent,distance_very_far,if_adjacent)); } UserConstants::ID UserConstants::FindCategory(Stuff::Scalar user_value, UserConstants::ID first, UserConstants::ID last) const { Verify(last > first); Verify(first >= ID_FIRST); Verify(last <= ID_LAST); UserConstants::ID category = first; {for (int i = first; i < last; ++i) { if (user_value > Get((UserConstants::ID)i)) { category = (UserConstants::ID)((int)category + 1); } else { break; } }} Verify(category >= first); Verify(category <= last); return (category); } Stuff::Scalar UserConstants::FindCategorizedValue(Stuff::Scalar user_value, UserConstants::ID first, UserConstants::ID last, UserConstants::ID first_lookup) const { Verify((first_lookup > last) || (first_lookup < first)); Verify(first_lookup >= ID_FIRST); Verify(first_lookup <= ID_LAST); UserConstants::ID category = FindCategory(user_value,first,last); int difference = category - first; UserConstants::ID lookup = (UserConstants::ID)(first_lookup + difference); return (Get(lookup)); } Stuff::Scalar UserConstants::GetMultiplier_Bearing(const Stuff::Point3D& self, const Stuff::LinearMatrix4D& shooting_at, Stuff::Scalar target_speed) const { Stuff::Point3D delta; delta.Subtract(self,(Stuff::Point3D)shooting_at); if (delta.GetLengthSquared() == 0) { return (1); } Stuff::UnitVector3D delta_normalized(delta); Stuff::UnitVector3D local_forward; shooting_at.GetLocalForwardInWorld(&local_forward); Stuff::Scalar bearing = delta_normalized * local_forward; if (bearing < 0) { bearing = -bearing; } if (bearing > 1) { bearing = 1; } Stuff::Scalar multiplier = bearing + ((1 - bearing) * Get(if_bearing_90)); switch (FindCategory(target_speed,speed_stopped,speed_maximum)) { case speed_stopped: case speed_slow: { break; } case speed_medium: case speed_fast: { multiplier *= multiplier; break; } case speed_maximum: { multiplier *= multiplier; multiplier *= multiplier; break; } default: { Verify(!"Should never get here."); break; } } return (multiplier); } Stuff::Scalar UserConstants::GetMultiplier_TurnRate(Stuff::Scalar yaw_demand) const { Verify(yaw_demand >= 0); Verify(yaw_demand <= 1); return ((1 - yaw_demand) + (yaw_demand * Get(if_turning))); }