#include "generale.h" #include "assets.h" #include "game.h" void initGenerale(Entity * entity, Game * game) { entity->model = &game->assets.models[GENERALE_ASSET]; entity->collisionModel = entityCreateCollisionModel(*entity->model); entity->transformedCollisionModel = entityCreateCollisionModel(*entity->model); setEntityRadius(entity); entity->velocity.angularVelocity = (AxisAngle){ .axis = (Vector3){0.0, 1.0, 0.0}, .angle = PI/2.0 }; // Allocate data. entity->data = KF_MALLOC(sizeof(Generale)); if (entity->data == NULL) { ALLOCATION_ERROR; return; } Generale * data = (Generale*)entity->data; data->flyToPoint = (EntityFlyToPointInfo){ .controller.bangbang.speed = 100.0, .controller.bangbang.stopAt = 0.0, .controlType = ENTITY_FLY_TO_POINT_BANG_BANG, .rotationSpeed = 0.0, .applyRotation = false }; data->zigzag = GENERALE_ZIG; data->targetNotSet = true; data->laserDirection = Vector3One(); data->isLaserOn = false; } void closeGenerale(Entity * entity) { if (entity->data != NULL) KF_FREE(entity->data); entityFreeCollisionModel(entity->collisionModel); entityFreeCollisionModel(entity->transformedCollisionModel); } void updateGeneraleLaser(Game * game, Entity * entity) { float t = GetFrameTime(); Entity * player = getEntityFromWorld(game->world, 0); Generale * data = (Generale*)entity->data; // Not within distance. data->isLaserOn = Vector3Distance(player->position, entity->position) <= GENERALE_LASER_MAX_DISTANCE; if (!data->isLaserOn) return; // Direction to player. Vector3 targetDirection = Vector3Normalize(Vector3Subtract(player->position, entity->position)); // Update laser direction. data->laserDirection = Vector3Lerp(data->laserDirection, targetDirection, t * GENERALE_LASER_TRACKING_SPEED); // Check if hits player Ray ray = (Ray){ .position = entity->position, .direction = data->laserDirection }; RayCollision collision = traceRayToEntity(*player, ray); // Do damage. if (collision.hit) player->health -= t * GENERALE_LASER_DAMAGE; printf("%d\n", collision.hit); } void drawGeneraleLaser(Entity * entity) { Generale * data = (Generale*)entity->data; if (!data->isLaserOn) return; // Draw the evil laser of doom. DrawCylinderEx( Vector3Add(entity->position, Vector3Scale(data->laserDirection, entity->radius)), Vector3Add(entity->position, Vector3Scale(data->laserDirection, GENERALE_LASER_MAX_DISTANCE)), GENERALE_LASER_THICKNESS, GENERALE_LASER_THICKNESS, GENERALE_LASER_SIDES, RED ); } void updateGenerale(Game * game, Entity * entity) { entityUpdateLastValues(entity); Generale * data = (Generale*)entity->data; // Next point. if (data->targetNotSet) { getTargetGenerale(game, entity); data->targetNotSet = false; } else if (Vector3Distance(entity->position, data->target) <= GENERALE_NEXT_POINT_THRESHOLD) getTargetGenerale(game, entity); entityFlyToPoint( entity, data->target, &data->flyToPoint ); // Spin this fucker. entityUpdateRotation(entity); // THE EVIL LASER OF DOOM!!!!! updateGeneraleLaser(game, entity); entityCheckTransformedCollisionModel(entity); } void drawGenerale(Game * game, Entity * entity) { entityDraw(entity); drawGeneraleLaser(entity); /* Generale * data = (Generale*)entity->data; DrawLine3D( entity->position, data->target, BLUE ); DrawCubeV(data->target, Vector3One(), BLUE); */ } void getTargetGenerale(Game * game, Entity * entity) { Entity * player = getEntityFromWorld(game->world, 0); Generale * data = (Generale*)entity->data; Vector3 dis = Vector3Subtract(player->position, entity->position); Vector3 dir = Vector3Normalize(dis); SetRandomSeed(time(NULL)); float targetDis = GetRandomValue(GENERALE_ZIGZAG_SIZE_MIN, GENERALE_ZIGZAG_SIZE_MAX); float distance = Vector3Distance(entity->position, player->position); if (distance < targetDis) targetDis = distance; if (data->zigzag == GENERALE_ZIG) { dir = Vector3RotateByAxisAngle(dir, Vector3One(), PI/4); data->zigzag = GENERALE_ZAG; } else { dir = Vector3RotateByAxisAngle(dir, Vector3One(), -PI/4); data->zigzag = GENERALE_ZIG; } dir = Vector3Scale(dir, targetDis); data->target = Vector3Add(entity->position, dir); }