From 4d8b46235962e53853ae735e58ad0b8705ae006e Mon Sep 17 00:00:00 2001 From: Allanis <allanis@saracraft.net> Date: Mon, 30 Sep 2013 22:29:53 +0100 Subject: [PATCH] [Add] First round to bring more control to beam weapons. --- src/pilot.c | 61 ++++++++++++++++++++++++++- src/pilot.h | 3 ++ src/player.c | 31 ++++++++++---- src/player.h | 8 ++-- src/weapon.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/weapon.h | 6 +++ 6 files changed, 210 insertions(+), 14 deletions(-) diff --git a/src/pilot.c b/src/pilot.c index 069658e..1c843dd 100644 --- a/src/pilot.c +++ b/src/pilot.c @@ -222,6 +222,39 @@ void pilot_shoot(Pilot* p, const unsigned int target, const int secondary) { } } +/** + * @fn void pilot_shootStop(Pilot* p, const int secondary) + * + * @brief + */ +void pilot_shootStop(Pilot* p, 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. */ + o = p->outfits[i].outfit; + if(!outfit_isProp(o, OUTFIT_PROP_WEAP_SECONDARY) && + outfit_isBeam(o)) /** @todo Possibly make this neater. */ + if(p->outfits[i].beamid > 0) { + p->outfits[i].beamid = 0; + } + } + } else { /* Secondary weapons. */ + o = p->secondary->outfit; + + if(o == NULL) return; /* No secondary weapon. */ + + if(outfit_isBeam(o) && (p->secondary->beamid > 0)) { + beam_end(p->id, p->secondary->beamid); + p->secondary->beamid = 0; + } + } +} + /** * @fn static void pilot_shootWeapon(Pilot* p, PilotOutfit* w, const unsigned int t) * @@ -254,8 +287,8 @@ static void pilot_shootWeapon(Pilot* p, PilotOutfit* w, const unsigned int t) { /** @todo Handle warmup stage. */ w->state = PILOT_OUTFIT_ON; - weapon_add(w->outfit, p->solid->dir, - &p->solid->pos, &p->solid->vel, p->id, t); + w->beamid = beam_start(w->outfit, p->solid, p->solid->dir, + &p->solid->pos, &p->solid->vel, p->id, t); } /* @@ -289,6 +322,30 @@ static void pilot_shootWeapon(Pilot* p, PilotOutfit* w, const unsigned int t) { w->timer = SDL_GetTicks(); } +/** + * @fn void pilot_switchSecondary(Pilot* p, int i) + * + * @brief + */ +void pilot_switchSecondary(Pilot* p, int i) { + PilotOutfit* cur; + + cur = player->secondary; + + if((i < 0) || (i >= player->noutfits)) + player->secondary = NULL; + else + player->secondary = &player->outfits[i]; + + /* Check for weapon change. */ + if((cur != NULL) && (player->secondary != cur)) { + if(outfit_isBeam(cur->outfit) && (cur->beamid > 0)) { + beam_end(p->id, cur->beamid); + cur->beamid = 0; + } + } +} + /** * @fn void pilot_hit(Pilot* p, const Solid* w, const unsigned int shooter, * const DamageType dtype, const double damage) diff --git a/src/pilot.h b/src/pilot.h index a6f7344..36b7159 100644 --- a/src/pilot.h +++ b/src/pilot.h @@ -76,6 +76,7 @@ typedef struct PilotOutfit_ { Outfit* outfit; /**< Associated outfit. */ int quantity; /**< Number of outfits of this type that the pilot has. */ PilotOutfitState state; /**< State of the outfit. */ + int beamid; /**< ID of the beam used in this outfit, only for beams. */ unsigned int timer; /**< Used to store last used weapon time. */ } PilotOutfit; @@ -213,8 +214,10 @@ int pilot_getJumps(const Pilot* p); /* Misc. */ void pilot_shoot(Pilot* p, const unsigned int target, const int secondary); +void pilot_shootStop(Pilot* p, const int secondary); void pilot_hit(Pilot* p, const Solid* w, const unsigned int shooter, const DamageType dtype, const double damage); +void pilot_switchSecondary(Pilot* p, int i); void pilot_setSecondary(Pilot* p, const char* secondary); void pilot_setAmmo(Pilot* p); void pilot_setAfterburner(Pilot* p); diff --git a/src/player.c b/src/player.c index 49c765e..42019ba 100644 --- a/src/player.c +++ b/src/player.c @@ -1389,9 +1389,27 @@ void player_think(Pilot* pplayer) { pplayer->solid->dir_vel -= player->turn * player_turn; } - if(player_isFlag(PLAYER_PRIMARY)) pilot_shoot(pplayer, player_target, 0); - if(player_isFlag(PLAYER_SECONDARY)) /* Needs a target. */ - pilot_shoot(pplayer, player_target, 1); + /* Weapon shooting stuff. */ + + /* Primary weapon. */ + if(player_isFlag(PLAYER_PRIMARY)) { + pilot_shoot(pplayer, player_target, 0); + player_setFlag(PLAYER_PRIMARY_L); + } + else if(player_isFlag(PLAYER_PRIMARY_L)) { + pilot_shootStop(pplayer, 0); + player_rmFlag(PLAYER_PRIMARY_L); + } + + /* Secondary. */ + if(player_isFlag(PLAYER_SECONDARY)) { + pilot_shoot(pplayer, player_target, 0); + player_setFlag(PLAYER_SECONDARY_L); + } + else if(player_isFlag(PLAYER_SECONDARY_L)) { + pilot_shootStop(pplayer, 0); + player_rmFlag(PLAYER_SECONDARY_L); + } /* Afterburn! */ if(player_isFlag(PLAYER_AFTERBURNER)) { @@ -1405,7 +1423,7 @@ void player_think(Pilot* pplayer) { vect_pset(&pplayer->solid->force, pplayer->thrust * player_acc, pplayer->solid->dir); - /* Update sound position. */ + /* Sound. */ sound_updateListener(pplayer->solid->dir, pplayer->solid->pos.x, pplayer->solid->pos.y); @@ -1447,13 +1465,12 @@ void player_secondaryNext(void) { /* Get the next secondary weapon. */ for(; i < player->noutfits; i++) if(outfit_isProp(player->outfits[i].outfit, OUTFIT_PROP_WEAP_SECONDARY)) { - player->secondary = player->outfits + i; + pilot_switchSecondary(player, i); break; } /* We didn't find an outfit. */ if(i >= player->noutfits) - player->secondary = NULL; - + pilot_switchSecondary(player, -1); /* Set ammo. */ pilot_setAmmo(player); } diff --git a/src/player.h b/src/player.h index d440f3b..db48164 100644 --- a/src/player.h +++ b/src/player.h @@ -9,9 +9,11 @@ #define PLAYER_DESTROYED (1<<9) /* Player goes BOOM! */ #define PLAYER_FACE (1<<10) /* Player is facing target. */ #define PLAYER_PRIMARY (1<<11) /* Player is shooting primary weapon. */ -#define PLAYER_SECONDARY (1<<12) /* Player is shooting secondary weapon. */ -#define PLAYER_LANDACK (1<<13) /* Player has permission to land. */ -#define PLAYER_CREATING (1<<14) /* Player is being created. */ +#define PLAYER_PRIMARY_L (1<<12) /**< Player shot primary weapon last frame. */ +#define PLAYER_SECONDARY (1<<13) /* Player is shooting secondary weapon. */ +#define PLAYER_SECONDARY_L (1<<14) /**< Player shot secondary last frame. */ +#define PLAYER_LANDACK (1<<15) /* Player has permission to land. */ +#define PLAYER_CREATING (1<<16) /* Player is being created. */ /* Flag functions. */ #define player_isFlag(f) (player_flags & f) diff --git a/src/weapon.c b/src/weapon.c index e6b1981..b0bd66a 100644 --- a/src/weapon.c +++ b/src/weapon.c @@ -39,6 +39,7 @@ extern void ai_attacked(Pilot* attacked, const unsigned int attacker); typedef struct Weapon_ { Solid* solid; /* Actually has its own solid. :D */ + int ID; /**< Only used for beam weapons. */ unsigned int faction; /* Faction of pilot that shot the weapon. */ unsigned int parent; /* The pilot that just shot at you! */ @@ -64,6 +65,9 @@ static Weapon** wfrontLayer = NULL; /* Behind pilots. */ static int nwfrontLayer = 0; /* Number of elements. */ static int mwfrontLayer = 0; /* Allocated memory size. */ +/* Internal stuff. */ +static int beam_idgen = 0; /**< Beam identifier generator. */ + /* Static. */ static Weapon* weapon_create(const Outfit* outfit, const double dir, const Vec2* pos, const Vec2* vel, @@ -703,8 +707,8 @@ void weapon_add(const Outfit* outfit, const double dir, const Vec2* pos, Weapon** curLayer; int* mLayer, *nLayer; - if(!outfit_isWeapon(outfit) && - !outfit_isAmmo(outfit) && !outfit_isTurret(outfit)) { + if(!outfit_isBolt(outfit) && + !outfit_isAmmo(outfit)) { ERR("Trying to create a weapon from a non-Weapon type Outfit"); return; } @@ -745,6 +749,113 @@ void weapon_add(const Outfit* outfit, const double dir, const Vec2* pos, } } +/** + * @fn int beam_start(const Outfit* outfit, + * const double dir, const Vec2* pos, const Vec2* vel, + * const unsigned int parent, const unsigned int target) + * + * @brief Start the beam weapon. + * @param outfit Outfit which spawns the weapon. + * @param dir Direction of the shooter. + * @param vel Velocity of the shooter. + * @param parent Pilot ID of the shooter. + * @param target Target ID that is getting shot. + * @return The identifier of the beam weapon. + */ +int beam_start(const Outfit* outfit, + const double dir, const Vec2* pos, const Vec2* vel, + const unsigned int parent, const unsigned int target) { + + WeaponLayer layer; + Weapon* w; + Weapon** curLayer; + int* mLayer, *nLayer; + + if(!outfit_isBeam(outfit)) { + ERR("Trying to create a Beam Weapon from a non-beam outfit."); + return -1; + } + + layer = (parent == PLAYER_ID) ? WEAPON_LAYER_FG : WEAPON_LAYER_BG; + w = weapon_create(outfit, dir, pos, vel, parent, target); + w->ID = ++beam_idgen; + + switch(layer) { + case WEAPON_LAYER_BG: + curLayer = wbackLayer; + nLayer = &nwbackLayer; + mLayer = &mwbackLayer; + break; + case WEAPON_LAYER_FG: + curLayer = wfrontLayer; + nLayer = &nwfrontLayer; + mLayer = &mwbackLayer; + break; + default: + ERR("Invalid WEAPON_LAYER specified."); + return -1; + } + + if(*mLayer > *nLayer) /* More memory allocated then needed. */ + curLayer[(*nLayer)++] = w; + else { /* Need to allocate more memory. */ + switch (layer) { + case WEAPON_LAYER_BG: + (*mLayer) += WEAPON_CHUNK; + curLayer = wbackLayer = realloc(curLayer, (*mLayer)*sizeof(Weapon*)); + break; + case WEAPON_LAYER_FG: + (*mLayer) += WEAPON_CHUNK; + curLayer = wfrontLayer = realloc(curLayer, (*mLayer)*sizeof(Weapon*)); + break; + } + curLayer[(*nLayer)++] = w; + } + + return w->ID; +} + +/** + * @fn void beam_end(const unsigned int parent, int beam) + * + * @brief End a beam weapon. + * @param parent + * @param beam + */ +void beam_end(const unsigned int parent, int beam) { + int i; + WeaponLayer layer; + Weapon** curLayer; + int* mLayer, *nLayer; + + layer = (parent == PLAYER_ID) ? WEAPON_LAYER_FG : WEAPON_LAYER_BG; + + /* Set the proper layer. */ + switch(layer) { + case WEAPON_LAYER_BG: + curLayer = wbackLayer; + nLayer = &nwbackLayer; + mLayer = &mwbackLayer; + break; + case WEAPON_LAYER_FG: + curLayer = wfrontLayer; + nLayer = &nwfrontLayer; + mLayer = &mwfrontLayer; + break; + default: + ERR("Invalid WEAPON_LAYER specified."); + return; + } + + /* Now try to destroy the beam. */ + for(i = 0; i < *nLayer; i++) { + if(curLayer[i]->ID == beam) { /* Found it. */ + weapon_destroy(curLayer[i], layer); + break; + } + } +} + /* Destroy the weapon. */ static void weapon_destroy(Weapon* w, WeaponLayer layer) { int i; diff --git a/src/weapon.h b/src/weapon.h index 2c8e7c7..0462091 100644 --- a/src/weapon.h +++ b/src/weapon.h @@ -16,6 +16,12 @@ void weapon_add(const Outfit* outfit, const double dir, const Vec2* pos, const Vec2* vel, unsigned int parent, const unsigned int target); +int beam_start(const Outfit* outfit, + const double dir, const Vec2* pos, const Vec2* vel, + const unsigned int parent, const unsigned int beam); + +void beam_end(const unsigned int parent, int beam); + /* Update. */ void weapons_update(const double dt); void weapons_render(const WeaponLayer layer);