| 86 | } |
| 87 | |
| 88 | void LizardControl(short itemNumber) |
| 89 | { |
| 90 | if (!CreatureActive(itemNumber)) |
| 91 | return; |
| 92 | |
| 93 | auto& item = g_Level.Items[itemNumber]; |
| 94 | auto& creature = *GetCreatureInfo(&item); |
| 95 | |
| 96 | short headingAngle = 0; |
| 97 | short tiltAngle = 0; |
| 98 | auto headOrient = EulerAngles::Identity; |
| 99 | |
| 100 | if (item.HitPoints <= 0) |
| 101 | { |
| 102 | // Avoid doing the death animation if summoned. |
| 103 | if (item.Animation.ActiveState != LIZARD_STATE_DEATH) |
| 104 | SetAnimation(item, LIZARD_ANIM_DEATH); |
| 105 | |
| 106 | // Explode if summoned. |
| 107 | if (item.TestFlagField(0, 1) && item.Animation.FrameNumber == 50) |
| 108 | CreatureDie(itemNumber, true); |
| 109 | } |
| 110 | else |
| 111 | { |
| 112 | AI_INFO ai; |
| 113 | CreatureAIInfo(&item, &ai); |
| 114 | GetCreatureMood(&item, &ai, true); |
| 115 | CreatureMood(&item, &ai, true); |
| 116 | |
| 117 | if (IsLizardTargetBlocked(item)) |
| 118 | creature.Mood = MoodType::Attack; |
| 119 | |
| 120 | headingAngle = CreatureTurn(&item, creature.MaxTurn); |
| 121 | |
| 122 | // Turn head. Avoid while climbing or falling. |
| 123 | if (ai.ahead && |
| 124 | item.Animation.ActiveState < LIZARD_STATE_DEATH) |
| 125 | { |
| 126 | headOrient.x = ai.xAngle; |
| 127 | headOrient.y = ai.angle; |
| 128 | } |
| 129 | |
| 130 | bool isPlayerPoisonedOrTargetBlocked = |
| 131 | (creature.Enemy != nullptr && GetLaraInfo(creature.Enemy)->Status.Poison < 256) || |
| 132 | IsLizardTargetBlocked(item); |
| 133 | |
| 134 | switch (item.Animation.ActiveState) |
| 135 | { |
| 136 | case LIZARD_STATE_IDLE: |
| 137 | creature.MaxTurn = 0; |
| 138 | creature.Flags = 0; |
| 139 | |
| 140 | if (creature.Mood == MoodType::Escape) |
| 141 | { |
| 142 | item.Animation.TargetState = LIZARD_STATE_RUN_FORWARD; |
| 143 | } |
| 144 | else if (creature.Mood == MoodType::Bored) |
| 145 | { |
nothing calls this directly
no test coverage detected