Beispiel #1
0
/**
 * @brief Finishes the mission.
 *
 *    @luaparam properly If true and the mission is unique it marks the mission
 *                     as completed.  If false it deletes the mission but
 *                     doesn't mark it as completed.  If the parameter isn't
 *                     passed it just ends the mission (without removing it
 *                     from the player's list of active missions).
 * @luafunc finish( properly )
 */
static int misn_finish( lua_State *L )
{
   int b;
   Mission *cur_mission;

   if (lua_isboolean(L,1))
      b = lua_toboolean(L,1);
   else {
      lua_pushstring(L, NLUA_DONE);
      lua_error(L); /* THERE IS NO RETURN */
      return 0;
   }

   lua_pushboolean( L, 1 );
   lua_setglobal( L, "__misn_delete" );
   cur_mission = misn_getFromLua(L);

   if (b && mis_isFlag(cur_mission->data,MISSION_UNIQUE))
      player_missionFinished( mission_getID( cur_mission->data->name ) );

   lua_pushstring(L, NLUA_DONE);
   lua_error(L); /* shouldn't return */

   return 0;
}
Beispiel #2
0
/**
 * @brief Adds some mission cargo to the player.  He cannot sell it nor get rid of it
 *  unless he abandons the mission in which case it'll get eliminated.
 *
 *    @luaparam cargo Name of the cargo to add.
 *    @luaparam quantity Quantity of cargo to add.
 *    @luareturn The id of the cargo which can be used in cargoRm.
 * @luafunc cargoAdd( cargo, quantity )
 */
static int misn_cargoAdd( lua_State *L )
{
   const char *cname;
   Commodity *cargo;
   int quantity, ret;
   Mission *cur_mission;

   /* Parameters. */
   cname    = luaL_checkstring(L,1);
   quantity = luaL_checkint(L,2);
   cargo = commodity_get( cname );

   /* Check if the cargo exists. */
   if(cargo == NULL) {
      NLUA_ERROR(L, "Cargo '%s' not found.", cname);
      return 0;
   }

   cur_mission = misn_getFromLua(L);

   /* First try to add the cargo. */
   ret = pilot_addMissionCargo( player.p, cargo, quantity );
   mission_linkCargo( cur_mission, ret );

   lua_pushnumber(L, ret);
   return 1;
}
Beispiel #3
0
/**
 * @brief Adds an NPC.
 *
 * @note Do not use this at all in the "create" function. Use setNPC, setDesc and the "accept" function instead.
 *
 * @usage npc_id = misn.npcAdd( "my_func", "Mr. Test", "none", "A test." ) -- Creates an NPC.
 *
 *    @luaparam func Name of the function to run when approaching, gets passed the npc_id when called.
 *    @luaparam name Name of the NPC
 *    @luaparam portrait Portrait to use for the NPC (from gfx/portraits*.png).
 *    @luaparam desc Description associated to the NPC.
 *    @luaparam priority Optional priority argument (defaults to 5, highest is 0, lowest is 10).
 *    @luareturn The ID of the NPC to pass to npcRm.
 * @luafunc npcAdd( func, name, portrait, desc, priority )
 */
static int misn_npcAdd( lua_State *L )
{
   unsigned int id;
   int priority;
   const char *func, *name, *gfx, *desc;
   char portrait[PATH_MAX];
   Mission *cur_mission;

   /* Handle parameters. */
   func = luaL_checkstring(L, 1);
   name = luaL_checkstring(L, 2);
   gfx  = luaL_checkstring(L, 3);
   desc = luaL_checkstring(L, 4);

   /* Optional priority. */
   if (lua_gettop(L) > 4)
      priority = luaL_checkint( L, 5 );
   else
      priority = 5;

   /* Set path. */
   nsnprintf( portrait, PATH_MAX, "gfx/portraits/%s.png", gfx );

   cur_mission = misn_getFromLua(L);

   /* Add npc. */
   id = npc_add_mission( cur_mission, func, name, priority, portrait, desc );

   /* Return ID. */
   if (id > 0) {
      lua_pushnumber( L, id );
      return 1;
   }
   return 0;
}
Beispiel #4
0
/**
 * @brief Attempts to accept the mission.
 *
 * @usage if not misn.accept() then return end
 *    @luareturn true if mission was properly accepted.
 * @luafunc accept()
 */
