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

extern TYPE_CreatureActive CreatureActive;
extern TYPE_CreatureCollision CreatureCollision;
extern TYPE_CreatureAIInfo CreatureAIInfo;
extern TYPE_GetCreatureMood GetCreatureMood;
extern TYPE_CreatureMood CreatureMood;
extern TYPE_InitialiseCreature InitialiseCreature;
extern TYPE_CreatureAnimation CreatureAnimation;
extern TYPE_CreatureJoint CreatureJoint;
extern TYPE_CreatureTilt CreatureTilt;
extern TYPE_CreatureTurn CreatureTurn;
extern TYPE_DrawAnimatingItem DrawAnimatingItem;
extern TYPE_SoundEffect SoundEffect;
extern TYPE_GetRandomControl GetRandomControl;
extern TYPE_Targetable Targetable;
extern TYPE_ShotLara ShotLara;
extern TYPE_GetAITarget GetAITarget;
extern TYPE_phd_atan phd_atan;
extern TYPE2_GetBoundsAccurate GetBoundsAccurate_2;

#define HP_MC1 (45)
#define HP_MC2 (50)
#define MC1_DAMAGE (8)
#define MC2_DAMAGE (50)
#define MC_WALK_TURN (728)
#define MC_RUN_TURN (1092)
#define MC_SHOOT_DISTANCE (0x400000)
#define MC_WALK_CHANCE (0x100)
#define MC1_DIE_ANIM (14)

static BITE_INFO mercenary1_bite = EnemyBite[TROFF_MERCENARY1];
static BITE_INFO mercenary2_bite = EnemyBite[TROFF_MERCENARY2];

enum MC1_STATE {
    ST_MC1_EMPTY,
    ST_MC1_STOP,
    ST_MC1_WALK,
    ST_MC1_RUN,
    ST_MC1_AIM1,
    ST_MC1_SHOOT1,
    ST_MC1_AIM2,
    ST_MC1_SHOOT2,
    ST_MC1_SHOOT3,
    ST_MC1_SHOOT4,
    ST_MC1_SHOOT5,
    ST_MC1_WIDE_AIM,
    ST_MC1_WALK_AIM,
    ST_MC1_DEATH,
    ST_MC1_SHOOT6
};

