| 50 | }; |
| 51 | |
| 52 | void NatlaControl(short itemNumber) |
| 53 | { |
| 54 | if (!CreatureActive(itemNumber)) |
| 55 | return; |
| 56 | |
| 57 | auto* item = &g_Level.Items[itemNumber]; |
| 58 | auto* creature = GetCreatureInfo(item); |
| 59 | |
| 60 | short headingAngle = 0; |
| 61 | short tiltAngle = 0; |
| 62 | auto extraHeadRot = EulerAngles::Identity; |
| 63 | auto extraTorsoRot = EulerAngles::Identity; |
| 64 | |
| 65 | AI_INFO ai; |
| 66 | int timer = creature->Flags & NATLA_TIMER; |
| 67 | bool shoot = false; |
| 68 | |
| 69 | if (item->HitPoints <= 0 && item->ItemFlags[1] != 0) |
| 70 | { |
| 71 | item->Animation.TargetState = NATLA_STATE_DEATH; |
| 72 | } |
| 73 | else if (item->HitPoints <= (Objects[item->ObjectNumber].HitPoints / 2)) |
| 74 | { |
| 75 | creature->LOT.Step = CLICK(1); |
| 76 | creature->LOT.Drop = -CLICK(1); |
| 77 | creature->LOT.Fly = NO_FLYING; |
| 78 | creature->LOT.Zone = ZoneType::Basic; |
| 79 | CreatureAIInfo(item, &ai); |
| 80 | |
| 81 | // NOTE: Only rotate joints if alive. |
| 82 | if (ai.ahead && item->ItemFlags[1] == 1) |
| 83 | { |
| 84 | extraHeadRot.x = ai.xAngle / 2; |
| 85 | extraHeadRot.y = ai.angle / 2; |
| 86 | extraTorsoRot.x = ai.xAngle / 2; |
| 87 | extraTorsoRot.y = ai.angle / 2; |
| 88 | } |
| 89 | |
| 90 | GetCreatureMood(item, &ai, true); |
| 91 | CreatureMood(item, &ai, true); |
| 92 | |
| 93 | headingAngle = CreatureTurn(item, creature->MaxTurn); |
| 94 | |
| 95 | if (item->ItemFlags[0] != 0) |
| 96 | { |
| 97 | item->Pose.Orientation.y += item->ItemFlags[0]; |
| 98 | item->ItemFlags[0] = 0; |
| 99 | } |
| 100 | |
| 101 | switch (item->Animation.ActiveState) |
| 102 | { |
| 103 | case NATLA_STATE_FALL: |
| 104 | creature->MaxTurn = 0; |
| 105 | |
| 106 | if (item->Pose.Position.y < item->Floor) |
| 107 | { |
| 108 | item->Animation.IsAirborne = true; |
| 109 | item->Animation.Velocity.z = 0; |
nothing calls this directly
no test coverage detected