static int misn_accept( lua_State *L )
{
   int i, ret;
   Mission *cur_mission;

   ret = 0;

   /* find last mission */
   for (i=0; i<MISSION_MAX; i++)
      if (player_missions[i].data == NULL)
         break;

   cur_mission = misn_getFromLua(L);

   /* no missions left */
   if (i>=MISSION_MAX)
      ret = 1;
   else { /* copy it over */
      memcpy( &player_missions[i], cur_mission, sizeof(Mission) );
      memset( cur_mission, 0, sizeof(Mission) );
      cur_mission = &player_missions[i];
      cur_mission->accepted = 1; /* Mark as accepted. */

      /* Need to change pointer. */
      lua_pushlightuserdata(L,cur_mission);
      lua_setglobal(L,"__misn");
   }

   lua_pushboolean(L,!ret); /* we'll convert C style return to Lua */
   return 1;
}
Beispiel #5
0
/**
 * @brief Creates a mission OSD.
 *
 * @note You can index elements by using '\t' as first character of an element.
 *
 * @usage misn.osdCreate( "My OSD", {"Element 1", "Element 2"})
 *
 *    @luaparam title Title to give the OSD.
 *    @luaparam list List of elements to put in the OSD.
 * @luafunc osdCreate( title, list )
 */
static int misn_osdCreate( lua_State *L )
{
   const char *title;
   int nitems;
   char **items;
   int i;
   Mission *cur_mission;

   cur_mission = misn_getFromLua(L);

   /* Must be accepted. */
   if (!cur_mission->accepted) {
      WARN("Can't create an OSD on an unaccepted mission!");
      return 0;
   }

   /* Check parameters. */
   title  = luaL_checkstring(L,1);
   luaL_checktype(L,2,LUA_TTABLE);
   nitems = lua_objlen(L,2);

   /* Destroy OSD if already exists. */
   if (cur_mission->osd != 0) {
      osd_destroy( cur_mission->osd );
      cur_mission->osd = 0;
   }

   /* Allocate items. */
   items = calloc( nitems, sizeof(char *) );

   /* Get items. */
   for (i=0; i<nitems; i++) {
      lua_pushnumber(L,i+1);
      lua_gettable(L,2);
      if (!lua_isstring(L,-1)) {
         free(items);
         luaL_typerror(L, -1, "string");
         return 0;
      }
      items[i] = strdup( lua_tostring(L, -1) );
      lua_pop(L,1);
   }

   /* Create OSD. */
   cur_mission->osd = osd_create( title, nitems, (const char**) items,
         cur_mission->data->avail.priority );
   cur_mission->osd_set = 1; /* OSD was explicitly set. */

   /* Free items. */
   for (i=0; i<nitems; i++)
      free(items[i]);
   free(items);

   return 0;
}
Beispiel #6
0
/**
 * @brief Runs a mission set up with misn_runStart.
 *
 *    @param misn Mission that owns the function.
 *    @param func Name of the function to call.
 *    @return -1 on error, 1 on misn.finish() call, 2 if mission got deleted
 *            and 0 normally.
 */
