#include <StdAfx.h>
#include "wk_machinegun.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_DrawAnimatingItem DrawAnimatingItem;
extern TYPE_SoundEffect SoundEffect;
extern TYPE_GetRandomControl GetRandomControl;
extern TYPE_Targetable Targetable;
extern TYPE_ShotLara ShotLara;

#define HP_WORK2 (20)
#define WORK2_WALK_TURN (ONE_DEGREE*3)
#define WORK2_RUN_TURN (910)
#define WORK2_DAMAGE (30)
#define WORK2_RUN_DISTANCE (0x400000)
#define WORK2_SHOOT_DISTANCE (0x900000)
#define WORK2_DEAD_ANIM 19
#define WORK2_STOP_ANIM 12

static BITE_INFO work2_bite = EnemyBite[TROFF_WKMACHINEGUN];

enum WORKER2_STATE {
    ST_WORK2_EMPTY,
    ST_WORK2_STOP,
    ST_WORK2_WALK,
    ST_WORK2_RUN,
    ST_WORK2_WAIT,
    ST_WORK2_SHOOT1,
    ST_WORK2_SHOOT2,
    ST_WORK2_DEATH,
    ST_WORK2_AIM1,
    ST_WORK2_AIM2,
    ST_WORK2_AIM3,
    ST_WORK2_SHOOT3
};

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

    ITEM_INFO* item;
    CREATURE_INFO* machinegun;
    AI_INFO info;
    short angle, head_y, torso_y, tilt;
    short dmg1, dmg2, dmg3;

    item = &Ptr_VetItems[item_number];
    machinegun = (CREATURE_INFO*)item->data;
    angle = head_y = torso_y = 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);

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

        switch (item->current_anim_state)
        {
            case ST_WORK2_STOP:
                machinegun->flags = 0;
                machinegun->maximum_turn = 0;

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

                if (machinegun->mood == MOOD_ESCAPE)
                {
                    item->goal_anim_state = ST_WORK2_RUN;
                }
                else if (Targetable(item, &info))
                {
                    if (info.distance < WORK2_SHOOT_DISTANCE || info.src_zone != info.target_zone)
                        item->goal_anim_state = (GetRandomControl() < 0x4000) ? ST_WORK2_AIM1 : ST_WORK2_AIM3;
                    else
                        item->goal_anim_state = ST_WORK2_WALK;
                }
                else if (machinegun->mood != MOOD_BORED || !info.ahead)
                {
                    if (info.distance <= WORK2_RUN_DISTANCE)
                        item->goal_anim_state = ST_WORK2_WALK;
                    else
                        item->goal_anim_state = ST_WORK2_RUN;
                }
                else
                {
                    item->goal_anim_state = ST_WORK2_WAIT;
                }
                break;

            case ST_WORK2_WALK:
                machinegun->maximum_turn = WORK2_WALK_TURN;
                machinegun->flags = 0;
                if (info.ahead)
                {
                    head_y = info.angle;
                }

                if (machinegun->mood == MOOD_ESCAPE)
                {
                    item->goal_anim_state = ST_WORK2_RUN;
                }
                else if (Targetable(item, &info))
                {
                    if (info.distance < WORK2_SHOOT_DISTANCE || info.src_zone != info.target_zone)
                        item->goal_anim_state = ST_WORK2_STOP;
                    else
                        item->goal_anim_state = ST_WORK2_AIM2;
                }
                else if (machinegun->mood != MOOD_BORED || !info.ahead)
                {
                    if (info.distance > WORK2_RUN_DISTANCE)
                        item->goal_anim_state = ST_WORK2_RUN;
                }
                else
                {
                    item->goal_anim_state = ST_WORK2_STOP;
                }
                break;

            case ST_WORK2_RUN:
                machinegun->maximum_turn = WORK2_RUN_TURN;
                tilt = angle / 2;
                if (info.ahead)
                {
                    head_y = info.angle;
                }

                if (machinegun->mood != MOOD_ESCAPE)
                {
                    if (Targetable(item, &info))
                    {
                        item->goal_anim_state = ST_WORK2_WALK;
                    }
                    else if (machinegun->mood == MOOD_BORED || machinegun->mood == MOOD_STALK)
                    {
                        item->goal_anim_state = ST_WORK2_WALK;
                    }
                }
                break;

            case ST_WORK2_WAIT:
                if (info.ahead)
                {
                    head_y = info.angle;
                }

                if (Targetable(item, &info))
                {
                    item->goal_anim_state = ST_WORK2_SHOOT1;
                }
                else
                {
                    if (machinegun->mood != MOOD_BORED)
                    {
                        item->goal_anim_state = ST_WORK2_STOP;
                    }
                    else if (!info.ahead)
                    {
                        item->goal_anim_state = ST_WORK2_STOP;
                    }
                }
                break;

            case ST_WORK2_AIM1:
            case ST_WORK2_AIM3:
                machinegun->flags = 0;

                if (info.ahead)
                {
                    torso_y = info.angle;

                    if (Targetable(item, &info))
                    {
                        item->goal_anim_state = (item->current_anim_state == ST_WORK2_AIM1) ? ST_WORK2_SHOOT1 : ST_WORK2_SHOOT3;
                    }
                    else
                    {
                        item->goal_anim_state = ST_WORK2_STOP;
                    }
                }

                break;

            case ST_WORK2_AIM2:
                machinegun->flags = 0;

                if (info.ahead)
                {
                    torso_y = info.angle;

                    if (Targetable(item, &info))
                    {
                        item->goal_anim_state = ST_WORK2_SHOOT2;
                    }
                    else
                    {
                        item->goal_anim_state = ST_WORK2_WALK;
                    }
                }

                break;

            case ST_WORK2_SHOOT1:
            case ST_WORK2_SHOOT2:
                if (info.ahead)
                {
                    torso_y = info.angle;
                }

                if (machinegun->flags)
                {
                    machinegun->flags--;
                }
                else
                {
                    Utils.EnemyShot(item, &info, &work2_bite, torso_y, DOUBLE_VALUE_ANIM(item->current_anim_state, ST_WORK2_SHOOT1, DOUBLE_VALUE_ITEM(dmg1, WORK2_DAMAGE), DOUBLE_VALUE_ITEM(dmg3, WORK2_DAMAGE)));
                    item->fired_weapon = 2;
                    machinegun->flags = 5;
                }

                break;

            case ST_WORK2_SHOOT3:
                if (item->goal_anim_state != ST_WORK2_STOP && (machinegun->mood == MOOD_ESCAPE || info.distance > WORK2_SHOOT_DISTANCE || !Targetable(item, &info)))
                {
                    item->goal_anim_state = ST_WORK2_STOP;
                }

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

                if (machinegun->flags)
                {
                    machinegun->flags--;
                }
                else
                {
                    Utils.EnemyShot(item, &info, &work2_bite, torso_y, DOUBLE_VALUE_ITEM(dmg2, WORK2_DAMAGE));
                    item->fired_weapon = 2;
                    machinegun->flags = 5;
                }
                break;
        }
    }

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

