#include <StdAfx.h>
#include "pierre.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_CreatureTurn CreatureTurn;
extern TYPE_GetRandomControl GetRandomControl;
extern TYPE_Targetable Targetable;
extern TYPE_CreatureTilt CreatureTilt;
extern TYPE_CreatureJoint CreatureJoint;
extern TYPE_CreatureAnimation CreatureAnimation;
extern TYPE2_LOS LOS_2;
extern TYPE_DisableBaddieAI DisableBaddieAI;
extern TYPE_KillItem KillItem;

#define PIERRE_POSE_CHANCE 0x60 // = 96
#define PIERRE_SHOT_DAMAGE 50
#define PIERRE_WALK_TURN (ONE_DEGREE * 3) // = 546
#define PIERRE_RUN_TURN (ONE_DEGREE * 6) // = 1092
#define PIERRE_WALK_RANGE SQUARE(WALL_L * 3) // = 9437184
#define PIERRE_DIE_ANIM 12
#define PIERRE_WIMP_CHANCE 0x2000
#define PIERRE_RUN_HITPOINTS 40
#define PIERRE_DISAPPEAR 10
#define PIERRE_HITPOINTS 70
#define PIERRE_RADIUS (WALL_L / 10) // = 102
#define PIERRE_SMARTNESS 0x7FFF

static BITE_INFO PierreGun1 = EnemyBite[TROFF_PIERRE_LEFT];
static BITE_INFO PierreGun2 = EnemyBite[TROFF_PIERRE_RIGHT];

enum PIERRE_ANIM {
    PIERRE_EMPTY = 0,
    PIERRE_STOP = 1,
    PIERRE_WALK = 2,
    PIERRE_RUN = 3,
    PIERRE_AIM = 4,
    PIERRE_DEATH = 5,
    PIERRE_POSE = 6,
    PIERRE_SHOOT = 7,
};

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

    ITEM_INFO* item = &Ptr_VetItems[item_num];
    CREATURE_INFO* pierre = (CREATURE_INFO*) item->data;
    short head = 0;
    short angle = 0;
    short tilt = 0;
    short dmg1 = Utils.getObjectAttribute(tsu_slots[item->object_number], ATT_DMG1);

	if (item->hit_points <= 4 * Ptr_VetObjects[item->object_number].hit_points / 7
		&& !(item->ocb_bits & 1)) {
        item->hit_points = 4 * Ptr_VetObjects[item->object_number].hit_points / 7;
        pierre->flags++;
    }

    if (item->hit_points <= 0) {
        if (item->current_anim_state != PIERRE_DEATH) {
            item->current_anim_state = PIERRE_DEATH;
            item->anim_number = Ptr_VetObjects[item->object_number].anim_index + PIERRE_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;
        }

        if (pierre->flags) {
            info.target_zone = -1;
            item->hit_status = 1;
        }

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

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

        switch (item->current_anim_state) {
        case PIERRE_STOP:
			pierre->maximum_turn = 0;
            if (item->required_anim_state) {
                item->goal_anim_state = item->required_anim_state;
            } else if (pierre->mood == MOOD_BORED) {
                item->goal_anim_state = GetRandomControl() < PIERRE_POSE_CHANCE
                    ? PIERRE_POSE
                    : PIERRE_WALK;
            } else if (pierre->mood == MOOD_ESCAPE) {
                item->goal_anim_state = PIERRE_RUN;
            } else {
                item->goal_anim_state = PIERRE_WALK;
            }
            break;

        case PIERRE_POSE:
            if (pierre->mood != MOOD_BORED) {
                item->goal_anim_state = PIERRE_STOP;
            } else if (GetRandomControl() < PIERRE_POSE_CHANCE) {
                item->required_anim_state = PIERRE_WALK;
                item->goal_anim_state = PIERRE_STOP;
            }
            break;

        case PIERRE_WALK:
            pierre->maximum_turn = PIERRE_WALK_TURN;
            if (pierre->mood == MOOD_BORED
                && GetRandomControl() < PIERRE_POSE_CHANCE) {
                item->required_anim_state = PIERRE_POSE;
                item->goal_anim_state = PIERRE_STOP;
            } else if (pierre->mood == MOOD_ESCAPE) {
                item->required_anim_state = PIERRE_RUN;
                item->goal_anim_state = PIERRE_STOP;
            } else if (Targetable(item, &info)) {
                item->required_anim_state = PIERRE_AIM;
                item->goal_anim_state = PIERRE_STOP;
            } else if (!info.ahead || info.distance > PIERRE_WALK_RANGE) {
                item->required_anim_state = PIERRE_RUN;
                item->goal_anim_state = PIERRE_STOP;
            }
            break;

        case PIERRE_RUN:
            pierre->maximum_turn = PIERRE_RUN_TURN;
            tilt = angle / 2;
            if (pierre->mood == MOOD_BORED
                && GetRandomControl() < PIERRE_POSE_CHANCE) {
                item->required_anim_state = PIERRE_POSE;
                item->goal_anim_state = PIERRE_STOP;
            } else if (Targetable(item, &info)) {
                item->required_anim_state = PIERRE_AIM;
                item->goal_anim_state = PIERRE_STOP;
            } else if (info.ahead && info.distance < PIERRE_WALK_RANGE) {
                item->required_anim_state = PIERRE_WALK;
                item->goal_anim_state = PIERRE_STOP;
            }
            break;

        case PIERRE_AIM:
            if (item->required_anim_state) {
                item->goal_anim_state = item->required_anim_state;
            } else if (Targetable(item, &info)) {
                item->goal_anim_state = PIERRE_SHOOT;
            } else {
                item->goal_anim_state = PIERRE_STOP;
            }
            break;

        case PIERRE_SHOOT:
            if (!item->required_anim_state) {
				Utils.EnemyShot(item, &info, &PierreGun1, head, DOUBLE_VALUE_ITEM(dmg1, PIERRE_SHOT_DAMAGE / 2));
				Utils.EnemyShot(item, &info, &PierreGun2, head, DOUBLE_VALUE_ITEM(dmg1, PIERRE_SHOT_DAMAGE / 2));
				item->fired_weapon = 4;
				item->reserved_1 = 3;
                item->required_anim_state = PIERRE_AIM;
            }
            if (pierre->mood == MOOD_ESCAPE
                && GetRandomControl() > PIERRE_WIMP_CHANCE) {
                item->required_anim_state = PIERRE_STOP;
            }
            break;
        }
    }

    CreatureTilt(item, tilt);
    CreatureJoint(item, 0, head);
    CreatureAnimation(item_num, angle, 0);

    if (pierre->flags) {
        GAMEVECTOR target;
        target.x = item->pos.x_pos;
        target.y = item->pos.y_pos - WALL_L;
        target.z = item->pos.z_pos;

        GAMEVECTOR start;
        start.x = Camera_Pos.x;
        start.y = Camera_Pos.y;
        start.z = Camera_Pos.z;
		start.room_number = Camera_Pos.room_number;

        if (LOS_2(&start, &target)) {
            pierre->flags = 1;
        } else if (pierre->flags > PIERRE_DISAPPEAR) {
            DisableBaddieAI(item_num);
            KillItem(item_num);
            item->status = STS_DESACTIVATED;
        }
    }
}

