#include <StdAfx.h>
#include "mg_dual_revolver.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_CULT3 (150)
#define CULT3_WALK_TURN (ONE_DEGREE*3)
#define CULT3_RUN_TURN (ONE_DEGREE*3)
#define CULT3_WAIT_OUT_ANIM 2
#define CULT3_WAIT_IN_ANIM 3
#define CULT3_DAMAGE 50
#define CULT3_AIM_DUAL_DISTANCE (0x900000)
#define CULT3_RUN_DISTANCE (0x1900000)
#define CULT3_PARTICULAR_AIM_ANGLE (0x2000)  // -32767 / 32767
#define CULT3_OCB_HOLSTER_OUT 0
#define CULT3_OCB_HOLSTER_IN 1

static BITE_INFO cult3_bite_left  = EnemyBite[TROFF_DUAL_GUN_LEFT];
static BITE_INFO cult3_bite_right = EnemyBite[TROFF_DUAL_GUN_RIGHT];

enum CULT3_STATE {
    ST_CULT3_EMPTY,
    ST_CULT3_WAIT_OUT,
    ST_CULT3_WAIT_IN,
    ST_CULT3_WALK,
    ST_CULT3_RUN,
    ST_CULT3_AIM_LEFT,
    ST_CULT3_AIM_RIGHT,
    ST_CULT3_SHOOT_LEFT,
    ST_CULT3_SHOOT_RIGHT,
    ST_CULT3_AIM_DUAL,
    ST_CULT3_SHOOT_DUAL,
    ST_CULT3_DEATH
};

#define LEFT_P -0x1000
#define RIGHT_P 0x1000

