#include <StdAfx.h>
#include "skate_kid.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_SoundEffect SoundEffect;
extern TYPE_Targetable Targetable;
extern TYPE_GetRandomControl GetRandomControl;
extern TYPE_CreatureJoint CreatureJoint;
extern TYPE_CreatureAnimation CreatureAnimation;
extern TYPE_ItemNewRoom ItemNewRoom;

#define SKATE_KID_STOP_SHOT_DAMAGE 50
#define SKATE_KID_SKATE_SHOT_DAMAGE 40
#define SKATE_KID_STOP_RANGE SQUARE(WALL_L * 4) // = 16777216
#define SKATE_KID_DONT_STOP_RANGE SQUARE(WALL_L * 5 / 2) // = 6553600
#define SKATE_KID_TOO_CLOSE SQUARE(WALL_L) // = 1048576
#define SKATE_KID_SKATE_TURN (ONE_DEGREE * 4) // = 728
#define SKATE_KID_PUSH_CHANCE 0x200
#define SKATE_KID_SKATE_CHANCE 0x400
#define SKATE_KID_DIE_ANIM 13
#define SKATE_KID_HITPOINTS 125
#define SKATE_KID_RADIUS (WALL_L / 5) // = 204
#define SKATE_KID_SMARTNESS 0x7FFF

static BITE_INFO KidGun1 = EnemyBite[TROFF_SKATE_KID_LEFT];
static BITE_INFO KidGun2 = EnemyBite[TROFF_SKATE_KID_RIGHT];

enum SKATE_KID_ANIM {
    SKATE_KID_STOP = 0,
    SKATE_KID_SHOOT = 1,
    SKATE_KID_SKATE = 2,
    SKATE_KID_PUSH = 3,
    SKATE_KID_SHOOT2 = 4,
    SKATE_KID_DEATH = 5,
};

