diff --git a/scripts/ai/include/basic.lua b/scripts/ai/include/basic.lua index 8055a1f..46d89dc 100644 --- a/scripts/ai/include/basic.lua +++ b/scripts/ai/include/basic.lua @@ -17,18 +17,22 @@ function attack() return end - dir = ai.face(target) - dist = ai.dist(ai.pos(target)) - second = ai.secondary() + -- Get stats about enemy. + dir = ai.face(target) -- Face target. + dist = ai.dist(ai.pos(target)) -- Get distance. + second = ai.secondary() -- Get best secondary weapon. - if ai.secondary() == "Launcher" then + -- Shoot missiles if in range. + if ai.secondary() == "Launcher" and dist < ai.getweaprange(1) then ai.settarget(target) ai.shoot(2) end - if dir < 10 and dist > 300 then + -- Attack if in range. + range = ai.getweaprange() + if dir < 10 and dist > range then ai.accel() - elseif(dir < 10 or ai.hasturrets()) and dist < 300 then + elseif(dir < 10 or ai.hasturrets()) and dist < range then ai.shoot() end end diff --git a/src/ai.c b/src/ai.c index 1f816cb..2435ae6 100644 --- a/src/ai.c +++ b/src/ai.c @@ -128,6 +128,7 @@ static int ai_hasturrets(lua_State* L); /* bool hasturrets() */ static int ai_shoot(lua_State* L); /* shoot(number) number = 1,2,3. */ static int ai_getenemy(lua_State* L); /* number getenemy(). */ static int ai_hostile(lua_State* L); /* hostile(number). */ +static int ai_getweaprange(lua_State* L); /* number getweaprange(). */ /* Timers. */ static int ai_settimer(lua_State* L); /* settimer(number, number) */ static int ai_timeup(lua_State* L); /* boolean timeup(number) */ @@ -180,6 +181,7 @@ static const luaL_Reg ai_methods[] = { { "shoot", ai_shoot }, { "getenemy", ai_getenemy }, { "hostile", ai_hostile }, + { "getweaprange", ai_getweaprange }, /* Timers. */ { "settime", ai_settimer }, { "timeup", ai_timeup }, @@ -879,6 +881,48 @@ static int ai_hostile(lua_State* L) { return 0; } +/* Return the maximum range of weapons if parameter is 1, then do secondary. */ +static int ai_getweaprange(lua_State* L) { + int i; + double range, max; + Outfit* o; + + /* If 1 is passed as parameter, secondary weapon is checked. */ + if(lua_isnumber(L, 1) && ((int)lua_tonumber(L, 1) == 1)) + if(cur_pilot->secondary != NULL) { + /* Get range, launchers use ammo's range. */ + if(outfit_isLauncher(cur_pilot->secondary->outfit) && (cur_pilot->ammo != NULL)) + range = outfit_range(cur_pilot->ammo->outfit); + else + range = outfit_range(cur_pilot->secondary->outfit); + + if(range < 0.) return 0; /* Secondary doesn't have range. */ + + /* Secondary does have range. */ + lua_pushnumber(L, range); + return 1; + } + + max = -1.; + for(i = 0; i < cur_pilot->noutfits; i++) { + o = cur_pilot->outfits[i].outfit; + + /* Not interested in secondary weapons nor ammunition. */ + if(outfit_isProp(o, OUTFIT_PROP_WEAP_SECONDARY) || outfit_isAmmo(o)) + continue; + + /* Compare vs current outfit's range. */ + range = outfit_range(o); + if(range > max) + max = range; + } + + if(max < 0.) return 0; /* No ranged weapons. */ + + lua_pushnumber(L, max); + return 1; +} + /* Set the timer. */ static int ai_settimer(lua_State* L) { LLUA_MIN_ARGS(2); diff --git a/src/outfit.c b/src/outfit.c index ac464fd..d7e4bb3 100644 --- a/src/outfit.c +++ b/src/outfit.c @@ -180,48 +180,55 @@ int outfit_isMap(const Outfit* o) { /* Get the outfit graphics. */ glTexture* outfit_gfx(const Outfit* o) { - if(outfit_isWeapon(o)) return o->u.blt.gfx_space; - else if(outfit_isAmmo(o)) return o->u.amm.gfx_space; + if(outfit_isWeapon(o)) return o->u.blt.gfx_space; + else if(outfit_isAmmo(o)) return o->u.amm.gfx_space; else if(outfit_isTurret(o)) return o->u.blt.gfx_space; return NULL; } /* Get the outfit spfx if applicable. */ int outfit_spfx(const Outfit* o) { - if(outfit_isWeapon(o)) return o->u.blt.spfx; - else if(outfit_isAmmo(o)) return o->u.amm.spfx; + if(outfit_isWeapon(o)) return o->u.blt.spfx; + else if(outfit_isAmmo(o)) return o->u.amm.spfx; else if(outfit_isTurret(o)) return o->u.blt.spfx; return -1; } double outfit_damage(const Outfit* o) { - if(outfit_isWeapon(o)) return o->u.blt.damage; - else if(outfit_isAmmo(o)) return o->u.amm.damage; + if(outfit_isWeapon(o)) return o->u.blt.damage; + else if(outfit_isAmmo(o)) return o->u.amm.damage; else if(outfit_isTurret(o)) return o->u.blt.damage; return -1; } DamageType outfit_damageType(const Outfit* o) { - if(outfit_isWeapon(o)) return o->u.blt.dtype; - else if(outfit_isAmmo(o)) return o->u.amm.dtype; + if(outfit_isWeapon(o)) return o->u.blt.dtype; + else if(outfit_isAmmo(o)) return o->u.amm.dtype; else if(outfit_isTurret(o)) return o->u.blt.dtype; return DAMAGE_TYPE_NULL; } int outfit_delay(const Outfit* o) { - if(outfit_isWeapon(o)) return o->u.blt.delay; + if(outfit_isWeapon(o)) return o->u.blt.delay; else if(outfit_isLauncher(o)) return o->u.lau.delay; - else if(outfit_isTurret(o)) return o->u.blt.delay; + else if(outfit_isTurret(o)) return o->u.blt.delay; return -1; } double outfit_energy(const Outfit* o) { - if(outfit_isWeapon(o)) return o->u.blt.energy; - else if(outfit_isAmmo(o)) return o->u.amm.energy; + if(outfit_isWeapon(o)) return o->u.blt.energy; + else if(outfit_isAmmo(o)) return o->u.amm.energy; else if(outfit_isTurret(o)) return o->u.blt.energy; return -1.; } +double outfit_range(const Outfit* o) { + if(outfit_isWeapon(o)) return o->u.blt.range; + else if(outfit_isAmmo(o)) return 0.8*o->u.amm.speed*o->u.amm.duration; + else if(outfit_isTurret(o)) return o->u.blt.range; + return -1.; +} + const char* outfit_typename[] = { "NULL", "Bolt Cannon", diff --git a/src/outfit.h b/src/outfit.h index 1c9232b..7b55efe 100644 --- a/src/outfit.h +++ b/src/outfit.h @@ -145,6 +145,7 @@ double outfit_damage(const Outfit* o); DamageType outfit_damageType(const Outfit* o); int outfit_delay(const Outfit* o); double outfit_energy(const Outfit* o); +double outfit_range(const Outfit* o); /* Load/free outfit stack. */ int outfit_load(void);