#include "sergente.h" #include "assets.h" #include "game.h" #include #include #include #include void initSergente(Entity * entity, Game * game) { entity->model = &game->assets.models[SERGENTE_ASSET]; entity->collisionModel = entityCreateCollisionModel(*entity->model); entity->transformedCollisionModel = entityCreateCollisionModel(*entity->model); setEntityRadius(entity); // Allocate data. entity->data = KF_MALLOC(sizeof(Sergente)); if (entity->data == NULL) { ALLOCATION_ERROR; return; } Sergente * data = (Sergente*)entity->data; data->flyToPoint = (EntityFlyToPointInfo){ .controller.bangbang.speed = 85.0, .controller.bangbang.stopAt = 0.0, .controlType = ENTITY_FLY_TO_POINT_BANG_BANG, .rotationSpeed = 0.0, .applyRotation = false }; createSergenteTarget(game, entity); data->timeSinceLastShot = 0.0; } void closeSergente(Entity * entity) { if (entity->data != NULL) KF_FREE(entity->data); entityFreeCollisionModel(entity->collisionModel); entityFreeCollisionModel(entity->transformedCollisionModel); } void updateRotationSergente(Game * game, Entity * entity) { float t = GetFrameTime(); Entity * player = getEntityFromWorld(game->world, 0); // Get rotation. Matrix matrix = MatrixLookAt(player->position, entity->position, (Vector3){0.0, 1.0, 0.0}); Quaternion rotation = QuaternionInvert(QuaternionFromMatrix(matrix)); // Update current rotation. entity->rotation = QuaternionSlerp(entity->rotation, rotation, t * SERGENTE_ROTATION_SPEED); } Vector3 getSergenteShotSpread() { return Vector3Scale( (Vector3){ (float)GetRandomValue(-UCHAR_MAX, UCHAR_MAX) / UCHAR_MAX, (float)GetRandomValue(-UCHAR_MAX, UCHAR_MAX) / UCHAR_MAX, (float)GetRandomValue(-UCHAR_MAX, UCHAR_MAX) / UCHAR_MAX }, SERGENTE_SPREAD ); } void updateGunsSergente(Game * game, Entity * entity) { int i; int hits = 0; float t = GetTime(); Sergente * data = (Sergente*)entity->data; Entity * player = getEntityFromWorld(game->world, 0); Bullet shot; // Cool down. if (t - data->timeSinceLastShot < SERGENTE_COOL_DOWN) return; // We will use random numbers later. SetRandomSeed(time(NULL)); // Get direction to player. Vector3 dirToPlayer = Vector3Subtract(player->position, entity->position); dirToPlayer = Vector3Normalize(dirToPlayer); Vector3 direction; // Shot the shots because this is a fucking shot gun. for (i = 0; i < SERGENTE_SHOT_COUNT; ++i) { direction = Vector3Add(dirToPlayer, getSergenteShotSpread()); // Create shot. shot = createBulletFromDirection(*entity, direction, SERGENTE_DAMAGE); // Shoot it. hits += shootBulletAtEntity(player, shot).hit ? 1 : 0; data->shots[i] = shot; } //printf("%f\n", (float)hits / SERGENTE_SHOT_COUNT); data->timeSinceLastShot = t; } void updateSergente(Game * game, Entity * entity) { entityUpdateLastValues(entity); Sergente * data = (Sergente*)entity->data; entityFlyToPoint(entity, data->target, &data->flyToPoint); // Create next point. if (Vector3Distance(entity->position, data->target) <= SERGENTE_NEXT_POINT_THRESHOLD) createSergenteTarget(game, entity); updateGunsSergente(game, entity); updateRotationSergente(game, entity); entityCheckTransformedCollisionModel(entity); } void drawSergente(Game * game, Entity * entity) { entityDraw(entity); // Debug shots int i; Sergente * data = (Sergente*)entity->data; for (i = 0; i < SERGENTE_SHOT_COUNT; ++i) { DrawRay(data->shots[i].ray, BLUE); DrawCube(data->shots[i].ray.position, 1.0, 1.0, 1.0, BLUE); } // Test if facing player always. //DrawLine3D( // entity->position, // Vector3Add( // entity->position, // Vector3Scale(Vector3RotateByQuaternion((Vector3){0.0, 0.0, 1.0}, entity->rotation), 500.0) // ), // BLUE //); // The fucking debug line. //DrawLine3D(entity->position, ((Sergente*)entity->data)->target, BLUE); } void comeBackToPlayerSergente(Game * game, Entity * entity) { Entity * player = getEntityFromWorld(game->world, 0); Sergente * data = (Sergente*)entity->data; data->target = Vector3Subtract(player->position, entity->position); data->target = Vector3Scale(data->target, SERGENTE_COME_BACK_PERCENT); data->target = Vector3Add(entity->position, data->target); } void createSergenteTarget(Game * game, Entity * entity) { Sergente * data = (Sergente*)entity->data; Entity * player = getEntityFromWorld(game->world, 0); // To far away. if (Vector3Distance(entity->position, player->position) >= SERGENTE_COME_BACK_DIS) { comeBackToPlayerSergente(game, entity); return; } SetRandomSeed(time(NULL)); // Set target direction. data->target = (Vector3){ GetRandomValue(-UCHAR_MAX, UCHAR_MAX), GetRandomValue(-UCHAR_MAX, UCHAR_MAX), GetRandomValue(-UCHAR_MAX, UCHAR_MAX) }; data->target = Vector3Normalize(data->target); // Scale target and transform. float dis = GetRandomValue(SERGENTE_TARGET_DIS_MIN, SERGENTE_TARGET_DIS_MAX); data->target = Vector3Scale(data->target, dis); data->target = Vector3Add(entity->position, data->target); }