#include <StdAfx.h>
#include "mg_stick.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_CreatureAnimation CreatureAnimation;
extern TYPE_CreatureJoint CreatureJoint;
extern TYPE_CreatureTilt CreatureTilt;
extern TYPE_CreatureAIInfo CreatureAIInfo;
extern TYPE_CreatureTurn CreatureTurn;
extern TYPE_CreatureMood CreatureMood;
extern TYPE_GetCreatureMood GetCreatureMood;
extern TYPE_CreatureVault CreatureVault;
extern TYPE_DrawAnimatingItem DrawAnimatingItem;
extern TYPE_SoundEffect SoundEffect;
extern TYPE_GetRandomControl GetRandomControl;
extern TYPE_CreatureEffect CreatureEffect;
extern TYPE2_DoBloodSplat DoBloodSplat_2;

#define HP_MGSTICK (27)
#define WORK3_WALK_TURN (ONE_DEGREE*5)
#define WORK3_RUN_TURN (ONE_DEGREE*6)
#define WORK3_ATTACK0_RANGE SQUARE(STEP_L)
#define WORK3_ATTACK1_RANGE SQUARE(WALL_L)
#define WORK3_ATTACK2_RANGE SQUARE(WALL_L*3/2)
#define WORK3_WALK_RANGE SQUARE(WALL_L*2)
#define WORK3_STOP_RANGE SQUARE(WALL_L/2)
#define WORK3_WALK_CHANCE 0x100
#define WORK3_WAIT_CHANCE 0x100
#define WORK3_DIE_ANIM 26
#define WORK3_CLIMB1_ANIM 28
#define WORK3_CLIMB2_ANIM 29
#define WORK3_CLIMB3_ANIM 27
#define WORK3_FALL3_ANIM  30
#define WORK3_TOUCH 0x600
#define WORK3_VAULT_SHIFT 260
#define WORK3_WAIT_ANIM 6
#define WORK3_HIT_DAMAGE 80
#define WORK3_SWIPE_DAMAGE 100

static BITE_INFO work3_hit = { 247,10,11, 10 };

