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

extern TYPE_DrawAnimatingItem DrawAnimatingItem;
extern TYPE_GetFloor GetFloor;
extern TYPE_GetRandomControl GetRandomControl;
extern TYPE_GetHeight GetHeight;
extern TYPE_GetCeiling GetCeiling;
extern TYPE_ItemNearLara ItemNearLara;
extern TYPE_LaraBurn LaraBurn;
extern TYPE_TriggerDynamic TriggerDynamic;
extern TYPE_KillItem KillItem;
extern TYPE_ItemNewRoom ItemNewRoom;
extern TYPE2_AnimateItem AnimateItem_2;
extern TYPE_KillEffect KillEffect;
extern TYPE_DoBloodSplat DoBloodSplat;
extern TYPE_Richochet Richochet;
extern TYPE_EffectNewRoom EffectNewRoom;
extern TYPE_SoundEffect SoundEffect;
extern TYPE_TriggerRichochetSparks TriggerRichochetSparks;
extern TYPE_mGetAngle mGetAngle;
extern TYPE_TriggerExplosionSparks TriggerExplosionSparks;

#define FLAME_DAMAGE 3
#define KNIFE_DAMAGE 50
#define ROCKET_DAMAGE 100
#define SHARD_DAMAGE 30
#define ROCKET_RANGE WALL_L

void ControlSparkles(short fx_number)
{
    FX_INFO* fx;
    int mesh;

    fx = &Ptr_VetEffects[fx_number];
    mesh = (fx->frame_number - Ptr_VetObjects[fx->object_number].mesh_index) / 2 + 1;
    if (mesh >= Ptr_VetObjects[fx->object_number].nmeshes)
        mesh = 0;
    fx->frame_number = Ptr_VetObjects[fx->object_number].mesh_index + 2 * mesh;
    fx->counter = mesh << 10 | fx->object_number;
    --fx->fallspeed;
    if (!fx->fallspeed)
        KillEffect(fx_number);
    else
        RotateItem(&fx->flag1);
}