int misn_runFunc( Mission *misn, const char *func, int nargs )
{
   int i, ret, errf;
   const char* err;
   lua_State *L;
   int misn_delete;
   Mission *cur_mission;

   /* For comfort. */
   L = misn->L;

#if DEBUGGING
   errf = -2-nargs;
#else /* DEBUGGING */
   errf = 0;
#endif /* DEBUGGING */

   ret = lua_pcall(L, nargs, 0, errf);
   cur_mission = misn_getFromLua(L); /* The mission can change if accepted. */
   if (ret != 0) { /* error has occurred */
      err = (lua_isstring(L,-1)) ? lua_tostring(L,-1) : NULL;
      if ((err==NULL) || (strcmp(err,NLUA_DONE)!=0)) {
         WARN("Mission '%s' -> '%s': %s",
               cur_mission->data->name, func, (err) ? err : "unknown error");
         ret = -1;
      }
      else
         ret = 1;
      lua_pop(L,1);
   }
#if DEBUGGING
   lua_pop(L,1);
#endif /* DEBUGGING */

   /* Get delete. */
   lua_getglobal(L,"__misn_delete");
   misn_delete = lua_toboolean(L,-1);
   lua_pop(L,1);

   /* mission is finished */
   if (misn_delete) {
      ret = 2;
      mission_cleanup( cur_mission );
      for (i=0; i<MISSION_MAX; i++)
         if (cur_mission == &player_missions[i]) {
            memmove( &player_missions[i], &player_missions[i+1],
                  sizeof(Mission) * (MISSION_MAX-i-1) );
            memset( &player_missions[MISSION_MAX-1], 0, sizeof(Mission) );
            break;
         }
   }

   return ret;
}
Beispiel #7
0
/**
 * @brief Creates a mission hook to a certain stack.
 *
 * Basically a generic approach to hooking.
 *
 *    @param L Lua state.
 *    @param stack Stack to put the hook in.
 *    @param ms Milliseconds to delay (pass stack as NULL to set as timer).
 *    @param pos Position in the stack of the function name.
 *    @return The hook ID or 0 on error.
 */
static unsigned int hook_generic( lua_State *L, const char* stack, double ms, int pos, ntime_t date )
{
   int i;
   const char *func;
   unsigned int h;
   Event_t *running_event;
   Mission *running_mission;

   /* Last parameter must be function to hook */
   func = luaL_checkstring(L,pos);

   /* Get stuff. */
   running_event = event_getFromLua(L);
   running_mission = misn_getFromLua(L);

   h = 0;
   if (running_mission != NULL) {
      /* make sure mission is a player mission */
      for (i=0; i<MISSION_MAX; i++)
         if (player_missions[i].id == running_mission->id)
            break;
      if (i>=MISSION_MAX) {
         WARN("Mission not in stack trying to hook, forgot to run misn.accept()?");
         return 0;
      }

      if (stack != NULL)
         h = hook_addMisn( running_mission->id, func, stack );
      else if (date != 0)
         h = hook_addDateMisn( running_mission->id, func, date );
      else
         h = hook_addTimerMisn( running_mission->id, func, ms );
   }
   else if (running_event != NULL) {
      if (stack != NULL)
         h = hook_addEvent( running_event->id, func, stack );
      else if (date != 0)
         h = hook_addDateEvt( running_event->id, func, date );
      else
         h = hook_addTimerEvt( running_event->id, func, ms );
   }

   if (h == 0) {
      NLUA_ERROR(L,"No hook target was set.");
      return 0;
   }

   /* Check parameter. */
   if (!lua_isnil(L,pos+1))
      hookL_setarg( L, h, pos+1 );

   return h;
}
Beispiel #8
0
/**
 * @brief Destroys the mission OSD.
 *
 * @luafunc osdDestroy()
 */
static int misn_osdDestroy( lua_State *L )
{
   Mission *cur_mission;
   cur_mission = misn_getFromLua(L);

   if (cur_mission->osd != 0) {
      osd_destroy( cur_mission->osd );
      cur_mission->osd = 0;
   }

   return 0;
}
Beispiel #9
0
/**
 * @brief Tries to claim systems.
 *
 * Claiming systems is a way to avoid mission collisions preemptively.
 *
 * Note it does not actually claim the systems if it fails to claim. It also
 *  does not work more then once.
 *
 * @usage if not misn.claim( { system.get("Gamma Polaris") } ) then misn.finish( false ) end
 * @usage if not misn.claim( system.get("Gamma Polaris") ) then misn.finish( false ) end
 *
 *    @luaparam systems Table of systems to claim or a single system.
 *    @luareturn true if was able to claim, false otherwise.
 * @luafunc claim( systems )
 */