void InitialiseTR1_Pierre()
{
    for (int index = 0; index < SLOTS_NUMBER; ++index)
    {
        tomb[TR1_PIERRE1 + index].set_name("Pierre");
        tomb[TR1_PIERRE1 + index].initialise(TR1_PIERRE1 + index, FUNCTION_SHADOW, QUERY_GUNFLASH);
        tomb[TR1_PIERRE1 + index].set_shadow_size(128);
        tomb[TR1_PIERRE1 + index].set_func_initialise(InitialiseCreature);
        tomb[TR1_PIERRE1 + index].set_func_collide(CreatureCollision);
        tomb[TR1_PIERRE1 + index].set_func_control(CtrlTR1_Pierre);
        tomb[TR1_PIERRE1 + index].set_bitoffset(TROFF_PIERRE_LEFT | DOUBLE_OFFSET_MUZZLEFLASH);
        tomb[TR1_PIERRE1 + index].set_func_draw(DrawAnimatingItemCustom, NULL);
        tomb[TR1_PIERRE1 + index].set_health(PIERRE_HITPOINTS);
        tomb[TR1_PIERRE1 + index].set_radius_and_pivot(PIERRE_RADIUS, 0);
        tomb[TR1_PIERRE1 + index].set_hit_effect(HIT_BLOOD);
        tomb[TR1_PIERRE1 + index].set_creature(TRUE);
        tomb[TR1_PIERRE1 + index].set_rotation_meshtree(6, ROT_Y);
        tomb[TR1_PIERRE1 + index].set_save(TRUE, TRUE, TRUE, FALSE, TRUE);
    }
}
