[Add] Added a ton more escort stuff.

This commit is contained in:
Allanis 2013-12-30 21:51:59 +00:00
parent febcfdbbb5
commit 8aaba0be4c
7 changed files with 322 additions and 61 deletions

176
src/escort.c Normal file
View File

@ -0,0 +1,176 @@
/**
* @file escorts.c
*
* @brief Handles the players escorts.
*/
#include "lephisto.h"
#include "log.h"
#include "player.h"
#include "llua.h"
#include "lluadef.h"
#include "llua_space.h"
#include "escort.h"
#define ESCORT_PREALLOC 8 /**< Number of escorts to automatically allocate first. */
#define ESCORT_ATTACK 1 /**< Attack order. */
#define ESCORT_HOLD 2 /**< Hold order. */
#define ESCORT_RETURN 3 /**< Return to ship order. */
#define ESCORT_CLEAR 4 /**< Clear orders. */
/* Static. */
static int escort_command(Pilot* parent, int cmd, int param);
/* Extern. */
extern void ai_setPilot(Pilot* p);
/**
* @fn int escort_create(unsigned int parent, char* ship,
* Vec2* pos, Vec2* vel, int carried)
*
* @brief Create an escort.
* @param parent Parent of the escort (who she's guarding).
* @param ship Name of the ship escort should have.
* @param pos Position to create escort at.
* @param vel Velocity to create escort with.
* @param carried Does escort come out of the parent?
*/
int escort_create(unsigned int parent, char* ship,
Vec2* pos, Vec2* vel, int carried) {
Ship* s;
Pilot* p, *pe;
char buf[16];
unsigned int e, f;
/* Get important stuff. */
p = pilot_get(parent);
s = ship_get(ship);
snprintf(buf, 16, "tpl/escort*%u", parent);
/* Set flags. */
f = PILOT_ESCORT;
if(carried) f |= PILOT_CARRIED;
/* Create the pilot. */
e = pilot_create(s, NULL, p->faction, buf, 0., pos, vel, f);
pe = pilot_get(e);
pe->parent = parent;
/* Add to escort list. */
p->nescorts++;
if(p->nescorts == 1)
p->escorts = malloc(sizeof(unsigned int) * ESCORT_PREALLOC);
else if(p->nescorts > ESCORT_PREALLOC)
p->escorts = realloc(p->escorts, sizeof(unsigned int) * p->nescorts);
p->escorts[p->nescorts-1] = e;
return 0;
}
/**
* @fn static int escort_command(Pilot* parent, int cmd, int param)
*
* @brief Run an escort command on all of a pilots escorts.
* @param parent Pilot who is giving orders.
* @param cmd Order to give.
* @param param Parameter for order.
* @return 0 on success, 1 if no orders given.
*/
static int escort_command(Pilot* parent, int cmd, int param) {
int i, n;
lua_State* L;
Pilot* e;
char* buf;
if(parent->nescorts == 0)
return 1;
n = 0;
for(i = 0; i < parent->nescorts; i++) {
e = pilot_get(parent->escorts[i]);
if(e == NULL) /* Most likely died. */
continue;
/* Check if command makes sense. */
if((cmd == ESCORT_RETURN) && !pilot_isFlag(parent, PILOT_CARRIED))
continue;
n++; /* Amount of escorts left. */
/* Prepare ai. */
ai_setPilot(e);
/* Set up stack. */
L = e->ai->L;
switch(cmd) {
case ESCORT_ATTACK:
buf = "e_attack";
break;
case ESCORT_HOLD:
buf = "e_hold";
break;
case ESCORT_RETURN:
buf = "e_return";
break;
case ESCORT_CLEAR:
buf = "e_clear";
break;
}
lua_getglobal(L, buf);
if(param >= 0)
lua_pushnumber(L, param);
/* Run command. */
if(lua_pcall(L, (param >= 0) ? 1 : 0, 0, 0))
WARN("Pilot '%s' ai -> '%s' : %s", e->name,
buf, lua_tostring(L, -1));
}
return !n;
}
/**
* @fn void escorts_attack(Pilot* parent)
*
* @brief HAve a pilot order it's escorts to attack its target.
* @param parent Pilot giving the order.
*/
void escorts_attack(Pilot* parent) {
if(parent->target != parent->id)
if(escort_command(parent, ESCORT_ATTACK, parent->target)==0)
player_message("Escorts: Attacking %s.", pilot_get(parent->target)->name);
}
/**
* @fn void escorts_hold(Pilot* parent)
*
* @brief Have a pilot order its escorts to hold position.
* @param parent Pilot giving the order.
*/
void escorts_hold(Pilot* parent) {
if(escort_command(parent, ESCORT_HOLD, -1)==0)
player_message("Escorts: Holding position.");
}
/**
* @fn void escorts_return(Pilot* parent)
*
* @brief Have a pilot order its escorts to dock.
* @param parent Pilot giving the order.
*/
void escorts_return(Pilot* parent) {
if(escort_command(parent, ESCORT_RETURN, -1)==0)
player_message("Escorts: Returning to ship.");
}
/**
* @fn void escorts_clear(Pilot* parent)
*
* @brief Have a pilot order its escorts to clear orders.
* @param parent Pilot giving the order.
*/
void escorts_clear(Pilot* parent) {
if(escort_command(parent, ESCORT_CLEAR, -1)==0)
player_message("Escorts: Clearing orders.");
}