static int misn_claim( lua_State *L )
{
   int i, l;
   LuaSystem *ls;
   SysClaim_t *claim;
   Mission *cur_mission;

   /* Get mission. */
   cur_mission = misn_getFromLua(L);

   /* Check to see if already claimed. */
   if (cur_mission->claims != NULL) {
      NLUA_ERROR(L, "Mission trying to claim but already has.");
      return 0;
   }

   /* Create the claim. */
   claim = claim_create();

   if (lua_istable(L,1)) {
      /* Iterate over table. */
      l = lua_objlen(L,1);
      for (i=0; i<l; i++) {
         lua_pushnumber(L,i+1);
         lua_gettable(L,1);
         if (lua_issystem(L,-1)) {
            ls = lua_tosystem( L, -1 );
            claim_add( claim, ls->id );
         }
         lua_pop(L,1);
      }
   }
   else if (lua_issystem(L, 1)) {
      ls = lua_tosystem( L, 1 );
      claim_add( claim, ls->id );
   }
   else
      NLUA_INVALID_PARAMETER(L);

   /* Test claim. */
   if (claim_test( claim )) {
      claim_destroy( claim );
      lua_pushboolean(L,0);
      return 1;
   }

   /* Set the claim. */
   cur_mission->claims = claim;
   claim_activate( claim );
   lua_pushboolean(L,1);
   return 1;
}
Beispiel #10
0
/**
 * @brief Sets the current mission reward description.
 *
 *    @luaparam reward Description of the reward to use.
 * @luafunc setReward( reward )
 */
static int misn_setReward( lua_State *L )
{
   const char *str;
   Mission *cur_mission;

   str = luaL_checkstring(L,1);

   cur_mission = misn_getFromLua(L);
   if (cur_mission->reward) /* cleanup old reward */
      free(cur_mission->reward);
   cur_mission->reward = strdup(str);
   return 0;
}
Beispiel #11
0
/**
 * @brief Removes an NPC.
 *
 * @usage misn.npcRm( npc_id )
 *
 *    @luaparam id ID of the NPC to remove.
 * @luafunc npcRm( id )
 */
static int misn_npcRm( lua_State *L )
{
   unsigned int id;
   int ret;
   Mission *cur_mission;

   id = luaL_checklong(L, 1);
   cur_mission = misn_getFromLua(L);
   ret = npc_rm_mission( id, cur_mission );

   if (ret != 0)
      NLUA_ERROR(L, "Invalid NPC ID!");
   return 0;
}
Beispiel #12
0
/**
 * @brief Sets the current mission title.
 *
 *    @luaparam title Title to use for mission.
 * @luafunc setTitle( title )
 */
static int misn_setTitle( lua_State *L )
{
   const char *str;
   Mission *cur_mission;

   str = luaL_checkstring(L,1);

   cur_mission = misn_getFromLua(L);
   if (cur_mission->title) /* cleanup old title */
      free(cur_mission->title);
   cur_mission->title = strdup(str);

   return 0;
}
Beispiel #13
0
/**
 * @brief Sets the current mission description.
 *
 * Also sets the mission OSD unless you explicitly force an OSD, however you
 *  can't specify bullet points or other fancy things like with the real OSD.
 *
 *    @luaparam desc Description to use for mission.
 * @luafunc setDesc( desc )
 */
static int misn_setDesc( lua_State *L )
{
   const char *str;
   Mission *cur_mission;

   str = luaL_checkstring(L,1);

   cur_mission = misn_getFromLua(L);
   if (cur_mission->desc) /* cleanup old description */
      free(cur_mission->desc);
   cur_mission->desc = strdup(str);

   return 0;
}
Beispiel #14
0
/**
 * @brief Sets active in mission OSD.
 *
 * @note Uses Lua indexes, so 1 is first member, 2 is second and so on.
 *
 *    @luaparam n Element of the OSD to make active.
 * @luafunc osdActive( n )
 */
