[Change] Improved enemy and turret ai, they hit a lot now!
-- also improved the global attack() ai.
This commit is contained in:
parent
76d7e811b5
commit
719bb753a2
@ -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
|
||||
|
||||
|
78
src/ai.c
78
src/ai.c
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) ||
|
||||
|
@ -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. */
|
||||
|
14
src/pilot.c
14
src/pilot.c
@ -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;
|
||||
|
@ -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. */
|
||||
|
22
src/weapon.c
22
src/weapon.c
@ -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. */
|
||||
|
Loading…
Reference in New Issue
Block a user