diff --git a/bin/Makefile b/bin/Makefile index 55df686..79c922e 100644 --- a/bin/Makefile +++ b/bin/Makefile @@ -5,6 +5,8 @@ DEBUG = 1 OS := LINUX #OS := WIN32 +#CC = clang + # VERSION. VMAJOR = 0 VMINOR = 0 diff --git a/src/pilot.c b/src/pilot.c index 484333f..7a8c765 100644 --- a/src/pilot.c +++ b/src/pilot.c @@ -204,15 +204,18 @@ int pilot_freeSpace(Pilot* p) { /* Mkay, this is how we shoot. Listen up. */ void pilot_shoot(Pilot* p, const unsigned int target, const int secondary) { int i; + Outfit* o; if(!p->outfits) return; /* No outfits. */ if(!secondary) { /* Primary weapons. */ - for(i = 0; i < p->noutfits; i++) - /* Cycle through outfits to find primary weapons. */ - if(!outfit_isProp(p->outfits[i].outfit, OUTFIT_PROP_WEAP_SECONDARY)) + for(i = 0; i < p->noutfits; i++) { + o = p->outfits[i].outfit; + if(!outfit_isProp(o, OUTFIT_PROP_WEAP_SECONDARY) && + (outfit_isBolt(o) || outfit_isBeam(o))) /** @todo Possibly make the neater. */ pilot_shootWeapon(p, &p->outfits[i], target); + } } else { if(!p->secondary) return; /* No secondary weapon. */ pilot_shootWeapon(p, p->secondary, target); @@ -243,14 +246,16 @@ static void pilot_shootWeapon(Pilot* p, PilotOutfit* w, const unsigned int t) { p->energy -= outfit_energy(w->outfit); weapon_add(w->outfit, p->solid->dir, &p->solid->pos, &p->solid->vel, p->id, t); - - /* Can't shoot it for a bit. */ - w->timer = SDL_GetTicks(); } /* Beam Weapons. */ else if(outfit_isBeam(w->outfit)) { + if(outfit_energy(w->outfit) > p->energy) return; + /** @todo Handle warmup stage. */ + w->state = PILOT_OUTFIT_ON; + weapon_add(w->outfit, p->solid->dir, + &p->solid->pos, NULL, p->id, t); } /* @@ -275,9 +280,13 @@ static void pilot_shootWeapon(Pilot* p, PilotOutfit* w, const unsigned int t) { weapon_add(p->ammo->outfit, p->solid->dir, &p->solid->pos, &p->solid->vel, p->id, t); - w->timer = SDL_GetTicks(); /* Can't shoot for a while. */ p->ammo->quantity -= 1; /* There's no getting this one back. */ + } else { + WARN("Shooting unknown weapon type: %s", w->outfit->name); } + + /* Update the weapon last used timer. */ + w->timer = SDL_GetTicks(); } /** diff --git a/src/pilot.h b/src/pilot.h index 8e70382..7cc6ff2 100644 --- a/src/pilot.h +++ b/src/pilot.h @@ -53,16 +53,29 @@ #define pilot_isPlayer(p) ((p)->flags & PILOT_PLAYER) /**< Check if pilot is a player. */ #define pilot_isDisabled(p) ((p)->flags & PILOT_DISABLED) /**< Check if pilot is disabled. */ +/** + * @enum PilotOutfitState + * + * @brief Contains the state of the outfit. + * + * Currently only applicable to beam weapons. + */ +typedef enum PilotOutfitState_ { + PILOT_OUTFIT_OFF, /**< Normal state. */ + PILOT_OUTFIT_WARMUP, /**< Outfit is starting to warm up. */ + PILOT_OUTFIT_ON /**< Outfit is activated and running. */ +} PilotOutfitState; + /** * @struct PilotOutfit * * @brief Store an outfit the pilot has. */ typedef struct PilotOutfit_ { - Outfit* outfit; /**< Associated outfit. */ - int quantity; /**< Number of outfits of this type that the pilot has. */ - - unsigned int timer; /**< Used to store last used weapon time. */ + Outfit* outfit; /**< Associated outfit. */ + int quantity; /**< Number of outfits of this type that the pilot has. */ + PilotOutfitState state; /**< State of the outfit. */ + unsigned int timer; /**< Used to store last used weapon time. */ } PilotOutfit; /** diff --git a/src/weapon.c b/src/weapon.c index c583029..d081e74 100644 --- a/src/weapon.c +++ b/src/weapon.c @@ -11,6 +11,7 @@ #include "collision.h" #include "player.h" #include "spfx.h" +#include "opengl.h" #include "weapon.h" #define weapon_isSmart(w) (w->think != NULL) @@ -22,7 +23,11 @@ #define WEAPON_STATUS_JAMMED 1 /* Got jammed. */ #define WEAPON_STATUS_UNJAMMED 2 /* Surviving jaming. */ -/* Some stuff from pilot. */ +/* OpenGL stuff. */ +extern Vec2* gl_camera; +extern double gui_xoff, gui_yoff; + +/* Pilot stuff. */ extern Pilot** pilot_stack; extern int pilot_nstack; @@ -69,6 +74,8 @@ static void weapon_render(const Weapon* w); static void weapons_updateLayer(const double dt, const WeaponLayer layer); static void weapon_update(Weapon* w, const double dt, WeaponLayer layer); static void weapon_hit(Weapon* w, Pilot* p, WeaponLayer layer, Vec2* pos); +static void weapon_hitBeam(Weapon* w, Pilot* p, WeaponLayer layer, + Vec2 pos[2], const double dt); static void weapon_destroy(Weapon* w, WeaponLayer layer); static void weapon_free(Weapon* w); /* Think. */ @@ -80,8 +87,20 @@ void weapon_minimap(const double res, const double w, const double h, const RadarShape shape); /* Draw the minimap weapons (player.c). */ -#define PIXEL(x,y) if((shape == RADAR_RECT && ABS(x) < w/2. && ABS(y)outfit->type) { @@ -315,10 +335,13 @@ static void weapon_render(const Weapon* w) { /* Beam weapons. */ case OUTFIT_TYPE_BEAM: case OUTFIT_TYPE_TURRET_BEAM: + x = w->solid->pos.x - VX(*gl_camera) + gui_xoff; + y = w->solid->pos.y - VY(*gl_camera) + gui_yoff; + COLOUR(*w->outfit->u.bem.colour); glBegin(GL_LINES); - glVertex2d(w->solid->pos.x, w->solid->pos.y); - glVertex2d(w->solid->pos.x + w->outfit->u.bem.range*cos(w->solid->dir), - w->solid->pos.y + w->outfit->u.bem.range*sin(w->solid->dir)); + glVertex2d(x, y); + glVertex2d(x + w->outfit->u.bem.range * cos(w->solid->dir), + y + w->outfit->u.bem.range * sin(w->solid->dir)); glEnd(); break; @@ -335,10 +358,6 @@ static void weapon_update(Weapon* w, const double dt, WeaponLayer layer) { glTexture* gfx; Vec2 crash[2]; - gfx = outfit_gfx(w->outfit); - - gl_getSpriteFromDir(&wsx, &wsy, gfx, w->solid->dir); - for(i = 0; i < pilot_nstack; i++) { /* Check for player to exist. */ if((i == 0) && (player == NULL)) continue; @@ -356,7 +375,7 @@ static void weapon_update(Weapon* w, const double dt, WeaponLayer layer) { &pilot_stack[i]->solid->pos, crash)) { - /** @todo beam_hit Needs it's own function. */ + weapon_hitBeam(w, pilot_stack[i], layer, crash, dt); /* No return because beam can still think, it's not * destroyed like the other weapons. */ @@ -365,27 +384,31 @@ static void weapon_update(Weapon* w, const double dt, WeaponLayer layer) { /* Smart weapons only collide with their target. */ else if(weapon_isSmart(w)) { + gfx = outfit_gfx(w->outfit); + gl_getSpriteFromDir(&wsx, &wsy, gfx, w->solid->dir); if((pilot_stack[i]->id == w->target) && CollideSprite(gfx, wsx, wsy, &w->solid->pos, pilot_stack[i]->ship->gfx_space, psx, psy, &pilot_stack[i]->solid->pos, &crash[0])) { weapon_hit(w, pilot_stack[i], layer, &crash[0]); - return; - } - /* Dumb weapons hit anything not of the same faction. */ - else if(!weapon_isSmart(w) && - !areAllies(w->faction, pilot_stack[i]->faction) && - CollideSprite(gfx, wsx, wsy, &w->solid->pos, - pilot_stack[i]->ship->gfx_space, psx, psy, &pilot_stack[i]->solid->pos, - &crash[0])) { - - weapon_hit(w, pilot_stack[i], layer, &crash[0]); - return; + return; /* Weapon is destroyed. */ } } - } + /* Dumb weapons hit anything not of the same faction. */ + else if(!weapon_isSmart(w)) { + gfx = outfit_gfx(w->outfit); + gl_getSpriteFromDir(&wsx, &wsy, gfx, w->solid->dir); + if(!areAllies(w->faction, pilot_stack[i]->faction) && + CollideSprite(gfx, wsx, wsy, &w->solid->pos, + pilot_stack[i]->ship->gfx_space, psx, psy, &pilot_stack[i]->solid->pos, + &crash[0])) { + weapon_hit(w, pilot_stack[i], layer, &crash[0]); + return; /* Weapon is destroyed. */ + } + } + } /* Smart weapons also get to think their next move. */ if(weapon_isSmart(w)) (*w->think)(w,dt); @@ -425,6 +448,48 @@ static void weapon_hit(Weapon* w, Pilot* p, WeaponLayer layer, Vec2* pos) { weapon_destroy(w, layer); } +/** + * @fn static void weapon_hitBeam(Weapon* w, Pilot* p, WeaponLayer layer, + * Vec2 pos[2], const double dt) + * + * @brief Weapon hit the pilot. + * @param w Weapon involved in the collision. + * @param p Pilot that got hit. + * @param layer Layer to which the weapon belongs. + * @param pos Position of the hit. + */ +static void weapon_hitBeam(Weapon* w, Pilot* p, WeaponLayer layer, + Vec2 pos[2], const double dt) { + + (void)layer; + + /* Inform the ai it has been attacked, useless if player. */ + if(!pilot_isPlayer(p)) { + if((player_target == p->id) || (RNGF()*dt < 0.70)) { /* 70% chance per second. */ + if((w->parent == PLAYER_ID) && + (!pilot_isFlag(p, PILOT_HOSTILE) || (RNGF() < 0.5))) { /* 50% chance. */ + faction_modPlayer(p->faction, -1); /* Slowly lower faction. */ + pilot_setFlag(p, PILOT_HOSTILE); + } + ai_attacked(p, w->parent); + } + spfx_add(outfit_spfx(w->outfit), pos[0].x, pos[0].y, + VX(p->solid->vel), VY(p->solid->vel), SPFX_LAYER_BACK); + spfx_add(outfit_spfx(w->outfit), pos[1].x, pos[1].y, + VX(p->solid->vel), VY(p->solid->vel), SPFX_LAYER_BACK); + + } else { + spfx_add(outfit_spfx(w->outfit), pos[0].x, pos[0].y, + VX(p->solid->vel), VY(p->solid->vel), SPFX_LAYER_FRONT); + spfx_add(outfit_spfx(w->outfit), pos[1].x, pos[1].y, + VX(p->solid->vel), VY(p->solid->vel), SPFX_LAYER_FRONT); + } + + /* Inform the ship that it should take some damage. */ + pilot_hit(p, w->solid, w->parent, + outfit_damageType(w->outfit), outfit_damage(w->outfit)*dt); +} + static Weapon* weapon_create(const Outfit* outfit, const double dir, const Vec2* pos, const Vec2* vel, unsigned int parent, const unsigned int target) { Vec2 v; @@ -491,6 +556,7 @@ static Weapon* weapon_create(const Outfit* outfit, const double dir, const Vec2* mass = 1.; w->solid = solid_create(mass, dir, pos, NULL); w->think = think_beam; + w->timer = outfit->u.bem.duration; break; /* Treat seekers togther. */