static int misn_osdActive( lua_State *L )
{
   int n;
   Mission *cur_mission;

   n = luaL_checkint(L,1);
   n = n-1; /* Convert to C index. */

   cur_mission = misn_getFromLua(L);

   if (cur_mission->osd != 0)
      osd_active( cur_mission->osd, n );

   return 0;
}
Beispiel #15
0
/**
 * @brief Gets the factions the mission is available for.
 *
 * @usage f = misn.factions()
 *    @luareturn A containing the factions for whom the mission is available.
 * @luafunc factions()
 */
static int misn_factions( lua_State *L )
{
   int i;
   MissionData *dat;
   LuaFaction f;
   Mission *cur_mission;

   cur_mission = misn_getFromLua(L);
   dat = cur_mission->data;

   /* we'll push all the factions in table form */
   lua_newtable(L);
   for (i=0; i<dat->avail.nfactions; i++) {
      lua_pushnumber(L,i+1); /* index, starts with 1 */
      f.f = dat->avail.factions[i];
      lua_pushfaction(L, f); /* value */
      lua_rawset(L,-3); /* store the value in the table */
   }
   return 1;
}
Beispiel #16
0
/**
 * @brief Moves a marker to a new system.
 *
 * @usage misn.markerMove( my_marker, system.get("Delta Pavonis") )
 *
 *    @luaparam id ID of the mission marker to move.
 *    @luaparam sys System to move the marker to.
 * @luafunc markerMove( id, sys )
 */
static int misn_markerMove( lua_State *L )
{
   int id;
   LuaSystem *sys;
   MissionMarker *marker;
   int i, n;
   Mission *cur_mission;

   /* Handle parameters. */
   id    = luaL_checkinteger( L, 1 );
   sys   = luaL_checksystem( L, 2 );

   cur_mission = misn_getFromLua(L);

   /* Mission must have markers. */
   if (cur_mission->markers == NULL) {
      NLUA_ERROR( L, "Mission has no markers set!" );
      return 0;
   }

   /* Check id. */
   marker = NULL;
   n = array_size( cur_mission->markers );
   for (i=0; i<n; i++) {
      if (id == cur_mission->markers[i].id) {
         marker = &cur_mission->markers[i];
         break;
      }
   }
   if (marker == NULL) {
      NLUA_ERROR( L, "Mission does not have a marker with id '%d'", id );
      return 0;
   }

   /* Update system. */
   marker->sys = sys->id;

   /* Update system markers. */
   mission_sysMark();
   return 0;
}
Beispiel #17
0
/**
 * @brief Jettisons the mission cargo.
 *
 *    @luaparam cargoid ID of the cargo to jettison.
 *    @luareturn true on success.
 * @luafunc cargoJet( cargoid )
 */
static int misn_cargoJet( lua_State *L )
{
   int ret;
   unsigned int id;
   Mission *cur_mission;

   id = luaL_checklong(L,1);

   /* First try to remove the cargo from player. */
   if (pilot_rmMissionCargo( player.p, id, 1 ) != 0) {
      lua_pushboolean(L,0);
      return 1;
   }

   cur_mission = misn_getFromLua(L);

   /* Now unlink the mission cargo if it was successful. */
   ret = mission_unlinkCargo( cur_mission, id );

   lua_pushboolean(L,!ret);
   return 1;
}
Beispiel #18
0
/**
 * @brief Removes a mission system marker.
 *
 * @usage misn.markerRm( my_marker )
 *
 *    @luaparam id ID of the marker to remove.
 * @luafunc markerRm( id )
 */