enum WORKER3_STATE {
    ST_WORK3_EMPTY,
    ST_WORK3_STOP,
    ST_WORK3_WALK,
    ST_WORK3_PUNCH2,
    ST_WORK3_AIM2,
    ST_WORK3_WAIT,
    ST_WORK3_AIM1,
    ST_WORK3_AIM0,
    ST_WORK3_PUNCH1,
    ST_WORK3_PUNCH0,
    ST_WORK3_RUN,
    ST_WORK3_DEATH,
    ST_WORK3_CLIMB3,
    ST_WORK3_CLIMB1,
    ST_WORK3_CLIMB2,
    ST_WORK3_FALL3
};

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

    ITEM_INFO* item;
    CREATURE_INFO* worker;
    OBJECT_INFO* slots;
    ANIM_STRUCT* anims;
    AI_INFO info;
    short angle, torso, head, tilt;
    int random;
    short dmg1, dmg2, dmg3, snd1, snd2, snd3;

    item = &Ptr_VetItems[item_number];
    worker = (CREATURE_INFO*)item->data;
    slots = &Ptr_VetObjects[item->object_number];
    angle = torso = head = tilt = 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);
    snd1 = Utils.getObjectProperty(tsu_slots[item->object_number], PTY_SND1);
    snd2 = Utils.getObjectProperty(tsu_slots[item->object_number], PTY_SND2);
    snd3 = Utils.getObjectProperty(tsu_slots[item->object_number], PTY_SND3);
    random = GetRandomControl();

    if (item->hit_points <= 0)
    {
        if (item->current_anim_state != ST_WORK3_DEATH)
        {
            item->anim_number = Ptr_VetObjects[item->object_number].anim_index + WORK3_DIE_ANIM;
            item->frame_number = Ptr_VetAnimations[item->anim_number].frame_base;
            item->current_anim_state = ST_WORK3_DEATH;
        }
    }
    else
    {
        CreatureAIInfo(item, &info);
        GetCreatureMood(item, &info, VIOLENT);
        CreatureMood(item, &info, VIOLENT);
        angle = CreatureTurn(item, worker->maximum_turn);

        switch (item->current_anim_state)
        {
            case ST_WORK3_STOP:
                worker->flags = 0;
                if (info.ahead)
                    torso = info.angle;

                worker->maximum_turn = 0;

                if (worker->mood == MOOD_ESCAPE)
                {
                    item->goal_anim_state = ST_WORK3_RUN;
                }
                else if (worker->mood == MOOD_BORED)
                {
                    if (item->required_anim_state)
                    {
                        item->goal_anim_state = item->required_anim_state;
                    }
                    else if (random < 0x4000)
                    {
                        item->goal_anim_state = ST_WORK3_WALK;
                    }
                    else
                    {
                        item->goal_anim_state = ST_WORK3_WAIT;
                    }
                }
                else if (info.bite && info.distance < WORK3_ATTACK0_RANGE)
                {
                    item->goal_anim_state = ST_WORK3_AIM0;
                }
                else if (info.bite && info.distance < WORK3_ATTACK1_RANGE)
                {
                    item->goal_anim_state = ST_WORK3_AIM1;
                }
                else if (info.bite && info.distance < WORK3_WALK_RANGE)
                {
                    item->goal_anim_state = ST_WORK3_WALK;
                }
                else
                {
                    item->goal_anim_state = ST_WORK3_RUN;
                }
                break;
            case ST_WORK3_WAIT:
                if (info.ahead)
                    torso = info.angle;

                if (worker->mood != MOOD_BORED)
                {
                    item->goal_anim_state = ST_WORK3_STOP;
                }
                else if (random < WORK3_WALK_CHANCE)
                {
                    item->required_anim_state = ST_WORK3_WALK;
                    item->goal_anim_state = ST_WORK3_STOP;
                }
                break;
            case ST_WORK3_WALK:
                if (info.ahead)
                    torso = info.angle;

                worker->maximum_turn = WORK3_WALK_TURN;

                if (worker->mood == MOOD_ESCAPE)
                {
                    item->goal_anim_state = ST_WORK3_RUN;
                }
                else if (worker->mood == MOOD_BORED)
                {
                    if (random < WORK3_WAIT_CHANCE)
                    {
                        item->required_anim_state = ST_WORK3_WAIT;
                        item->goal_anim_state = ST_WORK3_STOP;
                    }
                }
                else if (info.bite && info.distance < WORK3_STOP_RANGE)
                {
                    item->goal_anim_state = ST_WORK3_STOP;
                }
                else if (info.bite && info.distance < WORK3_ATTACK2_RANGE)
                {
                    item->goal_anim_state = ST_WORK3_AIM2;
                }
                else
                {
                    item->goal_anim_state = ST_WORK3_RUN;
                }
                break;
            case ST_WORK3_RUN:
                if (info.ahead)
                    torso = info.angle;

                worker->maximum_turn = WORK3_RUN_TURN;
                tilt = angle / 2;

                if (worker->mood == MOOD_ESCAPE)
                {
                    break;
                }
                else if (worker->mood == MOOD_BORED)
                {
                    item->goal_anim_state = ST_WORK3_WALK;
                }
                else if (info.ahead && info.distance < WORK3_WALK_RANGE)
                {
                    item->goal_anim_state = ST_WORK3_WALK;
                }
                break;
            case ST_WORK3_AIM0:
                if (info.ahead)
                    head = info.angle;

                worker->flags = 0;

                if (info.bite && info.distance < WORK3_ATTACK0_RANGE)
                {
                    item->goal_anim_state = ST_WORK3_PUNCH0;
                }
                else
                {
                    item->goal_anim_state = ST_WORK3_STOP;
                }
                break;
            case ST_WORK3_AIM1:
                if (info.ahead)
                    head = info.angle;

                worker->flags = 0;

                if (info.ahead && info.distance < WORK3_ATTACK1_RANGE)
                {
                    item->goal_anim_state = ST_WORK3_PUNCH1;
                }
                else
                {
                    item->goal_anim_state = ST_WORK3_STOP;
                }
                break;
            case ST_WORK3_AIM2:
                if (info.ahead)
                    head = info.angle;

                worker->flags = 0;

                if (info.bite && info.distance < WORK3_ATTACK2_RANGE)
                {
                    item->goal_anim_state = ST_WORK3_PUNCH2;
                }
                else
                {
                    item->goal_anim_state = ST_WORK3_WALK;
                }
                break;
            case ST_WORK3_PUNCH0:
                if (info.ahead)
                    head = info.angle;

                if (!worker->flags && item->touch_bits)
                {
                    LaraItem->hit_points -= DOUBLE_VALUE_ITEM(dmg1, WORK3_HIT_DAMAGE);
                    LaraItem->hit_status = 1;
                    CreatureEffect(item, &work3_hit, DoBloodSplat_2);
                    if (snd2 != NO_ITEM)
                        SoundEffect(snd2, &item->pos, 0);
                    worker->flags = 1;
                }
                break;
            case ST_WORK3_PUNCH1:
                if (info.ahead)
                    head = info.angle;

                if (!worker->flags && (item->touch_bits & WORK3_TOUCH))
                {
                    LaraItem->hit_points -= DOUBLE_VALUE_ITEM(dmg2, WORK3_HIT_DAMAGE);
                    LaraItem->hit_status = 1;
                    CreatureEffect(item, &work3_hit, DoBloodSplat_2);
                    if (snd1 != NO_ITEM)
                        SoundEffect(snd1, &item->pos, 0);
                    worker->flags = 1;
                }

                if (info.ahead && info.distance > WORK3_ATTACK1_RANGE && info.distance < WORK3_ATTACK2_RANGE)
                    item->goal_anim_state = ST_WORK3_PUNCH2;
                break;
            case ST_WORK3_PUNCH2:
                if (info.ahead)
                    head = info.angle;

                if (worker->flags != 2 && (item->touch_bits & WORK3_TOUCH))
                {
                    LaraItem->hit_points -= DOUBLE_VALUE_ITEM(dmg3, WORK3_SWIPE_DAMAGE);
                    LaraItem->hit_status = 1;
                    CreatureEffect(item, &work3_hit, DoBloodSplat_2);
                    if (snd3 != NO_ITEM)
                        SoundEffect(snd3, &item->pos, 0);
                    worker->flags = 2;
                }
                break;
        }
    }

    CreatureTilt(item, tilt);
    CreatureJoint(item, 0, head);
    CreatureJoint(item, 1, torso);

    if (item->current_anim_state < ST_WORK3_CLIMB3)
    {
        switch (CreatureVault(item_number, angle, 0, WORK3_VAULT_SHIFT))
        {
            case 2:
                item->anim_number = slots->anim_index + WORK3_CLIMB1_ANIM;
                anims = &Ptr_VetAnimations[item->anim_number];
                item->frame_number = anims->frame_base;
                item->current_anim_state = ST_WORK3_CLIMB1;
                worker->maximum_turn = 0;
                break;
            case 3:
                item->anim_number = slots->anim_index + WORK3_CLIMB2_ANIM;
                anims = &Ptr_VetAnimations[item->anim_number];
                item->frame_number = anims->frame_base;
                item->current_anim_state = ST_WORK3_CLIMB2;
                worker->maximum_turn = 0;
                break;
            case 4:
                item->anim_number = slots->anim_index + WORK3_CLIMB3_ANIM;
                anims = &Ptr_VetAnimations[item->anim_number];
                item->frame_number = anims->frame_base;
                item->current_anim_state = ST_WORK3_CLIMB3;
                worker->maximum_turn = 0;
                break;
            case -4:
                item->anim_number = slots->anim_index + WORK3_FALL3_ANIM;
                anims = &Ptr_VetAnimations[item->anim_number];
                item->frame_number = anims->frame_base;
                item->current_anim_state = ST_WORK3_FALL3;
                worker->maximum_turn = 0;
                break;
        }
    }
    else
    {
        CreatureAnimation(item_number, angle, 0);
    }
}