13
src/escort.h Normal file
View File

@ -0,0 +1,13 @@
#pragma once
#include "physics.h"
#include "pilot.h"
int escort_create(unsigned int parent, char* ship,
Vec2* pos, Vec2* vel, int carried);
/* Keybind commands. */
void escorts_attack(Pilot* parent);
void escorts_hold(Pilot* parent);
void escorts_return(Pilot* parent);
void escorts_clear(Pilot* parent);

View File

@ -12,6 +12,7 @@
#include "menu.h"
#include "board.h"
#include "map.h"
#include "escort.h"
#include "input.h"
#define KEY_PRESS ( 1.) /**< Key is pressed. */
@ -37,6 +38,8 @@ const char* keybindNames[] = {
"target", "target_nearest", "target_hostile",
/* Fighting. */
"primary", "face", "board",
/* Escorts. */
"e_attack", "e_hold", "e_return", "e_clear",
/* Secondary weapons. */
"secondary", "secondary_next",
/* Space Navigation. */
@ -52,8 +55,6 @@ unsigned int input_afterburnSensibility = 200; /**< ms between taps to afterbur
/* From player.c */
extern double player_turn;
extern unsigned int player_target;
/**
* @fn void input_setDefault(void)
@ -75,8 +76,15 @@ void input_setDefault(void) {
input_setKeybind("primary", KEYBIND_KEYBOARD, SDLK_SPACE, KMOD_NONE, 0);
input_setKeybind("face", KEYBIND_KEYBOARD, SDLK_f, KMOD_NONE, 0);
input_setKeybind("board", KEYBIND_KEYBOARD, SDLK_b, KMOD_NONE, 0);
/* Escorts. */
input_setKeybind("e_attack", KEYBIND_KEYBOARD, SDLK_f, KMOD_NONE, 0);
input_setKeybind("e_hold", KEYBIND_KEYBOARD, SDLK_g, KMOD_NONE, 0);
input_setKeybind("e_return", KEYBIND_KEYBOARD, SDLK_r, KMOD_NONE, 0);
input_setKeybind("e_cleark", KEYBIND_KEYBOARD, SDLK_c, KMOD_NONE, 0);
/* Secondary weapon. */
input_setKeybind("secondary", KEYBIND_KEYBOARD, SDLK_LSHIFT, KMOD_ALL, 0);
input_setKeybind("secondary", KEYBIND_KEYBOARD, SDLK_LSHIFT, KMOD_ALL, 0);
input_setKeybind("secondary_next", KEYBIND_KEYBOARD, SDLK_e, KMOD_NONE, 0);
/* Space */
input_setKeybind("autonav", KEYBIND_KEYBOARD, SDLK_j, KMOD_LCTRL, 0);
@ -299,6 +307,19 @@ static void input_key(int keynum, double value, int kabs) {
player_board();
}
}
/* Escorts. */
else if(INGAME() && KEY("e_attack")) {
if(value == KEY_PRESS) escorts_attack(player);
}
else if(INGAME() && KEY("e_hold")) {
if(value == KEY_PRESS) escorts_hold(player);
}
else if(INGAME() && KEY("e_return")) {
if(value == KEY_PRESS) escorts_return(player);
}
else if(INGAME() && KEY("e_clear")) {
if(value == KEY_PRESS) escorts_clear(player);
}
/* Shooting secondary weapon. */
else if(KEY("secondary") && NOHYP()) {
if(value == KEY_PRESS) { player_setFlag(PLAYER_SECONDARY); }

View File

@ -265,6 +265,28 @@ int outfit_isJammer(const Outfit* o) {
return(o->type == OUTFIT_TYPE_JAMMER);
}
/**
* @fn int outfit_isFighterBay(const Outfit* o)
*
* @brief Check if outfit is a fighter bay.
* @param o Outfit to check.
* @param 1 if o is a jammer.
*/
int outfit_isFighterBay(const Outfit* o) {
return (o->type == OUTFIT_TYPE_FIGHTER_BAY);
}
/**
* @fn int outfit_isFighter(const Outfit* o)
*
* @brief Check if outfit is a fighter.
* @param o Outfit to check.
* @param 1 if o is a jammer.
*/
int outfit_isFighter(const Outfit* o) {
return (o->type == OUTFIT_TYPE_FIGHTER);
}
/**
* @fn int outfit_isMap(const Outfit* o)
*
@ -336,9 +358,10 @@ DamageType outfit_damageType(const Outfit* o) {
* @param o Outfit to get information from.
*/
int outfit_delay(const Outfit* o) {
if(outfit_isBolt(o)) return o->u.blt.delay;
else if(outfit_isBeam(o)) return o->u.bem.delay;
else if(outfit_isLauncher(o)) return o->u.lau.delay;
if(outfit_isBolt(o)) return o->u.blt.delay;
else if(outfit_isBeam(o)) return o->u.bem.delay;
else if(outfit_isLauncher(o)) return o->u.lau.delay;
else if(outfit_isFighterBay(o)) return o->u.bay.delay;
return -1;
}
@ -407,6 +430,8 @@ const char* outfit_getType(const Outfit* o) {
"Ship Modification",
"Afterburner",
"Jammer",
"Fighter Bay",
"Fighter",
"Map"
};
@ -421,32 +446,18 @@ const char* outfit_getType(const Outfit* o) {
* @return the outfits broad type in human readable form.
*/
const char* outfit_getTypeBroad(const Outfit* o) {
int i = 0;
const char* outfit_typenamebroad[] = {
"NULL",
"Bolt Weapon",
"Beam Weapon",
"Launcher",
"Ammo",
"Turret",
"Modification",
"Afterburner",
"Jammer",
"Map"
};
if(outfit_isBolt(o)) i = 1;
else if(outfit_isBeam(o)) i = 2;
else if(outfit_isLauncher(o)) i = 3;
else if(outfit_isAmmo(o)) i = 4;
else if(outfit_isTurret(o)) i = 5;
else if(outfit_isMod(o)) i = 6;
else if(outfit_isAfterburner(o)) i = 7;
else if(outfit_isJammer(o)) i = 8;
else if(outfit_isMap(o)) i = 9;
return outfit_typenamebroad[i];
if(outfit_isBolt(o)) return "Bolt Weapon";
else if(outfit_isBeam(o)) return "Beam Weapon";
else if(outfit_isLauncher(o)) return "Launcher";
else if(outfit_isAmmo(o)) return "Ammo";
else if(outfit_isTurret(o)) return "Turret";
else if(outfit_isMod(o)) return "Modification";
else if(outfit_isAfterburner(o)) return "Afterburner";
else if(outfit_isJammer(o)) return "Jammer";
else if(outfit_isFighterBay(o)) return "Fighter Bay";
else if(outfit_isFighter(o)) return "Fighter";
else if(outfit_isMap(o)) return "Map";
else return "Unknown";
}
/* Return the damage type from a str. */
@ -904,22 +915,26 @@ int outfit_load(void) {
/* Frees the outfit stack. */
void outfit_free(void) {
int i;
Outfit* o;
for(i = 0; i < outfit_nstack; i++) {
o = &outfit_stack[i];
/* Free graphics. */
if(outfit_gfx(&outfit_stack[i]))
gl_freeTexture(outfit_gfx(&outfit_stack[i]));
/* Type specification. */
if(outfit_isLauncher(o) && o->u.lau.ammo)
free(o->u.lau.ammo);
if(outfit_isFighterBay(o) && o->u.bay.ammo)
free(o->u.bay.ammo);
/* Strings. */
if(outfit_isLauncher(&outfit_stack[i]) && outfit_stack[i].u.lau.ammo)
free(outfit_stack[i].u.lau.ammo);
if(outfit_stack[i].description)
free(outfit_stack[i].description);
if(outfit_stack[i].gfx_store)
gl_freeTexture(outfit_stack[i].gfx_store);
free(outfit_stack[i].name);
if(o->description)
free(o->description);
if(o->gfx_store)
gl_freeTexture(o->gfx_store);
free(o->name);
}
free(outfit_stack);
}

View File

@ -32,6 +32,8 @@ typedef enum OutfitType_ {
OUTFIT_TYPE_MODIFICATION, /**< Modifies the ship afterburn capability. */
OUTFIT_TYPE_AFTERBURNER, /**< Gives the ship afterburn capability. */
OUTFIT_TYPE_JAMMER, /**< Used to nullify seeker missiles. */
OUTFIT_TYPE_FIGHTER_BAY, /**< Contains other ships. */
OUTFIT_TYPE_FIGHTER, /**< Ship contained in FIGHTER BAY. */
OUTFIT_TYPE_MAP, /**< Give the player more knowledge about systems. */
OUTFIT_TYPE_SENTINEL /**< Indicates last type. */
} OutfitType;
@ -171,6 +173,26 @@ typedef struct OutfitAfterburnerData_ {
double energy; /**< Energy used while active. */
} OutfitAfterburnerData;
/**
* @struct OutfitFighterBayData
*
* @brief Represents a fighter bay.
*/
typedef struct OutfitFighterBayData_ {
char* ammo; /**< Ships to use as ammo. */
double delay; /**< Delay between launches. */
} OutfitFighterBayData;
/**
* @struct OutfitFighterData
*
* @brief Represents a fighter for a fighter bay.
*/
typedef struct OutfitFighterData_ {
char* ship; /**< Ship to use for fighter. */
int sound; /**< Sound to make when launching. */
} OutfitFighterData;
/**
* @struct OutfitMapData
*
@ -225,6 +247,8 @@ typedef struct Outfit_ {
OutfitModificationData mod; /**< MODIFICATION. */
OutfitAfterburnerData afb; /**< AFTERBURNER. */
OutfitJammerData jam; /**< JAMMER. */
OutfitFighterBayData bay; /**< FIGHTER_BAY. */
OutfitFighterData fig; /**< FIGHTER. */
OutfitMapData map; /**< MAP. */
} u;
} Outfit;
@ -245,8 +269,10 @@ int outfit_isAmmo(const Outfit* o);
int outfit_isTurret(const Outfit* o);
int outfit_isMod(const Outfit* o);
int outfit_isAfterburner(const Outfit* o);
int outfit_isMap(const Outfit* o);
int outfit_isJammer(const Outfit* o);
int outfit_isFighterBay(const Outfit* o);
int outfit_isFighter(const Outfit* o);
int outfit_isMap(const Outfit* o);
const char* outfit_getType(const Outfit* o);
const char* outfit_getTypeBroad(const Outfit* o);

View File

@ -1260,6 +1260,13 @@ void pilot_init(Pilot* pilot, Ship* ship, char* name, int faction,
/* All update the same way. */
pilot->update = pilot_update;
/* Escort stuff. */
if(flags & PILOT_ESCORT) {
pilot->flags |= PILOT_ESCORT;
if(flags & PILOT_CARRIED)
pilot->flags |= PILOT_CARRIED;
}
/* AI. */
pilot->target = pilot->id; /* Self = no target. */
if(ai != NULL)
@ -1378,6 +1385,7 @@ void pilot_free(Pilot* p) {
if(p->outfits) free(p->outfits);
free(p->name);
if(p->commodities) free(p->commodities);
if(p->escorts) free(p->escorts);
free(p);
}

View File

@ -33,24 +33,26 @@
#define pilot_setFlag(p,f) (p->flags |= (f)) /**< Set flag f on pilot p. */
#define pilot_rmFlag(p,f) (p->flags ^= (f)) /**< Remove flag f on pilot p. */
/* Creation. */
#define PILOT_PLAYER (1<<0) /**< Pilot is a player. */
#define PILOT_HASTURRET (1<<20) /**< Pilot has turrets. */
#define PILOT_HASBEAMS (1<<23) /**< Pilot has beam weapons. */
#define PILOT_NO_OUTFITS (1<<21) /**< Do not create the pilot with outfits. */
#define PILOT_EMPTY (1<<22) /**< Do not add pilot to stack. */
#define PILOT_PLAYER (1<<0) /**< Pilot is a player. */
#define PILOT_ESCORT (1<<1) /**< Pilot is an escort. */
#define PILOT_CARRIED (1<<2) /**< Pilot usually resides in a fighter bay. */
#define PILOT_EMPTY (1<<5) /**< Do not add pilot to stack. */
#define PILOT_NO_OUTFITS (1<<6) /**< Do not create the pilot with outfits. */
#define PILOT_HASTURRET (1<<9) /**< Pilot has turrets. */
#define PILOT_HASBEAMS (1<<10) /**< Pilot has beam weapons. */
/* Dynamic. */
#define PILOT_HOSTILE (1<<1) /**< Pilot is hostile to the player. */
#define PILOT_COMBAT (1<<2) /**< Pilot is engaged in combat. */
#define PILOT_AFTERBURNER (1<<3) /**< Pilot has her afterburner activated. */
#define PILOT_HYP_PREP (1<<5) /**< Pilot is getting ready for hyperspace. */
#define PILOT_HYP_BEGIN (1<<6) /**< Pilot is starting engines. */
#define PILOT_HYPERSPACE (1<<7) /**< Pilot is in hyperspace. */
#define PILOT_BOARDED (1<<8) /**< Pilot has been boarded already! */
#define PILOT_DISABLED (1<<9) /**< Pilot is disabled. */
#define PILOT_DEAD (1<<10) /**< Pilot is on it's death bed. */
#define PILOT_DEATH_SOUND (1<<11) /**< Pilot just did death explosion. */
#define PILOT_EXPLODED (1<<12) /**< Pilot did final death explosion. */
#define PILOT_DELETE (1<<15) /**< Pilot will get delete asap. */
#define PILOT_HOSTILE (1<<11) /**< Pilot is hostile to the player. */
#define PILOT_COMBAT (1<<12) /**< Pilot is engaged in combat. */
#define PILOT_AFTERBURNER (1<<13) /**< Pilot has her afterburner activated. */
#define PILOT_HYP_PREP (1<<15) /**< Pilot is getting ready for hyperspace. */
#define PILOT_HYP_BEGIN (1<<16) /**< Pilot is starting engines. */
#define PILOT_HYPERSPACE (1<<17) /**< Pilot is in hyperspace. */
#define PILOT_BOARDED (1<<18) /**< Pilot has been boarded already! */
#define PILOT_DISABLED (1<<19) /**< Pilot is disabled. */
#define PILOT_DEAD (1<<20) /**< Pilot is on it's death bed. */
#define PILOT_DEATH_SOUND (1<<21) /**< Pilot just did death explosion. */
#define PILOT_EXPLODED (1<<22) /**< Pilot did final death explosion. */
#define PILOT_DELETE (1<<25) /**< Pilot will get delete asap. */
/* Just makes life simpler. */
#define pilot_isPlayer(p) ((p)->flags & PILOT_PLAYER) /**< Check if pilot is a player. */
@ -164,7 +166,7 @@ typedef struct Pilot_ {
/* Escort stuff. */
unsigned int parent; /**< Pilots parent. */
unsigned int* escort; /**< Pilots escorts. */
unsigned int* escorts; /**< Pilots escorts. */
int nescorts; /**< Number of pilot escorts. */
/* AI. */