static int misn_markerRm( lua_State *L )
{
   int id;
   int i, n;
   MissionMarker *marker;
   Mission *cur_mission;

   /* Handle parameters. */
   id    = luaL_checkinteger( L, 1 );

   cur_mission = misn_getFromLua(L);

   /* Mission must have markers. */
   if (cur_mission->markers == NULL) {
      /* Already removed. */
      return 0;
   }

   /* Check id. */
   marker = NULL;
   n = array_size( cur_mission->markers );
   for (i=0; i<n; i++) {
      if (id == cur_mission->markers[i].id) {
         marker = &cur_mission->markers[i];
         break;
      }
   }
   if (marker == NULL) {
      /* Already removed. */
      return 0;
   }

   /* Remove the marker. */
   array_erase( &cur_mission->markers, marker, &marker[1] );

   /* Update system markers. */
   mission_sysMark();
   return 0;
}
Beispiel #19
0
/**
 * @brief Adds a new marker.
 *
 * @usage my_marker = misn.markerAdd( system.get("Gamma Polaris"), "low" )
 *
 * Valid marker types are:<br/>
 *  - "plot": Important plot marker.<br/>
 *  - "high": High importance mission marker (lower than plot).<br/>
 *  - "low": Low importance mission marker (lower than high).<br/>
 *  - "computer": Mission computer marker.<br/>
 *
 *    @luaparam sys System to mark.
 *    @luaparam type Colouring scheme to use.
 *    @luareturn A marker ID to be used with markerMove and markerRm.
 * @luafunc markerAdd( sys, type )
 */
static int misn_markerAdd( lua_State *L )
{
   int id;
   LuaSystem *sys;
   const char *stype;
   SysMarker type;
   Mission *cur_mission;

   /* Check parameters. */
   sys   = luaL_checksystem( L, 1 );
   stype = luaL_checkstring( L, 2 );

   /* Handle types. */
   if (strcmp(stype, "computer")==0)
      type = SYSMARKER_COMPUTER;
   else if (strcmp(stype, "low")==0)
      type = SYSMARKER_LOW;
   else if (strcmp(stype, "high")==0)
      type = SYSMARKER_HIGH;
   else if (strcmp(stype, "plot")==0)
      type = SYSMARKER_PLOT;
   else {
      NLUA_ERROR(L, "Unknown marker type: %s", stype);
      return 0;
   }

   cur_mission = misn_getFromLua(L);

   /* Add the marker. */
   id = mission_addMarker( cur_mission, -1, sys->id, type );

   /* Update system markers. */
   mission_sysMark();

   /* Return the ID. */
   lua_pushnumber( L, id );
   return 1;
}
Beispiel #20
0
/**
 * @brief Sets the current mission NPC.
 *
 * This is used in bar missions where you talk to a person. The portraits are
 *  the ones found in gfx/portraits without the png extension. So for
 *  gfx/portraits/none.png you would just use "none".
 *
 * @usage misn.setNPC( "Invisible Man", "none" )
 *
 *    @luaparam name Name of the NPC.
 *    @luaparam portrait Name of the portrait to use for the NPC.
 * @luafunc setNPC( name, portrait )
 */
static int misn_setNPC( lua_State *L )
{
   char buf[PATH_MAX];
   const char *name, *str;
   Mission *cur_mission;

   cur_mission = misn_getFromLua(L);

   /* Free if portrait is already set. */
   if (cur_mission->portrait != NULL) {
      gl_freeTexture(cur_mission->portrait);
      cur_mission->portrait = NULL;
   }

   /* Free NPC name. */
   if (cur_mission->npc != NULL) {
      free(cur_mission->npc);
      cur_mission->npc = NULL;
   }

   /* For no parameters just leave having freed NPC. */
   if (lua_gettop(L) == 0)
      return 0;

   /* Get parameters. */
   name = luaL_checkstring(L,1);
   str  = luaL_checkstring(L,2);

   /* Set NPC name. */
   cur_mission->npc = strdup(name);

   /* Set portrait. */
   nsnprintf( buf, PATH_MAX, "gfx/portraits/%s.png", str );
   cur_mission->portrait = gl_newImage( buf, 0 );

   return 0;
}