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

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

#define HP_DOG (10)
#define DOG_WALK_TURN (ONE_DEGREE*3)
#define DOG_RUN_TURN (ONE_DEGREE*6)
#define DOG_CROUCH_STOP_CHANCE (0x100)
#define DOG_ATK1_STOP_CHANCE (0x500)
#define DOG_WAIT_STOP_CHANCE (0x200)
#define DOG_ATK2_DAMAGE 100
#define DOG_ATK3_DAMAGE 100
#define DOG_JUMPATK_DAMAGE 200
#define DOG_OCB_CROUCH 0x1
#define DOG_ATTACK_RANGE SQUARE(WALL_L/4)
#define DOG_JUMPATK_RANGE SQUARE(9*WALL_L/8)
#define DOG_ATK1_CHANCE (0x300)
#define DOG_WALK_STOP_CHANCE (0xB00)
#define DOG_CROUCH_CHANCE (0x600)
#define DOG_TOUCH (0x13F7000)
#define DOG_MIN_ATK_DISTANCE SQUARE(WALL_L/4)
#define DOG_MAX_ATK_DISTANCE SQUARE(WALL_L)

#define FDOG_ATK1 1
#define FDOG_JUMP 2
#define FDOG_ATK3 3

static BITE_INFO dog_bite = { 0, 30, 141, 20 };

enum DOG_STATE {
    ST_DOG_EMPTY,
    ST_DOG_WALK,
    ST_DOG_RUN,
    ST_DOG_STOP,
    ST_DOG_ATK1,
    ST_DOG_CROUCH,
    ST_DOG_WAIT,
    ST_DOG_ATK2,
    ST_DOG_JUMPATK,
    ST_DOG_ATK3,
    ST_DOG_DEATH
};

