#include <StdAfx.h>
#include "wolf.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_GetRandomControl GetRandomControl;
extern TYPE_CreatureAIInfo CreatureAIInfo;
extern TYPE_GetCreatureMood GetCreatureMood;
extern TYPE_CreatureMood CreatureMood;
extern TYPE_CreatureTurn CreatureTurn;
extern TYPE_SoundEffect SoundEffect;
extern TYPE_CreatureEffect CreatureEffect;
extern TYPE2_DoBloodSplat DoBloodSplat_2;
extern TYPE_CreatureTilt CreatureTilt;
extern TYPE_CreatureJoint CreatureJoint;
extern TYPE_CreatureAnimation CreatureAnimation;

#define WOLF_SLEEP_FRAME 96
#define WOLF_BITE_DAMAGE 100
#define WOLF_POUNCE_DAMAGE 50
#define WOLF_DIE_ANIM 20
#define WOLF_WALK_TURN (2 * ONE_DEGREE) // = 364
#define WOLF_RUN_TURN (5 * ONE_DEGREE) // = 910
#define WOLF_STALK_TURN (2 * ONE_DEGREE) // = 364
#define WOLF_ATTACK_RANGE SQUARE(WALL_L * 3 / 2) // = 2359296
#define WOLF_STALK_RANGE SQUARE(WALL_L * 3) // = 9437184
#define WOLF_BITE_RANGE SQUARE(345) // = 119025
#define WOLF_WAKE_CHANCE 32
#define WOLF_SLEEP_CHANCE 32
#define WOLF_HOWL_CHANCE 384
#define WOLF_TOUCH 0x774F
#define WOLF_HITPOINTS 6
#define WOLF_RADIUS (WALL_L / 3) // = 341
#define WOLF_SMARTNESS 0x2000

static BITE_INFO WolfJawBite = { 0, -14, 174, 6 };

enum WOLF_ANIM {
    WOLF_EMPTY = 0,
    WOLF_STOP = 1,
    WOLF_WALK = 2,
    WOLF_RUN = 3,
    WOLF_JUMP = 4,
    WOLF_STALK = 5,
    WOLF_ATTACK = 6,
    WOLF_HOWL = 7,
    WOLF_SLEEP = 8,
    WOLF_CROUCH = 9,
    WOLF_FASTTURN = 10,
    WOLF_DEATH = 11,
    WOLF_BITE = 12,
};

