#include <StdAfx.h>
#include "bear.h"
#include <trng_core.h>
#include "utility.h"
#include "Class/TRClass.h"

extern TYPE_InitialiseCreature InitialiseCreature;
extern TYPE_CreatureCollision CreatureCollision;
extern TYPE_CreatureActive CreatureActive;
extern TYPE_CreatureTurn CreatureTurn;
extern TYPE_SoundEffect SoundEffect;
extern TYPE_CreatureAIInfo CreatureAIInfo;
extern TYPE_GetCreatureMood GetCreatureMood;
extern TYPE_CreatureMood CreatureMood;
extern TYPE_GetRandomControl GetRandomControl;
extern TYPE_CreatureEffect CreatureEffect;
extern TYPE2_DoBloodSplat DoBloodSplat_2;
extern TYPE_CreatureJoint CreatureJoint;
extern TYPE_CreatureAnimation CreatureAnimation;

#define BEAR_CHARGE_DAMAGE 3
#define BEAR_SLAM_DAMAGE 200
#define BEAR_ATTACK_DAMAGE 200
#define BEAR_PAT_DAMAGE 400
#define BEAR_TOUCH 0x2406C
#define BEAR_ROAR_CHANCE 80
#define BEAR_REAR_CHANCE 768
#define BEAR_DROP_CHANCE 1536
#define BEAR_REAR_RANGE SQUARE(WALL_L * 2) // = 4194304
#define BEAR_ATTACK_RANGE SQUARE(WALL_L) // = 1048576
#define BEAR_PAT_RANGE SQUARE(285) // = 360000
#define BEAR_RUN_TURN (5 * ONE_DEGREE) // = 910
#define BEAR_WALK_TURN (2 * ONE_DEGREE) // = 364
#define BEAR_EAT_RANGE SQUARE(WALL_L * 3 / 4) // = 589824
#define BEAR_HITPOINTS 20
#define BEAR_RADIUS (WALL_L / 3) // = 341
#define BEAR_SMARTNESS 0x4000

static BITE_INFO BearHeadBite = { 0, 96, 335, 14 };

enum BEAR_ANIM {
    BEAR_STROLL = 0,
    BEAR_STOP = 1,
    BEAR_WALK = 2,
    BEAR_RUN = 3,
    BEAR_REAR = 4,
    BEAR_ROAR = 5,
    BEAR_ATTACK1 = 6,
    BEAR_ATTACK2 = 7,
    BEAR_EAT = 8,
    BEAR_DEATH = 9,
};

