#include <StdAfx.h>
#include "wk_flamethrower.h"
#include <trng_core.h>
#include "utility.h"
#include "phd_math.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_TriggerDynamic TriggerDynamic;
extern TYPE2_GetJointAbsPosition GetJointAbsPosition_2;
extern TYPE_AddFire AddFire;
extern TYPE_CreateEffect CreateEffect;
extern TYPE_InitialiseItem InitialiseItem;
extern TYPE_CreatureEffect CreatureEffect;
extern TYPE_GetRandomDraw GetRandomDraw;

#define HP_FLAMETHROWER (20)
#define FLAMER_SHOT_DAMAGE 1
#define FLAMER_WALK_TURN (ONE_DEGREE*3)
#define FLAMER_RUN_TURN (ONE_DEGREE*5)
#define FLAMER_RUN_RANGE SQUARE(WALL_L*2)
#define FLAMER_SHOOT1_RANGE SQUARE(WALL_L*3)
#define FLAMER_AWARE_DISTANCE SQUARE(WALL_L)
#define FLAMER_DIE_ANIM 19
#define FLAMER_STOP_ANIM 12
#define SEAL_BURP_STATE 2
#define SEAL_X_OFFSET 0x800

static BITE_INFO flamer_bite = { 0, 308, 32, 9 };
static short FlamethrowerSlot;

enum WORKER2_STATE {
    ST_WORK4_EMPTY,
    ST_WORK4_STOP,
    ST_WORK4_WALK,
    ST_WORK4_RUN,
    ST_WORK4_WAIT,
    ST_WORK4_SHOOT1,
    ST_WORK4_SHOOT2,
    ST_WORK4_DEATH,
    ST_WORK4_AIM1,
    ST_WORK4_AIM2,
    ST_WORK4_AIM3,
    ST_WORK4_SHOOT3
};

short Flame(int x, int y, int z, short speed, short yrot, short room_number)
{
    short fx_number;
    FX_INFO* fx;
    int mesh;

    fx_number = CreateEffect(room_number);
    if (fx_number != NO_ITEM)
    {
        fx = &Ptr_VetEffects[fx_number];
        fx->pos.x_pos = x;
        fx->pos.y_pos = y;
        fx->pos.z_pos = z;
        fx->room_number = room_number;
        fx->pos.x_rot = fx->pos.z_rot = 0;
        fx->pos.y_rot = yrot;
        fx->speed = 200;
        fx->object_number = Utils.getObjects(Utils.getLinks(tsu_slots[FlamethrowerSlot], LNK_OBJECT1));
        mesh = Ptr_VetObjects[fx->object_number].nmeshes * GetRandomDraw() / 32768;
        fx->frame_number = Ptr_VetObjects[fx->object_number].mesh_index + 2 * mesh;
        fx->shade = 14 * 256;
        fx->fallspeed = 20;
        fx->counter = mesh << 10 | fx->object_number;
        Utils.ShootAtLara(fx);
        RotateItem(&fx->flag1);
    }
	return fx_number;
}

