[Add] Mountpoints for turrets implemented.

This commit is contained in:
Allanis 2014-05-20 14:23:16 +01:00
parent 252f2f87b7
commit 5429ed970d
7 changed files with 315 additions and 70 deletions

View File

@ -920,5 +920,52 @@
<outfit quantity="2">Seeker Launcher</outfit> <outfit quantity="2">Seeker Launcher</outfit>
<outfit quantity="20">Seeker Missile</outfit> <outfit quantity="20">Seeker Missile</outfit>
</outfits> </outfits>
<mounts>
<mount x="30" y="0" h="3">0</mount>
<mount x="-18" y="-5" h="10">1</mount>
<mount x="-18" y="5" h="10">2</mount>
<mount x="30" y="0" h="3">3</mount>
</mounts>
</ship>
<ship name="Pirate Kestrel">
<GFX target="kestrel">kestrel_pirate</GFX>
<GUI>minimal</GUI>
<sound>engine</sound>
<class>Cruiser</class>
<price>5700000</price>
<fabricator>Skull and Bones</fabricator>
<tech>9009</tech>
<description>The Kestrel is the best ship made the the Skull and Bones. It is extremely agile for a cruiser yet doesn't even lack the firepower necessary to question the authority of the Empire. A very strong ship for those pirates who can afford it.</description>
<movement>
<thrust>130</thrust>
<turn>110</turn>
<speed>150</speed>
</movement>
<health>
<shield>600</shield>
<armour>280</armour>
<energy>830</energy>
<shield_regen>380</shield_regen>
<armour_regen>90</armour_regen>
<energy_regen>1300</energy_regen>
</health>
<characteristics>
<crew>28</crew>
<mass>2725</mass>
<fuel>300</fuel>
<cap_weapon>160</cap_weapon>
<cap_cargo>55</cap_cargo>
</characteristics>
<outfits>
<outfit quantity="2">Heavy Ion Turret</outfit>
<outfit quantity="2">Seeker Launcher</outfit>
<outfit quantity="20">Seeker Missile</outfit>
</outfits>
<mounts>
<mount x="30" y="0" h="3">0</mount>
<mount x="-18" y="-5" h="10">1</mount>
<mount x="-18" y="5" h="10">2</mount>
<mount x="30" y="0" h="3">3</mount>
</mounts>
</ship> </ship>
</Ships> </Ships>

View File

