* @brief Determines the creature's mood based on its situation. * * MOOD TYPES: * - Bored: Wandering randomly, not actively engaged. * - Attack: Directly pursuing and attacking the enemy. * - Escape: Fleeing from the enemy. * - Stalk: Following the enemy at a distance, waiting to attack. * * MOOD TRANSITIONS: * - Bored/Stalk -> Attack: When in same zone as enemy and close enough. * - Att
| 2778 | * @param isViolent If true, creature is aggressive (no stalking behavior). |
| 2779 | */ |
| 2780 | void GetCreatureMood(ItemInfo* item, AI_INFO* AI, bool isViolent) |
| 2781 | { |
| 2782 | if (!item->IsCreature()) |
| 2783 | return; |
| 2784 | |
| 2785 | auto* creature = GetCreatureInfo(item); |
| 2786 | auto* enemy = creature->Enemy; |
| 2787 | auto* LOT = &creature->LOT; |
| 2788 | |
| 2789 | // Clear target if creature is in a blocked box. |
| 2790 | if (item->BoxNumber == NO_VALUE || creature->LOT.Node[item->BoxNumber].searchNumber == (creature->LOT.SearchNumber | SEARCH_BLOCKED)) |
| 2791 | creature->LOT.RequiredBox = NO_VALUE; |
| 2792 | |
| 2793 | // Clear target if it's no longer valid (different zone, blocked, etc.) |
| 2794 | if (creature->Mood != MoodType::Attack && creature->LOT.RequiredBox != NO_VALUE && !ValidBox(item, AI->zoneNumber, creature->LOT.TargetBox)) |
| 2795 | { |
| 2796 | if (AI->zoneNumber == AI->enemyZone) |
| 2797 | creature->Mood = MoodType::Bored; |
| 2798 | |
| 2799 | creature->LOT.RequiredBox = NO_VALUE; |
| 2800 | } |
| 2801 | |
| 2802 | // Store current mood to detect changes later. |
| 2803 | auto mood = creature->Mood; |
| 2804 | |
| 2805 | // MOOD DECISION LOGIC |
| 2806 | // Based on enemy state, creature state, and zone relationships. |
| 2807 | if (enemy) |
| 2808 | { |
| 2809 | // Enemy is dead - go back to idle wandering. |
| 2810 | if (enemy->HitPoints <= 0 && enemy == LaraItem) // TODO: deal with LaraItem global ! |
| 2811 | { |
| 2812 | creature->Mood = MoodType::Bored; |
| 2813 | } |
| 2814 | else if (isViolent) |
| 2815 | { |
| 2816 | // VIOLENT CREATURE BEHAVIOR |
| 2817 | // These creatures are highly aggressive - they don't stalk, only attack or flee. |
| 2818 | switch (creature->Mood) |
| 2819 | { |
| 2820 | case MoodType::Bored: |
| 2821 | case MoodType::Stalk: |
| 2822 | // Same zone = can reach enemy, so attack immediately. |
| 2823 | if (AI->zoneNumber == AI->enemyZone) |
| 2824 | creature->Mood = MoodType::Attack; |
| 2825 | // Got hit but can't reach enemy - flee instead. |
| 2826 | else if (item->HitStatus) |
| 2827 | creature->Mood = MoodType::Escape; |
| 2828 | |
| 2829 | break; |
| 2830 | |
| 2831 | case MoodType::Attack: |
| 2832 | // Lost access to enemy's zone - give up and wander. |
| 2833 | if (AI->zoneNumber != AI->enemyZone) |
| 2834 | creature->Mood = MoodType::Bored; |
| 2835 | |
| 2836 | break; |
| 2837 |
no test coverage detected