// flame dmg instead of pure dmg !
void CtrlTR2_WKFlamethrower(short item_number)
{
    if (!CreatureActive(item_number))
        return;

    ITEM_INFO* item;
    CREATURE_INFO* flame;
    AI_INFO info;
    StrMovePosition pos;
    short angle, head_y, torso_y, tilt;
    int rnd;

    item = &Ptr_VetItems[item_number];
    flame = (CREATURE_INFO*)item->data;
    angle = head_y = torso_y = tilt = 0;
    rnd = GetRandomControl();

    pos.RelX = flamer_bite.x;
    pos.RelY = flamer_bite.y;
    pos.RelZ = flamer_bite.z;
    GetJointAbsPosition_2(item, &pos, flamer_bite.mesh_num);

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

        switch (item->current_anim_state)
        {
            case ST_WORK4_STOP:
                flame->flags = 0;
                flame->maximum_turn = 0;

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

                if (flame->mood == MOOD_ESCAPE)
                {
                    item->goal_anim_state = ST_WORK4_RUN;
                }
                else if (Targetable(item, &info))
                {
                    if (info.distance < FLAMER_SHOOT1_RANGE || info.src_zone != info.target_zone)
                        item->goal_anim_state = ST_WORK4_AIM1;
                    else
                        item->goal_anim_state = ST_WORK4_WALK;
                }
                else if (flame->mood != MOOD_BORED || !info.ahead)
                {
                    if (info.distance <= FLAMER_RUN_RANGE)
                        item->goal_anim_state = ST_WORK4_WALK;
                    else
                        item->goal_anim_state = ST_WORK4_RUN;
                }
                else
                {
                    item->goal_anim_state = ST_WORK4_WAIT;
                }
                break;

            case ST_WORK4_WALK:
                flame->maximum_turn = FLAMER_WALK_TURN;
                flame->flags = 0;
                if (info.ahead)
                {
                    head_y = info.angle;
                }

                if (flame->mood == MOOD_ESCAPE)
                {
                    item->goal_anim_state = ST_WORK4_RUN;
                }
                else if (Targetable(item, &info))
                {
                    if (info.distance < FLAMER_SHOOT1_RANGE || info.src_zone != info.target_zone)
                        item->goal_anim_state = ST_WORK4_STOP;
                    else
                        item->goal_anim_state = ST_WORK4_AIM2;
                }
                else if (flame->mood != MOOD_BORED || !info.ahead)
                {
                    if (info.distance > FLAMER_RUN_RANGE)
                        item->goal_anim_state = ST_WORK4_RUN;
                }
                else
                {
                    item->goal_anim_state = ST_WORK4_STOP;
                }
                break;

            case ST_WORK4_RUN:
                flame->maximum_turn = FLAMER_RUN_TURN;
                tilt = angle / 2;
                if (info.ahead)
                {
                    head_y = info.angle;
                }

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

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

                if (Targetable(item, &info))
                {
                    item->goal_anim_state = ST_WORK4_SHOOT1;
                }
                else
                {
                    if (flame->mood != MOOD_BORED)
                    {
                        item->goal_anim_state = ST_WORK4_STOP;
                    }
                    else if (!info.ahead)
                    {
                        item->goal_anim_state = ST_WORK4_STOP;
                    }
                }
                break;

            case ST_WORK4_SHOOT1:
            case ST_WORK4_SHOOT2:
                if (info.ahead)
                {
                    torso_y = info.angle;
                }

                FlamethrowerSlot = item->object_number;
                CreatureEffect(item, &flamer_bite, Flame);

                break;

            case ST_WORK4_AIM1:
            case ST_WORK4_AIM3:
                flame->flags = 0;

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

                    if (Targetable(item, &info))
                    {
                        item->goal_anim_state = (item->current_anim_state == ST_WORK4_AIM1) ? ST_WORK4_SHOOT1 : ST_WORK4_SHOOT3;
                    }
                    else
                    {
                        item->goal_anim_state = ST_WORK4_STOP;
                    }
                }

                break;

            case ST_WORK4_AIM2:
                flame->flags = 0;

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

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

                break;

            case ST_WORK4_SHOOT3:
                if (item->goal_anim_state != ST_WORK4_STOP && (flame->mood == MOOD_ESCAPE || info.distance > FLAMER_SHOOT1_RANGE || !Targetable(item, &info)))
                {
                    item->goal_anim_state = ST_WORK4_STOP;
                }

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

                FlamethrowerSlot = item->object_number;
                CreatureEffect(item, &flamer_bite, Flame);

                break;
        }
    }

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

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

void InitialiseTR2_GoonFlamethrower()
{
    for (int index = 0; index < SLOTS_NUMBER; ++index)
    {
        short dependency = Utils.getLinks(TR2_FLAMETHROWER1 + index, LNK_OBJECT1);
        if (dependency >= 0 && dependency < TR_OBJECTS_NUMBER && MapToFirst(dependency, SLOTS_NUMBER) == TR2_FLAME1 && tomb[dependency].get_object())
        {
            tomb[TR2_FLAMETHROWER1 + index].set_name("Rig Flamethrower");
            tomb[TR2_FLAMETHROWER1 + index].initialise(TR2_FLAMETHROWER1 + index, FUNCTION_SHADOW, 0);
            tomb[TR2_FLAMETHROWER1 + index].set_shadow_size(128);
            tomb[TR2_FLAMETHROWER1 + index].set_func_initialise(InitTR2_WKFlamethrower);
            tomb[TR2_FLAMETHROWER1 + index].set_func_collide(CreatureCollision);
            tomb[TR2_FLAMETHROWER1 + index].set_func_control(CtrlTR2_WKFlamethrower);
            tomb[TR2_FLAMETHROWER1 + index].set_func_draw(DrawAnimatingItemCustom, NULL);
            tomb[TR2_FLAMETHROWER1 + index].set_health(HP_FLAMETHROWER);
            tomb[TR2_FLAMETHROWER1 + index].set_radius_and_pivot(102, 0);
            tomb[TR2_FLAMETHROWER1 + index].set_hit_effect(HIT_BLOOD);
            tomb[TR2_FLAMETHROWER1 + index].set_creature(TRUE);
            tomb[TR2_FLAMETHROWER1 + index].set_rotation_meshtree(4, ROT_Y);
            tomb[TR2_FLAMETHROWER1 + index].set_rotation_meshtree(13, ROT_Y);
            tomb[TR2_FLAMETHROWER1 + index].set_save(TRUE, TRUE, TRUE, FALSE, TRUE);
        }
    }
}