#include "antifaShip.h" #include "game.h" #include "settings.h" #include "bullets.h" #include "assets.h" void initAntifaShip(Entity * entity, Game * game) { entity->model = &game->assets.models[ANTIFA_SHIP_ASSET]; entity->collisionModel = entityCreateCollisionModel(*entity->model); entity->transformedCollisionModel = entityCreateCollisionModel(*entity->model); setEntityRadius(entity); // Acceleration stuff. entity->useAcceleration = true; entity->acceleration = (EntityAcceleration){ .speedUp = 30.0, .speedDown = 15, .rotation = (Vector3){2000000.0, 2000000.0, 2000000.0} }; // Set Data pointer. entity->data = KF_MALLOC(sizeof(AntifaShip)); if (entity->data == NULL) { ALLOCATION_ERROR; return; } AntifaShip * data = (AntifaShip*)entity->data; data->lastMouse = GetMousePosition(); data->forwardSpeed = 0.0; data->shouldInitMousePosition = true; data->timeSinceLastBullet = GetTime(); data->doAutoTarget = false; data->targetedEntityId = ENTITY_NONE; // Targeting PID indeed (: PIDConfig targetingPIDConfig = (PIDConfig){ .kP = 500.0, .kI = 0.1, .kD = 0.0, .angleMode = false, .doClamp = false, .min = 0.0, .max = 0.0 }; data->targetingPID = createPID(targetingPIDConfig); } // Go back to burger king you elon musking loving mother fucker! void closeAntifaShip(Entity * entity) { if (entity->data != NULL) KF_FREE(entity->data); entityFreeCollisionModel(entity->collisionModel); entityFreeCollisionModel(entity->transformedCollisionModel); } // Returns closest entity to ship or none. EntityId getClosestShipToAntifaShip(Game * game, Entity * entity) { int i; // Needs at least two entities to work correctly. if (game->world.entitiesCount < 2) return ENTITY_NONE; // Start out with entity 1 as closest. Entity * currentEntity = &game->world.entities[1]; EntityId closestId = currentEntity->id; float closestDistance = Vector3Distance(currentEntity->position, entity->position); float distance; // This entity will only ever be at id 0 so skip it. Also skip the one after that (: for (i = 2; i < game->world.entitiesCount; ++i) { // Get entity and distance. currentEntity = &game->world.entities[i]; distance = Vector3Distance(currentEntity->position, entity->position); // Is closest. if (distance < closestDistance) { closestDistance = distance; closestId = currentEntity->id; } } return closestId; } bool isAntifaShipGunInRange(Entity * ship, Entity * targetEntity) { Vector3 directionAiming = Vector3RotateByQuaternion((Vector3){0.0, 0.0, 1.0}, ship->rotation); Vector3 directionToTarget = Vector3Normalize(Vector3Subtract(targetEntity->position, ship->position)); return Vector3Distance(directionAiming, directionToTarget) <= ANTIFA_START_AUTO_TARGET_MAX; } void updateAntifaShipTarget(Game * game, Entity * entity) { float t = GetFrameTime(); AntifaShip * data = (AntifaShip*)entity->data; if (data->doAutoTarget) { Entity * targetEntity = getEntityFromWorld(game->world, data->targetedEntityId); // Lost target. if (targetEntity == NULL) { data->doAutoTarget = false; return; } else if (targetEntity->fingerprint != data->targetedEntityFingerprint) { data->doAutoTarget = false; return; } else if (!isAntifaShipGunInRange(entity, targetEntity)) { data->doAutoTarget = false; return; } Vector3 directionToTarget = Vector3Normalize(Vector3Subtract(targetEntity->position, entity->position)); // Run targeting PID and update target. float speed = runPID(Vector3Distance(data->gunTarget, directionToTarget), 0.0, &data->targetingPID); data->gunTarget = Vector3Lerp(data->gunTarget, directionToTarget, speed * t); } else { resetPID(&data->targetingPID); data->gunTarget = Vector3RotateByQuaternion((Vector3){0.0, 0.0, 1.0}, entity->rotation); } } void toggleAntifaShipAutoTarget(Game * game, Entity * entity) { AntifaShip * data = (AntifaShip*)entity->data; // Turn off auto target. if (data->doAutoTarget) { data->doAutoTarget = false; return; } // Get closest entity to target on. EntityId closestId = getClosestShipToAntifaShip(game, entity); if (closestId == ENTITY_NONE) return; data->targetedEntityId = closestId; Entity * closestEntity = getEntityFromWorld(game->world, closestId); data->targetedEntityFingerprint = closestEntity->fingerprint; // Lock on target if can. if (isAntifaShipGunInRange(entity, closestEntity)) data->doAutoTarget = true; } // This fucker will fire a bullet!!! void fireBulletAntifa(Game * game, Entity * entity) { double t = GetTime(); AntifaShip * data = (AntifaShip*)entity->data; // Let it cool down. if (t - data->timeSinceLastBullet < ANTIFA_BULLET_COOLDOWN) return; puts("shoot shoot"); Bullet bullet = createBulletFromDirection(*entity, data->gunTarget, 1.0); BulletHitInfo info = shootBullet(&game->world, bullet); data->lastBulletShot = bullet; if (info.hit) { Entity * hitEntity = getEntityFromWorld(game->world, info.hitId); printVector3(hitEntity->position); } else { puts("you stink"); } data->timeSinceLastBullet = t; } void controlAntifaShipJoystick(Game * game, Entity * entity) { Settings settings = game->settings; int gamePadNum = settings.gamePadNum; // Get joystick values. float pitchStick = GetGamepadAxisMovement(gamePadNum, settings.pitchStick); float yawStick = GetGamepadAxisMovement(gamePadNum, settings.yawStick); float rollStick = GetGamepadAxisMovement(gamePadNum, settings.rollStick); float speedStick = GetGamepadAxisMovement(gamePadNum, settings.speedStick); // Shoot button. if (IsGamepadButtonPressed(gamePadNum, 8)) fireBulletAntifa(game, entity); Vector3 stick = (Vector3){ pitchStick, -yawStick, rollStick }; stick = Vector3Scale(stick, settings.joystickSensitivity); float speed = fabs(speedStick * ANTIFA_SHIP_MAX_SPEED); entityJoystickControl(entity, stick, speed); } void controlAntifaShipKeyboardAndMouse(Game * game, Entity * entity) { AntifaShip * data = (AntifaShip*)entity->data; // Resets mouse on init. if (data->shouldInitMousePosition) { data->shouldInitMousePosition = false; SetMousePosition(0, 0); data->lastMouse = Vector2Zero(); } // Shoot bullet. if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) toggleAntifaShipAutoTarget(game, entity); if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) fireBulletAntifa(game, entity); // Get mouse values. Vector2 mouse = GetMousePosition(); float speed = GetMouseWheelMove(); data->forwardSpeed += (speed * game->settings.scrollBarSpeed); if (data->forwardSpeed < 0.) data->forwardSpeed = 0.0; else if (data->forwardSpeed > ANTIFA_SHIP_MAX_SPEED) data->forwardSpeed = ANTIFA_SHIP_MAX_SPEED; Vector2 v = Vector2Subtract(mouse, data->lastMouse); v = Vector2Scale(v, 1.0 / GetFrameTime()); data->lastMouse = mouse; // Using mouse as a joystick. Vector3 mouseStick = (Vector3){v.y, -v.x, 0.0}; mouseStick = Vector3Scale(mouseStick, game->settings.mouseSensitivity); // Swap axis for more movement with mouse. if (IsMouseButtonDown(MOUSE_BUTTON_MIDDLE)) { mouseStick.z = -mouseStick.y; mouseStick.y = 0.0; } entityJoystickControl(entity, mouseStick, data->forwardSpeed); } void updateAntifaShip(Game * game, Entity * entity) { entityUpdateLastValues(entity); updateAntifaShipTarget(game, entity); switch (game->settings.controlMode) { case JOYSTICK_CONTROL: controlAntifaShipJoystick(game, entity); break; case KEYBOARD_AND_MOUSE_CONTROL: controlAntifaShipKeyboardAndMouse(game, entity); break; default: break; } //printf("%f\n", entity->health); entityCheckTransformedCollisionModel(entity); } void drawAntifaShip(Game * game, Entity * entity) { entityDraw(entity); // Draw bullet. AntifaShip * data = (AntifaShip*)entity->data; if (data->doAutoTarget) { DrawLine3D(entity->position, Vector3Add(Vector3Scale(data->gunTarget, 100), entity->position), YELLOW); //printVector3(data->gunTarget); } if (GetTime() - data->timeSinceLastBullet <= ANTIFA_DRAW_BULLET_FOR) DrawRay(data->lastBulletShot.ray, BLUE); }