[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,25 +17,34 @@ function attack()
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
ai.settarget(target)
|
||||||
|
|
||||||
-- Get stats about enemy.
|
-- Get stats about enemy.
|
||||||
dir = ai.face(target) -- Face target.
|
|
||||||
dist = ai.dist(ai.pos(target)) -- Get distance.
|
dist = ai.dist(ai.pos(target)) -- Get distance.
|
||||||
second = ai.secondary() -- Get best secondary weapon.
|
|
||||||
|
range = ai.getweaprange()
|
||||||
|
|
||||||
|
-- We first bias towards range.
|
||||||
|
if dist > range then
|
||||||
|
dir = ai.face(target) -- Normal face the target.
|
||||||
|
|
||||||
-- Shoot missiles if in range.
|
-- Shoot missiles if in range.
|
||||||
if ai.secondary() == "Launcher" and
|
if ai.secondary() == "Launcher" and
|
||||||
dist < ai.getweaprange(1) and dir < 30 then -- More lenient with aiming.
|
dist < ai.getweaprange(1) and dir < 30 then -- More leniant with aiming.
|
||||||
ai.settarget(target)
|
|
||||||
ai.shoot(2)
|
ai.shoot(2)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Attack if in range.
|
if dir < 10 then
|
||||||
range = ai.getweaprange()
|
|
||||||
if dir < 10 and dist > range then
|
|
||||||
ai.accel()
|
ai.accel()
|
||||||
elseif(dir < 10 or ai.hasturrets()) and dist < range then
|
end
|
||||||
|
|
||||||
|
-- Close enough to melee.
|
||||||
|
else
|
||||||
|
dir = ai.aim(target) -- we aim instead of face.
|
||||||
|
if (dir < 10 or ai.hasturret()) then
|
||||||
ai.shoot()
|
ai.shoot()
|
||||||
end
|
end
|
||||||
|
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_accel(lua_State* L); /* accel(number); nuimber <= 1. */
|
||||||
static int ai_turn(lua_State* L); /* turn(number); abs(number) <= 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_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_brake(lua_State* L); /* Brake() */
|
||||||
static int ai_getnearestplanet(lua_State* L); /* pointer getnearestplanet() */
|
static int ai_getnearestplanet(lua_State* L); /* pointer getnearestplanet() */
|
||||||
static int ai_getrndplanet(lua_State* L); /* pointer getrndplanet() */
|
static int ai_getrndplanet(lua_State* L); /* pointer getrndplanet() */
|
||||||
@ -180,6 +181,7 @@ static const luaL_Reg ai_methods[] = {
|
|||||||
{ "stop", ai_stop },
|
{ "stop", ai_stop },
|
||||||
{ "hyperspace", ai_hyperspace },
|
{ "hyperspace", ai_hyperspace },
|
||||||
/* Combat. */
|
/* Combat. */
|
||||||
|
{ "aim", ai_aim },
|
||||||
{ "combat", ai_combat },
|
{ "combat", ai_combat },
|
||||||
{ "settarget", ai_settarget },
|
{ "settarget", ai_settarget },
|
||||||
{ "secondary", ai_secondary },
|
{ "secondary", ai_secondary },
|
||||||
@ -243,7 +245,7 @@ int ai_init(void) {
|
|||||||
strlen(AI_INCLUDE)) != 0) &&
|
strlen(AI_INCLUDE)) != 0) &&
|
||||||
(strncmp(files[i] + strlen(files[i]) - strlen(AI_SUFFIX), /* Suffixed. */
|
(strncmp(files[i] + strlen(files[i]) - strlen(AI_SUFFIX), /* Suffixed. */
|
||||||
AI_SUFFIX, strlen(AI_SUFFIX))==0))
|
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]);
|
WARN("Error loading AI profile '%s'", files[i]);
|
||||||
|
|
||||||
/* Free the char allocated by pack. */
|
/* Free the char allocated by pack. */
|
||||||
@ -358,7 +360,7 @@ void ai_think(Pilot* pilot) {
|
|||||||
|
|
||||||
cur_pilot->solid->dir_vel = 0.;
|
cur_pilot->solid->dir_vel = 0.;
|
||||||
if(pilot_turn) /* Set the turning velocity. */
|
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,
|
vect_pset(&cur_pilot->solid->force, cur_pilot->thrust * pilot_acc,
|
||||||
cur_pilot->solid->dir);
|
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);
|
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(lua_gettop(L) > 1 && lua_isnumber(L,2)) invert = (int)lua_tonumber(L,2);
|
||||||
if(invert) mod *= -1;
|
if(invert) mod *= -1;
|
||||||
vect_cset(&sv, VX(cur_pilot->solid->pos) + FACE_WVEL*VX(cur_pilot->solid->vel),
|
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;
|
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. */
|
/* Toggle combat flag. Default is on. */
|
||||||
static int ai_combat(lua_State* L) {
|
static int ai_combat(lua_State* L) {
|
||||||
int i;
|
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. */
|
/* Return the maximum range of weapons if parameter is 1, then do secondary. */
|
||||||
static int ai_getweaprange(lua_State* L) {
|
static int ai_getweaprange(lua_State* L) {
|
||||||
int i;
|
double range;
|
||||||
double range, max;
|
|
||||||
Outfit* o;
|
|
||||||
|
|
||||||
/* If 1 is passed as parameter, secondary weapon is checked. */
|
/* If 1 is passed as parameter, secondary weapon is checked. */
|
||||||
if(lua_isnumber(L, 1) && ((int)lua_tonumber(L, 1) == 1))
|
if(lua_isnumber(L, 1) && ((int)lua_tonumber(L, 1) == 1))
|
||||||
@ -972,23 +1020,7 @@ static int ai_getweaprange(lua_State* L) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
max = -1.;
|
lua_pushnumber(L, cur_pilot->weap_range);
|
||||||
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,6 +243,13 @@ double outfit_range(const Outfit* o) {
|
|||||||
return -1.;
|
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) {
|
int outfit_isSeeker(const Outfit* o) {
|
||||||
if((o->type == OUTFIT_TYPE_MISSILE_SEEK_AMMO) ||
|
if((o->type == OUTFIT_TYPE_MISSILE_SEEK_AMMO) ||
|
||||||
(o->type == OUTFIT_TYPE_MISSILE_SEEK_SMART_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);
|
int outfit_delay(const Outfit* o);
|
||||||
double outfit_energy(const Outfit* o);
|
double outfit_energy(const Outfit* o);
|
||||||
double outfit_range(const Outfit* o);
|
double outfit_range(const Outfit* o);
|
||||||
|
double outfit_speed(const Outfit* o);
|
||||||
int outfit_isSeeker(const Outfit* o);
|
int outfit_isSeeker(const Outfit* o);
|
||||||
|
|
||||||
/* Load/free outfit stack. */
|
/* 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) {
|
void pilot_calcStats(Pilot* pilot) {
|
||||||
int i;
|
int i;
|
||||||
double q;
|
double q;
|
||||||
|
double wrange, wspeed;
|
||||||
|
int nweaps;
|
||||||
Outfit* o;
|
Outfit* o;
|
||||||
double ac, sc, ec, fc; /* Temp health coeficients to set. */
|
double ac, sc, ec, fc; /* Temp health coeficients to set. */
|
||||||
|
|
||||||
@ -725,6 +727,8 @@ void pilot_calcStats(Pilot* pilot) {
|
|||||||
pilot_calcCargo(pilot);
|
pilot_calcCargo(pilot);
|
||||||
|
|
||||||
/* Now add outfit changes. */
|
/* Now add outfit changes. */
|
||||||
|
nweaps = 0;
|
||||||
|
wrange = wspeed = 0.;
|
||||||
for(i = 0; i < pilot->noutfits; i++) {
|
for(i = 0; i < pilot->noutfits; i++) {
|
||||||
o = pilot->outfits[i].outfit;
|
o = pilot->outfits[i].outfit;
|
||||||
q = (double) pilot->outfits[i].quantity;
|
q = (double) pilot->outfits[i].quantity;
|
||||||
@ -756,7 +760,17 @@ void pilot_calcStats(Pilot* pilot) {
|
|||||||
}
|
}
|
||||||
pilot->energy_regen -= o->u.jam.energy;
|
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. */
|
/* Give the pilot her health proportion back. */
|
||||||
pilot->armour = ac * pilot->armour_max;
|
pilot->armour = ac * pilot->armour_max;
|
||||||
|
@ -106,6 +106,10 @@ typedef struct Pilot_ {
|
|||||||
int ncommodities;
|
int ncommodities;
|
||||||
int cargo_free;
|
int cargo_free;
|
||||||
|
|
||||||
|
/* Weapon Properties. */
|
||||||
|
double weap_range; /* Average range of primary weapons */
|
||||||
|
double weap_speed; /* Average speed of primary weapons. */
|
||||||
|
|
||||||
/* Misc. */
|
/* Misc. */
|
||||||
uint32_t flags; /* Used for AI etc. */
|
uint32_t flags; /* Used for AI etc. */
|
||||||
unsigned int ptimer; /* Generic timer for internal pilot use. */
|
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;
|
Vec2 v;
|
||||||
double mass, rdir;
|
double mass, rdir;
|
||||||
Pilot* pilot_target;
|
Pilot* pilot_target;
|
||||||
|
double x, y, t, dist;
|
||||||
Weapon* w;
|
Weapon* w;
|
||||||
|
|
||||||
/* Create basic features. */
|
/* 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. */
|
/* Only difference is the direction of fire. */
|
||||||
if((outfit->type == OUTFIT_TYPE_TURRET_BOLT) && (w->parent != w->target) &&
|
if((outfit->type == OUTFIT_TYPE_TURRET_BOLT) && (w->parent != w->target) &&
|
||||||
(w->target != 0)) { /* Must have a valid 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.,
|
rdir += RNG(-outfit->u.blt.accuracy/2.,
|
||||||
outfit->u.blt.accuracy/2.)/180.*M_PI;
|
outfit->u.blt.accuracy/2.)/180.*M_PI;
|
||||||
} else /* Fire straight. */
|
} 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->solid = solid_create(mass, rdir, pos, &v);
|
||||||
w->voice = sound_addVoice(VOICE_PRIORITY_BOLT,
|
w->voice = sound_addVoice(VOICE_PRIORITY_BOLT,
|
||||||
w->solid->pos.x, w->solid->pos.y,
|
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;
|
break;
|
||||||
|
|
||||||
/* Treat seekers togther. */
|
/* Treat seekers togther. */
|
||||||
|
Loading…
Reference in New Issue
Block a user