void InitTR2_MGStick(short ItemIndex)
{
    InitialiseCreature(ItemIndex);
}

void InitialiseTR2_GoonStick()
{
    for (int index = 0; index < SLOTS_NUMBER; ++index)
    {
        tomb[TR2_STICK_GOON1 + index].initialise(TR2_STICK_GOON1 + index, FUNCTION_ZONE_BEFORE | FUNCTION_SHADOW, QUERY_VAULT);
        tomb[TR2_STICK_GOON1 + index].set_name("Goon Stick");
        tomb[TR2_STICK_GOON1 + index].set_shadow_size(128);
        tomb[TR2_STICK_GOON1 + index].set_func_initialise(InitTR2_MGStick);
        tomb[TR2_STICK_GOON1 + index].set_func_collide(CreatureCollision);
        tomb[TR2_STICK_GOON1 + index].set_func_control(CtrlTR2_MGStick);
        tomb[TR2_STICK_GOON1 + index].set_func_draw(DrawAnimatingItemCustom, NULL);
        tomb[TR2_STICK_GOON1 + index].set_health(HP_MGSTICK);
        tomb[TR2_STICK_GOON1 + index].set_radius_and_pivot(102, 0);
        tomb[TR2_STICK_GOON1 + index].set_hit_effect(HIT_BLOOD);
        tomb[TR2_STICK_GOON1 + index].set_creature(TRUE);
        tomb[TR2_STICK_GOON1 + index].set_rotation_meshtree(0, ROT_Y);
        tomb[TR2_STICK_GOON1 + index].set_rotation_meshtree(4, ROT_Y);
        tomb[TR2_STICK_GOON1 + index].set_save(TRUE, TRUE, TRUE, FALSE, TRUE);
    }
}