#include #include #include #include #include "main.h" #include "log.h" #include "weapon.h" #include "pilot.h" // Stack of pilot id's to assure uniqueness. static unsigned int pilot_id = 0; // Stack of pilots - yes, they come in stacks now. Pilot** pilot_stack; int pilots = 0; extern Pilot* player; // External. extern void ai_destroy(Pilot* p); // Ai. extern void player_think(Pilot* pilot); // Player.c extern void ai_think(Pilot* pilot); // Ai.c // Internal. static void pilot_update(Pilot* pilot, const double dt); void pilot_render(Pilot* pilot); static void pilot_free(Pilot* p); // Pull a pilot out of the pilot_stack based on id. Pilot* get_pilot(unsigned int id) { // Regular search. #if 0 for(int i = 0; i < pilots; i++) if(pilot_stack[i]->id == id) return pilot_stack[i]; return NULL; #endif if(id == 0) return player; // Dichotomical search. int i, n; for(i = 0, n = pilots/2; n > 0; n /= 2) i += (pilot_stack[i+n]->id > id) ? 0 : n; return (pilot_stack[i]->id == id) ? pilot_stack[i] : NULL; } // Mkay, this is how we shoot. Listen up. void pilot_shoot(Pilot* p, int secondary) { int i; if(!secondary) { // Primary weapons. if(!p->outfits) return; // No outfits. for(i = 0; p->outfits[i].outfit; i++) // Cycle through outfits to find weapons. if(outfit_isWeapon(p->outfits[i].outfit) || // Is a weapon or launch? outfit_isLauncher(p->outfits[i].outfit)) // Ready to shoot again. if((SDL_GetTicks()-p->outfits[i].timer) > (p->outfits[i].outfit->delay/p->outfits[i].quantity)) // Different weapons have different behaviours. switch(p->outfits[i].outfit->type) { case OUTFIT_TYPE_BOLT: weapon_add(p->outfits[i].outfit, p->solid->dir, &p->solid->pos, &p->solid->vel, p->id, (p==player) ? WEAPON_LAYER_FG : WEAPON_LAYER_BG); p->outfits[i].timer = SDL_GetTicks(); break; default: break; } } } // Damage the pilot. void pilot_hit(Pilot* p, double damage_shield, double damage_armor) { if(p->shield - damage_shield > 0.) p->shield -= damage_shield; else if(p->shield > 0.) { // Shields can take part of the blow. p->armor -= p->shield/damage_shield*damage_armor; p->shield = 0.; } else if(p->armor-damage_armor > 0.) p->armor -= damage_armor; else p->armor = 0.; } // Render the pilot. void pilot_render(Pilot* p) { int sprite; gl_texture* t = p->ship->gfx_space; // Get the sprite corresponding to the direction facing. sprite = (int)(p->solid->dir / (2.0*M_PI / (t->sy * t->sx))); gl_blitSprite(t, &p->solid->pos, sprite % (int)t->sx, sprite / (int)t->sy); } // Update the pilot. static void pilot_update(Pilot* pilot, const double dt) { // Regeneration. if(pilot->armor < pilot->armor_max) pilot->armor += pilot->ship->armor_regen*dt; else pilot->shield += pilot->ship->shield_regen*dt; if(pilot->armor > pilot->armor_max) pilot->armor = pilot->armor_max; if(pilot->armor > pilot->armor_max) pilot->armor = pilot->armor_max; if((pilot->solid->dir > 2.*M_PI) || (pilot->solid->dir < 0.0)) pilot->solid->dir = fmod(pilot->solid->dir, 2.*M_PI); // Update the solid. pilot->solid->update(pilot->solid, dt); if(VMOD(pilot->solid->vel) > pilot->ship->speed) { // Should not go faster. vect_pset(&pilot->solid->vel, pilot->ship->speed, VANGLE(pilot->solid->vel)); } pilot_render(pilot); } // ==Init pilot.=========================================== // ship : Ship pilot is flying. // name : Pilot's name, if NULL, ships name will be used. // dir : Initial facing direction. (radians) // vel : Initial velocity. // pos : Initial position. // flags : Tweaking the pilot. // ======================================================== void pilot_init(Pilot* pilot, Ship* ship, char* name, const double dir, const Vec2* pos, const Vec2* vel, const int flags) { if(flags & PILOT_PLAYER) // Player is ID 0 pilot->id = 0; else pilot->id = ++pilot_id; // New unique pilot id based on pilot_id, Can't be 0. pilot->ship = ship; pilot->name = strdup((name == NULL) ? ship->name : name); pilot->solid = solid_create(ship->mass, dir, pos, vel); // Max shields armor. pilot->armor_max = ship->armor; pilot->shield_max = ship->shield; pilot->energy_max = ship->energy; pilot->armor = pilot->armor_max; pilot->shield = pilot->shield_max; pilot->energy = pilot->energy_max; // Initially idle. pilot->task = NULL; // Outfits. pilot->outfits = NULL; ShipOutfit* so; if(ship->outfit) { int noutfits = 0; for(so = ship->outfit; so; so = so->next) { pilot->outfits = realloc(pilot->outfits, (noutfits+1)*sizeof(PilotOutfit)); pilot->outfits[noutfits].outfit = so->data; pilot->outfits[noutfits].quantity = so->quantity; pilot->outfits[noutfits].timer = 0; noutfits++; } // Sentinal. pilot->outfits = realloc(pilot->outfits, (noutfits+1)*sizeof(PilotOutfit)); pilot->outfits[noutfits].outfit = NULL; pilot->outfits[noutfits].quantity = 0; pilot->outfits[noutfits].timer = 0; } if(flags & PILOT_PLAYER) { pilot->think = player_think; // Players don't need to thing! :P pilot->render = NULL; pilot->properties |= PILOT_PLAYER; player = pilot; } else { pilot->think = ai_think; pilot->render = pilot_render; } pilot->update = pilot_update; } // Create a new pilot - Params are same as pilot_init. Return pilot's id. unsigned int pilot_create(Ship* ship, char* name, const double dir, const Vec2* pos, const Vec2* vel, const int flags) { Pilot* dyn = MALLOC_L(Pilot); if(dyn == NULL) { WARN("Unable to allocate memory."); return 0; } pilot_init(dyn, ship, name, dir, pos, vel, flags); if(flags & PILOT_PLAYER) { // Player. if(!pilot_stack) { pilot_stack = MALLOC_L(Pilot*); pilots = 1; } pilot_stack[0] = dyn; } else { // Add to the stack. pilot_stack = realloc(pilot_stack, ++pilots*sizeof(Pilot*)); pilot_stack[pilots-1] = dyn; } return dyn->id; } // Frees and cleans up a pilot. static void pilot_free(Pilot* p) { solid_free(p->solid); free(p->outfits); free(p->name); ai_destroy(p); free(p); } // Destroy pilot from stack. void pilot_destroy(Pilot* p) { int i; for(i = 0; i < pilots; i++) if(pilot_stack[i] == p) break; while(i < pilots) { pilot_stack[i] = pilot_stack[i+1]; i++; } pilot_free(p); } // Free the prisoned pilot! void pilots_free(void) { int i; for(i = 0; i < pilots; i++) pilot_free(pilot_stack[i]); free(pilot_stack); } // Update all pilots. void pilots_update(double dt) { int i; for(i = 0; i < pilots; i++) { if(pilot_stack[i]->think) pilot_stack[i]->think(pilot_stack[i]); if(pilot_stack[i]->update) pilot_stack[i]->update(pilot_stack[i], dt); if(pilot_stack[i]->render) pilot_stack[i]->render(pilot_stack[i]); } }