Lephisto/src/escort.c
2014-03-07 23:35:52 +00:00

200 lines
4.8 KiB
C

/**
* @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;
double dir;
/* 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;
/* Get the direction. */
if(carried) dir = p->solid->dir;
else dir = 0.;
/* Create the pilot. */
e = pilot_create(s, NULL, p->faction, buf, dir, 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(e, 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 int escorts_attack(Pilot* parent)
*
* @brief HAve a pilot order it's escorts to attack its target.
* @param parent Pilot giving the order.
*/
int escorts_attack(Pilot* parent) {
int ret;
Pilot* t;
ret = 1;
if(parent->target != parent->id)
ret = escort_command(parent, ESCORT_ATTACK, parent->target);
if((ret == 0) && (parent == player)) {
t = pilot_get(parent->target);
if(t != NULL)
player_message("Escorts: Attacking %s.", t->name);
}
return ret;
}
/**
* @fn int escorts_hold(Pilot* parent)
*
* @brief Have a pilot order its escorts to hold position.
* @param parent Pilot giving the order.
*/
int escorts_hold(Pilot* parent) {
int ret;
ret = escort_command(parent, ESCORT_HOLD, -1);
if((ret == 0) && (parent == player))
player_message("Escorts: Holding position.");
return ret;
}
/**
* @fn int escorts_return(Pilot* parent)
*
* @brief Have a pilot order its escorts to dock.
* @param parent Pilot giving the order.
*/
int escorts_return(Pilot* parent) {
int ret;
ret = escort_command(parent, ESCORT_RETURN, -1);
if((ret == 0) && (parent == player))
player_message("Escorts: Returning to ship.");
return ret;
}
/**
* @fn int escorts_clear(Pilot* parent)
*
* @brief Have a pilot order its escorts to clear orders.
* @param parent Pilot giving the order.
*/
int escorts_clear(Pilot* parent) {
int ret;
ret = escort_command(parent, ESCORT_CLEAR, -1);
if((ret == 0) && (parent == player))
player_message("Escorts: Clearing orders.");
return ret;
}