void InitTR1_SkateKid(short item_num)
{
    InitialiseCreature(item_num);
}

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

    ITEM_INFO* item = &Ptr_VetItems[item_num];
    CREATURE_INFO* kid = (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 snd1 = Utils.getObjectProperty(tsu_slots[item->object_number], PTY_SND1);

    if (item->hit_points <= 0) {
        if (item->current_anim_state != SKATE_KID_DEATH) {
            item->current_anim_state = SKATE_KID_DEATH;
            item->anim_number =
                Ptr_VetObjects[item->object_number].anim_index + SKATE_KID_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 = CreatureTurn(item, kid->maximum_turn);

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

        switch (item->current_anim_state) {
        case SKATE_KID_STOP:
			kid->maximum_turn = 0;
            kid->flags = 0;
            if (item->required_anim_state) {
                item->goal_anim_state = item->required_anim_state;
            } else if (Targetable(item, &info)) {
                item->goal_anim_state = SKATE_KID_SHOOT;
            } else {
                item->goal_anim_state = SKATE_KID_SKATE;
            }
            break;

        case SKATE_KID_SKATE:
			kid->maximum_turn = SKATE_KID_SKATE_TURN;
            kid->flags = 0;
            if (GetRandomControl() < SKATE_KID_PUSH_CHANCE) {
                item->goal_anim_state = SKATE_KID_PUSH;
            } else if (Targetable(item, &info)) {
                if (info.distance > SKATE_KID_DONT_STOP_RANGE
                    && info.distance < SKATE_KID_STOP_RANGE
                    && kid->mood != MOOD_ESCAPE) {
                    item->goal_anim_state = SKATE_KID_STOP;
                } else {
                    item->goal_anim_state = SKATE_KID_SHOOT2;
                }
            }
            break;

        case SKATE_KID_PUSH:
            if (GetRandomControl() < SKATE_KID_SKATE_CHANCE) {
                item->goal_anim_state = SKATE_KID_SKATE;
            }
            break;

        case SKATE_KID_SHOOT:
        case SKATE_KID_SHOOT2:
            if (!kid->flags && Targetable(item, &info)) {
				Utils.EnemyShot(item, &info, &KidGun1, head, DOUBLE_VALUE_ANIM(item->current_anim_state, SKATE_KID_SHOOT, DOUBLE_VALUE_ITEM(dmg1, SKATE_KID_STOP_SHOT_DAMAGE), DOUBLE_VALUE_ITEM(dmg2, SKATE_KID_SKATE_SHOT_DAMAGE)));
				Utils.EnemyShot(item, &info, &KidGun2, head, DOUBLE_VALUE_ANIM(item->current_anim_state, SKATE_KID_SHOOT, DOUBLE_VALUE_ITEM(dmg1, SKATE_KID_STOP_SHOT_DAMAGE), DOUBLE_VALUE_ITEM(dmg2, SKATE_KID_SKATE_SHOT_DAMAGE)));
				item->fired_weapon = 4;
				item->reserved_1 = 3;
                kid->flags = 1;
            }
            if (kid->mood == MOOD_ESCAPE
                || info.distance < SKATE_KID_TOO_CLOSE) {
                item->required_anim_state = SKATE_KID_SKATE;
            }
            break;
        }
    }

    CreatureJoint(item, 0, head);
    CreatureAnimation(item_num, angle, 0);
}

void DrawTR1_SkateKid(ITEM_INFO* item)
{
    DrawAnimatingItemCustom(item);
	short object_number = item->object_number;
	short anim_number = item->anim_number;
	short frame_number = item->frame_number;
	item->object_number = Utils.getObjects(Utils.getLinks(tsu_slots[object_number], LNK_OBJECT1));
	item->anim_number += Ptr_VetObjects[item->object_number].anim_index - Ptr_VetObjects[object_number].anim_index;
	item->frame_number += Ptr_VetAnimations[item->anim_number].frame_base - Ptr_VetAnimations[anim_number].frame_base;
	DrawAnimatingItemCustom(item);
	item->object_number = object_number;
	item->anim_number = anim_number;
	item->frame_number = frame_number;
}

void InitialiseTR1_SkateBoard()
{
    for (int index = 0; index < SLOTS_NUMBER; ++index)
    {
        tomb[TR1_SKATEBOARD1 + index].set_name("Skate Board");
        tomb[TR1_SKATEBOARD1 + index].initialise(TR1_SKATEBOARD1 + index, 0, 0);
    }
}

void InitialiseTR1_SkateKid()
{
    for (int index = 0; index < SLOTS_NUMBER; ++index)
    {
        short dependency = Utils.getLinks(TR1_SKATEBOARD_KID1 + index, LNK_OBJECT1);
        if (dependency >= 0 && dependency < TR_OBJECTS_NUMBER && MapToFirst(dependency, SLOTS_NUMBER) == TR1_SKATEBOARD1 && tomb[dependency].get_object())
        {
			tomb[TR1_SKATEBOARD_KID1 + index].set_name("Skate Kid");
			tomb[TR1_SKATEBOARD_KID1 + index].initialise(TR1_SKATEBOARD_KID1 + index, FUNCTION_SHADOW, QUERY_GUNFLASH);
			tomb[TR1_SKATEBOARD_KID1 + index].set_shadow_size(128);
			tomb[TR1_SKATEBOARD_KID1 + index].set_func_initialise(InitTR1_SkateKid);
			tomb[TR1_SKATEBOARD_KID1 + index].set_func_collide(CreatureCollision);
			tomb[TR1_SKATEBOARD_KID1 + index].set_func_control(CtrlTR1_SkateKid);
			tomb[TR1_SKATEBOARD_KID1 + index].set_bitoffset(TROFF_SKATE_KID_LEFT | DOUBLE_OFFSET_MUZZLEFLASH);
			tomb[TR1_SKATEBOARD_KID1 + index].set_func_draw(DrawTR1_SkateKid, NULL);
			tomb[TR1_SKATEBOARD_KID1 + index].set_health(SKATE_KID_HITPOINTS);
			tomb[TR1_SKATEBOARD_KID1 + index].set_radius_and_pivot(SKATE_KID_RADIUS, 0);
			tomb[TR1_SKATEBOARD_KID1 + index].set_hit_effect(HIT_BLOOD);
			tomb[TR1_SKATEBOARD_KID1 + index].set_creature(TRUE);
			tomb[TR1_SKATEBOARD_KID1 + index].set_rotation_meshtree(0, ROT_Y);
			tomb[TR1_SKATEBOARD_KID1 + index].set_save(TRUE, TRUE, TRUE, FALSE, TRUE);
		}
    }
}
