[Change] Improved enemy and turret ai, they hit a lot now!

-- also improved the global attack() ai.
This commit is contained in:
Allanis 2013-08-14 16:48:32 +01:00
parent 76d7e811b5
commit 719bb753a2
7 changed files with 125 additions and 40 deletions

View File

@ -17,24 +17,33 @@ function attack()
return
end
ai.settarget(target)
-- 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.
dist = ai.dist(ai.pos(target)) -- Get distance.
-- Shoot missiles if in range.
if ai.secondary() == "Launcher" and
dist < ai.getweaprange(1) and dir < 30 then -- More lenient with aiming.
ai.settarget(target)
ai.shoot(2)
end
-- Attack if in range.
range = ai.getweaprange()
if dir < 10 and dist > range then
ai.accel()
elseif(dir < 10 or ai.hasturrets()) and dist < range then
ai.shoot()
-- We first bias towards range.
if dist > range then
dir = ai.face(target) -- Normal face the target.
-- Shoot missiles if in range.
if ai.secondary() == "Launcher" and
dist < ai.getweaprange(1) and dir < 30 then -- More leniant with aiming.
ai.shoot(2)
end
if dir < 10 then
ai.accel()
end
-- Close enough to melee.
else
dir = ai.aim(target) -- we aim instead of face.
if (dir < 10 or ai.hasturret()) then
ai.shoot()
end
end
end

View File