void InitTR1_Wolf(short item_num)
{
	ITEM_INFO* item = &Ptr_VetItems[item_num];
    InitialiseCreature(item_num);
	item->anim_number = Ptr_VetObjects[item->object_number].anim_index;
	item->frame_number = Ptr_VetAnimations[item->anim_number].frame_base + WOLF_SLEEP_FRAME;
	item->goal_anim_state = WOLF_SLEEP;
	item->current_anim_state = WOLF_SLEEP;
}

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

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

    if (item->hit_points <= 0) {
        if (item->current_anim_state != WOLF_DEATH) {
            item->current_anim_state = WOLF_DEATH;
            item->anim_number = Ptr_VetObjects[item->object_number].anim_index + WOLF_DIE_ANIM
                + (GetRandomControl() / 11000);
            item->frame_number = Ptr_VetAnimations[item->anim_number].frame_base;
        }
    } else {
        AI_INFO info;
        CreatureAIInfo(item, &info);

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

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

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

        if (item->hit_status && snd1 != NO_ITEM) {
			SoundEffect(snd1, &item->pos, 0);
        }

        switch (item->current_anim_state) {
        case WOLF_SLEEP:
			wolf->maximum_turn = 0;
            head = 0;
            if (wolf->mood == MOOD_ESCAPE
                || info.src_zone == info.target_zone) {
                item->required_anim_state = WOLF_CROUCH;
                item->goal_anim_state = WOLF_STOP;
            } else if (GetRandomControl() < WOLF_WAKE_CHANCE) {
                item->required_anim_state = WOLF_WALK;
                item->goal_anim_state = WOLF_STOP;
            }
            break;

        case WOLF_STOP:
			wolf->maximum_turn = 0;
            if (item->required_anim_state) {
                item->goal_anim_state = item->required_anim_state;
            } else {
                item->goal_anim_state = WOLF_WALK;
            }
            break;

        case WOLF_WALK:
            wolf->maximum_turn = WOLF_WALK_TURN;
            if (wolf->mood != MOOD_BORED) {
                item->goal_anim_state = WOLF_STALK;
                item->required_anim_state = WOLF_EMPTY;
            } else if (GetRandomControl() < WOLF_SLEEP_CHANCE) {
                item->required_anim_state = WOLF_SLEEP;
                item->goal_anim_state = WOLF_STOP;
            }
            break;

        case WOLF_CROUCH:
            if (item->required_anim_state) {
                item->goal_anim_state = item->required_anim_state;
            } else if (wolf->mood == MOOD_ESCAPE) {
                item->goal_anim_state = WOLF_RUN;
            } else if (info.distance < WOLF_BITE_RANGE && info.bite) {
                item->goal_anim_state = WOLF_BITE;
            } else if (wolf->mood == MOOD_STALK) {
                item->goal_anim_state = WOLF_STALK;
            } else if (wolf->mood == MOOD_BORED) {
                item->goal_anim_state = WOLF_STOP;
            } else {
                item->goal_anim_state = WOLF_RUN;
            }
            break;

        case WOLF_STALK:
            wolf->maximum_turn = WOLF_STALK_TURN;
            if (wolf->mood == MOOD_ESCAPE) {
                item->goal_anim_state = WOLF_RUN;
            } else if (info.distance < WOLF_BITE_RANGE && info.bite) {
                item->goal_anim_state = WOLF_BITE;
            } else if (info.distance > WOLF_STALK_RANGE) {
                item->goal_anim_state = WOLF_RUN;
            } else if (wolf->mood == MOOD_ATTACK) {
                if (!info.ahead || info.distance > WOLF_ATTACK_RANGE
                    || (info.enemy_facing < FRONT_ARC
                        && info.enemy_facing > -FRONT_ARC)) {
                    item->goal_anim_state = WOLF_RUN;
                }
            } else if (GetRandomControl() < WOLF_HOWL_CHANCE) {
                item->required_anim_state = WOLF_HOWL;
                item->goal_anim_state = WOLF_CROUCH;
            } else if (wolf->mood == MOOD_BORED) {
                item->goal_anim_state = WOLF_CROUCH;
            }
            break;

        case WOLF_RUN:
            wolf->maximum_turn = WOLF_RUN_TURN;
            tilt = angle;
            if (info.ahead && info.distance < WOLF_ATTACK_RANGE) {
                if (info.distance > (WOLF_ATTACK_RANGE / 2)
                    && (info.enemy_facing > FRONT_ARC
                        || info.enemy_facing < -FRONT_ARC)) {
                    item->required_anim_state = WOLF_STALK;
                    item->goal_anim_state = WOLF_CROUCH;
                } else {
                    item->goal_anim_state = WOLF_ATTACK;
                    item->required_anim_state = WOLF_EMPTY;
                }
            } else if (
                wolf->mood == MOOD_STALK && info.distance < WOLF_STALK_RANGE) {
                item->required_anim_state = WOLF_STALK;
                item->goal_anim_state = WOLF_CROUCH;
            } else if (wolf->mood == MOOD_BORED) {
                item->goal_anim_state = WOLF_CROUCH;
            }
            break;

        case WOLF_ATTACK:
			wolf->maximum_turn = 0;
            tilt = angle;
            if (item->required_anim_state == WOLF_EMPTY
                && (item->touch_bits & WOLF_TOUCH)) {
                CreatureEffect(item, &WolfJawBite, DoBloodSplat_2);
                LaraItem->hit_points -= DOUBLE_VALUE_ITEM(dmg1, WOLF_POUNCE_DAMAGE);
                LaraItem->hit_status = 1;
                item->required_anim_state = WOLF_RUN;
            }
            item->goal_anim_state = WOLF_RUN;
            break;

        case WOLF_BITE:
			wolf->maximum_turn = 0;
            if (item->required_anim_state == WOLF_EMPTY
                && (item->touch_bits & WOLF_TOUCH) && info.ahead) {
                CreatureEffect(item, &WolfJawBite, DoBloodSplat_2);
                LaraItem->hit_points -= DOUBLE_VALUE_ITEM(dmg2, WOLF_BITE_DAMAGE);
                LaraItem->hit_status = 1;
                item->required_anim_state = WOLF_CROUCH;
            }
            break;
        }
    }

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

void InitialiseTR1_Wolf()
{
    for (int index = 0; index < SLOTS_NUMBER; ++index)
    {
        tomb[TR1_WOLF1 + index].set_name("Wolf");
        tomb[TR1_WOLF1 + index].initialise(TR1_WOLF1 + index, FUNCTION_ZONE_BEFORE | FUNCTION_SHADOW, 0);
        tomb[TR1_WOLF1 + index].set_shadow_size(128);
        tomb[TR1_WOLF1 + index].set_func_initialise(InitTR1_Wolf);
        tomb[TR1_WOLF1 + index].set_func_collide(CreatureCollision);
        tomb[TR1_WOLF1 + index].set_func_control(CtrlTR1_Wolf);
        tomb[TR1_WOLF1 + index].set_func_draw(DrawAnimatingItemCustom, NULL);
        tomb[TR1_WOLF1 + index].set_health(WOLF_HITPOINTS);
        tomb[TR1_WOLF1 + index].set_radius_and_pivot(WOLF_RADIUS, 375);
        tomb[TR1_WOLF1 + index].set_hit_effect(HIT_BLOOD);
        tomb[TR1_WOLF1 + index].set_creature(TRUE);
        tomb[TR1_WOLF1 + index].set_rotation_meshtree(2, ROT_Y);
        tomb[TR1_WOLF1 + index].set_save(TRUE, TRUE, TRUE, FALSE, TRUE);
    }
}