void ControlFlameThrower(short fx_number)
{
    FX_INFO* fx;
    void* floors;
    short room_number;
    int speed, index, uw, x, y, z;
    short first, dmg1, dmg2, snd1, snd2;

    fx = &Ptr_VetEffects[fx_number];
    first = MapToFirst(tsu_slots[fx->object_number], SLOTS_NUMBER);

	if (first == TR3_GAS1)
	{
		fx->fallspeed--;

		if (!fx->fallspeed)
		{
			KillEffect(fx_number);
			return;
		}
	}

    speed = (fx->speed * phd_cos_tr2(fx->pos.x_rot)) >> W2V_SHIFT;
    fx->pos.z_pos += (speed * phd_cos_tr2(fx->pos.y_rot)) >> W2V_SHIFT;
    fx->pos.x_pos += (speed * phd_sin_tr2(fx->pos.y_rot)) >> W2V_SHIFT;
    fx->pos.y_pos -= (fx->speed * phd_sin_tr2(fx->pos.x_rot)) >> W2V_SHIFT;

    room_number = fx->room_number;
    floors = GetFloor(fx->pos.x_pos, fx->pos.y_pos, fx->pos.z_pos, &room_number);

    if (fx->pos.y_pos >= GetHeight(floors, fx->pos.x_pos, fx->pos.y_pos, fx->pos.z_pos) ||
        fx->pos.y_pos <= GetCeiling(floors, fx->pos.x_pos, fx->pos.y_pos, fx->pos.z_pos))
    {
        if (first == TR1_MUTANT_BULLET1 || first == TR2_KNIFE1)
        {
            TriggerRichochetSparks((GAME_VECTOR*) &fx->pos, mGetAngle(fx->pos.z_pos, fx->pos.x_pos, LaraItem->pos.z_pos, LaraItem->pos.x_pos) / 16 % 4096, 3, 0);
            snd1 = Utils.getObjectProperty(tsu_slots[fx->object_number], PTY_SND1);
            if (snd1 != NO_ITEM)
                SoundEffect(snd1, &fx->pos, 0);
        }
        else if (first == TR2_FLAME1)
        {
            TriggerDynamic(fx->pos.x_pos, fx->pos.y_pos, fx->pos.z_pos, 13, 255, 255, 255);
        }
        else if (first == TR1_MUTANT_GRENADE1)
        {
			uw = Ptr_VetRoom[fx->room_number].FlagsRoom & SUNDERWATER;
			TriggerExplosionSparks(fx->pos.x_pos, fx->pos.y_pos, fx->pos.z_pos, 3, -2, uw, fx->room_number);
			for (index = 0; index < 3; ++index)
				TriggerExplosionSparks(fx->pos.x_pos, fx->pos.y_pos, fx->pos.z_pos, 2, 0, uw, fx->room_number);
            snd1 = Utils.getObjectProperty(tsu_slots[fx->object_number], PTY_SND1);
            if (snd1 != NO_ITEM)
                SoundEffect(snd1, &fx->pos, 0);
			x = fx->pos.x_pos - LaraItem->pos.x_pos;
			y = fx->pos.y_pos - LaraItem->pos.y_pos;
			z = fx->pos.z_pos - LaraItem->pos.z_pos;
			if (ABS(x) < ROCKET_RANGE && ABS(y) < ROCKET_RANGE && ABS(z) < ROCKET_RANGE && SQUARE(x) + SQUARE(y) + SQUARE(z) < SQUARE(ROCKET_RANGE))
			{
			    dmg2 = Utils.getObjectAttribute(tsu_slots[fx->object_number], ATT_DMG2);
				LaraItem->hit_points -= DOUBLE_VALUE_ITEM(dmg2, ROCKET_DAMAGE / 2);
				LaraItem->hit_status = 1;
			}
        }

        KillEffect(fx_number);
        return;
    }

    if (room_number != fx->room_number)
        EffectNewRoom(fx_number, room_number);

    dmg1 = Utils.getObjectAttribute(tsu_slots[fx->object_number], ATT_DMG1);

    if (first == TR2_FLAME1)
    {
        if (ItemNearLara(&fx->pos, 350))
        {
            LaraItem->hit_points -= DOUBLE_VALUE_ITEM(dmg1, FLAME_DAMAGE);
            LaraItem->hit_status = 1;
            LaraBurn();
        }
        else
        {
            --fx->fallspeed;
            if (fx->fallspeed < 0)
            {
                TriggerDynamic(fx->pos.x_pos, fx->pos.y_pos, fx->pos.z_pos, 13, 255, 255, 255);
                snd1 = Utils.getObjectProperty(tsu_slots[fx->object_number], PTY_SND1);

                if (snd1 != NO_ITEM)
                    SoundEffect(snd1, &fx->pos, 0);
                KillEffect(fx_number);
                return;
            }
        }
        RotateItem(&fx->flag1);
    }
    else if (first == TR1_MUTANT_BULLET1 || first == TR2_KNIFE1)
    {
        if (ItemNearLara(&fx->pos, 200))
        {
            LaraItem->hit_points -= DOUBLE_VALUE_ITEM(dmg1, first == TR1_MUTANT_BULLET1 ? SHARD_DAMAGE : KNIFE_DAMAGE);
            LaraItem->hit_status = 1;

            snd2 = Utils.getObjectProperty(tsu_slots[fx->object_number], PTY_SND2);

            if (snd2 != NO_ITEM)
                SoundEffect(snd2, &fx->pos, 0); // knife hit lara sound
            DoBloodSplat(fx->pos.x_pos, fx->pos.y_pos, fx->pos.z_pos, GetRandomControl() % 4 + 3, LaraItem->pos.y_rot, LaraItem->room_number);
            KillEffect(fx_number);
            return;
        }

		if (first == TR2_KNIFE1)
			fx->pos.z_rot += 30 * ONE_DEGREE;
    }
    else if (first == TR1_MUTANT_GRENADE1)
    {
        if (ItemNearLara(&fx->pos, 200))
        {
			LaraItem->hit_points -= DOUBLE_VALUE_ITEM(dmg1, ROCKET_DAMAGE);
            LaraItem->hit_status = 1;
			if (LaraItem->hit_points > 0)
			{
				SoundEffect(31, &LaraItem->pos, 0);
				tsu_spaz = 5;
				tsu_direction = (WORD) (LaraItem->pos.y_rot - PHD_180 - phd_atan_tr2(fx->pos.z_pos - LaraItem->pos.z_pos, fx->pos.x_pos - LaraItem->pos.x_pos) + PHD_45) / PHD_90;
			}
            snd2 = Utils.getObjectProperty(tsu_slots[fx->object_number], PTY_SND2);

            if (snd2 != NO_ITEM)
                SoundEffect(snd2, &fx->pos, 0);

			uw = Ptr_VetRoom[fx->room_number].FlagsRoom & SUNDERWATER;
			TriggerExplosionSparks(fx->pos.x_pos, fx->pos.y_pos, fx->pos.z_pos, 3, -2, uw, fx->room_number);
			for (index = 0; index < 3; ++index)
				TriggerExplosionSparks(fx->pos.x_pos, fx->pos.y_pos, fx->pos.z_pos, 2, 0, uw, fx->room_number);
            KillEffect(fx_number);
        }
	}
	else if (first == TR3_GAS1)
	{
		if (ItemNearLara(&fx->pos, 350))
			Utils.AddPoison(DOUBLE_VALUE_ITEM(dmg1, 4));
	}
}

