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

extern TYPE_InitialiseCreature InitialiseCreature;
extern TYPE_CreatureCollision CreatureCollision;
extern TYPE_CreatureActive CreatureActive;
extern TYPE_CreatureAIInfo CreatureAIInfo;
extern TYPE_GetCreatureMood GetCreatureMood;
extern TYPE_CreatureMood CreatureMood;
extern TYPE_phd_atan phd_atan;
extern TYPE_GetRandomControl GetRandomControl;
extern TYPE_CreatureKill CreatureKill;
extern TYPE_CreatureJoint CreatureJoint;
extern TYPE2_AnimateItem AnimateItem_2;
extern TYPE_CreatureAnimation CreatureAnimation;
extern TYPE_SoundEffect SoundEffect;
extern TYPE_ExplodingDeath ExplodingDeath;
extern TYPE_DisableBaddieAI DisableBaddieAI;
extern TYPE_KillItem KillItem;

#define ABORTION_DIE_ANIM 13
#define ABORTION_PART_DAMAGE 250
#define ABORTION_ATTACK_DAMAGE 500
#define ABORTION_TOUCH_DAMAGE 5
#define ABORTION_NEED_TURN (ONE_DEGREE * 45) // = 8190
#define ABORTION_TURN (ONE_DEGREE * 3) // = 546
#define ABORTION_ATTACK_RANGE SQUARE(2600) // = 6760000
#define ABORTION_CLOSE_RANGE SQUARE(2 * WALL_L) // = 5062500
#define ABORTION_TLEFT 0x7FF0
#define ABORTION_TRIGHT 0x3FF8000
#define ABORTION_TOUCH (ABORTION_TLEFT | ABORTION_TRIGHT)
#define ABORTION_HITPOINTS 500
#define ABORTION_RADIUS (WALL_L / 3) // = 341
#define ABORTION_SMARTNESS 0x7FFF

enum ABORTION_ANIM {
    ABORTION_EMPTY = 0,
    ABORTION_STOP = 1,
    ABORTION_TURN_L = 2,
    ABORTION_TURN_R = 3,
    ABORTION_ATTACK1 = 4,
    ABORTION_ATTACK2 = 5,
    ABORTION_ATTACK3 = 6,
    ABORTION_FORWARD = 7,
    ABORTION_SET = 8,
    ABORTION_FALL = 9,
    ABORTION_DEATH = 10,
    ABORTION_KILL = 11,
};