enum MC2_STATE {
    ST_MC2_EMPTY,
    ST_MC2_AIM1,
    ST_MC2_STOP,
    ST_MC2_WALK,
    ST_MC2_RUN,
    ST_MC2_AIM2,
    ST_MC2_AIM3,
    ST_MC2_SHOOT1,
    ST_MC2_SHOOT2,
    ST_MC2_SHOOT3,
    ST_MC2_SHOOT4,
    ST_MC2_DEATH,
    ST_MC2_AIM4,
    ST_MC2_SHOOT5,
};

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

    ITEM_INFO* item;
    CREATURE_INFO* mc1;
    AI_INFO info;
    short angle, head_y, torso_y, tilt;
    int random;
    short dmg1, dmg2, dmg3, dmg4, dmg5, dmg6, dmg;

    item = &Ptr_VetItems[item_number];
    mc1 = (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);
    dmg4 = Utils.getObjectAttribute(tsu_slots[item->object_number], ATT_DMG4);
    dmg5 = Utils.getObjectAttribute(tsu_slots[item->object_number], ATT_DMG5);
    dmg6 = Utils.getObjectAttribute(tsu_slots[item->object_number], ATT_DMG6);

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

        switch (item->current_anim_state)
        {
            case ST_MC1_STOP:
                if (info.ahead)
                {
                    head_y = info.angle;
                }

                mc1->maximum_turn = 0;

                if (mc1->mood == MOOD_ESCAPE)
                {
                    item->goal_anim_state = ST_MC1_RUN;
                }
                else if (Targetable(item, &info))
                {
                    if (info.distance > MC_SHOOT_DISTANCE)
                    {
                        item->goal_anim_state = ST_MC1_WALK;
                        break;
                    }
                    
                    random = GetRandomControl();
                    if (random >= 0x2000)
                    {
                        if (random >= 0x4000)
                            item->goal_anim_state = ST_MC1_WIDE_AIM;
                        else
                            item->goal_anim_state = ST_MC1_SHOOT2;
                    }
                    else
                    {
                        item->goal_anim_state = ST_MC1_SHOOT1;
                    }
                }
                else
                {
                    if (mc1->mood != MOOD_BORED)
                    {
                        item->goal_anim_state = ST_MC1_RUN;
                    }
                    else if (!info.ahead)
                    {
                        item->goal_anim_state = ST_MC1_WALK;
                    }
                    else
                    {
                        item->goal_anim_state = ST_MC1_STOP;
                    }
                }
                break;
            case ST_MC1_WALK:
                if (info.ahead)
                {
                    head_y = info.angle;
                }

                mc1->maximum_turn = MC_WALK_TURN;

                if (mc1->mood == MOOD_ESCAPE)
                {
                    item->goal_anim_state = ST_MC1_RUN;
                }
                else if (Targetable(item, &info))
                {
                    if (info.distance <= MC_SHOOT_DISTANCE || info.src_zone != info.target_zone)
                    {
                        item->goal_anim_state = ST_MC1_STOP;
                    }
                    else
                    {
                        item->goal_anim_state = ST_MC1_WALK_AIM;
                    }
                }
                else if (mc1->mood != MOOD_BORED)
                {
                    item->goal_anim_state = ST_MC1_RUN;
                }
                else
                {
                    if (info.ahead)
                    {
                        item->goal_anim_state = ST_MC1_WALK;
                    }
                    else
                    {
                        item->goal_anim_state = ST_MC1_STOP;
                    }
                }
                break;
            case ST_MC1_RUN:
                if (info.ahead)
                {
                    head_y = info.angle;
                }

                mc1->maximum_turn = MC_RUN_TURN;
                tilt = (angle / 2);

                if (mc1->mood != MOOD_ESCAPE)
                {
                    if (Targetable(item, &info))
                    {
                        item->goal_anim_state = ST_MC1_STOP;
                    }
                    else if (mc1->mood == MOOD_BORED)
                    {
                        item->goal_anim_state = ST_MC1_WALK;
                    }
                }
                break;

            case ST_MC1_SHOOT1:
            case ST_MC1_SHOOT2:
            case ST_MC1_SHOOT3:
            case ST_MC1_SHOOT4:
                if (info.ahead)
                {
                    torso_y = info.angle;
                }

				if (item->current_anim_state == ST_MC1_SHOOT1)
					dmg = dmg1;
				else if (item->current_anim_state == ST_MC1_SHOOT2)
					dmg = dmg4;
				else if (item->current_anim_state == ST_MC1_SHOOT3)
					dmg = dmg5;
				else
					dmg = dmg6;
                if (!Utils.EnemyShot(item, &info, &mercenary1_bite, torso_y, DOUBLE_VALUE_ITEM(dmg, MC1_DAMAGE)))
                    item->goal_anim_state = ST_MC1_STOP;
                item->fired_weapon = 2;
                break;

            case ST_MC1_SHOOT5:
            case ST_MC1_SHOOT6:
                if (info.ahead)
                {
                    torso_y = info.angle;
                }

                if (!Utils.EnemyShot(item, &info, &mercenary1_bite, torso_y, DOUBLE_VALUE_ANIM(item->current_anim_state, ST_MC1_SHOOT5, DOUBLE_VALUE_ITEM(dmg2, MC1_DAMAGE), DOUBLE_VALUE_ITEM(dmg3, MC1_DAMAGE))))
                    item->goal_anim_state = ST_MC1_WALK;
                item->fired_weapon = 2;

                if (info.distance < MC_SHOOT_DISTANCE)
                    item->goal_anim_state = ST_MC1_WALK;
                break;
        }
    }

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

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

    ITEM_INFO* item;
    CREATURE_INFO* mc2;
    AI_INFO info;
    short angle, head_y, torso_y, tilt;
    int random;
    short dmg1, dmg2, dmg3, dmg4, dmg5, dmg;

    item = &Ptr_VetItems[item_number];
    mc2 = (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);
    dmg4 = Utils.getObjectAttribute(tsu_slots[item->object_number], ATT_DMG4);
    dmg5 = Utils.getObjectAttribute(tsu_slots[item->object_number], ATT_DMG5);
    random = GetRandomControl();

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

        switch (item->current_anim_state)
        {
            case ST_MC2_STOP:
                mc2->maximum_turn = 0;
                if (info.ahead)
                {
                    head_y = info.angle;
                }

                if (mc2->mood == MOOD_ESCAPE)
                {
                    item->goal_anim_state = ST_MC2_RUN;
                }
                else if (Targetable(item, &info))
                {
                    if (info.distance <= MC_SHOOT_DISTANCE || random >= 0x4000)
                    {
                        if (random >= 0x2000)
                        {
                            if (random >= 0x5000)
                                item->goal_anim_state = ST_MC2_AIM4;
                            else
                                item->goal_anim_state = ST_MC2_SHOOT2;
                        }
                        else
                        {
                            item->goal_anim_state = ST_MC2_SHOOT1;
                        }
                    }
                    else
                    {
                        item->goal_anim_state = ST_MC2_WALK;
                    }
                }
                else
                {
                    if (mc2->mood != MOOD_BORED)
                        item->goal_anim_state = ST_MC2_RUN;
                    else if (!info.ahead || random < MC_WALK_CHANCE)
                        item->goal_anim_state = ST_MC2_WALK;
                }
                break;
            case ST_MC2_WALK:
                mc2->maximum_turn = MC_WALK_TURN;
                if (info.ahead)
                {
                    head_y = info.angle;
                }

                if (mc2->mood == MOOD_ESCAPE)
                {
                    item->goal_anim_state = ST_MC2_RUN;
                }
                else if (Targetable(item, &info))
                {
                    if (info.distance < MC_SHOOT_DISTANCE || info.src_zone == info.target_zone || random < 1024)
                        item->goal_anim_state = ST_MC2_STOP;
                    else
                        item->goal_anim_state = ST_MC2_AIM1;
                }
                else if (mc2->mood != MOOD_BORED)
                {
                    item->goal_anim_state = ST_MC2_RUN;
                }
                else if (info.ahead && random < 1024)
                {
                    item->goal_anim_state = ST_MC2_STOP;
                }
                break;
            case ST_MC2_RUN:
                mc2->maximum_turn = MC_RUN_TURN;
                tilt = (angle / 2);

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

                if (mc2->mood != MOOD_ESCAPE && (mc2->mood == MOOD_BORED || Targetable(item, &info)))
                    item->goal_anim_state = ST_MC2_STOP;
                break;
            case ST_MC2_AIM1:
            case ST_MC2_AIM2:
            case ST_MC2_AIM3:
                mc2->flags = 0;

                if (info.ahead)
                {
                    torso_y = info.angle;
                }
                break;
            case ST_MC2_SHOOT1:
            case ST_MC2_SHOOT2:
            case ST_MC2_SHOOT5:
                if (info.ahead)
                {
                    torso_y = info.angle;
                }
                if (!mc2->flags)
                {
					if (item->current_anim_state == ST_MC2_SHOOT1)
						dmg = dmg1;
					else if (item->current_anim_state == ST_MC2_SHOOT2)
						dmg = dmg4;
					else
						dmg = dmg5;
                    if (!Utils.EnemyShot(item, &info, &mercenary2_bite, torso_y, DOUBLE_VALUE_ITEM(dmg, MC2_DAMAGE)) || random < 0x2000)
                        item->goal_anim_state = ST_MC2_STOP;

                    item->fired_weapon = 2;
                    mc2->flags = 1;
                }
                break;
            case ST_MC2_SHOOT3:
                if (info.ahead)
                {
                    torso_y = info.angle;
                }

                if (mc2->flags != 1)
                {
                    if (!Utils.EnemyShot(item, &info, &mercenary2_bite, torso_y, DOUBLE_VALUE_ITEM(dmg2, MC2_DAMAGE)))
                        item->goal_anim_state = ST_MC2_WALK;
                    item->fired_weapon = 2;
                    mc2->flags = 1;
                }
                if (info.distance < MC_SHOOT_DISTANCE)
                    item->goal_anim_state = ST_MC2_WALK;
                break;
            case ST_MC2_AIM4:
                mc2->flags = 0;

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

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

                if (mc2->flags != 2)
                {
                    if (!Utils.EnemyShot(item, &info, &mercenary2_bite, torso_y, DOUBLE_VALUE_ITEM(dmg3, MC2_DAMAGE)))
                        item->goal_anim_state = ST_MC2_WALK;
                    item->fired_weapon = 2;
                    mc2->flags = 2;
                }
                if (info.distance < MC_SHOOT_DISTANCE)
                    item->goal_anim_state = ST_MC2_WALK;
                break;
        }
    }

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

