| 80 | } |
| 81 | |
| 82 | void ControlAutoGun(short itemNumber) |
| 83 | { |
| 84 | auto& item = g_Level.Items[itemNumber]; |
| 85 | auto& playerItem = *LaraItem; |
| 86 | |
| 87 | if (!TriggerActive(&item)) |
| 88 | return; |
| 89 | |
| 90 | if (TestLastFrame(*&item)) |
| 91 | { |
| 92 | auto& autoGun = *GetCreatureInfo(&item); |
| 93 | |
| 94 | // Set visible meshes. |
| 95 | item.MeshBits.Set(AutoGunClosedHatchJoints); |
| 96 | item.MeshBits.Clear(AutoGunChassisJoints); |
| 97 | |
| 98 | // Assess line of sight. |
| 99 | auto origin = GameVector(item.Pose.Position, item.RoomNumber); |
| 100 | auto target = GameVector(GetJointPosition(&playerItem, LM_TORSO), playerItem.RoomNumber); |
| 101 | bool los = LOS(&origin, &target); |
| 102 | |
| 103 | // Interpolate orientation. |
| 104 | auto orient = EulerAngles(item.ItemFlags[0], item.ItemFlags[1], 0); |
| 105 | auto orientTo = los ? Geometry::GetOrientToPoint(origin.ToVector3(), target.ToVector3()) : item.Pose.Orientation; |
| 106 | orient.Lerp(orientTo, AUTO_GUN_ORIENT_LERP_ALPHA); |
| 107 | |
| 108 | item.ItemFlags[0] = orient.x; |
| 109 | item.ItemFlags[1] = orient.y; |
| 110 | |
| 111 | auto deltaAngle = orient - orientTo; |
| 112 | |
| 113 | // Handle joint rotation. |
| 114 | autoGun.JointRotation[0] = orient.y; |
| 115 | autoGun.JointRotation[1] = orient.x; |
| 116 | autoGun.JointRotation[2] += item.ItemFlags[2]; |
| 117 | |
| 118 | // Fire gunshot. |
| 119 | if (los && |
| 120 | abs(deltaAngle.x) <= AUTO_GUN_FIRE_CONSTRAINT_ANGLE && |
| 121 | abs(deltaAngle.y) <= AUTO_GUN_FIRE_CONSTRAINT_ANGLE) |
| 122 | { |
| 123 | SoundEffect(SFX_TR4_HK_FIRE, &item.Pose, SoundEnvironment::Land, 0.8f); |
| 124 | |
| 125 | if (GlobalCounter & 1) |
| 126 | { |
| 127 | item.MeshBits.Set(AutoGunFlashJoints); |
| 128 | |
| 129 | auto lightColor = Vector3(Random::GenerateFloat(0.75f, 0.85f), Random::GenerateFloat(0.5f, 0.6f), 0.0f) * 255; |
| 130 | SpawnDynamicLight(origin.x, origin.y, origin.z, 10, lightColor.x, lightColor.y, lightColor.z); |
| 131 | |
| 132 | // Spawn blood. |
| 133 | if (Random::TestProbability(AUTO_GUN_BLOOD_EFFECT_CHANCE)) |
| 134 | { |
| 135 | DoDamage(&playerItem, AUTO_GUN_SHOT_DAMAGE); |
| 136 | |
| 137 | auto bloodPos = GetJointPosition(&playerItem, Random::GenerateInt(0, NUM_LARA_MESHES - 1)); |
| 138 | float bloodVel = Random::GenerateFloat(4.0f, 8.0f); |
| 139 | DoBloodSplat(bloodPos.x, bloodPos.y, bloodPos.z, bloodVel, Random::GenerateAngle(), playerItem.RoomNumber); |
nothing calls this directly
no test coverage detected