void CtrlTR1_Bear(short item_num)
{
    if (!CreatureActive(item_num))
        return;

    ITEM_INFO* item = &Ptr_VetItems[item_num];
    CREATURE_INFO* bear = (CREATURE_INFO*) item->data;
    short head = 0;
    short angle = 0;
    short dmg1 = Utils.getObjectAttribute(tsu_slots[item->object_number], ATT_DMG1);
    short dmg2 = Utils.getObjectAttribute(tsu_slots[item->object_number], ATT_DMG2);
    short dmg3 = Utils.getObjectAttribute(tsu_slots[item->object_number], ATT_DMG3);
    short dmg4 = Utils.getObjectAttribute(tsu_slots[item->object_number], ATT_DMG4);
    short snd1 = Utils.getObjectProperty(tsu_slots[item->object_number], PTY_SND1);

    if (item->hit_points <= 0) {
        angle = CreatureTurn(item, bear->maximum_turn);

        switch (item->current_anim_state) {
        case BEAR_WALK:
            item->goal_anim_state = BEAR_REAR;
            break;

        case BEAR_RUN:
        case BEAR_STROLL:
            item->goal_anim_state = BEAR_STOP;
            break;

        case BEAR_REAR:
            bear->flags = 1;
            item->goal_anim_state = BEAR_DEATH;
            break;

        case BEAR_STOP:
			bear->maximum_turn = 0;
            bear->flags = 0;
            item->goal_anim_state = BEAR_DEATH;
            break;

        case BEAR_DEATH:
			bear->maximum_turn = 0;
            if (bear->flags && (item->touch_bits & BEAR_TOUCH)) {
                LaraItem->hit_points -= DOUBLE_VALUE_ITEM(dmg1, BEAR_SLAM_DAMAGE);
                LaraItem->hit_status = 1;
                bear->flags = 0;
            }
            break;
        }
    } else {
        AI_INFO info;
        CreatureAIInfo(item, &info);

        if (info.ahead) {
            head = info.angle;
        }

        GetCreatureMood(item, &info, VIOLENT);
        CreatureMood(item, &info, VIOLENT);

        angle = CreatureTurn(item, bear->maximum_turn);

        bool dead_enemy = LaraItem->hit_points <= 0;
        if (item->hit_status) {
			if (snd1 != NO_ITEM)
				SoundEffect(snd1, &item->pos, 0);

            bear->flags = 1;
        }

        switch (item->current_anim_state) {
        case BEAR_STOP:
			bear->maximum_turn = 0;
            if (dead_enemy) {
                if (info.bite && info.distance < BEAR_EAT_RANGE) {
                    item->goal_anim_state = BEAR_EAT;
                } else {
                    item->goal_anim_state = BEAR_STROLL;
                }
            } else if (item->required_anim_state) {
                item->goal_anim_state = item->required_anim_state;
            } else if (bear->mood == MOOD_BORED) {
                item->goal_anim_state = BEAR_STROLL;
            } else {
                item->goal_anim_state = BEAR_RUN;
            }
            break;

        case BEAR_STROLL:
            bear->maximum_turn = BEAR_WALK_TURN;
            if (dead_enemy && (item->touch_bits & BEAR_TOUCH) && info.ahead) {
                item->goal_anim_state = BEAR_STOP;
            } else if (bear->mood != MOOD_BORED) {
                item->goal_anim_state = BEAR_STOP;
                if (bear->mood == MOOD_ESCAPE) {
                    item->required_anim_state = BEAR_STROLL;
                }
            } else if (GetRandomControl() < BEAR_ROAR_CHANCE) {
                item->required_anim_state = BEAR_ROAR;
                item->goal_anim_state = BEAR_STOP;
            }
            break;

        case BEAR_RUN:
            bear->maximum_turn = BEAR_RUN_TURN;
            if (item->touch_bits & BEAR_TOUCH) {
                LaraItem->hit_points -= DOUBLE_VALUE_ITEM(dmg2, BEAR_CHARGE_DAMAGE);
                LaraItem->hit_status = 1;
            }
            if (bear->mood == MOOD_BORED || dead_enemy) {
                item->goal_anim_state = BEAR_STOP;
            } else if (info.ahead && !item->required_anim_state) {
                if (!bear->flags && info.distance < BEAR_REAR_RANGE
                    && GetRandomControl() < BEAR_REAR_CHANCE) {
                    item->required_anim_state = BEAR_REAR;
                    item->goal_anim_state = BEAR_STOP;
                } else if (info.distance < BEAR_ATTACK_RANGE) {
                    item->goal_anim_state = BEAR_ATTACK1;
                }
            }
            break;

        case BEAR_REAR:
			bear->maximum_turn = BEAR_WALK_TURN;
            if (bear->flags) {
                item->required_anim_state = BEAR_STROLL;
                item->goal_anim_state = BEAR_STOP;
            } else if (item->required_anim_state) {
                item->goal_anim_state = item->required_anim_state;
            } else if (bear->mood == MOOD_BORED || bear->mood == MOOD_ESCAPE) {
                item->goal_anim_state = BEAR_STOP;
            } else if (info.bite && info.distance < BEAR_PAT_RANGE) {
                item->goal_anim_state = BEAR_ATTACK2;
            } else {
                item->goal_anim_state = BEAR_WALK;
            }
            break;

        case BEAR_WALK:
            if (bear->flags) {
                item->required_anim_state = BEAR_STROLL;
                item->goal_anim_state = BEAR_REAR;
            } else if (info.ahead && (item->touch_bits & BEAR_TOUCH)) {
                item->goal_anim_state = BEAR_REAR;
            } else if (bear->mood == MOOD_ESCAPE) {
                item->goal_anim_state = BEAR_REAR;
                item->required_anim_state = BEAR_STROLL;
            } else if (
                bear->mood == MOOD_BORED
                || GetRandomControl() < BEAR_ROAR_CHANCE) {
                item->required_anim_state = BEAR_ROAR;
                item->goal_anim_state = BEAR_REAR;
            } else if (
                info.distance > BEAR_REAR_RANGE
                || GetRandomControl() < BEAR_DROP_CHANCE) {
                item->required_anim_state = BEAR_STOP;
                item->goal_anim_state = BEAR_REAR;
            }
            break;

        case BEAR_ATTACK1:
            if (!item->required_anim_state && (item->touch_bits & BEAR_TOUCH)) {
                CreatureEffect(item, &BearHeadBite, DoBloodSplat_2);
                LaraItem->hit_points -= DOUBLE_VALUE_ITEM(dmg3, BEAR_ATTACK_DAMAGE);
                LaraItem->hit_status = 1;
                item->required_anim_state = BEAR_STOP;
            }
            break;

        case BEAR_ATTACK2:
            if (!item->required_anim_state && (item->touch_bits & BEAR_TOUCH)) {
                LaraItem->hit_points -= DOUBLE_VALUE_ITEM(dmg4, BEAR_PAT_DAMAGE);
                LaraItem->hit_status = 1;
                item->required_anim_state = BEAR_REAR;
            }
            break;
        }
    }

    CreatureJoint(item, 0, head);
    CreatureAnimation(item_num, angle, 0);
}

void InitialiseTR1_Bear()
{
    for (int index = 0; index < SLOTS_NUMBER; ++index)
    {
        tomb[TR1_BEAR1 + index].set_name("Bear");
        tomb[TR1_BEAR1 + index].initialise(TR1_BEAR1 + index, FUNCTION_SHADOW, 0);
        tomb[TR1_BEAR1 + index].set_shadow_size(128);
        tomb[TR1_BEAR1 + index].set_func_initialise(InitialiseCreature);
        tomb[TR1_BEAR1 + index].set_func_collide(CreatureCollision);
        tomb[TR1_BEAR1 + index].set_func_control(CtrlTR1_Bear);
        tomb[TR1_BEAR1 + index].set_func_draw(DrawAnimatingItemCustom, NULL);
        tomb[TR1_BEAR1 + index].set_health(BEAR_HITPOINTS);
        tomb[TR1_BEAR1 + index].set_radius_and_pivot(BEAR_RADIUS, 0);
        tomb[TR1_BEAR1 + index].set_hit_effect(HIT_BLOOD);
        tomb[TR1_BEAR1 + index].set_creature(TRUE);
        tomb[TR1_BEAR1 + index].set_rotation_meshtree(13, ROT_Y);
        tomb[TR1_BEAR1 + index].set_save(TRUE, TRUE, TRUE, FALSE, TRUE);
    }
}