void InitTR2_WKMachineGun(short item_number)
{
    InitialiseCreature(item_number);
}

void InitialiseTR2_GoonMachineGun()
{
    for (int index = 0; index < SLOTS_NUMBER; ++index)
    {
        tomb[TR2_RIG_WORKER_BLUE_JEANS1 + index].initialise(TR2_RIG_WORKER_BLUE_JEANS1 + index, FUNCTION_SHADOW, QUERY_GUNFLASH);
        tomb[TR2_RIG_WORKER_BLUE_JEANS1 + index].set_name("Goon Machine Gun");
        tomb[TR2_RIG_WORKER_BLUE_JEANS1 + index].set_shadow_size(128);
        tomb[TR2_RIG_WORKER_BLUE_JEANS1 + index].set_func_initialise(InitTR2_WKMachineGun);
        tomb[TR2_RIG_WORKER_BLUE_JEANS1 + index].set_func_collide(CreatureCollision);
        tomb[TR2_RIG_WORKER_BLUE_JEANS1 + index].set_func_control(CtrlTR2_WKMachineGun);
        tomb[TR2_RIG_WORKER_BLUE_JEANS1 + index].set_bitoffset(TROFF_WKMACHINEGUN);
        tomb[TR2_RIG_WORKER_BLUE_JEANS1 + index].set_func_draw(DrawAnimatingItemCustom, NULL);
        tomb[TR2_RIG_WORKER_BLUE_JEANS1 + index].set_health(HP_WORK2);
        tomb[TR2_RIG_WORKER_BLUE_JEANS1 + index].set_radius_and_pivot(102, 0);
        tomb[TR2_RIG_WORKER_BLUE_JEANS1 + index].set_hit_effect(HIT_BLOOD);
        tomb[TR2_RIG_WORKER_BLUE_JEANS1 + index].set_creature(TRUE);
        tomb[TR2_RIG_WORKER_BLUE_JEANS1 + index].set_rotation_meshtree(4, ROT_Y);
        tomb[TR2_RIG_WORKER_BLUE_JEANS1 + index].set_rotation_meshtree(13, ROT_Y);
        tomb[TR2_RIG_WORKER_BLUE_JEANS1 + index].set_save(TRUE, TRUE, TRUE, FALSE, TRUE);
    }
}