void CtrlTR1_Abortion(short item_num)
{
    if (!CreatureActive(item_num))
        return;

    ITEM_INFO* item = &Ptr_VetItems[item_num];
    CREATURE_INFO* abortion = (CREATURE_INFO*) item->data;
    short head = 0;
    short angle = 0;
    short dmg1 = Utils.getObjectAttribute(tsu_slots[item->object_number], ATT_DMG1);
    short dmg2 = Utils.getObjectAttribute(tsu_slots[item->object_number], ATT_DMG2);
    short anim = Utils.getObjectProperty(tsu_slots[item->object_number], PTY_ANIM);
    short snd1 = Utils.getObjectProperty(tsu_slots[item->object_number], PTY_SND1);
    short snd2 = Utils.getObjectProperty(tsu_slots[item->object_number], PTY_SND2);

    if (item->hit_points <= 0) {
        if (item->current_anim_state != ABORTION_DEATH) {
            item->current_anim_state = ABORTION_DEATH;
            item->anim_number =
				Ptr_VetObjects[item->object_number].anim_index + ABORTION_DIE_ANIM;
            item->frame_number = Ptr_VetAnimations[item->anim_number].frame_base;
        }
    } else {
        AI_INFO info;
        CreatureAIInfo(item, &info);

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

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

        angle = phd_atan(
                    abortion->target.z - item->pos.z_pos,
                    abortion->target.x - item->pos.x_pos)
            - item->pos.y_rot;

        if (item->touch_bits) {
            LaraItem->hit_points -= ABORTION_TOUCH_DAMAGE;
            LaraItem->hit_status = 1;
        }

        if (item->hit_status && snd2 != NO_ITEM) {
			SoundEffect(snd2, &item->pos, 0);
        }

        switch (item->current_anim_state) {
        case ABORTION_SET:
            item->goal_anim_state = ABORTION_FALL;
            item->gravity_status = 1;
            break;

        case ABORTION_STOP:
            if (LaraItem->hit_points <= 0) {
                break;
            }

            abortion->flags = 0;
            if (angle > ABORTION_NEED_TURN) {
                item->goal_anim_state = ABORTION_TURN_R;
            } else if (angle < -ABORTION_NEED_TURN) {
                item->goal_anim_state = ABORTION_TURN_L;
            } else if (info.distance >= ABORTION_ATTACK_RANGE) {
                item->goal_anim_state = ABORTION_FORWARD;
            } else if (LaraItem->hit_points > ABORTION_ATTACK_DAMAGE) {
                if (GetRandomControl() < 0x4000) {
                    item->goal_anim_state = ABORTION_ATTACK1;
                } else {
                    item->goal_anim_state = ABORTION_ATTACK2;
                }
            } else if (info.distance < ABORTION_CLOSE_RANGE) {
                item->goal_anim_state = ABORTION_ATTACK3;
            } else {
                item->goal_anim_state = ABORTION_FORWARD;
            }
            break;

        case ABORTION_FORWARD:
            if (angle > ABORTION_NEED_TURN || angle < -ABORTION_NEED_TURN) {
                item->goal_anim_state = ABORTION_STOP;
            } else if (info.distance < ABORTION_ATTACK_RANGE) {
                item->goal_anim_state = ABORTION_STOP;
            }
            break;

        case ABORTION_TURN_L:
            if (!abortion->flags) {
                abortion->flags = item->frame_number;
            } else if (
                item->frame_number - abortion->flags > 13
                && item->frame_number - abortion->flags < 23) {
                item->pos.y_rot -= ONE_DEGREE * 9;
            }

            if (angle > -ABORTION_NEED_TURN) {
                item->goal_anim_state = ABORTION_STOP;
            }
            break;

        case ABORTION_TURN_R:
            if (!abortion->flags) {
                abortion->flags = item->frame_number;
            } else if (
                item->frame_number - abortion->flags > 16
                && item->frame_number - abortion->flags < 23) {
                item->pos.y_rot += ONE_DEGREE * 14;
            }

            if (angle < ABORTION_NEED_TURN) {
                item->goal_anim_state = ABORTION_STOP;
            }
            break;

        case ABORTION_ATTACK1:
            if (!abortion->flags && (item->touch_bits & ABORTION_TRIGHT)) {
                LaraItem->hit_points -= DOUBLE_VALUE_ITEM(dmg1, ABORTION_ATTACK_DAMAGE);
                LaraItem->hit_status = 1;
                abortion->flags = 1;
            }
            break;

        case ABORTION_ATTACK2:
            if (!abortion->flags && (item->touch_bits & ABORTION_TOUCH)) {
                LaraItem->hit_points -= DOUBLE_VALUE_ITEM(dmg2, ABORTION_ATTACK_DAMAGE);
                LaraItem->hit_status = 1;
                abortion->flags = 1;
            }
            break;

        case ABORTION_ATTACK3:
            if ((item->touch_bits & ABORTION_TRIGHT)
                || LaraItem->hit_points <= 0) {
                LaraItem->hit_points = -1;

                if (anim != NO_ITEM) {
					abortion->maximum_turn = 0;
                    CreatureKill(item, 19, ABORTION_KILL, anim);
                    tsu_killer = tsu_slots[item->object_number];
                    return;
                }
            }
            break;
        }
    }

    CreatureJoint(item, 0, head);

    if (item->current_anim_state == ABORTION_FALL) {
        AnimateItem_2(item);

        if (item->pos.y_pos > item->floor) {
            item->goal_anim_state = ABORTION_STOP;
            item->gravity_status = 0;
            item->pos.y_pos = item->floor;
            Camera_Bounce = 500;
        }
    } else {
        CreatureAnimation(item_num, 0, 0);
    }

    if (item->status == STS_DESACTIVATED) {
		if (snd1 != NO_ITEM)
            SoundEffect(snd1, &item->pos, 0);

        ExplodingDeath(item_num, -1, 769);
        DisableBaddieAI(item_num);
        KillItem(item_num);
    }
}

void InitialiseTR1_Abortion()
{
    for (int index = 0; index < SLOTS_NUMBER; ++index)
    {
        tomb[TR1_GIANT_MUTANT1 + index].set_name("Torso");
        tomb[TR1_GIANT_MUTANT1 + index].initialise(TR1_GIANT_MUTANT1 + index, FUNCTION_ZONE_BEFORE | FUNCTION_SHADOW, QUERY_KILLER);
        tomb[TR1_GIANT_MUTANT1 + index].set_shadow_size(85);
        tomb[TR1_GIANT_MUTANT1 + index].set_func_initialise(InitialiseCreature);
        tomb[TR1_GIANT_MUTANT1 + index].set_func_collide(CreatureCollision);
        tomb[TR1_GIANT_MUTANT1 + index].set_func_control(CtrlTR1_Abortion);
        tomb[TR1_GIANT_MUTANT1 + index].set_func_draw(DrawAnimatingItemCustom, NULL);
        tomb[TR1_GIANT_MUTANT1 + index].set_health(ABORTION_HITPOINTS);
        tomb[TR1_GIANT_MUTANT1 + index].set_radius_and_pivot(ABORTION_RADIUS, 0);
        tomb[TR1_GIANT_MUTANT1 + index].set_hit_effect(HIT_BLOOD);
        tomb[TR1_GIANT_MUTANT1 + index].set_creature(TRUE);
        tomb[TR1_GIANT_MUTANT1 + index].set_rotation_meshtree(1, ROT_Y);
        tomb[TR1_GIANT_MUTANT1 + index].set_save(TRUE, TRUE, TRUE, FALSE, TRUE);
    }
}
