/** * @brief The pseudo-ai of the beam weapons. * * @param w Weapon to do the thinking. * @param dt Current delta tick. */ static void think_beam( Weapon* w, const double dt ) { (void)dt; Pilot *p, *t; double diff; Vector2d v; /* Get pilot, if pilot is dead beam is destroyed. */ p = pilot_get(w->parent); if (p==NULL) { w->timer = -1.; /* Hack to make it get destroyed next update. */ return; } /* Check if pilot has enough energy left to keep beam active. */ p->energy -= dt*w->outfit->u.bem.energy; if (p->energy < 0.) { p->energy = 0.; w->timer = -1; return; } /* Use mount position. */ pilot_getMount( p, w->mount, &v ); w->solid->pos.x = p->solid->pos.x + v.x; w->solid->pos.y = p->solid->pos.y + v.y; /* Handle aiming. */ switch (w->outfit->type) { case OUTFIT_TYPE_BEAM: w->solid->dir = p->solid->dir; break; case OUTFIT_TYPE_TURRET_BEAM: /* Get target, if target is dead beam stops moving. */ t = pilot_get(w->target); if (t==NULL) { weapon_setTurn( w, 0. ); return; } if (w->target == w->parent) /* Invalid target, tries to follow shooter. */ diff = angle_diff(w->solid->dir, p->solid->dir); else diff = angle_diff(w->solid->dir, /* Get angle to target pos */ vect_angle(&w->solid->pos, &t->solid->pos)); weapon_setTurn( w, CLAMP( -w->outfit->u.bem.turn, w->outfit->u.bem.turn, 10 * diff * w->outfit->u.bem.turn )); break; default: return; } }
/** * @brief Updates the camera. * * @param dt Current delta tick. */ void cam_update( double dt ) { Pilot *p; double dx, dy; /* Calculate differential. */ dx = old_X; dy = old_Y; /* Going to position. */ p = NULL; if (camera_fly) { if (camera_followpilot != 0) { p = pilot_get( camera_followpilot ); if (p == NULL) { camera_followpilot = 0; camera_fly = 0; } else { cam_updateFly( p->solid->pos.x, p->solid->pos.y, dt ); cam_updatePilotZoom( p, NULL, dt ); } } else cam_updateFly( target_X, target_Y, dt ); } else { /* Track pilot. */ if (camera_followpilot != 0) { p = pilot_get( camera_followpilot ); if (p == NULL) camera_followpilot = 0; else cam_updatePilot( p, dt ); } } /* Update manual zoom. */ if (conf.zoom_manual) cam_updateManualZoom( dt ); /* Set the sound. */ if ((p==NULL) || !conf.snd_pilotrel) { dx = dt*(dx-camera_X); dy = dt*(dy-camera_Y); sound_updateListener( CAMERA_DIR, camera_X, camera_Y, dx, dy ); } else { sound_updateListener( p->solid->dir, p->solid->pos.x, p->solid->pos.y, p->solid->vel.x, p->solid->vel.y ); } }
/** * @brief Creates an escort. * * @param p Parent of the escort (who he'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 dir Direction to face. * @param type Type of escort. * @param add Whether or not to add it to the escort list. * @return The ID of the escort on success. */ unsigned int escort_create( Pilot *p, char *ship, Vector2d *pos, Vector2d *vel, double dir, EscortType_t type, int add ) { Ship *s; Pilot *pe; unsigned int e; PilotFlags f; unsigned int parent; /* Get important stuff. */ parent = p->id; s = ship_get(ship); /* Set flags. */ pilot_clearFlagsRaw( f ); pilot_setFlagRaw( f, PILOT_NOJUMP ); if (type == ESCORT_TYPE_BAY) pilot_setFlagRaw( f, PILOT_CARRIED ); /* Create the pilot. */ e = pilot_create( s, NULL, p->faction, "escort", dir, pos, vel, f ); pe = pilot_get(e); pe->parent = parent; /* Add to escort list. */ if (add != 0) escort_addList( p, ship, type, e, 1 ); return e; }
/** * @brief Changes the pilot's AI. * * @usage p:changeAI( "empire" ) -- set the pilot to use the Empire AI * * @luafunc changeAI( p, newai ) */ static int pilotL_changeAI( lua_State *L ) { LuaPilot *lp; Pilot *p; const char *str; int ret; /* Get the pilot. */ lp = luaL_checkpilot(L,1); p = pilot_get(lp->pilot); if (p==NULL) { NLUA_ERROR(L,"Pilot is invalid."); return 0; } /* Get parameters. */ str = luaL_checkstring(L,2); /* Get rid of current AI. */ ai_destroy(p); /* Create the new AI. */ ret = ai_pinit( p, str ); lua_pushboolean(L, ret); return 1; }
/** * @brief Hooks the function to a specific pilot. * * You can hook to different actions. Curently hook system only supports:<br /> * - "death" : triggered when pilot dies.<br /> * - "board" : triggered when pilot is boarded.<br /> * - "disable" : triggered when pilot is disabled.<br /> * - "jump" : triggered when pilot jumps to hyperspace.<br /> * - "hail" : triggered when pilot is hailed.<br /> * - "attacked" : triggered when the pilot is attacked in manual control <br /> * - "idle" : triggered when the pilot becomes idle in manual control <br /> * * @luaparam pilot Pilot identifier to hook. * @luaparam type One of the supported hook types. * @luaparam funcname Name of function to run when hook is triggered. * @luareturn Hook identifier. * @luafunc pilot( pilot, type, funcname ) */ static int hook_pilot( lua_State *L ) { unsigned int h; LuaPilot *p; int type; const char *hook_type; /* Parameters. */ p = luaL_checkpilot(L,1); hook_type = luaL_checkstring(L,2); /* Check to see if hook_type is valid */ if (strcmp(hook_type,"death")==0) type = PILOT_HOOK_DEATH; else if (strcmp(hook_type,"board")==0) type = PILOT_HOOK_BOARD; else if (strcmp(hook_type,"disable")==0) type = PILOT_HOOK_DISABLE; else if (strcmp(hook_type,"jump")==0) type = PILOT_HOOK_JUMP; else if (strcmp(hook_type,"hail")==0) type = PILOT_HOOK_HAIL; else if (strcmp(hook_type,"attacked")==0) type = PILOT_HOOK_ATTACKED; else if (strcmp(hook_type,"idle")==0) type = PILOT_HOOK_IDLE; else { /* hook_type not valid */ NLUA_DEBUG("Invalid pilot hook type: '%s'", hook_type); return 0; } /* actually add the hook */ h = hook_generic( L, hook_type, 3 ); pilot_addHook( pilot_get(p->pilot), type, h ); return 0; }
/** * @brief Throws cargo out in space graphically. * * @param pilot ID of the pilot throwing the stuff out * @param com Commodity to throw out. * @param quantity Quantity thrown out. */ void commodity_Jettison( int pilot, Commodity* com, int quantity ) { (void)com; int i; Pilot* p; int n, effect; double px,py, bvx, bvy, r,a, vx,vy; p = pilot_get( pilot ); n = MAX( 1, RNG(quantity/10, quantity/5) ); px = p->solid->pos.x; py = p->solid->pos.y; bvx = p->solid->vel.x; bvy = p->solid->vel.y; for (i=0; i<n; i++) { effect = spfx_get("cargo"); /* Radial distribution gives much nicer results */ r = RNGF()*25 - 12.5; a = 2. * M_PI * RNGF(); vx = bvx + r*cos(a); vy = bvy + r*sin(a); /* Add the cargo effect */ spfx_add( effect, px, py, vx, vy, SPFX_LAYER_BACK ); } }
/** * @brief Has a pilot attempt to board another pilot. * * @param p Pilot doing the boarding. * @return 1 if target was boarded. */ int pilot_board( Pilot *p ) { Pilot *target; /* Make sure target is sane. */ target = pilot_get(p->target); if (target == NULL) { DEBUG("NO TARGET"); return 0; } /* Check if can board. */ if (!pilot_isDisabled(target)) return 0; else if (vect_dist(&p->solid->pos, &target->solid->pos) > target->ship->gfx_space->sw * PILOT_SIZE_APROX ) return 0; else if ((pow2(VX(p->solid->vel)-VX(target->solid->vel)) + pow2(VY(p->solid->vel)-VY(target->solid->vel))) > (double)pow2(MAX_HYPERSPACE_VEL)) return 0; else if (pilot_isFlag(target,PILOT_BOARDED)) return 0; /* Set the boarding flag. */ pilot_setFlag(target, PILOT_BOARDED); pilot_setFlag(p, PILOT_BOARDING); /* Set time it takes to board. */ p->ptimer = 3.; return 1; }
/** * @brief Updates the boarding window fields. * * @param wdw Window to update. */ static void board_update( unsigned int wdw ) { int i, j; char str[PATH_MAX]; char cred[10]; Pilot* p; p = pilot_get(player->target); j = 0; /* Credits. */ credits2str( cred, p->credits, 2 ); j += snprintf( &str[j], PATH_MAX-j, "%s\n", cred ); /* Commodities. */ if (p->ncommodities==0) j += snprintf( &str[j], PATH_MAX-j, "none\n" ); else { for (i=0; i<p->ncommodities; i++) j += snprintf( &str[j], PATH_MAX-j, "%d %s\n", p->commodities[i].quantity, p->commodities[i].commodity->name ); } /* Fuel. */ if (p->fuel <= 0.) j += snprintf( &str[j], PATH_MAX-j, "none\n" ); else j += snprintf( &str[j], PATH_MAX-j, "%.0f Units\n", p->fuel ); window_modifyText( wdw, "txtData", str ); }
/** * @brief Checks to see if the pilot can steal from it's target. * * @param p Pilot stealing from it's target. * @return 0 if successful, 1 if fails, -1 if fails and kills target. */ static int board_trySteal( Pilot *p ) { Pilot *target; /* Get the target. */ target = pilot_get(p->target); if (target == NULL) return 1; /* See if was successful. */ if (RNGF() > (0.5 * (10. + (double)target->ship->crew)/(10. + (double)p->ship->crew))) return 0; /* Triggered self destruct. */ if (RNGF() < 0.4) { /* Don't actually kill. */ target->armour = 1.; /* This will make the boarding ship take the possible faction hit. */ pilot_hit( target, NULL, p->id, DAMAGE_TYPE_KINETIC, 100. ); /* Return ship dead. */ return -1; } return 1; }
/** * @brief Sets the target to follow. */ void cam_setTargetPilot( unsigned int follow, int soft_over ) { Pilot *p; double dir, x, y; /* Set the target. */ camera_followpilot = follow; dir = CAMERA_DIR; /* Set camera if necessary. */ if (!soft_over) { if (follow != 0) { p = pilot_get( follow ); if (p != NULL) { dir = p->solid->dir; x = p->solid->pos.x; y = p->solid->pos.y; camera_X = x; camera_Y = y; old_X = x; old_Y = y; } } camera_fly = 0; } else { old_X = camera_X; old_Y = camera_Y; camera_fly = 1; camera_flyspeed = (double) soft_over; } sound_updateListener( dir, camera_X, camera_Y, 0., 0. ); }
/** * @brief Adds an outfit to a pilot. * * @usage added = p:addOutfit( "Laser Cannon", 5 ) -- Adds 5 laser cannons to p * * @luaparam p Pilot to add outfit to. * @luaparam outfit Name of the outfit to add. * @luaparam q Amount to add. * @luareturn The amount actually added. * @luafunc addOutfit( p, outfit, q ) */ static int pilotL_addOutfit( lua_State *L ) { LuaPilot *lp; Pilot *p; const char *outfit; int q, n; Outfit *o; /* Get the pilot. */ lp = luaL_checkpilot(L,1); p = pilot_get(lp->pilot); if (p==NULL) { NLUA_ERROR(L,"Pilot is invalid."); return 0; } /* Get parameters. */ outfit = luaL_checkstring(L,2); q = luaL_checkint(L,3); /* Get the outfit. */ o = outfit_get( outfit ); if (o == NULL) return 0; /* Add outfit. */ n = pilot_addOutfit( p, o, q ); lua_pushnumber(L,n); return 1; }
/** * @brief Attempt to steal the boarded ship's cargo. * * @param wdw Window triggering the function. * @param str Unused. */ static void board_stealCargo( unsigned int wdw, char* str ) { (void)str; int q; Pilot* p; p = pilot_get(player->target); if (p->ncommodities==0) { /* no cargo */ player_message("The ship has no cargo."); return; } else if (pilot_cargoFree(player) <= 0) { player_message("You have no room for cargo."); return; } if (board_fail(wdw)) return; /** steal as much as possible until full - @todo let player choose */ q = 1; while ((p->ncommodities > 0) && (q!=0)) { q = pilot_addCargo( player, p->commodities[0].commodity, p->commodities[0].quantity ); pilot_rmCargo( p, p->commodities[0].commodity, q ); } board_update( wdw ); player_message("You manage to steal the ship's cargo."); }
/** * @brief Attempt to steal the boarded ship's fuel. * * @param wdw Window triggering the function. * @param str Unused. */ static void board_stealFuel( unsigned int wdw, char* str ) { (void)str; Pilot* p; p = pilot_get(player->target); if (p->fuel <= 0.) { /* no fuel. */ player_message("The ship has no fuel."); return; } else if (player->fuel == player->fuel_max) { player_message("Your ship is at maximum fuel capacity."); return; } if (board_fail(wdw)) return; /* Steal fuel. */ player->fuel += p->fuel; p->fuel = 0.; /* Make sure doesn't overflow. */ if (player->fuel > player->fuel_max) { p->fuel = player->fuel_max - player->fuel; player->fuel = player->fuel_max; } board_update( wdw ); player_message("You manage to steal the ship's fuel."); }
/** * @brief Sets the pilot's faction. * * @usage p:setFaction( "Empire" ) * @usage p:setFaction( faction.get( "Dvaered" ) ) * * @luaparam p Pilot to change faction of. * @luaparam faction Faction to set by name or faction. * @luafunc setFaction( faction ) */ static int pilotL_setFaction( lua_State *L ) { Pilot *p; LuaPilot *lp; LuaFaction *f; int fid; const char *faction; /* Parse parameters. */ lp = luaL_checkpilot(L,1); if (lua_isstring(L,2)) { faction = lua_tostring(L,2); fid = faction_get(faction); } else if (lua_isfaction(L,2)) { f = lua_tofaction(L,2); fid = f->f; } else NLUA_INVALID_PARAMETER(); /* Get pilot/faction. */ p = pilot_get(lp->pilot); if (p==NULL) { NLUA_ERROR(L,"Pilot is invalid."); return 0; } /* Set the new faction. */ p->faction = fid; return 0; }
/** * @brief Runs an escort command on all of a pilot's 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; }
/** * @brief Sends a message to the target or player if no target is passed. * * @usage p:comm( "How are you doing?" ) -- Messages the player * @usage p:comm( "You got this?", true ) -- Messages the player ignoring interference * @usage p:comm( target, "Heya!" ) -- Messages target * @usage p:comm( target, "Got this?", true ) -- Messages target ignoring interference * * @luaparam p Pilot to message the player. * @ulaparam target Target to send message to. * @luaparam msg Message to send. * @luafunc comm( p, target, msg ) */ static int pilotL_comm( lua_State *L ) { Pilot *p, *t; LuaPilot *lp, *target; const char *msg; int ignore_int; /* Parse parameters. */ lp = luaL_checkpilot(L,1); if (lua_isstring(L,2)) { target = NULL; msg = luaL_checkstring(L,2); ignore_int = lua_toboolean(L,3); } else { target = luaL_checkpilot(L,2); msg = luaL_checkstring(L,3); ignore_int = lua_toboolean(L,4); } /* Check to see if pilot is valid. */ p = pilot_get(lp->pilot); if (p == NULL) { NLUA_ERROR(L,"Pilot param 1 not found in pilot stack!"); return 0; } if (target == NULL) t = player; else { t = pilot_get(target->pilot); if (t == NULL) { NLUA_ERROR(L,"Pilot param 2 not found in pilot stack!"); return 0; } } /* Broadcast message. */ pilot_message( p, t->id, msg, ignore_int ); return 0; }
/** * @brief Checks to see if pilot is still alive. * * @usage if p:alive() then -- Pilot is still alive * * @luaparam p Pilot to check to see if is still alive. * @luareturn true if pilot is still alive. * @luafunc alive( p ) */ static int pilotL_alive( lua_State *L ) { LuaPilot *lp; Pilot *p; /* Parse parameters. */ lp = luaL_checkpilot(L,1); p = pilot_get( lp->pilot ); /* Check if is alive. */ lua_pushboolean(L, p!=NULL); return 1; }
/** * @brief Opens the communication dialogue with a pilot. * * @param pilot Pilot to communicate with. * @return 0 on success. */ int comm_openPilot( unsigned int pilot ) { const char *msg; unsigned int wid; /* Get the pilot. */ comm_pilot = pilot_get( pilot ); if (comm_pilot == NULL) return -1; /* Must not be disabled. */ if (pilot_isFlag(comm_pilot, PILOT_DISABLED)) { player_message("%s does not respond.", comm_pilot->name); return 0; } /* Check to see if pilot wants to communicate. */ msg = comm_getString( "comm_no" ); if (msg != NULL) { player_message( msg ); return 0; } /* Set up for the comm_get* functions. */ ai_setPilot( comm_pilot ); /* Create the generic comm window. */ wid = comm_open( ship_loadCommGFX( comm_pilot->ship ), comm_pilot->faction, pilot_isHostile(comm_pilot) ? -1 : pilot_isFriendly(comm_pilot) ? 1 : 0, pilot_isFlag(comm_pilot, PILOT_BRIBED), comm_pilot->name ); /* Add special buttons. */ window_addButton( wid, -20, 20 + BUTTON_HEIGHT + 20, BUTTON_WIDTH, BUTTON_HEIGHT, "btnGreet", "Greet", NULL ); if (!pilot_isFlag(comm_pilot, PILOT_BRIBED) && /* Not already bribed. */ ((faction_getPlayer( comm_pilot->faction ) < 0) || /* Hostile. */ pilot_isHostile(comm_pilot))) window_addButton( wid, -20, 20 + 2*BUTTON_HEIGHT + 40, BUTTON_WIDTH, BUTTON_HEIGHT, "btnBribe", "Bribe", comm_bribePilot ); else window_addButton( wid, -20, 20 + 2*BUTTON_HEIGHT + 40, BUTTON_WIDTH, BUTTON_HEIGHT, "btnRequest", "Refuel", comm_requestFuel ); /* Run hooks if needed. */ pilot_runHook( comm_pilot, PILOT_HOOK_HAIL ); return 0; }
/** * @brief Destroys a weapon. * * @param w Weapon to destroy. * @param layer Layer to which the weapon belongs. */ static void weapon_destroy( Weapon* w, WeaponLayer layer ) { int i; Weapon** wlayer; int *nlayer; Pilot *pilot_target; /* Decrement target lockons if needed */ if (outfit_isSeeker(w->outfit)) { pilot_target = pilot_get( w->target ); if (pilot_target != NULL) pilot_target->lockons--; } /* Stop playing sound if beam weapon. */ if (outfit_isBeam(w->outfit)) { sound_stop( w->voice ); sound_playPos(w->outfit->u.bem.sound_off, w->solid->pos.x, w->solid->pos.y, w->solid->vel.x, w->solid->vel.y); } switch (layer) { case WEAPON_LAYER_BG: wlayer = wbackLayer; nlayer = &nwbackLayer; break; case WEAPON_LAYER_FG: wlayer = wfrontLayer; nlayer = &nwfrontLayer; break; default: WARN("Unknown weapon layer!"); } for (i=0; (wlayer[i] != w) && (i < *nlayer); i++); /* get to the curent position */ if (i >= *nlayer) { WARN("Trying to destroy weapon not found in stack!"); return; } weapon_free(wlayer[i]); wlayer[i] = NULL; (*nlayer)--; for ( ; i < (*nlayer); i++) wlayer[i] = wlayer[i+1]; }
/** * @brief Creates an escort. * * @param parent Parent of the escort (who he'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, Vector2d *pos, Vector2d *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, "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; }
/** * @brief Have a pilot order it's escorts to attack it's 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; }
/** * @brief Plays a sound based on position. * * @param sound Sound to play. * @param px X position of the sound. * @param py Y position of the sound. * @param vx X velocity of the sound. * @param vy Y velocity of the sound. * @return Voice identifier on success. */ int sound_playPos( int sound, double px, double py, double vx, double vy ) { alVoice *v; alSound *s; Pilot *p; double cx, cy, dist; int target; if (sound_disabled) return 0; if ((sound < 0) || (sound >= sound_nlist)) return -1; target = cam_getTarget(); /* Following a pilot. */ p = pilot_get(target); if (target && (p != NULL)) { if (!pilot_inRange( p, px, py )) return 0; } /* Set to a position. */ else { cam_getPos(&cx, &cy); dist = pow2(px - cx) + pow2(py - cy); if (dist > pilot_sensorRange()) return 0; } /* Gets a new voice. */ v = voice_new(); /* Get the sound. */ s = &sound_list[sound]; /* Try to play the sound. */ if (sound_sys_playPos( v, s, px, py, vx, vy )) return -1; /* Actually add the voice to the list. */ v->state = VOICE_PLAYING; v->id = ++voice_genid; voice_add(v); return v->id; }
/** * @brief Hooks the function to a specific pilot. * * You can hook to different actions. Curently hook system only supports:<br /> * <ul> * <li> "death" : triggered when pilot dies (before marked as dead). <br /> * <li> "exploded" : triggered when pilot has died and the final explosion has begun. <br /> * <li> "board" : triggered when pilot is boarded.<br /> * <li> "disable" : triggered when pilot is disabled (with disable set).<br /> * <li> "jump" : triggered when pilot jumps to hyperspace (before he actually jumps out).<br /> * <li> "hail" : triggered when pilot is hailed.<br /> * <li> "land" : triggered when pilot is landing (right when starting land descent).<br /> * <li> "attacked" : triggered when the pilot is attacked. <br /> * <li> "idle" : triggered when the pilot becomes idle in manual control.<br /> * </ul> * <br /> * If you pass nil as pilot, it will set it as a global hook that will jump for all pilots.<br /> * <br /> * DO NOT DO UNSAFE THINGS IN PILOT HOOKS. THIS MEANS STUFF LIKE player.teleport(). IF YOU HAVE DOUBTS USE A "safe" HOOK.<br /> * <br /> * These hooks all pass the pilot triggering the hook as a parameter, so they should have the structure of:<br /> * <br /> * function my_hook( pilot, arg )<br /> * end<br /> * <br /> * The combat hooks also pass the pilot acting on it, so for example the pilot * that disabled, attacked or killed the selected pilot. They have the * following format:<br /> * <br /> * function combat_hook( pilot, attacker, arg )<br /> * end<br /> * <br /> * Please note that in the case of disable or death hook the attacker may be nil * indicating that it was killed by other means like for example the shockwave * of a dying ship or nebula volatility. * * @luaparam pilot Pilot identifier to hook (or nil for all). * @luaparam type One of the supported hook types. * @luaparam funcname Name of function to run when hook is triggered. * @luaparam arg Argument to pass to hook. * @luareturn Hook identifier. * @luafunc pilot( pilot, type, funcname, arg ) */ static int hook_pilot( lua_State *L ) { unsigned int h; LuaPilot *p; int type; const char *hook_type; char buf[ PATH_MAX ]; /* Parameters. */ if (lua_ispilot(L,1)) p = luaL_checkpilot(L,1); else if (lua_isnil(L,1)) p = NULL; else { NLUA_ERROR(L, "Invalid parameter #1 for hook.pilot, expecting pilot or nil."); return 0; } hook_type = luaL_checkstring(L,2); /* Check to see if hook_type is valid */ if (strcmp(hook_type,"death")==0) type = PILOT_HOOK_DEATH; else if (strcmp(hook_type,"exploded")==0) type = PILOT_HOOK_EXPLODED; else if (strcmp(hook_type,"board")==0) type = PILOT_HOOK_BOARD; else if (strcmp(hook_type,"disable")==0) type = PILOT_HOOK_DISABLE; else if (strcmp(hook_type,"jump")==0) type = PILOT_HOOK_JUMP; else if (strcmp(hook_type,"hail")==0) type = PILOT_HOOK_HAIL; else if (strcmp(hook_type,"land")==0) type = PILOT_HOOK_LAND; else if (strcmp(hook_type,"attacked")==0) type = PILOT_HOOK_ATTACKED; else if (strcmp(hook_type,"idle")==0) type = PILOT_HOOK_IDLE; else { /* hook_type not valid */ NLUA_ERROR(L, "Invalid pilot hook type: '%s'", hook_type); return 0; } /* actually add the hook */ snprintf( buf, sizeof(buf), "p_%s", hook_type ); h = hook_generic( L, buf, 0., 3, 0 ); if (p==NULL) pilots_addGlobalHook( type, h ); else pilot_addHook( pilot_get(p->pilot), type, h ); lua_pushnumber( L, h ); return 1; }
/** * @brief Removes an outfit from a pilot. * * "all" will remove all outfits. * * @usage p:rmOutfit( "all" ) -- Leaves the pilot naked. * @usage p:rmOutfit( "Neutron Disruptor", 1 ) -- Removes a neutron disruptor. * * @luparam p Pilot to remove outfit from. * @luaparam outfit Name of the outfit to remove. * @luaparam q Amount to remove. * @luareturn The amount actually removed. * @luafunc rmOutfit( p, outfit, q ) */ static int pilotL_rmOutfit( lua_State *L ) { LuaPilot *lp; Pilot *p; const char *outfit; int q, n; Outfit *o; /* Get the pilot. */ lp = luaL_checkpilot(L,1); p = pilot_get(lp->pilot); if (p==NULL) { NLUA_ERROR(L,"Pilot is invalid."); return 0; } /* Get parameters. */ outfit = luaL_checkstring(L,2); /* If outfit is "all", we remove everything. */ if (strcmp(outfit,"all")==0) { n = 0; while (p->outfits != NULL) { pilot_rmOutfit( p, p->outfits[0].outfit, p->outfits[0].quantity ); n++; } lua_pushnumber(L,n); return 1; } /* We'll need a quantity now. */ q = luaL_checkint(L,3); /* Get the outfit. */ o = outfit_get( outfit ); if (o == NULL) { NLUA_ERROR(L,"Outfit isn't found in outfit stack."); return 0; } /* Add outfit. */ n = pilot_rmOutfit( p, o, q ); lua_pushnumber(L,n); return 1; }
/** * @brief Runs an escort command on all of a pilot's escorts. * * @param parent Pilot who is giving orders. * @param cmd Order to give. * @param idx Lua index of argument or 0. * @return 0 on success, 1 if no orders given. */ static int escort_command( Pilot *parent, const char *cmd, unsigned int idx ) { int i; Pilot *e; if (parent->nescorts == 0) return 1; for (i=0; i<parent->nescorts; i++) { e = pilot_get( parent->escorts[i].id ); if (e == NULL) /* Most likely died. */ continue; pilot_msg(parent, e, cmd, idx); } return 0; }
/** * @brief Sets the pilot as friendly to player. * * @usage p:setFriendly() * * @luaparam p Pilot to set as friendly. * @luafunc setFriendly( p ) */ static int pilotL_setFriendly( lua_State *L ) { LuaPilot *lp; Pilot *p; /* Get the pilot. */ lp = luaL_checkpilot(L,1); p = pilot_get(lp->pilot); if (p==NULL) { NLUA_ERROR(L,"Pilot is invalid."); return 0; } /* Remove hostile and mark as friendly. */ pilot_setFriendly(p); return 0; }
/** * @brief Sets the pilot as hostile to player. * * @usage p:setHostile() * * @luaparam p Pilot to set as hostile. * @luafunc setHostile( p ) */ static int pilotL_setHostile( lua_State *L ) { LuaPilot *lp; Pilot *p; /* Get the pilot. */ lp = luaL_checkpilot(L,1); p = pilot_get(lp->pilot); if (p==NULL) { NLUA_ERROR(L,"Pilot is invalid."); return 0; } /* Set as hostile. */ pilot_setHostile(p); return 0; }
/** * @fn void player_board (void) * * @brief Attempt to board the player's target. * * Creates the window on success. */ void player_board (void) { Pilot *p; unsigned int wdw; char c; HookParam hparam[2]; if (player.p->target==PLAYER_ID) { /* We don't try to find far away targets, only nearest and see if it matches. * However, perhaps looking for first boardable target within a certain range * could be more interesting. */ player_targetNearest(); p = pilot_get(player.p->target); if ((!pilot_isDisabled(p) && !pilot_isFlag(p,PILOT_BOARDABLE)) || pilot_isFlag(p,PILOT_NOBOARD)) { player_targetClear(); player_message("\erYou need a target to board first!"); return; }
/** * @brief Weapon hit the pilot. * * @param w Weapon involved in the collision. * @param p Pilot that got hit. * @param layer Layer to which the weapon belongs. * @param pos Position of the hit. */ static void weapon_hit( Weapon* w, Pilot* p, WeaponLayer layer, Vector2d* pos ) { Pilot *parent; int spfx; double damage; DamageType dtype; WeaponLayer spfx_layer; int s; /* Get general details. */ parent = pilot_get(w->parent); damage = w->strength * outfit_damage(w->outfit); dtype = outfit_damageType(w->outfit); /* Play sound if they have it. */ s = outfit_soundHit(w->outfit); if (s != -1) w->voice = sound_playPos( s, w->solid->pos.x, w->solid->pos.y, w->solid->vel.x, w->solid->vel.y); /* Have pilot take damage and get real damage done. */ damage = pilot_hit( p, w->solid, w->parent, dtype, damage ); /* Get the layer. */ spfx_layer = (p==player) ? SPFX_LAYER_FRONT : SPFX_LAYER_BACK; /* Choose spfx. */ if (p->shield > 0.) spfx = outfit_spfxShield(w->outfit); else spfx = outfit_spfxArmour(w->outfit); /* Add sprite, layer depends on whether player shot or not. */ spfx_add( spfx, pos->x, pos->y, VX(p->solid->vel), VY(p->solid->vel), spfx_layer ); /* Inform AI that it's been hit. */ weapon_hitAI( p, parent, damage ); /* no need for the weapon particle anymore */ weapon_destroy(w,layer); }
/** * @brief Gets the pilot's current name. * * @usage name = p:name() * * @luaparam p Pilot to get the name of. * @luareturn The current name of the pilot. * @luafunc name( p ) */ static int pilotL_name( lua_State *L ) { LuaPilot *p1; Pilot *p; /* Parse parameters. */ p1 = luaL_checkpilot(L,1); p = pilot_get( p1->pilot ); /* Pilot must exist. */ if (p == NULL) { NLUA_ERROR(L,"Pilot is invalid."); return 0; } /* Get name. */ lua_pushstring(L, p->name); return 1; }