[Add] Mountpoints for turrets implemented.
This commit is contained in:
parent
252f2f87b7
commit
5429ed970d
47
dat/ship.xml
47
dat/ship.xml
@ -920,5 +920,52 @@
|
||||
<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 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>
|
||||
</Ships>
|
||||
|
156
src/pilot.c
156
src/pilot.c
@ -7,6 +7,7 @@
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "lephisto.h"
|
||||
#include "log.h"
|
||||
@ -69,9 +70,10 @@ static void pilot_update(Pilot* pilot, const double dt);
|
||||
static void pilot_hyperspace(Pilot* pilot);
|
||||
void pilot_render(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 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.
|
||||
@ -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.
|
||||
* @param p Pilot that is shooting.
|
||||
@ -299,9 +322,20 @@ void pilot_shootStop(Pilot* p, const int secondary) {
|
||||
* @param t Pilot's target.
|
||||
*/
|
||||
static void pilot_shootWeapon(Pilot* p, PilotOutfit* w) {
|
||||
int id;
|
||||
Vec2 v;
|
||||
|
||||
/* Check to see if weapon is ready. */
|
||||
if(w->timer > 0.)
|
||||
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. */
|
||||
if(outfit_isBolt(w->outfit)) {
|
||||
/* Enough energy? */
|
||||
@ -309,7 +343,7 @@ static void pilot_shootWeapon(Pilot* p, PilotOutfit* w) {
|
||||
|
||||
p->energy -= outfit_energy(w->outfit);
|
||||
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. */
|
||||
@ -319,7 +353,7 @@ static void pilot_shootWeapon(Pilot* p, PilotOutfit* w) {
|
||||
/** @todo Handle warmup stage. */
|
||||
w->state = PILOT_OUTFIT_ON;
|
||||
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;
|
||||
|
||||
p->energy -= outfit_energy(w->outfit);
|
||||
weapon_add(p->ammo->outfit, p->solid->dir, &p->solid->pos,
|
||||
&p->solid->vel, p->id, p->target);
|
||||
weapon_add(p->ammo->outfit, p->solid->dir,
|
||||
&v, &p->solid->vel, p->id, p->target);
|
||||
|
||||
p->ammo->quantity -= 1; /* There's no getting this one back. */
|
||||
if(p->ammo->quantity <= 0) /* Out of ammo. */
|
||||
@ -360,7 +394,7 @@ static void pilot_shootWeapon(Pilot* p, PilotOutfit* w) {
|
||||
|
||||
/* Create escort. */
|
||||
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. */
|
||||
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);
|
||||
}
|
||||
|
||||
/* Reset timer. */
|
||||
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.
|
||||
* @param pilot Pilot to add the outfit to.
|
||||
@ -910,8 +989,10 @@ void pilot_hyperspaceAbort(Pilot* p) {
|
||||
* @return Amount of the outfit added.
|
||||
*/
|
||||
int pilot_addOutfit(Pilot* pilot, Outfit* outfit, int quantity) {
|
||||
int i, q, free_space;
|
||||
int i;
|
||||
int o, q, free_space;
|
||||
char* osec;
|
||||
PilotOutfit* po;
|
||||
|
||||
free_space = pilot_freeSpace(pilot);
|
||||
q = quantity;
|
||||
@ -940,12 +1021,19 @@ int pilot_addOutfit(Pilot* pilot, Outfit* outfit, int quantity) {
|
||||
/* Does outfit already exist? */
|
||||
for(i = 0; i < pilot->noutfits; i++)
|
||||
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. */
|
||||
if(pilot->outfits[i].quantity > outfit->max) {
|
||||
q -= pilot->outfits[i].quantity - outfit->max;
|
||||
pilot->outfits[i].quantity = outfit->max;
|
||||
if(po->quantity > outfit->max) {
|
||||
q -= po->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. */
|
||||
pilot_calcStats(pilot);
|
||||
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. */
|
||||
|
||||
/* Grow the outfits. */
|
||||
pilot->outfits = realloc(pilot->outfits, (pilot->noutfits+1)*sizeof(PilotOutfit));
|
||||
pilot->outfits[pilot->noutfits].outfit = outfit;
|
||||
pilot->outfits[pilot->noutfits].quantity = q;
|
||||
pilot->outfits[pilot->noutfits].timer = 0;
|
||||
pilot->outfits[pilot->noutfits].beamid = 0;
|
||||
pilot->noutfits++;
|
||||
pilot->outfits = realloc(pilot->outfits, pilot->noutfits*sizeof(PilotOutfit));
|
||||
po = &pilot->outfits[pilot->noutfits-1];
|
||||
memset(po, 0, sizeof(PilotOutfit));
|
||||
po->outfit = outfit;
|
||||
po->quantity = q;
|
||||
|
||||
/* Can't be over max. */
|
||||
if(pilot->outfits[pilot->noutfits].quantity > outfit->max) {
|
||||
q -= pilot->outfits[pilot->noutfits].quantity - outfit->max;
|
||||
pilot->outfits[i].quantity = outfit->max;
|
||||
if(po->quantity > outfit->max) {
|
||||
q -= po->quantity - outfit->max;
|
||||
po->quantity = outfit->max;
|
||||
}
|
||||
pilot->outfits[pilot->noutfits].timer = 0; /* Reset time. */
|
||||
(pilot->noutfits)++;
|
||||
|
||||
if(outfit_isTurret(outfit))
|
||||
/* Used to speed up AI. */
|
||||
if(outfit_isTurret(outfit)) { /* 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);
|
||||
}
|
||||
|
||||
if(outfit_isBeam(outfit))
|
||||
/* 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. */
|
||||
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. */
|
||||
memmove(&pilot->outfits[i], &pilot->outfits[i+1],
|
||||
sizeof(PilotOutfit)*(pilot->noutfits-i-1));
|
||||
@ -1419,18 +1512,16 @@ void pilot_init(Pilot* pilot, Ship* ship, char* name, int faction,
|
||||
/* Solid. */
|
||||
pilot->solid = solid_create(ship->mass, dir, pos, vel);
|
||||
|
||||
/* Mounts. */
|
||||
if(ship->nmounts > 0)
|
||||
pilot->mounted = calloc(ship->nmounts, sizeof(int));
|
||||
|
||||
/* Outfits. */
|
||||
if(!(flags & PILOT_NO_OUTFITS)) {
|
||||
if(ship->outfit) {
|
||||
pilot->noutfits = 0;
|
||||
for(so = ship->outfit; so; so = so->next) {
|
||||
pilot->outfits = realloc(pilot->outfits, (pilot->noutfits+1)*sizeof(PilotOutfit));
|
||||
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);
|
||||
pilot_addOutfit(pilot, so->data, so->quantity);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1580,13 +1671,16 @@ void pilot_free(Pilot* p) {
|
||||
if(p->hook_type[i] != PILOT_HOOK_NONE)
|
||||
hook_rm(p->hook[i]);
|
||||
|
||||
free(p->name);
|
||||
|
||||
/* Clean up data. */
|
||||
if(p->ai != NULL)
|
||||
ai_destroy(p); /* Must be destroyed first if applicable. */
|
||||
/* Case for if pilot is the player. */
|
||||
if(player == p) player = NULL;
|
||||
solid_free(p->solid);
|
||||
if(p->mounted != NULL) free(p->mounted);
|
||||
if(p->outfits) free(p->outfits);
|
||||
free(p->name);
|
||||
if(p->commodities) free(p->commodities);
|
||||
if(p->escorts) free(p->escorts);
|
||||
free(p);
|
||||
|
@ -89,6 +89,8 @@ typedef struct PilotOutfit_ {
|
||||
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. */
|
||||
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. */
|
||||
} PilotOutfit;
|
||||
|
||||
@ -167,6 +169,7 @@ typedef struct Pilot_ {
|
||||
uint32_t flags; /**< Used for AI etc. */
|
||||
double ptimer; /**< Generic timer for internal pilot use. */
|
||||
int lockons; /**< Stores how many seeking weapons are targetting pilot. */
|
||||
int* mounted; /**< Number of mounted outfits on the mount. */
|
||||
|
||||
/* Hook attached 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);
|
||||
void pilot_hyperspaceAbort(Pilot* p);
|
||||
/* Special outfit stuff. */
|
||||
int pilot_getMount(Pilot* p, int id, Vec2* v);
|
||||
void pilot_switchSecondary(Pilot* p, int i);
|
||||
void pilot_setSecondary(Pilot* p, const char* secondary);
|
||||
void pilot_setAmmo(Pilot* p);
|
||||
|
109
src/ship.c
109
src/ship.c
@ -44,6 +44,52 @@ Ship* ship_get(const char* name) {
|
||||
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. */
|
||||
Ship** ship_getTech(int* n, const int* tech, const int techmax) {
|
||||
int i, j, k, num, price;
|
||||
@ -226,9 +272,9 @@ int ship_basePrice(Ship* s) {
|
||||
static int ship_parse(Ship* tmp, xmlNodePtr parent) {
|
||||
xmlNodePtr cur, node;
|
||||
ShipOutfit* otmp, *ocur;
|
||||
|
||||
char str[PATH_MAX];
|
||||
char* stmp;
|
||||
int id;
|
||||
|
||||
/* Clear memory. */
|
||||
memset(tmp, 0, sizeof(Ship));
|
||||
@ -253,6 +299,10 @@ static int ship_parse(Ship* tmp, xmlNodePtr parent) {
|
||||
SHIP_GFX"%s"SHIP_EXT, 6, 6,
|
||||
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. */
|
||||
tmp->gfx_comm = xml_parseTexture(node,
|
||||
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));
|
||||
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));
|
||||
|
||||
tmp->thrust *= tmp->mass; /* Helps keep number sane. */
|
||||
|
||||
#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) {
|
||||
Ship* s;
|
||||
ShipOutfit* so, *sot;
|
||||
int i;
|
||||
for(i = 0; i < ship_nstack; i++) {
|
||||
/* Free stored strings. */
|
||||
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);
|
||||
s = &ship_stack[i];
|
||||
|
||||
so = ship_stack[i].outfit;
|
||||
while(so) { /* free the ship outfit. */
|
||||
/* Free stored strings. */
|
||||
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;
|
||||
so = so->next;
|
||||
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);
|
||||
}
|
||||
free(ship_stack);
|
||||
|
31
src/ship.h
31
src/ship.h
@ -8,9 +8,7 @@
|
||||
#define SHIP_TARGET_H 96 /**< Ship target graphic height. */
|
||||
|
||||
/**
|
||||
* @typedef ShipClass
|
||||
*
|
||||
* @breif Contains the different types of ships.
|
||||
* @brief Contains the different types of ships.
|
||||
*/
|
||||
typedef enum ShipClass_ {
|
||||
SHIP_CLASS_NULL, /**< Invalid ship. */
|
||||
@ -38,7 +36,18 @@ typedef enum ShipClass_ {
|
||||
/** @todo hybrid ship classification. */
|
||||
} 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_ {
|
||||
struct ShipOutfit_* next; /* Linked list. */
|
||||
Outfit* data; /* Data itself. */
|
||||
@ -87,19 +96,25 @@ typedef struct Ship_ {
|
||||
|
||||
/* Outfits */
|
||||
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;
|
||||
|
||||
/* Load/quit. */
|
||||
int ships_load(void);
|
||||
void ships_free(void);
|
||||
|
||||
/* Get. */
|
||||
int ship_getMount(Ship* s, double dir, const int id, Vec2* p);
|
||||
Ship* ship_get(const char* name);
|
||||
Ship** ship_getTech(int* n, const int* tech, const int techmax);
|
||||
char* ship_class(Ship* p);
|
||||
ShipClass ship_classFromString(char* str);
|
||||
int ship_basePrice(Ship* s);
|
||||
|
||||
/* Load/quit. */
|
||||
int ships_load(void);
|
||||
void ships_free(void);
|
||||
|
||||
/* Toolkit. */
|
||||
void ship_view(unsigned int unused, char* shipname);
|
||||
|
||||
|
27
src/weapon.c
27
src/weapon.c
@ -63,7 +63,8 @@ typedef struct Weapon_ {
|
||||
double lockon; /**< Some weapons have a lockon delay. */
|
||||
double timer; /**< Mainly used to see when the weapon was fired. */
|
||||
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. */
|
||||
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;
|
||||
Pilot* p, *t;
|
||||
double diff;
|
||||
Vec2 v;
|
||||
|
||||
/* Get pilot, if pilot is dead beam is destroyed too. */
|
||||
p = pilot_get(w->parent);
|
||||
@ -260,9 +262,10 @@ static void think_beam(Weapon* w, const double dt) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Update beam position to match pilot. */
|
||||
w->solid->pos.x = p->solid->pos.x;
|
||||
w->solid->pos.y = p->solid->pos.y;
|
||||
/* Use mount position. */
|
||||
pilot_getMount(p, w->mount, &v);
|
||||
w->solid->pos.x = v.x;
|
||||
w->solid->pos.y = v.y;
|
||||
|
||||
/* Handle aiming. */
|
||||
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.
|
||||
* @param w Weapon to update.
|
||||
* @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. */
|
||||
if(outfit_isBeam(w->outfit)) {
|
||||
/* Check for collision. */
|
||||
if(!areAllies(w->faction, pilot_stack[i]->faction) &&
|
||||
CollideLineSprite(&w->solid->pos, w->solid->dir,
|
||||
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. */
|
||||
parent = pilot_get(w->parent);
|
||||
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. */
|
||||
}
|
||||
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.
|
||||
* @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.
|
||||
* @param mount Mount on the ship.
|
||||
* @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) {
|
||||
const unsigned int parent, const unsigned int target,
|
||||
const int mount) {
|
||||
|
||||
WeaponLayer layer;
|
||||
Weapon* w;
|
||||
@ -1033,6 +1033,7 @@ int beam_start(const Outfit* outfit,
|
||||
layer = (parent == PLAYER_ID) ? WEAPON_LAYER_FG : WEAPON_LAYER_BG;
|
||||
w = weapon_create(outfit, dir, pos, vel, parent, target);
|
||||
w->ID = ++beam_idgen;
|
||||
w->mount = mount;
|
||||
|
||||
switch(layer) {
|
||||
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.
|
||||
* @param parent
|
||||
* @param beam
|
||||
|
@ -18,7 +18,8 @@ void weapon_add(const Outfit* outfit, const double dir, const Vec2* pos,
|
||||
|
||||
int beam_start(const Outfit* outfit,
|
||||
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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user