[Add] Secondary weapons.
[Add] Preliminary seeker missile.
This commit is contained in:
parent
627240c5a4
commit
36f1936667
@ -18,10 +18,8 @@
|
||||
<ai>merchant</ai>
|
||||
<faction>Merchant</faction>
|
||||
<pilots>
|
||||
<pilot chance='100'>Merchant Ship</pilot>
|
||||
<pilot chance='80'>Merchant Ship</pilot>
|
||||
<pilot chance='80'>Merchant Ship</pilot>
|
||||
<pilot chance='60'>Merchant Ship</pilot>
|
||||
<pilot chance='60'>Merchant Ship</pilot>
|
||||
</pilots>
|
||||
</fleet>
|
||||
<fleet name="Pirate">
|
||||
|
@ -1,13 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Outfits>
|
||||
<outfit name="laser">
|
||||
<outfit name="Laser">
|
||||
<general>
|
||||
<max>5</max>
|
||||
<tech>2</tech>
|
||||
<mass>1</mass>
|
||||
<mass>5</mass>
|
||||
</general>
|
||||
<specific type = "1">
|
||||
<sound>laser</sound>
|
||||
<specific type="1">
|
||||
<gfx>lasergreen</gfx>
|
||||
<delay>500</delay>
|
||||
<speed>550</speed>
|
||||
@ -19,4 +18,33 @@
|
||||
</damage>
|
||||
</specific>
|
||||
</outfit>
|
||||
<outfit name="Missile Launcher">
|
||||
<general>
|
||||
<max>2</max>
|
||||
<tech>4</tech>
|
||||
<mass>10</mass>
|
||||
</general>
|
||||
<specific type="5" secondary="1">
|
||||
<ammo>Missile</ammo>
|
||||
<delay>1200</delay>
|
||||
</specific>
|
||||
</outfit>
|
||||
<outfit name="Missile">
|
||||
<general>
|
||||
<max>60</max>
|
||||
<tech>2</tech>
|
||||
<mass>1</mass>
|
||||
</general>
|
||||
<specific type="6">
|
||||
<gfx>missile</gfx>
|
||||
<duration>5</duration>
|
||||
<thrust>1200</thrust>
|
||||
<turn>200</turn>
|
||||
<speed>600</speed>
|
||||
<damage>
|
||||
<armour>25</armour>
|
||||
<shield>20</shield>
|
||||
</damage>
|
||||
</specific>
|
||||
</outfit>
|
||||
</Outfits>
|
||||
|
@ -24,7 +24,7 @@
|
||||
<cap_cargo>25</cap_cargo>
|
||||
</characteristics>
|
||||
<outfits>
|
||||
<outfit quantity='1'>laser</outfit>
|
||||
<outfit quantity='1'>Laser</outfit>
|
||||
</outfits>
|
||||
</ship>
|
||||
<ship name = "Leapard">
|
||||
@ -51,7 +51,7 @@
|
||||
<cap_cargo>10</cap_cargo>
|
||||
</characteristics>
|
||||
<outfits>
|
||||
<outfit quantity ='2'>laser</outfit>
|
||||
<outfit quantity ='2'>Laser</outfit>
|
||||
</outfits>
|
||||
</ship>
|
||||
<ship name="Lancer">
|
||||
@ -78,7 +78,9 @@
|
||||
<cap_cargo>40</cap_cargo>
|
||||
</characteristics>
|
||||
<outfits>
|
||||
<outfit quantity='4'>laser</outfit>
|
||||
<outfit quantity='3'>Laser</outfit>
|
||||
<outfit quantity='2'>Missile Launcher</outfit>
|
||||
<outfit quantity='20'>Missile</outfit>
|
||||
</outfits>
|
||||
</ship>
|
||||
</Ships>
|
||||
|
BIN
gfx/outfit/missile.png
Normal file
BIN
gfx/outfit/missile.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
107
src/ai.c
107
src/ai.c
@ -48,8 +48,10 @@
|
||||
|
||||
// Call the AI function with name f.
|
||||
#define AI_LCALL(f) (lua_getglobal(L, f), lua_pcall(L, 0, 0, 0))
|
||||
// Register a number constant n to name s (syntax is just like lua_register).
|
||||
// Register a number constant n to name s (syntax is just like lua_regfunc).
|
||||
#define lua_regnumber(l,s,n) (lua_pushnumber(l,n), lua_setglobal(l,s))
|
||||
// Registers a C function.
|
||||
#define lua_regfunc(l,s,f) (lua_pushcfunction(l,f), lua_setglobal(L,s))
|
||||
// L state, void* buf, int n size, char* s identifier.
|
||||
#define luaL_dobuffer(L,b,n,s) (luaL_loadbuffer(L,b,n,s) || lua_pcall(L, 0, LUA_MULTRET, 0))
|
||||
|
||||
@ -60,6 +62,13 @@
|
||||
#define MAX_DIR_ERR 0.1*M_PI/180.
|
||||
#define MIN_VEL_ERR 0.5
|
||||
|
||||
// Ai flags.
|
||||
#define ai_setFlag(f) (pilot_flags |= f)
|
||||
#define ai_isFlag(f) (pilot_flags & f)
|
||||
// Flags.
|
||||
#define AI_PRIMARY (1<<0) // Firing primary weapon.
|
||||
#define AI_SECONDARY (1<<1) // Firing secondary weapon.
|
||||
|
||||
// file info.
|
||||
#define AI_PREFIX "../scripts/ai/"
|
||||
#define AI_SUFFIX ".lua"
|
||||
@ -114,6 +123,7 @@ static int ai_getrndplanet(lua_State* L); // pointer getrndplanet()
|
||||
static int ai_hyperspace(lua_State* L); // [number] hyperspace()
|
||||
// Combat.
|
||||
static int ai_combat(lua_State* L); // combat(number)
|
||||
static int ai_settarget(lua_State* L); // settarget(number)
|
||||
static int ai_shoot(lua_State* L); // shoot(number) number = 1,2,3.
|
||||
static int ai_getenemy(lua_State* L); // number getenemy().
|
||||
static int ai_hostile(lua_State* L); // hostile(number).
|
||||
@ -130,7 +140,8 @@ static int ai_rng(lua_State* L); // rng(number, number)
|
||||
static Pilot* cur_pilot = NULL;
|
||||
static double pilot_acc = 0.;
|
||||
static double pilot_turn = 0.;
|
||||
static int pilot_primary = 0;
|
||||
static int pilot_flags = 0;
|
||||
static int pilot_target = 0;
|
||||
|
||||
// Destroy the AI part of the pilot.
|
||||
void ai_destroy(Pilot* p) {
|
||||
@ -190,47 +201,48 @@ static int ai_loadProfile(char* filename) {
|
||||
|
||||
// Register C funstions in Lua.
|
||||
// Tasks.
|
||||
lua_register(L, "pushtask", ai_pushtask);
|
||||
lua_register(L, "poptask", ai_poptask);
|
||||
lua_register(L, "taskname", ai_taskname);
|
||||
lua_regfunc(L, "pushtask", ai_pushtask);
|
||||
lua_regfunc(L, "poptask", ai_poptask);
|
||||
lua_regfunc(L, "taskname", ai_taskname);
|
||||
// Consult.
|
||||
lua_register(L, "gettarget", ai_gettarget);
|
||||
lua_register(L, "gettargetid", ai_gettargetid);
|
||||
lua_register(L, "armour", ai_armour);
|
||||
lua_register(L, "shield", ai_shield);
|
||||
lua_register(L, "parmour", ai_parmour);
|
||||
lua_register(L, "pshield", ai_pshield);
|
||||
lua_register(L, "getdist", ai_getdistance);
|
||||
lua_register(L, "getpos", ai_getpos);
|
||||
lua_register(L, "minbrakedist", ai_minbrakedist);
|
||||
lua_regfunc(L, "gettarget", ai_gettarget);
|
||||
lua_regfunc(L, "gettargetid", ai_gettargetid);
|
||||
lua_regfunc(L, "armour", ai_armour);
|
||||
lua_regfunc(L, "shield", ai_shield);
|
||||
lua_regfunc(L, "parmour", ai_parmour);
|
||||
lua_regfunc(L, "pshield", ai_pshield);
|
||||
lua_regfunc(L, "getdist", ai_getdistance);
|
||||
lua_regfunc(L, "getpos", ai_getpos);
|
||||
lua_regfunc(L, "minbrakedist", ai_minbrakedist);
|
||||
// Boolean.
|
||||
lua_register(L, "exists", ai_exists);
|
||||
lua_register(L, "ismaxvel", ai_ismaxvel);
|
||||
lua_register(L, "isstopped", ai_isstopped);
|
||||
lua_register(L, "isenemy", ai_isenemy);
|
||||
lua_register(L, "isally", ai_isally);
|
||||
lua_register(L, "incombat", ai_incombat);
|
||||
lua_regfunc(L, "exists", ai_exists);
|
||||
lua_regfunc(L, "ismaxvel", ai_ismaxvel);
|
||||
lua_regfunc(L, "isstopped", ai_isstopped);
|
||||
lua_regfunc(L, "isenemy", ai_isenemy);
|
||||
lua_regfunc(L, "isally", ai_isally);
|
||||
lua_regfunc(L, "incombat", ai_incombat);
|
||||
// Movement.
|
||||
lua_register(L, "accel", ai_accel);
|
||||
lua_register(L, "turn", ai_turn);
|
||||
lua_register(L, "face", ai_face);
|
||||
lua_register(L, "brake", ai_brake);
|
||||
lua_register(L, "getnearestplanet", ai_getnearestplanet);
|
||||
lua_register(L, "getrndplanet", ai_getrndplanet);
|
||||
lua_register(L, "hyperspace", ai_hyperspace);
|
||||
lua_regfunc(L, "accel", ai_accel);
|
||||
lua_regfunc(L, "turn", ai_turn);
|
||||
lua_regfunc(L, "face", ai_face);
|
||||
lua_regfunc(L, "brake", ai_brake);
|
||||
lua_regfunc(L, "getnearestplanet", ai_getnearestplanet);
|
||||
lua_regfunc(L, "getrndplanet", ai_getrndplanet);
|
||||
lua_regfunc(L, "hyperspace", ai_hyperspace);
|
||||
// Combat.
|
||||
lua_register(L, "combat", ai_combat);
|
||||
lua_register(L, "shoot", ai_shoot);
|
||||
lua_register(L, "getenemy", ai_getenemy);
|
||||
lua_register(L, "hostile", ai_hostile);
|
||||
lua_regfunc(L, "combat", ai_combat);
|
||||
lua_regfunc(L, "settarget", ai_settarget);
|
||||
lua_regfunc(L, "shoot", ai_shoot);
|
||||
lua_regfunc(L, "getenemy", ai_getenemy);
|
||||
lua_regfunc(L, "hostile", ai_hostile);
|
||||
// Timers.
|
||||
lua_register(L, "settimer", ai_settimer);
|
||||
lua_register(L, "timeup", ai_timeup);
|
||||
lua_regfunc(L, "settimer", ai_settimer);
|
||||
lua_regfunc(L, "timeup", ai_timeup);
|
||||
// Misc.
|
||||
lua_register(L, "createvect", ai_createvect);
|
||||
lua_register(L, "comm", ai_comm);
|
||||
lua_register(L, "broadcast", ai_broadcast);
|
||||
lua_register(L, "rng", ai_rng);
|
||||
lua_regfunc(L, "createvect", ai_createvect);
|
||||
lua_regfunc(L, "comm", ai_comm);
|
||||
lua_regfunc(L, "broadcast", ai_broadcast);
|
||||
lua_regfunc(L, "rng", ai_rng);
|
||||
|
||||
|
||||
// Now load the file, since all the functions have been previously loaded.
|
||||
@ -277,7 +289,8 @@ void ai_think(Pilot* pilot) {
|
||||
|
||||
// Clean up some variables.
|
||||
pilot_acc = pilot_turn = 0.;
|
||||
pilot_primary = 0;
|
||||
pilot_flags = 0;
|
||||
pilot_target = 0;
|
||||
|
||||
// Control function if pilot is idle or tick is up.
|
||||
if((cur_pilot->tcontrol < SDL_GetTicks()) || (cur_pilot->task == NULL)) {
|
||||
@ -299,7 +312,9 @@ void ai_think(Pilot* pilot) {
|
||||
cur_pilot->solid->dir_vel -= cur_pilot->ship->turn * pilot_turn;
|
||||
vect_pset(&cur_pilot->solid->force, cur_pilot->ship->thrust * pilot_acc, cur_pilot->solid->dir);
|
||||
|
||||
if(pilot_primary) pilot_shoot(pilot, 0); // AMG, he's gunna shoot!
|
||||
// Fire weapons if needs be.
|
||||
if(ai_isFlag(AI_PRIMARY)) pilot_shoot(pilot, pilot_target, 0); // Primary.
|
||||
if(ai_isFlag(AI_SECONDARY)) pilot_shoot(pilot, pilot_target, 1); // Secondary.
|
||||
}
|
||||
|
||||
// Pilot is attacked.
|
||||
@ -676,14 +691,22 @@ static int ai_combat(lua_State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Set the pilots target.
|
||||
static int ai_settarget(lua_State* L) {
|
||||
MIN_ARGS(1);
|
||||
|
||||
if(lua_isnumber(L,1)) pilot_target = (int)lua_tonumber(L,1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Pew pew.. Says the pilot.
|
||||
static int ai_shoot(lua_State* L) {
|
||||
int n = 1;
|
||||
if(lua_isnumber(L, 1)) n = (int)lua_tonumber(L,1);
|
||||
|
||||
if(n == 1) pilot_primary = 1;
|
||||
//else if(n == 2) pilot_secondary = 1;
|
||||
//else if(n == 3) pilot_primary = pilot_secondary = 1;
|
||||
if(n == 1) ai_setFlag(AI_PRIMARY);
|
||||
else if(n == 2) ai_setFlag(AI_SECONDARY);
|
||||
else if(n == 3) ai_setFlag(AI_PRIMARY | AI_SECONDARY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
90
src/outfit.c
90
src/outfit.c
@ -7,6 +7,8 @@
|
||||
#include "xml.h"
|
||||
#include "outfit.h"
|
||||
|
||||
#define outfit_setProp(o,p) ((o)->properties |= p)
|
||||
|
||||
#define XML_OUTFIT_ID "Outfits"
|
||||
#define XML_OUTFIT_TAG "outfit"
|
||||
|
||||
@ -18,6 +20,8 @@ static int outfits = 0;
|
||||
|
||||
static Outfit* outfit_parse(const xmlNodePtr parent);
|
||||
static void outfit_parseSWeapon(Outfit* tmp, const xmlNodePtr parent);
|
||||
static void outfit_parseSLauncher(Outfit* tmp, const xmlNodePtr parent);
|
||||
static void outfit_parseSAmmo(Outfit* tmp, const xmlNodePtr parent);
|
||||
|
||||
// Return an outfit.
|
||||
Outfit* outfit_get(const char* name) {
|
||||
@ -98,7 +102,8 @@ static void outfit_parseSWeapon(Outfit* tmp, const xmlNodePtr parent) {
|
||||
}
|
||||
} while((node = node->next));
|
||||
#define MELEMENT(o,s) if((o) == 0) WARN("Outfit '%s' missing '"s"' element", tmp->name)
|
||||
MELEMENT(tmp->accuracy, "tech");
|
||||
if(tmp->gfx_space == NULL)
|
||||
WARN("Outfit '%s' missing 'gfx' element", tmp->name);
|
||||
MELEMENT(tmp->delay, "delay");
|
||||
MELEMENT(tmp->speed, "speed");
|
||||
MELEMENT(tmp->range, "range");
|
||||
@ -108,6 +113,60 @@ static void outfit_parseSWeapon(Outfit* tmp, const xmlNodePtr parent) {
|
||||
#undef MELEMENT
|
||||
}
|
||||
|
||||
// Parse the specific area for a launcher and loads it into Outfit.
|
||||
static void outfit_parseSLauncher(Outfit* tmp, const xmlNodePtr parent) {
|
||||
xmlNodePtr node;
|
||||
node = parent->xmlChildrenNode;
|
||||
|
||||
do {
|
||||
// Load the dataz.
|
||||
if(xml_isNode(node, "delay")) tmp->delay = xml_getInt(node);
|
||||
else if(xml_isNode(node, "ammo")) tmp->ammo = strdup(xml_get(node));
|
||||
} while((node = node->next));
|
||||
|
||||
#define MELEMENT(o,s) if((o) == 0) WARN("Outfit '%s' missing '"s"' element", tmp->name)
|
||||
if(tmp->ammo == NULL) WARN("Outfit '%s' missing 'ammo' element", tmp->name);
|
||||
MELEMENT(tmp->delay, "delay");
|
||||
#undef MELEMENT
|
||||
}
|
||||
|
||||
// Parse the specific area for a weapon and load it into Outfit.
|
||||
static void outfit_parseSAmmo(Outfit* tmp, const xmlNodePtr parent) {
|
||||
xmlNodePtr cur, node;
|
||||
node = parent->xmlChildrenNode;
|
||||
|
||||
char str[PATH_MAX] = "\0";
|
||||
|
||||
do {
|
||||
if(xml_isNode(node, "thrust")) tmp->thrust = xml_getFloat(node);
|
||||
else if(xml_isNode(node, "turn")) tmp->turn = xml_getFloat(node);
|
||||
else if(xml_isNode(node, "speed")) tmp->speed = xml_getFloat(node);
|
||||
else if(xml_isNode(node, "duration")) tmp->duration = 1000*(unsigned int)xml_getFloat(node);
|
||||
else if(xml_isNode(node, "gfx")) {
|
||||
snprintf(str, strlen(xml_get(node))+sizeof(OUTFIT_GFX)+4,
|
||||
OUTFIT_GFX"%s.png", xml_get(node));
|
||||
tmp->gfx_space = gl_newSprite(str, 6, 6);
|
||||
}
|
||||
else if(xml_isNode(node, "damage")) {
|
||||
cur = node->children;
|
||||
do {
|
||||
if(xml_isNode(cur, "armour")) tmp->damage_armour = xml_getFloat(cur);
|
||||
else if(xml_isNode(cur, "shield")) tmp->damage_shield = xml_getFloat(cur);
|
||||
} while((cur = cur->next));
|
||||
}
|
||||
} while((node = node->next));
|
||||
#define MELEMENT(o,s) if((o) == 0) WARN("Outfit '%s' missing '"s"' element", tmp->name)
|
||||
if(tmp->gfx_space == NULL)
|
||||
WARN("Outfit '%s' missing 'gfx' element", tmp->name);
|
||||
MELEMENT(tmp->thrust, " thrust");
|
||||
MELEMENT(tmp->turn, "turn");
|
||||
MELEMENT(tmp->speed, "speed");
|
||||
MELEMENT(tmp->range, "duration");
|
||||
MELEMENT(tmp->damage_armour, "armour' from element 'damage");
|
||||
MELEMENT(tmp->damage_shield, "shield' from element 'damage");
|
||||
#undef MELEMENT
|
||||
}
|
||||
|
||||
// Parse and return Outfits from parent node.
|
||||
static Outfit* outfit_parse(const xmlNodePtr parent) {
|
||||
Outfit* tmp = CALLOC_L(Outfit);
|
||||
@ -130,21 +189,28 @@ static Outfit* outfit_parse(const xmlNodePtr parent) {
|
||||
}
|
||||
else if(xml_isNode(node, "specific")) {
|
||||
// Has to be processed seperately.
|
||||
|
||||
// Get the type.
|
||||
prop = xml_nodeProp(node, "type");
|
||||
if(prop == NULL)
|
||||
ERR("Outfit '%s' element 'specific' missing property 'type'", tmp->name);
|
||||
tmp->type = atoi(prop);
|
||||
free(prop);
|
||||
switch(tmp->type) {
|
||||
case OUTFIT_TYPE_NULL:
|
||||
WARN("Outfit '%s' is of type NONE", tmp->name);
|
||||
break;
|
||||
case OUTFIT_TYPE_BOLT:
|
||||
outfit_parseSWeapon(tmp, node);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
// Is this the secondary weapon?
|
||||
prop = xml_nodeProp(node, "secondary");
|
||||
if(prop != NULL) {
|
||||
if((int)atoi(prop)) outfit_setProp(tmp, OUTFIT_PROP_WEAP_SECONDARY);
|
||||
free(prop);
|
||||
}
|
||||
if(tmp->type == OUTFIT_TYPE_NULL)
|
||||
WARN("Outfit '%s' is of type NONE", tmp->name);
|
||||
else if(outfit_isWeapon(tmp))
|
||||
outfit_parseSWeapon(tmp, node);
|
||||
else if(outfit_isLauncher(tmp))
|
||||
outfit_parseSLauncher(tmp, node);
|
||||
else if(outfit_isAmmo(tmp))
|
||||
outfit_parseSAmmo(tmp, node);
|
||||
}
|
||||
} while((node = node->next));
|
||||
#define MELEMENT(o,s) if((o) == 0) WARN("Outfit '%s' missing '"s"' element", tmp->name)
|
||||
@ -202,6 +268,10 @@ void outfit_free(void) {
|
||||
for(i = 0; i < outfits; i++) {
|
||||
if(outfit_isWeapon(&outfit_stack[i]) && outfit_stack[i].gfx_space)
|
||||
gl_freeTexture(outfit_stack[i].gfx_space);
|
||||
|
||||
if(outfit_isLauncher(&outfit_stack[i]) && outfit_stack[i].ammo)
|
||||
free(outfit_stack[i].ammo);
|
||||
|
||||
free(outfit_stack[i].name);
|
||||
}
|
||||
free(outfit_stack);
|
||||
|
13
src/outfit.h
13
src/outfit.h
@ -1,8 +1,9 @@
|
||||
#pragma once
|
||||
#include "opengl.h"
|
||||
|
||||
#define OUTFIT_PROP_WEAP_PRIMARY (1<<0)
|
||||
#define OUTFIT_PROP_WEAP_SECONDARY (1<<1)
|
||||
#define outfit_isProp(o,p) ((o)->properties & p)
|
||||
// Property flags.
|
||||
#define OUTFIT_PROP_WEAP_SECONDARY (1<<0)
|
||||
|
||||
// Outfit types.
|
||||
typedef enum {
|
||||
@ -48,12 +49,14 @@ typedef struct {
|
||||
};
|
||||
struct { // Launcher.
|
||||
//unsigned int delay; // Delay between shots.
|
||||
char* ammo;
|
||||
};
|
||||
struct { // Ammo.
|
||||
//double speed; // Max speed.
|
||||
//double turn; // Turn vel.
|
||||
//double thrust; // Acceleration.
|
||||
//double damage_armour, damage_shield;
|
||||
double turn; // Turn vel.
|
||||
double thrust; // Acceleration.
|
||||
unsigned int duration; // Duration.
|
||||
//double damage_armour, damage_shield; // Damage.
|
||||
|
||||
//gl_texture* gfx_space;
|
||||
};
|
||||
|
50
src/pilot.c
50
src/pilot.c
@ -64,7 +64,7 @@ unsigned int pilot_getNearest(const Pilot* p) {
|
||||
for(tp = 0, d = 0., i = 0; i < pilots; i++)
|
||||
if(areEnemies(p->faction, pilot_stack[i]->faction)) {
|
||||
td = vect_dist(&pilot_stack[i]->solid->pos, &p->solid->pos);
|
||||
if((!tp) || (td < d)) {
|
||||
if(!pilot_isDisabled(pilot_stack[i]) && ((!tp) || (td < d))) {
|
||||
d = td;
|
||||
tp = pilot_stack[i]->id;
|
||||
}
|
||||
@ -106,27 +106,40 @@ Pilot* pilot_get(const unsigned int id) {
|
||||
}
|
||||
|
||||
// Mkay, this is how we shoot. Listen up.
|
||||
void pilot_shoot(Pilot* p, const int secondary) {
|
||||
void pilot_shoot(Pilot* p, const unsigned int target, const int secondary) {
|
||||
int i;
|
||||
if(!secondary) {
|
||||
// Primary weapons.
|
||||
if(!p->outfits) return; // No outfits.
|
||||
|
||||
for(i = 0; i < p->noutfits; i++) // Cycle through outfits to find weapons.
|
||||
if(outfit_isWeapon(p->outfits[i].outfit) || // Is a weapon or launch?
|
||||
outfit_isLauncher(p->outfits[i].outfit))
|
||||
if(outfit_isWeapon(p->outfits[i].outfit)) // Are we a weapon?
|
||||
// Ready to shoot again.
|
||||
if((SDL_GetTicks()-p->outfits[i].timer) > (p->outfits[i].outfit->delay/p->outfits[i].quantity))
|
||||
// Different weapons have different behaviours.
|
||||
switch(p->outfits[i].outfit->type) {
|
||||
case OUTFIT_TYPE_BOLT:
|
||||
weapon_add(p->outfits[i].outfit, p->solid->dir, &p->solid->pos,
|
||||
&p->solid->vel, p->id, (p==player) ? WEAPON_LAYER_FG : WEAPON_LAYER_BG);
|
||||
p->outfits[i].timer = SDL_GetTicks();
|
||||
&p->solid->vel, p->id, target, (p==player) ? WEAPON_LAYER_FG : WEAPON_LAYER_BG);
|
||||
p->outfits[i].timer = SDL_GetTicks(); // Let's not try this again for a while.
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if(!p->secondary) return; // No secondary weapon.
|
||||
|
||||
if(outfit_isLauncher(p->secondary->outfit)) {
|
||||
if(((SDL_GetTicks()-p->secondary->timer) >
|
||||
(p->secondary->outfit->delay/p->secondary->quantity)) &&
|
||||
p->ammo && (p->ammo->quantity > 0)) {
|
||||
weapon_add(p->ammo->outfit, p->solid->dir, &p->solid->pos, &p->solid->vel,
|
||||
p->id, target, (p==player) ? WEAPON_LAYER_FG : WEAPON_LAYER_BG);
|
||||
|
||||
p->secondary->timer = SDL_GetTicks(); // Let's not try this again for a while.
|
||||
p->ammo->quantity -= 1; // No getting this one back.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -145,6 +158,27 @@ void pilot_hit(Pilot* p, const double damage_shield, const double damage_armour)
|
||||
p->armour = 0.;
|
||||
}
|
||||
|
||||
// Set the pilot's ammo based on their secondary weapon.
|
||||
void pilot_setAmmo(Pilot* p) {
|
||||
int i;
|
||||
char* name;
|
||||
|
||||
if((p->secondary == NULL) || !outfit_isLauncher(p->secondary->outfit)) {
|
||||
p->ammo = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
name = p->secondary->outfit->ammo;
|
||||
|
||||
for(i = 0; i < p->noutfits; i++)
|
||||
if(strcmp(p->outfits[i].outfit->name, name)==0) {
|
||||
p->ammo = p->outfits + i;
|
||||
return;
|
||||
}
|
||||
|
||||
p->ammo = NULL;
|
||||
}
|
||||
|
||||
// Render the pilot.
|
||||
void pilot_render(Pilot* p) {
|
||||
int sx, sy;
|
||||
@ -231,6 +265,8 @@ void pilot_init(Pilot* pilot, Ship* ship, char* name, Faction* faction, AI_Profi
|
||||
|
||||
// Outfits.
|
||||
pilot->outfits = NULL;
|
||||
pilot->secondary = NULL;
|
||||
pilot->ammo = NULL;
|
||||
ShipOutfit* so;
|
||||
if(ship->outfit) {
|
||||
pilot->noutfits = 0;
|
||||
@ -316,7 +352,7 @@ void pilots_free(void) {
|
||||
void pilots_update(double dt) {
|
||||
int i;
|
||||
for(i = 0; i < pilots; i++) {
|
||||
if(pilot_stack[i]->think && !pilot_isFlag(pilot_stack[i], PILOT_DISABLED))
|
||||
if(pilot_stack[i]->think && !pilot_isDisabled(pilot_stack[i]))
|
||||
pilot_stack[i]->think(pilot_stack[i]);
|
||||
if(pilot_stack[i]->update)
|
||||
pilot_stack[i]->update(pilot_stack[i], dt);
|
||||
|
@ -25,6 +25,7 @@
|
||||
#define PILOT_DISABLED (1<<4) // Pilot is disabled.
|
||||
// Just makes life simpler.
|
||||
#define pilot_isPlayer(p) ((p)->flags & PILOT_PLAYER)
|
||||
#define pilot_isDisabled(p) ((p)->flags & PILOT_DISABLED)
|
||||
|
||||
typedef struct {
|
||||
Outfit* outfit; // Associated outfit.
|
||||
@ -54,6 +55,8 @@ typedef struct Pilot {
|
||||
// Outfit management.
|
||||
PilotOutfit* outfits;
|
||||
int noutfits;
|
||||
PilotOutfit* secondary; // Secondary weapon.
|
||||
PilotOutfit* ammo; // Secondary ammo (if needed).
|
||||
|
||||
unsigned int flags; // Used for AI etc.
|
||||
|
||||
@ -90,8 +93,9 @@ unsigned int pilot_getHostile(void); // Only for the player.
|
||||
Fleet* fleet_get(const char* name);
|
||||
|
||||
// MISC.
|
||||
void pilot_shoot(Pilot* p, const int secondary);
|
||||
void pilot_shoot(Pilot* p, const unsigned int target, const int secondary);
|
||||
void pilot_hit(Pilot* p, const double damage_shield, const double damage_armour);
|
||||
void pilot_setAmmo(Pilot* p);
|
||||
|
||||
// Creation.
|
||||
void pilot_init(Pilot* dest, Ship* ship, char* name, Faction* faction, AI_Profile* ai,
|
||||
|
86
src/player.c
86
src/player.c
@ -26,6 +26,8 @@
|
||||
#define PLAYER_TURN_LEFT (1<<0) // Player is turning left.
|
||||
#define PLAYER_TURN_RIGHT (1<<1) // Player is turning right.
|
||||
#define PLAYER_FACE (1<<2) // Player is facing target.
|
||||
#define PLAYER_PRIMARY (1<<3) // Player is shooting primary weapon.
|
||||
#define PLAYER_SECONDARY (1<<4) // Player is shooting secondary weapon.
|
||||
|
||||
// Flag functions.
|
||||
#define player_isFlag(f) (player_flags & f)
|
||||
@ -46,19 +48,17 @@ static Keybind** player_input; // Contains the players keybindings.
|
||||
// Name of each keybinding.
|
||||
const char* keybindNames[] = { "accel", "left", "right", // Movement.
|
||||
"primary", "target", "target_nearest", "face", "board", // Combat.
|
||||
"secondary", "secondary_next", // Secondary weapons.
|
||||
"mapzoomin", "mapzoomout", "screenshot", "end" }; // Misc.
|
||||
|
||||
// Player stuff.
|
||||
Pilot* player = NULL; // extern in pilot.h
|
||||
unsigned int credits = 0;
|
||||
static int player_flags = 0; // Player flags.
|
||||
static unsigned int player_flags = 0; // Player flags.
|
||||
static double player_turn = 0.; // Turn velocity from input.
|
||||
static double player_acc = 0.; // Accel velocity from input.
|
||||
static int player_primary = 0; // Player is shooting primary weapon.
|
||||
//static int player_secondary = 0; // layer is shooting secondary weapon.
|
||||
static unsigned int player_target = PLAYER_ID; // Targetted pilot.
|
||||
static int planet_target = -1; // Targetted planet.
|
||||
static int weapon = -1; // Secondary weapon is in use.
|
||||
|
||||
// Pilot stuff for GUI.
|
||||
extern Pilot** pilot_stack;
|
||||
@ -148,6 +148,7 @@ static void gui_renderBar(const glColour* c, const Vec2* p, const Rect* r, const
|
||||
|
||||
// Keybinds.
|
||||
static void player_board(void);
|
||||
static void player_secondaryNext(void);
|
||||
static void player_screenshot(void);
|
||||
|
||||
// Create a new player.
|
||||
@ -254,7 +255,7 @@ void player_render(void) {
|
||||
if(player_target != PLAYER_ID) {
|
||||
p = pilot_get(player_target);
|
||||
|
||||
if(pilot_isFlag(p, PILOT_DISABLED)) c = &cInert;
|
||||
if(pilot_isDisabled(p)) c = &cInert;
|
||||
else if(pilot_isFlag(p, PILOT_HOSTILE)) c = &cHostile;
|
||||
else c = &cNeutral;
|
||||
|
||||
@ -340,7 +341,7 @@ void player_render(void) {
|
||||
gui_renderBar(&cEnergy, &gui.pos_energy, &gui.energy, player->energy / player->energy_max);
|
||||
|
||||
// Weapon.
|
||||
if(weapon == -1) {
|
||||
if(player->secondary == NULL) {
|
||||
i = gl_printWidth(NULL, "Secondary");
|
||||
vect_csetmin(&v, VX(gui.pos_weapon) + (gui.weapon.w - i)/2., VY(gui.pos_weapon) - 5);
|
||||
gl_print(NULL, &v, &cConsole, "Secondary");
|
||||
@ -348,7 +349,21 @@ void player_render(void) {
|
||||
vect_csetmin(&v, VX(gui.pos_weapon) + (gui.weapon.w - i)/2., VY(gui.pos_weapon) - 10 - gl_defFont.h);
|
||||
gl_print(&gui.smallFont, &v, &cGrey, "None");
|
||||
} else {
|
||||
|
||||
if(player->ammo == NULL) {
|
||||
i = gl_printWidth(&gui.smallFont, "%s", player->secondary->outfit->name);
|
||||
vect_csetmin(&v, VX(gui.pos_weapon) + (gui.weapon.w - i)/2.,
|
||||
VY(gui.pos_weapon) - (gui.weapon.h - gui.smallFont.h)/2.);
|
||||
gl_print(&gui.smallFont, &v, &cConsole, "%s", player->secondary->outfit->name);
|
||||
} else {
|
||||
i = gl_printWidth(&gui.smallFont, "%s", player->secondary->outfit->name);
|
||||
vect_csetmin(&v, VX(gui.pos_weapon) + (gui.weapon.w - i)/2.,
|
||||
VY(gui.pos_weapon) - 5);
|
||||
gl_print(&gui.smallFont, &v, NULL, "%s", player->ammo->outfit->name);
|
||||
i = gl_printWidth(NULL, "%d", player->ammo->quantity);
|
||||
vect_csetmin(&v, VX(gui.pos_weapon) + (gui.weapon.w - i)/2.,
|
||||
VY(gui.pos_weapon) - 10 - gl_defFont.h);
|
||||
gl_print(NULL, &v, &cConsole, "%d", player->ammo->quantity);
|
||||
}
|
||||
}
|
||||
|
||||
// Target.
|
||||
@ -362,7 +377,7 @@ void player_render(void) {
|
||||
gl_print(&gui.smallFont, &gui.pos_target_faction, NULL, "%s", p->faction->name);
|
||||
|
||||
// Target status.
|
||||
if(pilot_isFlag(p, PILOT_DISABLED))
|
||||
if(pilot_isDisabled(p))
|
||||
// Disable the pilot.
|
||||
gl_print(&gui.smallFont, &gui.pos_target_health, NULL, "Disabled");
|
||||
else if(p->shield > p->shield_max / 100.)
|
||||
@ -433,7 +448,7 @@ static void gui_renderPilot(const Pilot* p) {
|
||||
glBegin(GL_QUADS);
|
||||
// Colours.
|
||||
if(p->id == player_target) COLOUR(cRadar_targ);
|
||||
else if(pilot_isFlag(p, PILOT_DISABLED)) COLOUR(cInert);
|
||||
else if(pilot_isDisabled(p)) COLOUR(cInert);
|
||||
else if(pilot_isFlag(p, PILOT_HOSTILE)) COLOUR(cHostile);
|
||||
else COLOUR(cNeutral);
|
||||
|
||||
@ -750,7 +765,9 @@ void player_think(Pilot* player) {
|
||||
if(player_turn)
|
||||
player->solid->dir_vel -= player->ship->turn * player_turn;
|
||||
|
||||
if(player_primary) pilot_shoot(player, 0);
|
||||
if(player_isFlag(PLAYER_PRIMARY)) pilot_shoot(player, 0, 0);
|
||||
if(player_isFlag(PLAYER_SECONDARY) && (player_target != PLAYER_ID)) // Needs a target.
|
||||
pilot_shoot(player, player_target, 1);
|
||||
|
||||
vect_pset(&player->solid->force, player->ship->thrust * player_acc, player->solid->dir);
|
||||
}
|
||||
@ -764,7 +781,7 @@ void player_board(void) {
|
||||
}
|
||||
p = pilot_get(player_target);
|
||||
|
||||
if(!pilot_isFlag(p, PILOT_DISABLED)) {
|
||||
if(!pilot_isDisabled(p)) {
|
||||
player_message("You cannot board a ship that isn't disabled!");
|
||||
return;
|
||||
}
|
||||
@ -778,7 +795,32 @@ void player_board(void) {
|
||||
player_message("You are going too fact to board the ship");
|
||||
return;
|
||||
}
|
||||
player_message("Ship boarding isn't implemented yet! HAHA");
|
||||
player_message("It's a shame Allanis hasn't added boarding yet, right?!");
|
||||
}
|
||||
|
||||
// Get the next secondary weapon.
|
||||
static void player_secondaryNext(void) {
|
||||
int i = 0;
|
||||
|
||||
// Get the current secondary weapon pos.
|
||||
if(player->secondary != NULL)
|
||||
for(i = 0; i < player->noutfits; i++)
|
||||
if(&player->outfits[i] == player->secondary) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
// 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;
|
||||
break;
|
||||
}
|
||||
// We didn't find an outfit.
|
||||
if(i >= player->noutfits)
|
||||
player->secondary = NULL;
|
||||
|
||||
// Set ammo.
|
||||
pilot_setAmmo(player);
|
||||
}
|
||||
|
||||
// Take a screenshot.
|
||||
@ -803,6 +845,8 @@ void input_setDefault(void) {
|
||||
input_setKeybind("target_nearest", KEYBIND_KEYBOARD, SDLK_r, 0);
|
||||
input_setKeybind("face", KEYBIND_KEYBOARD, SDLK_f, 0);
|
||||
input_setKeybind("board", KEYBIND_KEYBOARD, SDLK_b, 0);
|
||||
input_setKeybind("secondary", KEYBIND_KEYBOARD, SDLK_LSHIFT, 0);
|
||||
input_setKeybind("secondary_next", KEYBIND_KEYBOARD, SDLK_q, 0);
|
||||
input_setKeybind("mapzoomin", KEYBIND_KEYBOARD, SDLK_UP, 0);
|
||||
input_setKeybind("mapzoomout", KEYBIND_KEYBOARD, SDLK_DOWN, 0);
|
||||
input_setKeybind("screenshot", KEYBIND_KEYBOARD, SDLK_F12, 0);
|
||||
@ -881,8 +925,8 @@ static void input_key(int keynum, double value, int abs) {
|
||||
}
|
||||
// Shoot primary weapon. BOOM BOOM.
|
||||
else if(strcmp(player_input[keynum]->name, "primary")==0) {
|
||||
if(value == KEY_PRESS) player_primary = 1;
|
||||
else if(value == KEY_RELEASE) player_primary = 0;
|
||||
if(value == KEY_PRESS) player_setFlag(PLAYER_PRIMARY);
|
||||
else if(value == KEY_RELEASE) player_rmFlag(PLAYER_PRIMARY);
|
||||
}
|
||||
// Targetting.
|
||||
else if(strcmp(player_input[keynum]->name, "target")==0) {
|
||||
@ -907,16 +951,26 @@ static void input_key(int keynum, double value, int abs) {
|
||||
else if(strcmp(player_input[keynum]->name, "board")==0) {
|
||||
if(value == KEY_PRESS) player_board();
|
||||
}
|
||||
// Shooting secondary weapon.
|
||||
else if(strcmp(player_input[keynum]->name, "secondary")==0) {
|
||||
if(value == KEY_PRESS) player_setFlag(PLAYER_SECONDARY);
|
||||
else if(value == KEY_RELEASE) player_rmFlag(PLAYER_SECONDARY);
|
||||
}
|
||||
// Selecting secondary weapon.
|
||||
else if(strcmp(player_input[keynum]->name, "secondary_next")==0) {
|
||||
if(value == KEY_PRESS) player_secondaryNext();
|
||||
}
|
||||
// Zoom in.
|
||||
else if(strcmp(player_input[keynum]->name, "mapzoomin")==0) {
|
||||
if(value == KEY_PRESS && gui.radar.res < RADAR_RES_MAX)
|
||||
if((value == KEY_PRESS) && (gui.radar.res < RADAR_RES_MAX))
|
||||
gui.radar.res += RADAR_RES_INTERVAL;
|
||||
}
|
||||
// Zoom out.
|
||||
else if(strcmp(player_input[keynum]->name, "mapzoomout")==0) {
|
||||
if(value == KEY_PRESS && gui.radar.res > RADAR_RES_MIN)
|
||||
if((value == KEY_PRESS) && (gui.radar.res > RADAR_RES_MIN))
|
||||
gui.radar.res -= RADAR_RES_INTERVAL;
|
||||
}
|
||||
// Take a screenshot.
|
||||
else if(strcmp(player_input[keynum]->name, "screenshot")==0) {
|
||||
if(value == KEY_PRESS) player_screenshot();
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ static Ship* ship_parse(xmlNodePtr parent) {
|
||||
|
||||
if((ocur = tmp->outfit) == NULL) tmp->outfit = otmp;
|
||||
else {
|
||||
while(ocur->next);
|
||||
while(ocur->next) ocur = ocur->next;
|
||||
ocur->next = otmp;
|
||||
}
|
||||
}
|
||||
|
92
src/weapon.c
92
src/weapon.c
@ -12,6 +12,8 @@
|
||||
#include "player.h"
|
||||
#include "weapon.h"
|
||||
|
||||
#define weapon_isSmart(w) (w->think)
|
||||
|
||||
// Some stuff from pilot.
|
||||
extern Pilot** pilot_stack;
|
||||
extern int pilots;
|
||||
@ -23,6 +25,7 @@ typedef struct Weapon {
|
||||
Solid* solid; // Actually has its own solid. :D
|
||||
|
||||
unsigned int parent; // The pilot that just shot at you!
|
||||
unsigned int target; // Target to hit. Only used by seeking stuff.
|
||||
const Outfit* outfit; // Related outfit that fired.
|
||||
unsigned int timer; // Mainly used to see when the weapon was fired.
|
||||
|
||||
@ -42,12 +45,16 @@ static int mwfrontLayer = 0; // Allocated memory size.
|
||||
|
||||
|
||||
static Weapon* weapon_create(const Outfit* outfit, const double dir,
|
||||
const Vec2* pos, const Vec2* vel, unsigned int parent);
|
||||
const Vec2* pos, const Vec2* vel, const unsigned int parent,
|
||||
const unsigned int target);
|
||||
|
||||
static void weapon_render(const Weapon* w);
|
||||
static void weapon_update(Weapon* w, const double dt, WeaponLayer layer);
|
||||
static void weapon_hit(Weapon* w, Pilot* p, WeaponLayer layer);
|
||||
static void weapon_destroy(Weapon* w, WeaponLayer layer);
|
||||
static void weapon_free(Weapon* w);
|
||||
// Think.
|
||||
static void think_seeker(Weapon* w);
|
||||
|
||||
// Draw the minimap weapons (player.c).
|
||||
#define PIXEL(x,y) if((shape == RADAR_RECT && ABS(x) < w/2. && ABS(y)<h/2.) || \
|
||||
@ -72,6 +79,25 @@ void weapon_minimap(const double res, const double w, const double h, const Rada
|
||||
}
|
||||
#undef PIXEL
|
||||
|
||||
static void think_seeker(Weapon* w) {
|
||||
if(w->target == w->parent) return; // HEY! Self harm is not allowed.
|
||||
|
||||
Pilot* p = pilot_get(w->target);
|
||||
if(p == NULL) return; // Can't do anything with no pilots.
|
||||
|
||||
double diff = angle_diff(w->solid->dir, vect_angle(&w->solid->pos, &p->solid->pos));
|
||||
w->solid->dir_vel = 10 * diff * w->outfit->turn;
|
||||
// Face the target.
|
||||
if(w->solid->dir_vel > w->outfit->turn) w->solid->dir_vel = w->outfit->turn;
|
||||
else if(w->solid->dir_vel < -w->outfit->turn) w->solid->dir_vel = -w->outfit->turn;
|
||||
|
||||
vect_pset(&w->solid->force, w->outfit->thrust, w->solid->dir);
|
||||
|
||||
if(VMOD(w->solid->vel) > w->outfit->speed)
|
||||
// We should not go any faster.
|
||||
vect_pset(&w->solid->vel, w->outfit->speed, VANGLE(w->solid->vel));
|
||||
}
|
||||
|
||||
// Update all weapons in the layer.
|
||||
void weapons_update(const double dt, WeaponLayer layer) {
|
||||
Weapon** wlayer;
|
||||
@ -92,15 +118,20 @@ void weapons_update(const double dt, WeaponLayer layer) {
|
||||
for(i = 0; i < (*nlayer); i++) {
|
||||
w = wlayer[i];
|
||||
switch(wlayer[i]->outfit->type) {
|
||||
case OUTFIT_TYPE_BOLT:
|
||||
case OUTFIT_TYPE_MISSILE_SEEK_AMMO:
|
||||
if(SDL_GetTicks() > (wlayer[i]->timer + wlayer[i]->outfit->duration)) {
|
||||
weapon_destroy(wlayer[i], layer);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Check see if it exceeds distance.
|
||||
if(SDL_GetTicks() > (wlayer[i]->timer + 1000*(unsigned int)
|
||||
wlayer[i]->outfit->range/wlayer[i]->outfit->speed)) {
|
||||
weapon_destroy(wlayer[i],layer);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
weapon_update(wlayer[i], dt, layer);
|
||||
// If the weapon has been deleted we are going to have to hold back one.
|
||||
@ -126,38 +157,51 @@ static void weapon_update(Weapon* w, const double dt, WeaponLayer layer) {
|
||||
for(i = 0; i < pilots; i++) {
|
||||
gl_getSpriteFromDir(&psx, &psy, pilot_stack[i]->ship->gfx_space,
|
||||
pilot_stack[i]->solid->dir);
|
||||
if(w->parent == pilot_stack[i]->id) continue; // Hey! That's you.
|
||||
|
||||
if((w->parent != pilot_stack[i]->id) && // The pilot hasn't shoot it.
|
||||
if((weapon_isSmart(w)) && (pilot_stack[i]->id == w->target) &&
|
||||
CollideSprite(w->outfit->gfx_space, wsx, wsy, &w->solid->pos,
|
||||
pilot_stack[i]->ship->gfx_space, psx, psy, &pilot_stack[i]->solid->pos)) {
|
||||
weapon_hit(w, pilot_stack[i], layer);
|
||||
return;
|
||||
}
|
||||
else if(!weapon_isSmart(w) &&
|
||||
!areAllies(pilot_get(w->parent)->faction, pilot_stack[i]->faction) &&
|
||||
CollideSprite(w->outfit->gfx_space, wsx, wsy, &w->solid->pos,
|
||||
pilot_stack[i]->ship->gfx_space, psx, psy, &pilot_stack[i]->solid->pos)) {
|
||||
|
||||
if(!pilot_isPlayer(pilot_stack[i]))
|
||||
// Inform the ai it has been attacked. Useless if we are player.
|
||||
ai_attacked(pilot_stack[i], w->parent);
|
||||
if(w->parent == PLAYER_ID) // Make hostile to player.
|
||||
pilot_setFlag(pilot_stack[i], PILOT_HOSTILE);
|
||||
|
||||
// Inform the ship that it should take some damage.
|
||||
pilot_hit(pilot_stack[i], w->outfit->damage_shield, w->outfit->damage_armour);
|
||||
// No need for the weapon particle anymore.
|
||||
weapon_destroy(w, layer);
|
||||
weapon_hit(w, pilot_stack[i], layer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(w->think) (*w->think)(w);
|
||||
if(weapon_isSmart(w)) (*w->think)(w);
|
||||
(*w->solid->update)(w->solid, dt);
|
||||
|
||||
weapon_render(w);
|
||||
}
|
||||
|
||||
// Good shot.
|
||||
static void weapon_hit(Weapon* w, Pilot* p, WeaponLayer layer) {
|
||||
// Someone should let the ai know it's been attacked.
|
||||
if(!pilot_isPlayer(p))
|
||||
ai_attacked(p, w->parent);
|
||||
if(w->parent == PLAYER_ID)
|
||||
// Make hostile to player.
|
||||
pilot_setFlag(p, PILOT_HOSTILE);
|
||||
|
||||
// Let the ship know that is should take some kind of damage.
|
||||
pilot_hit(p, w->outfit->damage_shield, w->outfit->damage_armour);
|
||||
// We don't need the weapon particle any longer.
|
||||
weapon_destroy(w, layer);
|
||||
}
|
||||
|
||||
static Weapon* weapon_create(const Outfit* outfit, const double dir, const Vec2* pos,
|
||||
const Vec2* vel, unsigned int parent) {
|
||||
const Vec2* vel, unsigned int parent, const unsigned int target) {
|
||||
Vec2 v;
|
||||
double mass = 1; // Presumer lasers have a mass of 1.
|
||||
double rdir = dir; // Real direction (accuracy).
|
||||
Weapon* w = MALLOC_L(Weapon);
|
||||
w->parent = parent; // Non-Changeable.
|
||||
w->target = target; // Non-Changeable.
|
||||
w->outfit = outfit; // Non-Changeable.
|
||||
w->update = weapon_update;
|
||||
w->timer = SDL_GetTicks();
|
||||
@ -172,6 +216,11 @@ static Weapon* weapon_create(const Outfit* outfit, const double dir, const Vec2*
|
||||
vect_cadd(&v, outfit->speed*cos(rdir), outfit->speed*sin(rdir));
|
||||
w->solid = solid_create(mass, rdir, pos, &v);
|
||||
break;
|
||||
case OUTFIT_TYPE_MISSILE_SEEK_AMMO:
|
||||
mass = w->outfit->mass;
|
||||
w->solid = solid_create(mass, dir, pos, vel);
|
||||
w->think = think_seeker; // Eeek!!!
|
||||
break;
|
||||
default:
|
||||
// Just dump it where the player is.
|
||||
w->solid = solid_create(mass, dir, pos, vel);
|
||||
@ -182,13 +231,14 @@ static Weapon* weapon_create(const Outfit* outfit, const double dir, const Vec2*
|
||||
|
||||
// Add a new weapon.
|
||||
void weapon_add(const Outfit* outfit, const double dir, const Vec2* pos, const Vec2* vel,
|
||||
unsigned int parent, WeaponLayer layer) {
|
||||
if(!outfit_isWeapon(outfit)) {
|
||||
unsigned int parent, unsigned int target, WeaponLayer layer) {
|
||||
|
||||
if(!outfit_isWeapon(outfit) && !outfit_isAmmo(outfit)) {
|
||||
ERR("Trying to create a weapon from a non-Weapon type Outfit");
|
||||
return;
|
||||
}
|
||||
|
||||
Weapon* w = weapon_create(outfit, dir, pos, vel, parent);
|
||||
Weapon* w = weapon_create(outfit, dir, pos, vel, parent, target);
|
||||
|
||||
// Set the propper layer.
|
||||
Weapon** curLayer = NULL;
|
||||
|
@ -5,7 +5,8 @@
|
||||
typedef enum { WEAPON_LAYER_BG, WEAPON_LAYER_FG } WeaponLayer;
|
||||
|
||||
void weapon_add(const Outfit* outfit, const double dir,
|
||||
const Vec2* pos, const Vec2* vel, unsigned int parent, WeaponLayer layer);
|
||||
const Vec2* pos, const Vec2* vel, unsigned int parent,
|
||||
const unsigned int target, WeaponLayer layer);
|
||||
|
||||
void weapons_update(const double dt, WeaponLayer layer);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user