ref: 7cfaff0c7b618e8150bd97ad43fca9899f4a5514
dir: /src/wipeout/droid.c/
#include "../types.h"
#include "../mem.h"
#include "../system.h"
#include "../utils.h"
#include "object.h"
#include "track.h"
#include "ship.h"
#include "weapon.h"
#include "hud.h"
#include "droid.h"
#include "camera.h"
#include "image.h"
#include "scene.h"
#include "object.h"
#include "game.h"
static Object *droid_model;
void droid_load() {
texture_list_t droid_textures = image_get_compressed_textures("wipeout/common/rescu.cmp");
droid_model = objects_load("wipeout/common/rescu.prm", droid_textures);
}
void droid_init(droid_t *droid, ship_t *ship) {
droid->section = g.track.sections;
while (flags_not(droid->section->flags, SECTION_JUMP)) {
droid->section = droid->section->next;
}
droid->position = vec3_add(ship->position, vec3(0, -200, 0));
droid->velocity = vec3(0, 0, 0);
droid->acceleration = vec3(0, 0, 0);
droid->angle = vec3(0, 0, 0);
droid->angular_velocity = vec3(0, 0, 0);
droid->update_timer = DROID_UPDATE_TIME_INITIAL;
droid->mat = mat4_identity();
droid->cycle_timer = 0;
droid->update_func = droid_update_intro;
droid->sfx_tractor = sfx_reserve_loop(SFX_TRACTOR);
flags_rm(droid->sfx_tractor->flags, SFX_PLAY);
}
void droid_draw(droid_t *droid) {
droid->cycle_timer += system_tick() * M_PI * 2;
Prm prm = {.primitive = droid_model->primitives};
int rf = sin(droid->cycle_timer) * 127 + 128;
int gf = sin(droid->cycle_timer + 0.2) * 127 + 128;
int bf = sin(droid->cycle_timer * 0.5 + 0.1) * 127 + 128;
int r, g, b;
for (int i = 0; i < 11; i++) {
if (i < 2) {
r = 40;
g = gf;
b = 40;
}
else if (i < 6) {
r = bf >> 1;
b = bf;
g = bf >> 1;
}
else {
r = rf;
b = 40;
g = 40;
}
switch (prm.f3->type) {
case PRM_TYPE_GT3:
prm.gt3->colour[0].as_rgba.r = r;
prm.gt3->colour[0].as_rgba.g = g;
prm.gt3->colour[0].as_rgba.b = b;
prm.gt3->colour[1].as_rgba.r = r;
prm.gt3->colour[1].as_rgba.g = g;
prm.gt3->colour[1].as_rgba.b = b;
prm.gt3->colour[2].as_rgba.r = r;
prm.gt3->colour[2].as_rgba.g = g;
prm.gt3->colour[2].as_rgba.b = b;
prm.gt3++;
break;
case PRM_TYPE_GT4:
prm.gt4->colour[0].as_rgba.r = r;
prm.gt4->colour[0].as_rgba.g = g;
prm.gt4->colour[0].as_rgba.b = b;
prm.gt4->colour[1].as_rgba.r = r;
prm.gt4->colour[1].as_rgba.g = g;
prm.gt4->colour[1].as_rgba.b = b;
prm.gt4->colour[2].as_rgba.r = r;
prm.gt4->colour[2].as_rgba.g = g;
prm.gt4->colour[2].as_rgba.b = b;
prm.gt4->colour[3].as_rgba.r = 40;
prm.gt4->colour[3].as_rgba.g = 40;
prm.gt4->colour[3].as_rgba.b = 40;
prm.gt4++;
break;
}
}
mat4_set_translation(&droid->mat, droid->position);
mat4_set_yaw_pitch_roll(&droid->mat, droid->angle);
object_draw(droid_model, &droid->mat);
}
void droid_update(droid_t *droid, ship_t *ship) {
(droid->update_func)(droid, ship);
droid->velocity = vec3_add(droid->velocity, vec3_mulf(droid->acceleration, 30 * system_tick()));
droid->velocity = vec3_sub(droid->velocity, vec3_mulf(droid->velocity, 0.125 * 30 * system_tick()));
droid->position = vec3_add(droid->position, vec3_mulf(droid->velocity, 0.015625 * 30 * system_tick()));
droid->angle = vec3_add(droid->angle, vec3_mulf(droid->angular_velocity, system_tick()));
droid->angle = vec3_wrap_angle(droid->angle);
if (flags_is(droid->sfx_tractor->flags, SFX_PLAY)) {
sfx_set_position(droid->sfx_tractor, droid->position, droid->velocity, 0.5);
}
}
void droid_update_intro(droid_t *droid, ship_t *ship) {
droid->update_timer -= system_tick();
if (droid->update_timer < DROID_UPDATE_TIME_INTRO_3) {
droid->acceleration.x = (-sin(droid->angle.y) * cos(droid->angle.x)) * 0.25 * 4096.0;
droid->acceleration.y = 0;
droid->acceleration.z = (cos(droid->angle.y) * cos(droid->angle.x)) * 0.25 * 4096.0;
droid->angular_velocity.y = 0;
}
else if (droid->update_timer < DROID_UPDATE_TIME_INTRO_2) {
droid->acceleration.x = (-sin(droid->angle.y) * cos(droid->angle.x)) * 0.125 * 4096.0;
droid->acceleration.y = -140;
droid->acceleration.z = (cos(droid->angle.y) * cos(droid->angle.x)) * 0.125 * 4096.0;
droid->angular_velocity.y = (-8.0 / 4096.0) * M_PI * 2 * 30;
}
else if (droid->update_timer < DROID_UPDATE_TIME_INTRO_1) {
droid->acceleration.y -= 90 * system_tick();
droid->angular_velocity.y = (8.0 / 4096.0) * M_PI * 2 * 30;
}
if (droid->update_timer <= 0) {
droid->update_timer = DROID_UPDATE_TIME_INITIAL;
droid->update_func = droid_update_idle;
droid->position.x = droid->section->center.x;
droid->position.y = -3000;
droid->position.z = droid->section->center.z;
}
}
void droid_update_idle(droid_t *droid, ship_t *ship) {
section_t *next = droid->section->next;
vec3_t target = vec3(
(droid->section->center.x + next->center.x) * 0.5,
droid->section->center.y - 3000,
(droid->section->center.z + next->center.z) * 0.5
);
vec3_t target_vector = vec3_sub(target, droid->position);
float target_heading = -atan2(target_vector.x, target_vector.z);
float quickest_turn = target_heading - droid->angle.y;
float turn;
if (droid->angle.y < 0) {
turn = target_heading - (droid->angle.y + M_PI*2);
}
else {
turn = target_heading - (droid->angle.y - M_PI*2);
}
if (fabsf(turn) < fabsf(quickest_turn)) {
droid->angular_velocity.y = turn * 30 / 64.0;
}
else {
droid->angular_velocity.y = quickest_turn * 30.0 / 64.0;
}
droid->acceleration.x = (-sin(droid->angle.y) * cos(droid->angle.x)) * 0.125 * 4096;
droid->acceleration.y = target_vector.y / 64.0;
droid->acceleration.z = (cos(droid->angle.y) * cos(droid->angle.x)) * 0.125 * 4096;
if (flags_is(ship->flags, SHIP_IN_RESCUE)) {
flags_add(droid->sfx_tractor->flags, SFX_PLAY);
droid->update_func = droid_update_rescue;
droid->update_timer = DROID_UPDATE_TIME_INITIAL;
g.camera.update_func = camera_update_rescue;
flags_add(ship->flags, SHIP_VIEW_REMOTE);
if (flags_is(ship->section->flags, SECTION_JUMP)) {
g.camera.section = ship->section->next;
}
else {
g.camera.section = ship->section;
}
// If droid is not nearby the rescue position teleport it in!
if (droid->section != ship->section && droid->section != ship->section->prev) {
droid->section = ship->section;
section_t *next = droid->section->next;
droid->position.x = (droid->section->center.x + next->center.x) * 0.5;
droid->position.y = droid->section->center.y - 3000;
droid->position.z = (droid->section->center.z + next->center.z) * 0.5;
}
flags_rm(ship->flags, SHIP_IN_TOW);
droid->velocity = vec3(0,0,0);
droid->acceleration = vec3(0,0,0);
}
// AdjustDirectionalNote(START_SIREN, 0, 0, (VECTOR){droid->position.x, droid->position.y, droid->position.z});
}
void droid_update_rescue(droid_t *droid, ship_t *ship) {
droid->angular_velocity.y = 0;
droid->angle.y = ship->angle.y;
vec3_t target = vec3(ship->position.x, ship->position.y - 350, ship->position.z);
vec3_t distance = vec3_sub(target, droid->position);
if (flags_is(ship->flags, SHIP_IN_TOW)) {
droid->velocity = vec3(0,0,0);
droid->acceleration = vec3(0,0,0);
droid->position = target;
}
else if (vec3_len(distance) < 8) {
flags_add(ship->flags, SHIP_IN_TOW);
droid->velocity = vec3(0,0,0);
droid->acceleration = vec3(0,0,0);
droid->position = target;
}
else {
droid->velocity = vec3_mulf(distance, 16);
}
// Are we done rescuing?
if (flags_not(ship->flags, SHIP_IN_RESCUE)) {
flags_rm(droid->sfx_tractor->flags, SFX_PLAY);
droid->siren_started = false;
droid->update_func = droid_update_idle;
droid->update_timer = DROID_UPDATE_TIME_INITIAL;
while (flags_not(droid->section->flags, SECTION_JUMP)) {
droid->section = droid->section->prev;
}
}
}