void CtrlTR2_MGDualRevolver(short ItemIndex)
{
    if (!CreatureActive(ItemIndex))
        return;

    ITEM_INFO* item = &Ptr_VetItems[ItemIndex];
    CREATURE_INFO* dual = (CREATURE_INFO*)item->data;
    AI_INFO info;
    short angle = 0, head_y = 0, left_y = 0, right_y = 0, torso_y = 0, tilt = 0;
    short dmg1, dmg2, dmg3;

    // get the damage attribute !
    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_CULT3_DEATH)
        {
            item->anim_number = Ptr_VetObjects[item->object_number].anim_index + 32;
            item->frame_number = Ptr_VetAnimations[item->anim_number].frame_base;
            item->current_anim_state = ST_CULT3_DEATH;
        }
    }
    else
    {
        CreatureAIInfo(item, &info);

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

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

        switch (item->current_anim_state)
        {
            case ST_CULT3_WAIT_OUT:
            case ST_CULT3_WAIT_IN:
                dual->maximum_turn = 0;

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

                if (dual->mood != MOOD_BORED || LaraItem->hit_points > 0)
                {
                    if (Targetable(item, &info))
                    {
                        if (info.distance <= CULT3_AIM_DUAL_DISTANCE)
                            item->goal_anim_state = ST_CULT3_AIM_DUAL;
                        else
                            item->goal_anim_state = ST_CULT3_WALK;
                    }
                    else
                    {
                        if (dual->mood == MOOD_ESCAPE)
                        {
                            item->goal_anim_state = ST_CULT3_RUN;
                        }
                        else if (dual->mood == MOOD_ATTACK)
                        {
                            if (info.distance > CULT3_RUN_DISTANCE || !info.ahead)
                                item->goal_anim_state = ST_CULT3_RUN;
                            else
                                item->goal_anim_state = ST_CULT3_WALK;
                        }
                        else if (dual->mood == MOOD_STALK)
                        {
                            item->goal_anim_state = ST_CULT3_WALK;
                        }
                        else if (!info.ahead)
                        {
                            item->goal_anim_state = ST_CULT3_WALK;
                        }
                    }
                }
                else
                {
                    item->goal_anim_state = ST_CULT3_WAIT_IN;
                }
                break;
            case ST_CULT3_WALK:
                dual->maximum_turn = CULT3_WALK_TURN;

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

                if (Targetable(item, &info))
                {
                    if (info.distance < CULT3_AIM_DUAL_DISTANCE || info.src_zone != info.target_zone)
                    {
                        item->goal_anim_state = ST_CULT3_WAIT_OUT;
                    }
                    else
                    {
                        if (info.angle >= 0)
                            item->goal_anim_state = ST_CULT3_AIM_RIGHT;
                        else
                            item->goal_anim_state = ST_CULT3_AIM_LEFT;
                    }
                }
                else if (dual->mood == MOOD_ESCAPE)
                {
                    item->goal_anim_state = ST_CULT3_RUN;
                }
                else if (dual->mood == MOOD_ATTACK || dual->mood == MOOD_STALK)
                {
                    if (info.distance > CULT3_RUN_DISTANCE || !info.ahead)
                        item->goal_anim_state = ST_CULT3_RUN;
                }
                else if (LaraItem->hit_points > 0)
                {
                    if (info.ahead)
                        item->goal_anim_state = ST_CULT3_WAIT_OUT;
                }
                else
                {
                    item->goal_anim_state = ST_CULT3_WAIT_IN;
                }
                break;
            case ST_CULT3_RUN:
                dual->maximum_turn = CULT3_RUN_TURN;

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

                tilt = angle / 4;

                if (Targetable(item, &info))
                {
                    if (info.src_zone == info.target_zone)
                    {
                        if (info.angle >= 0)
                            item->goal_anim_state = ST_CULT3_AIM_RIGHT;
                        else
                            item->goal_anim_state = ST_CULT3_AIM_LEFT;
                    }
                    else
                    {
                        item->goal_anim_state = ST_CULT3_WAIT_OUT;
                    }
                }
                else if (dual->mood != MOOD_BORED)
                {
                    if (info.ahead && info.distance < CULT3_RUN_DISTANCE)
                        item->goal_anim_state = ST_CULT3_WALK;
                }
                else if (LaraItem->hit_points > 0)
                {
                    item->goal_anim_state = ST_CULT3_WAIT_OUT;
                }
                else
                {
                    item->goal_anim_state = ST_CULT3_WAIT_IN;
                }
                break;
            case ST_CULT3_AIM_LEFT:
                dual->flags = 0;

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

                if (Targetable(item, &info))
                    item->goal_anim_state = ST_CULT3_SHOOT_LEFT;
                else
                    item->goal_anim_state = ST_CULT3_WALK;
                break;
            case ST_CULT3_AIM_RIGHT:
                dual->flags = 0;

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

                if (Targetable(item, &info))
                    item->goal_anim_state = ST_CULT3_SHOOT_RIGHT;
                else
                    item->goal_anim_state = ST_CULT3_WALK;
                break;
            case ST_CULT3_SHOOT_LEFT:
                if (info.ahead)
                {
                    head_y = info.angle;
                    left_y = info.angle;
                }

                if (!dual->flags)
                {
                    Utils.EnemyShot(item, &info, &cult3_bite_left, torso_y, DOUBLE_VALUE_ITEM(dmg1, CULT3_DAMAGE));
                    item->fired_weapon = 2;
                    item->reserved_1 = 1;
                    dual->flags = 1;
                }
                break;
            case ST_CULT3_SHOOT_RIGHT:
                if (info.ahead)
                {
                    head_y = info.angle;
                    right_y = info.angle;
                }

                if (!dual->flags)
                {
                    Utils.EnemyShot(item, &info, &cult3_bite_right, torso_y, DOUBLE_VALUE_ITEM(dmg3, CULT3_DAMAGE));
                    item->fired_weapon = 2;
                    item->reserved_1 = 2;
                    dual->flags = 1;
                }
                break;
            case ST_CULT3_AIM_DUAL:
                dual->flags = 0;

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

                if (Targetable(item, &info))
                    item->goal_anim_state = ST_CULT3_SHOOT_DUAL;
                else
                    item->goal_anim_state = ST_CULT3_WAIT_OUT;
                break;
            case ST_CULT3_SHOOT_DUAL:
                if (info.ahead)
                {
                    torso_y = info.angle;
                }

                if (!dual->flags)
                {
                    Utils.EnemyShot(item, &info, &cult3_bite_left, 0, DOUBLE_VALUE_ITEM(dmg2, CULT3_DAMAGE));
                    Utils.EnemyShot(item, &info, &cult3_bite_right, 0, DOUBLE_VALUE_ITEM(dmg2, CULT3_DAMAGE));
                    item->fired_weapon = 4;
                    item->reserved_1 = 3;
                    dual->flags = 1;
                }
                break;
        }
    }

    CreatureTilt(item, tilt);
    CreatureJoint(item, 0, torso_y);
    CreatureJoint(item, 1, left_y);
    CreatureJoint(item, 2, right_y);
    CreatureJoint(item, 3, head_y);
    CreatureAnimation(ItemIndex, angle, 0);
}