void InitialiseTR2_Mercenary1()
{
    for (int index = 0; index < SLOTS_NUMBER; ++index)
    {
        tomb[TR2_MERCENARY1 + index].set_name("Mercenary 1");
        tomb[TR2_MERCENARY1 + index].initialise(TR2_MERCENARY1 + index, FUNCTION_SHADOW, QUERY_GUNFLASH);
        tomb[TR2_MERCENARY1 + index].set_shadow_size(128);
        tomb[TR2_MERCENARY1 + index].set_func_initialise(InitialiseCreature);
        tomb[TR2_MERCENARY1 + index].set_func_collide(CreatureCollision);
        tomb[TR2_MERCENARY1 + index].set_func_control(CtrlTR2_Mercenary1);
        tomb[TR2_MERCENARY1 + index].set_bitoffset(TROFF_MERCENARY1);
        tomb[TR2_MERCENARY1 + index].set_func_draw(DrawAnimatingItemCustom, NULL);
        tomb[TR2_MERCENARY1 + index].set_health(HP_MC1);
        tomb[TR2_MERCENARY1 + index].set_radius_and_pivot(102, 0);
        tomb[TR2_MERCENARY1 + index].set_hit_effect(HIT_BLOOD);
        tomb[TR2_MERCENARY1 + index].set_creature(TRUE);
        tomb[TR2_MERCENARY1 + index].set_rotation_meshtree(6, ROT_Y);
        tomb[TR2_MERCENARY1 + index].set_rotation_meshtree(8, ROT_Y);
        tomb[TR2_MERCENARY1 + index].set_save(TRUE, TRUE, TRUE, FALSE, TRUE);
    }
}