@ -118,6 +118,7 @@ static int ai_haslockon(lua_State* L); /* boolean haslockon() */
static int ai_accel(lua_State* L); /* accel(number); nuimber <= 1. */
static int ai_turn(lua_State* L); /* turn(number); abs(number) <= 1. */
static int ai_face(lua_State* L); /* face(number/pointer) */
static int ai_aim(lua_State* L); /* aim(number). */
static int ai_brake(lua_State* L); /* Brake() */
static int ai_getnearestplanet(lua_State* L); /* pointer getnearestplanet() */
static int ai_getrndplanet(lua_State* L); /* pointer getrndplanet() */
@ -180,6 +181,7 @@ static const luaL_Reg ai_methods[] = {
{ "stop", ai_stop },
{ "hyperspace", ai_hyperspace },
/* Combat. */
{ "aim", ai_aim },
{ "combat", ai_combat },
{ "settarget", ai_settarget },
{ "secondary", ai_secondary },
@ -243,7 +245,7 @@ int ai_init(void) {
strlen(AI_INCLUDE)) != 0) &&
(strncmp(files[i] + strlen(files[i]) - strlen(AI_SUFFIX), /* Suffixed. */
AI_SUFFIX, strlen(AI_SUFFIX))==0))
if(ai_loadProfile(files[i]))
if(ai_loadProfile(files[i])) /* Load the profiles. */
WARN("Error loading AI profile '%s'", files[i]);
/* Free the char allocated by pack. */
@ -358,7 +360,7 @@ void ai_think(Pilot* pilot) {
cur_pilot->solid->dir_vel = 0.;
if(pilot_turn) /* Set the turning velocity. */
cur_pilot->solid->dir_vel -= cur_pilot->turn * pilot_turn;
cur_pilot->solid->dir_vel += cur_pilot->turn * pilot_turn;
vect_pset(&cur_pilot->solid->force, cur_pilot->thrust * pilot_acc,
cur_pilot->solid->dir);
@ -723,7 +725,7 @@ static int ai_face(lua_State* L) {
}
else if(lua_islightuserdata(L,1)) v = (Vec2*)lua_topointer(L,1);
mod = -10;
mod = 10;
if(lua_gettop(L) > 1 && lua_isnumber(L,2)) invert = (int)lua_tonumber(L,2);
if(invert) mod *= -1;
vect_cset(&sv, VX(cur_pilot->solid->pos) + FACE_WVEL*VX(cur_pilot->solid->vel),
@ -856,6 +858,54 @@ static int ai_stop(lua_State* L) {
return 0;
}
/* Aim at the pilot, trying to hit it. */
static int ai_aim(lua_State* L) {
int id;
double x, y;
double t;
Pilot* p;
Vec2 tv;
double dist, diff;
double mod;
LLUA_MIN_ARGS(1);
/* Only acceptable parameter is pilot id. */
if(lua_isnumber(L,1))
id = lua_tonumber(L,1);
else
LLUA_INVALID_PARAMETER();
/* Get the pilot. */
p = pilot_get(id);
if(p == NULL) {
WARN("Pilot is invalid");
return 0;
}
/* Get the distance. */
dist = vect_dist(&cur_pilot->solid->pos, &p->solid->pos);
/* Time for shots to reach distance. */
t = dist / cur_pilot->weap_speed;
/* Position is calculated on where it should be. */
x = p->solid->pos.x + p->solid->vel.x*t
- (cur_pilot->solid->pos.x + cur_pilot->solid->vel.x*t);
y = p->solid->pos.y + p->solid->vel.y*t
- (cur_pilot->solid->pos.y + cur_pilot->solid->vel.y*t);
vect_cset(&tv, x, y);
/* Calculate what we need to turn. */
mod = 10.;
diff = angle_diff(cur_pilot->solid->dir, VANGLE(tv));
pilot_turn = mod * diff;
/* Return distance to target (in grad). */
lua_pushnumber(L, ABS(diff*180./M_PI));
return 1;
}
/* Toggle combat flag. Default is on. */
static int ai_combat(lua_State* L) {
int i;
@ -952,9 +1002,7 @@ static int ai_hostile(lua_State* L) {
/* 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;
double range;
/* If 1 is passed as parameter, secondary weapon is checked. */
if(lua_isnumber(L, 1) && ((int)lua_tonumber(L, 1) == 1))
@ -972,23 +1020,7 @@ static int ai_getweaprange(lua_State* L) {
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);
lua_pushnumber(L, cur_pilot->weap_range);
return 1;
}

View File

@ -243,6 +243,13 @@ double outfit_range(const Outfit* o) {
return -1.;
}
double outfit_speed(const Outfit* o) {
if(outfit_isWeapon(o)) return o->u.blt.speed;
else if(outfit_isAmmo(o)) return o->u.amm.speed;
else if(outfit_isTurret(o)) return o->u.blt.speed;
return -1.;
}
int outfit_isSeeker(const Outfit* o) {
if((o->type == OUTFIT_TYPE_MISSILE_SEEK_AMMO) ||
(o->type == OUTFIT_TYPE_MISSILE_SEEK_SMART_AMMO) ||

View File

@ -155,6 +155,7 @@ DamageType outfit_damageType(const Outfit* o);
int outfit_delay(const Outfit* o);
double outfit_energy(const Outfit* o);
double outfit_range(const Outfit* o);
double outfit_speed(const Outfit* o);
int outfit_isSeeker(const Outfit* o);
/* Load/free outfit stack. */

View File

@ -697,6 +697,8 @@ char* pilot_getOutfits(Pilot* pilot) {
void pilot_calcStats(Pilot* pilot) {
int i;
double q;
double wrange, wspeed;
int nweaps;
Outfit* o;
double ac, sc, ec, fc; /* Temp health coeficients to set. */
@ -725,6 +727,8 @@ void pilot_calcStats(Pilot* pilot) {
pilot_calcCargo(pilot);
/* Now add outfit changes. */
nweaps = 0;
wrange = wspeed = 0.;
for(i = 0; i < pilot->noutfits; i++) {
o = pilot->outfits[i].outfit;
q = (double) pilot->outfits[i].quantity;
@ -756,8 +760,18 @@ void pilot_calcStats(Pilot* pilot) {
}
pilot->energy_regen -= o->u.jam.energy;
}
else if((outfit_isWeapon(o) || outfit_isTurret(o)) && /* Primary weapon. */
!outfit_isProp(o, OUTFIT_PROP_WEAP_SECONDARY)) {
nweaps++;
wrange = MAX(wrange, outfit_range(o));
wspeed += outfit_speed(o);
}
}
/* Set weapon range and speed. */
pilot->weap_range = wrange; /* Range is max. */
pilot->weap_speed = wspeed / (double)nweaps;
/* Give the pilot her health proportion back. */
pilot->armour = ac * pilot->armour_max;
pilot->shield = sc * pilot->shield_max;

View File

@ -106,6 +106,10 @@ typedef struct Pilot_ {
int ncommodities;
int cargo_free;
/* Weapon Properties. */
double weap_range; /* Average range of primary weapons */
double weap_speed; /* Average speed of primary weapons. */
/* Misc. */
uint32_t flags; /* Used for AI etc. */
unsigned int ptimer; /* Generic timer for internal pilot use. */

View File

@ -389,6 +389,7 @@ static Weapon* weapon_create(const Outfit* outfit, const double dir, const Vec2*
Vec2 v;
double mass, rdir;
Pilot* pilot_target;
double x, y, t, dist;
Weapon* w;
/* Create basic features. */
@ -408,7 +409,23 @@ static Weapon* weapon_create(const Outfit* outfit, const double dir, const Vec2*
/* Only difference is the direction of fire. */
if((outfit->type == OUTFIT_TYPE_TURRET_BOLT) && (w->parent != w->target) &&
(w->target != 0)) { /* Must have a valid target. */
rdir = vect_angle(pos, &pilot_get(w->target)->solid->pos);
pilot_target = pilot_get(w->target);
/* Get the distance. */
dist = vect_dist(pos, &pilot_target->solid->pos);
/* Time for shots to reach that distance. */
t = dist / w->outfit->u.blt.speed;
/* Position is calculated on where it should be. */
x = (pilot_target->solid->pos.x + pilot_target->solid->vel.x*t)
- (pos->x + vel->x*t);
y = (pilot_target->solid->pos.y + pilot_target->solid->vel.y*t)
- (pos->y + vel->y*t);
vect_cset(&v, x, y);
rdir = VANGLE(v);
rdir += RNG(-outfit->u.blt.accuracy/2.,
outfit->u.blt.accuracy/2.)/180.*M_PI;
} else /* Fire straight. */
@ -424,7 +441,8 @@ static Weapon* weapon_create(const Outfit* outfit, const double dir, const Vec2*
w->solid = solid_create(mass, rdir, pos, &v);
w->voice = sound_addVoice(VOICE_PRIORITY_BOLT,
w->solid->pos.x, w->solid->pos.y,
w->solid->vel.x, w->solid->vel.y, w->outfit->u.blt.sound, 0);
w->solid->vel.x, w->solid->vel.y,
w->outfit->u.blt.sound, 0);
break;
/* Treat seekers togther. */