@ -7,6 +7,7 @@
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include <stdlib.h> #include <stdlib.h>
#include <limits.h>
#include "lephisto.h" #include "lephisto.h"
#include "log.h" #include "log.h"
@ -69,9 +70,10 @@ static void pilot_update(Pilot* pilot, const double dt);
static void pilot_hyperspace(Pilot* pilot); static void pilot_hyperspace(Pilot* pilot);
void pilot_render(Pilot* pilot); void pilot_render(Pilot* pilot);
static void pilot_calcCargo(Pilot* pilot); static void pilot_calcCargo(Pilot* pilot);
void pilot_free(Pilot* p); void pilot_free(Pilot* p); /* Externed in player.c */
static int fleet_parse(Fleet* tmp, const xmlNodePtr parent); static int fleet_parse(Fleet* tmp, const xmlNodePtr parent);
static void pilot_dead(Pilot* p); static void pilot_dead(Pilot* p);
static int pilot_setOutfitMounts(Pilot* p, PilotOutfit* po, int o, int q);
/** /**
* @brief Get the pilots position in the stack. * @brief Get the pilots position in the stack.
@ -292,6 +294,27 @@ void pilot_shootStop(Pilot* p, const int secondary) {
} }
} }
/**
* @brief Get the mount position of a pilot.
* @param p Pilot to get mount position of.
* @param id ID of the mount.
* @param[out] v Position of the mount.
* @return 0 on success.
*/
int pilot_getMount(Pilot* p, int id, Vec2* v) {
double a;
/* Calculate the sprite angle. */
a = (double)(p->tsy * p->ship->gfx_space->sx + p->tsx);
a *= p->ship->mangle;
/* Get the mount and add the player offset. */
ship_getMount(p->ship, a, id, v);
vect_cadd(v, p->solid->pos.x, p->solid->pos.y);
return 0;
}
/** /**
* @brief Actually handles the shooting, how often the player can shoot and such. * @brief Actually handles the shooting, how often the player can shoot and such.
* @param p Pilot that is shooting. * @param p Pilot that is shooting.
@ -299,9 +322,20 @@ void pilot_shootStop(Pilot* p, const int secondary) {
* @param t Pilot's target. * @param t Pilot's target.
*/ */
static void pilot_shootWeapon(Pilot* p, PilotOutfit* w) { static void pilot_shootWeapon(Pilot* p, PilotOutfit* w) {
int id;
Vec2 v;
/* Check to see if weapon is ready. */ /* Check to see if weapon is ready. */
if(w->timer > 0.) if(w->timer > 0.)
return; return;
/* Get weapon to see if weapon is ready. */
if(w->mounts == NULL)
id = 0;
else if(outfit_isTurret(w->outfit))
id = w->mounts[w->lastshot];
pilot_getMount(p, id, &v);
/* Regular bolt weapons. */ /* Regular bolt weapons. */
if(outfit_isBolt(w->outfit)) { if(outfit_isBolt(w->outfit)) {
/* Enough energy? */ /* Enough energy? */
@ -309,7 +343,7 @@ static void pilot_shootWeapon(Pilot* p, PilotOutfit* w) {
p->energy -= outfit_energy(w->outfit); p->energy -= outfit_energy(w->outfit);
weapon_add(w->outfit, p->solid->dir, weapon_add(w->outfit, p->solid->dir,
&p->solid->pos, &p->solid->vel, p->id, p->target); &v, &p->solid->vel, p->id, p->target);
} }
/* Beam Weapons. */ /* Beam Weapons. */
@ -319,7 +353,7 @@ static void pilot_shootWeapon(Pilot* p, PilotOutfit* w) {
/** @todo Handle warmup stage. */ /** @todo Handle warmup stage. */
w->state = PILOT_OUTFIT_ON; w->state = PILOT_OUTFIT_ON;
w->beamid = beam_start(w->outfit, p->solid->dir, w->beamid = beam_start(w->outfit, p->solid->dir,
&p->solid->pos, &p->solid->vel, p->id, p->target); &v, &p->solid->vel, p->id, p->target, id);
} }
/* /*
@ -341,8 +375,8 @@ static void pilot_shootWeapon(Pilot* p, PilotOutfit* w) {
return; return;
p->energy -= outfit_energy(w->outfit); p->energy -= outfit_energy(w->outfit);
weapon_add(p->ammo->outfit, p->solid->dir, &p->solid->pos, weapon_add(p->ammo->outfit, p->solid->dir,
&p->solid->vel, p->id, p->target); &v, &p->solid->vel, p->id, p->target);
p->ammo->quantity -= 1; /* There's no getting this one back. */ p->ammo->quantity -= 1; /* There's no getting this one back. */
if(p->ammo->quantity <= 0) /* Out of ammo. */ if(p->ammo->quantity <= 0) /* Out of ammo. */
@ -360,7 +394,7 @@ static void pilot_shootWeapon(Pilot* p, PilotOutfit* w) {
/* Create escort. */ /* Create escort. */
escort_create(p->id, p->ammo->outfit->u.fig.ship, escort_create(p->id, p->ammo->outfit->u.fig.ship,
&p->solid->pos, &p->solid->vel, 1); &v, &p->solid->vel, 1);
p->ammo->quantity -= 1; /* We just shot it. */ p->ammo->quantity -= 1; /* We just shot it. */
if(p->ammo->quantity <= 0) /* Out of ammo. */ if(p->ammo->quantity <= 0) /* Out of ammo. */
@ -369,7 +403,13 @@ static void pilot_shootWeapon(Pilot* p, PilotOutfit* w) {
WARN("Shooting unknown weapon type: %s", w->outfit->name); WARN("Shooting unknown weapon type: %s", w->outfit->name);
} }
/* Reset timer. */
w->timer += ((double)outfit_delay(w->outfit) / (double)w->quantity)/1000.; w->timer += ((double)outfit_delay(w->outfit) / (double)w->quantity)/1000.;
/* Mark last updated. */
w->lastshot++;
if(w->lastshot >= w->quantity)
w->lastshot = 0;
} }
/** /**
@ -902,6 +942,45 @@ void pilot_hyperspaceAbort(Pilot* p) {
} }
} }
/**
* @brief Set the mount points for an outfit.
* @param po Outfit to set mount points for.
* @param o Original number of outfits.
* @param q outfits added.
* @retrurn 0 on success.
*/
static int pilot_setOutfitMounts(Pilot* p, PilotOutfit* po, int o, int q) {
int i, n, k, min;
/* Grow the memory. */
po->mounts = realloc(po->mounts, o+q * sizeof(int));
/* Has to be done for each outfit added. */
for(n = o; n < o+q; n++) {
/* Special case no ship mounts. */
if(p->mounted == NULL) {
po->mounts[n] = 0;
continue;
}
/* Default to 0. */
k = 0;
min = INT_MAX;
/* Find mount with fewest spots. */
for(i = 1; i < p->ship->nmounts; i++) {
if(p->mounted[i] < min) {
k = i;
min = p->mounted[i];
}
}
/* Add the mount point. */
po->mounts[n] = k;
p->mounted[k]++;
}
return 0;
}
/** /**
* @brief Add an outfit to the pilot. * @brief Add an outfit to the pilot.
* @param pilot Pilot to add the outfit to. * @param pilot Pilot to add the outfit to.
@ -910,8 +989,10 @@ void pilot_hyperspaceAbort(Pilot* p) {
* @return Amount of the outfit added. * @return Amount of the outfit added.
*/ */
int pilot_addOutfit(Pilot* pilot, Outfit* outfit, int quantity) { int pilot_addOutfit(Pilot* pilot, Outfit* outfit, int quantity) {
int i, q, free_space; int i;
int o, q, free_space;
char* osec; char* osec;
PilotOutfit* po;
free_space = pilot_freeSpace(pilot); free_space = pilot_freeSpace(pilot);
q = quantity; q = quantity;
@ -940,12 +1021,19 @@ int pilot_addOutfit(Pilot* pilot, Outfit* outfit, int quantity) {
/* Does outfit already exist? */ /* Does outfit already exist? */
for(i = 0; i < pilot->noutfits; i++) for(i = 0; i < pilot->noutfits; i++)
if(strcmp(outfit->name, pilot->outfits[i].outfit->name)==0) { if(strcmp(outfit->name, pilot->outfits[i].outfit->name)==0) {
pilot->outfits[i].quantity += q; po = &pilot->outfits[i];
o = po->quantity;
po->quantity += q;
/* Can't be over max. */ /* Can't be over max. */
if(pilot->outfits[i].quantity > outfit->max) { if(po->quantity > outfit->max) {
q -= pilot->outfits[i].quantity - outfit->max; q -= po->quantity - outfit->max;
pilot->outfits[i].quantity = outfit->max; po->quantity = outfit->max;
} }
/* If it's a turret we need to find a mount spot for it. */
if(outfit_isTurret(outfit))
pilot_setOutfitMounts(pilot, po, o, q);
/* Recalculate the stats. */ /* Recalculate the stats. */
pilot_calcStats(pilot); pilot_calcStats(pilot);
return q; return q;
@ -957,23 +1045,24 @@ int pilot_addOutfit(Pilot* pilot, Outfit* outfit, int quantity) {
/* since pilot has only one afterburner it's handled at the end. */ /* since pilot has only one afterburner it's handled at the end. */
/* Grow the outfits. */ /* Grow the outfits. */
pilot->outfits = realloc(pilot->outfits, (pilot->noutfits+1)*sizeof(PilotOutfit)); pilot->noutfits++;
pilot->outfits[pilot->noutfits].outfit = outfit; pilot->outfits = realloc(pilot->outfits, pilot->noutfits*sizeof(PilotOutfit));
pilot->outfits[pilot->noutfits].quantity = q; po = &pilot->outfits[pilot->noutfits-1];
pilot->outfits[pilot->noutfits].timer = 0; memset(po, 0, sizeof(PilotOutfit));
pilot->outfits[pilot->noutfits].beamid = 0; po->outfit = outfit;
po->quantity = q;
/* Can't be over max. */ /* Can't be over max. */
if(pilot->outfits[pilot->noutfits].quantity > outfit->max) { if(po->quantity > outfit->max) {
q -= pilot->outfits[pilot->noutfits].quantity - outfit->max; q -= po->quantity - outfit->max;
pilot->outfits[i].quantity = outfit->max; po->quantity = outfit->max;
} }
pilot->outfits[pilot->noutfits].timer = 0; /* Reset time. */
(pilot->noutfits)++;
if(outfit_isTurret(outfit)) if(outfit_isTurret(outfit)) { /* Used to speed up AI. */
/* Used to speed up AI. */ /* If it's a turret we need to find a mount sport for it. */
pilot_setOutfitMounts(pilot, po, 0, q);
pilot_setFlag(pilot, PILOT_HASTURRET); pilot_setFlag(pilot, PILOT_HASTURRET);
}
if(outfit_isBeam(outfit)) if(outfit_isBeam(outfit))
/* Used to speed up some calculation. */ /* Used to speed up some calculation. */
@ -1011,6 +1100,10 @@ int pilot_rmOutfit(Pilot* pilot, Outfit* outfit, int quantity) {
/* Hack in case it reallocs - Can happen even when shrinking. */ /* Hack in case it reallocs - Can happen even when shrinking. */
osec = (pilot->secondary) ? pilot->secondary->outfit->name : NULL; osec = (pilot->secondary) ? pilot->secondary->outfit->name : NULL;
/* Free some memory if needed. */
if(pilot->outfits[i].mounts != NULL)
free(pilot->outfits[i].mounts);
/* Remove the outfit. */ /* Remove the outfit. */
memmove(&pilot->outfits[i], &pilot->outfits[i+1], memmove(&pilot->outfits[i], &pilot->outfits[i+1],
sizeof(PilotOutfit)*(pilot->noutfits-i-1)); sizeof(PilotOutfit)*(pilot->noutfits-i-1));
@ -1419,18 +1512,16 @@ void pilot_init(Pilot* pilot, Ship* ship, char* name, int faction,
/* Solid. */ /* Solid. */
pilot->solid = solid_create(ship->mass, dir, pos, vel); pilot->solid = solid_create(ship->mass, dir, pos, vel);
/* Mounts. */
if(ship->nmounts > 0)
pilot->mounted = calloc(ship->nmounts, sizeof(int));
/* Outfits. */ /* Outfits. */
if(!(flags & PILOT_NO_OUTFITS)) { if(!(flags & PILOT_NO_OUTFITS)) {
if(ship->outfit) { if(ship->outfit) {
pilot->noutfits = 0; pilot->noutfits = 0;
for(so = ship->outfit; so; so = so->next) { for(so = ship->outfit; so; so = so->next) {
pilot->outfits = realloc(pilot->outfits, (pilot->noutfits+1)*sizeof(PilotOutfit)); pilot_addOutfit(pilot, so->data, so->quantity);
pilot->outfits[pilot->noutfits].outfit = so->data;
pilot->outfits[pilot->noutfits].quantity = so->quantity;
pilot->outfits[pilot->noutfits].timer = 0;
(pilot->noutfits)++;
if(outfit_isTurret(so->data)) /* Used to speed up AI a bit. */
pilot_setFlag(pilot, PILOT_HASTURRET);
} }
} }
} }
@ -1580,15 +1671,18 @@ void pilot_free(Pilot* p) {
if(p->hook_type[i] != PILOT_HOOK_NONE) if(p->hook_type[i] != PILOT_HOOK_NONE)
hook_rm(p->hook[i]); hook_rm(p->hook[i]);
free(p->name);
/* Clean up data. */ /* Clean up data. */
if(p->ai != NULL) if(p->ai != NULL)
ai_destroy(p); /* Must be destroyed first if applicable. */ ai_destroy(p); /* Must be destroyed first if applicable. */
/* Case for if pilot is the player. */
if(player == p) player = NULL; if(player == p) player = NULL;
solid_free(p->solid); solid_free(p->solid);
if(p->outfits) free(p->outfits); if(p->mounted != NULL) free(p->mounted);
free(p->name); if(p->outfits) free(p->outfits);
if(p->commodities) free(p->commodities); if(p->commodities) free(p->commodities);
if(p->escorts) free(p->escorts); if(p->escorts) free(p->escorts);
free(p); free(p);
} }

View File

@ -89,6 +89,8 @@ typedef struct PilotOutfit_ {
int quantity; /**< Number of outfits of this type that the pilot has. */ int quantity; /**< Number of outfits of this type that the pilot has. */
PilotOutfitState state; /**< State of the outfit. */ PilotOutfitState state; /**< State of the outfit. */
int beamid; /**< ID of the beam used in this outfit, only for beams. */ int beamid; /**< ID of the beam used in this outfit, only for beams. */
int* mounts; /**< ID of each outfit mount. */
int lastshot; /**< ID of the outfit that last shot. */
double timer; /**< Used to store last used weapon time. */ double timer; /**< Used to store last used weapon time. */
} PilotOutfit; } PilotOutfit;
@ -167,6 +169,7 @@ typedef struct Pilot_ {
uint32_t flags; /**< Used for AI etc. */ uint32_t flags; /**< Used for AI etc. */
double ptimer; /**< Generic timer for internal pilot use. */ double ptimer; /**< Generic timer for internal pilot use. */
int lockons; /**< Stores how many seeking weapons are targetting pilot. */ int lockons; /**< Stores how many seeking weapons are targetting pilot. */
int* mounted; /**< Number of mounted outfits on the mount. */
/* Hook attached to the pilot. */ /* Hook attached to the pilot. */
int hook_type[PILOT_HOOKS]; /**< Type of the hook atached to the pilot. */ int hook_type[PILOT_HOOKS]; /**< Type of the hook atached to the pilot. */
@ -239,6 +242,7 @@ void pilot_hit(Pilot* p, const Solid* w, const unsigned int shooter,
double pilot_face(Pilot* p, const double dir); double pilot_face(Pilot* p, const double dir);
void pilot_hyperspaceAbort(Pilot* p); void pilot_hyperspaceAbort(Pilot* p);
/* Special outfit stuff. */ /* Special outfit stuff. */
int pilot_getMount(Pilot* p, int id, Vec2* v);
void pilot_switchSecondary(Pilot* p, int i); void pilot_switchSecondary(Pilot* p, int i);
void pilot_setSecondary(Pilot* p, const char* secondary); void pilot_setSecondary(Pilot* p, const char* secondary);
void pilot_setAmmo(Pilot* p); void pilot_setAmmo(Pilot* p);

View File

@ -44,6 +44,52 @@ Ship* ship_get(const char* name) {
return tmp+i; return tmp+i;
} }
/**
* @brief Get the position of a ship mount point.
* @param s Ship to get the mount point o.
* @param dir Direction ship is facing.
* @param id ID of the mount point to get.
* @param[out] The position of the mount point.
* @return 0 on success.
*/
int ship_getMount(Ship* s, double dir, const int id, Vec2* p) {
ShipMount* m;
double cm, sm;
/* Special case no mounts. */
if((id == 0) && (s->nmounts == 0)) {
p->x = 0.;
p->y = 0.;
return 0;
}
/* Check to see if mount is valid. */
if((id >= s->nmounts) || (id < 0)) {
WARN("Invalid mount point id '%d' on ship class '%s'.", id, s->name);
p->x = 0.;
p->y = 0.;
return 1;
}
m = &s->mounts[id];
/*
* 2D rotation matrix.
* [ x' ] [ cos sin ] [ x ]
* [ y' ] = [-sin cos ] * [ y ]
*
* dir is inverted s that rotation is counter-clockwise.
*/
cm = cos(-dir);
sm = sin(-dir);
p->x = m->x * cm + m->y * sm;
p->y = m->x * -sm + m->y * cm;
/* Don't forget to add height. */
p->y += m->h;
return 0;
}
/* Return all the ships in text form. */ /* Return all the ships in text form. */
Ship** ship_getTech(int* n, const int* tech, const int techmax) { Ship** ship_getTech(int* n, const int* tech, const int techmax) {
int i, j, k, num, price; int i, j, k, num, price;
@ -226,9 +272,9 @@ int ship_basePrice(Ship* s) {
static int ship_parse(Ship* tmp, xmlNodePtr parent) { static int ship_parse(Ship* tmp, xmlNodePtr parent) {
xmlNodePtr cur, node; xmlNodePtr cur, node;
ShipOutfit* otmp, *ocur; ShipOutfit* otmp, *ocur;
char str[PATH_MAX]; char str[PATH_MAX];
char* stmp; char* stmp;
int id;
/* Clear memory. */ /* Clear memory. */
memset(tmp, 0, sizeof(Ship)); memset(tmp, 0, sizeof(Ship));
@ -253,6 +299,10 @@ static int ship_parse(Ship* tmp, xmlNodePtr parent) {
SHIP_GFX"%s"SHIP_EXT, 6, 6, SHIP_GFX"%s"SHIP_EXT, 6, 6,
OPENGL_TEX_MAPTRANS); OPENGL_TEX_MAPTRANS);
/* Calculate mount angle. */
tmp->mangle = 2.*M_PI;
tmp->mangle /= tmp->gfx_space->sx * tmp->gfx_space->sy;
/* Load the comm graphic. */ /* Load the comm graphic. */
tmp->gfx_comm = xml_parseTexture(node, tmp->gfx_comm = xml_parseTexture(node,
SHIP_GFX"%s"SHIP_COMM SHIP_EXT, 1, 1, 0); SHIP_GFX"%s"SHIP_COMM SHIP_EXT, 1, 1, 0);
@ -341,8 +391,33 @@ static int ship_parse(Ship* tmp, xmlNodePtr parent) {
} while(xml_nextNode(cur)); } while(xml_nextNode(cur));
continue; continue;
} }
if(xml_isNode(node, "mounts")) {
/* First pass, get number of mounts. */
cur = node->children;
do {
if(xml_isNode(cur, "mount"))
tmp->nmounts++;
} while(xml_nextNode(cur));
/* Allocate the space. */
tmp->mounts = calloc(tmp->nmounts, sizeof(ShipMount));
/* Second pass, initialize the mounts. */
cur = node->children;
do {
if(xml_isNode(cur, "mount")) {
id = xml_getInt(cur);
xmlr_attr(cur, "x", stmp);
tmp->mounts[id].x = atof(stmp);
free(stmp);
xmlr_attr(cur, "y", stmp);
tmp->mounts[id].y = atof(stmp);
free(stmp);
xmlr_attr(cur, "h", stmp);
tmp->mounts[id].h = atof(stmp);
free(stmp);
}
} while(xml_nextNode(cur));
}
} while(xml_nextNode(node)); } while(xml_nextNode(node));
tmp->thrust *= tmp->mass; /* Helps keep number sane. */ tmp->thrust *= tmp->mass; /* Helps keep number sane. */
#define MELEMENT(o,s) if(o) WARN("Ship '%s' missing '"s"' element", tmp->name) #define MELEMENT(o,s) if(o) WARN("Ship '%s' missing '"s"' element", tmp->name)
@ -421,24 +496,34 @@ int ships_load(void) {
} }
void ships_free(void) { void ships_free(void) {
Ship* s;
ShipOutfit* so, *sot; ShipOutfit* so, *sot;
int i; int i;
for(i = 0; i < ship_nstack; i++) { for(i = 0; i < ship_nstack; i++) {
/* Free stored strings. */ s = &ship_stack[i];
if(ship_stack[i].name) free(ship_stack[i].name);
if(ship_stack[i].description) free(ship_stack[i].description);
if(ship_stack[i].gui) free(ship_stack[i].gui);
if(ship_stack[i].fabricator) free(ship_stack[i].fabricator);
if(ship_stack[i].license != NULL) free(ship_stack[i].license);
so = ship_stack[i].outfit; /* Free stored strings. */
while(so) { /* free the ship outfit. */ if(s->name != NULL) free(s->name);
if(s->description != NULL) free(s->description);
if(s->gui != NULL) free(s->gui);;
if(s->fabricator != NULL) free(s->fabricator);
if(s->license != NULL) free(s->license);
/* Free outfits. */
so = s->outfit;
while(so) {
sot = so; sot = so;
so = so->next; so = so->next;
free(sot); free(sot);
} }
gl_freeTexture(ship_stack[i].gfx_space);
gl_freeTexture(ship_stack[i].gfx_comm); /* Free mounts. */
if(s->nmounts > 0)
free(s->mounts);
/* Free graphics. */
gl_freeTexture(s->gfx_space);
gl_freeTexture(s->gfx_comm);
gl_freeTexture(ship_stack[i].gfx_target); gl_freeTexture(ship_stack[i].gfx_target);
} }
free(ship_stack); free(ship_stack);

View File

@ -8,9 +8,7 @@
#define SHIP_TARGET_H 96 /**< Ship target graphic height. */ #define SHIP_TARGET_H 96 /**< Ship target graphic height. */
/** /**
* @typedef ShipClass * @brief Contains the different types of ships.
*
* @breif Contains the different types of ships.
*/ */
typedef enum ShipClass_ { typedef enum ShipClass_ {
SHIP_CLASS_NULL, /**< Invalid ship. */ SHIP_CLASS_NULL, /**< Invalid ship. */
@ -38,7 +36,18 @@ typedef enum ShipClass_ {
/** @todo hybrid ship classification. */ /** @todo hybrid ship classification. */
} ShipClass; } ShipClass;
/* Small wrapper for the outfits. */ /**
* @brief Represents a ship weapon mount point.
*/
typedef struct ShipMount_ {
double x; /**< X position of the mount point. */
double y; /**< Y position of the mount point. */
double h; /**< Mount point height (displacement). */
} ShipMount;
/**
* @brief Small wrapper for the outfits.
*/
typedef struct ShipOutfit_ { typedef struct ShipOutfit_ {
struct ShipOutfit_* next; /* Linked list. */ struct ShipOutfit_* next; /* Linked list. */
Outfit* data; /* Data itself. */ Outfit* data; /* Data itself. */
@ -87,19 +96,25 @@ typedef struct Ship_ {
/* Outfits */ /* Outfits */
ShipOutfit* outfit; ShipOutfit* outfit;
/* Mounts. */
ShipMount* mounts; /**< Ship weapon mount points. First is primary weapon. */
int nmounts; /**< Number of mount points ship has. */
double mangle; /**< Mount angle to simplify mount calculations. */
} Ship; } Ship;
/* Load/quit. */
int ships_load(void);
void ships_free(void);
/* Get. */ /* Get. */
int ship_getMount(Ship* s, double dir, const int id, Vec2* p);
Ship* ship_get(const char* name); Ship* ship_get(const char* name);
Ship** ship_getTech(int* n, const int* tech, const int techmax); Ship** ship_getTech(int* n, const int* tech, const int techmax);
char* ship_class(Ship* p); char* ship_class(Ship* p);
ShipClass ship_classFromString(char* str); ShipClass ship_classFromString(char* str);
int ship_basePrice(Ship* s); int ship_basePrice(Ship* s);
/* Load/quit. */
int ships_load(void);
void ships_free(void);
/* Toolkit. */ /* Toolkit. */
void ship_view(unsigned int unused, char* shipname); void ship_view(unsigned int unused, char* shipname);

View File

@ -63,7 +63,8 @@ typedef struct Weapon_ {
double lockon; /**< Some weapons have a lockon delay. */ double lockon; /**< Some weapons have a lockon delay. */
double timer; /**< Mainly used to see when the weapon was fired. */ double timer; /**< Mainly used to see when the weapon was fired. */
double anim; /**< Used for beam weapon graphics and others. */ double anim; /**< Used for beam weapon graphics and others. */
int sprite; /**< USed for spinning outfits. */ int sprite; /**< Used for spinning outfits. */
int mount; /**< Used for beam weapons. */
/* Update position and render. */ /* Update position and render. */
void(*update)(struct Weapon_*, const double, WeaponLayer); /**< Update the weapon. */ void(*update)(struct Weapon_*, const double, WeaponLayer); /**< Update the weapon. */
@ -244,6 +245,7 @@ static void think_beam(Weapon* w, const double dt) {
(void) dt; (void) dt;
Pilot* p, *t; Pilot* p, *t;
double diff; double diff;
Vec2 v;
/* Get pilot, if pilot is dead beam is destroyed too. */ /* Get pilot, if pilot is dead beam is destroyed too. */
p = pilot_get(w->parent); p = pilot_get(w->parent);
@ -260,9 +262,10 @@ static void think_beam(Weapon* w, const double dt) {
return; return;
} }
/* Update beam position to match pilot. */ /* Use mount position. */
w->solid->pos.x = p->solid->pos.x; pilot_getMount(p, w->mount, &v);
w->solid->pos.y = p->solid->pos.y; w->solid->pos.x = v.x;
w->solid->pos.y = v.y;
/* Handle aiming. */ /* Handle aiming. */
switch(w->outfit->type) { switch(w->outfit->type) {
@ -544,8 +547,6 @@ static void weapon_render(Weapon* w, const double dt) {
} }
/** /**
* @fn static void weapon_update(Weapon* w, const double dt, WeaponLayer layer)
*
* @brief Updates an individual weapon. * @brief Updates an individual weapon.
* @param w Weapon to update. * @param w Weapon to update.
* @param dt Current delta tick. * @param dt Current delta tick.
@ -570,6 +571,7 @@ static void weapon_update(Weapon* w, const double dt, WeaponLayer layer) {
/* Beam weapons have special collisions. */ /* Beam weapons have special collisions. */
if(outfit_isBeam(w->outfit)) { if(outfit_isBeam(w->outfit)) {
/* Check for collision. */
if(!areAllies(w->faction, pilot_stack[i]->faction) && if(!areAllies(w->faction, pilot_stack[i]->faction) &&
CollideLineSprite(&w->solid->pos, w->solid->dir, CollideLineSprite(&w->solid->pos, w->solid->dir,
w->outfit->u.bem.range, w->outfit->u.bem.range,
@ -692,7 +694,7 @@ static void weapon_hitBeam(Weapon* w, Pilot* p, WeaponLayer layer,
((player->target == p->id) || (RNGF() < 0.30*dt))) { /* 30% chance per second. */ ((player->target == p->id) || (RNGF() < 0.30*dt))) { /* 30% chance per second. */
parent = pilot_get(w->parent); parent = pilot_get(w->parent);
if((parent != NULL) && (parent->faction == FACTION_PLAYER) && if((parent != NULL) && (parent->faction == FACTION_PLAYER) &&
(!pilot_isFlag(p, PILOT_HOSTILE) || (RNGF() < 0.5))) { /* 50% chance. */ (!pilot_isFlag(p, PILOT_HOSTILE) || (RNGF()*dt < 0.5))) { /* 50% chance. */
faction_modPlayer(p->faction, -1.); /* Slowly lower faction. */ faction_modPlayer(p->faction, -1.); /* Slowly lower faction. */
} }
pilot_rmFlag(p, PILOT_BRIBED); pilot_rmFlag(p, PILOT_BRIBED);
@ -1004,21 +1006,19 @@ 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. * @brief Start the beam weapon.
* @param outfit Outfit which spawns the weapon. * @param outfit Outfit which spawns the weapon.
* @param dir Direction of the shooter. * @param dir Direction of the shooter.
* @param vel Velocity of the shooter. * @param vel Velocity of the shooter.
* @param parent Pilot ID of the shooter. * @param parent Pilot ID of the shooter.
* @param target Target ID that is getting shot. * @param target Target ID that is getting shot.
* @param mount Mount on the ship.
* @return The identifier of the beam weapon. * @return The identifier of the beam weapon.
*/ */
int beam_start(const Outfit* outfit, int beam_start(const Outfit* outfit,
const double dir, const Vec2* pos, const Vec2* vel, const double dir, const Vec2* pos, const Vec2* vel,
const unsigned int parent, const unsigned int target) { const unsigned int parent, const unsigned int target,
const int mount) {
WeaponLayer layer; WeaponLayer layer;
Weapon* w; Weapon* w;
@ -1033,6 +1033,7 @@ int beam_start(const Outfit* outfit,
layer = (parent == PLAYER_ID) ? WEAPON_LAYER_FG : WEAPON_LAYER_BG; layer = (parent == PLAYER_ID) ? WEAPON_LAYER_FG : WEAPON_LAYER_BG;
w = weapon_create(outfit, dir, pos, vel, parent, target); w = weapon_create(outfit, dir, pos, vel, parent, target);
w->ID = ++beam_idgen; w->ID = ++beam_idgen;
w->mount = mount;
switch(layer) { switch(layer) {
case WEAPON_LAYER_BG: case WEAPON_LAYER_BG:
@ -1070,8 +1071,6 @@ int beam_start(const Outfit* outfit,
} }
/** /**
* @fn void beam_end(const unsigned int parent, int beam)
*
* @brief End a beam weapon. * @brief End a beam weapon.
* @param parent * @param parent
* @param beam * @param beam

View File

@ -18,7 +18,8 @@ void weapon_add(const Outfit* outfit, const double dir, const Vec2* pos,
int beam_start(const Outfit* outfit, int beam_start(const Outfit* outfit,
const double dir, const Vec2* pos, const Vec2* vel, const double dir, const Vec2* pos, const Vec2* vel,
const unsigned int parent, const unsigned int beam); const unsigned int parent, const unsigned int target,
const int mount);
void beam_end(const unsigned int parent, int beam); void beam_end(const unsigned int parent, int beam);