void InitialiseTR2_Mercenary2()
{
    for (int index = 0; index < SLOTS_NUMBER; ++index)
    {
        tomb[TR2_MERCENARY_BLACK_MASK1 + index].set_name("Mercenary 2");
        tomb[TR2_MERCENARY_BLACK_MASK1 + index].initialise(TR2_MERCENARY_BLACK_MASK1 + index, FUNCTION_SHADOW, QUERY_GUNFLASH);
        tomb[TR2_MERCENARY_BLACK_MASK1 + index].set_shadow_size(128);
        tomb[TR2_MERCENARY_BLACK_MASK1 + index].set_func_initialise(InitialiseCreature);
        tomb[TR2_MERCENARY_BLACK_MASK1 + index].set_func_collide(CreatureCollision);
        tomb[TR2_MERCENARY_BLACK_MASK1 + index].set_func_control(CtrlTR2_Mercenary2);
        tomb[TR2_MERCENARY_BLACK_MASK1 + index].set_bitoffset(TROFF_MERCENARY2);
        tomb[TR2_MERCENARY_BLACK_MASK1 + index].set_func_draw(DrawAnimatingItemCustom, NULL);
        tomb[TR2_MERCENARY_BLACK_MASK1 + index].set_health(HP_MC2);
        tomb[TR2_MERCENARY_BLACK_MASK1 + index].set_radius_and_pivot(102, 0);
        tomb[TR2_MERCENARY_BLACK_MASK1 + index].set_hit_effect(HIT_BLOOD);
        tomb[TR2_MERCENARY_BLACK_MASK1 + index].set_creature(TRUE);
        tomb[TR2_MERCENARY_BLACK_MASK1 + index].set_rotation_meshtree(6, ROT_Y);
        tomb[TR2_MERCENARY_BLACK_MASK1 + index].set_rotation_meshtree(8, ROT_Y);
        tomb[TR2_MERCENARY_BLACK_MASK1 + index].set_save(TRUE, TRUE, TRUE, FALSE, TRUE);
    }
}