naev 0.11.5
nlua_pilotoutfit.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
10#include <lauxlib.h>
11
12#include "naev.h"
15#include "nlua_pilotoutfit.h"
16
17#include "array.h"
18#include "log.h"
19#include "nlua_asteroid.h"
20#include "nlua_outfit.h"
21#include "nlua_pilot.h"
22#include "nlua_munition.h"
23#include "nlua_vec2.h"
24#include "nluadef.h"
25#include "slots.h"
26#include "weapon.h"
27
28int pilotoutfit_modified = 0;
29
30/* Pilot outfit metatable methods. */
31static int poL_slot( lua_State *L );
32static int poL_outfit( lua_State *L );
33static int poL_state( lua_State *L );
34static int poL_progress( lua_State *L );
35static int poL_set( lua_State *L );
36static int poL_clear( lua_State *L );
37static int poL_munition( lua_State *L );
38static int poL_shoot( lua_State *L );
39static int poL_heat( lua_State *L );
40static int poL_heatup( lua_State *L );
41static const luaL_Reg poL_methods[] = {
42 { "slot", poL_slot },
43 { "outfit", poL_outfit },
44 { "state", poL_state },
45 { "progress", poL_progress },
46 { "set", poL_set },
47 { "clear", poL_clear },
48 { "munition", poL_munition },
49 { "shoot", poL_shoot },
50 { "heat", poL_heat },
51 { "heatup", poL_heatup },
52 {0,0}
53};
61int nlua_loadPilotOutfit( nlua_env env )
62{
63 nlua_register(env, PILOTOUTFIT_METATABLE, poL_methods, 1);
64 return 0;
65}
66
79PilotOutfitSlot* lua_topilotoutfit( lua_State *L, int ind )
80{
81 return *((PilotOutfitSlot**) lua_touserdata(L,ind));
82}
90PilotOutfitSlot* luaL_checkpilotoutfit( lua_State *L, int ind )
91{
92 if (lua_ispilotoutfit(L,ind))
93 return lua_topilotoutfit(L,ind);
94 luaL_typerror(L, ind, PILOTOUTFIT_METATABLE);
95 return NULL;
96}
104PilotOutfitSlot* luaL_validpilotoutfit( lua_State *L, int ind )
105{
107
108 if (lua_ispilotoutfit(L, ind))
109 o = luaL_checkpilotoutfit(L,ind);
110 else {
111 luaL_typerror(L, ind, PILOTOUTFIT_METATABLE);
112 return NULL;
113 }
114
115 if (o == NULL)
116 NLUA_ERROR(L, _("Pilot Outfit is invalid."));
117
118 return o;
119}
128{
129 PilotOutfitSlot **lpo = (PilotOutfitSlot**) lua_newuserdata(L, sizeof(PilotOutfitSlot*));
130 *lpo = po;
131 luaL_getmetatable(L, PILOTOUTFIT_METATABLE);
132 lua_setmetatable(L, -2);
133 return lpo;
134}
142int lua_ispilotoutfit( lua_State *L, int ind )
143{
144 int ret;
145
146 if (lua_getmetatable(L,ind)==0)
147 return 0;
148 lua_getfield(L, LUA_REGISTRYINDEX, PILOTOUTFIT_METATABLE);
149
150 ret = 0;
151 if (lua_rawequal(L, -1, -2)) /* does it have the correct mt? */
152 ret = 1;
153
154 lua_pop(L, 2); /* remove both metatables */
155 return ret;
156}
157
166static int poL_slot( lua_State *L )
167{
169 const ShipOutfitSlot *sslot = po->sslot;
170 const OutfitSlot *slot = &sslot->slot;
171
172 /* make the slot table and put it in */
173 lua_newtable(L);
174
175 lua_pushstring(L, "type"); /* key */
176 lua_pushstring(L, slotName( slot->type )); /* value */
177 lua_rawset(L, -3); /* table[key = value ]*/
178
179 lua_pushstring(L, "size"); /* key */
180 lua_pushstring(L, slotSize(slot->size) );
181 lua_rawset(L, -3); /* table[key] = value */
182
183 lua_pushstring(L, "property"); /* key */
184 lua_pushstring( L, sp_display(slot->spid)); /* value */
185 lua_rawset(L, -3); /* table[key] = value */
186
187 lua_pushstring(L, "required"); /* key */
188 lua_pushboolean( L, sslot->required); /* value */
189 lua_rawset(L, -3); /* table[key] = value */
190
191 lua_pushstring(L, "exclusive"); /* key */
192 lua_pushboolean( L, sslot->exclusive); /* value */
193 lua_rawset(L, -3); /* table[key] = value */
194
195 lua_pushstring(L, "locked"); /* key */
196 lua_pushboolean( L, sslot->locked); /* value */
197 lua_rawset(L, -3); /* table[key] = value */
198
199 return 1;
200}
201
209static int poL_outfit( lua_State *L )
210{
211 const PilotOutfitSlot *po = luaL_validpilotoutfit(L,1);
212 lua_pushoutfit(L, po->outfit );
213 return 1;
214}
215
223static int poL_state( lua_State *L )
224{
226 const char *state = luaL_optstring(L,2,NULL);
227 PilotOutfitState pos = po->state;
228
229 if (!outfit_isMod( po->outfit ))
230 return NLUA_ERROR( L, _("'pilotoutfit.%s' only works with modifier outfits!"), "state");
231
232 if (state==NULL || strcmp(state,"off")==0)
233 po->state = PILOT_OUTFIT_OFF;
234 else if (strcmp(state,"warmup")==0)
235 po->state = PILOT_OUTFIT_WARMUP;
236 else if (strcmp(state,"on")==0)
237 po->state = PILOT_OUTFIT_ON;
238 else if (strcmp(state,"cooldown")==0)
239 po->state = PILOT_OUTFIT_COOLDOWN;
240 else
241 return NLUA_ERROR( L, _("Unknown PilotOutfit state '%s'!"), state );
242
243 /* Mark as modified if state changed. */
244 if (pos != po->state)
245 pilotoutfit_modified = 1;
246
247 return 0;
248}
249
257static int poL_progress( lua_State *L )
258{
260
261 if (!outfit_isMod( po->outfit ))
262 return NLUA_ERROR( L, _("'pilotoutfit.%s' only works with modifier outfits!"), "progress");
263
264 po->progress = CLAMP( 0., 1., luaL_checknumber(L,2) );
265 return 0;
266}
267
276static int poL_set( lua_State *L )
277{
279 const char *name = luaL_checkstring(L,2);
280 double value = luaL_checknumber(L,3);
281 po->lua_stats = ss_statsSetList( po->lua_stats, ss_typeFromName(name), value, 1, 0 );
282 pilotoutfit_modified = 1;
283 return 0;
284}
285
292static int poL_clear( lua_State *L )
293{
295 ss_free( po->lua_stats );
296 po->lua_stats = NULL;
297 pilotoutfit_modified = 1;
298 return 0;
299}
300
301static Target lua_totarget( lua_State *L, int idx )
302{
303 Target t;
304 /* Handle target. */
305 if (lua_isnoneornil(L,idx))
306 t.type = TARGET_NONE;
307 else if (lua_ispilot(L,idx)) {
308 t.type = TARGET_PILOT;
309 t.u.id = lua_topilot(L,idx);
310 }
311 else if (lua_isasteroid(L,idx)) {
312 const LuaAsteroid_t *ast = lua_toasteroid(L,idx);
313 t.type = TARGET_ASTEROID;
314 t.u.ast.anchor = ast->parent;
315 t.u.ast.asteroid = ast->id;
316 }
317 else if (lua_ismunition(L,idx)) {
318 const LuaMunition *lm = lua_tomunition(L,idx);
319 t.type = TARGET_WEAPON;
320 t.u.id = lm->id;
321 }
322 else {
323 NLUA_INVALID_PARAMETER_NORET(L,idx);
324 t.type = TARGET_NONE;
325 }
326 return t;
327}
328
343static int poL_munition( lua_State *L )
344{
346 Pilot *p = luaL_validpilot( L, 2 );
347 const Outfit *o= luaL_optoutfit( L, 3, po->outfit );
348 Target t = lua_totarget( L, 4 );
349 double dir = luaL_optnumber( L, 5, p->solid.dir );
350 const vec2 *vp = luaL_optvector( L, 6, &p->solid.pos );
351 const vec2 *vv = luaL_optvector( L, 7, &p->solid.vel );
352 int noaim = lua_toboolean( L, 8 );
353 const Weapon *w = weapon_add( po, o, dir, vp, vv, p, &t, 0., !noaim );
354 lua_pushmunition( L, w );
355 return 1;
356}
357
368static int poL_shoot( lua_State *L )
369{
371 Pilot *p = luaL_validpilot( L, 2 );
372 Target t = lua_totarget( L, 3 );
373 int stagger = lua_toboolean( L, 4 );
374 double time;
375 int ret;
376 int has_ammo;
377
378 /* The particular weapon can't fire, so ignore. */
379 if (po->timer > 0.) {
380 lua_pushboolean(L,0);
381 return 1;
382 }
383
384 /* Out of ammo. */
385 has_ammo = outfit_isLauncher(po->outfit) || outfit_isFighterBay(po->outfit);
386 if (has_ammo && (po->u.ammo.quantity <= 0)) {
387 lua_pushboolean(L,0);
388 return 1;
389 }
390
391 /* See if we should stagger the outfits. */
392 if (stagger) {
393 double q, maxt, rate_mod, energy_mod;
394 int maxp, minh;
395
396 /* Calculate rate modifier. */
397 pilot_getRateMod( &rate_mod, &energy_mod, p, po->outfit );
398
399 /* Find optimal outfit, coolest that can fire. */
400 minh = -1;
401 maxt = 0.;
402 maxp = -1;
403 q = 0.;
404 for (int i=0; i<array_size(p->outfits); i++) {
405 PilotOutfitSlot *pos = p->outfits[i];
406 if (pos->outfit != po->outfit)
407 continue;
408 /* Launcher only counts with ammo. */
409 if (has_ammo && (pos->u.ammo.quantity <= 0))
410 continue;
411 /* Get coolest that can fire. */
412 if (pos->timer <= 0.) {
413 if (has_ammo) {
414 if ((minh < 0) || (p->outfits[ minh ]->u.ammo.quantity < pos->u.ammo.quantity))
415 minh = i;
416 }
417 else {
418 if ((minh < 0) || (p->outfits[ minh ]->heat_T > pos->heat_T))
419 minh = i;
420 }
421 }
422
423 /* Save some stuff. */
424 if ((maxp < 0) || (pos->timer > maxt)) {
425 maxp = i;
426 maxt = pos->timer;
427 }
428 q += 1.;
429 }
430
431 /* Only fire if the last weapon to fire fired more than (q-1)/q ago. */
432 if ((minh < 0) || (maxt > rate_mod * outfit_delay(po->outfit) * ((q-1.) / q))) {
433 lua_pushboolean(L,0);
434 return 1;
435 }
436 }
437
438 time = weapon_targetFlyTime( po->outfit, p, &t );
439 ret = pilot_shootWeapon( p, po, &t, time, -1 );
440
441 lua_pushboolean( L, ret );
442 return 1;
443}
444
453static int poL_heat( lua_State *L )
454{
456 if (lua_isboolean(L,2))
457 lua_pushnumber( L, po->heat_T );
458 else
459 lua_pushnumber( L, pilot_heatEfficiencyMod(po->heat_T, po->outfit->overheat_min, po->outfit->overheat_max) );
460 return 1;
461}
462
476static int poL_heatup( lua_State *L )
477{
479 double heat = luaL_checknumber( L, 2 );
480 po->heat_T += heat / po->heat_C;
481 /* Enforce a minimum value as a safety measure. */
482 po->heat_T = MAX( po->heat_T, CONST_SPACE_STAR_TEMP );
483 return 0;
484}
Provides macros to work with dynamic arrays.
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
Definition array.h:168
Header file with generic functions and naev-specifics.
#define CLAMP(a, b, x)
Definition naev.h:41
#define MAX(x, y)
Definition naev.h:39
int lua_isasteroid(lua_State *L, int ind)
Checks to see if ind is a asteroid.
LuaAsteroid_t * lua_toasteroid(lua_State *L, int ind)
Gets asteroid at index.
int lua_ismunition(lua_State *L, int ind)
Checks to see if ind is a munition.
LuaMunition * lua_tomunition(lua_State *L, int ind)
Lua bindings to interact with munitions.
LuaMunition * lua_pushmunition(lua_State *L, const Weapon *w)
Pushes a weapon as a munition on the stack.
const Outfit ** lua_pushoutfit(lua_State *L, const Outfit *outfit)
Pushes a outfit on the stack.
LuaPilot lua_topilot(lua_State *L, int ind)
Lua bindings to interact with pilots.
Definition nlua_pilot.c:522
Pilot * luaL_validpilot(lua_State *L, int ind)
Makes sure the pilot is valid or raises a Lua error.
Definition nlua_pilot.c:547
int lua_ispilot(lua_State *L, int ind)
Checks to see if ind is a pilot.
Definition nlua_pilot.c:578
static const luaL_Reg poL_methods[]
int nlua_loadPilotOutfit(nlua_env env)
Loads the pilot outfit library.
PilotOutfitSlot * luaL_validpilotoutfit(lua_State *L, int ind)
Makes sure the outfit is valid or raises a Lua error.
static int poL_progress(lua_State *L)
Sets the state progress of the PilotOutfit.
static int poL_heat(lua_State *L)
Gets the heat status of the pilot outfit.
PilotOutfitSlot * luaL_checkpilotoutfit(lua_State *L, int ind)
Gets outfit at index or raises error if there is no outfit at index.
static int poL_munition(lua_State *L)
Creates a munition.
PilotOutfitSlot ** lua_pushpilotoutfit(lua_State *L, PilotOutfitSlot *po)
Pushes a pilot outfit on the stack.
static int poL_set(lua_State *L)
Sets a temporary ship stat modifier of the pilot outfit.
static int poL_outfit(lua_State *L)
Gets the outfit of the PilotOutfit.
PilotOutfitSlot * lua_topilotoutfit(lua_State *L, int ind)
Lua bindings to interact with pilot outfits.
static int poL_heatup(lua_State *L)
Heats up a pilot outfit.
int lua_ispilotoutfit(lua_State *L, int ind)
Checks to see if ind is a pilot outfit.
static int poL_shoot(lua_State *L)
Shoots at an object.
static int poL_state(lua_State *L)
Sets the state of the PilotOutfit.
static int poL_clear(lua_State *L)
Clears all the temporary ship stat modifiers of the pilot outfit.
static int poL_slot(lua_State *L)
Gets the properties of the outfit slot.
int outfit_isLauncher(const Outfit *o)
Checks if outfit is a weapon launcher.
Definition outfit.c:564
int outfit_isFighterBay(const Outfit *o)
Checks if outfit is a fighter bay.
Definition outfit.c:616
const char * slotName(const OutfitSlotType type)
Definition outfit.c:335
int outfit_isMod(const Outfit *o)
Checks if outfit is a ship modification.
Definition outfit.c:598
const char * slotSize(const OutfitSlotSize o)
Gets the slot size as a string.
Definition outfit.c:358
double outfit_delay(const Outfit *o)
Gets the outfit's delay.
Definition outfit.c:734
double pilot_heatEfficiencyMod(double T, double Tb, double Tc)
Returns a 0:1 modifier representing efficiency (1. being normal).
Definition pilot_heat.c:235
void pilot_getRateMod(double *rate_mod, double *energy_mod, const Pilot *p, const Outfit *o)
Gets applicable fire rate and energy modifications for a pilot's weapon.
int pilot_shootWeapon(Pilot *p, PilotOutfitSlot *w, const Target *target, double time, int aim)
Actually handles the shooting, how often the player.p can shoot and such.
void ss_free(ShipStatList *ll)
Frees a list of ship stats.
Definition shipstats.c:887
ShipStatsType ss_typeFromName(const char *name)
Gets the type from the name.
Definition shipstats.c:685
const char * sp_display(unsigned int spid)
Gets the display name of a slot property (in English).
Definition slots.c:159
Lua Munition wrapper.
unsigned int id
Pilot slot that can contain outfits.
Definition outfit.h:109
OutfitSlotSize size
Definition outfit.h:113
unsigned int spid
Definition outfit.h:110
OutfitSlotType type
Definition outfit.h:112
A ship outfit, depends radically on the type.
Definition outfit.h:328
double overheat_max
Definition outfit.h:358
double overheat_min
Definition outfit.h:357
Stores an outfit the pilot has.
Definition pilot.h:108
PilotOutfitAmmo ammo
Definition pilot.h:135
double heat_C
Definition pilot.h:118
double heat_T
Definition pilot.h:117
double progress
Definition pilot.h:127
PilotOutfitState state
Definition pilot.h:123
ShipStatList * lua_stats
Definition pilot.h:140
double timer
Definition pilot.h:125
ShipOutfitSlot * sslot
Definition pilot.h:114
const Outfit * outfit
Definition pilot.h:112
The representation of an in-game pilot.
Definition pilot.h:217
Ship outfit slot.
Definition ship.h:70
int exclusive
Definition ship.h:73
int required
Definition ship.h:74
OutfitSlot slot
Definition ship.h:71
int locked
Definition ship.h:75
Represents a weapon target.
Definition target.h:19
In-game representation of a weapon.
Definition weapon.h:47
Represents a 2d vector.
Definition vec2.h:32
double weapon_targetFlyTime(const Outfit *o, const Pilot *p, const Target *t)
Gets the fly time for a weapon target.
Definition weapon.c:2538
Weapon * weapon_add(PilotOutfitSlot *po, const Outfit *ref, double dir, const vec2 *pos, const vec2 *vel, const Pilot *parent, const Target *target, double time, int aim)
Creates a new weapon.
Definition weapon.c:2511