[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="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>
|
||||||
|
156
src/pilot.c
156
src/pilot.c
@ -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,13 +1671,16 @@ 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->mounted != NULL) free(p->mounted);
|
||||||
if(p->outfits) free(p->outfits);
|
if(p->outfits) free(p->outfits);
|
||||||
free(p->name);
|
|
||||||
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);
|
||||||
|
@ -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);
|
||||||
|
109
src/ship.c
109
src/ship.c
@ -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);
|
||||||
|
31
src/ship.h
31
src/ship.h
@ -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);
|
||||||
|
|
||||||
|
27
src/weapon.c
27
src/weapon.c
@ -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
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user