| 2776 | } |
| 2777 | |
| 2778 | bool AIDetermineAimPoint(object *robot, object *target, vector *aim_pt, float weapon_speed) { |
| 2779 | if (DIFF_LEVEL == DIFFICULTY_TRAINEE && ((robot->ai_info->flags & AIF_TEAM_MASK) != AIF_TEAM_REBEL)) { |
| 2780 | *aim_pt = target->pos; |
| 2781 | return true; |
| 2782 | } |
| 2783 | |
| 2784 | float vl = AIDetermineObjVisLevel(robot, target); |
| 2785 | |
| 2786 | ai_frame *ai_info = robot->ai_info; |
| 2787 | vector to_target = target->pos - robot->pos; |
| 2788 | float dist_to_target = vm_NormalizeVector(&to_target); |
| 2789 | |
| 2790 | if (weapon_speed == 0.0f && ai_info) |
| 2791 | weapon_speed = ai_info->weapon_speed; |
| 2792 | |
| 2793 | if (weapon_speed == 0.0f) { |
| 2794 | *aim_pt = target->pos; |
| 2795 | return false; |
| 2796 | } |
| 2797 | |
| 2798 | float wsp = weapon_speed - (to_target * target->mtype.phys_info.velocity); |
| 2799 | |
| 2800 | if (wsp <= 0.0f || vl < AIVIS_BARELY) { |
| 2801 | *aim_pt = target->pos; |
| 2802 | return false; |
| 2803 | } |
| 2804 | |
| 2805 | float dt = dist_to_target / wsp; |
| 2806 | |
| 2807 | float scale; |
| 2808 | |
| 2809 | if (ai_info) |
| 2810 | scale = ai_info->lead_accuracy; |
| 2811 | else |
| 2812 | scale = 1.0f; |
| 2813 | |
| 2814 | // chrishack -- add stuff so that rebels get better as DIFF lowers and |
| 2815 | // ptmc gets better as DIFF increases |
| 2816 | if (target->type != OBJ_PLAYER || |
| 2817 | (DIFF_LEVEL < DIFFICULTY_HOTSHOT && ((robot->ai_info->flags & AIF_TEAM_MASK) != AIF_TEAM_REBEL)) || |
| 2818 | scale < 0.4f || vl <= AIVIS_MOSTLY) |
| 2819 | *aim_pt = target->pos + (target->mtype.phys_info.velocity * dt) * scale; |
| 2820 | else |
| 2821 | ApplyConstantForce(target, aim_pt, &target->mtype.phys_info.thrust, dt * scale); |
| 2822 | |
| 2823 | return true; |
| 2824 | } |
| 2825 | |
| 2826 | vector *AIDetermineFovVec(object *obj, vector *fov) { |
| 2827 | ai_frame *ai_info = obj->ai_info; |
no test coverage detected