void CtrlTR2_Dog(short item_number)
{
    if (!CreatureActive(item_number))
        return;

    ITEM_INFO* item;
    CREATURE_INFO* dog;
    AI_INFO info;
    short head_y, tilt, angle;
    int random = GetRandomControl();
    short dmg1, dmg2, dmg3;

    item = &Ptr_VetItems[item_number];
    dog = (CREATURE_INFO*)item->data;
    head_y = tilt = angle = 0;
    dmg1 = Utils.getObjectAttribute(tsu_slots[item->object_number], ATT_DMG1);
    dmg2 = Utils.getObjectAttribute(tsu_slots[item->object_number], ATT_DMG2);
    dmg3 = Utils.getObjectAttribute(tsu_slots[item->object_number], ATT_DMG3);

    if (item->hit_points <= 0)
    {
        if (item->current_anim_state != ST_DOG_DEATH)
        {
            item->anim_number = Ptr_VetObjects[item->object_number].anim_index + 13;
            item->frame_number = Ptr_VetAnimations[item->anim_number].frame_base;
            item->current_anim_state = ST_DOG_DEATH;
        }
    }
    else
    {
        CreatureAIInfo(item, &info);
        
        if (info.ahead)
        {
            head_y = info.angle;
        }

        GetCreatureMood(item, &info, VIOLENT);
        CreatureMood(item, &info, VIOLENT);
        angle = CreatureTurn(item, dog->maximum_turn);

        switch (item->current_anim_state)
        {
            case ST_DOG_STOP:
                dog->maximum_turn = 0;
                dog->flags = 0;

                if (dog->mood == MOOD_BORED)
                {
                    if (item->required_anim_state)
                    {
                        item->goal_anim_state = item->required_anim_state;
                    }
                    else if (random < 768)
                    {
                        item->goal_anim_state = ST_DOG_ATK1;
                    }
                    else if (random < 1536)
                    {
                        item->goal_anim_state = ST_DOG_CROUCH;
                    }
                    else if (random < 9728)
                    {
                        item->goal_anim_state = ST_DOG_WALK;
                    }
                }
                else if (dog->mood == MOOD_ESCAPE)
                {
                    item->goal_anim_state = ST_DOG_RUN;
                }
                else if (info.distance < DOG_ATTACK_RANGE && info.ahead)
                {
                    item->goal_anim_state = ST_DOG_ATK2;
                }
                else
                {
                    item->goal_anim_state = ST_DOG_RUN;
                }
                break;
            case ST_DOG_WAIT:
                if (dog->mood != MOOD_BORED || random < DOG_WAIT_STOP_CHANCE)
                {
                    item->goal_anim_state = ST_DOG_STOP;
                }
                break;
            case ST_DOG_ATK1:
                if (dog->mood != MOOD_BORED || random < DOG_ATK1_STOP_CHANCE)
                {
                    item->goal_anim_state = ST_DOG_STOP;
                }
                break;
            case ST_DOG_CROUCH:
                if (dog->mood != MOOD_BORED || random < DOG_CROUCH_STOP_CHANCE)
                {
                    item->goal_anim_state = ST_DOG_STOP;
                }
                break;
            case ST_DOG_WALK:
                dog->maximum_turn = DOG_WALK_TURN;

                if (dog->mood != MOOD_BORED)
                {
                    item->goal_anim_state = ST_DOG_RUN;
                }
                else
                {
                    if (random < DOG_ATK1_CHANCE)
                    {
                        item->required_anim_state = ST_DOG_ATK1;
                        item->goal_anim_state = ST_DOG_STOP;
                    }
                    else if (random < DOG_CROUCH_CHANCE)
                    {
                        item->required_anim_state = ST_DOG_CROUCH;
                        item->goal_anim_state = ST_DOG_STOP;
                    }
                    else if (random < DOG_WALK_STOP_CHANCE)
                    {
                        item->goal_anim_state = ST_DOG_STOP;
                    }
                }
                break;
            case ST_DOG_RUN:
                dog->maximum_turn = DOG_RUN_TURN;
                tilt = angle;

                if (dog->mood == MOOD_BORED)
                {
                    item->goal_anim_state = ST_DOG_STOP;
                }
                else if (info.distance < DOG_JUMPATK_RANGE)
                {
                    item->goal_anim_state = ST_DOG_JUMPATK;
                }
                break;
            case ST_DOG_ATK2:
                dog->maximum_turn = 0;

                if (dog->flags != FDOG_ATK1 && info.ahead && (item->touch_bits & DOG_TOUCH))
                {
                    CreatureEffect(item, &dog_bite, DoBloodSplat_2);
                    LaraItem->hit_points -= DOUBLE_VALUE_ITEM(dmg1, DOG_ATK2_DAMAGE);
                    LaraItem->hit_status = 1;
                    dog->flags = FDOG_ATK1;
                }

                if (info.distance > DOG_MIN_ATK_DISTANCE && info.distance < DOG_MAX_ATK_DISTANCE)
                    item->goal_anim_state = ST_DOG_ATK3;
                else
                    item->goal_anim_state = ST_DOG_STOP;
                break;
            case ST_DOG_ATK3:
                dog->maximum_turn = DOG_RUN_TURN;

                if (dog->flags != FDOG_ATK3 && (item->touch_bits & DOG_TOUCH))
                {
                    CreatureEffect(item, &dog_bite, DoBloodSplat_2);
                    LaraItem->hit_points -= DOUBLE_VALUE_ITEM(dmg2, DOG_ATK3_DAMAGE);
                    LaraItem->hit_status = 1;
                    dog->flags = FDOG_ATK3;
                }

                if (info.distance < DOG_MIN_ATK_DISTANCE)
                    item->goal_anim_state = ST_DOG_ATK2;
                break;
            case ST_DOG_JUMPATK:
                if (dog->flags != FDOG_JUMP && (item->touch_bits & DOG_TOUCH))
                {
                    CreatureEffect(item, &dog_bite, DoBloodSplat_2);
                    LaraItem->hit_points -= DOUBLE_VALUE_ITEM(dmg3, DOG_JUMPATK_DAMAGE);
                    LaraItem->hit_status = 1;
                    dog->flags = FDOG_JUMP;
                }

                if (info.distance < DOG_MIN_ATK_DISTANCE)
                {
                    item->goal_anim_state = ST_DOG_ATK2;
                }
                else if (info.distance < DOG_MAX_ATK_DISTANCE)
                {
                    item->goal_anim_state = ST_DOG_ATK3;
                }
                break;
        }
    }

    CreatureTilt(item, tilt);
    CreatureJoint(item, 0, head_y);
    CreatureAnimation(item_number, angle, tilt);
}

void InitialiseTR2_Dog()
{
    for (int index = 0; index < SLOTS_NUMBER; ++index)
    {
        tomb[TR2_DOBERMAN1 + index].set_name("Dog");
        tomb[TR2_DOBERMAN1 + index].initialise(TR2_DOBERMAN1 + index, FUNCTION_SHADOW, 0);
        tomb[TR2_DOBERMAN1 + index].set_shadow_size(128);
        tomb[TR2_DOBERMAN1 + index].set_func_initialise(InitialiseCreature);
        tomb[TR2_DOBERMAN1 + index].set_func_collide(CreatureCollision);
        tomb[TR2_DOBERMAN1 + index].set_func_control(CtrlTR2_Dog);
        tomb[TR2_DOBERMAN1 + index].set_func_draw(DrawAnimatingItemCustom, NULL);
        tomb[TR2_DOBERMAN1 + index].set_health(HP_DOG);
        tomb[TR2_DOBERMAN1 + index].set_radius_and_pivot(341, 300);
        tomb[TR2_DOBERMAN1 + index].set_hit_effect(HIT_BLOOD);
        tomb[TR2_DOBERMAN1 + index].set_creature(TRUE);
        tomb[TR2_DOBERMAN1 + index].set_rotation_meshtree(19, ROT_Y);
        tomb[TR2_DOBERMAN1 + index].set_save(TRUE, TRUE, TRUE, FALSE, TRUE);
    }
}