void InitialiseTR1_Rocket()
{
    for (int index = 0; index < SLOTS_NUMBER; ++index)
    {
        tomb[TR1_MUTANT_GRENADE1 + index].set_name("Rocket");
        tomb[TR1_MUTANT_GRENADE1 + index].initialise(TR1_MUTANT_GRENADE1 + index, 0, 0);
        tomb[TR1_MUTANT_GRENADE1 + index].set_func_control(ControlFlameThrower);
    }
}

void InitialiseTR1_Shard()
{
    for (int index = 0; index < SLOTS_NUMBER; ++index)
    {
        tomb[TR1_MUTANT_BULLET1 + index].set_name("Shard");
        tomb[TR1_MUTANT_BULLET1 + index].initialise(TR1_MUTANT_BULLET1 + index, 0, 0);
        tomb[TR1_MUTANT_BULLET1 + index].set_func_control(ControlFlameThrower);
    }
}

void InitialiseTR2_Sparkles()
{
    for (int index = 0; index < SLOTS_NUMBER; ++index)
    {
        tomb[TR2_SPARKLE1 + index].set_name("Sparkles");
        tomb[TR2_SPARKLE1 + index].initialise(TR2_SPARKLE1 + index, 0, QUERY_SPRITE);
        tomb[TR2_SPARKLE1 + index].set_func_control(ControlSparkles);
    }
}

void InitialiseTR2_DragonFire()
{
    for (int index = 0; index < SLOTS_NUMBER; ++index)
    {
        tomb[TR2_FLAME1 + index].set_name("Dragon Fire");
        tomb[TR2_FLAME1 + index].initialise(TR2_FLAME1 + index, 0, QUERY_SPRITE);
        tomb[TR2_FLAME1 + index].set_func_control(ControlFlameThrower);
    }
}

void InitialiseTR2_Knife()
{
    for (int index = 0; index < SLOTS_NUMBER; ++index)
    {
        tomb[TR2_KNIFE1 + index].set_name("Knife");
        tomb[TR2_KNIFE1 + index].initialise(TR2_KNIFE1 + index, 0, 0);
        tomb[TR2_KNIFE1 + index].set_func_control(ControlFlameThrower);
    }
}

void InitialiseTR3_Gas()
{
    for (int index = 0; index < SLOTS_NUMBER; ++index)
    {
        tomb[TR3_GAS1 + index].set_name("Gas");
        tomb[TR3_GAS1 + index].initialise(TR3_GAS1 + index, 0, 0);
        tomb[TR3_GAS1 + index].set_func_control(ControlFlameThrower);
    }
}