void InitTR2_MGDualRevolver(short ItemIndex)
{
    ITEM_INFO* item = &Ptr_VetItems[ItemIndex];
    InitialiseCreature(ItemIndex);
    
    item->anim_number = Ptr_VetObjects[item->object_number].anim_index + CULT3_WAIT_IN_ANIM;

    ANIM_STRUCT* anims = &Ptr_VetAnimations[item->anim_number];
    item->frame_number = anims->frame_base;
    item->current_anim_state = anims->current_anim_state;
    item->goal_anim_state = anims->current_anim_state;
}

void InitialiseTR2_DualGun()
{
    for (int index = 0; index < SLOTS_NUMBER; ++index)
    {
        tomb[TR2_SHOTGUN_GOON1 + index].initialise(TR2_SHOTGUN_GOON1 + index, FUNCTION_SHADOW, QUERY_GUNFLASH);
        tomb[TR2_SHOTGUN_GOON1 + index].set_name("Dual Gun (Boss)");
        tomb[TR2_SHOTGUN_GOON1 + index].set_shadow_size(128);
        tomb[TR2_SHOTGUN_GOON1 + index].set_func_initialise(InitTR2_MGDualRevolver);
        tomb[TR2_SHOTGUN_GOON1 + index].set_func_collide(CreatureCollision);
        tomb[TR2_SHOTGUN_GOON1 + index].set_func_control(CtrlTR2_MGDualRevolver);
        tomb[TR2_SHOTGUN_GOON1 + index].set_bitoffset(TROFF_DUAL_GUN_LEFT | DOUBLE_OFFSET_MUZZLEFLASH);
        tomb[TR2_SHOTGUN_GOON1 + index].set_func_draw(DrawAnimatingItemCustom, NULL);
        tomb[TR2_SHOTGUN_GOON1 + index].set_health(HP_CULT3);
        tomb[TR2_SHOTGUN_GOON1 + index].set_radius_and_pivot(102, 0);
        tomb[TR2_SHOTGUN_GOON1 + index].set_hit_effect(HIT_BLOOD);
        tomb[TR2_SHOTGUN_GOON1 + index].set_creature(TRUE);
        tomb[TR2_SHOTGUN_GOON1 + index].set_rotation_meshtree(0, ROT_Y);
        tomb[TR2_SHOTGUN_GOON1 + index].set_rotation_meshtree(2, ROT_Y);
        tomb[TR2_SHOTGUN_GOON1 + index].set_rotation_meshtree(6, ROT_Y);
        tomb[TR2_SHOTGUN_GOON1 + index].set_rotation_meshtree(10, ROT_Y);
        tomb[TR2_SHOTGUN_GOON1 + index].set_save(TRUE, TRUE, TRUE, FALSE, TRUE);
    }
}